Files
wow20/_bmad-output/implementation-artifacts/spec-3-9-deterministische-relevanz-und-reconcile-routing-schliessen.md
T
Michael TamseandClaude 73f2c9e71d feat: Story 3.9 (Loop-2) — Deterministische Relevanz- & Reconcile-Routing schließen, review reif
§5.15 „Deterministische Relevanz- & Reconcile-Routing (Story 3.9)" in schema/compiler.md
(Revision 3.4): geschlossene Termgewinnung (AC-1), symmetrische Normalisierung +
literal-sichere Suche (AC-2), eine exklusive Routing-Tabelle UPDATE→CREATE→ORPHAN/HOLD→NO_OP
(AC-3, NO_OP als Update-Unter-Entscheidung), Raw-Immutability-Guard M/D/R→Run-FAIL (AC-4),
reservierte Zielpfade index/log/source/README→deterministischer Hold (AC-5), Zwei-Run-Identität
nicht-vakuum inkl. praktisch ausgeübter at-Exzeption (AC-6). §3.2-Pkt.-3d-Anker, §5.14-Pkt.-5-Scope
und §7-Bullet nachgeführt.

Review-Loop-2: 2 bad_spec (BS-L2-1 NO_OP-Leere-Candidate-Liste, BS-L2-2 Status-Codes R/C)
durch Re-Ableitung behoben; Step-04-Re-Review (2 frische Layer + Verification Gap) ohne
neuen Loopback (F-6 Lowercasing-Pkt.-1, F8 Guard-Abbruch real, F9 ableitungsbasierte
Term-Erwartung, F-22/F-27 BUNDLE-BYTE-Nachweis angewandt). Sandbox R-1..R-9 PASS, Exit 0.

Re-Derivation: deferred-work.md D-8/D-9 aufgegriffen; epic-3-context.md Z. 39 → Ist;
sprint-status.yaml Story-3.9 → review. AD-3 read-only + Erhaltungs-Invariante (nur
wiki/log.md) gewahrt. Suggested Review Order in Spec 3.9 angehängt.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-21 06:21:08 +02:00

