feat: Story 2.3 Code-Review-Patches (Rev 2.0) — Pin-Schärfung + Change-Log-Scope Code-Review (4 Layer) Story 2.3 — 2 Patch-Findings umgesetzt, 7 deferred. Patch 1 (schema/compiler.md §5.6 → Revision 2.0): - Form-Check (Formel 2) um Exklusions-Stufe `grep -vE '^\.'` ergänzt — Ziele mit `./`-Präfix werden definiert aus dem Pin ausgenommen statt still als "interne .md-Form" durchzugehen (Blind-Hunter BH-8 / Edge-Case EH-4). - Dangling-Check (Formel 3) case-Muster um `./*|/*` erweitert — konsistent zu `../*`-Exklusion (kein DANGLING: ./foo.md-Fehlbenennung mehr). - Byte-identisch in Spec-Verification gespiegelt (5/5 Formeln, verifiziert). Patch 2 (spec Change Log / bad_spec-Zeile): - Scope-Klarstellung der raw/-Zählungen: 30 (log.md-exkludiert, gepinnte Baseline) vs. 34 (inkl. log.md) vs. 28 (Zeilen-Metrik) — verschiedene Metriken, kein Widerspruch mehr. Review-Findings-Sektion + Spec-Change-Log-Eintrag in spec-2-3-…md; 7 Defer-Findings unter "## Deferred from: code review" in deferred-work.md (Image-Scope, Multi-Line-, Reference-Style-, Leading-Space-Ziele, Area-log.md, Cross-Page-Evidenz, log.md-Exklusion — Story-2.4-Kandidat). Positiv-Kontrolle nach Patch: Bestands 8, Form 0, Dangling leer, raw/ 30≡30. sprint-status.yaml: 2-3-… -> done; last_updated 08-17-2026 15:40. Co-Authored-By: Claude <noreply@anthropic.com> @
154 lines
23 KiB
Markdown
154 lines
23 KiB
Markdown
---
|
||
title: 'Concepts verlinken — eine erlaubte Linkform (Story 2.3)'
|
||
type: 'feature'
|
||
created: '2026-08-17'
|
||
status: 'done'
|
||
review_loop_iteration: 2
|
||
baseline_commit: 7e1f449bf78741bb6739d8f510f3ab5543617fef
|
||
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 Link-Schicht von `wiki/` existiert bisher nur in `index.md`; AD-7b/A0-9 („genau eine Form: bundle-relativ, mit oder ohne Endung — nie beide") ist noch formal offen — `schema/compiler.md` (§5.3 Pkt.3, §5.5 Pkt.1) und `schema/validator.md` (Punkt 11, §8) tragen alle die Klausel „Festlegung ist Story 2.3". Zwei Producer könnten aus demselben Baum unterschiedliche IDs berechnen; es existieren noch keine Concept-zwischen-Concept-Links (AD-8).
|
||
|
||
**Approach:** Die Linkform wird auf **bundle-relativ mit `.md`-Endung** gepinnt (alle 3 bestehenden Concept-Links in `wiki/index.md` sind bereits in dieser Form → Null-Migration; die 3 `../schema/`-Links in `index.md` liegen außerhalb des Pin-Wirkungsbereichs (andere Schicht) und bleiben unberührt; Ziele sind explizite Dateien, auch mit Areas eindeutig; Standard-Markdown-Tools lösen ohne Konventionswissen auf, AD-8). Gepinnt wird die Form in `schema/compiler.md` (neue §5.6 + re-executierbare Selbsttest-Formeln + Auflösung der „bis Story 2.3"-Klauseln); demonstriert in zwei inhaltsbasierten Cross-Links in **einem** Concept-Body (`wiki/wissensarchitektur-trennung-states.md` — die Ziel-Concepts werden nicht mutiert, da keine inhaltsbegründete Gegenverbindung besteht: keine erzwungene Gegenseitigkeit, AD-8); dokumentiert in `wiki/log.md`. Der Validator bleibt strukturell unverändert (Präzedenz Story 2.2, D-3; Punkt 11 prüft weiter nur das Vorhandensein von Links).
|
||
|
||
## Boundaries & Constraints
|
||
|
||
**Always:**
|
||
- Gepinnte Form: `[<text>](<bundle-relativer Pfad mit `.md`-Endung>)` — genau eine Form; Ziel = Concept-OKF-Identität (AD-7a) + `.md` (AD-7b, A0-9). Links gehören in Concept-Bodies und `wiki/index.md`; Body-Links ändern keine Aussagen, `sources` oder Frontmatter (Navigations-/Beziehungsschicht ≠ Provenienz, AD-8).
|
||
- `schema/compiler.md` ist einziger Instruktions-Ort (D-3): neue §5.6 „Concept-Links (Story 2.3)" — Pin, Geltungsbereich (Concept-Links + `index.md`-Links; `raw/`-Provenienz-Verweise nach §5.5 bleiben in Plain-/Komma-Form, andere Schicht), Selbsttest-Formeln (re-executierbar, AD-17h), Worked Example; die „bis Story 2.3"-Klauseln in §5.3 Pkt.3 und §5.5 Pkt.1 werden auf §5.6 referenziert; §7-Selbstbegrenzung-Bullet umformuliert; §8-Revisionslog (1.8) + Normreferenzen (AD-7b/AD-8, A0-9, FR-10).
|
||
- **§5.6-Inhalts-Pflichten (Verifikations-Vertrag):** §5.6 MUSS enthalten — (a) exakt eine Pin-Zeile in der oben gepinnten Form, gerendert ohne verschachtelte Backticks (innerer Code-Fence = Anführungszeichen, kein zweites Backtick-Paar); (b) Geltungsbereich = Concept-Bodies + `wiki/index.md`; explizit ausgenommen: `raw/`-Provenienz-Verweise (§5.5, andere Schicht), `../schema/`-Links, `http`-Links, **Gleichseit-Anker `(#…)`** (Form-Check und Dangling-Check exkludieren Anker); (c) **vier** re-executierbare Selbsttest-Formeln — Bestands-Check, Form-Check (erwartet `0`), Dangling-Check (erwartet keine Ausgabe), **Kontakt-mit-`raw/`-Unverändert-Check** (deterministische Baseline-Extraktion aus `baseline_commit` via `git show`, AD-17h — keine „identisch zur X-Baseline"-Behauptung ohne extrahierbare Baseline); alle vier Formeln deterministisch re-executierbar (AD-17h) und bei `wiki/`-Area-Subtree (Story 2.4/2.5) lauffest (rekursive Erfassung, keine künftigen Area-Concepts verpasst); (d) NFR-4-Regel: jede Form-Verletzung → Run-FAIL mit textuell benannter Ursache; (e) Worked Example (gepinnter Link + Form-Check-Auflösung). Die Formeln sind so zu halten, dass die §6.6-Referenztabellen (`Positiv-/Negativ-Beispiele`) eine §5.6-Zeile tragen können (✓-Vorgabe / ✗-Formfehler → deterministische Ursache).
|
||
- Body-Cross-Links inhaltsbegründet (nicht mechanisch): `wiki/wissensarchitektur-trennung-states.md` → `llm-wiki-prinzip.md` (das Wiki-Concept ist der Gegenstand des Architektur-States „curated bundle") und → `knowledge-kompilation-inkrementell.md` (die Kompilation realisiert die Trennung); jeweils ein kurzer Kontextsatz an semantisch passender Stelle. Die Kontextsätze sind **§5.5-konform zu formulieren**: jede darin belegte Aussage trägt entweder einen Inline-`raw/`-Verweis oder einen Kontext-Marker („… nicht eigenständig belegt") — keine unbelegte neue Behauptung im Body.
|
||
- `wiki/log.md`: datumsgruppierter Eintrag (Vertrag §5-Format, neueste zuerst). Der Eintrag MUSS die Tatsachen des Runs abbilden: (a) Formel-Zählung identisch mit §5.6 (vier Selbsttest-Formeln); (b) `sprint-status.yaml`-Statuswechsel `2-3-…` `backlog` → `in-progress` **dokumentieren** (dieser findet statt — kein „bereits in-progress"); (c) `raw/`-Unverändert-Beleg als extrahierbare Baseline-Aussage (Zahl + `baseline_commit`), nicht als bloße „identisch"-Behauptung. `sprint-status.yaml`: Key `2-3-…` → `in-progress`.
|
||
- **Evidenz-Auflösung (re-executierbar, AD-17h):** Jede im Code Map / Verification / log-Eintrag stehende Zählung-Behauptung über den Ausgangszustand ist an `baseline_commit` (Frontmatter) zu extrahieren — z. B. `git show 7e1f449:wiki/index.md` für den Link-Bestand, `git show 7e1f449:… | grep` für `raw/`-Treffer — keine freistehende Zahl ohne extrahierbare Quelle.
|
||
|
||
**Ask First:** Andere Pin-Wahl (mit vs. ohne `.md`) · irgendeine Änderung an `schema/validator.md` (Punkt-11-Einschränkung, neue §7-Klasse) · neue Concepts/Areas (Story 2.4/2.5).
|
||
|
||
**Never:** Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`raw/` (AD-3; der Validator akzeptiert bis auf Weiteres beide Formen — Einschränkung wäre eigene Autorisierung) · Links in Frontmatter/`sources` (AD-4b) · neue §7-Invaliditätsklasse · Standalone-Tool (D-3) · Vorwegnahme Area-Zuordnung/Discovery (Story 2.4/2.5) · Renames (AD-7d) · OKF-Dialekt.
|
||
|
||
## I/O & Edge-Case Matrix
|
||
|
||
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|
||
|----------|--------------|---------------------------|----------------|
|
||
| HAPPY_PATH | Bundle nach dem Pin | Genau eine Linkform in `wiki/`; 2 neue Body-Links auflösbar; Validator-Lauf SUCCESS (5 `wiki/`-Dateien) | N/A |
|
||
| FORMVERLETZUNG | Concept-Link ohne `.md` (oder Mischform) | Selbsttest-Formel (Pkt. 3, Form-Check) trifft deterministisch; Link wird korrigiert oder entfernt, bevor veröffentlicht | Run-FAIL textuell benannt (NFR-4) |
|
||
| DANGLING_LINK | Body-Link auf nicht existente `wiki/`-Datei | Dangling-Formel (Pkt. 3) trifft; Link wird korrigiert oder entfernt | Run-FAIL textuell benannt (NFR-4) |
|
||
| GLEICHSSEIT_ANKER | Gleichseit-Anker-Link `(#…)` im Body | von Form-Check und Dangling-Check exkludiert — keine falsche FAIL/Dangling-Meldung; bleibt außerhalb des Pins | N/A |
|
||
| KONTAKT_MIT_RAW | `raw/`-Provenienz-Verweis (§5.5) im Body | bleibt in Plain-/Komma-Form — der Pin berührt ihn nicht (Selbsttest-Formel `\(raw/` ergibt unveränderte Ausgabe zur `baseline_commit`-Extraktion) | N/A |
|
||
|
||
</frozen-after-approval>
|
||
|
||
## Code Map
|
||
|
||
- `schema/compiler.md` — **mutiert**: neue §5.6 „Concept-Links (Story 2.3)" (Pin, Geltungsbereich, Selbsttest-Formeln, Worked Example) nach §5.5, vor §6 (L123); „bis Story 2.3"-Klauseln in §5.3 Pkt.3 (L62) und §5.5 Pkt.1 (L78) → Verweis auf §5.6; §7-Bullet (L174); §8-Revisionslog (L198 → Eintrag 1.8) + Normreferenzen (AD-7b/AD-8, A0-9, FR-10).
|
||
- `wiki/wissensarchitektur-trennung-states.md` — **mutiert**: 2 Body-Cross-Links (→ `llm-wiki-prinzip.md`, → `knowledge-kompilation-inkrementell.md`) je mit kurzem Kontextsatz; ansonsten unverändert.
|
||
- `wiki/llm-wiki-prinzip.md`, `wiki/knowledge-kompilation-inkrementell.md` — **mutiert nur bei** inhaltsbegründeter Gegenrichtung; sonst unverändert.
|
||
- `wiki/index.md` — **read-only (konform)**: die 3 Concept-Links (L29–31) sind bereits in der gepinnten Form (`.md`) → kein Change; die 3 `../schema/`-Links (L33) liegen außerhalb des Pin-Wirkungsbereichs (andere Schicht) → kein Change; Punkt-11-Check.
|
||
- `wiki/log.md` — **append**: Eintrag unter `## 2026-08-17`.
|
||
- `schema/wiki-compiler.md` (L58: AD-8 Navigations-Schicht), `schema/validator.md` (Punkt 11, L70; §8, L297 — „Story 2.3"-Notiz bleibt) — **read-only**.
|
||
- `raw/architecture-spine/…` (AD-7b L246–248, AD-8 L260–268), `raw/epics/…` (A0-9 L57) — **read-only Evidenz**.
|
||
- `_bmad-output/implementation-artifacts/deferred-work.md` (L66–68: der Linkform-Eintrag, aktuell ohne `status:`-Zeile) und `sprint-status.yaml` (L48) — **mutiert** (Eintrag schließen / Status).
|
||
|
||
## Tasks & Acceptance
|
||
|
||
**Execution:**
|
||
- [x] `schema/compiler.md` — neue §5.6 „Concept-Links (Story 2.3)": Pin (`…/.md`), Geltungsbereich + `raw/`-Exklusion, 4 Selbsttest-Formeln (bestands-, form-, dangling-, `raw/`-Unverändert-Check; re-executierbar), Worked Example; „bis Story 2.3"-Klauseln (§5.3 Pkt.3, §5.5 Pkt.1) auf §5.6 umformuliert; §7-Bullet angepasst; §8-Revisionslog 1.8 + Normreferenzen — AD-7b/AD-8/A0-9, D-3, AD-17h.
|
||
- [x] `wiki/wissensarchitektur-trennung-states.md` — 2 inhaltsbegründete Cross-Links in der gepinnten Form, je ein kurzer Kontextsatz (Link = Navigation, keine Provenienz-Änderung).
|
||
- [x] `wiki/log.md` — Eintrag: Pin-Entscheidung (mit `.md`; Rationale: Null-Migration, explizite Datei-Ziele, Standard-Tools), veränderte Dateien, Validator-Lauf-Ergebnis.
|
||
- [x] `sprint-status.yaml` — `2-3-…` → `in-progress`.
|
||
- [x] `deferred-work.md` — Eintrag L66–68 um `status:`-Zeile schließen (Format wie die bestehenden `status: umgesetzt (…)`-Einträge).
|
||
- [x] Verifikation — alle Formeln aus der Verification-Sektion re-executieren + Validator-Lauf (5 `wiki/`-Dateien SUCCESS).
|
||
|
||
**Acceptance Criteria:**
|
||
- Given zwei zusammengehörige Concepts, when eine Beziehung ausgedrückt wird, then nutzt sie einen normalen Markdown-Link in genau einer erlaubten Form — bundle-relativ mit `.md`-Endung (AD-7b, A0-9).
|
||
- Given der Link-Form-Standard, when ein Consumer die Links traversiert, then sind die Ziel-Concepts ohne Wiki-Software auffindbar (alle internen Links auflösen; FR-10, AD-8).
|
||
- Given ein Link, when er gespeichert wird, then verändert er weder Concept-Inhalt noch `sources`/Frontmatter (Selbsttest-Formel `\(raw/` liefert identische Ausgabe wie vor der Änderung).
|
||
- Given die Instruktion, when geprüft, then §5.6 pinnt die Form, die Selbsttest-Formeln sind deterministisch re-executierbar (AD-17h), Validator/Vertrag/`raw/` sind unverändert und das Bundle bleibt Validator-SUCCESS (keine neue §7-Klasse).
|
||
|
||
## Spec Change Log
|
||
|
||
- **2026-08-17 (Erstellung):** Initiale Approve-Baseline.
|
||
- **2026-08-17 (bmad-code-review, Review-Runde):** Review-Schärfungen (Blind-Hunter + Edge-Case-Hunter) — **Patch 1:** Formel-2-(Form-Check)-Exklusions-Stufe `grep -vE '^\.'` ergänzt (Ziele mit `./`-Präfix definiert aus dem Pin ausgenommen statt still als „interne `.md`-Form" durchzugehen) + Dangling-Formel-3-`case` um `./*|/*` erweitert; beide Formeln byte-identisch in `compiler.md` §5.6 gespiegelt (5/5-Identität). **Patch 2:** bad_spec-Zeile um Scope-Klarstellung der Zählungen ergänzt (30 = `log.md`-exkludierte Vorkommen-gepinnte Baseline; 34 = inkl. `log.md`; 28 = Zeilen-Metrik — verschiedene Metriken, kein Widerspruch). Verifikation nach Patch: alle vier Formeln re-executiert (Bestands `8`, Form `0`, Dangling ∅, `raw/` `30≡30`). Defer-Findings → `deferred-work.md`.
|
||
- **2026-08-17 (Loop 1, Step-04-Review, bad_spec):** Auslösender Befund: Die Verification-Zeile `KONTAKT_MIT_RAW`-Baseline behauptete „identisch zur Story-2.2-Baseline (27 Treffer)". Die Zahl „27" war nicht re-executierbar (verstoß gegen AD-17h — Story-2.2-Zeitrechnung, zeilenbasiert inkl. `log.md`) und damit ein direkter Spezifikationsfehler (nicht nur ein Implementierungs-Fehler). **Scope-Klarstellung der extrahierbaren Zählungen (verschiedene Metriken, nicht Widerspruch):** (a) **30 Vorkommen** = `grep -oE '\(raw/'` über alle `wiki/`-Dateien **außer `log.md`** (diese Zahl pinnt die gepinnte Formel 4 und ist die Run-Baseline); (b) **34 Vorkommen** = derselbe `grep -oE '\(raw/'`-Scan **inkl. `log.md`** (log.md trägt 4 `(raw/`-Vorkommen, u.a. aus dem Story-2.2-Zitat); (c) **28 Treffer-Zeilen** = zeilenbasierte `grep -rnE '\(raw/'`-Zählung inkl. `log.md` (mehrere Vorkommen je Zeile). Die im Befund genannten „34 Vorkommen (28 Treffer-Zeilen)" beziehen sich auf den **inkl.-`log.md`-Scan**; die gepinnte, log.md-exkludierte Baseline ist **30**. **Geändert:** (1) Verification `KONTAKT_MIT_RAW`-Zeile auf deterministische Baseline-Extraktion aus `baseline_commit` umgestellt (`git show 7e1f449:… | grep -oE '\(raw/' | wc -l` → **30** Vorkommen, `log.md`-exkludiert; aktuell ≡ Baseline), keine freistehende Zahl; der inkl.-`log.md`-Scan ergibt baseline wie aktuell **34** (kein Pin-Treffer, nur Doku-Zitat); (2) Approach-Überbehauptung „alle 6 bestehenden Links sind bereits in dieser Form" korrigiert zu „alle 3 bestehenden Concept-Links in `index.md`" (die 3 `../schema/`-Links liegen außerhalb des Pin-Wirkungsbereichs); (3) Approach „demonstriert in zwei … Concept-Bodies" korrigiert zu „in **einem** Concept-Body" (nur `wissensarchitektur-trennung-states.md` mutiert — keine erzwungene Gegenseitigkeit, AD-8); (4) I/O-Matrix `FORMVERLETZUNG` um „oder entfernt" ergänzt und Falsch-Verweis „(Pkt. 2 unten)" → „(Pkt. 3, Form-Check)"; neue Matrix-Zeile `GLEICHSSEIT_ANKER`; (5) Always-Bullets um §5.6-Inhalts-Pflichten (vier Formeln inkl. `raw/`-Unverändert-Check mit extrahierbarer Baseline; Anker-Exklusion; Area-robustheit; §5.5-konforme Kontextsätze; log-Eintrag dokumentiert den `sprint-status`-Wechsel und die extrahierbare `raw/`-Baseline) und um Evidenz-Auflösungs-Pflicht (Zählungen an `baseline_commit` extrahieren); (6) Code Map `index.md` um `../schema/`-Ausnahme präzisiert. **Vermeideter Known-Bad-State:** eine Spezifikation, die eine nicht re-executierbare Zählung (27) als Baseline nennt und damit die AD-17h-Determinismus-Eigenschaft des eigenen Artefakts verletzt. **KEEP-Instructions (positive Erhaltung bei Re-Derivation):** (a) Pin-Form `bundle-relativ mit .md` und deren Rationale (Null-Migration der 3 Concept-Links, explizite Datei-Ziele, Standard-Tools) — unverändert beibehalten; (b) die drei Kern-Selbsttest-Formeln (Bestands-/Form-/Dangling-Check) in der bewährten, negativ-geprüften `sh -c`-Form — beibehalten, um `raw/`-Unverändert-Check (vierte Formel) ergänzt; (c) „Validator/Vertrag/`raw/` unverändert, keine neue §7-Klasse, kein Standalone (D-3)" — strikt beibehalten; (d) §5.6 als einziger Instruktions-Ort (D-3) — beibehalten; (e) die 2 inhaltsbegründeten Cross-Links (ohne erzwungene Gegenseitigkeit) — beibehalten, Kontextsätze jedoch §5.5-konform (Inline-`raw/`-Verweis oder Kontext-Marker) zu formulieren.
|
||
|
||
## Verification
|
||
|
||
**Commands (re-executierbar, ab Workspace-Root; alle vier Formeln AD-17h-konform und negativ-geprüft):**
|
||
|
||
Alle Formeln scannen `wiki/` rekursiv (künftige Area-Concepts unter `wiki/<area>/`, Story 2.4) und exkludieren `log.md` (Dokumentation, keine Link-/Provenienz-Schicht — sie enthält die Formel-Texte selbst als Zitate und würde die Zählungen verunreinigen).
|
||
|
||
1. **Bestands-Check** (Link-Überblick):
|
||
`sh -c "grep -roE ']\([^)]*\)' --include='*.md' --exclude=log.md wiki/"`
|
||
— erwartet: 6 `index.md`-Links (3 Concept mit `.md`, 3 `../schema/`) + 2 neue Body-Links (beide `.md`); alle internen Concept-Ziele `*.md`. (`[^)]*` statt `[^)]+` — leere Ziele `]()` werden sichtbar statt unsichtbar.)
|
||
|
||
2. **Form-Check** (erwartet Ausgabe `0`, Exit `0`):
|
||
`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"`
|
||
— jeder interne Link in der gepinnten Form (`.md`-Endung); exkludiert: `raw/`-Provenienz (§5.5, andere Schicht), `../schema/`, `./`-Präfix-Ziele (`^\.` — nicht root-relativ/keine Bundle-Pfad-Form), externe Ziele (alle mit `:` — `http://`, `https://`, `mailto:`, protocol-less Hostnamen; interne OKF-Ziele sind Kebab-Case und enthalten nie `:`), Gleichseit-Anker `(#…)`. `|| true` bindet den Exit-Code (grep `-c` liefert Exit `1` bei Ausgabe `0` — die *gewünschte* SUCCESS-Konfiguration). Negativ-geprüft: fehlende `.md`-Endung liefert `1`; `mailto:`/`https://` exkludiert; `]()` wird gezählt. (Cross-Page-Anker `file.md#sec` werden weiterhin gezählt — normative Frage, s. `deferred-work.md`.)
|
||
|
||
3. **Dangling-Check** (erwartet keine Ausgabe):
|
||
```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'
|
||
```
|
||
— jedes interne Ziel existiert relativ zum Bundle-Root (bundlerelativ — das Auflösungsmodell des Bundles, AD-7b); 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; leere Ziele `]()` werden als `DANGLING: (leeres Ziel)` gemeldet, nicht still exkludiert. Negativ-geprüft: nicht existierendes Ziel liefert `DANGLING: <pfad>`; `]()` liefert `DANGLING: (leeres Ziel)`; `https://…`/`#anker` exkludiert; `concepts.md#s1` (existierende Datei) liefert **keine** Ausgabe. (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** (aktuell ≡ Baseline, beide re-executierbar, AD-17h):
|
||
- aktuell: `sh -c "grep -roE '\(raw/' --include='*.md' --exclude=log.md wiki/ | wc -l"`
|
||
- Baseline an `baseline_commit` extrahiert (Dateimenge dynamisch aus dem Commit abgeleitet — keine handgelistete Pfadliste, keine Newline-Verbindungs-Abhängigkeit; **einschließende** Einzelanführungszeichen, damit `$f` erst im inneren Shell expandiert):
|
||
`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'`
|
||
— beide Vorkommen-Zählungen müssen identisch sein (erwartet **30**; 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). Der Pin berührt `raw/`-Provenienz-Verweise nicht. (Ersetzt die frühere, nicht re-executierbare Formulierung „identisch zur Story-2.2-Baseline (27 Treffer)" und die handgelistete 5-Datei-`git show`-Kette.)
|
||
|
||
5. **Validator-Lauf** (deterministisch, D-3 manuell-mechanisch): alle 5 `wiki/`-Dateien SUCCESS (Punkte 1/6/11/14, EC-1).
|
||
|
||
**Manual checks:**
|
||
- Cross-Links inhaltsbegründet (Kontextsatz, keine erzwungene Gegenseitigkeit); Kontextsätze §5.5-konform (Inline-`raw/`-Verweis oder Kontext-Marker); keine Frontmatter-/`sources`-Änderung; `log.md`-Eintrag datiert, im Vertrag-§5-Format, dokumentiert den `sprint-status`-Wechsel und die extrahierbare `raw/`-Baseline; `sprint-status.yaml` und `deferred-work.md` konsistent.
|
||
|
||
## Suggested Review Order
|
||
|
||
**Pin & Selbsttest-Formeln (Konvention) — Einstieg**
|
||
|
||
- Der eigentliche Change: §5.6 mit Pin, Geltungsbereich, vier Formeln, NFR-4, Worked Example.
|
||
[`compiler.md:123`](../../schema/compiler.md#L123)
|
||
|
||
- §6.6 trägt die §5.6-Zeile: ✓ gepinnte Form / ✗ fehlende `.md` → Run-FAIL.
|
||
[`compiler.md:213`](../../schema/compiler.md#L213)
|
||
|
||
- Revisionslog 1.8/1.9: vollständige Änderungsgeschichte inkl. Loop-1-Schärfungen der Formeln.
|
||
[`compiler.md:251`](../../schema/compiler.md#L251)
|
||
|
||
**Demonstration**
|
||
|
||
- Der Demonstrations-Run: zwei Cross-Links mit §5.5-konformem Kontext (L20, L22).
|
||
[`wissensarchitektur-trennung-states.md:20`](../../wiki/wissensarchitektur-trennung-states.md#L20)
|
||
|
||
**Dokumentation & Tracking**
|
||
|
||
- Story-2.3-Eintrag: Rationale, `sprint-status`-Wechsel, `raw/`-Baseline (30 ≡ 30), Validator-Lauf.
|
||
[`log.md:4`](../../wiki/log.md#L4)
|
||
|
||
- Linkform-Eintrag (spec-1-4) geschlossen; vier neue Defer-Einträge am Dateiende.
|
||
[`deferred-work.md:69`](./deferred-work.md#L69)
|
||
|
||
- Statuswechsel `backlog` → `in-progress` (→ `review` mit diesem Schritt).
|
||
[`sprint-status.yaml:48`](./sprint-status.yaml#L48)
|
||
|
||
### Review Findings (bmad-code-review 2026-08-17, 4 Layer)
|
||
|
||
**Patch (2):**
|
||
- [x] [Review][Patch] Formel-Lücke `./`-Präfix & schemalose Hostnamen: `[x](./foo.md)`/`[x](example.com/foo.md)` bestehen Form-Check & Dangling-Check — verletzt "bundle-relativ", aber `.md`-Endung genügt. **→ §5.6-Pin-Zeile/Formel 2: Root-relative-Ausschluss ergänzen** [`schema/compiler.md:227`](../../schema/compiler.md#L227) — **umgesetzt**: Formel 2 um `grep -vE '^\.'`-Stufe ergänzt (Ausschluss `./`-Präfix), Dangling-`case` um `./*|/*`-Muster erweitert; Identität compiler↔spec verifiziert (5/5 Formeln byte-identisch); Positiv-Kontrolle nach Patch: Form-Check `0`, Dangling leer, Bestands `8`, `raw/`-Baseline `30≡30`. — **Revision 2.0** in `compiler.md` §8 (siehe Zusatz-Eintrag).
|
||
- [x] [Review][Patch] spec Change-Log `34 Vorkommen (28 Treffer-Zeilen)` ohne Scope/Metrik — drei implizite Zahlen (27/30/34); re-executierbare Baseline **30** (log.md-exkludiert) widerspricht "34". Scope/Metrik (Inkl.-`log.md` + Vorkommen) an der bad_spec-Stelle offenlegen. [`spec-2-3-…md` Change Log](#spec-change-log) — **umgesetzt**: bad_spec-Zeile um Scope-Klarstellung ergänzt (30 exkl. `log.md` = gepinnte Baseline; 34 inkl. `log.md`; 28 Zeilen-Metrik).
|
||
|
||
**Defer (7):** Auf die Story-Datei folgen die Defer-Einträge in `deferred-work.md`; hier nur Zusammenfassung, Details dort.
|
||
|
||
- [x] [Review][Defer] `log.md`-Exklusions-Begründung "zitiert Formel-Texte" ist für Formeln 1–3 gegenstandslos (aktuell 0 `](`-Treffer in log.md); lasttragend nur für Formel 4 — dokumentarische Präzisierung Empfehlung [`schema/compiler.md:132`](../../schema/compiler.md#L132)
|
||
- [x] [Review][Defer] Cross-Page-Defer-Eintrag beschreibt Prä-Patch-Dangling-Verhalten (`DANGLING: concepts.md#s1`) — Zieldatei existiert im aktuellen §5.6-Kern — inkonsistente Evidenz-Zeile [`deferred-work.md:221`](./deferred-work.md#L221)
|
||
- [x] [Review][Defer] Image-/Non-Navigations-`](...)`: kein `
|
||
- [x] [Review][Defer] Multi-Line-Ziele `](foo\nbar.md)` unsichtbar (Ein-Zeilen-Grep) — konservativer Vorbeilass, D-3-Konflikt [`schema/compiler.md:140`](../../schema/compiler.md#L140)
|
||
- [x] [Review][Defer] Reference-Style-Links `[x][ref]`/`[ref]: ziel.md` unsichtbar — zweite Linkform detectable [`schema/compiler.md:140`](../../schema/compiler.md#L140)
|
||
- [x] [Review][Defer] Leading-Space-Ziel `]( ziel.md)` wird als Form-konform UND vorhanden gewertet [`schema/compiler.md:146`](../../schema/compiler.md#L146)
|
||
- [x] [Review][Defer] künftiges `wiki/<area>/log.md` bricht Baseline-Extraktion (Top-Level-Filter `wiki/log.md$`) [`schema/compiler.md:163`](../../schema/compiler.md#L163)
|