feat(site): llms.txt als Wegweiser + Charset-Fix für llms.md

Anlass war die Frage, ob `llms.md` ein guter Name ist. Zwei Befunde:

1. Der Zweck der Konvention ist ein anderer, als D43 annahm. llmstxt.org
   über die eigene Datei: „a markdown file that provides brief background
   information and guidance, along with links to markdown files providing
   more detailed information“ — ein Index, kein Inhalt. Der 211-Zeilen-
   Leitfaden ist genau eine jener verlinkten Dateien; `llms.md` ist damit
   der richtige Name, es fehlte der Wegweiser davor.

2. `llms.md` kam auf der stabilen Instanz falsch kodiert an: Apache kennt
   `.md` nicht und sendet GAR KEINEN Content-Type, der Browser rät
   windows-1252. Gemessen: characterSet=windows-1252, aus „notation —
   guide“ wurde „notation â€" guide“, 31 Zeilen betroffen. GitHub Pages
   liefert dieselbe Datei korrekt als text/markdown; charset=utf-8 aus.

- frontend/public/llms.txt: Index nach der Konvention (Titel, Blockquote,
  Notation in Kurzform, ## Docs, ## Optional). Rein ASCII — er ist die
  Datei, die ein fremder Agent ungefragt abruft, und soll auch dort
  ankommen, wo ein Server die Kodierung verschweigt. Alle 5 Links: 200.
- scripts/prod.htaccess: AddType für .md/.txt/.werkbaum, von
  deploy-prod.sh als .htaccess gespiegelt. Nicht in public/ — dort landete
  es wirkungslos im Pages-Artefakt. Rückweg bei 500 steht in der Datei.
- Beide Deploy-Wege kopieren llms.txt mit.

SPEC §13 + D43-Nachtrag 2 (mit Richtigstellung der D43-Annahme);
Plan: #not.llms.index [x]. 243 Tests grün, Plan 157 Knoten, 0 Warnungen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-24 11:01:51 +02:00
co-authored by Claude Opus 5
parent cb966e4e20
commit 48d3174684
7 changed files with 137 additions and 3 deletions
+2
View File
@@ -86,6 +86,8 @@ jobs:
cp LICENSE site/LICENSE
# Agenten-Fassung der Notation (D43) — liegt per Vite-public/ in dist/
cp frontend/dist/llms.md site/llms.md
# Wegweiser der llms.txt-Konvention (D43-Nachtrag 2)
cp frontend/dist/llms.txt site/llms.txt
- name: Pages-Konfiguration
uses: actions/configure-pages@v6
+57 -1
View File
@@ -2805,7 +2805,63 @@ und der Footer-Link rückt zwischen Versionsnummer und Copyright — zur
Werkzeug-Ecke des Footers statt ans Ende hinter die Rechtstexte. Der
Dateiname bleibt als Linktext (übersetzungsfrei), die Wurzel-Lage bleibt.
## D44 — Falt-Umschalter: „ab M abwärts“ statt einer Tiefenzahl
**Nachtrag 2 — `llms.txt` ist ein Wegweiser, keine Referenz; er fehlte, und
die Auslieferung von `llms.md` war kaputt.** Anlass war die Frage, ob
`llms.md` überhaupt ein guter Name sei. Beim Nachsehen kamen zwei Dinge
heraus, und das erste ist eine **Richtigstellung dieses Eintrags**.
**Der Zweck der Konvention ist ein anderer, als D43 annahm.** Der Haupttext
oben beschreibt `llms.txt` als „eine Markdown-Datei an der Site-Wurzel, die
die Site für Sprachmodelle beschreibt — genau der Zweck“. Das ist zu weit
gefasst. llmstxt.org sagt über die eigene Datei wörtlich: *„a markdown file
that provides brief background information and guidance, along with **links to
markdown files providing more detailed information**“* — also ein **Index**,
kein Inhalt. Werkbaums 211-Zeilen-Leitfaden ist genau eine jener
„markdown files providing more detailed information“, auf die so ein Index
zeigt; als `llms.txt` wäre er zweckentfremdet gewesen.
**Damit ist `llms.md` nicht bloß geduldet, sondern richtig** — und der erste
Nachtrag hat aus dem falschen Grund das Richtige getan: Er begründete die
Endung mit Format-Ehrlichkeit und gab dafür die Auffindbarkeit auf, die den
Namen in D43 überhaupt begründet hatte. Tatsächlich musste die Kurzfassung
diesen Namen tragen; gefehlt hat nicht die richtige Endung, sondern der
Wegweiser davor. Der liegt jetzt als `frontend/public/llms.txt` daneben und
wird von beiden Deploy-Wegen mitkopiert.
**Zweiter Befund: `llms.md` kam auf der stabilen Instanz falsch kodiert an.**
Apache kennt die Endung nicht und sendet dann **gar keinen** `Content-Type`
ohne Charset rät der Browser windows-1252. Gemessen am 24.08.2026 auf
`werkbaum.javagil.de`: `document.characterSet` = `windows-1252`, und aus
`# Werkbaum notation — guide for AI agents` wurde `… notation â€" guide …`;
31 Zeilen enthalten ``, `—`, `…` oder `≥`. Dieselbe Datei von GitHub Pages:
`text/markdown; charset=utf-8`, fehlerfrei. Es ist also **kein** Argument
gegen die Endung, sondern ein Konfigurationsfehler auf genau einer Instanz —
und dieselbe Falle, die D24 für `.werkbaum` längst benannt hatte („wer selbst
ausliefert, nimmt `text/plain; charset=utf-8`“).
Behoben mit `scripts/prod.htaccess`, das `deploy-prod.sh` als `.htaccess` in
die Site-Wurzel spiegelt (`.md``text/markdown;charset=utf-8`, dazu `.txt`
und `.werkbaum` als `text/plain`). Bewusst **nicht** in `frontend/public/`:
Von dort landete es über `dist/` auch im Pages-Artefakt, wo es wirkungslos
wäre — Pages ist kein Apache und macht es ohnehin richtig. Der Rückweg steht
in der Datei selbst: Antwortet der Server nach einem Deploy mit 500, verbietet
seine `AllowOverride`-Einstellung `AddType`, und die drei Zeilen gehören in
die vhost-Konfiguration.
**Der Wegweiser ist rein ASCII** — er ist die eine Datei, die ein fremder
Agent ungefragt abruft, und er soll auch dann ankommen, wenn ein Server die
Kodierung verschweigt. Das ist keine Vorsichtsmaßnahme ins Blaue: Genau dieser
Fall ist oben gemessen. Aufbau nach der Konvention: `#`-Titel, Blockquote mit
einem Satz, ein Absatz Notation in Kurzform, dann `## Docs` mit den Links, die
man wirklich braucht, und `## Optional` für DECISIONS und Repo — die Konvention
erlaubt ausdrücklich, den Optional-Abschnitt wegzulassen, wenn der Kontext
knapp ist.
**Der Footer verlinkt weiterhin `llms.md`, nicht den Index.** Für einen
Menschen ist der Leitfaden das nützliche Dokument; der Wegweiser besteht aus
zehn Zeilen Links. Und Agenten finden ihn nicht über den Footer, sondern weil
er an der konventionellen Adresse liegt — wie `robots.txt`, das auch niemand
in eine Fußzeile schreibt. Falt-Umschalter: „ab M abwärts“ statt einer Tiefenzahl
Einzeln zu falten (D38) reicht für einen Plan mit 167 Knoten nicht — man will
den Baum am Stück auf eine Arbeitshöhe bringen. Der Diagramm-Kopf bekommt
dafür einen **Umschalter** neben „verworfene einblenden“ und „günstigster
+9 -2
View File
@@ -990,6 +990,13 @@ Eine **englische Kurzfassung dieser Spezifikation für KI-Agenten** (lesen
**und** schreiben) liegt als Markdown in `frontend/public/llms.md` und wird
von jeder Instanz unter der Site-Wurzel ausgeliefert
(`https://werkbaum.javagil.de/llms.md`); der Footer verlinkt sie neben der
Versionsnummer. Angelehnt an die llms.txt-Konvention, mit `.md` als der zum
Inhalt ehrlichen Endung. **Diese SPEC bleibt normativ**: Bei Syntaxänderungen
Versionsnummer. **Diese SPEC bleibt normativ**: Bei Syntaxänderungen
wird die Agenten-Fassung im selben Zug nachgezogen (CLAUDE.md). Siehe D43.
Daneben liegt `llms.txt` — der **Wegweiser** der llms.txt-Konvention
(llmstxt.org): Name, ein Satz zur Sache und Links auf die Kurzfassung, diese
SPEC, den Editor und das Repo. Er ist bewusst kurz und **rein ASCII**, damit
er auch dort ankommt, wo ein Server die Kodierung nicht mitschickt. Die
Konvention meint mit `llms.txt` genau so einen Index, **nicht** den Inhalt
selbst — die Kurzfassung ist eine der „markdown files providing more detailed
information“, auf die er zeigt. Siehe D43-Nachtrag 2.
+6
View File
@@ -25,6 +25,7 @@
- [-] #not.store: A separate storage format for the structure (L) %% the text is the format
- [ ] #not.ticket: Ticket references (#123,#US-123) (S) %% Taiga writes #US-123 for a user story
- [^] #not.llms: llms.md, the notation explained to AI agents (S)
- [x] #not.llms.index: llms.txt, the signpost that points at it (XS) %% the convention wants an index, not the content
- [?] #not.benefit: Benefit per node, not only cost (M)
| [?] #not.benefit.sigil: Another sigil next to the size (S)
| [?] #not.benefit.points: Story points behind the T-shirt sizes (M)
@@ -296,6 +297,11 @@
AI agent can read and write Werkbaum without working through the German
SPEC. It is not normative: the SPEC changes first and this follows.
#not.llms.index
The llms.txt convention asks for a short index that links to the detailed
files, not for the detailed file itself. This is that index, and it sits at
the one address an agent tries on its own.
#not.benefit
Sizes say what something costs; nothing yet says what it is worth. With both
you could sort by value for money instead of only minimizing cost.
+33
View File
@@ -0,0 +1,33 @@
# Werkbaum
> A plain-text notation for work breakdown structures (WBS) with and/or
> decomposition, plus a browser editor that renders it as a diagram. This file
> is an index; the notation itself is explained in the guide linked below.
A Werkbaum plan is ordinary UTF-8 text, one node per line. Indentation carries
the hierarchy, and the leading character says how the children relate: `-` all
required, `+` an optional extra, `|` alternatives, `=` exactly one of them. A
checkbox such as `[x]` gives the status, `(M)` the T-shirt size. Nothing else
is needed to store, share or version a plan.
## Docs
- [Notation guide](https://werkbaum.javagil.de/llms.md): Everything needed to
read and write the notation, in English: line format and extraction order,
gates, status codes and progress ranks, sizes, node ids, dependencies,
folding marks, descriptions, plus a complete example. Self-contained; start
here.
- [Specification](https://github.com/mhoennig/werkbaum/blob/main/docs/SPEC.md):
The normative language definition (German). Where it and the guide disagree,
it wins.
- [Editor](https://werkbaum.javagil.de/): Renders a plan as a diagram.
`?sourceUrl=<url>` loads any CORS-readable http(s) text file, and
`?etherpad=<pad-url>` follows a live Etherpad.
## Optional
- [Design decisions](https://github.com/mhoennig/werkbaum/blob/main/docs/DECISIONS.md):
Why the notation looks the way it does, at length (German). Background only,
not needed to read or write plans.
- [Repository](https://github.com/mhoennig/werkbaum): Source and example plans
under `docs/examples/*.werkbaum`.
+7
View File
@@ -134,6 +134,13 @@ 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.md "$STAGE/llms.md"
# Der Wegweiser der llms.txt-Konvention (D43-Nachtrag 2): kurzer Index, der auf
# llms.md, SPEC und Repo zeigt. Nur er liegt an der Adresse, die Agenten von
# selbst probieren.
cp frontend/dist/llms.txt "$STAGE/llms.txt"
# Ohne diese Zuordnung liefert Apache `.md` ohne Content-Type aus und der
# Browser rät windows-1252 (D43-Nachtrag 2). Pages braucht sie nicht.
cp scripts/prod.htaccess "$STAGE/.htaccess"
# ---- 3) Spiegeln (--delete: nichts Altes bleibt am Ziel) ----
# --chmod=D755,F644 erzwingt web-taugliche Rechte am Ziel, unabhängig von den
+23
View File
@@ -0,0 +1,23 @@
# Werkbaum — Apache-Konfiguration der produktiven Instanz (D43-Nachtrag 2).
# Wird von scripts/deploy-prod.sh als `.htaccess` in die Site-Wurzel gespiegelt.
# GitHub Pages ignoriert `.htaccess` (kein Apache) und braucht es auch nicht —
# dort ist die Zuordnung schon richtig; die Datei liegt deshalb NICHT in
# frontend/public/, sonst landete sie im Pages-Artefakt.
#
# Warum es sie gibt: Apache kennt die Endung `.md` nicht und sendet dann GAR
# KEINEN Content-Type. Der Browser rät daraufhin windows-1252 und macht aus
# jedem `—` ein `â€"` — gemessen am 24.08.2026 auf werkbaum.javagil.de, 31
# betroffene Zeilen in llms.md. Dieselbe Datei kommt von GitHub Pages als
# `text/markdown; charset=utf-8` korrekt an.
#
# `.werkbaum` bekommt `text/plain` aus dem in SPEC §12/D24 genannten Grund:
# dann zeigt der Browser die Datei an, statt sie herunterzuladen.
#
# Sollte der Server nach einem Deploy 500 antworten, verbietet seine
# `AllowOverride`-Einstellung `AddType` (Klasse FileInfo) — dann gehören die
# drei Zeilen in die vhost-Konfiguration und diese Datei entfällt.
<IfModule mod_mime.c>
AddType text/markdown;charset=utf-8 .md
AddType text/plain;charset=utf-8 .txt
AddType text/plain;charset=utf-8 .werkbaum
</IfModule>