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>
185 lines
34 KiB
Markdown
185 lines
34 KiB
Markdown
---
|
|
title: 'Deterministische Bereichszuordnung & Concept-Hierarchie (Story 2.4)'
|
|
type: 'feature'
|
|
created: '2026-08-18'
|
|
status: 'done'
|
|
review_loop_iteration: 2
|
|
baseline_commit: 66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a
|
|
context:
|
|
- _bmad-output/implementation-artifacts/epic-2-context.md
|
|
---
|
|
|
|
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
|
|
|
|
## Intent
|
|
|
|
**Problem:** Die Ziel-Pfad-Regel (§5.1) erzwingt noch konzeptlos alle neuen Concepts auf Root-Ebene ("Area-Zuordnung ist Story 2.4") — es gibt keine deterministische Regel, wohin ein erkanntes Thema gehört (AD-7c/A0-10 sind offen); die §5.6-Linkformeln exkludieren `../`-Ziele pauschal und wären für Area-Pfade nicht renderer-konform (offenes Deferred, Home Story 2.4).
|
|
|
|
**Approach:** Neue §5.7 „Deterministische Bereichszuordnung & Concept-Hierarchie" in `schema/compiler.md`: Bereichszuordnung textual-deterministisch ((a) First-Class-Link aus dem bestehenden `index.md`-Baum, sonst (b) Root-Ebene; nie Embedding/Vector — AD-7c/AD-13), kanonische ID-Normalisierung (AD-7a), §3.2-Kollisions-Hold für Top-Level-Konflikte (A0-10, kein neues Prädikat), file-relatives Link-Auflösungsmodell (eine syntaktische Form, `../`-fähig; §5.6-Formeln area-fest). §5.1/§5.3/§7/§8/§6.6 nachgeführt. Demo: neue Area `wiki/wissensarchitektur/` (frontmatterloser Area-`index.md` + ein neues Area-Concept aus `raw/` mit `../`-Links auf Root-Concepts) + Negativ-Test der Kollision im Sandbox-Baum; kein MOVE bestehender Concepts (Kuratierung/AD-7d ist Epic-3-Nähe, nicht in den ACs).
|
|
|
|
## Boundaries & Constraints
|
|
|
|
**Always:**
|
|
- Bereichszuordnung ist **textual-deterministisch** ((a) bestehender `index.md`-Link gibt den Bereich vor; (b) Default Root-Ebene), nie Embedding/Vector (AD-7c, A0-10, AD-13). Die Regel wird als Instruktion in **§5.7** verankert — einziger Instruktions-Ort (D-3); keine Vertrags-/Validator-Änderung (§-Struktur wie Story 2.2/2.3-Präzedenz). Validator Punkt 11 akzeptiert bereits Areas (Area-`index.md`, verlinkt im nächsten Vorfahren) — strukturell unverändert.
|
|
- Identität = relativer OKF-Pfad ohne `.md` (AD-7a): `wiki/spring/index.md` → `spring`, `wiki/<area>/<concept>.md` → `<area>/<concept>`; genau eine Normalisierung. Eine als Area gedachte Anlage (`wiki/<area>/index.md` + Concept darunter) ist ab dieser Story **konform**, nicht mehr Bereichs-Hinweis.
|
|
- **Link-Auflösungsmodell (löst §5.6-Defer):** Concept-Links sind **file-relativ** zur `.md`-Datei — eine syntaktische Form (bundle-relativ = identisch bei Root-Dateien; `../` für Aufwärts-Ziele innerhalb `wiki/`; `.md`-Endung bleibt Pflicht). §5.6-Formeln 2/3 exkludieren `../` **nicht mehr pauschal**, sondern validieren `../`-Ziele als in-Bundle-Aufwärts-Pfade (Quell-Verzeichnis relativ, Ziel muss unter `wiki/` liegen). `../schema/` bleibt anderer Schicht (exkludiert). Dangling-Auflösung: Existenztest relativ zum Bundleroot nach `../`-Auflösung.
|
|
- Neue Area `wiki/wissensarchitektur/`: `index.md` **frontmatterlos** (Vertrag §2, Punkt 10), verlinkt die Area-Concepts in gepinnter Form (§5.6); neues Area-Concept `source-material.md` (`type: concept`, `sources` → `raw/architecture-spine/…`/`raw/prd/…`, §5.5-Inline-Verweise), Body-Links zu Root-Concepts im file-relativem `../`-Format (`[LLM-Wiki-Prinzip](../llm-wiki-prinzip.md)` u. ä.), inhaltsbegründet. Root-Concept `wissensarchitektur-trennung-states.md` bleibt unverändert auf Root.
|
|
- `wiki/index.md`: neue Area-Sektion verlinkt `wissensarchitektur/index.md` (Navigation Root → Area, AD-9); bestehende Root-Links unverändert. `wiki/log.md`: Eintrag (Vertrag-§5-Format) mit Area-Anlage, neuem Concept, `sprint-status`-Wechsel `2-4-…` `backlog` → `in-progress`.
|
|
- §5.6-Formel-4-Basislinie: Dieser Run ist ein expliziter „Datei-Zuwachs"-Run (neue Area-Dateien) — die „unveränderte Dateimenge"-Voraussetzung ist per §5.6-Text für diesen Run nicht erfüllt; die Baseline-Extraktion wird auf den neuen Baum (dieser Spezifikations-`baseline_commit`) neu durchgeführt und im log-Eintrag/Zählung dokumentiert. Kein Widerspruch zu §5.6-Text (dieser sieht den Zuwachs-Fall ausdrücklich vor).
|
|
- `deferred-work.md`: die Story-2.4-benannten Defer-Einträge (bundlerelative Area-Auflösung; ggf. Cross-Page-Anker) erhalten `status:`-Zeile geschlossen bzw. dokumentarisch korrigiert (append-only; bestehende Einträge unverändert). `sprint-status.yaml`: Key `2-4-…` → `in-progress`.
|
|
- Negativ-Test im Sandbox-/tmp-Baum: Erstellungskandidat mit Top-Level-ID-Kollision (z. B. `llm-wiki-prinzip`) löst den **§3.2-Hold** aus („Concept existiert bereits — Aktualisierung ist Epic 3"), kein stiller Overwrite, keine Index-Verlinkung.
|
|
|
|
**Ask First:** Andere Pin-Wahl als file-relativ (`../`-fähig) · MOVE/Neuzuordnung bestehender Concepts (AD-7d) · Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`raw/` · neue Areas über die eine Demo-Area hinaus · Standalone-Tool.
|
|
|
|
**Never:** Veränderung an `schema/wiki-compiler.md`/`schema/validator.md`/`raw/` (AD-3) · neuen §7-Invaliditätsklasse · Vorwegnahme progressiver Discovery-Indizes/Navigation (Story 2.5) · Renames/Redirects (AD-7d) · Embedding/Vector-Infrastruktur (AD-13) · OKF-Dialekt.
|
|
|
|
## I/O & Edge-Case Matrix
|
|
|
|
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|
|
|----------|--------------|---------------------------|----------------|
|
|
| HAPPY_PATH | Bundle + neue Area `wissensarchitektur/`, neues Area-Concept `source-material.md` | Area-`index.md` (frontmatterlos) verlinkt das Concept; Root-`index.md` verlinkt die Area; `../`-Body-Links lösen in Renderern und Dangling-Check auf; Validator SUCCESS (6 `wiki/`-Dateien) | N/A |
|
|
| TOP_LEVEL_COLLISION | Erstellungskandidat mit ID = bestehendem Root-Pfad (`llm-wiki-prinzip`) | §3.2-Kollisions-Hold: kein Overwrite, kein Index-Link, keine Datei; Run „teilweise erfolgreich"/textueller Hinweis | N/A (Hold-Verhalten fixiert, §3.2) |
|
|
| AREA_WITHOUT_INDEX | `wiki/<area>/` ohne `index.md` | validator Punkt 11 FAIL („Area ohne index.md=…") — Anlage ohne Area-Index ist strukturell invalide | Run-FAIL, textuelle Ursache (NFR-4) |
|
|
| DEEP_LINK_UP | Body-Link `../llm-wiki-prinzip.md` aus `wiki/wissensarchitektur/source-material.md` | Form-Check `0`; Dangling: Auflösung relativ zum Quell-Verzeichnis → `wiki/llm-wiki-prinzip.md` existiert → keine Ausgabe | `../schema/…` weiterhin exkludiert (andere Schicht) |
|
|
| DIVING_NON_EXISTENT | `../fehlt.md` aus Area-Concept | Dangling-Check meldet `DANGLING: ../fehlt.md` | Run-FAIL textuell benannt |
|
|
|
|
</frozen-after-approval>
|
|
|
|
## Code Map
|
|
|
|
- `schema/compiler.md` — **mutiert**: neue **§5.7** „Deterministische Bereichszuordnung & Concept-Hierarchie (Story 2.4)" (nach §5.6, vor §6): (1) Routing-Regel textual-deterministisch (index.md-Erst-`Link` → Bereich, sonst Root; AD-7c/A0-10/AD-13), (2) kanonische ID-Normalisierung (AD-7a, Beispieltabelle `wiki/<area>/index.md` → `<area>`), (3) Kollisions-Hold → Verweis auf fixierten §3.2 (kein neues Prädikat, A0-10), (4) Link-Auflösungsmodell file-relativ (`../`-fähig, eine Form) + Formel-2/3-`../`-Schärfung, (5) Worked Example Area-Concept; **§5.1 Pkt.1** umgeschrieben (Root-Formel → Verweis auf §5.7; „Area-Zuordnung ist Story 2.4"-Backlog-Klausel aufgelöst); **§5.3 Pkt.3** (Area-Concept → Link in Area-`index.md` statt Bundleroot); **§5.6 Pkt.2/3** (Geltungsbereich/Auflösung `../` präzisiert, Formel-2-Exklusions-Liste + Formel-3-`case` um `../`-in-Bundle-Auflösung ergänzt; **Containment nach dem Loop-1-Review: Formel 3 MUSS Out-of-Bundle-Ausbruch über `..`-Traversale sperren** — ein Ziel `../[^./]…` (bzw. nach Auflösung unter `wiki/`) ist zulässig als in-Bundle-Aufwärts-Pfad, ein Ziel, dessen `..`-Auflösung **nicht** unter `wiki/` bleibt, MUSS als `DANGLING` gemeldet werden); **§5.6 Pkt.4 (Formel-4-Neu-Baseline)** muss die Baseline **aus dem `baseline_commit`-Kopf dieser Spezifikation** (`66451b6e6c9e139fb3aa3bbf4b01291e1e2d273a`) extrahieren, nicht aus dem Story-2.3-`7e1f449…`; **§5.7 Pkt.5** meldet eine Area ohne `index.md` **wörtlich** als `FAIL … Punkt 11: Index-Regel verletzt (Area ohne index.md=…)` (kein inventiertes `AREA_WITHOUT_INDEX`-Label); **§6.6** `§5.1`-Zeile angepasst (`wiki/<area>/<slug>.md` konform; Bereichs-Hinweis-Zelle entfällt); **§7**-Bullet „Deterministische Area-Zuordnung" von „verbleibt Story 2.4" → „in §5.7 verankert"; **§8**-Revisionslog 2.1 + Normreferenzen AD-7c/A0-10.
|
|
- `wiki/wissensarchitektur/index.md` — **neu**: Area-`index.md`, frontmatterlos, verlinkt `source-material.md` (gepinnte Form).
|
|
- `wiki/wissensarchitektur/source-material.md` — **neu**: Area-Concept, `type: concept`, `sources` → `raw/architecture-spine/architecture-spine-2026-08-14.md` (+ ggf. `raw/prd/prd-wow20-2026-08-14.md`), §5.5-Inline-Verweise, `../`-Links auf Root-Concepts.
|
|
- `wiki/index.md` — **mutiert**: Area-Sektion verlinkt `wissensarchitektur/index.md`; bestehende Root-Links unverändert.
|
|
- `wiki/log.md` — **append**: Eintrag (Area-Anlage, neues Concept, §5.6-Formel-4-Neu-Baseline, `sprint-status`-Wechsel, Negativ-Test-Hold-Nachweis).
|
|
- `_bmad-output/implementation-artifacts/sprint-status.yaml` — **mutiert**: `2-4-deterministische-bereichszuordnung-concept-hierarchie` → `in-progress`.
|
|
- `_bmad-output/implementation-artifacts/deferred-work.md` — **mutiert**: Story-2.4-Defer (bundlerelative Area-Auflösung) `status: umgesetzt (…)`-Zeile; Cross-Page-Anker-Eintrag dokumentarisch auf Ist-Verhalten korrigiert (append-only, keine bestehende Zeile ändern außer Status-/Korrektur-Fall).
|
|
- `schema/wiki-compiler.md` (Punkt 11, §6), `schema/validator.md`, `raw/…` — **read-only** (AD-3).
|
|
|
|
## Tasks & Acceptance
|
|
|
|
**Execution:**
|
|
- [x] `schema/compiler.md` — §5.7 (Routing, ID-Normalisierung, Hold-Verweis, file-relativ-Auflösung + Formel-2/3-`../`-Schärfung, Worked Example); §5.1/§5.3/§5.6/§6.6/§7/§8 nachgeführt. Kein Schema-/Validator-/raw-Change.
|
|
- [x] `wiki/wissensarchitektur/index.md` + `wiki/wissensarchitektur/source-material.md` — anlegen; Area-Index frontmatterlos, Concept §5.5-konform, `../`-Links gepinnt/inhaltsbegründet.
|
|
- [x] `wiki/index.md` — Area-Sektion + Link auf `wissensarchitektur/index.md`.
|
|
- [x] `wiki/log.md` — Eintrag gemäß Verifikations-Vorgaben; `sprint-status.yaml` → in-progress; `deferred-work.md`-Einträge schließen/korrigieren.
|
|
- [x] Negative-/Edge-Tests im Sandbox-/tmp-Baum (TOP_LEVEL_COLLISION → §3.2-Hold; Area ohne `index.md` → Punkt 11 „Area ohne index.md=…"; `../`-Dangling; Out-of-Bundle-`..`-Escape → `DANGLING`).
|
|
|
|
**Acceptance Criteria:**
|
|
- Given ein erkanntes Thema, when der Bereich bestimmt wird, then geschieht dies textual-deterministisch (bestehender `index.md`-Link oder Root-Ebene; nie Embedding) (A0-10, AD-13).
|
|
- Given die Concept-Identität, when ein Concept abgelegt wird, then entspricht sie dem relativen OKF-Pfad ohne `.md` mit genau einer Normalisierung (`wiki/<area>/index.md` → `<area>`, AD-7a, A0-8).
|
|
- Given eine Bereichsnavigation, when ein Consumer sich orientiert, then führt die Hierarchie (Area-`index.md`) schrittweise zu den Concepts — die neue Area ist über die Root-`index.md` erreichbar (AD-9, FR-11).
|
|
- Given ein Konflikt mit existierendem Top-Level-Pfad, when erkannt, then löst der fixierte §3.2-Hold aus statt stillem Überschreiben (A0-10).
|
|
- Given die Instruktion, when geprüft, then ist §5.7 der einzige Instruktions-Ort (D-3), §5.6-Formeln area-fest re-executierbar (AD-17h) und der Validator läuft SUCCESS (keine neue §7-Klasse, kein Schema-/Validator-/raw-Change).
|
|
|
|
## Spec Change Log
|
|
|
|
- **2026-08-18 (Loop 2, bmad-code-review, 4 Layer; Abschluss):** Review-Loop 2 abgeschlossen — 3 `decision-needed` (Nutzer-Entscheidungen 1/1/1), 14 `patch` (alle umgesetzt), 4 `defer` (in `deferred-work.md` verankert), 8 dismissed. **Amendierung der nicht-gefrorenen Sektionen:** (a) Verification-Item 3 (Formel 4) von „Extraktion aus `baseline_commit` `66451b6…`" auf „Extraktion aus dem **Kopf des letzten Zuwachs-Runs** (`862cf41…`, 38 ≡ 38)" umgestellt (Decision 1 — der gepinnte Selbsttest hätte deterministisch `38 ≠ 30` = Run-FAIL geliefert); (b) Verification-Item 1 um den byte-identischen Formel-3-String (quellenbasierte `../schema/*`-Exklusion, Decision 2) ergänzt; (c) Verification-Item 4 auf 7 `wiki/`-Dateien + korrekten Punkt-Satz (die „6" der gefrorenen I/O-Matrix bleibt frozen — Defer). **Frozen-Sektionen unverändert** (I/O-Matrix „6 `wiki/`-Dateien"/„stillem Overwrite" = Änderungskandidat der nächsten Renegotiations-Runde). **Status:** `sprint-status.yaml` `2-4-…` `review` → `done` (spec-2-3-Präzedenz: `done` nach Review-Freigabe; Frontmatter `status: 'done'` damit deckungsgleich), `review_loop_iteration` → 2. **Kein Schema-/Validator-/raw-Change (AD-3); keine neue §7-Klasse; keine Vertragsänderung.**
|
|
- **2026-08-18 (Erstellung):** Initiale Approve-Baseline.
|
|
- **2026-08-18 (Loop 1, Step-04-bad_spec):** Amendierung der nicht-gefrorenen Sektionen (Code Map / Tasks / Verification) nach dem Review-Loop 1. **Auslöser-Findings:** (A1) `schema/compiler.md` §5.6 Formel 3 (Dangling-Check) ließ Out-of-Bundle-`..`-Traversale still passieren — `[x](../../README.md)` aus einem Area-Concept erzeugte **keine** Ausgabe (der `-f`-Existenztest löste `wiki/<area>/../../README.md` zur existierenden Workspace-`README.md` auf); Kontainment war nur Prosa („Ziel muss unter `wiki/` liegen", „kein Stiller Vorbeilass"), nie durch eine Prüfung erzwungen. (A2) Formel 4 (Kontakt-mit-`raw/`-Baseline) extrahierte aus dem veralteten Story-2.3-`7e1f449…` (Ergebnis `30`), während die Formel-Prosa `66451b6` + Basename-Filter + „dieser Run: 30" beanspruchte und die Ist-Zählung `38` beträgt — ein Producer, der den wörtlichen Selbsttest ausführt, erhält `38 ≠ 30` = FAIL ohne Auflösung. (B1) Das Label `AREA_WITHOUT_INDEX` ist **inventiert** — es existiert in keinem Validator-Output; die reale Meldung ist `FAIL … Punkt 11: Index-Regel verletzt (Area ohne index.md=…)`. **Geändert:** (a) Code Map präzisiert, dass Formel 3 Out-of-Bundle-Ausbruch sperren MUSS (aufgelöster Ziel-Pfad bleibt unter `wiki/`, sonst `DANGLING`); (b) Formel-4-Extraktion auf den `baseline_commit`-Kopf dieser Spezifikation (`66451b6…`) fixiert; (c) `AREA_WITHOUT_INDEX` durch die wörtliche Punkt-11-Meldung ersetzt (Code Map/Tasks/Verification). **Vermeidet den bekannten-bösen Zustand:** (A1) ein Consumer-Renderer kann `../../README.md` nicht auflösen → stiller Verstoß gegen das Renderer-konforme Link-Auflösungsmodell der Story; (A2) re-executierbarer Selbsttest (AD-17h) schlägt auf dem neuen Baum fehl; (B1) Instruktions-Text behauptet eine Validator-Meldung, die der Validator nicht emittiert (Falsch-Attribution auf den Validator). **KEEP (positive Erhaltung, muss die Re-Derivation überleben):** neue Area `wissensarchitektur/` (frontmatterlose `index.md` + `source-material.md`, `type: concept`, `sources` s1=architecture-spine + s2=prd, §5.5-Inline-Verweise, `../`-Links mit Kontext-Marker); bestehende Root-Concepts + Root-`index.md`-Links byte-identisch (kein MOVE, AD-7d); §5.7-Routing-Prinzip ((a) bestehender `index.md`-Link → Bereich / (b) Default Root; neue Areas nur konsolidiert; kein neues Prädikat; kein MOVE); file-relatives Auflösungsmodell; Formel-Berichtigungen oben; die Story-2.4-`deferred-work.md`-Einträge (file-relativ umgesetzt, Basename-Filter). **Kein Schema-/Validator-/raw-Change (AD-3); keine neue §7-Klasse; keine Vertragsänderung.
|
|
|
|
## Design Notes
|
|
|
|
**File-relatives Auflösungsmodell (statt bundleroot-relativ):** Bei Root-Dateien sind file-relativ und bundleroot-relativ identisch (alle 8 bestehenden Bestands-Links bleiben byte-identisch — Null-Delta zum Story-2.3-Pin). In Areas unterscheiden sie sich: `wissensarchitektur/trennung-states.md → llm-wiki-prinzip.md` ist bundleroot-relativ `llm-wiki-prinzip.md` (im Renderer falsch), file-relativ `../llm-wiki-prinzip.md` (im Renderer korrekt). File-relativ erfüllt die zwei Story-2.3-Pin-Rationale (Standard-Tools lösen ohne Konventionswissen auf, FR-10/AD-8) und ist der einzige beide-Ebenen-taugliche Modus; es bleibt **eine syntaktische Form** (relativer Pfad + `.md`-Endung), damit die AD-7b-„zwei-Producer-Eine-ID"-Eigenschaft erhalten bleibt. Die §5.6-`../`-Exklusion war fürs flache Bundle korrekt (jedes `../` war einst außerhalb); mit Areas wird sie zur in-Bundle-Aufwärts-Auflösung. `../schema/` bleibt als andere Schicht exkludiert — Abgrenzung über das Zielverzeichnis (unter `wiki/` = in-Bundle) statt über das bloße `../`-Präfix.
|
|
|
|
**Warum kein MOVE bestehender Concepts in der Demo:** Neuzuordnung/Umbenennung existierender Concepts ist semantische Kuratierung mit AD-7d-Redirect-Pflicht — Epic-3-Nähe, nicht in den Story-2.4-ACs (die nur _neue_ Einheiten zuordnen). Die Demo erzeugt deshalb ein neues Area-Concept + Area-Index; die Routing-/Hold-/Normalisierungs-ACs sind vollständig durch den Sandbox-Negativ-Test und den realen Erzeugungspfad belegt.
|
|
|
|
## Verification
|
|
|
|
**Commands (re-executierbar, ab Workspace-Root):**
|
|
|
|
1. **§5.6-Formel 1/2/3 (area-fest)** — erwartet: Bestands-Check zeigt den neuen Bestand (inkl. `wissensarchitektur/source-material.md` und `../`-Ziele); Form-Check Ausgabe `0`, Exit `0`; Dangling-Check keine Ausgabe:
|
|
- `sh -c "grep -roE '\]\([^)]*\)' --include='*.md' --exclude=log.md wiki/"`
|
|
- Formel 3 (Dangling-Check, nach Story-2.4-`../`-Schärfung, byte-identisch in §5.6 gespiegelt — Rev-2.0-Konvention; Loop-2: quellenbasierte `../schema/*`-Exklusion, Decision 2):
|
|
- `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'
|
|
- **Out-of-Bundle-Escape-Negativkontrolle (Loop-1-Review-Fix):** In einer Sandbox-/tmp-Kopie des `wiki/`-Baums, die auch die Workspace-`README.md` bzw. `schema/compiler.md` außerhalb von `wiki/` enthält, MUSS Formel 3 ein Body-Ziel `[x](../../README.md)` bzw. `[x](../../schema/compiler.md)` aus einem Area-Concept **als `DANGLING: …` melden** (Existenztest reicht nicht — `-f` löst `wiki/<area>/../../README.md` zu einer existierenden Out-of-Bundle-Datei auf und würde still passieren). Die Formel MUSS stattdessen sperren: aufgelöster Ziel-Pfad nach `..`-Auflösung muss unter `wiki/` bleiben.
|
|
2. **Determinismus-Show (Routing):** Negativ-Test Sandbox-`/tmp/…/wiki`: Kandidat mit ID `llm-wiki-prinzip` → §3.2-Hold-Meldung, keine Datei/kein Link; `wiki/foo/` ohne `index.md` → wörtliche Punkt-11-Ausgabe `FAIL … Punkt 11: Index-Regel verletzt (Area ohne index.md=foo)` (kein inventiertes `AREA_WITHOUT_INDEX`).
|
|
3. **§5.6-Formel 4 (Re-Baseline für Zuwachs-Runs, Loop-2-Decision 1):** aktuelle Vorkommen-Zählung `(raw/` (log.md-exkludiert) mit Extraktion aus dem **Kopf des letzten Zuwachs-Runs** (dieser Run: `862cf410c624072833cd959da9a2fb26235716f6`, beide Zählungen = **38**) re-executieren — die Extraktions-Formel im §5.6-Text trägt den Run-Kopf-Commit, nicht den Story-2.3-`7e1f449…` und nicht den `baseline_commit`-Wert der Spec-Frontmatter (`66451b6…` = Zustand **vor** dem Zuwachs, extrahiert `30`; bleibt als Referenz dieses Runs im Log); bei jedem weiteren Datei-Zuwachs ist die Baseline-Extraktion erneut auf den dann aktuellen Run-Kopf durchzuführen (Wieder-Baseline-Klausel §5.6 Pkt. 3, Formel (4)).
|
|
4. **Validator-Lauf:** alle 7 `wiki/`-Dateien SUCCESS (Bundleroot `index.md`, `log.md`, 3 Root-Concepts, Area-`index.md`, Area-Concept; Punkte 1/2/6/7/8/9/10/11/12/13/14, EC-1) — incl. Area-`index.md` frontmatterlos (Punkt 10) und Area-Concept verlinkt im nächsten Vorfahren (Punkt 11). Die „6 `wiki/`-Dateien" der gefrorenen I/O-Matrix bleiben frozen (Defizitzählung; Defer in `deferred-work.md`).
|
|
|
|
**Manual checks:**
|
|
- §7-Story-2.4-Bullet als „in §5.7 verankert" statt „verbleibt"; kein Schema-/Validator-/raw-Diff; `log.md`-Eintrag datiert (2026-08-18), Vertrag-§5-Format, dokumentiert den `sprint-status`-Wechsel und die Formel-4-Neu-Baseline; `deferred-work.md`-Einträge geschlossen/korrigiert (append-only); `sprint-status.yaml` konsistent.
|
|
|
|
## Suggested Review Order
|
|
|
|
**Story 2.4 — deterministische Bereichszuordnung & Concept-Hierarchie (Loop 0 → Loop-1-Findings A1/A2/B1).** Review-Reihenfolge nach Belang, beginnend beim Design-Einstieg.
|
|
|
|
**Design-Einstieg — die neue Routing-Regel**
|
|
|
|
- §5.7 ist der einzige Instruktions-Ort (D-3); von hier versteht man den gesamten Change: (a) bestehender `index.md`-Link → Bereich, (b) Default Root, neue Areas nur konsolidiert, kein MOVE (AD-7c/A0-10/AD-13).
|
|
[`compiler.md:178`](../../schema/compiler.md#L178)
|
|
- Routing-Regel im Detail — textual-deterministische Bereiche, nie Embedding (Pkt. 1).
|
|
[`compiler.md:182`](../../schema/compiler.md#L182)
|
|
- Top-Level-Kollisions-Hold → fixierter §3.2, kein neues Prädikat, kein MOVE (Pkt. 3, A0-10).
|
|
[`compiler.md:196`](../../schema/compiler.md#L196)
|
|
|
|
**Link-Auflösungsmodell & die Loop-1-Fixes**
|
|
|
|
- File-relatives Auflösungsmodell inkl. Out-of-Bundle-`..`-Containment — der Kern der Story; löst das §5.6-Defer (Pkt. 4; Root byte-identisch).
|
|
[`compiler.md:198`](../../schema/compiler.md#L198)
|
|
- Dangling-Check (Formel 3): Quell-Datei-Spur + `..`-Kollabierung + `wiki/*`-Containment — Loop-1-**A1-Fix** (Out-of-Bundle-Escape → `DANGLING`).
|
|
[`compiler.md:154`](../../schema/compiler.md#L154)
|
|
- Negativ-Beispiel 2 (Escape): `[x](../../README.md)` wird als `DANGLING` gesperrt statt still passiert (Loop-1-A1-Nachweis).
|
|
[`compiler.md:174`](../../schema/compiler.md#L174)
|
|
- Kontakt-mit-`raw/`-Baseline (Formel 4): Extraktion aus `66451b6…` (`baseline_commit` dieser Spec) + Basename-Filter — Loop-1-**A2-Fix** (nicht mehr der alte `7e1f449…`).
|
|
[`compiler.md:163`](../../schema/compiler.md#L163)
|
|
|
|
**Area-Hierarchie & Index**
|
|
|
|
- Area-`index.md`-Regel: frontmatterlos (Punkt 10), Punkt-11-Meldung wörtlich (`Area ohne index.md=<area>`) — Loop-1-**B1-Fix** (kein inventiertes `AREA_WITHOUT_INDEX`).
|
|
[`compiler.md:199`](../../schema/compiler.md#L199)
|
|
- Worked Example: `source-material.md` — `type: concept`, `sources` s1/s2, `../`-Links, gepinnte Verlinkung in der Area-`index.md`.
|
|
[`compiler.md:200`](../../schema/compiler.md#L200)
|
|
|
|
**Bundle-Instanz (Demo-Area)**
|
|
|
|
- Frontmatterlose Area-`index.md` verlinkt das Area-Concept (Punkt 10/11 konform, §5.7-Hierarchie).
|
|
[`wissensarchitektur/index.md:1`](../../wiki/wissensarchitektur/index.md#L1)
|
|
- Bereichs-Concept mit §5.5-Inline-Verweisen + `../`-Body-Links auf Root-Concepts (AD-7a/A0-8).
|
|
[`wissensarchitektur/source-material.md:1`](../../wiki/wissensarchitektur/source-material.md#L1)
|
|
- Bundleroot: neue Area-Sektion verlinkt `wissensarchitektur/index.md` (Navigation Root → Area, AD-9).
|
|
[`index.md:35`](../../wiki/index.md#L35)
|
|
|
|
**Nachweis & Logistik**
|
|
|
|
- Spec-Änderung nach Loop 1 (Code Map/Verification präzisiert: Containment-Pflicht, `66451b6`-Baseline, wörtliche Punkt-11-Meldung).
|
|
[`spec …:48`](../../_bmad-output/implementation-artifacts/spec-2-4-deterministische-bereichszuordnung-concept-hierarchie.md#L48)
|
|
- Spec Change Log: Loop-1-Eintrag (Auslöser, Geändert, vermiedener Zustand, KEEP).
|
|
[`spec …:75`](../../_bmad-output/implementation-artifacts/spec-2-4-deterministische-bereichszuordnung-concept-hierarchie.md#L75)
|
|
- `log.md`-Eintrag 2026-08-18: Formel-4-Re-Baseline (`38`), Statuswechsel, gültige Punkt-11-Wortwahl, `sprint-status`-Wechsel.
|
|
[`wiki/log.md:3`](../../wiki/log.md#L3)
|
|
- `sprint-status.yaml`: `2-4-…` → `review` (review-loopiterierte Story, bereit zur Review-Freigabe).
|
|
[`sprint-status.yaml:49`](../../_bmad-output/implementation-artifacts/sprint-status.yaml#L49)
|
|
|
|
## Review Findings (bmad-code-review, 2026-08-18 — Loop 2, 4 Layer)
|
|
|
|
### Decision-Needed (resolved 2026-08-18, Nutzer-Entscheidung)
|
|
|
|
- [x] [Review][Decision] Formel 4 (Kontakt-mit-`raw/`) ist auf dem ausgelieferten Baum per eigener Vorgabe nicht passierbar (38 ≠ 30) — `schema/compiler.md` §5.6 Pkt. 3, Formel (4) hält an „erwartet: aktuell ≡ Baseline" und „Beide Vorkommen-Zählungen **müssen** übereinstimmen" fest, während derselbe Absatz die Ist-Zahl `38` und die aus `66451b6` extrahierte Baseline `30` benennt; ein Producer, der den AD-17h-Selbsttest wörtlich re-executiert, erhält deterministisch `38 ≠ 30` = Run-FAIL nach NFR-4 — exakt der von Loop-1-A2 als bekannt-bös klassifizierte Zustand. `wiki/log.md` rahmt „38 ≠ 30" als „kein Fehlalarm: Zuwachs-Re-Baseline", die Logik sagt also OK, die Formel FAIL; der neue Referenzwert 38 existiert nur als Prosa, nicht in extrahierbarer Form. Re-Execution bestätigt: Ist=38, Baseline(`66451b6`)=30, Extraktion aus Run-Kopf `862cf41`=38. — **Aufgelöst (Nutzer, Option 1):** Re-Baseline auf den Run-Kopf `862cf41` (Extraktion = 38) pinnen; Erwartungstext „Ist ≡ Extraktion aus dem Baseline-Commit des letzten Zuwachs-Runs"; `66451b6`/30 bleibt als Dokumentation dieses Runs im Log. → Patch (unten).
|
|
- [x] [Review][Decision] `../schema/*`-Exklusion in Formel 3/2 ist zielbasiert, nicht quellbasiert — die Prosa (compiler.md `:174`, `:198`, Negativ-Beispiel 2) beschränkt die Exklusion auf „einstufiges `../schema/*` **aus Root-Dateien**", die Formel (`:154` `case "$t" in …|../schema/*) continue`) exkludiert aber unabhängig von der Quelle. Sandbox-verifiziert: `[z](../schema/compiler.md)` aus `wiki/wissensarchitektur/source-material.md` → Auflösung `wiki/schema/compiler.md` (unter `wiki/`, existiert nicht) → Formel-Ausgabe **leer**, Exit 0. Stiller Vorbeilass der einstufigen in-Bundle-Form aus Areas (NFR-4), während der Out-of-Bundle-Escape (`../../…`) korrekt gesperrt wird. — **Aufgelöst (Nutzer, Option 1):** Formel quellenbasiert schärfen — `../schema/*` wird nur exkludiert, wenn die Quell-Datei `wiki/index.md` ist; aus anderen Quellen läuft das Ziel durch Auflösung + Containment + `-f`-Test (→ `DANGLING` bei Nichtexistenz). Prosa bleibt, Formel folgt der Prosa. → Patch (unten).
|
|
- [x] [Review][Decision] Routing-Regel §5.7 Pkt. 1(a) ist bei mehreren passenden `index.md`-Links nicht deterministisch — „inhaltlich deckungsgleichen Eintrag" trägt kein textuelles Prädikat; bei Mehrfachtreffern (real im Ist-Bundle: Bundleroot verlinkt Root-Concept `wissensarchitektur-trennung-states.md`, die Area `wissensarchitektur/` denselben Themenraum) ist unklar, welcher Link den Bereich vorgibt; AD-7c/A0-10 verlangen textual-deterministische Zuordnung. — **Aufgelöst (Nutzer, Option 1):** Deterministisches Treffer-Prädikat + Tie-Break in Pkt. 1(a) verankern: Treffer = Identitäts-Identität des Link-Ziels ≡ kanonischer Name des Themas (kein „inhaltlich deckungsgleich"-Urteil, AD-13); Mehrfachtreffer → Bundleroot-Links vor Area-Links, dann lexicografische Pfad-Reihenfolge. → Patch (unten).
|
|
|
|
### Patch
|
|
|
|
- [x] [Review][Patch] Negativ-Test-Nachweis fehlt in `wiki/log.md` — Code Map verspricht „Negativ-Test-Hold-Nachweis", Task 5 ist `[x]`, aber der 2026-08-18-Log-Eintrag enthält keine Hold-Meldung, keine wörtliche Punkt-11-`Area-ohne-index.md`-Ausgabe, keinen `DANGLING`-Nachweis und keinen Sandbox-Pfad; Execution-Nachweis der I/O-Matrix-Zeilen (TOP_LEVEL_COLLISION, AREA_WITHOUT_INDEX, DIVING_NON_EXISTENT) fehlt im Artefakt [wiki/log.md:4]
|
|
- [x] [Review][Patch] Veraltete „bundle-relativ"-Passagen widersprechen dem neuen file-relativen Pin — `schema/compiler.md:62` (§5.3 Pkt. 3: „file-relativ bundle-relativ mit `.md-Endung" — Oxymoron), `:241` (§6.6-Zelle: „bundlerelativ"), `:254` (§7-Bullet: „bundle-relativ mit `.md-Endung"`) wurden nicht auf file-relativ nachgeführt; für Area-Links faktisch falsch, widerspricht §5.6 Pkt. 1/§5.7 Pkt. 4 [schema/compiler.md:62,241,254]
|
|
- [x] [Review][Patch] Log/YAML/Spec-Status-Divergenz: `sprint-status.yaml` zeigt `review`, der Log-Eintrag dokumentiert nur `backlog → in-progress` („dieser Statuswechsel findet mit diesem Eintrag statt") — die Transition `in-progress → review` (Review-Handoff) ist protokolldokumentarisch nicht abgebildet; die gefrorene Vorgabe („→ `in-progress`") und die Spec-SRO („→ `review`") sind intern spaltig [wiki/log.md:4, sprint-status.yaml:49]
|
|
- [x] [Review][Patch] Spec-Verification „6 `wiki/`-Dateien" vs. Log „7 Dateien" + falsche Punkt-9-Begründung — Spec-Verification (`:96`) erwartet „6 `wiki/`-Dateien, Punkte 1/6/8/9/10/11/14"; der Log dokumentiert 7 Dateien (inkl. `log.md`) mit dem Punkt-Satz 1/2/6/7/8/9/10/11/12/13/14 und begründet die Differenz fälschlich mit „Punkt 9/10" (Punkt 9 = `okf_version`/`type: bundle`-Verbot außerhalb der Bundleroot, nicht log.md-Validierung). Die gefrorene I/O-Matrix („6 `wiki/`-Dateien") selbst bleibt angefasst (→ Defer) [wiki/log.md:4, spec:96]
|
|
- [x] [Review][Patch] Spec-Verification spiegelt die neue Formel 3 nicht byte-identisch — Rev-2.0-Konvention („5/5 Formel-Strings identisch compiler↔spec") bricht: die Verification listet nur den Formel-1-String; der neue Formel-3-String (Quell-Datei-Spur, `..`-Kollabierung, Containment, compiler.md `:154`) fehlt als re-executierbarer Spiegel in der Spec [spec-2-4-….md:124-127]
|
|
- [x] [Review][Patch] §7-Scope-Einleitung veraltet — „Diese Instruktion ist auf die Erzeugung neuer Concepts auf Root-Ebene begrenzt" (`:249`) widerspricht dem eigenen Bullet direkt darunter, das die Area-Anlage in §5.7 verankert; Scope-Satz auf „Root-Ebene und Areas gemäß §5.7" nachführen [schema/compiler.md:249]
|
|
- [x] [Review][Patch] Typos/Orthografie in normativen Texten — `schema/compiler.md:166` + `wiki/log.md:4`: „akte-Baseline" (→ „aktuelle Baseline"); `compiler.md:241`: doppeltes Leerzeichen „(bundlerelativ , `.md`-Endung)"; (frozen-Spec „stillem Overwrite" → Defer) [schema/compiler.md:166,241]
|
|
- [x] [Review][Patch] Ambiguität „Kopf dieser Spezifikation" — Formel 4/Rev-2.1-Log bezeichnen `66451b6` als „Kopf dieser Spezifikation"; gemeint ist der deklarierte `baseline_commit`-Wert der Spec-Frontmatter (Eltern-Commit, nicht der Story-2.4-Branch-Kopf) — Referenz auf den deklarierten Wert umstellen [schema/compiler.md:159,163,283]
|
|
- [x] [Review][Patch] Area-`index.md`-Prosa überzeichnet den Area-Inhalt — `wiki/wissensarchitektur/index.md:3` verspricht „die Link-Form und die progressive Discovery" als gebündelte Themen; existiert genau ein Area-Concept (`source-material.md`), zur Link-Form/Discovery kein Concept (Story 2.5) [wiki/wissensarchitektur/index.md:3]
|
|
- [x] [Review][Patch] `sprint-status.yaml last_updated` ohne Zeitanteil — `08-18-2026` bricht das etablierte Feld-Format `MM-DD-YYYY HH:MM` (bisher `08-17-2026 15:40`) [sprint-status.yaml:32]
|
|
- [x] [Review][Patch] Drei „Story-2.4-Kandidat"-Defer-Einträge bleiben offen, ohne Status-Nachführung — `deferred-work.md:219` (`)`-blinde Ziel-Extraktion), `:223` (Cross-Page-Anker), `:249` (Multi-Line-Ziele) nennen Story 2.4 als Home; die Story ist abgeschlossen ohne Umsetzung und ohne Weiterleitung — Home-Angaben auf nächste Runde (z. B. Story 2.5/fokussierte Instruktionsrunde) umstellen [deferred-work.md:219,223,249]
|
|
- [x] [Review][Patch] (aus Decision 1) Formel-4-Re-Baseline auf Run-Kopf — `schema/compiler.md` §5.6 Pkt. 3, Formel (4): Extraktions-Commit von `66451b6` auf `862cf41` (Run-Kopf, Extraktion = 38) umstellen, Erwartungstext auf „Ist ≡ Extraktion aus dem Baseline-Commit des letzten Zuwachs-Runs"; `66451b6`/30 bleibt als Dokumentation dieses Zuwachs-Runs im Log; `wiki/log.md`-Eintrag um die neue Runnable-Baseline (38 ≡ 38 aus `862cf41`) nachführen [schema/compiler.md:159-166, wiki/log.md:4]
|
|
- [x] [Review][Patch] (aus Decision 2) Formel 3 quellenbasierte `../schema/*`-Exklusion — `schema/compiler.md` §5.6 Pkt. 3, Formel (3): `case "$t" in "#"*|../schema/*)` um Quell-Bedingung schärfen (Exklusion nur, wenn `src` = `wiki/index.md`); aus anderen Quellen läuft das Ziel durch die bestehende Auflösung + Containment + `-f`-Test; Prosa/§5.7 Pkt. 4/Negativ-Beispiel 2 bleiben (sie sind jetzt konsistent); Sandbox-Negativnachweis (in-Bundle-`../schema/x.md` aus Area → `DANGLING`) im Patch-Vergleich verifizieren [schema/compiler.md:154]
|
|
- [x] [Review][Patch] (aus Decision 3) §5.7 Pkt. 1(a) Treffer-Prädikat + Tie-Break — `schema/compiler.md` §5.7 Pkt. 1(a): „auf das erkannte Thema bzw. einen inhaltlich deckungsgleichen Eintrag" ersetzen durch textuelles Prädikat (Identität des Link-Ziels ≡ kanonischer Name des neuen Themas) und Mehrfachtreffer-Regel (Bundleroot-Links vor Area-Links, dann lexicografische Pfad-Reihenfolge); AD-7c/A0-10/AD-13-Referenzen bleiben [schema/compiler.md:183]
|
|
|
|
### Defer
|
|
|
|
- [x] [Review][Defer] Spec-Frontmatter `status: 'done'` bei offenem Review — Präzedenz spec-2-3: `done` erst nach Review-Freigabe; der Status wird mit diesem Review-Loop abgeschlossen synchron (Step-6-Regel), kein separates Patch [spec-2-4-….md:5]
|
|
- [x] [Review][Defer] Gefrorene I/O-Matrix „6 `wiki/`-Dateien" + „stillem Overwrite" — frozen-after-approval-Sektion, nur per Renegotiation änderbar; wird mit der Loop-2-Spec-Amendierung (Decision-Resolution) nachgeführt [spec-2-4-….md:74-76]
|
|
- [x] [Review][Defer] ID-Kollision Area-`index.md` vs. Root-Concept (`wiki/<a>/index.md` und `wiki/<a>.md` → beide Identität `<a>`) — der §3.2-Hold feuert nur auf Datei-Kollision; eine Identitätskollision ohne Dateikollision ist undefiniert. Fix erfordert §3.2-Erweiterung/Vertragsänderung (AD-3 read-only, „kein neues Prädikat") — Home: nächste autorisierte Validator-/Vertragsrevision [schema/compiler.md:190-197]
|
|
- [x] [Review][Defer] Spec-These „Validator Punkt 11 akzeptiert bereits Areas" nicht vom read-only-Validator-Text gedeckt — Punkt 11 verlangt die Identität „als relativer Bundle-Pfad referenziert"; die Area-`index.md` verlinkt file-relativ `source-material.md`, die Bundle-Identität `wissensarchitektur/source-material` erscheint textuell nicht → ein wörtlicher Punkt-11-Check ist auf dem Demo-Concept nicht deterministisch entscheidbar; SUCCESS-Nachweis der Log nicht unabhängig überprüfbar. Fix = autorisierte Validator-Revision (AD-3) — Home: Rev-9-Aktionsitem [validator.md:70, wiki/wissensarchitektur/index.md:9]
|