board.js rechnet headless Rollen (&epic/&story/&task, sonst aus Schachtelung und Größe), Lanes aus den obersten Epics, Karten mit Aufgabenzeilen und Status-Leiste; renderBoardHtml zeichnet, Karten und Zeilen sind .node mit den Attributen des Baums. Nur Anzeige; Filter, Zähler, Export und Drag&Drop folgen als eigene Teilpakete. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #6
132 lines
6.5 KiB
Markdown
132 lines
6.5 KiB
Markdown
> **Hinweis:** Dieses Dokument beschreibt nur die Änderung dieses PR.
|
||
> Es kann veraltet sein, sobald der nächste PR gemergt ist.
|
||
> Historische PR-Dokumentation wird nicht nachgepflegt — sie ist eine Momentaufnahme, keine aktuelle Doku.
|
||
|
||
## Das Problem
|
||
|
||
D98 hat die Kanban-Ansicht geplant; gebaut war nichts.
|
||
Das Risiko des Features ist das Kartenmodell — die Regel, nach der ein Baum beliebiger Tiefe zu Lanes, Karten und Aufgabenzeilen wird.
|
||
Die Regel muss stehen und am echten Plan stimmen, bevor sich das Zeichnen lohnt; und sie ist erst zu beurteilen, wenn man sie sieht.
|
||
|
||
## Nicht das Ziel
|
||
|
||
- Kein Umhängen im Baum durch Ziehen: Der Drop ändert die Statusbox, nie die Lane.
|
||
- Faltmarken wirken nicht auf das Board (Nutzer-Entscheidung); der Falt-Durchschalter ruht dort.
|
||
- Keine Änderung an den drei Baum-Modi.
|
||
|
||
## Die Szenarien
|
||
|
||
### Feature: Kanban-Board als vierter Modus
|
||
|
||
#### Szenario#6.01: Rollen ohne Schlagworte
|
||
|
||
Damit ein Plan ohne ein einziges Tag ein vollständiges Board ergibt.
|
||
|
||
- **Gegeben** `#fe` mit den Blättern `#fe.rel (S)`, `#fe.accounts (L)` und `#infra` mit dem Paket `#infra.db` und dem Blatt `#infra.decision`
|
||
- **Wenn** die Rollen abgeleitet werden
|
||
- **Dann** ist `#fe` eine Story mit allen Blättern als Tasks, `#infra` ein Epic, `#infra.db` eine Story und `#infra.decision` eine Task ohne Story
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- `tests/board.test.js`, Block „Rollen — abgeleitet aus Schachtelung und Größe“.
|
||
|
||
#### Szenario#6.02: Schlagworte übersteuern
|
||
|
||
Damit ein Autor die Ableitung dort korrigiert, wo sie rät.
|
||
|
||
- **Gegeben** `&story` an einem Knoten mit Enkeln, `&epic` an einem Knoten mit Blättern
|
||
- **Wenn** die Rollen abgeleitet werden
|
||
- **Dann** sind unter der Story alle Nachkommen Tasks, unter dem Epic alle Blätter Stories ohne Aufgaben
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- `tests/board.test.js`, Block „Rollen — Schlagworte übersteuern“.
|
||
|
||
#### Szenario#6.03: Spalten aus den Boxen, Lanes aus den obersten Epics
|
||
|
||
- **Gegeben** der Plan aus Szenario 1
|
||
- **Wenn** das Board gebaut wird
|
||
- **Dann** gibt es sieben Spalten (acht mit Verworfen-Filter), die Lane der Wurzel mit ihren direkten Stories zuerst, dann eine Lane je oberstem Epic; `[!]` steht in der `[ ]`-Spalte
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- `tests/board.test.js`, Blöcke „Spalten“ und „Lanes und Karten“; im Browser am HSAdmin-Plan: 7 Lanes, 62 Karten, 35 Aufgabenzeilen.
|
||
|
||
#### Szenario#6.04: Karten sind Knoten
|
||
|
||
Damit Cursor-Zeile, Knoten-Fenster und Sprünge ohne neue Verdrahtung gelten.
|
||
|
||
- **Gegeben** das Board mit der Story `#fe` und ihrer Aufgabenzeile `#fe.rel`
|
||
- **Wenn** der Cursor im Text auf der Zeile von `#fe.rel` steht bzw. eine Zeile geklickt wird
|
||
- **Dann** trägt die Aufgabenzeile die `current`-Hervorhebung bzw. öffnet das Knoten-Fenster mit ihren Fakten
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- `tests/board.test.js`, Block „renderBoardHtml“ (`data-line`/`data-tip` an Karte, Zeile und Lane-Titel).
|
||
- Browser: `node brow st-arbeit current pulse` an `#fe.rel`; echter Klick auf `#fe.accounts` öffnet `#fe.accounts · planned`.
|
||
|
||
#### Szenario#6.05: Linse und Pfad filtern das Board
|
||
|
||
Damit die beiden vorhandenen Bedienelemente das Board bedienen, ohne eigene Filterleiste.
|
||
|
||
- **Gegeben** ein Plan mit `@`-Tags und ein günstigster Pfad
|
||
- **Wenn** eine Person in der Personen-Leiste gewählt ist bzw. der Pfad-Umschalter an ist
|
||
- **Dann** bleiben nur die Karten und Aufgabenzeilen der Person (mit Vererbung vom Paket) bzw. auf dem Pfad stehen; leere Lanes entfallen; die Spaltenköpfe zählen das Gezeigte samt ordinaler Größen-Spanne
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- `tests/board.test.js`, Blöcke „Filter — Personen-Linse“, „Filter — nur der günstigste Pfad“, „Zähler je Spalte“.
|
||
- Browser am HSAdmin-Plan: 50 Karten → Linse `@marc` 9 Karten in 3 Lanes; Kopf „no status 40 · S–L“.
|
||
|
||
#### Szenario#6.06: Status schreiben, nicht über die Aufgaben hinaus
|
||
|
||
Damit das Board ein Werkzeug ist und nicht nur eine Ansicht — ohne dass eine Story ihren Aufgaben davonläuft.
|
||
|
||
- **Gegeben** die Story `#fe` in `[~]` mit den Aufgaben `[~]`, `[~]`, `[ ]`
|
||
- **Wenn** die Karte in „planned“ gezogen oder in der Auswahl `[ ]` gewählt wird
|
||
- **Dann** steht `[ ]` in der Zeile und die Karte in der Spalte; „done“ nimmt die Karte nicht an und `~ / x ^` sind in der Auswahl gesperrt, bis die Aufgaben so weit sind
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- `tests/board.test.js`, Block „Aufgaben-Schranke“.
|
||
- Browser am HSAdmin-Plan: `data-ceil="1"`, gesperrte Einträge `~ / x ^`, Drop auf „done“ bernstein ohne Schreiben, Drop auf „idea“ schreibt `[?]`.
|
||
|
||
#### Szenario#6.07: Export und Druck zeigen das Board
|
||
|
||
Damit „die Sicht als Bild teilen“ auch für das Board gilt.
|
||
|
||
- **Gegeben** das Board mit Linse oder Pfad-Filter
|
||
- **Wenn** Kopieren, SVG oder PNG ausgelöst wird
|
||
- **Dann** enthält das Bild Kopfzeile, Lanes und die gezeigten Karten mit Status-Leiste und Aufgabenzeilen; Abweichungs- und ”-Marke fehlen
|
||
|
||
##### Nachgewiesen durch
|
||
|
||
- Browser am HSAdmin-Plan: SVG 1208 × 8248 px, 333 Rechtecke, 501 Texte, als Bild geprüft.
|
||
|
||
## Die Lösung
|
||
|
||
- `frontend/src/board.js` (neu, headless): `assignRoles`, `boardModel`, `columnOf`, `taskShares`, `filterBoard`, `columnStats`, `taskCeiling`, `statusAllowed`.
|
||
- `frontend/src/render.js`: `nodeDataAttrs` aus `nodeHtml` herausgelöst und mit `renderBoardHtml` geteilt; `gateWarnings`, damit `mixedGate` auch im Board gemeldet wird.
|
||
- `frontend/src/app.js`: Modus `kanban` in `applyLayout` (Neubau beim Wechsel, Falt-Knopf ausgegraut) und `render()` (Board-Zweig), Wächter in `drawDepLinks`, `cheap-on` nur im Baum, `LAYOUT_MODES` für den Mobil-Wähler; `boardToSvg()` und die Weiche `exportSvg()` für Kopieren/SVG/PNG.
|
||
- `index.html`: viertes Icon; `style.css`: Board-Regeln unter `#out.kanban`; i18n `modeKanban`/`boardNoStatus` × 9.
|
||
- SPEC §9 (neue Sektion) und §11 (Ableitung wie gebaut), `llms.md`, D98-Nachtrag, CHANGELOG, Plan-Knoten `#ed.kanban` samt allen sieben Teilpaketen und `#not.tag.roles` auf `[^]`.
|
||
|
||
Warum die Ableitung beim Bauen korrigiert wurde: Die D98-Fassung „Blatt ab M ist eine Story“ machte `#fe.accounts (L)` zur Story und damit `#fe` zum Epic — die Frontend-Karte zerfiel.
|
||
Jetzt zählt die Größe nur bei Blättern neben Paketen; ein Paket aus Blättern bleibt eine Karte.
|
||
|
||
## Offene Fragen
|
||
|
||
- Keine für diesen PR. Die Lane-Titel auf dem Telefon und die Breite der Spalten werden mit dem Filter-Teilpaket noch einmal angesehen.
|
||
|
||
## Weitere Änderungen
|
||
|
||
- Keine.
|
||
|
||
## Vorausgesetzte PRs
|
||
|
||
- PR#5 (Planung, D98).
|
||
|
||
## Folge-PRs
|
||
|
||
- Keine geplant; die Kanban-Ansicht ist mit diesem PR vollständig.
|