191 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 'Story 3.9 — Deterministische Relevanz- und Reconcile-Routing schließen'
type: 'feature'
created: '2026-08-20'
status: 'done'
baseline_commit: '2f079ee3c87311cda9c9f07614c5e20c869b4500'
review_loop_iteration: 2
context:
- '_bmad-output/implementation-artifacts/epic-3-context.md'
---
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
## Intent
**Problem:** §3.2 (Story 3.2) und §5.14 (Story 3.8) verankern die Relevanz-Mechanik und schließen Normalisierungs-/Match-/Orphan-Lücken, aber die **Routing-Ebene des Reconcile** fehlt als geschlossene, **einzige** Routing-Tabelle: `UPDATE`/`CREATE`/`ORPHAN/HOLD`/`NO_OP` sind über §3 Pkt. 2, §5.1/§5.7, §5.10 Pkt. 8 und §5.9 Pkt. 2 / §3.2-Pkt. 3d verstreut. Termgewinnung (AC-1) bleibt producer-urteilsabhängig; der Guard für **modifizierte/gelöschte committete `raw/`-Dateien** (AC-4) und der Hold für **reservierte Zielnamen** `index`/`log` (AC-5) fehlen. Die Defers D-8 (Mehrfach-Term-Vereinigung) und D-9 (Orphan-Term-Ableitung) haben Home Story 3.9; §5.14 Pkt. 5/§7 markieren die Story-3.9-ACs explizit als „noch nicht verankert".
**Approach:** Neue Sektion **§5.15 „Deterministische Relevanz- & Reconcile-Routing (Story 3.9)"** (nach §5.14, vor §6): (1) **Termgewinnung** als geschlossener, geordneter Algorithmus (deterministisch aus der Zuwachs-Sicht der committeten Evidenz, §5.9 Pkt. 6 R-1) bzw. explizites persistiertes Term-Manifest — kein freies Producer-Urteil (AC-1); (2) **symmetrische Normalisierung + literal-sichere Suche** (Suchterm und Concept-Body identisch normalisiert; `index.md`-Treffer bleiben für die Traversal-Stufe) (AC-2); (3) **eine exklusive Routing-Tabelle** mit deterministischer Prüf-Reihenfolge, alle Zellen referenzieren die bestehenden Mechaniken Wortlaut-unverändert (kein neues Prädikat, keine fünfte Update-Form) (AC-3); (4) **Raw-Immutability-Guard** — modifizierte/gelöschte committete `raw/`-Source im Zuwachs-Befund → Run-FAIL vor jeder Mutation; akzeptiert nur neu hinzugefügte oder separat versionierte Sources (AD-3) (AC-4); (5) **reservierte Zielpfade** `index`/`log` und weitere Bundle-Namen → keine Anlage, deterministischer Hold verlangt disambiguierte Identität (AC-5); (6) **Zwei-Run-Identität** mit positiven UND negativen ausführbaren Fixtures (AC-6, AD-17h/A0-19).
## Boundaries & Constraints
**Always:**
- Nur `schema/compiler.md` mutiert (neue §5.15 + §7-Scope-Präzisierung des Story-3.9-Rests + §8-Revisionslog **Revision 3.4** + ggf. §3.2-Verweis-Anker). `schema/validator.md`, `schema/wiki-compiler.md`, `adapters/`, `raw/` **read-only** (AD-3); `schema/canonical-terms.md` bleibt append-only-Registry (keine Bestandsedits; kein neuer Normalisierungs-Operand — Umlaut-vs-Transkription bleibt Defer, D-3).
- Determinismus aus dem committeten Git-State (AD-17h/A0-19): Termgewinnung, Normalisierung, Routing-Entscheidung, Guard- und Hold-Befund — gleicher Git-State + gleiches Eingabemanifest ⇒ identische Candidate-Liste, Reihenfolge und Routing-Entscheidung (AC-6).
- Die **eine** Routing-Tabelle referenziert die bestehenden Mechaniken **Wortlaut-unverändert**: §3 Pkt. 2 (Update) / §5.1+§5.7 (Neu-Anlage) / §5.10 Pkt. 8 + §5.14 Pkt. 5 (Reconcile-Orphan-Regel) / §5.9 Pkt. 2 + §3.2-Pkt. 3d (No-Op/UNTOUCHED_CONCEPT). Keine Re-Negotiation.
- ORPHAN/HOLD-Zelle bleibt **fail-closed** (keine Wissensmutation, `raw/` unangetastet); der **Hold-Home bleibt Story 3.10** (Review-Loop-3-D-4-Präzedenz) — Story 3.9 verankert nur die Routing-Entscheidung, nicht den Hold-Ausbau.
- Sandbox-Nachweis re-executierbar (Muster sandbox-3-8, Exit 0), harte PASS/FAIL-Assertionen, keine Berührung des realen Ist-Baums; Zwei-Run-Identität nicht-vakuum (getrennte Läufe).
**Ask First:**
- Umlaut-vs-Transkription-Divergenz im Match-Pfad schließen (bleibt benannter Defer — kein neuer Normalisierungs-Operand, append-only).
- `generated.at`-Verhalten ändern (bleibt A0-20-Konvention, §5.14-Ausnahme unverändert).
- Fünfte Routing-/Update-Klasse, neuer Prädikat-/Format-/Frontmatter-Key.
- Weitere reservierte Bundle-Namen über die benannten hinaus (Kollisionsprüfung gegen Ist-Dateien).
**Never:**
- `raw/`-Inhalte verändern (AD-3); textueller Auto-Merge (AD-17c); Wanduhr-Steuerung der Routing-/Bestätigungs-Mechanik; Standalone/eigene LLM-Runtime/neuer Prozess/Server/MCP (D-3, AD-11); Änderung an `schema/validator.md`/`schema/wiki-compiler.md`/`adapters/`; neue §7-Invaliditätsklasse; AD-16-Klassifikation/semantische Kollisionsauflösung (Epic 4); atomares Root-Scope-Leasing (Story 3.11), transaktionaler Lifecycle (Story 3.12), Abnahmegate (Story 3.13) vorwegnehmen.
## I/O & Edge-Case Matrix
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|----------|--------------|---------------------------|----------------|
| TERMGEWINNUNG_GESCHLOSSEN | Zuwachs-`raw/`-Datei(en) gg. `<Baseline-Commit>` | deterministisch geordnete Term-Liste aus der Zuwachs-Sicht (oder über persistiertes Term-Manifest); Teil des Run-Receipts | kein Producer-Urteil; identisch je Run |
| NORMALISIERUNG_SYMMETRISCH | Suchterm + Concept-Body mit Groß-/Klein, Leerzeichen, `_`, `-`, ``, `—` | beide Seiten identisch normalisiert (lowercase + `[-–— _]``-`), literal-sicherer Wort-Vergleich; `index.md`-Treffer bleiben für Stufe b | deterministisch, keine Varianten-Divergenz |
| ROUTING_UPDATE | bestehender Concept-Match (Candidate) | Zelle UPDATE → §3 Pkt. 2 / §5.9-Update | kein Duplikat, kein Overwrite |
| ROUTING_CREATE | eigenständige neue Wissenseinheit, kein Match | Zelle CREATE → §5.1/§5.7-Neu-Anlage | Index-Regel, §5.7-Routing |
| ROUTING_ORPHAN | neu committete Evidenz ohne Ziel-Pfad-Treffer | Zelle ORPHAN/HOLD → §5.10-Pkt. 8-Reconcile-Orphan-Regel (log.md-verwaist, kein Banner, keine Mutation) | fail-closed, AD-16-Default |
| ROUTING_NOOP | Evidenz bereits vollständig repräsentiert | Zelle NO_OP → §5.9-Pkt. 2-No-Op / §3.2-Pkt. 3d, byte-identisches Ziel | keine Mutation, kein `at`-Bump |
| RAW_GUARD_MODIFIZIERT | committete `raw/`-Datei im Zuwachs modifiziert/gelöscht | Run-FAIL **vor jeder Mutation** (AD-3: keine modifizierte/gelöschte committete Source als Input) | textuell benannt (NFR-4) |
| RESERVED_ZIEL_INDEX_LOG | neues Concept-Ziel mit Slug `index`/`log`/reserviertem Bundle-Name | keine Datei geschrieben; deterministischer Hold verlangt disambiguierte Identität | textuell benannt, Run „teilweise erfolgreich" |
| ZWEI_RUN_IDENTISCH | gleicher Git-State + gleiches Eingabemanifest, zwei Läufe | identische Candidate-Liste, Reihenfolge und Routing-Entscheidung; Assertion nicht-vakuum | PASS; Abweichung = AD-16-Klassifikationsdefekt (§5.14 Pkt. 4) |
## Code Map
- `schema/compiler.md`**primär mutiert** (D-3): neue Sektion **§5.15 „Deterministische Relevanz- & Reconcile-Routing (Story 3.9)"** (nach §5.14 Z. 377, vor §6 Z. 379; Pkt. 16); §7-Relevanzbestimmung-Bullet Z. 434 („Story-3.9-ACs noch nicht verankert"/P-8-Scope-Präzisierung → auf §5.15-Verankerung nachgeführt); §8-Revisionslog **Revision 3.4** nach Z. 477 (Abschlussklausel AD-3/D-3/keine neue §7-Klasse); optional §3.2-Verweis-Anker (Pkt. 1 Term-Ziehverfahren Z. 4954, Pkt. 3d NO_MATCH Z. 63 → §5.15-Pkt.-1/-3-Verweis). Bestehende §3/§5.9/§5.10/§5.14-Mechaniken bleiben **textuell unverändert** (Referenz statt Re-Negotiation).
- `_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh`**neu** (re-executierbar, Muster `sandbox-3-8/run-sandbox.sh`, Exit 0): Szenarien R-1..R-9 (Matrix-Zeilen als harte Assertionen; Zwei-Run-Identität in getrennten Läufen; negative Kontrolle je Guard/Hold).
- `_bmad-output/implementation-artifacts/sprint-status.yaml`**mutiert**: Key `3-9-deterministische-relevanz-und-reconcile-routing-schliessen` `backlog``in-progress`; `last_updated` (Format `MM-DD-YYYY HH:MM`).
- `_bmad-output/implementation-artifacts/deferred-work.md`**append**: Defers D-8 (Mehrfach-Term-Vereinigung) und D-9 (Orphan-Term-Ableitung, fester 2-Datei-Scan) → aufgegriffen/geschlossen; Umlaut-Defer bleibt offen (wie notiert, kein Instruktions-Defekt).
- `wiki/log.md`**append** (Vertrag §5, bestehende Bullets unverändert): Story-3.9-Eintrag (Verankerung §5.15, Sandbox-Nachweis R-1..R-9, Status-Flip, Validator-Verdikt).
- `_bmad-output/implementation-artifacts/epic-3-context.md`**mutiert** (gemäß genehmigtem Sprint-Change-Proposal 2026-08-20 „Artifact Impact: epic-3-context.md synchronisiert"; Header „Edit freely"): Technical Decision Z. 39 „Zielzustand … geplant für Story 3.9 … noch nicht verankert; §3.2 ist bis dahin maßgeblich" → Ist/§5.15-Verankerung; Z. 41/43 (Story 3.11/3.12) bleiben Zielzustand.
**Read-only evidence (AD-3):** `schema/validator.md` (Rev 9), `schema/wiki-compiler.md`, `adapters/`, `raw/` (z. B. `raw/architecture-spine/architecture-spine-2026-08-14.md` AD-3/AD-13/AD-17h; `raw/epics/epics-2026-08-14.md` FR-4/FR-5/FR-6, A0-18/A0-19). `schema/canonical-terms.md` append-only unangetastet (leer; keine Einträge nötig — Termgewinnung lebt als Regel in §5.15/§3.2).
## Tasks & Acceptance
**Execution:**
- [ ] `schema/compiler.md` — §5.15 einfügen (nach §5.14, vor §6): Pkt. 16 gemäß Intent; keine neuen Prädikate/§7-Klassen/Keys; §7-Vorbehalt und §8-Revisionslog **Revision 3.4** nachführen
- [ ] `_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh` — R-1..R-9, harte PASS/FAIL, Zwei-Run nicht-vakuum, Exit 0
- [ ] `_bmad-output/implementation-artifacts/sprint-status.yaml` — Key 3-9 → `in-progress`; `deferred-work.md` — D-8/D-9 aufgegriffen; `wiki/log.md` — Story-3.9-Eintrag (Verankerung, Sandbox, Validator-Verdikt)
- [ ] `_bmad-output/implementation-artifacts/epic-3-context.md` — Z. 39 Zielzustand → §5.15-Ist (Z. 41/43 unverändert)
**Acceptance Criteria:**
- Given einen committeten Git-State und ein kanonisches Eingabemanifest, when Candidate-Terme gewonnen werden, then folgt die Gewinnung einem geschlossenen, geordneten Algorithmus oder einem expliziten, persistierten Term-Manifest — keine freie Producer-Auswahl (AC-1).
- Given semantisch gleiche Schreibweisen (Groß-/Kleinschreibung, Leerzeichen, Unterstrich, Bindestrich, En-Dash, Em-Dash), when die Stufe-a-Suche läuft, then werden Suchterm und Concept-Body identisch normalisiert und literal-sicher verglichen; `index.md`-Treffer bleiben für die Traversal-Stufe erhalten (AC-2).
- Given interpretierte Evidenz, when Reconcile abgeschlossen wird, then gilt genau eine Routing-Tabelle: bestehender Match → `UPDATE`; eigenständige neue Wissenseinheit → `CREATE`; nicht klassifizierbare Evidenz → `ORPHAN/HOLD`; bereits vollständig repräsentierte identische Evidenz → `NO_OP` (AC-3).
- Given eine geänderte oder gelöschte bereits committete Datei unter `raw/`, when der Run seine Eingaben prüft, then schlägt er vor jeder Mutation fehl; akzeptiert werden nur neu hinzugefügte oder separat versionierte Sources (AD-3) (AC-4).
- Given ein neues Concept-Ziel, when dessen Slug `index` oder `log` beziehungsweise ein anderer reservierter Bundle-Name wäre, then wird das Ziel nicht geschrieben und ein deterministischer Hold verlangt eine disambiguierte Identität (AC-5).
- Given gleicher Git-State plus gleiches Eingabemanifest, when zwei Runs ausgeführt werden, then erzeugen sie dieselbe Candidate-Liste, Reihenfolge und Routing-Entscheidung — belegt durch positive und negative ausführbare Fixtures (AD-17h, A0-19) (AC-6).
## Spec Change Log
- **Review-Loop-2 bad_spec-Loopback (2026-08-20):** bmad-code-review (Blind Hunter 28 / Edge Case Hunter 10 / Verification Gap 9 verifizierte Findings, D-3-Gewichtung) ergab **2 bad_spec** (innerer Instruktions-Widerspruch), 4 patch, 2 defer, restliche als reject/verworfen; **kein intent_gap** (kein Eingriff in `<frozen-after-approval>`). **Kern-Defekt (BS-L2-1):** die §5.15-Pkt.-3-Routing-Tabelle definiert **NO_OP (Zelle 4) ausschließlich als Unter-Entscheidung des Update-Pfads** („bereits vollständig repräsentierte, identische Evidenz"), während der **§3.2-Pkt.-3d-Verweis-Anker (compiler.md Z. 63)** die NO_MATCH-Leer-Candidate-Liste pauschal an **„Zelle 4 (NO_OP)“** koppelt — eine **neue Einheit ohne bestehenden Treffer** gehört aber in den Bewertungsraum **Zelle 2 (CREATE)** / **Zelle 3 (ORPHAN/HOLD)**, nicht NO_OP. Die Sandbox setzt diesen Fehler fort und verletzt damit zusätzlich das KEEP-Design (Design Notes Z. 87: „neue Wissenseinheit → CREATE“): R-5 (`run-sandbox.sh` Z. 462467) assertiert für neue Terme `zeta-a`/`zeta-b` explizit „NO_OP-Pfad, kein Anlage-Zwang“ — neue Einheiten würden unter dieser Interpretation nie angelegt. **(BS-L2-2):** die Status-Codes sind inkonsistent — §5.15-Pkt.-1-Satz nennt `--diff-filter=ACMR` (impliziert R/C behandelt), der Guard Pkt. 4 definiert nur `A`/`M`/`D`, R/C-Zuordnung bleibt undefiniert (Rename einer committeten `raw/`-Datei = AD-3-Verletzung, Copy = neu). **KEEP (muss in der Loop-2-Re-Ableitung überleben):** §5.15 als eigene Sektion nach §5.14 mit **einer** exklusiven Tabelle (vier Zellen UPDATE/CREATE/ORPHAN-HOLD/NO_OP, NO_OP als Update-Unter-Entscheidung gemäß Design Notes, CREATE-vs-ORPHAN-Prädikat, Stufe-b-Zelle); Referenz-statt-Re-Negotiation (§3/§3.2/§5.9/§5.10/§5.14 textuell unverändert — lediglich der §3.2-Pkt.-3d-Verweis-Anker wird nach Paragraph-Korrektur auf „Zelle 2 (CREATE)?/Zelle 3 (ORPHAN/HOLD)“-Bewertungsraum nachgeführt); Raw-Immutability-Guard ≠ INPUT_UNCOMMITTED; Hold-Home Story 3.10; Zwei-Run-Identität nicht-vakuum in getrennten Runs; Umlaut-Defer bleibt offen (kein neuer Normalisierungs-Operand); AD-3 read-only (validator/wiki-compiler/adapters/raw/canonical-terms unverändert); Sandbox re-executierbar auf /tmp-Baum, Exit 0. **Loop-2-Auflagen:** **(BS-L2-1a)** §5.15-Pkt.-3-Tabelle + §3.2-Pkt.-3d-Anker + Sandbox R-3/R-5 in Einklang: leere Candidate-Liste bei neuer Einheit → **CREATE-Prädikat zuerst** (eigenständig interpreterbar + Ziel-Pfad ableitbar + Reserviertheits-Check) → sonst **ORPHAN/HOLD** (Zelle 3) → **niemals NO_OP**; NO_OP bleibt ausschließlich Update-Unter-Entscheidung (bestehende Evidenz identisch repräsentiert); R-5 übt den CREATE-Bewertungsraum (bzw. OPRHAN-Negativfall) ab, R-3-Fall-2 vergleicht die reale neue Evidenz gegen den tatsächlichen bestehenden Body (keine handgeschriebenen scratch/.txt). **(BS-L2-2a)** Status-Codes schließen R/C: Rename (R) einer committeten `raw/`-Datei = AD-3-Verletzung → Guard-FAIL; Copy (C) = wie neu (A) akzeptiert; `--diff-filter=ACMR` dokumentiert die Zuordnung; Sandbox-Fallback-Test (M/D/R → Guard-FAIL, A/C → akzeptiert). **(P-L2-1)** Sandbox-`norm()` auf die **eine** Kollaps-Definition (§3.2-Pkt.-1b-Ebene, Kollaps-Klasse `[-–— _]``-`, Läufe auf ein `-`, Trim führend/trailend; lowercasing) vereinheitlicht — keine vierte, abweichende Pipeline; Interleaved-Separator-/Umlaut-Grenzfall als benannter Defer (kein Instruktions-Defekt). **(P-L2-2)** R-2-`index.md`-Traversal-Test so ertüchtigt, dass der Guard-Branch real feuert (Fixture enthält den Term) — negatives Assert gegen die Traversal-Exklusion statt statischem Echo. **(P-L2-3)** R-1-Diff↔Manifest-Äquivalenz um einen **Negativ-Zweig** ergänzt (divergentes Manifest → Assert des Run-FAIL vor jeder Mutation). **(P-L2-4)** R-8-„Zwei-Run-Hold-Identität" real über **zwei getrennte Worktrees** über demselben committeten Baum statt Doppel-Read derselben Datei (`run-sandbox.sh` Z. 574575 — Behebung der Tautologie). **(P-L2-5)** R-6/R-7: Ziel-Slug aus dem echten abgeleiteten Kandidaten (nicht hartgesetzt `TARGET_SLUG="index"/"log"`), plus Ausübung der §5.15-Pkt.-5-Ist-Dateimenge (`git ls-tree`-Schnittmenge) mit Positiv-/Negativ-Fixture; R-8-„tote CAND"-Assertion entdoppeln (ein hartes Nicht-Existenz-Assert, kein `|| true`-Neutrum). **(P-L2-6)** R-9-Receipts um ein `generated.at`-Feld ergänzt und die **at-Exzeption** praktisch ausgeübt (legitime at-Abweichung wird NICHT als AD-16 gemeldet; nicht-at-Feld-Differenz wird HARD-FAIL) — die technisch einzige benannte Zwei-Run-Differenz ist damit real nachgewiesen. **(D-L2-1)** Mehrfach-Term-Vereinigung (D-8) in der Sandbox ausübend belegt (mehrere Terme je Zuwachs-Datei deterministisch abgeleitet und im Receipt geführt) oder explizit als ungetesteter Defer in `deferred-work.md` markiert. **(D-L2-2)** `ls-tree`-Schnittmenge (Pkt. 5) bleibt statisch definiert; da keine gültige Fixture eine kollidierende sonstige Struktur-Ziel-Anlage betrifft, bleibt sie als negative Matrix-Zeile benannt (nicht stiller Ausschluss). **Bekannte-Nicht-Story-Probleme (defer/reject)** bleiben sichtbar: Defer „Orphan voller Stufen b/c + Mehrziel" (Hold-Home Story 3.10 — post-Reconcile, Mehrziel aus D-8); Reject „Fixture-coupling deutsche Literale" (dekorativ, Kollaps-Harmonisierung deckt die zugrundeliegende Instruktions-Unschärfe); Reject „Spec untracked → eingebettete Kommandos unverifiziert" (AD-3/Erhaltungs-Clains durch Sandbox-Verlauf + Isolations-Realität verifiziert). Neu-Verhandlung des Frozen-Intents nötig: **Nein** (nur nicht-frozen Sektionen + abgeleiteter Code betroffen; kein AC-Wortlaut geändert).
- **Re-Review Loop-2 Step-04 (2026-08-21, bmad-code-review Re-Run — 2 frische Agent-Layer + Verification Gap):** Blind Hunter (frischer Kontext) + Edge Case Hunter (frischer Kontext) gegen das Loop-2-Re-Ableitungs-Bundle; anschließend **Verification Gap** (gegen Instruktion + Sandbox-Code). **Ergebnis: kein intent_gap; bad_spec-artige Lücken verifiziert und als patch/real behoben (kein weiterer Loopback).** **Blind-Hunter-Findings (F1F10):** **(F1F4, F6, F10, reject):** die §5.15-Pkt.-3-Tabelle (Z. 385395) deckt die Stufe-b/c-Zuordnung explizit ab (Z. 395: „Stufe-b-Zelle", UPDATE bei gewurzelter Erreichbarkeit, ORPHAN/HOLD bei Dangling), der §3.2-Pkt.-3d-Anker (Z. 63) ist vollständig konsistent mit Zelle 2/3 („leere CL → Zelle 2/3, nicht NO_OP"; UNTOUCHED_CONCEPT nur bei gar keiner Zuwachs-Evidenz), Status-Codes inkludieren R (Z. 383: „R = umbenannt"), Normalisierung nennt wörtlich lowercasing — die blind-hunte zitierten Zeilen („Z.22/37/52") existieren so nicht; die behaupteten Anker-Inkonsistenzen liegen nicht vor. **(F5, reject):** Sidecar-Exklusion über `case *.source.md` (Sandbox Z. 163) deterministisch; die Sidecar-Datei ist Teil des Zuwachs-Befunds, trägt aber keinen Term. **(F7, reject):** die zitierte Assertion gehört zu **R-8** (Z. 669672, Hold-Befund NFR-4), nicht zu R-9/at-Exzeption (Z. 803ff.); durch den BUNDLE-BYTE-Fix (F-27) ist die at-Exzeption zudem strukturell robust. **(F8, bad_spec → REAL behoben):** R-4 zeigte den Guard-Wert nur als „Status M/D erkannt"-Echo und prüfte ohne echten Guard-Abbruch — der „Run-FAIL vor jeder Mutation"-Pfad (Exit 1) wurde nicht real ausgeübt; Fix: Unterlauf, der bei M/D hart mit Exit 1 endet (über `|| G_ABBRUCH=$?`-Fänger unter `set -e`), plus Nachweis „keine neue wiki-Datei" — R-4 zeigt jetzt „Guard-Abbruch real geübt". **(F9, bad_spec → REAL behoben):** R-1 erwartete die Term-Liste als literal `beta beta-kommunikation kommunikation` (hart kodiert, reagiert nicht auf Dateinamen-Änderung); Fix: Erwartung wird aus dem Zuwachs-Dateinamen **ableitungsbasiert gegengeprüft** (gleiche Dateiname→Term-Synthese), kein fest verdrahteter Erwartungswert. **Edge-Case-Hunter-Findings (F-2…F-27):** siehe oben — F-6 (Lowercasing-Pkt.-1, Instruktions-Fix), F-17/F-18/F-20/F-21 (reject/erläutert), F-22/F-27 (BUNDLE-BYTE-FIX), F-15/F-16 (reject: A/C-Äquivalenz, R100-robust), F-23/F-24 (Re-Run-Idempotenz = Sandbox-Ergonomie, benannter Folgepunkt), F-25/F-26 (reject). **Keine Neu-Verhandlung des Frozen-Intents:** die Step-04-Fixes sind Sandbox-Code (R-4-Guard-Abbruch, R-1-ableitungsbasierte Erwartung, R-9-BUNDLE-BYTE) bzw. eine textuelle Klarstellung der bereits geschlossenen §3.2-Pkt.-1b-Normalisierung (F-6); kein AC-Wortlaut geändert. **Sandbox-Nachweis (nach allen Step-04-Fixes):** Exit 0 — R-1..R-9 harte PASS; R-1-Term-Ableitung gegengeprüft, R-4-Guard-Abbruch real, R-9-Bundle-byte-Identität (clean voll gleich, atgap maskiert gleich, divergent hart FAIL).**Verifizierte Findings & Umgang:** **(F-6, patch statt bad_spec, Instruktions-Fix angewandt):** §5.15-Pkt.-1-Termgewinnung nannte das **Lowercasing** im Dateiname→Term-Mapping nicht wörtlich (nur Kollaps-Klasse `[-–— _]``-`), während §3.2-Pkt.-1b (Z. 51) und §5.15-Pkt.-2 lowercasing einschließen → Asymmetrie; Fix: §5.15-Pkt.-1 „beide Seiten identisch normalisiert: **lowercasing + Kollaps-Klasse** … (§3.2-Pkt.-1b-Normalisierung)" — harmonisiert mit AC-2/Pkt. 2, kein neuer Operand. **(F-17, bad_spec-Vorwurf → geschwächt zu reject/patch):** die behauptete „schwerwiegende Dateikollision `wiki/meta.md`-über-CREATE" wird durch **§5.7-Pkt.-3-Top-Level-Update-Routing** (Dateikollision → Update-Routing, „kein Duplikat, kein stiller Overwrite") bereits deterministisch ausgeschlossen; die Pkt.-5-Reserviertheits-Schnittmenge (nur die 4 benannten Namen) ist dafür bewusst eine **statisch-definierte Ist-Basis** (Ask-First-Nomenklatur) und die CREATE-Zelle verlangt selbst „kein stiller Overwrite". Kein Guard-Durchbruch. **(F-8/F-9, reject):** Ziel-Slug deterministisch ableitbar via §5.15-Pkt.-5/§5.7-Pkt.-2-Kanonische-ID/§5.1 aus dem abgeleiteten Kandidaten (§5.15 Pkt. 1); Sandbox R-6/R-7 leitet den Slug aus dem abgeleiteten Kandidaten ab. **(F-20, teils annulliert → BUNDLE-FIX-Zusatz):** die Negativ-Kontrolle ist keine Zeilenanzahl-Tautologie — der divergente Run erzeugt eine andere Kandidaten-Liste (konstruierte AD-16-Differenzart), Receipt-Vergleich schlägt hart FAIL. **(F-22, patch → durch Bundle-Fix überdeckt):** at-Exzeption hing am festen Zeilenraster der Receipts; jetzt strukturell robust über den BUNDLE-BYTE-Vergleich (maskierte at-Zeile je Datei). **(F-27, patch bestätigt → BUNDLE-BYTE-FIX angewandt):** R-9 verglich nur **Receipt-Felder**, nicht die **byte-identischen MUTIERTEN Bundle-Bestandteile** (A0-19/§5.15 Pkt. 6): `run-sandbox.sh` mutiert je Lauf `wiki/alpha.md` (einzig laufabhängiges Feld `generated.at`), sichert SHA-256 voll + mit maskierter at-Zeile je Datei und assertiert: clean-vs-clean **voll identisch**, atgap-vs-clean **maskiert identisch** (at-Exzeption an der mutierten Datei), divergent **hart FAIL** — Exit 0, alle R-1..R-9 harte PASS. **(F-18, reject/patch geprüft):** Slug-Heuristik in der Sandbox ist Fixture-Darstellung des ableitbaren Kandidaten (kein hartes `TARGET_SLUG`); Operator ist §5.15-Pkt.-5/§5.7-Pkt.-2. **(F-19/F-23/F-24, patch-Hinweise, kein Loopback-Blocker):** `README`-case/Groß-Schreib-Normalisierung, Sandbox-**Re-Run-Idempotenz** (zweiter Lauf über gleichem `$ROOT` scheitert an wieder-existierenden `wt-*`-Worktree-Verzeichnissen) und stale-`$ROOT`-Reste sind **Sandbox-Ergonomie, keine Instruktions-Defekte** und liegen außerhalb der Story-ACs („Re-executierbar" gilt je frischem `$ROOT`); als benannter Folgepunkt (D-3-Qualitäts-/Ergonomie-Lücke, Home Story 3.13-Härtung) festgehalten. **(F-2/F-3, reject):** Sortierung (LC_ALL=C) + Term-Dedup via Sortierung/besuchte Menge; `norm()` deckt die volle Kollaps-Klasse. **(F-15/F-16, reject):** `C`-Status praktisch nie von git gemeldet (ohne `-C`); A/C-Äquivalenz akzeptiert, Guard robust gegen `R100`. **(F-21, reject):** zwei Runs über getrennte Arbeitstrees desselben Commits (commit-Hash-Differenz in `[bundle]` bestätigt). **(F-25/F-26, reject):** parallel-safe über separate `mktemp`-Roots; NFR-4-Hold-Befunde in Receipts/log-Dateien. **Keine Neu-Verhandlung des Frozen-Intents:** §5.15-Pkt.-1-Lowercasing-Fix ist textuelle Klarstellung der bereits geschlossenen §3.2-Pkt.-1b-Normalisierung; BUNDLE-BYTE-Fix ist Sandbox-Code (abgeleitet), keine AC-/Instruktions-Änderung. **Sandbox-Nachweis (nach Fixes):** Exit 0 — run9a/run9b `wiki/alpha.md`-SHA-256 voll identisch, run9at maskiert identisch, run9n divergent hart FAIL. **Neu-Verhandlung des Frozen-Intents nötig: Nein.**
- **Re-Ableitung Loop-2 (2026-08-20, nach Step-03-Loopback):** Alle Loop-2-Auflagen (BS-L2-1a/BS-L2-2a, P-L2-1..P-L2-6, D-L2-1/D-L2-2) sind in der Re-Ableitung umgesetzt: `schema/compiler.md` **Revision 3.4** mit vollständiger §5.15-Sektion (Pkt. 16), §3.2-Pkt.-3d-Verweis-Anker, §5.14-Pkt.-5-Scope-Präzisierung, §7-Bullet-Erweiterung, Revisionslog; Sandbox **R-1..R-9 harte PASS, Exit 0** (Termgewinnung inkl. D-8-Mehrfach-Term-Vereinigung + Negativ-Manifest, R-1b-R/C, norm()-Harmonisierung, R-2-index.md-reales Feuern, R-3-Fall-2-echter Evidenzvergleich, R-5-CREATE-Bewertungsraum + aus-Zuwachs-abgeleitete-Terme, R-6/R-7-Slug-Ableitung + `git ls-tree`-Schnittmenge, R-8-Zwei-Worktree-Hold, R-9-at-Exzeption). Re-Derivation: `deferred-work.md` D-8/D-9 → `aufgegriffen`, `epic-3-context.md` Z. 39 → Ist (§5.15 verankert), `sprint-status.yaml` Key `3-9-…``in-progress`. AD-3 read-only + Erhaltungs-Invariante §5.9 Pkt. 5 gewahrt (`git status --porcelain -- wiki/` zeigt ausschließlich `log.md`). **KEEP-Erhalt:** §5.15 eigene Sektion, eine exklusive Tabelle (vier Zellen, NO_OP als Update-Unter-Entscheidung, leere Candidate-Liste → Zellen 2/3), Referenz-statt-Re-Negotiation, Guard ≠ INPUT_UNCOMMITTED, Hold-Home Story 3.10, Zwei-Run-Identität nicht-vakuum, AD-3 read-only, Sandbox auf /tmp-Baum. Neu-Verhandlung des Frozen-Intents nötig: **Nein**. (Dieser Nachtrag betrifft die Re-Ableitung; der Review-Befund selbst bleibt im Eintrag oben Stand Review-Loop-2.)
- **Review-Loop-1 bad_spec-Loopback (2026-08-20):** bmad-code-review (Blind Hunter 15 / Edge Case Hunter 18 / Verification Gap 5, D-3-Gewichtung) ergab 7 bad_spec-Findings, 2 patch, 1 defer, 3 reject; kein intent_gap (kein Eingriff in `<frozen-after-approval>`). **Auslöser:** die Step-03-Ableitung hat die 6 ACs textuell verankert, aber nicht konsistent/ausführbar gemacht. **KEEP (muss in der Re-Ableitung überleben):** §5.15 als eigene Sektion nach §5.14; die **eine** Routing-Tabelle mit den vier Zellen UPDATE/CREATE/ORPHAN-HOLD/NO_OP; Referenz-statt-Re-Negotiation (bestehende §3/§3.2/§5.9/§5.10/§5.14-Mechaniken textuell unverändert); Raw-Immutability-Guard ≠ INPUT_UNCOMMITTED; Hold-Home Story 3.10; Zwei-Run-Identität nicht-vakuum in getrennten Run; Weak-Defers D-8/D-9 aufgegriffen; Umlaut-Defer bleibt offen; AD-3 read-only (validator/wiki-compiler/adapters/raw/canonical-terms unverändert); Sandbox re-executierbar auf /tmp-Baum. **Zu behebende bad_spec-Defekte (Re-Ableitungs-Auflagen):** (BS-1) §5.14-Pkt.-5-Z.377-Scope-Präzisierung auf das Story-3.9-Ist nachführen (Widerspruch zu §7-Z.449/log); (BS-2) Term-Ableitung instruieren — Dateiname→Term-Mapping (§5.15 Pkt. 1), `source.md`-Sidecar-Exklusion, Status-Codes `A/M/D`, §5.9-Pkt.-6-Diskrepanz-/Fallback-Kopplung, Diff↔Manifest-Äquivalenz; (BS-3) Routing-Tabelle exklusiv machen — NO_OP-Reihenfolge (Unter-Entscheidung im Update-Pfad)/CREATE-vs-ORPHAN-Prädikat/Stufe-b-Zelle konsistent mit Sandbox; (BS-4) Pkt. 5 reservierte-Namen-Menge erschöpfend + Ist-Dateimenge deterministisch (Ask-First-Nomenklatur); (BS-5) `tree=`-Ausnahme dokumentiert oder entfernt (§5.15-Pkt.-6-Receipt-Vergleich — nur `at` als benannte Differenz); (BS-6) R-8 Hold ausüben (NFR-4-log-Hold-Befund + „teilweise erfolgreich" + tote `CAND`); (BS-7) R-9 Negativ-Fixture (AD-16-Abweichung hart assertiert) + Manifest-Pfad nicht-konversationell; (P-1) Sandbox-`set -e` im Hauptkörper (sandbox-3-8-Härtung, kein false-PASS); (P-2) D-9-Aufgegriffen-Text „Stufen a/b/c" präzisieren (R-5 übt nur Stufe-a über die festen zwei Dateien). **Bekannte-Nicht-Story-Probleme (defer/reject)** bleiben sichtbar: Defer „Orphan voller Stufen b/c + Mehrziel" (Hold-Home Story 3.10); Reject „Fixture-coupling deutsche Literale" (R-4/R-8-Patterns) und „Spec untracked → eingebettete Kommandos unverifiziert" (AD-3/Erhaltungs-Clains verifiziert true). Neu-Verhandlung des Frozen-Intents nötig: **Nein** (nur nicht-frozen Sektionen + abgeleiteter Code betroffen).
## Design Notes
**Warum §5.15 als eigene Sektion, nicht §3.2-Umbau?** §3.2 ist die Relevanz-Findungs-Mechanik (append-only etabliert, Story 3.8); die Routing-Tabelle ist die **Reconcile-Entscheidungs-Ebene darüber**. §5.15 schließt die Story-3.9-ACs als eigene Sektion, ohne bestehenden §3.2-/§5.9-/§5.10-Wortlaut umzubauen (Fugen-Identität, Re-Negotiation-Vermeidung — gleiche Präzedenz wie §5.14/Story 3.8).
**Die Routing-Tabelle ersetzt keine Mechanik, sie schließt die Entscheidungs-Reihenfolge.** Die vier Zellen existieren bereits verstreut; §5.15 macht daraus die **eine** exklusive Tabelle mit fester Prüf-Reihenfolge (analog §5.9-Abgrenzungs-Reihenfolge): erst bestehender Match prüfen (UPDATE), dann Neu-Anlage (CREATE), dann nicht klassifizierbar (ORPHAN/HOLD — fail-closed, Hold-Home Story 3.10), dann bereits vollständig repräsentiert (NO_OP — engere Auslegung). Keine fünfte Form, kein neues Prädikat, AD-16-Klassifikation bleibt Epic 4.
**Raw-Immutability-Guard ≠ INPUT_UNCOMMITTED.** Der §5.9-P2-Block schützt den **uncommitteten** Zustand (AD-17a, Working-Copy vs. HEAD). AC-4 adressiert den anderen Fall: eine **committete**, aber im Zuwachs-Befund **modifizierte/gelöschte** `raw/`-Datei — das verletzt AD-3 (raw/ immutable), unabhängig vom Commit-Zustand. Der Guard prüft den Zuwachs-Befund (`git diff --name-only <Baseline-Commit> -- raw/` + SHA-256-Record, §5.9 Pkt. 6 R-1) auf modifizierte/gelöschte Einträge und schlägt **vor jeder Mutation** fehl.
**Reservierte Zielpfade.** `index` und `log` sind strukturelle Bundle-Namen (`index.md`-Hierarchie, `log.md`-Typ, Vertrag §5/§6); ein Concept mit Identität `index`/`log` kollidiert mit der Struktur. Der Hold erzwingt eine disambiguierte Identität (z. B. Pfad-Erweiterung), schreibt **keine** Datei und meldet textuell benannt (NFR-4) — analog §5.8-Instruktions-Hold (Zwei-Ebenen).
**Termgewinnung geschlossen vs. Manifest.** Primär: determinstische Ableitung der geordneten Term-Liste aus der Zuwachs-Sicht (Datei-Reihenfolge → Einheiten-Ordnung, §5.9-R-1-Vorlage); die Liste wird Teil des Run-Receipts (AC-6/§5.14). Optional zulässig: ein committetes, persistiertes Term-Manifest als Run-Input (dann Teil des kanonischen Eingabemanifests). Beide schließen freie Producer-Auswahl (AC-1) und geben D-9 (Term-Ableitung) ausführbare Coverage.
## Verification
**Commands (re-executierbar, ab Workspace-Root):**
1. `bash _bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh` — expected: R-1..R-9 harte PASS/FAIL, R-1-Term-Ableitung gegengeprüft (kein hart kodierter Erwartungswert), R-4-Guard-Abbruch real (M/D → Exit 1), R-9-Bundle-byte-Identität (clean voll byte-identisch, atgap maskiert byte-identisch, divergent hart FAIL), Zwei-Run-Identität nicht-vakuum (getrennte Läufe, kein Ansatz des realen Baums), Exit 0.
2. `grep -n "§5.15\|Revision 3.4" schema/compiler.md` — §5.15-Sektion + Revisionslog-Eintrag; `grep -n "Deterministische Relevanz- & Reconcile-Routing" schema/compiler.md` — Überschrift wortgleich.
3. Read-only (AD-3): `git status --porcelain` zeigt keinen Change an `schema/validator.md`/`schema/wiki-compiler.md`/`adapters/`/`raw/`; `schema/canonical-terms.md` unverändert.
4. Validator-Lauf: alle `wiki/`-Dateien SUCCESS (keine Inhalts-Mutation); auf `wiki/` begrenzt (`git status --porcelain -- wiki/`): ausschließlich `wiki/log.md` — Erhaltungs-Invariante §5.9 Pkt. 5 gewahrt.
**Zu beachten (beim step-04-Review):** (a) bestehende §3/§5.9/§5.10/§5.14-Mechaniken **textuell unverändert** (Referenz statt Re-Negotiation — §5.15 verankert nur die Routing-/Guards-/Hold-Ebene); (b) der Hold-Home verbleibt Story 3.10 (post-Reconcile-Orphan in §5.10 Pkt. 8, Review-Loop-3-D-4); (c) die vorhandene Revisionslog-Nummer ist **3.3** (Story 3.8) — **Revision 3.4 ist für Story 3.9 frei**; (d) Umlaut-vs-Transkription-Defer bleibt offen (kein stiller Abschluss); (e) §5.15 führt **kein** neues Prädikat/keine neue §7-Klasse/keinen neuen Key ein.
## Suggested Review Order
**Design-Intent & Einstieg**
- Geschlossene Routing-Ebene als eine exklusive Entscheidungs-Tabelle (Story 3.9).
[`compiler.md:379`](../../schema/compiler.md#L379)
**Instruktions-Verankerung (§5.15)**
- Termgewinnung: deterministischer Algorithmus aus Zuwachs-Sicht, kein Producer-Urteil (AC-1).
[`compiler.md:383`](../../schema/compiler.md#L383)
- Eine exklusive Tabelle: UPDATE→CREATE→ORPHAN/HOLD→NO_OP in fester Prüf-Reihenfolge (AC-3).
[`compiler.md:385`](../../schema/compiler.md#L385)
- Leere Candidate-Liste → Zelle 2/3, niemals NO_OP; NO_OP nur Update-Unter-Entscheidung (BS-L2-1).
[`compiler.md:394`](../../schema/compiler.md#L394)
- Stufe-b-Zelle: Traversal-Kandidaten in derselben Tabelle, kein CREATE bei Dangling-Link.
[`compiler.md:395`](../../schema/compiler.md#L395)
- Raw-Immutability-Guard: committete M/D/R-`raw/`-Datei → Run-FAIL vor Mutation (AC-4).
[`compiler.md:396`](../../schema/compiler.md#L396)
- Reservierte Zielpfade index/log/source/README → deterministischer Hold, keine Anlage (AC-5).
[`compiler.md:397`](../../schema/compiler.md#L397)
- Zwei-Run-Identität: gegeneinander verglichen, nur `at`-Exzeption als benannte Differenz (AC-6).
[`compiler.md:398`](../../schema/compiler.md#L398)
**Anker-Synchronisierung**
- §3.2-Pkt.-3d-Anker: leere Candidate-Liste bei neuer Evidenz auf Zelle 2/3 nachgeführt.
[`compiler.md:63`](../../schema/compiler.md#L63)
- §5.14-Pkt.-5-Scope-Präzisierung: Story-3.9-ACs verankert, Vorbehalt aufgelöst.
[`compiler.md:377`](../../schema/compiler.md#L377)
- §7-Relevanzbestimmung-Bullet: „Story-3.9-ACs noch nicht verankert"-Vorbehalt aufgelöst.
[`compiler.md:457`](../../schema/compiler.md#L457)
- Revisionslog Revision 3.4 dokumentiert die §5.15-Gesamtverankerung.
[`compiler.md:501`](../../schema/compiler.md#L501)
**Ausführbare Verifikation (Sandbox R-1..R-9)**
- R-1: Term-Liste ableitungsbasiert gegengeprüft, kein hart kodierter Erwartungswert.
[`run-sandbox.sh:228`](sandbox-3-9/run-sandbox.sh#L228)
- R-1b: Status-Codes geschlossen — R→Guard-FAIL, C wie A akzeptiert (BS-L2-2).
[`run-sandbox.sh:233`](sandbox-3-9/run-sandbox.sh#L233)
- R-4: Guard-Abbruch real geübt — M/D-Befund endet mit Exit 1 vor jeder Mutation.
[`run-sandbox.sh:427`](sandbox-3-9/run-sandbox.sh#L427)
- R-5: Terme aus committetem Zuwachs abgeleitet, leere Liste → CREATE-Bewertungsraum (BS-L2-1).
[`run-sandbox.sh:539`](sandbox-3-9/run-sandbox.sh#L539)
- R-6: Ziel-Slug abgeleitet + Ist-Dateimenge via `git ls-tree`-Schnittmenge deterministisch.
[`run-sandbox.sh:572`](sandbox-3-9/run-sandbox.sh#L572)
- R-8: Hold-Befund deterministisch identisch über zwei getrennte Worktrees.
[`run-sandbox.sh:664`](sandbox-3-9/run-sandbox.sh#L664)
- R-9: BUNDLE-BYTE-Identität + praktisch ausgeübte at-Exzeption + Divergenz hart FAIL.
[`run-sandbox.sh:726`](sandbox-3-9/run-sandbox.sh#L726)
**Peripherie (Status & Rekonsiliation)**
- Sprint-Status: Story-3.9-Key auf `in-progress` (finaler `review`/`done`-Flip per Step-04/05).
[`sprint-status.yaml:62`](sprint-status.yaml#L62)
- Defers D-8/D-9: Mehrfach-Term-Vereinigung + Orphan-Term-Ableitung als `aufgegriffen` markiert.
[`deferred-work.md:553`](deferred-work.md#L553)
- epic-3-context: Technical Decision Z. 39 von Zielzustand auf §5.15-Ist nachgeführt.
[`epic-3-context.md:39`](epic-3-context.md#L39)
- wiki/log.md: Story-3.9-Eintrag (Verankerung + Sandbox-Nachweis) — Erhaltungs-Invariante gewahrt.
[`log.md:4`](../../wiki/log.md#L4)