--- 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: 3 context: - '_bmad-output/implementation-artifacts/epic-3-context.md' --- ## 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. `` | 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/umbenannt (M/D/**R**, §5.15 Pkt. 4) | Run-FAIL **vor jeder Mutation** (AD-3: keine modifizierte/gelöschte/umbenannte 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. 1–6); §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. 49–54, 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` → `review` (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach konvergiertem Review-Loop); `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:** - [x] `schema/compiler.md` — §5.15 einfügen (nach §5.14, vor §6): Pkt. 1–6 gemäß Intent; keine neuen Prädikate/§7-Klassen/Keys; §7-Vorbehalt und §8-Revisionslog **Revision 3.4** nachführen - [x] `_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh` — R-1..R-9, harte PASS/FAIL, Zwei-Run nicht-vakuum, Exit 0 - [x] `_bmad-output/implementation-artifacts/sprint-status.yaml` — Key 3-9 → `in-progress` (→ `review` im Impl-Commit; finaler `done`-Flip Step-05); `deferred-work.md` — D-8/D-9 aufgegriffen; `wiki/log.md` — Story-3.9-Eintrag (Verankerung, Sandbox, Validator-Verdikt) - [x] `_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-3 (2026-08-21, bmad-code-review Re-Run — 4 Layer, `full`-Modus):** Blind Hunter (2 Durchläufe) + Edge Case Hunter + Acceptance Auditor + Verification Gap (über Retry; kein ausgefallener Layer) gegen den Story-3.9-Impl-Commit (7 Dateien). **Triage: 3 decision-needed, 15 patch, 2 defer, 8 verworfen.** **Decision-Resolutionen (Nutzer „Ich folge Deinen Empfehlungen"):** **(D-3.9-1 → Option 1)** die retrospektive §8-Revision-3.3-Nachführung (`in-progress` → `done` für Key 3-8) wird **behalten** — faktisch korrekt (Story 3.8 ist done); Dokumentation über diesen append-only Change-Log statt frozen-Code-Map-Edit; kein Rückbau. **(D-3.9-2 → Option 1)** Status-Kontraktion aufgelöst auf die 3.7/3.8-Präzedenz: maßgeblich ist `review` (Impl-Commit-Flip); Frontmatter-`done` wird zurückgesetzt, der finale `done`-Flip erfolgt im Step-05-Status-Sync nach konvergiertem Loop; Revision-3.4-/Code-Map-/SRO-Wortlaut „`in-progress`" auf `review`-Ist korrigiert. **(D-3.9-3 → Option 2 Minimal-Härtung)** die tautologischen/echte-Mechanik-fehlenden Sandbox-Szenarien werden gehärtet (R-1 echtes `manifest_check`-Run-FAIL, R-1b Guard-Sub-Runs ohne kumulative-Baseline-Kontraktion, R-3 Fall-2 echte NO_OP-Containment-Prüfung + Fall-4 echte `index.md`-Link-Resolution, R-5 echte `route()`-Funktion über den CREATE/Bewertungsraum, R-6/R-7 Slug aus echter Ableitung ohne `-doc$`-Strip, R-8 Receipt aus echter Mechanik); die strukturellen Restlimits (volle Stufen-b/c-Traversal-Coverage, Zwei-Run über realen Contents statt Receipt-Literale) bleiben **benannte Defers** (Home Story 3.13, Präzedenz DET-1/2-Defer). **Patch-Liste (angewandt):** §5.15 Pkt. 1 (`/dev/null`-Sort → `LC_ALL=C`-byttreue Stable-Sortierung; Status-Code-Entflechtung Pkt. 1 ↔ Pkt. 4: Befund A/M/D/R/C, Akzeptanz A/C vs. Run-FAIL M/D/R); Pkt. 2 (Actor-Body → **Concept-Body**); Pkt. 5 (hängender „§3.2-Endergebnis"-Verweis → §5.8-Instruktions-Hold als Run-Status-Definition); Revision 3.4 (Status-Wortlaut `review` + Status-Code-Korrektur). Sandbox: Escaper-Fix (sed-Trenner-Kollision `|`, verifiziert: `v1.0` → stilles Nicht-Match) + quoting, `README`-Reserviertheits-Fall (case-insensitiv), R-9-Bundle-Grep-Anchorung (Area-Pfade nicht mehr still ausgeschlossen) + Benennung der index/log-Ausnahme, R-8-Hold-Assert auf beide Worktrees, Worktree-Re-Run-Idempotenz (unter `$ROOT`), `local rc=$?`-Dead-Diagnostics, Term-Quoting + `sort -u`. Peripherie: I/O-Matrix-`RAW_GUARD_MODIFIZIERT`-Zeile um Rename (M/D/**R**); ``-Schließtag nach diesem Change Log ergänzt (Präzedenz Spec-3-7/3-8 — fehlender Tag ließ 7 Sektionen de facto frozen-intern liegen); `sprint-status.yaml` `last_updated`-Format `MM-DD-YYYY HH:MM`; `deferred-work.md` D-9-Aufgegriffen-Text auf den tatsächlich ausgeübten Umfang präzisiert (Stufe-a, Root-Glob); `wiki/log.md` 2026-08-21-Eintrag mit echtem Validator-Verdikt. **Frozen-Änderungen (dieser Eintrag autorisiert, dokumentiert im Frozen-Block):** I/O-Matrix-`RAW_GUARD_MODIFIZIERT`-Zelle (Rename-Nachführung — AC-4/BS-L2-2-Konsequenz, kein AC-Wortlaut-Wechsel) + Schließtag-Nachtrag. **Neu-Verhandlung des Frozen-Intents nötig: Nein** (keine AC-/Intent-Wortlaute geändert; die I/O-Zelle führt den bereits in §5.15 Pkt. 4 verankerten R-Status in die Matrix nach). **Korrektur-Postscript (2026-08-21, Re-Verifikation während der Patch-Anwendung):** der oben genannte „Escaper-Fix (sed-Trenner-Kollision `|`)" ist ein **Fehlalarm (P-3.9-1 verworfen)** und wurde **nicht** angewandt — die „Ausführung"-Evidenz des Verification-Gap-Layers war durch die Bash-Tool-Transport-Schicht korrumpiert (Backslash-Ebene halbiert, getesteter Code ≠ Datei-Code). Definitive Gegenprüfung (od-Beweis: Datei-Z. 74/790 enthalten `\\&`; Negativ-/Positiv-Kontrolle aus Datei-Bytes: `v1.0` matcht `v10`-Body **nicht** und `v1.0`-Body **ja**) belegt: der Escaper ist literal-sicher, `run-sandbox.sh` Z. 74/790 bleiben unverändert. Die anzuwendenden Pflaster reduzieren sich damit auf 14 (von 15); die übrigen Patch-Positionen dieses Eintrags gelten unverändert. - **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 ``). **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. 462–467) 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. 574–575 — 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 (F1–F10):** **(F1–F4, F6, F10, reject):** die §5.15-Pkt.-3-Tabelle (Z. 385–395) 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. 669–672, 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. 1–6), §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 ``). **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). *Appendix (Review-Loop-3, 2026-08-21, autorisiert im Change-Log-Eintrag oben): fehlendes ``-Schließtag nach dem Spec Change Log ergänzt (Präzedenz Spec-3-7 Z. 76 / Spec-3-8 Z. 166 — der Change Log liegt frozen-intern als Frozen-Änderungsdoku; Design Notes/Verification/Suggested Review Order wieder außerhalb des Frozen-Blocks). Kein frozen-interner Wortlaut wurde verändert, außer der im Change-Log dokumentierten I/O-Matrix-`RAW_GUARD_MODIFIZIERT`-Zellen-Nachführung.* ## 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 -- 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 `review` (finaler `done`-Flip per Step-05-Status-Sync nach konvergiertem Review-Loop). [`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) ### Review Findings *Review-Loop-3 (bmad-code-review, `full`-Modus) — 4 Layer (Blind Hunter ×2, Edge Case Hunter, Acceptance Auditor; Verification Gap über Retry). Triage: 3 `decision-needed`, 15 `patch` (davon 1 verworfen → **14 anzuwenden**), 2 `defer`, 8 verworfen (zusätzlich 1 patch-Finding nach Re-Verifikation verworfen → **9 verworfen**). Code-Vorab-Lektüre: `run-sandbox.sh` R-1..R-9 (vollständig), `compiler.md` §3.2/§5.14/§5.15/§8, Spec-Frontmatter/I/O-Matrix/Change-Log/Code-Map, `deferred-work.md` D-8/D-9, `wiki/log.md` 3.9-Eintrag.* **Decision-Needed** - [x] [Review][Decision] **D-3.9-1 — §8-Revision-3.3 retrospektiv mitumgeschrieben (außerhalb Code-Map-Scope, historische Story-3.8-Eintrag umgeformt).** [`compiler.md:500`] Der Diffformt die bereits committete **Revision 3.3** (Story 3.8) um: die `sprint-status.yaml`-Stelle wechselt von „Key 3-8 … `in-progress` (finaler `review`/`done`-Flip im Step-04/05)" zu „Key 3-8 … **`done`** (2026-08-20: …)". Das ist (a) außerhalb der Code Map (nur §5.15 + §7 + **Revision 3.4** + §3.2-Anker sind deklariert) und (b) eine Umformung eines historischen Revisionslog-Eintrags einer anderen Story. `sprint-status.yaml` Z. 61 trägt tatsächlich `done`, aber ob die Historik-Eintrag-Revision zulässig ist, ist eine Intent-Entscheidung. **Optionen:** 1) Revision-3.3-Änderung behalten (3.8 ist faktisch done) + Code Map um „§8-Revision-3.3-Nachführung" ergänzen; 2) Revision 3.3 auf den ursprünglichen Wortlaut zurücksetzen (Status-Nachführung gehört ausschließlich nach Revision 3.4 / sprint-status). - [x] [Review][Decision] **D-3.9-2 — Status-Kontraktion über die Diff-Artefakte (welcher Status ist für den 3-9-Key maßgeblich?).** [`spec frontmatter:5`, `sprint-status.yaml:62`, `compiler.md:501`] Vier Artefakte sagen vier Dinge über den 3-9-Key: Spec-Frontmatter `status: 'done'`; Suggested-Review-Order + Revision 3.4 „Key … **`in-progress`** (finaler `review`/`done`-Flip im Step-04/05)"; `sprint-status.yaml` Z. 62 **`review`**. Konsistente Lektüre: der Implementierungs-Commit hat `review` gesetzt (Review-Start), der finale `done`-Flip gehört erst nach diesem Review (Step-05). **Optionen:** 1) Frontmatter auf `in-progress` zurücksetzen, Sprint-Status `review` bleibt bis zum Step-05-`done`-Flip (konsistent mit Story 3.7/3.8-Präzedenz „finaler Flip im Step-05"); 2) alles auf `done` ziehen (Review als abschließend betrachten) — braucht aber die D-3.9-1-/Patch-Auflösung vorher. - [x] [Review][Decision] **D-3.9-3 — Sandbox-Re-Build-Tiefe: die Loop-2-Auflagen haben 11 defekte/tautologische Verifikationen hinterlassen.** [`run-sandbox.sh` R-1..R-9] Die Loop-2-Mandate (BS-L2-1a, P-L2-1..P-L2-6, D-L2-1/2) wurden formal umgesetzt, aber die resultierenden Szenarien üben die pinnte Instruktion **nicht real** aus — sie vergleichen handgeschriebene Werte mit sich selbst. Verifizierte Kern-Mängel: **R-1** Negativ-Manifest = String-Ungleichheit, der Run-FAIL-vor-Mutation-Pfad wird nie gefeuert; **R-1b/R-4** kumulatives `ST_*`-Diff gg. B1 enthält selbst R/M/D, assertet aber „Guard passiert" (Widerspruch zu §5.15 Pkt. 4, R = Guard-FAIL); **R-3** Fall-2 = 2-Wort-Präfix-Check auf eigens überlappendem Body, Stufe-b `STUFE_B_CAND="verwaister-concept"` wird mit sich selbst verglichen; **R-5** `ROUTE_ZETA="CREATE"` dann `[ "$ROUTE_ZETA" = "CREATE" ]` (Tautologie, kein Routing-Code; leere Candidate-Liste → NO_OP-Regression bliebe unsichtbar) + nur Primär-Terme (keine D-8-Vereinigung); **R-6/R-7** hart codiertes `printf 'index-doc'` + nicht-instruktionelle `sed 's/-doc$//'`; **R-8** Receipt wird von Hand gebaut (A/B-Identität garantiert), tote-CAND-Assert gegen nie geschriebene Datei; **R-9** at-Exzeption prüft zwei vom Run selbst geschriebene Konstanten auf Ungleichheit. Das ist kein einzelnes Pflaster, sondern die **Tiefe des Re-Builds** (minimale harte Feuern je Szenario vs. vollständige Re-Implementierung der Routing-/Guard-/Traversal-Mechanik in der Sandbox). **Optionen:** 1) **Voll-Re-Build** — jedes Szenario führt die echte Mechanik aus (Escaper, Guard-Sub-Run mit realer `git mv`/`rm`, Routing-Code statt Literal, Traversal-Stufe), negative Kontrollen feuern real; 2) **Minimal-Härtung** — nur die hartcodierten Tautologien (R-3/R-5/R-8) in echte Vergleichs-Feuern umbauen, Rest als benannte Sandbox-Defer; 3) **Scope-Split** — Re-Build als eigene Folge-Story (3.9.x / 3.10-Vorbereitung), Story 3.9 mit Defer-Liste abschließen. *(Die konkreten, eigenständig fixierbaren Pflaster — Escaper, README, R-9-Bundle-Grep, R-8-Grep, I/O-Matrix, u. a. — sind als `patch`-Findings separat gelistet und unabhängig von dieser Entscheidung anwendbar.)* **Patch** - [x] [Review][Patch] **P-3.9-1 — Escaper defekt: `sed 's|[][\.*^$+?(){}|]|\\&|g'` nutzt `|` als Trenner UND als Klassen-Mitglied → Metacharaktäre werden nicht escapet.** [`run-sandbox.sh:74`, `run-sandbox.sh:790`] **VERWORFEN (Fehlalarm) — nach Re-Verifikation am 2026-08-21.** Ursprüngliche Begründung („durch Ausführung verifiziert: `v1.0` → `v1&0`"): die „Ausführung" tippte das sed-Programm direkt in Bash-Befehle; die Tool-Transport-Schicht halbiert dabei Backslash-Ebenen (eingegebenes `\\&` ankam als `\&` = Literal-`&`-Ersetzung, **ohne** Backslash) — der getestete Code war damit **nicht** der Datei-Code. **Definitive Gegenprüfung (2026-08-21):** (a) `od -c` auf `run-sandbox.sh` Z. 74/790 belegt: die Datei enthält `\\&` (Zwei-Backslash-Sequenz) — korrektes GNU-sed-Programm; das `|` innerhalb der Klammer-Klasse ist ein literaler Klassen-Mitglied und beendet die Klasse nicht (die Klasse schließt sich am zweiten `]`); (b) Negativ-/Positiv-Kontrolle ausgeführt **aus den Datei-Bytes selbst** (Funktionen via `source` extrahierter Zeilen, keine Neubeeingabe): `match_stufe_a("v1.0", Body-`foo v10 bar`)` → **leer** (kein falsches Match trotz fehlendem Punkt — die `\.`-Escapage wirkt), `match_stufe_a("v1.0", Body-`foo v1.0 bar`)` → **Treffer** (Escape bricht echte Treffer nicht). **Fazit: Escaper ist literal-sicher, Z. 74/790 bleiben unverändert; keine Sandbox-Term-Änderung nötig.** Konsequenz: die im Loop-3-Change-Log genannte „Escaper-Fix" wurde NICHT angewandt (siehe Korrektur-Postscript des Eintrags); die Patch-Anwendungszahl sinkt von 15 auf 14. - [x] [Review][Patch] **P-3.9-2 — Reserviertheits-Check `case "$TARGET_SLUG" in index|log|source|README)` case-sensitiv, aber `TARGET_SLUG` ist immer lowercased → `README` ist unerreichbar.** [`run-sandbox.sh:591`, `run-sandbox.sh:635`] Ein CREATE mit Ziel `wiki/readme.md` (abgeleitet, lowercased) kollidiert mit dem reservierten Bundleroot-`README.md` (AC-5), wird aber nicht erwischt. Fix: Vergleich case-insensitiv machen (beide Seiten lowercased) bzw. `readme` in die Liste. - [x] [Review][Patch] **P-3.9-3 — §5.15 Pkt. 1: „die Ausgabe erfolgt deterministisch über `/dev/null`-Stable-Sortierung" ist inkoherent (ungenannter Mechanismus; die Sandbox nutzt `LC_ALL=C sort`).** [`compiler.md:383`] Fix: auf den konkreten, deterministischen Sort-Mechanismus verweisen (z. B. „stable Sortierung nach bytetreuer Kollation (C-Locale)"), `/dev/null`-Begriff entfernen. - [x] [Review][Patch] **P-3.9-4 — §5.15 Pkt. 5: „Run „teilweise erfolgreich" gemäß §3.2-Endergebnis" ist ein hängender Verweis (einzige „Endergebnis"-Stelle; das Run-Status-Konzept lebt in §3-Kollision-Hold Rev 1.4 / §5.8).** [`compiler.md:397`] Fix: Verweis auf die tatsächliche Run-Status-Definition (§5.8-Instruktions-Hold / §3-Kollision-Hold) korrigieren. - [x] [Review][Patch] **P-3.9-5 — §5.15 Pkt. 2: Tippfehler „kein Regex-Muster über den *Actor*-Body hinaus" → „Concept-Body" (normativ, nicht nur dekorativ).** [`compiler.md:384`] - [x] [Review][Patch] **P-3.9-6 — §5.15 Pkt. 1 Status-Code-Wortlaut selbstwidersprüchlich: „Status-Codes `A`/`M`/`D` — `--diff-filter=ACMR` liefert die akzeptierten Zuordnungen (… **R** = umbenannt; die Zuordnung fallspezifisch in Pkt. 4)" vermischt R in „akzeptiert", während Pkt. 4 M/D/R = Run-FAIL definiert.** [`compiler.md:383` vs `compiler.md:396`] Fix: Pkt. 1 so präzisieren, dass die `--diff-filter=ACMR`-Liste den *Befund* beschreibt und die A/C-vs-M/D/R-Zuordnung eindeutig auf Pkt. 4 verweist (R/C nicht als „akzeptiert" im Pkt.-1-Satz). - [x] [Review][Patch] **P-3.9-7 — R-9-Bundle-Vergleich: `grep -vE '/?(index|log)\.md$'` unanker → schließt neben index.md/log.md (bewusst, aber unbenannt) zusätzlich **jeden Basenamen, der *auf* `index.md`/`log.md` ENDET** (z. B. `myindex.md`, `prelog.md`) still aus dem „byte-identische mutierte Bundle-Bestandteile"-Vergleich aus.** [`run-sandbox.sh:856`] *(Re-Scope 2026-08-21: die Original-Finding-Formulierung „schließt JEDEN `wiki//…`-Pfad still aus" ist falsch — der Muster `/?(index|log)\.md$` matcht ausschließlich Pfade, deren letztes Segment exakt oder -präfixhaft `index.md`/`log.md` endet; normale Area-Concepts wie `wiki//begriff-x.md` bleiben im Vergleich. Der reale Defekt ist die Über-Ausschluss-Menge (Enden-Präfixe) + das unbenannte Bewusstsein.)* Eine Divergenz in einer falsch-geschnittenen Datei wäre unsichtbar (AC-6/A0-19). Fix: anchorn auf `(^|/)(index|log)\.md$` + Kommentar, der die index/log-Ausnahme explizit benannt. - [x] [Review][Patch] **P-3.9-8 — R-8: Hold-Befund-`grep` nur gegen `wt-hold-a`, nicht gegen `wt-hold-b` (Zwei-Worktree-Hold soll Identität über BEIDE belegen).** [`run-sandbox.sh:719-720`] Fix: Hold-Bullet-Assertion auf beide Worktrees ausdehnen. - [x] [Review][Patch] **P-3.9-9 — I/O-Matrix-Zeile `RAW_GUARD_MODIFIZIERT` nennt nur „modifiziert/gelöscht" und lässt Rename (R) aus, das §5.15 Pkt. 4 als Guard-FAIL definiert.** [`spec I/O-Matrix`] Fix: „modifiziert/gelöscht/umbenannt (M/D/R)" in die Zeile aufnehmen. - [x] [Review][Patch] **P-3.9-10 — ``-Block (öffnet Z. 12) ist nie geschlossen — alle 7 folgenden Sektionen fallen de facto in den Frozen-Block.** [`spec:12`] Konvention der Geschwister-Specs 3-7 (Z. 76) und 3-8 (Z. 166): Schließtag **nach dem Spec Change Log**. Fix: `` nach dem Change-Log-Bullet (vor „## Design Notes") ergänzen. - [x] [Review][Patch] **P-3.9-11 — `sprint-status.yaml` `last_updated: 08-21-2026` trägt das Code-Map-Format `MM-DD-YYYY HH:MM` nicht (HH:MM fehlt).** [`sprint-status.yaml:32`] - [x] [Review][Patch] **P-3.9-12 — `deferred-work.md` D-9-„aufgegriffen"-Text überzeichnet: „scannt den VOLLEN Kandidaten-Baum (`wiki/*.md`-Glob)" bzw. „Stufen a/b/c", aber R-5 scannt nur Stufe-a über den Root-`wiki/*.md`-Glob (keine Stufen b/c, keine Area-Rekursion).** [`deferred-work.md:554`] Fix: Aufgegriffen-Text auf den tatsächlich ausgeübten Umfang (Stufe-a, Root-Glob) präzisieren; Rest (Stufen b/c) als verbleibenden Defer benannen. - [x] [Review][Patch] **P-3.9-13 — `wiki/log.md` Story-3.9-Eintrag (Z. 4) trägt das von Spec-Task-Z. 68 / Verification-Cmd-4 verlangte explizite „Validator-Verdikt: alle `wiki/`-Dateien SUCCESS" nicht (nur Verankerung + Sandbox-Nachweis + Erhaltungs-Invariante).** [`wiki/log.md:4`] - [x] [Review][Patch] **P-3.9-14 — Worktrees `wt-hold-a/b` (R-8) und `wt-a/b/n/at` (R-9) werden AUSSERHALB der `isolate`-Verzeichnisse unter `$ROOT` angelegt → Re-Run über ein veraltetes `$ROOT` schlägt fehl (idempotente Re-Executierbarkeit fehlt).** [`run-sandbox.sh:664-665`, `run-sandbox.sh:763-766`] - [x] [Review][Patch] **P-3.9-15 — `local rc=$?` nach barem Subshell unter `set -e` (R-8 `hold_run`, R-9 `run9_worktree`) → die benannte HARD-FAIL-Diagnostik ist unerreichbar (tote Diagnostics; Hauptskript bricht trotzdem über `set -e` ab, also kein false-PASS, aber die geführte Fehlermeldung druckt nie).** [`run-sandbox.sh:694`, `run-sandbox.sh:867`] Fix: `rc` direkt nach dem Subshell-Ausdruck erfassen bzw. den Abbruch-Pfad ohne tote Variable formulieren. **Defer** - [x] [Review][Defer] **W-3.9-1 — `norm()`/`tr` ohne `LC_ALL`-Pinning: unter C/POSIX-Locale zerfällt die Byte-Klasse `[–—]` und `tr 'A-Z' 'a-z'` ist locale-abhängig → Kanon-Form hängt am Host-Locale.** [`run-sandbox.sh:53-61`] — deferred, bekannt (Story-3.8-Defer D-7), Scope jetzt auf den kompletten 952-Zeilen-Sandbox-3.9 ausgeweitet. - [x] [Review][Defer] **W-3.9-2 — Positive Zwei-Run-Identität (R-9 clean A==B) ist strukturell trivial: Plan-/Form-Literale sind Skript-Konstanten, die Nicht-Vakuum-Last tragen die echten Content-Hashes + Negativ-Kontrolle.** [`run-sandbox.sh:771-869`] — deferred, Präzedenz DES Story-3.8-Defer „DET-1/DET-2-Plan-Literale" (Home: Story-3.13-Abnahme, echte Gate-Runs).