Files
werkbaum/docs/TASKS.md
T
mhoennigandClaude Fable 5 ecc1b632f6 feat: von Station zu Station des günstigsten Pfads (D47)
Mit dem status-bewussten Pfad (D46) zeigt das Diagramm die offene Front — im
mitgelieferten Plan 24 Stationen, verteilt über einen Baum von über 20 000 px
Breite. Sie zu sehen war damit gelöst, sie abzugehen nicht. Der neue Knopf im
Diagramm-Kopf holt sie der Reihe nach in die Mitte: erster Druck die erste
(was als Nächstes dran ist), jeder weitere die nächste, nach der letzten
wieder die erste.

Der Sprung fasst nur das Diagramm an — zentrieren, hervorheben, Tastaturfokus,
also buchstäblich die Behandlung des ausdrücklichen Alt+Klicks (D25) samt Puls
und hervorgehobenen Abhängigkeits-Kanten. In den Text führt von dort
Alt+Enter, dieselbe Geste wie überall.

Ohne eigenen Zustand: Fortgesetzt wird am gerade hervorgehobenen Knoten. Ein
gemerkter Index wäre schlechter — der Baum wird bei jedem Tastendruck neu
gebaut, die Stationsliste ändert sich unter ihm. Verborgen, solange es keine
Station gibt (Pfad aus, oder alles erledigt); der Tooltip nennt die Anzahl.
i18n `leanNextTooltip` in neun Sprachen.

Die Mobil-Kopfzeile trug den neunten Knopf nicht mehr — D17-Nachtrag 5 hatte
sie gerade erst auf acht zurechtgemessen. Nachgemessen: bei 375 px reicht es
nach Lücke 8->6 px und Innenabstand 10->8 px weiterhin (345 px Inhalt, 359 px
Platz, 14 px Luft); bei 320 px passen neun Fingerziele arithmetisch nicht, und
unter 29 px zu gehen hat D17-Nachtrag 5 abgelehnt. Die Zeile schiebt dort
deshalb (`overflow-x:auto`, Balken ausgeblendet) — 41 px Schiebeweg, Kopfhöhe
unverändert 49 px, alle neun Elemente in voller Größe erreichbar.

Dabei ein älterer, stiller Fehler gefunden: Bei Platzmangel schrumpfte der
Modus-Wähler — das einzige Element ohne feste Größe — auf einen 2-px-Strich
zusammen, während sein Icon 38 px breit darüber hinausragte; er sah aus wie
ein Trennstrich und war unbenutzbar. `flex:0 0 auto` an allen Kindern der
Zeile stellt das ab.

236 Tests grün. SPEC §9 und D47 halten es fest; der Plan bekommt den Knoten
als `[x]` (noch nicht deployt), frontend/CLAUDE.md die Kopfzeilen-Stolperfalle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 13:22:52 +02:00

9.7 KiB

Aufgaben

Abhaken beim Erledigen; neue Aufgaben unten anfügen.

