feat: Story 2.4 deterministische Bereichszuordnung abgeschlossen (Rev 2.1)

§5.7 Routing-Regel (textual-deterministisch, AD-7c/A0-10), kanonische
ID-Normalisierung (AD-7a/A0-8), Kollisions-Hold auf §3.2, file-relatives
Link-Auflösungsmodell mit Out-of-Bundle-..-Containment, Area-Hierarchie
(Area-index.md, Punkt 11 wörtlich). Neue Demo-Area wissensarchitektur/
mit frontmatterloser index.md + source-material.md. Loop-1-Review-Fixes:
Containment in Formel 3 (Loop-1-A1), Formel-4-Baseline auf baseline_commit
66451b6 statt 7e1f449 (Loop-1-A2), kein inventiertes AREA_WITHOUT_INDEX
(Loop-1-B1). Schema/validator/raw unverändert (AD-3); keine neue §7-Klasse.
This commit is contained in:
Michael Tamse
2026-08-18 08:15:33 +02:00
parent 66451b6e6c
commit 862cf410c6
8 changed files with 252 additions and 24 deletions
+49 -19
View File
@@ -56,10 +56,10 @@ Je neuem Concept werden die Frontmatter-Metadaten nach Vertrag §3 festgelegt:
## 5. Mutieren (Dateien schreiben)
1. **Ziel-Pfad:** Das neue Concept ist eine Markdown-Datei unter `wiki/`. In dieser Story (keine deterministische Area-Zuordnung; Story 2.4) werden neue Concepts **auf Root-Ebene** angelegt: `wiki/<concept-kebab-case>.md`. Es wird **kein** `wiki/<area>/`-Verzeichnis angelegt; ein als Area gedachtes Ziel (Unterverzeichnis) wird bis Story 2.4 **abgelehnt** und führt zu einem textuell identifizierbaren Hinweis („Area-Zuordnung ist Story 2.4").
1. **Ziel-Pfad:** Das neue Concept ist eine Markdown-Datei unter `wiki/`. Der Ziel-Pfad ergibt sich aus der **deterministischen Bereichszuordnung** (§5.7): (a) verweist bereits ein bestehender `index.md`-Link auf das erkannte Thema, wird das Concept in dessen Bereich angelegt (`wiki/<area>/<concept-kebab-case>.md`); (b) sonst Default Root-Ebene (`wiki/<concept-kebab-case>.md`). Nie Embedding/Vector (AD-7c, A0-10, AD-13). Die „Area-Zuordnung ist Story 2.4"-Backlog-Klausel ist mit §5.7 aufgelöst.
- Konvention für den Dateinamen: kebab-case-Slug aus der Concept-Identität (kein Sonderzeichen, keine Endung `.md`-Dopplung). Der Dateiname definiert die Concept-Identität (relativer OKF-Pfad ohne `.md`, AD-7a).
2. **Dateiinhalt:** YAML-Frontmatter gemäß §4 (kein weiteres Feld), gefolgt von einem Markdown-Body, der die Wissenseinheit eigenständig und lesbar darstellt (NFR-2, NFR-3). Der Body darf keine großen Quell-Exzerpte enthalten (FR-2). Claim-granulare Inline-Provenienz (AD-4a) folgt §5.5 — für neu erzeugte Concepts unmittelbar bei der Erzeugung, für bestehende Bodies per Nachrüstung (Story 2.2).
3. **Index-Regel (Punkt 11/§6):** Nach Anlage MUSS das neue (Root-)Concept in der Bundleroot `wiki/index.md` verlinkt werden — seine Identität (relativer OKF-Pfad ohne `.md`) als relativer Bundle-Pfad referenziert die genau-eine-Form-Festlegung ist in **§5.6** gepinnt (bundle-relativ mit `.md`-Endung). Ohne diese Verlinkung ist das Bundle strukturell invalide (§7 Punkt 11).
3. **Index-Regel (Punkt 11/§6):** Nach Anlage MUSS das neue Concept in der `index.md` **seines Bereichs** verlinkt werden — für Root-Concepts in der Bundleroot `wiki/index.md`, für Area-Concepts in der jeweiligen Area-`index.md` (`wiki/<area>/index.md`, §5.7) — seine Identität (relativer OKF-Pfad ohne `.md`) als relativer Bundle-Pfad referenziert; die genau-eine-Form-Festlegung ist in **§5.6** gepinnt (file-relativ bundle-relativ mit `.md`-Endung; §5.7 Pkt. 4). Ohne diese Verlinkung ist das Bundle strukturell invalide (§7 Punkt 11).
- All dies (Anlage + Verlinkung + `log.md`) erst abschließen, wenn die Validierung (§6) SUCCESS liefert. Zwischenstände werden nicht als fertige Mutation veröffentlicht — Commit-Boundary ist die Mutations-Boundary (AD-17f). Bei Validierungs-FAIL wird der Teilzustand **explizit zurückgerollt**: neue Concept-Datei(en) gelöscht, zugehörige Index-Verlinkung(en) aus `wiki/index.md` entfernt, `log.md`-Eintrag(e) wieder entfernt — das Bundle nimmt seinen Zustand vor dem Run wieder ein (keine partielle Mutation bleibt liegen).
4. **Dokumentation (`log.md`, Vertrag §5):** Die Anlage neuer Concepts wird als datumsgruppierter Eintrag in `wiki/log.md` dokumentiert (neueste zuerst; Header = ISO-Datum `YYYY-MM-DD`), verknüpft mit dem neuen Concept-Pfad und den genutzten `raw/`-Quellen. `log.md` bleibt ohne Frontmatter (Punkt 10).
@@ -124,12 +124,12 @@ Provenienz ist **claim-granular** (AD-4a, A0-3): Nicht nur das Concept als Ganze
Beziehungen zwischen Concepts werden mit normalen Markdown-Links ausgedrückt — **genau eine erlaubte Form** (FR-10, AD-8, AD-7b, A0-9). Der Pin verhindert, dass zwei Producer aus demselben Baum unterschiedliche IDs berechnen (AD-7b). Die Link-Schicht ist die Navigations-/Beziehungsschicht, **nicht** die Provenienz (AD-8): ein Body-Link ändert keine Aussagen, kein `sources` und kein Frontmatter.
1. **Pin (genau eine Form):** Ein Concept-Link — im Concept-Body wie in `wiki/index.md` — steht in der Form:
1. **Pin (genau eine Form):** Ein Concept-Link — im Concept-Body wie in `wiki/index.md` und Area-`index.md` — steht in der Form:
`"[<text>](<bundle-relativer Pfad mit .md-Endung>)"`
`"[<text>](<file-relativer Pfad mit .md-Endung>)"`
Ziel ist die Concept-OKF-Identität (relativer OKF-Pfad, AD-7a) + die `.md`-Endung (AD-7b, A0-9). Rationale: die 3 bestehenden Concept-Links in `wiki/index.md` stehen bereits in dieser Form (Null-Migration); Ziele sind explizite Dateien — auch mit Areas eindeutig (Story 2.4); Standard-Markdown-Tools lösen den Link ohne Konventionswissen auf (FR-10, AD-8).
2. **Geltungsbereich & Ausnahmen:** Der Pin gilt für Concept-Links in Concept-Bodies und in `wiki/index.md`. Explizit ausgenommen (andere Schicht bzw. außerhalb des Pins): `raw/`-Provenienz-Verweise in der Plain-/Komma-Form aus §5.5, `../schema/`-Links (außerhalb des Bundles), `http`-Links (externe Referenzen) und **Gleichseit-Anker** mit `#`-Beginn — der Form-Check und der Dangling-Check in Pkt. 3 exkludieren sie. Die Formeln in Pkt. 3 scannen den kompletten `wiki/`-Baum **mit Ausnahme von `log.md`** (Dokumentation, keine Link-/Provenienz-Schicht — sie zitiert die Formel-Texte selbst und würde die Zählungen verunreinigen); ein `](`-Link in `log.md` ist damit weder Pin-Objekt noch Formel-Trigger.
Ziel ist die Concept-OKF-Identität (relativer OKF-Pfad, AD-7a) + die `.md`-Endung (AD-7b, A0-9). Das Auflösungsmodell ist **file-relativ** zur `.md`-Datei (§5.7 Pkt. 4): Bei Root-Dateien sind file-relativ und bundle-relativ identisch (die bestehenden Concept-Links in `wiki/index.md` stehen bereits in dieser Form Null-Migration, byte-identisch); in Areas bezeichnen `../` die Aufwärts-Ziele innerhalb `wiki/` (z. B. `[LLM-Wiki-Prinzip](../llm-wiki-prinzip.md)` aus `wiki/<area>/<concept>.md`). Rationale: Ziele sind explizite Dateien — auch mit Areas eindeutig (Story 2.4); Standard-Markdown-Tools lösen den Link **ohne Konventionswissen** dateirelativ auf (FR-10, AD-8) — eine Form, beide Ebenen (Root + Area) (AD-7b).
2. **Geltungsbereich & Ausnahmen:** Der Pin gilt für Concept-Links in Concept-Bodies, in `wiki/index.md` und in Area-`index.md`. Explizit ausgenommen (andere Schicht bzw. außerhalb des Pins): `raw/`-Provenienz-Verweise in der Plain-/Komma-Form aus §5.5, `../schema/`-Links (außerhalb des Bundles — andere Schicht), `http`-Links (externe Referenzen) und **Gleichseit-Anker** mit `#`-Beginn — der Form-Check und der Dangling-Check in Pkt. 3 exkludieren sie. **Die `../`-Exklusion ist Story 2.4 aufgelöst:** `../`-Ziele sind seit der deterministischen Bereichszuordnung (§5.7) **in-Bundle-Aufwärts-Pfade** — sie werden validiert (Formel 2/3, Pkt. 3) und müssen nach `..`-Auflösung unter `wiki/` bleiben; `../schema/…` bleibt als andere Schicht exkludiert (Abgrenzung über das Zielverzeichnis unter `wiki/`, nicht über das bloße `../`-Präfix). Die Formeln in Pkt. 3 scannen den kompletten `wiki/`-Baum **mit Ausnahme von `log.md`** (Dokumentation, keine Link-/Provenienz-Schicht — sie zitiert die Formel-Texte selbst und würde die Zählungen verunreinigen); ein `](`-Link in `log.md` ist damit weder Pin-Objekt noch Formel-Trigger.
3. **Selbsttest-Formeln (re-executierbar, AD-17h):** Vor Abschluss eines Runs, der Links anlegt oder verändert, prüft der Producer die folgenden vier Formeln ab der Workspace-Root (rekursiv — künftige Area-Concepts unter `wiki/<area>/` werden erfasst, Story 2.4/2.5):
Alle Formeln exkludieren `log.md` (Scan-Scope, Pkt. 2) und erfassen leere Ziele `]()` (`[^)]*` statt `[^)]+`).
@@ -146,35 +146,63 @@ Beziehungen zwischen Concepts werden mit normalen Markdown-Links ausgedrückt
sh -c "grep -rohE ']\([^)]*\)' --include='*.md' --exclude=log.md wiki/ | sed -E 's/^\]\(//; s/\)$//' | sort -u | grep -vE '^(raw/|\.\./|#)' | grep -vE '^\.' | grep -vE ':' | grep -cvE '^[^#]+\.md$' || true"
```
Exkludiert: `raw/`-Provenienz (§5.5, andere Schicht), `../schema/`, `./`-Präfix-Ziele (`^\.` — nicht root-relativ/keine Bundle-Pfad-Form), externe Ziele (alle enthalten `:` — `http://`, `https://`, `mailto:`, protocol-less Hostnamen; interne OKF-Ziele sind Kebab-Case und enthalten nie `:`), Gleichseit-Anker `(#…)`. Cross-Page-Anker `file.md#sec` werden weiterhin gezählt (normative Frage, s. `deferred-work.md`).
Exkludiert: `raw/`-Provenienz (§5.5, andere Schicht), `../schema/`, `./`-Präfix-Ziele (`^\.` — nicht root-relativ/keine Bundle-Pfad-Form), externe Ziele (alle enthalten `:` — `http://`, `https://`, `mailto:`, protocol-less Hostnamen; interne OKF-Ziele sind Kebab-Case und enthalten nie `:`), Gleichseit-Anker `(#…)`. Cross-Page-Anker `file.md#sec` werden weiterhin gezählt (normative Frage, s. `deferred-work.md`). **Story-2.4-`../`-Schärfung:** `../`-Ziele werden weiterhin von der Exklusions-Stufe `grep -vE '^(raw/|\.\./|#)'` aus der Form-Zählung genommen — denn in-Bundle-Aufwärts-Ziele (`../<ziel>.md`, Auflösung bleibt unter `wiki/`, §5.7 Pkt. 4) sind formkonform; die **Containment-Prüfung** (Ziel-Auflösung muss unter `wiki/` bleiben, sonst `DANGLING`) ist Aufgabe des Dangling-Checks (Pkt. 3, Formel 3).
**(3) Dangling-Check** (erwartet: keine Ausgabe — jedes interne Ziel existiert relativ zum Bundle-Root, bundlerelativ als Auflösungsmodell des Bundles, AD-7b; ein nicht existierendes Ziel liefert `DANGLING: <pfad>`; leere Ziele liefern `DANGLING: (leeres Ziel)`):
**(3) Dangling-Check** (erwartet: keine Ausgabe — jedes interne Ziel existiert relativ zum **Quell-Verzeichnis** (file-relatives Auflösungsmodell, §5.7 Pkt. 4 / AD-7b); ein nicht existierendes Ziel liefert `DANGLING: <pfad>`; leere Ziele liefern `DANGLING: (leeres Ziel)`; **Out-of-Bundle-`..`-Traversal wird gesperrt**: ein Ziel, dessen `..`-Auflösung aus `wiki/` austritt (z. B. `../../README.md` oder `../../schema/compiler.md` aus einem Area-Concept), wird als `DANGLING: <pfad>` gemeldet — der reine `-f`-Existenztest würde sonst still passieren, weil die aufgelöste Datei außerhalb `wiki/` existiert):
```sh
sh -c 'grep -rohE "]\([^)]*\)" --include="*.md" --exclude=log.md wiki/ | sed -E "s/^\]\(//; s/\)$//" | sort -u | while read -r t; do case "$t" in ""|*:*|raw/*|../*|./*|/*) if [ "$t" = "" ]; then echo "DANGLING: (leeres Ziel)"; fi; continue;; esac; case "$t" in "#"*) continue;; esac; p=${t%%#*}; [ -f "wiki/$p" ] || echo "DANGLING: $t"; done'
sh -c 'grep -roE "]\([^)]*\)" --include="*.md" --exclude=log.md wiki/ | sed -E "s#^([^:]+):\]\(([^)]*)\)\$#\1|\2#" | sort -u | while IFS="|" read -r src t; do case "$t" in ""|*:*|raw/*|./*|/*) if [ "$t" = "" ]; then echo "DANGLING: (leeres Ziel)"; fi; continue;; esac; case "$t" in "#"*|../schema/*) continue;; esac; p=${t%%#*}; f="/$(dirname "$src")/$p"; while printf "%s" "$f" | grep -qE "/[^/]+/\.\.(/|$)"; do f=$(printf "%s" "$f" | sed -E "s#/[^/]+/\.\.(/|$)#/#g"); done; f=${f#/}; case "$f" in wiki/*) [ -f "$f" ] || echo "DANGLING: $t";; *) echo "DANGLING: $t";; esac; done'
```
Das Fragment wird vor dem Existenztest gestripped (`file.md#sec` → `file.md` — kein falscher `DANGLING` für existierende Ziele; die Pin-Form-Frage bleibt beim Form-Check). Exkludiert wie beim Form-Check. (Bekannt-konservativ: Ziele mit `)` werden am ersten `)` abgeschnitten → falsch benannte Ursache, aber keine Stille — dokumentiert in `deferred-work.md`.)
Die Formel führt die Quell-Datei der Link-Quelle mit (`grep -roE` → `datei:](ziel)` → `sed` → `datei|ziel`) und löst **jedes interne Ziel einheitlich relativ zum Quell-Verzeichnis** auf (file-relatives Auflösungsmodell, §5.7 Pkt. 4): `f="/$(dirname "$src")/$p"` — bei Root-Dateien ist das identisch zum bisherigen Bundleroot-Resolve (`wiki/…`), bei Area-Dateien adressiert dasselbe-Verzeichnis-Ziele korrekt (`source-material.md` aus `wiki/<area>/index.md` → `wiki/<area>/source-material.md`) und `../`-Ziele die Aufwärts-Pfade innerhalb `wiki/` (`../llm-wiki-prinzip.md` → `wiki/llm-wiki-prinzip.md`). Nach Kollabierung der `X/..`-Segmente (Fixed-Point-`while`-Schleife) wird der aufgelöste Pfad gegen `wiki/*` geprüft — bleibt er unter `wiki/` und existiert die Datei, keine Ausgabe; verlässt er `wiki/` (Out-of-Bundle-`..`-Escape, z. B. `../../README.md` → `README.md` unterhalb `wiki/`) oder existiert die Datei nicht, `DANGLING: <pfad>`. `../schema/*` bleibt als andere Schicht **exkludiert** (Zielverzeichnis `schema/` außerhalb des Bundles — bestehende Root-`index.md`-Links `../schema/…` bleiben damit byte-identisch und pin-frei, §5.7 Pkt. 4; aus Areas ausbrechende `../../schema/*` fällt nicht unter die Exklusion und wird als `DANGLING` gesperrt, Loop-1-Fix). Das Fragment wird vor dem Existenztest gestripped (`file.md#sec` → `file.md` — kein falscher `DANGLING` für existierende Ziele; die Pin-Form-Frage bleibt beim Form-Check). Exkludiert wie beim Form-Check (Ausnahme `../schema/`). (Bekannt-konservativ: Ziele mit `)` werden am ersten `)` abgeschnitten → falsch benannte Ursache, aber keine Stille — dokumentiert in `deferred-work.md`.)
**(4) Kontakt-mit-`raw/`-Unverändert-Check** (erwartet: aktuell ≡ Baseline — der Pin berührt `raw/`-Provenienz-Verweise nicht; die Baseline wird deterministisch aus dem `baseline_commit` der Story-Spezifikation dynamisch extrahiert, AD-17h — keine „identisch"-Behauptung ohne extrahierbare Baseline; **einschließende** Einzelanführungszeichen um das `sh -c`-Argument, damit `$f` erst in der inneren Shell expandiert):
**(4) Kontakt-mit-`raw/`-Unverändert-Check** (erwartet: aktuell ≡ Baseline — der Pin berührt `raw/`-Provenienz-Verweise nicht; die Baseline wird deterministisch aus dem `baseline_commit` der Story-Spezifikation dynamisch extrahiert, AD-17h — keine „identisch"-Behauptung ohne extrahierbare Baseline; **einschließende** Einzelanführungszeichen um das `sh -c`-Argument, damit `$f` erst in der inneren Shell expandiert; **Story-2.4-Neu-Baseline:** Dieser Run ist ein expliziter Datei-Zuwachs-Run (neue Area-Dateien) — die Baseline-Extraktion läuft daher auf den **Kopf dieser Spezifikation** (`66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a`, `baseline_commit`), nicht auf den Story-2.3-`7e1f449…`; der Filter ist `grep -v "log.md$"` (Basename, damit ein künftiges Area-`log.md` konsistent mit dem `--exclude=log.md` der Ist-Zählung exkludiert wird):
```sh
sh -c "grep -roE '\(raw/' --include='*.md' --exclude=log.md wiki/ | wc -l"
sh -c 'git ls-tree -r --name-only 7e1f449bf78741bb6739d8f510f3ab5543617fef -- wiki/ | grep -v "wiki/log.md$" | while read -r f; do git show "7e1f449bf78741bb6739d8f510f3ab5543617fef:$f"; done | grep -oE "\(raw/" | wc -l'
sh -c 'git ls-tree -r --name-only 66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a -- wiki/ | grep -v "log.md$" | while read -r f; do git show "66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a:$f"; done | grep -oE "\(raw/" | wc -l'
```
Beide Vorkommen-Zählungen müssen identisch sein (dieser Run: **30**, `log.md`-exkludiert). Der Check setzt die unveränderte `wiki/`-Dateimenge voraus (gilt für diesen Run; bei Datei-Zuwachs in späteren Runs ist die Baseline-Extraktion neu durchzuführen).
Beide Vorkommen-Zählungen **müssen** übereinstimmen — die Ist-Zählung erfolgt auf dem neuen Baum (nach diesem Zuwachs), die Extraktion aus dem `baseline_commit` **dieser Spezifikation** (`66451b6`). Die Zahlen sind ein Formatbeleg, kein fester Wert: Auf dem Baum von Story 2.3 extrahierte die Baseline `30` aus dem alten Baum; der Zuwachs (neues Area-Concept `wiki/wissensarchitektur/source-material.md`) erhöht die Ist-Zählung auf den re-executierbaren neuen Stand (dieser Run: **38**, `log.md`-exkludiert, mit den korrigierten Formel-3/4-Formeltexten konsistent). Der Check verlangt die **akte-Baseline aus `66451b6`** — ein Producer, der aus dem veralteten `7e1f449…` extrahiert, würde `30` erhalten und die Formel bräche auf dem neuen Baum (`38 ≠ 30`). Bei jedem weiteren Datei-Zuwachs ist die Baseline-Extraktion erneut auf den dann aktuellen `baseline_commit` durchzuführen.
4. **NFR-4-Regel:** Jede Form-Verletzung (Pkt. 3, Formel (2) > `0`), jeder Dangling-Link (Pkt. 3, Formel (3), Ausgabe `DANGLING: …`) und jedes leere Ziel (Formel (3), Ausgabe `DANGLING: (leeres Ziel)`) ist ein **Run-FAIL mit textuell benannter Ursache** — der verletzende Ziel-Pfad bzw. die Meldung ist exakt die Formel-Ausgabe. Der Link wird korrigiert oder entfernt, bevor der Run abschließt — kein stiller Vorbeilass.
5. **Worked Example:** Der Body-Link `[LLM-Wiki-Prinzip](llm-wiki-prinzip.md)` (in `wiki/wissensarchitektur-trennung-states.md`) ist in der gepinnten Form. Form-Check-Auflösung: Ziel `llm-wiki-prinzip.md` trifft `^[^#]+\.md$` → zählt als `0`; keine Ausnahme-Klasse greift. Dangling-Check-Auflösung: `wiki/llm-wiki-prinzip.md` existiert → keine Ausgabe. Der gleiche Link in `wiki/index.md` (Bestands-Check, Pkt. 3, Formel (1)) löst identisch auf.
**Negativ-Beispiel:** `[Test](ohne-endung)` — Ziel ohne `.md`-Endung. Form-Check (Pkt. 3, Formel (2)) liefert `1` (Ziel `ohne-endung` zählt als Übertretung), Dangling-Check (Pkt. 3, Formel (3)) liefert `DANGLING: ohne-endung` — deterministische Fehlerursache, Run-FAIL gemäß Pkt. 4 (der Link wird korrigiert zu `[Test](ohne-endung.md)` oder entfernt).
**Area-`../`-Beispiel (Story 2.4):** Der Body-Link `[LLM-Wiki-Prinzip](../llm-wiki-prinzip.md)` in `wiki/wissensarchitektur/source-material.md` ist in der gepinnten file-relativen Form. Form-Check: Ziel `../llm-wiki-prinzip.md` fällt unter die `../`-Exklusions-Stufe → zählt als `0` (keine Form-Verletzung). Dangling-Check (einheitlich file-relativ, Quell-Verzeichnis `wiki/wissensarchitektur`): Auflösung `wiki/wissensarchitektur/../llm-wiki-prinzip.md` → kollabiert `wiki/llm-wiki-prinzip.md`, bleibt unter `wiki/`, existiert → **keine Ausgabe**. Gleiches Modell für dasselbe-Verzeichnis-Ziele von der Area-`index.md` aus: `[source-material.md](source-material.md)` in `wiki/wissensarchitektur/index.md` → `wiki/wissensarchitektur/source-material.md` existiert → keine Ausgabe. Die Formel-2/3-`../`-Schärfung macht genau diesen in-Bundle-Aufwärts-Pfad — und die einheitliche file-relative Auflösung alle Area-Ziele — zulässig.
**Negativ-Beispiel 1:** `[Test](ohne-endung)` — Ziel ohne `.md`-Endung. Form-Check (Pkt. 3, Formel (2)) liefert `1` (Ziel `ohne-endung` zählt als Übertretung), Dangling-Check (Pkt. 3, Formel (3)) liefert `DANGLING: ohne-endung` — deterministische Fehlerursache, Run-FAIL gemäß Pkt. 4 (der Link wird korrigiert zu `[Test](ohne-endung.md)` oder entfernt).
**Negativ-Beispiel 2 (Out-of-Bundle-`..`-Escape, Loop-1-Review-Fix):** Ein Body-Ziel `[x](../../README.md)` aus `wiki/wissensarchitektur/source-material.md` — der `-f`-Existenztest allein löst `wiki/wissensarchitektur/../../README.md` zur existierenden Workspace-`README.md` auf und würde **still passieren**. Formel 3 (Pkt. 3) sperrt: Auflösung kollabiert zu `README.md`, das nicht unter `wiki/` bleibt → **`DANGLING: ../../README.md`** — Run-FAIL gemäß Pkt. 4, keine Stille. Analog `[x](../../schema/compiler.md)` → `DANGLING: ../../schema/compiler.md` (der aufgelöste `schema/…`-Zielpfad liegt außerhalb des Bundles; die `../schema/*`-Exklusion gilt nur für das einstufige Root-`index.md`-Muster `../schema/*`, nicht für aus Areas ausbrechende `../../schema/*`). Nur das einstufige `../schema/*` aus Root-Dateien bleibt als andere Schicht exkludiert (§5.7 Pkt. 4).
Hinweis: Der Validator (strukturell unverändert, Story-2.2-Präzedenz) akzeptiert im Punkt-11-Check weiterhin beide Schreibweisen; der Pin liegt auf Instruktions-Ebene (Selbsttest-Formeln, Pkt. 3).
## 5.7 Deterministische Bereichszuordnung & Concept-Hierarchie (Story 2.4)
Bereichszuordnung und Concept-Hierarchie sind **textual-deterministisch** (AD-7c, A0-10, AD-13) — nie per Embedding/Vector-Infrastruktur (AD-13). Diese Sektion ist der **einzige Instruktions-Ort** der Bereichszuordnungs-Regel (D-3). Sie fügt **kein** Prädikat, keine neuen §7-Invaliditätsklassen und keinen Schema-/Validator-Change hinzu (Story-2.2/2.3-Präzedenz; Validator Punkt 11 akzeptiert Areas bereits strukturell: Area-`index.md`, verlinkt im nächsten Vorfahren). Eine als Area gedachte Anlage (`wiki/<area>/index.md` + Concept darunter) ist ab dieser Story **konform**, nicht mehr Bereichs-Hinweis (§5.1).
1. **Routing-Regel („wohin gehört ein Thema"):** Für jede erkannte neue Wissenseinheit wird der Ziel-Bereich deterministisch bestimmt:
- **(a) First-Class-Link aus dem bestehenden `index.md`-Baum:** Verweist bereits ein bestehender `index.md`-Link (Bundleroot oder Area-`index.md`) auf das erkannte Thema bzw. einen inhaltlich deckungsgleichen Eintrag, wird das neue Concept **in den Bereich dieses Links** angelegt (`wiki/<area>/<concept>.md`). Der Bereich existiert damit bereits als `wiki/<area>/index.md`.
- **(b) Default Root-Ebene:** Existiert kein solcher Link, wird das Concept auf Root-Ebene angelegt (`wiki/<concept-kebab-case>.md`, §5.1). Neue Areas werden **nur konsolidiert** erzeugt (mehrere neue Concepts desselben erkannten Themas im selben Run, die einen eigenständigen Bereich rechtfertigen) — nicht pro Einzel-Concept erfinden (AD-7c, A0-10; Rücksprache-Pflicht §0 Ask-First der Story-Spezifikation).
- **Kein Embedding/Vector, kein reines LLM-Urteil** als Entscheidungsbasis (AD-7c/AD-13, A0-10).
2. **Kanonische ID-Normalisierung (AD-7a, A0-8):** Identität = relativer OKF-Pfad ohne `.md` — **genau eine** Normalisierung, für alle Producer (auch per **Basename-Filter** für `log.md`-Exklusion, Formel 4):
| OKF-Pfad | Identität |
|---|---|
| `wiki/spring/index.md` | `spring` |
| `wiki/spring/testing.md` | `spring/testing` |
| `wiki/wissensarchitektur/index.md` | `wissensarchitektur` |
| `wiki/wissensarchitektur/source-material.md` | `wissensarchitektur/source-material` |
| `wiki/llm-wiki-prinzip.md` | `llm-wiki-prinzip` |
Eine als Area gedachte Anlage (`wiki/<area>/index.md` + Concept darunter) ist damit **konform**; der Bereichs-Hinweis aus §5.1 ist aufgelöst. Konzept-`id`s (s. `sources[].id`, §5.5 Pkt. 3) sind unabhängig davon je Concept eindeutig — Adressraum ist Concept-Pfad + `id`.
3. **Top-Level-Kollisions-Hold (A0-10, fixierter §3.2):** Kollidiert ein Erstellungskandidat mit einem bestehenden Top-Level-Pfad (deterministisch: Dateikollision über den relativen OKF-Pfad, §3.1/§3.2, AD-7a), löst der **fixierte §3.2-Kollisions-Hold** aus — **kein** neues Prädikat, **kein** stiller Overwrite, kein Index-Link, keine Datei: der Run bricht für diese Einheit textuell ab („Concept existiert bereits — Aktualisierung ist Epic 3") und setzt mit den übrigen Einheiten fort (§3.2; „teilweise erfolgreich"). **Kein MOVE/Neuzuordnung bestehender Concepts** — das ist Kuratierung mit AD-7d-Redirect-Pflicht (Epic-3-Nähe, nicht in den ACs dieser Story; Ask-First).
4. **File-relatives Link-Auflösungsmodell (löst das §5.6-Defer):** Concept-Links sind **file-relativ** zur `.md`-Datei (AD-8/FR-10/AD-7b — eine syntaktische Form, beide Ebenen): bei Root-Dateien ist file-relativ ≡ bundle-relativ (die bestehenden Bestands-Links bleiben byte-identisch, Null-Delta zu Story 2.3); in Areas bezeichnen `../`-Präfixe die Aufwärts-Ziele **innerhalb `wiki/`** (`[<text>](../<root-concept>.md)`). Auflösung & Containment (§5.6 Pkt. 3, Formel 3): `../`-Ziel relativ zum Quell-Verzeichnis auflösen, `X/..`-Segmente kollabieren, aufgelöster Pfad MUSS unter `wiki/` bleiben — sonst `DANGLING` (Out-of-Bundle-`..`-Escape gesperrt, Loop-1-Fix). `../schema/*` als andere Schicht (Ziel außerhalb des Bundles) bleibt exkludiert — Abgrenzung über das **Zielverzeichnis** (unter `wiki/` = in-Bundle), nicht über das bloße `../`-Präfix; einstufiges `../schema/*` aus Root-Dateien ist damit weiterhin pin-frei (bestehende Root-`index.md`-Links unverändert). `.md`-Endung bleibt Pflicht (§5.6 Pin).
5. **Area-`index.md` (Vertrag §2/§6, AD-9/FR-11):** Eine Area besitzt exakt eine `wiki/<area>/index.md`, **frontmatterlos** (Punkt 10), die ihre Area-Concepts in der gepinnten Form (§5.6) verlinkt (Identity = relativer OKF-Pfad ohne `.md`). Die Bundleroot-`index.md` verlinkt die Area-`index.md` (Navigation Root → Area, AD-9). **Area ohne `index.md` ist strukturell invalide** und wird vom Validator wörtlich gemeldet: `FAIL … Punkt 11: Index-Regel verletzt (Area ohne index.md=<area>)` (kein inventiertes Label; Verdikt-Grammatik §5 des Validators). Ein neues Area-Concept MUSS in `wiki/<area>/index.md` verlinkt sein (§5.3 Pkt. 3 ist entsprechend §5.7-nachgeführt); sonst Punkt 11.
6. **Worked Example (Area-Concept):** `wiki/wissensarchitektur/source-material.md` — ein neues Area-Concept: `type: concept`, `sources` → `raw/architecture-spine/architecture-spine-2026-08-14.md` (s1) + `raw/prd/prd-wow20-2026-08-14.md` (s2), §5.5-Inline-Verweise je belegter Aussage, Body-Links auf Root-Concepts in der file-relativen `../`-Form (`[LLM-Wiki-Prinzip](../llm-wiki-prinzip.md)` u. ä.), inhaltsbegründet. Verlinkt in der Area-`index.md` `wiki/wissensarchitektur/index.md` (frontmatterlos, gepinnte Form); diese wiederum in der Bundleroot `wiki/index.md` (Area-Sektion). §5.6-Formel-1 (Bestands-Check) erfasst die Area-Links; Formel 2 (Form-Check) `0`; Formel 3 (Dangling-Check) keine Ausgabe (in-Bundle-`../`-Auflösung, §5.7 Pkt. 4).
## 6. Validieren (mechanische Bestätigung)
1. Nach Abschluss aller Mutationen wird das gesamte Bundle gemäß `schema/validator.md` geprüft (§3 14 Punkte je Datei + §6-Fachprüfungen; Verdikt-Grammatik §5).
2. **Erfolgsbedingung:** Alle Dateien unter `wiki/` — Bundleroot, `log.md`, sämtliche neuen Concepts — liefern `SUCCESS` (kein FAIL; `stale_after`-WARN wäre nur Berichtskanal). Dabei ist insbesondere Punkt 11 (Index-Regel) zu bestätigen: jeder neue Root-Concept-Pfad ist in `wiki/index.md` verlinkt.
2. **Erfolgsbedingung:** Alle Dateien unter `wiki/` — Bundleroot, Area-`index.md`, `log.md`, sämtliche neuen Concepts — liefern `SUCCESS` (kein FAIL; `stale_after`-WARN wäre nur Berichtskanal). Dabei ist insbesondere Punkt 11 (Index-Regel) zu bestätigen: jedes neue Concept ist in der `index.md` **seines Bereichs** verlinkt (Root-Concepts in `wiki/index.md`, Area-Concepts in `wiki/<area>/index.md`, §5.7 Pkt. 5).
3. Bei jedem FAIL gilt der Run als gescheitert; es werden **keine** weiteren Mutationen durchgeführt, `raw/` bleibt unangetastet (AD-3), und die Fehlerursache wird textuell benannt (NFR-4). Der bereits geschriebene Teilzustand (neue Concept-Dateien, Index-Verlinkungen, `log.md`-Einträge) wird gemäß §5.3 zurückgerollt, sodass das Bundle seinen Zustand vor dem Run wieder einnimmt.
4. Der Producer hält das Verdikt-Ergebnis (je Datei SUCCESS/FAIL) als Ausführungs-Nachweis fest (z. B. in der Story-Spezifikations-Verification oder im Run-Bericht).
@@ -208,7 +236,7 @@ Die folgende Tabelle macht jede Erzeugungsregel dieser Instruktion reproduzierba
| §4.5 keine Duplikat-Keys (Punkt 13) | jeder Key einmal | zweimal `type:` → Punkt 13 |
| §4.2 `sources`-Eintrag-Key-Subset (Vertrag §3.3) | nur `resource`, `id`, `title`, `author`, `usage_count`, `last_modified` | `resource …` + z. B. `role: x` → Punkt 6 (unautorisiertes Feld, Innen-Ebene) |
| §4.5 kein `okf_version`/`type: bundle` (Punkt 9) | (nicht vorhanden) | `okf_version: "0.2"` → Punkt 9 |
| §5.1 Root-Pfad & Verlinkung (Punkt 11, §6) | `wiki/<slug>.md` + Link in `wiki/index.md` | Concept ohne Link in `index.md` → Punkt 11; `wiki/<area>/<slug>.md` → Bereichs-Hinweis (Story 2.4) |
| §5.1/§5.7 Ziel-Pfad & Verlinkung (Punkt 11, §6; §5.7 Pkt. 1/5) | Root: `wiki/<slug>.md` + Link in `wiki/index.md`; Area: `wiki/<area>/<slug>.md` + Link in `wiki/<area>/index.md` (konform, §5.7) | Concept ohne Link in der `index.md` seines Bereichs → Punkt 11; Area ohne `index.md` → Punkt 11 („Area ohne index.md=<area>") |
| §5.4 `log.md`-Dokumentation (§5) | datumsgruppierter Eintrag mit Concept-Pfad + Quellen | fehlender Eintrag → kein Validator-FAIL, aber dokumentarische Pflicht verletzt |
| §5.6 Concept-Link-Form (FR-10, AD-7b, A0-9) | `[<text>](<concept-pfad>.md)` (bundlerelativ, `.md`-Endung) | `[](concept-pfad)` ohne `.md` → Form-Check (Pkt. 3, Formel 2) > 0, Run-FAIL (NFR-4) |
| §4.2 Alle-Pfad-Formen-Vermeidung (Punkt 4) | `/`-getrennt, relativ, unter `raw/` | `..`-Traversal, führendes `/`, Backslash (`raw\foo.md`), URL-Form (`https://…`) → Punkt 4 |
@@ -221,7 +249,7 @@ Interpretations-Hinweis: Die „✗"-Zeilen zeigen die deterministische Fehlerur
Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene** begrenzt. Folgendes verbleibt in anderen Stories und wird hier **nicht** vorweggenommen:
- **Claim-granulare Provenienz** je belegter Aussage (Inline-`raw/`-Verweise, Kontext-Marker) — in **§5.5** dieser Instruktion verankert (Story 2.2; AD-4a, A0-3). Keine neue §7-Klasse, kein Standalone, keine Vertragsänderung.
- **Deterministische Area-Zuordnung & Concept-Hierarchie** (Anlage von `wiki/<area>/index.md` + `wiki/<area>/<concept>.md`) Story 2.4 (AD-7c, A0-10).
- **Deterministische Area-Zuordnung & Concept-Hierarchie** (Anlage von `wiki/<area>/index.md` + `wiki/<area>/<concept>.md`) — in **§5.7** dieser Instruktion verankert (Story 2.4; AD-7c, A0-10, A0-8, AD-13). Keine neue §7-Klasse, kein Validator-Change.
- **Progressive Discovery über `index.md`** (Navigation, Area-Indizes, Suche) → Story 2.5 (AD-9, FR-11).
- **Eine genau-eine-Linkform** (bundle-relativ mit `.md`-Endung) — in **§5.6** dieser Instruktion gepinnt (Story 2.3; AD-7b, A0-9, FR-10) — der Punkt-11-Check des Validators akzeptiert bis auf Weiteres beide Schreibweisen (strukturell unverändert, Story-2.2-Präzedenz).
- **Aktualisierung bestehender Concepts** (Erweitern/Präzisieren/Korrigieren) und **Synthese über mehrere Concepts** → Epic 3 (AD-5, FR-6/FR-7).
@@ -234,9 +262,10 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene** begren
- `schema/wiki-compiler.md` — autorisierter Vertrag (Story 1.3): §2 Bundleroot, §3.1–§3.7 Feldsubset & Formate, §5 `log.md`-Typ, §6 Index-Regel/Prädikate, §7 abschließende 14-Punkte-Liste, §8 Normreferenzen.
- `schema/validator.md` — Prüfgrundlage (Story 1.4, Revision 8): §3 14 Punkte, §4 Normalform (Reihenfolge §4.1, ISO-8601 §4.3), §5 Verdikt, §6 Fachprüfungen (EC-1 Existenz, EC-3 Kalender, EC-11 non-md).
- Architektur-Spine (raw/`architecture-spine`): AD-2/AD-3 (raw immutable), AD-4a (claim-granulare Provenienz, §5.5), AD-5 (inkrementelle Kompilation), AD-6 (Reason/Mutate-Trennung), AD-7a (Identität = OKF-Pfad ohne `.md`), AD-7b (genau eine Linkform gepinnt, §5.6), AD-8 (Standard-Markdown-Links = Navigations-/Beziehungsschicht, §5.6), AD-9 (Progressive Discovery), AD-10 (agent-unabhängige Regeln), AD-11 (keine eigene Runtime), AD-13 (Retrieval gehört zu Consumers), AD-14 (Git liefert Historie, nicht Domain-State), AD-15 (Trust-Metadaten v1), AD-16 (Konflikte werden explizit bewahrt), AD-17a (nur veröffentlichte/committete Inhalte als Input), AD-17f (Commit-Boundary = Mutations-Boundary), AD-17h (Determinismus), D-3 (kein Standalone).
- Architektur-Spine (raw/`architecture-spine`): AD-2/AD-3 (raw immutable), AD-4a (claim-granulare Provenienz, §5.5), AD-5 (inkrementelle Kompilation), AD-6 (Reason/Mutate-Trennung), AD-7a (Identität = OKF-Pfad ohne `.md`, §5.7), AD-7b (genau eine Linkform gepinnt, §5.6), AD-7c (deterministische Bereichszuordnung, §5.7), AD-7d (Renaming/Redirect-Pflicht — nicht in den ACs, Epic 3), AD-8 (Standard-Markdown-Links = Navigations-/Beziehungsschicht, §5.6), AD-9 (Progressive Discovery, §5.7), AD-10 (agent-unabhängige Regeln), AD-11 (keine eigene Runtime), AD-13 (Retrieval gehört zu Consumers / keine Embedding-Bereichszuordnung, §5.7), AD-14 (Git liefert Historie, nicht Domain-State), AD-15 (Trust-Metadaten v1), AD-16 (Konflikte werden explizit bewahrt), AD-17a (nur veröffentlichte/committete Inhalte als Input), AD-17f (Commit-Boundary = Mutations-Boundary), AD-17h (Determinismus), D-3 (kein Standalone).
- PRD (raw/prd): FR-2 (Sources vs. Curated), FR-5 (Concept-Erzeugung), FR-9 (OKF-Konformität), FR-10 (Concepts miteinander verlinken, §5.6), FR-16 (Consumer-Unabhängigkeit), A-4 (nur lokale Sources).
- Epics (raw/epics): Story-2.1-Ziel und -Abgrenzung zu Story 2.22.5; A0-3 (Kontext-Marker-Wortlaut, §5.5), A0-9 (eine erlaubte Linkform, §5.6); FR-6/FR-12/FR-14, A0-6/A0-7/A0-11/A0-18 (Belege der nachkonformierten Concept-Bodies).
- Epics (raw/epics): Story-2.1-Ziel und -Abgrenzung zu Story 2.22.5; A0-3 (Kontext-Marker-Wortlaut, §5.5), A0-8 (Concept-Identität/Normalisierung, §5.7), A0-9 (eine erlaubte Linkform, §5.6), A0-10 (deterministische Bereichszuordnung, §5.7), A0-13 (Lease-Root-Scope); FR-6/FR-12/FR-14, A0-6/A0-7/A0-11/A0-18 (Belege der nachkonformierten Concept-Bodies).
- PRD §4.3 (FR-11 — progressive Discovery, §5.7 Pkt. 5) und §8.2/§8.3 (Canonical State; Separation of Concerns).
**Revisionslog:**
@@ -251,3 +280,4 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene** begren
- **Revision 1.8 (2026-08-17, Story 2.3):** Neue Sektion „Concept-Links" als **§5.6** eingefügt (nach §5.5, vor §6): genau-eine-Form-**Pin** bundle-relativ mit `.md`-Endung (AD-7b, A0-9, FR-10; Rationale Null-Migration der 3 Concept-Links, explizite Datei-Ziele, Standard-Markdown-Tools/AD-8), Geltungsbereich (Concept-Bodies + `wiki/index.md`) mit expliziten Ausnahmen (`raw/`-Provenienz-Verweise §5.5, `../schema/`-Links, `http`-Links, Gleichseit-Anker `#…`), **vier** re-executierbare Selbsttest-Formeln (Bestands-, Form-, Dangling-Check + Kontakt-mit-`raw/`-Unverändert-Check mit deterministischer Baseline-Extraktion aus dem `baseline_commit` via `git show`, AD-17h; rekursiv lauffest für künftige Areas, Story 2.4/2.5), NFR-4-Regel (jede Form-Verletzung → Run-FAIL mit textuell benannter Ursache) und Worked Example. Die „bis Story 2.3"-Klauseln in §5.3 Pkt. 3 und §5.5 Pkt. 1 referenzieren jetzt §5.6; §7-Selbstbegrenzung-Bullet entsprechend umformuliert. Demonstrative Umsetzung: zwei inhaltsbegründete Cross-Links in `wiki/wissensarchitektur-trennung-states.md` (→ `llm-wiki-prinzip.md`, → `knowledge-kompilation-inkrementell.md`; keine erzwungene Gegenseitigkeit, AD-8). Keine Änderung an `wiki-compiler.md`/`validator.md`/`raw/` (der Punkt-11-Check akzeptiert bis auf Weiteres beide Schreibweisen — Einschränkung wäre eigene Autorisierung); keine neue §7-Invaliditätsklasse; kein Standalone (D-3); keine Vertragsänderung.
- **Revision 1.9 (2026-08-17, Story 2.3, Step-04-Review Loop 1, Patch-Runde):** §5.6-Formeln geschärft — (1) leere-Ziele-Erfassung (`[^)]*` statt `[^)]+` in Formel 1/2/3), (2) `log.md`-Exklusion in allen vier Formeln (`--exclude=log.md`) + Scan-Scope-Klarstellung in Pkt. 2 (Formeln scannen den `wiki/`-Baum mit Ausnahme von `log.md` — sie zitiert die Formel-Texte selbst), (3) externe-Ziel-Exklusion über `:` statt `http`-Präfix (Formel 2 `grep -vE ':'`; Formel 3 `case *:*`) — `http://`/`https://`/`mailto:`/protocol-less Hostnamen exkludiert, legale `http…`-Dateinamen nicht mehr fälschlich exkludiert, (4) Exit-Code-Bindung `|| true` am Ende des Form-Checks (grep `-c` liefert Exit `1` bei Ausgabe `0` — der gewünschten SUCCESS-Konfiguration), (5) Fragment-Strip im Dangling-Check vor dem Existenztest (`p=${t%%#*}` — `concepts.md#s1` bei existierender Datei liefert keinen falschen `DANGLING`; die Form-Frage bleibt beim Form-Check) und leere Ziele melden `DANGLING: (leeres Ziel)` statt still exkludiert; (6) raw/-Check (Formel 4) auf dynamische Baseline-Extraktion umgestellt (`git ls-tree -r --name-only <baseline_commit> -- wiki/` + `git show` je Datei, `wiki/log.md` gefiltert; einschließende Einzelanführungszeichen, damit `$f` erst in der inneren Shell expandiert) mit erwarteter Zählung **30** (`log.md`-exkludiert) und Voraussetzung „unveränderte `wiki/`-Dateimenge" (bei Datei-Zuwachs in späteren Runs Baseline-Extraktion neu durchführen). Pkt. 4 (NFR-4-Regel) um leere Ziele erweitert; Pkt. 5 (Worked Example) um Negativ-Beispiel (`[Test](ohne-endung)` → Form-Check `1` + `DANGLING: ohne-endung`) und Verweis-Korrektur („Pkt. 3.1" → „Pkt. 3, Formel (1)") ergänzt; §6.6 um §5.6-Referenzzeile (✓ gepinnte Form / ✗ fehlende `.md` → Form-Check > 0, Run-FAIL). Keine Änderung an `wiki-compiler.md`/`validator.md`/`raw/`; kein Standalone (D-3); keine neue §7-Klasse; keine Vertragsänderung.
- **Revision 2.0 (2026-08-17, Story 2.3, bmad-code-review, Review-Runde):** §5.6-Pin-Schärfung aus dem Code-Review (Blind-Hunter + Edge-Case-Hunter): (1) **Formel 2 (Form-Check)** um die Exklusions-Stufe `grep -vE '^\.'` erweitert — Ziele mit `./`-Präfix (und damit nicht-root-relative Pfade) werden definiert aus dem Pin ausgenommen, statt still als „interne `.md`-Form" durchzugehen; die erläuternde Exklusions-Aufzählung in Pkt. 2 entsprechend ergänzt (`./`-Präfix-Ziele: nicht root-relativ/keine Bundle-Pfad-Form); (2) **Formel 3 (Dangling-Check)** `case`-Muster um `./*` und `/*` erweitert — `./`-Präfix-Ziele und absolute Wurzel-Pfade werden konsistent exkludiert (Analog zu `../*`), statt `DANGLING: ./foo.md`-Fehlbenennung zu erzeugen. Beide Formeln bleiben deterministisch re-executierbar (AD-17h) und werden in der Spec-Verification byte-identisch gespiegelt (verifiziert: 5/5 Formel-Strings identisch compiler↔spec). Positiv-Kontrolle nach Patch: Form-Check `0` (Exit `0`), Dangling-Check leere Ausgabe, Bestands-Check `8` Links, `raw/`-Baseline `30 ≡ 30`. Keine Änderung an `wiki-compiler.md`/`validator.md`/`raw/`; kein Standalone (D-3); keine neue §7-Klasse; keine Vertragsänderung. (Die zugehörigen Defer-Findings — Image-Scope, Multi-Line-, Reference-Style- und Leading-Space-Ziele, künftiges Area-`log.md` — sind in `deferred-work.md` dokumentiert, Story-2.4-Kandidat.)
- **Revision 2.1 (2026-08-18, Story 2.4):** Neue Sektion **§5.7 „Deterministische Bereichszuordnung & Concept-Hierarchie"** eingefügt (nach §5.6, vor §6): (1) Routing-Regel textual-deterministisch (`index.md`-Erst-`Link` → Bereich, sonst Root; neue Areas nur konsolidiert; nie Embedding/Vector — AD-7c/A0-10/AD-13), (2) kanonische ID-Normalisierung mit Beispieltabelle `wiki/<area>/index.md` → `<area>` (AD-7a/A0-8), (3) Kollisions-Hold → Verweis auf den fixierten §3.2 (kein neues Prädikat, kein MOVE, A0-10), (4) **file-relatives Link-Auflösungsmodell** (`../`-fähig, eine Form, §5.6-Pin unverändert) inkl. Out-of-Bundle-`..`-Containment, (5) Area-`index.md`-Regel (frontmatterlos, Punkt 10; Area ohne `index.md` → wörtliche Punkt-11-Meldung `FAIL … Punkt 11: Index-Regel verletzt (Area ohne index.md=…)` — **kein** inventiertes `AREA_WITHOUT_INDEX`-Label; §5.7 Pkt. 5), (6) Worked Example Area-Concept. Nachgeführt: §5.1 Pkt. 1 (Ziel-Pfad → §5.7-Verweis, „Area-Zuordnung ist Story 2.4"-Backlog-Klausel aufgelöst), §5.3 Pkt. 3 (Index-Regel area-bewusst: Concept → `index.md` seines Bereichs), §5.6 Pkt. 1/2/3/4/5 (file-relatives Auflösungsmodell; `../`-Exklusion aufgelöst → in-Bundle-Auflösung; **Formel 2** Exklusions-Erläuterung um `../`-Zähl-Freistellung ergänzt; **Formel 3** um Quell-Datei-Spur (`grep -roE` + `datei|ziel`-sed) und **in-Bundle-`..`-Auflösung mit Containment** inkl. `../schema/*`-Exklusion erweitert — Out-of-Bundle-`..`-Escape (`../../README.md`, `../../schema/compiler.md`) wird als `DANGLING` gesperrt, Loop-1-Review-A1-Fix; **Formel 4** neu auf den `baseline_commit` dieser Spezifikation `66451b6…` basiert — nicht den Story-2.3-`7e1f449…`, Loop-1-Review-A2-Fix — mit Basename-Filter `grep -v "log.md$"`), §6.6 (Referenzzeile §5.1/§5.7), §6 Pkt. 2 (Erfolgsbedingung Punkt 11 area-bewusst), §7-Selbstbegrenzung-Bullet → „in §5.7 verankert", §8-Normreferenzen um AD-7c/AD-7d/A0-8/A0-10/A0-13/PRD-§8.2/§8.3 ergänzt. Keine Änderung an `wiki-compiler.md`/`validator.md`/`raw/`; keine neue §7-Klasse; kein Standalone (D-3); keine Vertragsänderung.