claude-codeandmhoennig 96a96ba866
werkator/jvm build succeeded after 09:44
Sporadisch scheiternde Browser-Szenarien als eigenen Knoten führen (#15)
Am 2026-10-23 scheiterte der Branch-Build zu [werkjournal PR#14](#14) an WJ-059 („Recover a work draft from a closed tab"). Derselbe Baum — `--amend` ohne inhaltliche Änderung, Force-Push — lief beim zweiten Anlauf grün. Lokale Wiederholungen desselben Commits scheiterten an zwei **anderen** Szenarien aus dem Habit-Bereich, und ein vollständiger lokaler Lauf war grün.

Wechselnde Szenarien, keine inhaltliche Gemeinsamkeit, keine Beziehung zur jeweiligen Änderung.

## Warum das einen eigenen Knoten verdient

Das PR-Tor ist damit in beide Richtungen unzuverlässig: ein grüner Lauf belegt nicht, dass eine Änderung trägt, und ein roter nicht, dass sie bricht. Jeder Fehlschlag kostet eine Untersuchung, die am Ende nichts über die Änderung aussagt — in dieser Session zweimal.

Der Werkbaum kannte die Lastempfindlichkeit der Pipeline bisher nur als **Laufzeitthema**: `#pipeline-duration`, `#rollback-timeouts` (Zeitgrenzen an einen überlasteten Host angepasst), `#branch-gate-engines` und `#branch-gate-recheck`. Dass einzelne Szenarien unter Last sporadisch *scheitern*, war nirgends erfasst.

Eine Ausnahme gibt es bereits, aber sie ist eng: `#habit-month-date-independent` hielt am 2026-10-03 fest, dass ein Szenario vom laufenden Datum abhing. Das war eine konkrete, behobene Ursache in einem Szenario — kein Knoten für das allgemeine Muster.

## Was der Knoten festhält

`#browser-flakiness` steht offen unter `#operations`, neben `#pipeline-duration`, mit Verweis auf `#branch-gate-engines`. Er nennt die drei zu prüfenden Richtungen:

- **Zeitgrenzen gegen eine langsame Antwort** — dann sind die Zusicherungen zu ungeduldig.
- **Gemeinsamer Zustand zwischen Szenarien** — dann fehlt Isolation.
- **Playwright-Aktionen gegen noch nicht fertige Vaadin-Updates** — dann warten die Schritte auf das falsche Ereignis.

Ausdrücklich festgehalten ist, die Sache **nicht durch eine Wiederholungsautomatik zu verdecken**, ehe die Ursache bekannt ist: eine Wiederholung versteckt genau die Information, die hier fehlt.

## Was dieser PR nicht tut

Keine Untersuchung, keine Behebung, kein Code — nur der Plan und die Version. Die Beobachtung ist belegt, die Ursache nicht; den Knoten jetzt anzulegen hält fest, was sonst mit dieser Session verloren geht.

## Nachweise

`JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefox` grün: `BUILD SUCCESSFUL in 7m 32s`, 72 Betriebstests. Version 0.1.128-SNAPSHOT.

Dass dieser grüne Lauf nach dem eigenen Knoten nur begrenzt beweist, ist mir bewusst.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #15
Reviewed-by: mi <1+mi@noreply.git.javagil.de>
Co-authored-by: claude-code <4+claude-code@noreply.git.javagil.de>
2026-10-24 22:21:30 +02:00

Werkjournal

Private Arbeitszeit- und Habit-Erfassung mit Kotlin, Vaadin Flow und Spring Boot.

Stand: E-Mail-Anmeldung aktiv; Ersteinrichtung erfolgreich bestätigt. Private Konten und der getrennte gemeinsame Gastzugang sind verfügbar. Vorhandene Daten müssen bei allen weiteren Migrationen erhalten bleiben.

Planung und Arbeitsweise

  • werkjournal.werkbaum: Entscheidungen und aktueller Umsetzungsstand.
  • gherkin/: englische Abnahmeszenarien; noch nicht vollständig implementiert.
  • docs/implementation/: geprüfte Infrastruktur, Toolchain und Testzuordnung.
  • docs/plans/: Spezifikationen geplanter Arbeitspakete mit HTML-Entwürfen unter docs/plans/mockups/; Umsetzung je Paket auf eigenem Branch mit Ergebnisdokument unter docs/implementation/.

Ein Umsetzungsknoten wird vor Beginn mit [~] committet und gepusht. Nach erfolgreicher Prüfung folgt [x] mit Abschlusscommit und Push. Abgeschlossene Entscheidungen sind ausdrücklich als solche beschriftet und nicht mit ausgelieferter Funktion gleichzusetzen.

Gestaltung

Farben, Schrift und Abstände stammen aus einem gemeinsamen Token-Satz (--wj-*), der in src/main/resources/META-INF/resources/styles.css und src/main/resources/static/login.css identisch definiert ist; alle Lumo-Variablen werden daraus abgeleitet. Hell und dunkel folgen der Darstellungswahl in den Einstellungen. Die Oberfläche ist für das Smartphone entworfen: beschriftete Bottom-Navigation, kompakte Eintragszeilen mit Inline-Stepper und Formulare als Bottom-Sheet unter 600 px. Neue Flächen erben Karten- und Buttonstil aus diesen Tokens, ohne eigene Farbwerte. Maßgeblich sind docs/plans/ui-refresh.md und der Nachweis docs/implementation/ui-refresh.md.

Anwendung bauen

./gradlew test bootJar -Pproduction=true

Der gepinnte Gradle-Wrapper prüft seine Distribution per SHA-256. Build und Tests verwenden Temurin JDK 25; Download und Prüfsumme sind in packaging/jdk.properties fixiert. Das Produktionsartefakt ist build/libs/werkjournal.jar. tools/ci-jvm baut, testet und prüft das JAR mit 256 MiB Heap und 192 MiB Metaspace in einer isolierten Testumgebung.

cp .env.example .env
remote backend install-jdk
# Nach Änderung des gepinnten JDK-Stands:
remote backend install-jdk --force

Die Installation benötigt keine Root-Rechte, verwendet eine SSH-Verbindung und aktiviert erst das vollständig heruntergeladene, geprüfte JDK. Ziel ist standardmäßig ~/opt/jdk25 beim Werkjournal-User. Bestehende JDK-Releases bleiben erhalten, damit laufende JVMs ihre Bibliotheken weiter erreichen. Geheimnisse gehören nicht in die JDK-Konfiguration.

GraalVM ist optional zurückgestellt. Nur -Pnative=true aktiviert dessen Gradle-Plugin; tools/ci-native bleibt ein experimenteller Einstieg ohne CI-Trigger oder Freigabeanspruch. Die bisherigen Ergebnisse stehen in docs/implementation/native-spike.md.

Die Anwendung bindet standardmäßig an 127.0.0.1:18090. /api/v1/info liefert die Buildversion, / das Heute-Dashboard. Dort führen Vortag, Heute und Folgetag auf einen anderen Tag, höchstens bis heute, und daneben öffnet ein Kalendersymbol die Datumsauswahl; /?date=JJJJ-MM-TT steigt direkt dort ein. Details: docs/implementation/home-day-navigation.md.

Ein separates Bookworm-Rootfs für Werkdock lässt sich lokal über tools/build-rootfs vorbereiten. Dazu wird ein lokaler Docker-Dienst verwendet; auf Hostsharing laufen Builds anschließend in Werkdock. Die erzeugten Dateien liegen unter dem git-ignorierten work/.

Mit direnv und direnv allow nimmt .envrc das Verzeichnis tools/ in den PATH auf. Produktionsgeheimnisse bleiben außerhalb des Repositorys.

Konten und Gastzugang

Auf dem Server ist WERKJOURNAL_GUEST_MODE=false gesetzt. Die Loginseite führt vier getrennte Ansichten: „Anmelden“ mit nur einem Adressfeld, „Du bist eingeladen“ beim Öffnen eines Einladungslinks, den Code-Schritt und unter /login?setup die Einrichtung bzw. Wiederherstellung mit dem Einrichtungscode vom Server. Der ausdrückliche Gastzugang steht weiter auf der Standardansicht. Einladungen entstehen unter /admin: Adresse und Sprache eingeben, „Einladung senden“ — die E-Mail geht sofort raus, der Link ist nur auf Wunsch oder nach einem fehlgeschlagenen Versand sichtbar. Die Einladungsliste zeigt Empfänger, Sprache, Zustand und lokal formatierte Zeitpunkte; „Neu einladen“ widerruft die offene Einladung und legt eine neue an. Die Empfängeradresse dient nur der Anzeige und wird beim Verbrauch der Einladung gelöscht; wer den unbenutzten Link besitzt, kann registrieren. Details: docs/implementation/auth-flow-refresh.md. Der bisherige gemeinsame Gastbereich bleibt getrennt von privaten Konten. Die Datenbank liegt unter data/werkjournal.mv.db. Die frühere Erlaubnis, Gastdaten zu verwerfen, gilt nicht mehr. Migrationen benötigen erhaltende Changesets, einen Test mit befülltem Vorgängerstand und eine konsistente Sicherung vor der Migration; siehe docs/implementation/deployment.md.

Das Datenfundament ist unter docs/implementation/foundation.md beschrieben. Die Kunden-/Projektpflege ist unter /catalog verfügbar. Der Quellstand enthält unter /habits frei konfigurierbare Gewohnheiten mit Tageszählern und optionalen Tages-/Wochenminima und -maxima. Grenzen sind Hinweise und blockieren das Zählen nicht. Einmalige, veränderbare Startvorgaben sind Kunde/Projekt „Allgemein“ sowie „Lesen“ und „Spaziergänge“ (Tagesminimum 1, Wochenminimum 5). Details und Testnachweise: docs/implementation/habits.md. Unter /work lassen sich Arbeitszeiten erfassen und ändern; Konflikte erhalten den Entwurf und erfordern eine ausdrückliche Auflösung. Entwürfe bleiben pro Tab erhalten und lassen sich auf demselben Gerät wiederaufnehmen. Details: docs/implementation/work.md. Die Arbeitserinnerung kommt Montag bis Freitag zur Erinnerungszeit des Kontos, einstellbar in den Einstellungen in Viertelstundenschritten zwischen 06:00 und 23:00; Vorgabe ist 20:00. Ein Ausfall wird noch zwei Stunden lang nachgeholt, höchstens bis Mitternacht, damit eine Erinnerung ihr Datum behält. Der Ein- und Ausschalter für Push bleibt pro Gerät. Details: docs/implementation/reminder-time.md. Dieser Funktionsstand ist öffentlich verfügbar.

Erstdeployment

remote backend deploy-prototype --artifact /pfad/zum/geprueften-ci-release

Das Verzeichnis enthält werkjournal.jar und das dazugehörige manifest.json aus einem erfolgreichen Werkator-Build. Der Befehl prüft den Hash lokal und auf dem Zielserver und baut nicht neu. Er richtet den systemd-User-Service sowie HTTP-Weiterleitung und HTTPS-Proxy auf dem Werkjournal-Host ein. Bereits vorhandene Releases, Dienste oder H2-Dateien werden abgelehnt: für reguläre Upgrades mit Datensicherung und Rollback dient remote backend deploy.

Betriebsstand, Verzeichnisse und Prüfergebnisse: docs/implementation/first-deploy.md.

Der laufende Dienst lässt sich mit remote backend status prüfen und mit remote backend start|stop|restart steuern. remote backend enable|disable ändert nur den Autostart. remote backend log --lines 30 zeigt Journalzeilen, remote backend log --follow folgt neuen Meldungen. Mutierende Befehle verwenden die Deployment-Sperre; vorhandene Wartung bleibt bestehen. Details und Fehlerfälle: docs/implementation/service-control.md.

remote backend setup schreibt die versionierte Unit und lädt systemd neu, ohne den Dienst neu zu starten. remote backend info prüft Version/Commit sowie interne und öffentliche Bereitschaft. remote ssh [COMMAND ARG...] öffnet eine Shell oder führt einen Befehl mit getrennten Argumenten aus. Details und vollständiger Befehlsabgleich: docs/implementation/remote-utilities.md.

Die angebundenen Fach- und Chromium-Gherkin-Szenarien laufen im normalen Testlauf mit. Die vollständige Pipeline ergänzt die Firefox-Abnahme und den Produktions-JAR-Smoke. Lokal zuerst die gepinnten Browser installieren:

JAVA_HOME=/pfad/zum/jdk25 ./gradlew --no-daemon installBrowsers

Der Werkdock-Build nutzt die Browser aus seinem vorbereiteten Image. Fehlende Browser werden im Testlauf nicht automatisch heruntergeladen oder übersprungen.

Bereich Suite Details
Arbeitszeit WorkCucumberTest docs/implementation/work-gherkin.md
Habits HabitCucumberTest docs/implementation/habit-gherkin.md
Push PushCucumberTest docs/implementation/push-gherkin.md
Konten IdentityCucumberTest docs/implementation/identity-gherkin.md
Chromium BrowserCucumberTest docs/implementation/browser-gherkin.md
Firefox firefoxAcceptance docs/implementation/firefox-acceptance.md
Produktions-JAR productionAcceptance docs/implementation/production-smoke-gherkin.md

Aufruf beispielsweise: ./gradlew test --tests '*BrowserCucumberTest' -Pproduction=true mit gesetztem JAVA_HOME. Berichte stehen unter build/reports/cucumber; noch offene Bindungen in docs/implementation/acceptance.md.

Erste Gastvorschau

remote backend deploy-guest-preview --artifact DIRECTORY ermöglicht ausschließlich den einmaligen Wechsel vom bekannten datenlosen Prototyp. Der Übergang wurde ausgeführt. Bei vorhandener Datenbank verweigert der Befehl weitere Deployments; allgemeine sichere Upgrades erfolgen über remote backend deploy. Details: docs/implementation/guest-preview.md.

Die zentrale Betriebsanleitung beschreibt Konfiguration, Releases, Wiederherstellung, Admin-Recovery und den geplanten Trixie-Wechsel.

Updates und Wiederherstellung

remote backend deploy --artifact /pfad/zum/geprueften-ci-release
remote backend recover

Mit remote backend upload --artifact DIRECTORY lässt sich ein geprüftes Release vorab bereitstellen. Es bleibt inaktiv, bis remote backend deploy --artifact DIRECTORY es mit Sicherung und Bereitschaftsprüfung aktiviert. Ein gewöhnlicher Neustart aktiviert den Upload nicht. Details: docs/implementation/candidate-upload.md.

remote backend backup [FILE] erstellt eine konsistente private Sicherung von H2-Daten und passendem Programmstand. Ohne Dateinamen landet sie in backups/. Der Dienst wird dafür kurz unter Wartung gestoppt und anschließend nur dann wieder gestartet, wenn er vorher lief. Vorhandene Dateien werden nicht überschrieben. Ablauf und Fehlerbehandlung: docs/implementation/operator-backup.md.

remote backend restore --backup FILE spielt diese Sicherung erst nach expliziter Bestätigung ein und sichert zuvor den bisherigen Stand. remote backend restore --recover behandelt einen unterbrochenen Versuch. Vorab lässt sich die Sicherung mit JAVA_HOME=/path/to/jdk25 tools/probe-restore --backup FILE isoliert prüfen. Details: docs/implementation/operator-restore.md.

Updates verwenden Wartungsseite, Dienststopp, konsistente H2-Dateisicherung und einen dauerhaften Wiederherstellungszustand. Überholte Kandidaten werden abgewiesen. Ein fehlgeschlagener Versuch bleibt in der Pipeline fehlgeschlagen, auch wenn die bisherige Version erfolgreich wiederhergestellt wurde. Einzelheiten: docs/implementation/deployment.md. Werkator führt dieses Deployment nach erfolgreichem Build im selben Pipeline-Skript aus.

Push-Schlüssel vorbereiten

Mit remote backend setup-push werden die VAPID-Schlüssel direkt auf dem Server in der geschützten systemd-Umgebungsdatei erzeugt. Wiederholter Aufruf erhält die vorhandenen Schlüssel. Der Befehl startet keinen Dienst neu und aktiviert keinen Versand. Details: docs/implementation/web-push-transport.md.

S
Description
No description provided
Readme
15 MiB
Languages
Kotlin 68.5%
Python 17.4%
CSS 5%
JavaScript 4.1%
Gherkin 2.3%
Other 2.7%