Phase 1 — Modularisierung & Tests

  • Projektgerüst: src/ (parser.js, model.js, render.js, app.js), tests/, index.html bindet Module ein; weiterhin ohne Build nutzbar (ES-Module) oder mit minimalem Setup (Vite) — Entscheidung dokumentieren. → Vite gewählt (D19): src/ als ES-Module, npm run build bündelt zu einer self-contained dist/index.html (file://-tauglich). Gerüst steht (aktuell src/app.js + src/style.css); Parser/Renderer werden in den folgenden Checkboxen herausgelöst.
  • Parser extrahieren; Verhalten exakt wie in docs/SPEC.md §1–§8. → src/parser.js exportiert parse, STATUS_BY_CODE, SIZE_RANK (headless, kein DOM); app.js importiert sie.
  • Unit-Tests für den Parser (Vitest): kanonisches Beispiel aus SPEC §10 als Fixture; Randfälle: gemischte Gates, Tabs/ungleichmäßige Einrückung, URL mit @, mehrere Wurzeln, leere Labels, %% am Zeilenanfang/-ende. → tests/parser.test.js (18 Tests).
  • Renderer extrahieren (HTML-String-Erzeugung), Snapshot-Tests für Normal- und Vertikalmodus sowie „Untergliederung fehlt“. → src/model.js (Baum-/Kostenlogik) + src/render.js (renderTreeHtml, headless); app.js reicht UI-State als Parameter herein. tests/render.test.js (6 Tests, Snapshots). Anm.: der Modus (horizontal/vertikal/kompakt) ist reine CSS-Container-Klasse und ändert den Renderer-String nicht — ein Snapshot deckt alle drei Modi ab.
  • Warnungs-Modell vereinheitlichen (Zeilennummern, Typen). → strukturierte Objekte {type, line, ...} (Renderer emittiert mixedGate); src/warnings.js formatWarning(w, t) macht daraus den lokalisierten, HTML-escapten Text an einer Stelle. Vorbereitet für Phase 2 (unknownStatus). tests/warnings.test.js.

Phase 2 — Qualität

  • Barrierefreiheit: Fokusreihenfolge, aria-Labels für Status/Größe/Tags. → je Knoten ein sprechender aria-label (Label+Status+Aufwand+Zuständige+ Link, lokalisiert, neue a11y*-Keys in allen 9 Sprachen); visuelle Badges aria-hidden; Knoten tabindex="0" (Fokus = Lesereihenfolge) mit :focus-visible-Rahmen; #warn als Live-Region (role=status, aria-live=polite). Snapshots aktualisiert.
  • Druck-Stylesheet (Diagramm ohne Editor-Panel). → @media print in style.css: blendet Kopf/Editor/Splitter/Bedien- elemente/Warnungen/Footer aus, Diagramm füllt die Seite; Statusfarben via print-color-adjust:exact, break-inside:avoid, Pfad-Overlay inklusive.
  • Fehlertolerantes Parsen weiter ausbauen (unbekannte Statuszeichen melden). → Parser erfasst die Statusbox als beliebiges Einzelzeichen, validiert gegen STATUS_BY_CODE; unbekannte Codes → unknownStatus-Warnung (Zeile + Code), Knoten neutral, Folgezeilen unberührt. render() führt Parser- + Renderer-Warnungen zusammen. i18n unknownStatusWarn in allen 9 Sprachen. tests/parser.test.js (5 neue Tests).

Deployment

  • GitHub-Pages-Workflow angelegt (.github/workflows/pages.yml, siehe docs/DECISIONS.md D16).

Phase 3 — Integrationen (siehe ROADMAP)

  • Backend-Gerüst per Spring Initializr in backend/ anlegen (Kotlin, Gradle Kotlin DSL, JDK 21; Konventionen: backend/CLAUDE.md).
  • SVG-Renderer (Layout-Engine) als gemeinsame Basis für Export und Mermaid-Plugin.
  • Mermaid-Plugin-Spike: Detektor + Registrierung, ein Minimalbaum.
  • Taiga-Spike: #ref-Syntax parsen, Status via REST-API auflösen (read-only), Mapping konfigurierbar.

Phase 4 — Vollständiges Lean-Pathfinding (siehe ROADMAP, D34)

Reihenfolge ist nicht beliebig: ohne IDs keine Abhängigkeiten, ohne die keinen effektiven Status und keine Closure-Rechnung. Jeder Punkt beginnt in SPEC §11 — die dort benannten offenen Schreibweisen sind zu entscheiden, bevor Code entsteht.

  • #-Doppelrolle auflösen und in SPEC §11 festschreiben. → Durch Wegfall statt Trennregel: Tickets haben Vorrang (#123 numerisch, oft zugleich die natürliche Knoten-ID; notfalls Präfix wie #t123); Schlagworte gehen auf &tag — niedrig priorisiert, gebaut erst mit dem ersten Konsumenten (D34-Nachtrag).
  • Knoten-IDs parsen; doppelte ID → Warnung mit Zeilennummer. → Umgesetzt (D36): Zeichenmenge wie @name, nur alleinstehend angesetzt und nur das erste Token je Zeile (:#a,#b und Ticket-Erwähnungen bleiben unberührt); Warnung duplicateId nennt beide Zeilen; sichtbar im Tooltip + aria-label; SPEC-§11-Teil nach §1 überführt; tests/ids.test.js.
  • Abhängigkeiten :#a,#b parsen; unbekannte ID → Warnung, Zyklen erlaubt. → Umgesetzt (D37): ein zusammenhängendes Token ohne Leerraum, nur alleinstehend angesetzt (eingeklammerte Erwähnungen bleiben Label); deps als ID-Strings am Knoten, Warnung unknownDep, Zyklen bewusst ungeprüft; sichtbar als → #a, #b im Tooltip + a11yDeps; SPEC-§11-Teil nach §1 überführt; tests/deps.test.js.
  • Effektiven Status rechnen (intrinsisch + Abhängigkeiten); Darstellung entscheiden — die Knotenfarbe zeigt heute den intrinsischen Status. → Entschieden und umgesetzt (D39): Fortschritts-Rang (SPEC §4), effektiv = Minimum über die Abhängigkeits-Hülle (Fixpunkt, Zyklen teilen ihr Minimum); Knotenfarbe = effektiver Status, bei Diskrepanz die eigene Statusbox als Marke unten links in den eigenen Farben (auch im Export); Tooltip + a11yEffective; tests/effective.test.js.
  • Günstigsten Pfad auf die Dependency Closure umstellen (gemeinsame Abhängigkeiten nur einmal zählen). Erweitert D18; die gierige Wahl je Alternativgruppe ist damit nicht mehr optimal — Verfahren wählen und benennen. → Umgesetzt (D42): erschöpfende Suche über die gekoppelten Gruppen (computeCheapPlan in model.js), ungekoppelte wählen lokal wie bisher; oberhalb des Suchlimits gierig mit zeilenloser Warnung cheapApprox. Abhängigkeiten ziehen auch optionale/nicht gewählte Ziele, verworfene nie; tests/closure.test.js.
  • Querverbindungen zeichnen (eigene SVG-Ebene, optisch sekundär); bei ausgewähltem Knoten ein-/ausgehende hervorheben. → Umgesetzt (D41): gekrümmte blassgraue Kanten mit Pfeilspitze auf das Gebrauchte, hinter den Knoten (drawDepLinks); Hervorhebung in Tinte für Fokus-Knoten bzw. Cursor-Zeile; Basis-Kanten auch im Export/Druck.
  • Faltmarken > / < parsen; interaktives Auf-/Zuklappen im Diagramm. → Schreibweise und Export-Verhalten entschieden (D34-Nachtrag): Marke hinter dem Zerlegungszeichen (- > [x] …), Export/Druck folgen der sichtbar eingeklappten Struktur mit Kennzeichnung am Knoten. Umgesetzt (D38): initialCollapsed() (< wandert die Faltung die Pfad-Ebenen hinunter, !!! holt sich mit hervor); Falt-Zeichen ▾/„▸ n" + Tastatur ←/→; Eingriffe je Label-Pfad, nur für die Sitzung; Warnungen aus eingeklappten Teilbäumen bleiben; tests/fold.test.js.
  • XOR-Gruppe (=) parsen (nur mit folgendem Leerraum, Mischung → mixedGate), zwei realisierte Alternativen melden. → Zeichen entschieden: = statt x (D34-Nachtrag). Umgesetzt (D35): „realisiert“ = [~]/[/]/[x]/[^], Warnung xorConflict je weiterer realisierter Alternative; Darstellung als any-of plus „1“-Plakette an der Sammelleiste (auch im Grafikexport); Legende + i18n in 9 Sprachen; tests/xor.test.js.
  • Knotenbeschreibungen: Schreibweise für kurze und lange Form festlegen (Einrückung ist bereits Hierarchie), dann Tooltip/Pop-up. → Schreibweise entschieden (D34-Nachtrag): Kurzform als "-Zeile unter dem Knoten (Leerraum-Regel), Langform als eingerückte ID-Blöcke hinter einem ----Trenner (SPEC §11). Umgesetzt (D40): Parser (desc am Knoten, Warnungen unknownDesc/descStray), Anzeige im Tooltip + aria-label mit ”-Marke am Knoten; tests/desc.test.js.

Phase 5 — Der Pfad zeigt, was als Nächstes dran ist

  • Günstigsten Pfad status-bewusst rechnen: Erledigtes ([x]/[^]) kostet nichts mehr, hervorgehoben wird die offene Front. → Umgesetzt (D46): isDone() + ownCost() in model.js; Stationen sind die tiefsten noch offenen Pfadknoten (hidesOpenCheap()), erledigte behalten Farbe und Pfadzugehörigkeit, verlieren aber Punkt und implizites M-Badge. Angefangenes ([~]/[/]) zählt weiter voll, maßgeblich ist der intrinsische Status. Kein neuer Umschalter — der vorhandene ändert seine Bedeutung. tests/frontier.test.js.
  • Von Station zu Station springen (Knopf im Diagramm-Kopf). → Umgesetzt (D47): jumpToLeanStation() holt die nächste offene Station in die Mitte (Behandlung wie Alt+Klick, D25), nach der letzten wieder die erste; ohne eigenen Zustand — fortgesetzt wird am hervorgehobenen Knoten. Verborgen, solange es keine Station gibt; i18n leanNextTooltip in neun Sprachen. Die Mobil-Kopfzeile musste dafür enger und darf unter 360 px schieben.
  • Nutzen je Knoten (Gegenstück zur Kosten-Größe) — Schreibweise offen, SPEC-first (siehe ROADMAP „Kleinere Ideen").
  • Aufwands-Rollup (Größen der Kinder aggregieren) — braucht erst eine Mapping-Konvention, Größen sind ordinal.
  • Ausbaustufen: ist eine Alternativgruppe komplett realisiert, zur nächsten per Nutzen gewählten Stufe weiterspringen. Baut auf beidem oben auf.