feat: Story 2.4 Code-Review-Patches (Rev 2.2) — Formel-3 quellenbasiert, Formel-4 Re-Baseline, §5.7 Pkt. 1(a) Prädikat + Tie-Break
bmad-code-review Loop 2 (4 Layer): 3 decision-needed (Nutzer-Optionen 1/1/1),
14 patch umgesetzt, 4 defer (deferred-work.md), 8 dismissed.
- schema/compiler.md Rev 2.2: Formel 3 quellenbasierte ../schema/*-Exklusion
(Decision 2), Formel 4 Re-Baseline auf Run-Kopf 862cf41 (Decision 1, 38 ≡ 38),
§5.7 Pkt. 1(a) textuelles Treffer-Prädikat + deterministisches Tie-Break
(Decision 3), file-relative Pin-Wortwahl, §7-Scope, Typos
- wiki/log.md: Review-Loop-2-Eintrag mit Negativ-Test-Nachweis (Sandbox-Ausgaben),
Status-Handoff (review → done), Validator-Lauf-Korrektur (7 Dateien)
- wiki/wissensarchitektur/index.md: Prosa auf Ist-Area-Inhalt gekürzt
- spec: Verification auf Ist-Zustand (Formel-3-Spiegel, 7-Dateien, Run-Kopf),
Change-Log Loop 2, review_loop_iteration → 2
- sprint-status.yaml: 2-4 → done, last_updated 08-18-2026 10:41
- deferred-work.md: 3 Story-2.4-Kandidat-Homes vorverlegt, 2 Defer umgesetzt
- Positiv-Kontrolle re-executiert: Formel 2 = 0 (Exit 0), Formel 3 leere Ausgabe,
Formel 4 = 38 ≡ 38
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+12
-11
@@ -59,7 +59,7 @@ Je neuem Concept werden die Frontmatter-Metadaten nach Vertrag §3 festgelegt:
|
||||
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 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).
|
||||
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, 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).
|
||||
|
||||
@@ -151,19 +151,19 @@ Beziehungen zwischen Concepts werden mit normalen Markdown-Links ausgedrückt
|
||||
**(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 -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'
|
||||
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 "#"*) continue;; esac; case "$t" in "../schema/"*) if [ "$(dirname "$src")" = "wiki" ]; then continue; fi;; 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'
|
||||
```
|
||||
|
||||
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`.)
|
||||
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 — quellenbasiert (Loop-2-Fix)**: die Exklusion gilt nur, wenn die Quell-Datei auf der Bundleroot-Ebene liegt (`dirname <quelle>` = `wiki`, z. B. `wiki/index.md`) — dort löst einstufiges `../schema/…` garantiert außerhalb des Bundles auf (`schema/…`), bestehende Root-Links bleiben damit byte-identisch und pin-frei (§5.7 Pkt. 4). Aus einer Area-Datei löst einstufiges `../schema/…` dagegen auf `wiki/schema/…` (**in-Bundle** — die Exklusion greift dann nicht), und das Ziel läuft durch die normale Auflösung + Containment + Existenztest: nicht existent → `DANGLING: …`. Aus Areas ausbrechende `../../schema/*` fällt ebenfalls 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; **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):
|
||||
**(4) Kontakt-mit-`raw/`-Unverändert-Check** (erwartet: Ist ≡ Baseline — der Pin berührt `raw/`-Provenienz-Verweise nicht; die Baseline wird deterministisch aus dem **Baseline-Commit des letzten Zuwachs-Runs** 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-Re-Baseline (Loop-2-Fix):** Dieser Run ist ein expliziter Datei-Zuwachs-Run (neue Area-Dateien) — die Baseline-Extraktion läuft auf den **Kopf dieses Zuwachs-Runs** (`862cf410c624072833cd959da9a2fb26235716f6`), nicht auf den Story-2.3-`7e1f449…` und nicht auf den `baseline_commit`-Wert der Story-2.4-Spec-Frontmatter (`66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a` = Zustand **vor** dem Zuwachs, extrahiert `30`); 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 66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a -- wiki/ | grep -v "log.md$" | while read -r f; do git show "66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a:$f"; done | grep -oE "\(raw/" | wc -l'
|
||||
sh -c 'git ls-tree -r --name-only 862cf410c624072833cd959da9a2fb26235716f6 -- wiki/ | grep -v "log.md$" | while read -r f; do git show "862cf410c624072833cd959da9a2fb26235716f6:$f"; done | grep -oE "\(raw/" | wc -l'
|
||||
```
|
||||
|
||||
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.
|
||||
Beide Vorkommen-Zählungen **müssen** übereinstimmen — die Ist-Zählung erfolgt auf dem aktuellen Baum, die Extraktion aus dem **Baseline-Commit des letzten Zuwachs-Runs** (aktuell: Run-Kopf `862cf41`, dieser Run: **38 ≡ 38**, `log.md`-exkludiert). Die Zahlen sind ein Formatbeleg, kein fester Wert: Auf dem Baum von Story 2.3 lag die Baseline bei `30` (extrahiert aus `7e1f449…`/`66451b6…` — beide tragen den Vor-Zuwachs-Zustand); der Zuwachs (neues Area-Concept `wiki/wissensarchitektur/source-material.md`) erhöht die Ist-Zählung auf `38`. Der Check verlangt die **aktuelle Baseline aus dem Run-Kopf `862cf41`** — ein Producer, der aus dem Vor-Zuwachs-Zustand (`7e1f449…` oder `66451b6…`) 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 Run-Kopf durchzuführen (die Zählung wächst um die `(raw/`-Vorkommen der neu angelegten Dateien).
|
||||
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.
|
||||
|
||||
@@ -171,7 +171,7 @@ Beziehungen zwischen Concepts werden mit normalen Markdown-Links ausgedrückt
|
||||
|
||||
**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).
|
||||
**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-Ebenen-Quellen bleibt als andere Schicht exkludiert (§5.7 Pkt. 4). **In-Bundle-Variante (Loop-2-Fix):** `[x](../schema/compiler.md)` aus `wiki/wissensarchitektur/source-material.md` — Auflösung `wiki/schema/compiler.md` (unter `wiki/`, Datei existiert nicht) → **`DANGLING: ../schema/compiler.md`**; die quellenbasierte `../schema/*`-Exklusion greift nur für Bundleroot-Ebenen-Quellen, nicht für Area-Quellen — kein stiller Vorbeilass (NFR-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).
|
||||
|
||||
@@ -180,7 +180,7 @@ Beziehungen zwischen Concepts werden mit normalen Markdown-Links ausgedrückt
|
||||
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`.
|
||||
- **(a) First-Class-Link aus dem bestehenden `index.md`-Baum:** Textuelles Treffer-Prädikat (Loop-2-Fix, kein „inhaltlich deckungsgleich"-Urteil — AD-13): Ein bestehender `index.md`-Link (Bundleroot oder Area-`index.md`) ist ein **Treffer**, wenn die **Identität seines Link-Ziels** (relativer OKF-Pfad ohne `.md`, Pkt. 2) **gleich dem kanonischen Namen des neuen Themas** (Pkt. 2) ist. Liegt genau ein Treffer vor, wird das neue Concept **in den Bereich dieses Links** angelegt (`wiki/<area>/<concept>.md`); der Bereich existiert damit bereits als `wiki/<area>/index.md`. **Mehrfachtreffer — deterministisches Tie-Break (Loop-2-Fix):** Bundleroot-Links schlagen Area-Links (ein Bundleroot-Treffer verweist auf ein Root-Concept → neues Concept auf Root-Ebene gemäß (b), da kein Area-Bereich zugeordnet ist); unter mehreren Area-Treffern gewinnt die **lexicografisch kleinste Area-Pfad-Zeichenfolge** (z. B. `wiki/a/…` vor `wiki/b/…`). Die Auswahl ist damit textual-deterministisch aus dem bestehenden `index.md`-Baum ableitbar (AD-7c, A0-10).
|
||||
- **(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):
|
||||
@@ -238,7 +238,7 @@ Die folgende Tabelle macht jede Erzeugungsregel dieser Instruktion reproduzierba
|
||||
| §4.5 kein `okf_version`/`type: bundle` (Punkt 9) | (nicht vorhanden) | `okf_version: "0.2"` → Punkt 9 |
|
||||
| §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) |
|
||||
| §5.6 Concept-Link-Form (FR-10, AD-7b, A0-9) | `[<text>](<concept-pfad>.md)` (file-relativ, `.md`-Endung; in Areas `../`-fähig, §5.7 Pkt. 4) | `[…](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 |
|
||||
| §7 Selbstbegrenzung (kein Standalone, D-3) | rein textuelle Instruktion | Code-/Executable-Abschnitt → D-3-Verstoß |
|
||||
|
||||
@@ -246,12 +246,12 @@ Interpretations-Hinweis: Die „✗"-Zeilen zeigen die deterministische Fehlerur
|
||||
|
||||
## 7. Selbstbegrenzung (Scope der Instruktion)
|
||||
|
||||
Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene** begrenzt. Folgendes verbleibt in anderen Stories und wird hier **nicht** vorweggenommen:
|
||||
Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene und in Areas gemäß §5.7** 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`) — 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).
|
||||
- **Eine genau-eine-Linkform** (file-relativ mit `.md`-Endung, in Areas `../`-fähig) — in **§5.6** dieser Instruktion gepinnt (Story 2.3; AD-7b, A0-9, FR-10; Auflösungsmodell §5.7 Pkt. 4) — 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).
|
||||
- **Standalone-Compiler / eigene LLM-Runtime / MCP** → verboten in v1 (D-3, D-4, AD-11).
|
||||
- **OKF-Dialekt / Schema-Erweiterung** → niemals (AD-1a; Vertrag §7 „abschließende Liste").
|
||||
@@ -281,3 +281,4 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene** begren
|
||||
- **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.
|
||||
- **Revision 2.2 (2026-08-18, Story 2.4, bmad-code-review Loop 2, 4 Layer; Nutzer-Entscheidungen 1/1/1):** (1) **Formel 3 (Dangling-Check) quellenbasierte `../schema/*`-Exklusion (Decision 2):** `case "$t" in …|../schema/*)` um Quell-Bedingung geschärft — die Exklusion greift nur, wenn die Quell-Datei auf Bundleroot-Ebene liegt (`dirname <quelle>` = `wiki`); aus Area-Quellen läuft einstufiges `../schema/…` durch die bestehende Auflösung + `wiki/*`-Containment + `-f`-Existenztest (nicht existent → `DANGLING: …`, kein stiller Vorbeilass, NFR-4); Negativ-Beispiel 2 um die In-Bundle-Variante `[x](../schema/compiler.md)` aus `wiki/wissensarchitektur/source-material.md` → `DANGLING: ../schema/compiler.md` ergänzt (Sandbox-Nachweis); (2) **Formel 4 (Kontakt-mit-`raw/`) Re-Baseline auf den Run-Kopf (Decision 1):** Extraktions-Commit von `66451b6…` auf `862cf410c624072833cd959da9a2fb26235716f6` (Kopf dieses Zuwachs-Runs, Extraktion = 38) umgestellt — der gepinnte Selbsttest lief auf dem Zuwachs-Baum deterministisch `38 ≠ 30` = Run-FAIL (bekannt-böser Zustand aus Loop-1-A2, nur halb geheilt); Erwartungstext jetzt „Ist ≡ Extraktion aus dem Baseline-Commit des letzten Zuwachs-Runs" (aktuell: Run-Kopf `862cf41`, **38 ≡ 38**); `66451b6`/`30` bleibt als Referenz des Vor-Zuwachs-Zustands dokumentiert; Wieder-Baseline-Klausel für künftige Zuwachs-Runs; (3) **§5.7 Pkt. 1(a) textuelles Treffer-Prädikat + deterministisches Tie-Break (Decision 3):** „inhaltlich deckungsgleichen Eintrag" (Urteil, AD-13-Verstoß) ersetzt — Treffer = Identität des `index.md`-Link-Ziels ≡ kanonischer Name des neuen Themas (Pkt. 2); Mehrfachtreffer → Bundleroot-Links vor Area-Links (Bundleroot-Treffer = Root-Concept-Verweis → Default Root-Ebene gemäß (b)), dann lexicografisch kleinste Area-Pfad-Zeichenfolge; (4) file-relative Pin-Wortwahl nachgeführt — §5.3 Pkt. 3 (Oxymoron „file-relativ bundle-relativ" aufgelöst: „file-relativ, mit `.md`-Endung; §5.7 Pkt. 4"), §6.6-Zelle (bzw. das doppelte Leerzeichen) und §7-Bullet; (5) §7-Scope-Einleitung „auf die Erzeugung neuer Concepts auf Root-Ebene begrenzt" → „Root-Ebene und in Areas gemäß §5.7"; (6) Typos („akte-Baseline" → „aktuelle Baseline", „Kopf dieser Spezifikation" → „Baseline-Commit des letzten Zuwachs-Runs"). Positiv-Kontrolle nach Patch (re-executiert): Formel 2 (Form-Check) `0` (Exit `0`), Formel 3 (Dangling-Check) leere Ausgabe, Formel 4 **38 ≡ 38**. Keine Änderung an `wiki-compiler.md`/`validator.md`/`raw/` (AD-3); keine neue §7-Klasse; kein Standalone (D-3); keine Vertragsänderung.
|
||||
|
||||
Reference in New Issue
Block a user