From 10c5ffb931139d8f07cca0ffadc042e8ec1aa42f Mon Sep 17 00:00:00 2001 From: mhoennig Date: Sat, 22 Aug 2026 20:58:52 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20llms.txt=20=E2=80=94=20die=20Notation?= =?UTF-8?q?=20f=C3=BCr=20KI-Agenten,=20unter=20der=20Site-Wurzel=20(SPEC?= =?UTF-8?q?=20=C2=A713,=20D43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Englische Markdown-Kurzfassung der Notation (Syntax + Semantik: Gates, Status, Ränge, Extraktionsreihenfolge, Abhängigkeits- und Beschreibungsregeln, Schreib-Faustregeln, vollständiges Beispiel), damit Agenten Werkbaum lesen und schreiben können. Name und Ort folgen der llms.txt-Konvention; Quelle in frontend/public/ (Dev-Server und dist/ gratis), Pages-Workflow und deploy-prod.sh kopieren sie mit je einer Zeile, Footer verlinkt den Dateinamen (keine i18n nötig, Tooltip DE·EN). Die SPEC bleibt normativ — Hausregel jetzt: SPEC zuerst, dann Code, dann llms.txt nachziehen. Co-Authored-By: Claude Fable 5 --- .github/workflows/pages.yml | 2 + CLAUDE.md | 4 +- docs/DECISIONS.md | 34 ++++++ docs/SPEC.md | 9 ++ docs/examples/werkbaum.werkbaum | 1 + frontend/index.html | 2 +- frontend/public/llms.txt | 186 ++++++++++++++++++++++++++++++++ scripts/deploy-prod.sh | 2 + 8 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 frontend/public/llms.txt diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 92ac6e1..1157c97 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -84,6 +84,8 @@ jobs: -e "s#\(]*>\)[0-9.]\+#\1${BUILD_VERSION}#" \ frontend/dist/index.html > site/index.html cp LICENSE site/LICENSE + # Agenten-Fassung der Notation (D43) — liegt per Vite-public/ in dist/ + cp frontend/dist/llms.txt site/llms.txt - name: Pages-Konfiguration uses: actions/configure-pages@v6 diff --git a/CLAUDE.md b/CLAUDE.md index 0551399..440cb7b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,9 @@ Integrations-Backend. ## Verbindliche Referenzen - Sprachdefinition: @docs/SPEC.md — die Notation ist der gemeinsame Vertrag - von Frontend und Backend. Syntaxänderungen: SPEC **zuerst**, dann Code. + von Frontend und Backend. Syntaxänderungen: SPEC **zuerst**, dann Code, + dann die Agenten-Fassung `frontend/public/llms.txt` nachziehen + (SPEC §13, D43). - Entscheidungen: @docs/DECISIONS.md — respektieren; Abweichungen als neuen Eintrag begründen, alte Einträge nie löschen. Besonders D13 (Backend-Stack) und D14 (Parser-Hoheit) beachten. diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index b5b5539..a6150a4 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -2069,3 +2069,37 @@ als Hülle für Tests und Kompatibilität; `render()` liest `exact` für die Warnung. `markCheapest` entfällt — die Menge entsteht jetzt in einem Worklist-Durchlauf je Belegung (Zyklen enden über die Mengen-Prüfung von selbst; erste ID-Vergabe gewinnt, D36/D39). + +## D43 — `llms.txt`: die Notation für KI-Agenten, unter der Site-Wurzel +KI-Agenten sollen Werkbaum-Texte lesen **und schreiben** können, ohne die +deutsche SPEC durchzuarbeiten. Dafür liefert jede Instanz eine englische +Markdown-Kurzfassung der Notation unter `/llms.txt` aus +(`https://werkbaum.javagil.de/llms.txt`). Die Entscheidungen: + +**Der Name folgt der llms.txt-Konvention** (llmstxt.org): eine Markdown-Datei +an der Site-Wurzel, die die Site für Sprachmodelle beschreibt — genau der +Zweck, und zunehmend der Ort, an dem Agenten und Werkzeuge von sich aus +nachsehen. Ein hübscherer Name (`notation.md`) wäre nicht auffindbar. Im +Footer steht der **Dateiname selbst als Link** — dadurch braucht er keine +Übersetzung in neun Sprachen; der Tooltip ist knapp zweisprachig (DE · EN), +wie beim Build-Hinweis (D16: Metainformation, kein Produkt-Feature-Text). + +**Englisch, obwohl die Doku deutsch ist.** „Doku auf Deutsch" (CLAUDE.md) +gilt der Projekt­dokumentation; die Agenten-Fassung ist ein **ausgeliefertes +Produkt-Artefakt** mit weltweitem Publikum — dieselbe Logik, nach der das +Beispiel-Dokument englisch ist (D22). + +**Quelle in `frontend/public/`** — damit erledigt Vite die halbe Arbeit: Der +Dev-Server liefert `/llms.txt` direkt aus, `vite build` kopiert es nach +`dist/`, und beide Deploy-Wege (Pages-Workflow und `deploy-prod.sh`, die die +Site je von Hand zusammenstellen, D16) kopieren es mit einer Zeile weiter. +Bewusst **nicht** in die eine `index.html` eingebettet: Agenten holen eine +URL, kein Bundle. + +**Drift ist das Hauptrisiko** — dieselbe Sorge wie bei einem zweiten Parser +(D14). Gegenmittel: Die Datei erklärt selbst, dass die SPEC normativ ist, und +die Hausregel in CLAUDE.md lautet jetzt „SPEC zuerst, dann Code, **dann +llms.txt nachziehen**" (SPEC §13 verweist zurück). Inhaltlich beschreibt sie +nur die **Notation samt Semantik** (Gates, Status, Ränge, Extraktions- +reihenfolge, Schreibregeln, ein vollständiges Beispiel) — keine Editor-UI: +Die braucht ein schreibender Agent nicht, und sie ändert sich öfter. diff --git a/docs/SPEC.md b/docs/SPEC.md index e9a5793..9d11259 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -797,3 +797,12 @@ Entscheidung und verworfene Alternativen: D34-Nachtrag, D40. - Es gibt keinen registrierten MIME-Typ; wer selbst ausliefert, nimmt `text/plain; charset=utf-8` (dann zeigt der Browser die Datei an, statt sie herunterzuladen). Siehe D24. + +## 13. Agenten-Fassung (`llms.txt`) + +Eine **englische Kurzfassung dieser Spezifikation für KI-Agenten** (lesen +**und** schreiben) liegt als Markdown in `frontend/public/llms.txt` und wird +von jeder Instanz unter der Site-Wurzel ausgeliefert +(`https://werkbaum.javagil.de/llms.txt`) — die llms.txt-Konvention. **Diese +SPEC bleibt normativ**: Bei Syntaxänderungen wird die Agenten-Fassung im +selben Zug nachgezogen (CLAUDE.md). Siehe D43. diff --git a/docs/examples/werkbaum.werkbaum b/docs/examples/werkbaum.werkbaum index 6fb37dd..0be9408 100644 --- a/docs/examples/werkbaum.werkbaum +++ b/docs/examples/werkbaum.werkbaum @@ -23,6 +23,7 @@ - [^] A long block at the end, addressed by its id (S) %% behind a --- separator - [-] A separate storage format for the structure (L) %% the text is the format - [ ] Ticket references (#123) (S) + - [x] llms.txt, the notation explained to AI agents (S) - [?] Benefit per node, not only cost (M) | [?] Another sigil next to the size (S) | [?] Story points behind the T-shirt sizes (M) diff --git a/frontend/index.html b/frontend/index.html index 13c2518..eb78d3b 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -198,7 +198,7 @@ - + diff --git a/frontend/public/llms.txt b/frontend/public/llms.txt new file mode 100644 index 0000000..f5bf007 --- /dev/null +++ b/frontend/public/llms.txt @@ -0,0 +1,186 @@ +# Werkbaum notation — guide for AI agents + +Werkbaum is a plain-text notation for work-breakdown structures (WBS) with +and/or decomposition. This guide teaches you to **read and write** it. The +normative specification (German) is +https://github.com/mhoennig/werkbaum/blob/main/docs/SPEC.md — if this guide +and the SPEC disagree, the SPEC wins. + +Files are UTF-8 with LF line endings; the extension `.werkbaum` is a +convention (plain `.txt` works too). The editor at +https://werkbaum.javagil.de renders the notation as a diagram; +`?sourceUrl=` loads any CORS-readable http(s) text file, and +`?etherpad=` follows a live Etherpad. + +## Line format + + [indent][gate] [fold] [status] Label (SIZE) URL @person #id :#id,#id !!! %% comment + +One node per line. Everything except the label is optional. + +### Hierarchy (indentation) + +- Indentation defines the tree: a node's parent is the nearest line **above** + with **less** indentation (a tab counts as 2 spaces; 2-space steps are the + convention). +- Lines without a gate character are **root** nodes; several roots make + several trees side by side. + +### Gate (first character after the indent) + +| char | meaning | semantics | +|---|---|---| +| `-` | all of | required part — all `-` siblings are needed | +| `+` | optional | a nice-to-have on the same and-group, dispensable | +| `\|` | any of | alternatives — at least one will be chosen | +| `=` | exactly one (xor) | alternatives — exactly one may be realized | + +- `-` and `+` may be mixed within one sibling group (conjunctive group). + `|` groups and `=` groups must be **uniform** — any other mixture is + invalid (rendered by the first child, warning `mixedGate`). +- `=` is recognized only with **following whitespace** — `=SUM(A1:B2)` stays + a label. +- In an `=` group at most **one** alternative may be *realized* (status + `[~]`, `[/]`, `[x]` or `[^]`); each additional realized one warns + (`xorConflict`). +- Optionality (`+`) is orthogonal to status: an optional node can be long + `[^]`. Optional nodes never count toward the cheapest path. + +### Fold mark (between gate and status box; on root lines at line start) + +- `>` — this subtree starts **collapsed** when the document opens. +- `<` — inside a collapsed region, bring this subtree back into view. +- Recognized only with following whitespace (`- >Careful` stays a label). + Presentation only: no effect on meaning, costs or warnings. + +### Status box + +| box | key | meaning | +|---|---|---| +| `[?]` | idea | vague idea | +| `[ ]` | planned | decided, nothing invested | +| `[~]` | in progress | costs invested, risk high | +| `[/]` | walking skeleton | works end to end, polish missing | +| `[x]` | done | complete | +| `[^]` | in production | deployed / live | +| `[-]` | discarded | deliberately dropped (hidden by default) | +| `[!]` | high risk | effort still unclear | + +- No box = neutral node. `x` may also be uppercase `X`. +- Unknown codes are tolerated: the node renders neutral, with a warning — + the line is never lost. + +### Size (effort) + +- T-shirt sizes in parentheses: `(XS) (S) (M) (L) (XL) (XXL)`. +- From `(M)` upward a node **should be decomposed further**; a node ≥ M + without children gets a placeholder hint in the diagram. +- For cost estimation a missing size counts as `M`. + +### Token extraction order (why nothing collides) + +1. `%% comment` — everything from `%%` to end of line is stripped **first** + (whole line or trailing part). This also applies inside descriptions. +2. Bare `https?://…` URL — makes the node clickable; extracted early so `@`, + `#` and `!!!` inside URLs never trigger. +3. `(SIZE)` — first match, case-insensitive. +4. `@name` — people tags; several per line, any position. Characters: + Unicode letters, digits, `.`, `_`, `-`. +5. `#id` — **node ID**: the *first* free-standing `#token` of the line + (preceded by start-of-line or whitespace). Uniquely names the node in the + whole document; a duplicate ID warns, and references resolve to the first + occurrence. Later `#tokens` stay label text; `C#` stays a label. Same + character set as `@name`. +6. `:#a,#b` — **dependencies**: one contiguous free-standing token — colon, + then comma-separated IDs, each with `#`, **no spaces** (`:#a, #b` reads + only `#a`, and the free-standing ` #b` would become the node ID!). + Several tokens per line merge. `(:#a,#b)` in parentheses stays label text + (quoting convention, same as `(#id)`). +7. `!!!` — **focus mark**, free-standing only: "everybody look here" — a + shared pointer for collaborative editing. Independent of status and + necessity; `Wow!!!` stays a label. +8. Whatever remains, whitespace-normalized, is the **label**. An empty label + means the line is ignored. + +### Dependency semantics + +- Dependencies constrain **status**, not order or start time — this is not a + PERT chart. A node is *effectively* at most as far as everything it needs: + progress ranks are `[?]`=0, `[ ]`=1, `[!]`=1, `[~]`=2, `[/]`=3, `[x]`=4, + `[^]`=5 (neutral and `[-]` count 0), and the **effective rank is the + minimum of the intrinsic ranks over the node itself and everything + reachable via `:#…`**. The diagram colors nodes by effective status and + marks held-back nodes with their own status box. +- Write only the **intrinsic** status into the text. The effective one is + always computed — never write it (one source of truth). +- **Cycles are legal** and mean "finished together" — no warning, including + self-dependencies. +- Referencing a nonexistent ID warns (`unknownDep`). +- For the cheapest-path cost, dependencies pull their targets (plus the + targets' own realization and dependencies) into the needed set; shared + targets count **once**. Discarded (`[-]`) targets are never pulled. + +### Descriptions + +- **Short form:** a line whose first non-blank character is `"` followed by + whitespace is a *description of the preceding node*, not a node. Several + consecutive `"` lines continue the same description; their indentation is + irrelevant. `"Quote"` without following whitespace stays a label. Only on + lines without a gate character. +- **Long form:** a separator line of three or more dashes (`---`) ends the + tree part. After it, an **unindented** line holding exactly one `#id` + opens a block; the **indented** lines below it are its text (blank lines = + paragraph breaks). There is no closing fence — the description section + runs to end of file. Stray lines there produce warnings, never silent loss. +- Inside descriptions no token extraction happens — `(M)`, `@name`, `#id` + and URLs stay literal text. Only `%%` comments are still stripped. + +## Rules of thumb for writing Werkbaum + +- One node per line; the label is mandatory, all else optional. +- Let indentation carry the hierarchy; keep sibling gates aligned. +- Never mix `|` or `=` with other gates in one sibling group. +- Decompose everything `(M)` or larger. +- Give a node its own status only; express "blocked by" with `:#…` + dependencies instead of understating the status. +- Mark nice-to-haves with `+` — otherwise they inflate the cheapest path. +- Keep rejected alternatives as `[-]` instead of deleting them: the decision + stays visible (add the reason as a `%%` comment). +- To mention syntax literally in a label without triggering it, wrap it in + parentheses or quotes: `(#id)`, `(:#a,#b)`, `"#123"`. + +## Complete example + + %% Project structure – Sprint 14 + [~] Website relaunch (XL) https://wiki.example.com/relaunch + " Folded chapters are done. + - > [x] Concept (M) + - [x] Audience analysis (S) + - [x] Sitemap (XS) + - [~] Implementation (XL) + - [~] Frontend (M) https://git.example.com/frontend @anna + | [ ] PWA (S) + | [ ] Web+Native + - [/] Web (S) + - [ ] Android (M) + - [ ] iOS (M) + - [!] Backend (L) @ben @carla + - [ ] CMS integration #cms (M) + | [ ] WordPress + | [?] Headless CMS + | [-] Custom build %% too much effort + - [x] Landing page (S) :#cms %% done, but effectively waiting for the CMS + + [?] Dark mode (S) %% nice to have, never on the cheapest path + - [?] Hosting (M) %% exactly one of these, hence = + = [ ] Cloud + = [?] On-premise + + --- + #cms + The articles live in the CMS, so everything that shows content + depends on it. + +## Reserved — do not use for other purposes + +- Purely numeric `#123`: ticket references (planned tracker integration). +- Free-standing `&tag`: keywords across the hierarchy (reserved, unbuilt). diff --git a/scripts/deploy-prod.sh b/scripts/deploy-prod.sh index da23918..25a9b35 100755 --- a/scripts/deploy-prod.sh +++ b/scripts/deploy-prod.sh @@ -132,6 +132,8 @@ fi sed "${SED_ARGS[@]}" frontend/dist/index.html > "$STAGE/index.html" cp LICENSE "$STAGE/LICENSE" +# Agenten-Fassung der Notation (D43) — liegt per Vite-public/ in dist/ +cp frontend/dist/llms.txt "$STAGE/llms.txt" # ---- 3) Spiegeln (--delete: nichts Altes bleibt am Ziel) ---- # --chmod=D755,F644 erzwingt web-taugliche Rechte am Ziel, unabhängig von den