feat: Knotenbeschreibungen — "-Zeilen und ----Beschreibungsteil (SPEC §1/§9, D40)

Parser: `"`-Zeilen (Leerraum-Regel, nur ohne Zerlegungszeichen) hängen am
vorangehenden Knoten; hinter einem `---`-Trenner eröffnen #id-Zeilen
Blöcke, deren eingerückte Zeilen der Text sind (Leerzeilen = Absätze,
weitere Trenner bedeutungslos). Freitext ohne §1-Extraktion, nur %% fällt
weiter weg. Warnungen: unknownDesc (ID ohne Knoten, Blocktext wird still
geschluckt) und descStray je verwaister Zeile — ein versehentlicher
Trenner meldet die verschluckten Knotenzeilen zeilengenau. Anzeige im
Tooltip (Text zuerst, mehrzeilig) + aria-label, ”-Marke am Knoten
(nicht im Export — eine Marke ohne Ziel wäre Rauschen). i18n in allen
9 Sprachen; SPEC-§11-Abschnitt in §1/§9 überführt; 16 neue Tests
(tests/desc.test.js).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-22 19:01:02 +02:00
co-authored by Claude Fable 5
parent c4abd24ce8
commit a42710b38f
10 changed files with 320 additions and 67 deletions
+38
View File
@@ -1909,3 +1909,41 @@ heißt Kosten investiert, und investiert ist investiert, auch wenn
Abhängigkeiten den Knoten zurückhalten; und „Was ist neu?“ (D28) — der gelbe
Kranz meldet das `[^]` im Text, also den Deploy des Knotens selbst. Beide
Prüfungen laufen im Parser bzw. auf dem Text und bleiben unberührt.
## D40 — Knotenbeschreibungen gebaut: Tooltip statt Pop-up, ”-Marke, laute Strays
Die in D34 entschiedene Schreibweise (`"`-Zeilen, `---`-Beschreibungsteil) ist
umgesetzt (SPEC §1/§9). Die Bau-Entscheidungen:
**Anzeige im Tooltip, kein eigenes Pop-up.** SPEC §11 ließ „Tooltip oder
Pop-up“ offen. Ein Pop-up bräuchte eine eigene Geste (Klick ist der Link,
Alt+Klick der Sprung, der lange Druck ebenso — es bliebe nur ein weiteres
Klickziel neben dem Falt-Zeichen), Positionierung, Schließen-Logik und
Mobil-Verhalten. Der Tooltip kostet nichts davon: Der Beschreibungstext steht
**zuerst** (mehrzeilig — `title` zeigt Zeilenumbrüche), danach die
Kurz-Fakten (ID, Abhängigkeiten, Status). Bekannte Grenze: Auf Touch-Geräten
gibt es keine Tooltips — dort bleibt der Text vorerst nur im `aria-label`;
ein Pop-up kann später ergänzt werden, die Syntax ändert sich dadurch nicht.
**Auffindbarkeit: die ”-Marke.** Eine Beschreibung, die nur im Tooltip lebt,
wäre unsichtbar (die D25-Lehre: was niemand sieht, ist keine Funktion). Ein
Knoten mit Beschreibung trägt deshalb ein kleines ” hinter dem Label — es
spiegelt das `"`-Zeichen der Notation, wie die `[x]`-Marke (D39) deren
Statusboxen spiegelt; kein neues Symbol zu lernen. **Nicht im Export**: Der
Text selbst kann im statischen Bild nicht erscheinen, eine Marke ohne Ziel
wäre Rauschen — anders als „▸ n“ (D38), das eine nachprüfbare Aussage über
verborgene Knoten trifft. Screenreader bekommen den Text im `aria-label`.
**Strays warnen einzeln, Blöcke unter unbekannter ID schlucken still.** Die
beiden Fehlerfälle sind verschieden: Eine verwaiste Zeile (uneingerückt und
keine ID-Zeile, oder eingerückt ohne offenen Block) ist wahrscheinlich ein
**verrutschter Knoten** — genau der Fall des versehentlichen Trenners mitten
im Plan — und meldet sich je Zeile (`descStray`), damit nichts still
verschwindet. Ein Block unter einer **unbekannten ID** dagegen ist als
Beschreibung erkennbar und schon mit `unknownDesc` gemeldet; seine Textzeilen
zusätzlich einzeln anzuprangern wäre nur Lärm (SKIP-Ziel im Parser).
**Freitext heißt Freitext:** In Beschreibungszeilen findet keine
§1-Extraktion statt — `(M)`, `@name`, `#id` oder URLs im Text bleiben Text.
Einzige Ausnahme ist `%%`: Der Kommentar fällt im ganzen Dokument als
Erstes weg (einheitliche Regel, §1) — so lassen sich auch Beschreibungen
kommentieren.
+42 -61
View File
@@ -94,6 +94,37 @@ hat etwas, das ein Cursor nicht hat: **alle** sehen dieselbe Stelle.
- Sie bleibt im Text stehen, bis jemand sie löscht; ein Werkzeug entfernt sie
nicht von selbst.
**Beschreibungszeilen (`"`) und Beschreibungsteil (`---`)** — erläuternder
Text zu einem Knoten (Anzeige: §9):
- **Kurzform:** Eine Zeile, deren erstes Zeichen nach der Einrückung `"` ist
(**mit folgendem Leerraum**, Leerraum-Regel wie bei `=` und `>`/`<` — ein
Label wie `"Zitat"` bleibt ein Label), ist **Beschreibung, kein Knoten**.
Sie gehört zum **vorangehenden Knoten**; mehrere `"`-Zeilen setzen dieselbe
Beschreibung fort. Die Einrückung der Zeile hat keine Bedeutung (Konvention:
wie ein Kind eingerückt); ohne vorangehenden Knoten: Warnung `descStray`.
Nur auf Zeilen **ohne** Zerlegungszeichen — `- " Zitat" …` bleibt ein
gewöhnlicher Knoten.
- **Langform:** Eine Zeile aus **drei oder mehr `-`** (nur Bindestriche,
umgebender Leerraum erlaubt) trennt den Baumteil vom **Beschreibungsteil**;
alles danach gehört zu ihm (YAML-/Frontmatter-Konvention). Es gibt keinen
Schlusszaun — er kann also nicht vergessen werden. Dort eröffnet eine
**uneingerückte Zeile mit genau einer Knoten-ID** (`#auth`, allein) einen
Block; die **eingerückten** Zeilen darunter sind sein Text (um den Einzug
gekürzt, Leerzeilen bleiben als Absatztrenner). Die Wurzelknoten-Regel (§2)
gilt hinter dem Trenner nicht mehr. Weitere `---`-Zeilen dort sind ohne
Bedeutung.
- **Fehlertoleranz:** ID ohne Knoten → `unknownDesc`; uneingerückte
Nicht-ID-Zeilen und eingerückte Zeilen ohne offenen Block → `descStray`, je
mit Zeilennummer. Ein versehentlicher Trenner mitten im Plan meldet die
verschluckten Knotenzeilen so zeilengenau selbst.
- Der Inhalt ist **Freitext** — die Extraktion aus diesem Abschnitt findet
darin nicht statt; nur `%%`-Kommentare fallen weiterhin als Erstes weg.
Mehrere Blöcke und Kurz- und Langform zum selben Knoten werden in
Dokumentreihenfolge aneinandergehängt.
- Bewusste Verhaltensänderungen: `---` ergab früher einen Knoten mit Label
`--`; eine zeichenlose `" `-Zeile war früher ein Wurzelknoten.
Referenz-Regex der Implementierung:
```
@@ -259,6 +290,14 @@ Stück zwischen Elternknoten und erstem Abzweig — eine kleine **„1“-Plaket
(weißer Kreis mit grauem Rand, graue Ziffer): „genau eine“. Sie erscheint auch
im Grafikexport. Siehe D35.
**Knotenbeschreibungen (§1)** erscheinen im **Tooltip** des Knotens (zuerst
der Text, dann die Kurz-Fakten wie ID und Abhängigkeiten) und im
`aria-label`. Ein Knoten mit Beschreibung trägt eine kleine **”-Marke** hinter
dem Label — sie macht die sonst unsichtbare Beschreibung auffindbar und
spiegelt das `"`-Zeichen der Notation. Die Marke erscheint **nicht** im
Grafikexport: Der Text selbst kann dort nicht angezeigt werden, eine Marke
ohne Ziel wäre Rauschen. Siehe D40.
**Die Knotenfarbe zeigt den effektiven Status (§4)**, nicht den intrinsischen —
das Diagramm beantwortet „wie weit ist das wirklich?“. Wo der eigene Status
**weiter** ist als der effektive (der Knoten wird von Abhängigkeiten
@@ -713,67 +752,9 @@ die Rechnung schwerer als heute — siehe D34.
### Knotenbeschreibungen (`"` und `---`)
Erläuternder Text zu einem Knoten, im Diagramm als Tooltip oder Pop-up.
Beide Schreibweisen sind **entschieden** (D34-Nachtrag), noch nicht gebaut.
Der Kern des Problems war: Einrückung bedeutet Hierarchie (§2) — eine
eingerückte Folgezeile **ist** ein Kindknoten, und jede Zeile ohne Zeichen ist
ein Wurzelknoten. Die Kurzform löst das mit einem eigenen Zeichen, die
Langform, indem sie den Geltungsbereich dieser Regeln beendet.
**Kurzform — `"`-Zeile unter dem Knoten:**
```
- [~] Auth-Dienst #auth (L)
" Kapselt Login, Tokens und Rollen.
```
- Eine Zeile, deren erstes Zeichen nach der Einrückung `"` ist (**mit
folgendem Leerraum**, Leerraum-Regel wie bei `=` und `>`/`<` — ein Label wie
`"Zitat"` bleibt damit ein Label), ist **Beschreibung, kein Knoten**.
- Sie gehört zum **vorangehenden Knoten**; mehrere `"`-Zeilen hintereinander
setzen dieselbe Beschreibung fort. Die Einrückung der `"`-Zeile hat keine
Bedeutung (Konvention: wie ein Kind eingerückt). Eine `"`-Zeile ohne
vorangehenden Knoten ist eine Warnung mit Zeilennummer.
- Der Inhalt ist **Freitext**: Die §1-Extraktion (Größe, Tags, IDs, URL …)
findet darin nicht statt. Nur `%%`-Kommentare werden weiterhin entfernt —
der Kommentar fällt als Erstes (§1), einheitlich im ganzen Dokument.
- Nur auf Zeilen **ohne** Zerlegungszeichen: `- " Zitat" als Label` bleibt ein
gewöhnlicher Knoten.
**Langform — Beschreibungsteil hinter `---`:**
```
[~] Auth-Dienst #auth (L)
- [ ] Login
---
#auth
Hintergrund, Entscheidungen, Verweise — freier Text,
zeilenweise eingerückt. Leerzeilen trennen Absätze.
#api
Der nächste Block.
```
- Eine Zeile aus **drei oder mehr `-`** (nur Bindestriche, umgebender Leerraum
erlaubt) trennt den Baumteil vom **Beschreibungsteil**; alles danach gehört
zu ihm (YAML-/Frontmatter-Konvention: „ab hier etwas anderes“). Es gibt
keinen Schlusszaun — er kann also nicht vergessen werden.
- Im Beschreibungsteil eröffnet eine **uneingerückte Zeile mit genau einer
Knoten-ID** (`#auth`, allein) einen Block; die **eingerückten** Zeilen
darunter sind sein Text (um den Einzug gekürzt; Leerzeilen bleiben als
Absatztrenner erhalten). Anführungszeichen braucht es hier nicht — die
Wurzelknoten-Regel (§2) gilt hinter dem Trenner nicht mehr.
- **Fehlertoleranz:** Eine ID ohne zugehörigen Knoten → Warnung (wie
`unknownDep`). Eine uneingerückte Zeile, die keine ID-Zeile ist, oder
eingerückte Zeilen ohne eröffneten Block → Warnung mit Zeilennummer. Ein
versehentlicher Trenner mitten im Plan fällt dadurch sofort auf: Die
verschluckten Knotenzeilen werden zeilengenau gemeldet.
- Mehrere Blöcke zur selben ID werden in Dokumentreihenfolge aneinander-
gehängt; Kurz- und Langform zum selben Knoten dürfen koexistieren
(Anzeige-Details werden beim Bauen festgelegt). Weitere `---`-Zeilen im
Beschreibungsteil haben keine Bedeutung.
- Bewusste Verhaltensänderung: Eine Zeile `---` ergab bisher einen Knoten mit
Label `--`; sie ist jetzt der Trenner.
**Umgesetzt** — Schreibweise in §1 (Kurzform als `"`-Zeile, Langform als
ID-Blöcke im `---`-Beschreibungsteil), Anzeige in §9 (Tooltip, ”-Marke).
Entscheidung und verworfene Alternativen: D34-Nachtrag, D40.
## 12. Dateiendung
+4 -2
View File
@@ -111,8 +111,10 @@ entscheiden, **bevor** Code entsteht.
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
- [x] 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). Zu bauen: Parser + Anzeige.
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`.