Files
wow20/_bmad-output/implementation-artifacts/spec-3-9-deterministische-relevanz-und-reconcile-routing-schliessen.md
T
Michael TamseandClaude 8c43d3a09c feat: Story 3.9 Review-Loop-3-Abschluss (bmad-code-review, 4 Layer; kein Loopback)
- 3 Decision-Resolutionen (D-3.9-1/2/3 = Option 1/1/2 — empfohlene Optionen)
- 14 Patches angewandt (von 15): P-3.9-1 Escaper-„Fehlalarm" verworfen — die
  „Ausführungs"-Evidenz war durch die Bash-Tool-Transport-Schicht korrumpiert
  (Backslash-Ebene halbiert); od-Beweis + Negativ/Positiv-Kontrolle aus
  Datei-Bytes belegen: Escaper literal-sicher, run-sandbox.sh Z. 74/790 unverändert
- 2 Defers (Home Story 3.13, Präzedenz DET-1/2), 9 verworfen
- Sandbox Minimal-Härtung (D-3.9-3 Option 2): R-1..R-9 mit echter feuernder
  Mechanik + echten Negativ-Kontrollen; Exit 0 auf frischem /tmp-Root,
  Re-Run-Idempotenz bestätigt
- compiler.md §5.15 (Pkt. 1/2/5 + Revision 3.4-Wortlaut), I/O-Matrix M/D/R,
  frozen-Schließtag + I/O-Zelle (Change-Log-autorisiert, keine Neu-Verhandlung)
- AD-3 read-only & wiki/-Erhaltungs-Invariante verifiziert (Validator SUCCESS)
- sprint-status 3-9 → done; Step-05 Status-Sync + Step-06 Abschluss

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

52 KiB
Raw Blame History

title, type, created, status, baseline_commit, review_loop_iteration, context
title type created status baseline_commit review_loop_iteration context
Story 3.9 — Deterministische Relevanz- und Reconcile-Routing schließen feature 2026-08-20 done 2f079ee3c8 3
_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. <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/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.mdprimä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.shneu (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.yamlmutiert: Key 3-9-deterministische-relevanz-und-reconcile-routing-schliessen backlogreview (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.mdappend: 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.mdappend (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.mdmutiert (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 (→ 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)
  • _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-progressdone 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); </frozen-after-approval>-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 <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).

Appendix (Review-Loop-3, 2026-08-21, autorisiert im Change-Log-Eintrag oben): fehlendes </frozen-after-approval>-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 <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

Instruktions-Verankerung (§5.15)

  • Termgewinnung: deterministischer Algorithmus aus Zuwachs-Sicht, kein Producer-Urteil (AC-1). compiler.md:383

  • Eine exklusive Tabelle: UPDATE→CREATE→ORPHAN/HOLD→NO_OP in fester Prüf-Reihenfolge (AC-3). compiler.md:385

  • Leere Candidate-Liste → Zelle 2/3, niemals NO_OP; NO_OP nur Update-Unter-Entscheidung (BS-L2-1). compiler.md:394

  • Stufe-b-Zelle: Traversal-Kandidaten in derselben Tabelle, kein CREATE bei Dangling-Link. compiler.md:395

  • Raw-Immutability-Guard: committete M/D/R-raw/-Datei → Run-FAIL vor Mutation (AC-4). compiler.md:396

  • Reservierte Zielpfade index/log/source/README → deterministischer Hold, keine Anlage (AC-5). compiler.md:397

  • Zwei-Run-Identität: gegeneinander verglichen, nur at-Exzeption als benannte Differenz (AC-6). compiler.md:398

Anker-Synchronisierung

  • §3.2-Pkt.-3d-Anker: leere Candidate-Liste bei neuer Evidenz auf Zelle 2/3 nachgeführt. compiler.md:63

  • §5.14-Pkt.-5-Scope-Präzisierung: Story-3.9-ACs verankert, Vorbehalt aufgelöst. compiler.md:377

  • §7-Relevanzbestimmung-Bullet: „Story-3.9-ACs noch nicht verankert"-Vorbehalt aufgelöst. compiler.md:457

  • Revisionslog Revision 3.4 dokumentiert die §5.15-Gesamtverankerung. compiler.md:501

Ausführbare Verifikation (Sandbox R-1..R-9)

  • R-1: Term-Liste ableitungsbasiert gegengeprüft, kein hart kodierter Erwartungswert. run-sandbox.sh:228

  • R-1b: Status-Codes geschlossen — R→Guard-FAIL, C wie A akzeptiert (BS-L2-2). run-sandbox.sh:233

  • R-4: Guard-Abbruch real geübt — M/D-Befund endet mit Exit 1 vor jeder Mutation. run-sandbox.sh:427

  • R-5: Terme aus committetem Zuwachs abgeleitet, leere Liste → CREATE-Bewertungsraum (BS-L2-1). run-sandbox.sh:539

  • R-6: Ziel-Slug abgeleitet + Ist-Dateimenge via git ls-tree-Schnittmenge deterministisch. run-sandbox.sh:572

  • R-8: Hold-Befund deterministisch identisch über zwei getrennte Worktrees. run-sandbox.sh:664

  • R-9: BUNDLE-BYTE-Identität + praktisch ausgeübte at-Exzeption + Divergenz hart FAIL. run-sandbox.sh:726

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

  • Defers D-8/D-9: Mehrfach-Term-Vereinigung + Orphan-Term-Ableitung als aufgegriffen markiert. deferred-work.md:553

  • epic-3-context: Technical Decision Z. 39 von Zielzustand auf §5.15-Ist nachgeführt. epic-3-context.md:39

  • wiki/log.md: Story-3.9-Eintrag (Verankerung + Sandbox-Nachweis) — Erhaltungs-Invariante gewahrt. log.md:4

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

  • [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).
  • [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.
  • [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

  • [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.0v1&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.
  • [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.
  • [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.
  • [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.
  • [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]
  • [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).
  • [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/<area>/…-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/<area>/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.
  • [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.
  • [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.
  • [Review][Patch] P-3.9-10 — <frozen-after-approval>-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: </frozen-after-approval> nach dem Change-Log-Bullet (vor „## Design Notes") ergänzen.
  • [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]
  • [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.
  • [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]
  • [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]
  • [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

  • [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.
  • [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).