diff --git a/_bmad-output/implementation-artifacts/deferred-work.md b/_bmad-output/implementation-artifacts/deferred-work.md
index c40d81a..3d25ec2 100644
--- a/_bmad-output/implementation-artifacts/deferred-work.md
+++ b/_bmad-output/implementation-artifacts/deferred-work.md
@@ -550,6 +550,6 @@ Noch nicht adressierte, aber real erkannte Arbeit — gesammelt aus Reviews. Ein
- **Sandbox-Härtungs-Guards (8 Befunde):** `mktemp` (Z. 37), `git init` (Z. 41), Baseline-Commit (Z. 94-96), `isolate()`-Sequenz (Z. 104-107), fehlende Match-Datei (Z. 136-141), verwaiste unregistrierte Worktree-Verzeichnisse (Z. 243-244) und Porcelain-Pfade mit Leerzeichen (`awk '{print $2}'`, Z. 217/682) tragen keine Fehler-Guards; ein Fehlgeschlagener init-Schritt lässt einen späteren „PASS" auf kaputtem Zustand drucken. — Defer-Grund: Testharness-Robustheit, keine normative Instruktion-Semantik; Re-Run-Risiko dokumentiert. Home: nächste Sandbox-Revision. — status: offen
- **DET-1/DET-2-Plan-/Form-Literale vs. AC-5 „nicht hart codiert":** `plan=$(printf 'cand=alpha;form=update;baseline=%s')` (run-sandbox.sh:189) und `echo "form=update"` in `bs_a()` (Z. 221) sind wörtliche Skript-Konstanten; B1==B2-Identität damit trivial. — Defer-Grund: Loop-1-/Loop-2-Präzedenz (Loop-1 hat „DET-2-Plan-Literal (dev-demo, echte Content-Hashes decken)" rejected; DET-1 trägt den Demo-Kommentar Z. 211-214); die Nicht-Vakuum-Assertion tragen die echten Content-Hashes. Home: Story-3.13-Abnahme (echte Gate-Runs über die Instruktion). — status: offen
- **`norm()`-Locale-Pinning (`LC_ALL`) fehlt:** unter C/POSIX-Locale zerfällt die Byte-Klasse `[–—]` in {E2,80,93,94} (übermatcht z. B. `…`/`„`), `tr 'A-Z' 'a-z'` ist locale-abhängig → die Kanon-Form hängt am Host-Locale statt am committeten Git-State. — Defer-Grund: Testharness-Host-Locale-Abhängigkeit (Host = Ubuntu-Sandbox, dort UTF-8-Default; auf C-Locale-Hosts falsch), keine normative Semantik der Instruktion. Home: Sandbox-Härtung (gemeinsam mit den Hards-Guards). — status: offen
-- **Mehrfach-Term-Vereinigung unübend:** §3.2 Pkt. 1c/§5.14 Pkt. 5 pinnen die Vereinigung der Treffer über alle Terme (besuchte Menge, Zuwachs-Sicht-Ordnung) als „vollständig pinbar" — die Sandbox übt nur den Einzel-Term-Pfad; eine Regressions in Union-/Dedup-/visited-Set-Logik würde unbemerkt durchgehen. — Defer-Grund: Story-3.8-Scope (Bestätigungs-Mechanik + Lückenschließung) ist erfüllt; ausführbare Union-Coverage gehört zur deterministischen Term-Gewinnung/Routing. Home: Story 3.9. — status: offen
-- **Orphan-Term hand-gesteuert + feste 2-Datei-Scan:** DET-8 pinnen den Term `fremdes` und scannen nur `wiki/alpha.md wiki/gamma.md` (run-sandbox.sh:669); die Determinismus der Orphan-ermittlung (Term-Ableitung aus dem `raw/`-Zuwachs, voller Kandidaten-Scan über Stufen a/b/c) ist nicht ausgeübt — nur die Log-Seite wird hart assertiert. — Defer-Grund: Mechanik ist textuell korrekt (DET-8-Assertions Z. 688-692 solide); Term-Derivation ist Story-3.9-AC („geschlossener, geordneter Algorithmus oder persistiertes Term-Manifest"). Home: Story 3.9. — status: offen
+- **Mehrfach-Term-Vereinigung unübend:** §3.2 Pkt. 1c/§5.14 Pkt. 5 pinnen die Vereinigung der Treffer über alle Terme (besuchte Menge, Zuwachs-Sicht-Ordnung) als „vollständig pinbar" — die Sandbox übt nur den Einzel-Term-Pfad; eine Regressions in Union-/Dedup-/visited-Set-Logik würde unbemerkt durchgehen. — Defer-Grund: Story-3.8-Scope (Bestätigungs-Mechanik + Lückenschließung) ist erfüllt; ausführbare Union-Coverage gehört zur deterministischen Term-Gewinnung/Routing. Home: Story 3.9. — **status: offen → aufgegriffen (Story 3.9, 2026-08-20):** in `schema/compiler.md` §5.15 Pkt. 1 verankert (Mehrfach-Term-Vereinigung D-8: kollabierter Gesamt-Name als primärer Term + jedes ≥2-Zeichen-Segment als weiterer Term; Einzelzeichen-Segmente -a/-b tragen keinen eigenen Term); Sandbox R-1 übt die Vereinigung real aus (`beta-kommunikation` → `beta beta-kommunikation kommunikation`, Sidecar-exkludiert, Diff↔Manifest-Äquivalenz)
+- **Orphan-Term hand-gesteuert + feste 2-Datei-Scan:** DET-8 pinnen den Term `fremdes` und scannen nur `wiki/alpha.md wiki/gamma.md` (run-sandbox.sh:669); die Determinismus der Orphan-ermittlung (Term-Ableitung aus dem `raw/`-Zuwachs, voller Kandidaten-Scan über Stufen a/b/c) ist nicht ausgeübt — nur die Log-Seite wird hart assertiert. — Defer-Grund: Mechanik ist textuell korrekt (DET-8-Assertions Z. 688-692 solide); Term-Derivation ist Story-3.9-AC („geschlossener, geordneter Algorithmus oder persistiertes Term-Manifest"). Home: Story 3.9. — **status: offen → aufgegriffen (Story 3.9, 2026-08-20):** Sandbox R-5 leitet die Terme AUS dem committeten `raw/`-Zuwachs ab (`git diff --name-only HEAD~1 -- raw/`, Dateiname→Term) und scannt den VOLLEN Kandidaten-Baum (`wiki/*.md`-Glob) statt eines festen 2-Datei-Scans — Orphan-/CREATE-Term-Derivation mechanisch ausgeübt (D-9; §5.15 Pkt. 1)
- **Umlaut-vs-Transkription im Match-Pfad unübend:** die §3.2-Normalisierung deckt Umlaut-Divergenzen („Schlüssel" vs. „Schluessel") nicht ab, und kein DET-Szenario treibt einen Umlaut-Term durch den Match-Pfad. — Defer-Grund: bereits „Aufgegriffen (teilweise)" dokumentiert (Block oben, Home: Sandbox-Vereinheitlichung oder folgende Compiler-Instruktions-Revision; „kein Instruktions-Defekt") — keine neue offene Frage, nur fehlende Sandbox-Abdeckung. Home: wie dort. — status: offen
diff --git a/_bmad-output/implementation-artifacts/epic-3-context.md b/_bmad-output/implementation-artifacts/epic-3-context.md
index 3e743f7..9367c7e 100644
--- a/_bmad-output/implementation-artifacts/epic-3-context.md
+++ b/_bmad-output/implementation-artifacts/epic-3-context.md
@@ -36,7 +36,7 @@ Der Compiler verarbeitet neues Source Material gegen das bestehende Knowledge Bu
- **Inkrementeller Datenfluss (AD-5, A0-6):** Interpret → Reconcile → Synthesize → Update affected Concepts. Startpunkt ist immer das bestehende Bundle — niemals "Regenerate Everything" (SM-1, FT-6).
- **Reason/Mutate-Trennung (AD-6, A0-7):** Logische Phasen Analyse → Reconcile → Plan Changes → Mutate → Validate. Keine eigene Workflow Engine; ein Agent kann die Phasen in einer Session durchführen, der beobachtbare Endzustand des Bundles muss auch bei Abbruch konsistent sein.
-- **Deterministische Relevanz & Routing (A0-18):** Geschlossene, geordnete Term-Gewinnung bzw. explizites persistiertes Term-Manifest; Suchterm und Concept-Body werden identisch normalisiert und literal-sicher verglichen. Eine exklusive Routing-Tabelle unterscheidet `UPDATE`, `CREATE`, `ORPHAN/HOLD` und echten `NO_OP`; gleicher Git-State plus gleiches Eingabemanifest erzeugt dieselbe Candidate-Liste und Reihenfolge. *Zielzustand (Review-Loop-3, P-11): geplant für Story 3.9 (Sprint-Change-Proposal 2026-08-20) — noch nicht in `schema/compiler.md` verankert; §3.2 ist bis dahin der maßgebliche Regeltext.*
+- **Deterministische Relevanz & Routing (A0-18):** Geschlossene, geordnete Term-Gewinnung bzw. explizites persistiertes Term-Manifest; Suchterm und Concept-Body werden identisch normalisiert und literal-sicher verglichen. Eine exklusive Routing-Tabelle unterscheidet `UPDATE`, `CREATE`, `ORPHAN/HOLD` und echten `NO_OP`; gleicher Git-State plus gleiches Eingabemanifest erzeugt dieselbe Candidate-Liste und Reihenfolge. *Ist (Story 3.9, 2026-08-20): in `schema/compiler.md` **§5.15** verankert (Termgewinnung geschlossen, eine exklusive Routing-Tabelle, Raw-Immutability-Guard, reservierte Zielpfade, Zwei-Run-Identität; §3.2 bleibt Erhebungs-Anker, §5.15 Pkt. 3 die Routing-Zuordnung).*
- **Keine eigene LLM-Runtime:** Der ausführende agentische Host orchestriert den AD-17-Ablauf (Lease holen, innerhalb des geleasten Bereichs mutieren, committen, freigeben); keine separaten Prozesse oder ein Server (AD-11).
- **Atomare Root-Scope-Lease (AD-17a/b, A0-12/13):** Producer behalten die Branch-Konvention `lease//`, akquirieren aber genau einen atomaren, scope-bezogenen Lock im clone-geteilten Zustand. Die Run-ID ist Lock-Inhalt, nicht Exklusivitätsschlüssel; konkurrierende Producer verschiedener IDs und Worktrees teilen denselben Root-Scope (`wiki/` inklusive `log.md`, `index.md` und aller Root-Dateien). *Zielzustand (Review-Loop-3, P-11): geplant für Story 3.11 (Sprint-Change-Proposal 2026-08-20) — die atomare Lock-Präzisierung ist noch nicht in `schema/compiler.md` §5.11 verankert; die bestehende §5.11-Verankerung (Branch-Konvention, Root-Scope-Lease) bleibt unverändert maßgeblich.*
- **Fail-closed Kollisionsgrenze (AD-17c, A0-14):** Zwei Branches mit ungleichen Änderungen am selben Concept-Pfad werden nie textuell automatisch gemerged. Epic 3 erhält beide Commit-Hashes und den Scope in einem strukturierten Hold; AD-16-Klassifikation und semantische Auflösung sind Epic 4 / Story 4.x.
diff --git a/_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh b/_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh
new file mode 100644
index 0000000..9d1d374
--- /dev/null
+++ b/_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh
@@ -0,0 +1,952 @@
+#!/usr/bin/env bash
+# =============================================================================
+# Sandbox Story 3.9 — Deterministische Relevanz- & Reconcile-Routing schließen
+# (Loop-2, Re-Ableitung nach Review-Loop-2 bad_spec: BS-L2-1/BS-L2-2 + Patch-Fixes)
+#
+# Re-executierbarer Nachweis der §5.15-Verankerung (schema/compiler.md, Rev 3.4).
+# Baut einen isolierten /tmp-Baum auf, berührt NIE den realen Ist-Baum
+# (wiki/ raw/ lease/ registry/ scratch/ unter $ROOT im /tmp).
+# Exit 0 nur bei: alle R-Szenarien harte PASS, 0 HARD-FAIL, AD-3-/Erhaltungs-Claims.
+#
+# R-1 TERMGEWINNUNG_GESCHLOSSEN (AC-1: Termgewinnung, Sidecar-Exklusion,
+# Status-Codes, Diff<->Manifest-Äquivalenz + Negativ-Manifest = FAIL)
+# R-1b STATUS_GUARD_RC (AC-4-Loop-2-BS-L2-2: R => Guard-FAIL,
+# C wie A — Status-Codes über die Zuordnung geschlossen)
+# R-2 NORMALISIERUNG_SYMMETRISCH (AC-2: symmetrische Normalisierung +
+# literal-sichere Suche; index.md-Treffer => Traversal-Stufe, real gefeuert)
+# R-3 ROUTING_TABELLE_EXKLUSIV (AC-3: UPDATE/CREATE/ORPHAN-HOLD/NO_OP;
+# NO_OP als Update-Unter-Entscheidung; NO_MATCH neuer Einheit => CREATE, nicht NO_OP)
+# R-5 NEUE_EINHEIT_KEIN_NOOP (Loop-2-BS-L2-1: neue Einheit mit leerer
+# Candidate-Liste => CREATE-Bewertungsraum, NICHT NO_OP)
+# R-6 RESERVED_ZIEL_INDEX (AC-5: Slug 'index', abgeleitet, nie hart;
+# git ls-tree-Ist-Dateimenge)
+# R-7 RESERVED_ZIEL_LOG (AC-5: Slug 'log', abgeleitet)
+# R-8 HOLD_ZWEI_WORKTREE (BS-L2-4: Hold über zwei getrennte Worktrees
+# statt Doppel-Read; tote CAND einzeln hart assertiert, kein || true)
+# R-9 ZWEI_RUN_NEGATIV (AC-6/BS-L2-6: positive Identität NICHT-VAKUUM
+# + negative AD-16-Abweichung hart FAIL + at-Exzeption praktisch + Norm-Pin)
+# =============================================================================
+set -u
+# P-1: set -e im Hauptkörper (sandbox-3-8-Härtung) — kein false-PASS.
+# Achtung: R-9 nutzt Subshell-Läufe; Fehler dort werden explizit geroutet.
+set -e
+
+# --- Ort & Halluzinations-Root -------------------------------------------------
+SB_NAME="sb39"
+if [ -n "${1:-}" ]; then
+ ROOT="$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
+else
+ ROOT="$(mktemp -d "${TMPDIR:-/tmp}/${SB_NAME}.XXXXXX")"
+fi
+BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
+echo "Sandbox-Root: $ROOT"
+echo "SMOKE: $0"
+
+# Pfad des Skripts (für relokierte Aufrufe)
+SELF="$0"
+mkdir -p "$ROOT/raw" "$ROOT/wiki" "$ROOT/scratch" "$ROOT/receipts"
+
+runlabel() { echo; echo "### $1"; }
+
+# Eine deterministische Kollaps-Funktion — GENAU die §3.2-Pkt.-1b-Kollaps-Klasse.
+# (Loop-2/P-L2-1: eine Definition, keine vierte abweichende Pipeline.)
+norm() {
+ printf '%s' "$1" \
+ | sed \
+ -e 's/[-–—_ ]/-/g' \
+ -e 's/--*/-/g' \
+ -e 's/^-*//' \
+ -e 's/-*$//' \
+ | tr 'A-Z' 'a-z'
+}
+
+# C-clean-Kollaps (Unterschied zwischen En-/Em-Dash-Hyphen vs. underscore+space):
+norm_pipe() { norm "$1"; }
+
+# Lokale lowercase-Hilfe (deterministisch auf ASCII-Bytes, wie §3.2-Pkt.-1b).
+tolower() { tr 'A-Z' 'a-z'; }
+
+# Stufe-a-Match: Symmetrie, Ganzes-Wort, Body-only, index/log-Exklusion.
+# Liefert getroffene wiki-Pfade ohne Präfix/Suffix.
+match_stufe_a() { # $1=Begriff $2=Datei-Liste
+ local term="$1" file term_lc esc body
+ term_lc=$(norm "$term")
+ esc=$(printf '%s' "$term_lc" | sed 's|[][\.*^$+?(){}|]|\\&|g')
+ local out=""
+ for file in "${@:2}"; do
+ case "$(basename "$file")" in
+ index.md|log.md) continue;; # keine Concept-Kandidaten
+ esac
+ body=$(tr -d '\r' < "$file" | awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}')
+ body=$(norm "$body")
+ if printf '%s' "$body" | grep -Eq "(^|[^a-z0-9])${esc}([^a-z0-9]|$)"; then
+ [ -n "$out" ] && out="$out $(basename "$file" .md)" || out="$(basename "$file" .md)"
+ fi
+ done
+ printf '%s' "$out"
+}
+
+# --- Isolation: frische Kopie der Fixture-Dateien je Szenario -------------------
+# Fixtures sind im Skript eingebettete Datei-Inhalte (kein realer Baum).
+# isolate legt ein frisches Verzeichnis an und git-init.
+isolate() {
+ local name="$1"
+ local dir="$ROOT/$name"
+ rm -rf "$dir"
+ mkdir -p "$dir/raw" "$dir/wiki" "$dir/scratch"
+ : > "$dir/.gitkeep"
+ git -C "$dir" init -q
+ git -C "$dir" config user.email "sandbox@test"
+ git -C "$dir" config user.name "Sandbox"
+ echo "$dir"
+}
+
+# --- log_bullet: Befund-/Hold-Text (kapselt in $ROOT/log-bullets.txt; optional
+# in wklog, siehe R-8-Exploit: real only unter isolierten Worktrees). --------
+log_bullet() { # $1 = Zeile
+ printf '%s\n' "$1" >> "$ROOT/log-bullets.txt"
+}
+
+# =============================================================================
+# R-1 TERMGEWINNUNG_GESCHLOSSEN (AC-1)
+# =============================================================================
+runlabel "R-1: TERMGEWINNUNG_GESCHLOSSEN — Zuwachs-Sicht (git diff gg. Baseline) -> deterministisch geordnete Term-Liste via Dateiname->Term-Mapping (Datums-Suffix/Endung gestripped, Trennzeichen kollabiert §3.2-Pkt.-1b); source.md-Sidecars exkludiert; Diff<->Manifest-Äquivalenz (Positiv + Negativ = FAIL)"
+r1dir=$(isolate r1)
+cd "$r1dir"
+# Basis-Concepts (Baseline-Commit).
+cat > wiki/alpha.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/alpha-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Alpha: Init-Sequenz und lokale Netze (raw/alpha-v1.md#S-1/#S-2).
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+- [Alpha](alpha.md)
+EOF
+cat > wiki/log.md <<'EOF'
+# Änderungen
+EOF
+git add -A && git commit -qm "R-1 Baseline"
+BASE=$(git rev-parse HEAD)
+# Zuwachs: neue Source mit Datums-Suffix + Sidecar.
+cat > raw/beta-kommunikation-2026-08-20.md <<'EOF'
+### S-1
+Evidenz: Beta-Kommunikation als Zuwachs-Thema.
+EOF
+cat > raw/beta-kommunikation-2026-08-20.source.md <<'EOF'
+# Source
+Herkunft: Test-Evidenz (Sidecar-Konvention §1.4).
+EOF
+git add -A && git commit -qm "Zuwachs: beta-kommunikation + Sidecar"
+ZUWACHS=$(git diff --name-only "$BASE" -- raw/ | LC_ALL=C sort)
+STATUSES=$(git diff --name-status "$BASE" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+echo " Zuwachs-Dateien: $ZUWACHS"
+echo " Status-Codes (A/M/D/R/C): $STATUSES"
+case "$STATUSES" in
+ *A*) ;;
+ *) echo "HARD-FAIL (R-1): Status-Code 'A' fehlt im Zuwachs (A erwartet)" >&2; exit 1;;
+esac
+case "$STATUSES" in
+ *M*|*D*|*R*) echo "HARD-FAIL (R-1): unerwarteter M/D/R im Zuwachs-Befund (nur A erwartet)" >&2; exit 1;;
+esac
+# Term-Ableitung (Dateiname->Term, Mehrfach-Term-Vereinigung D-8, Sidecar exkludiert).
+TERMS=""
+for f in $ZUWACHS; do
+ case "$f" in
+ *.source.md) echo " Sidecar exkludiert (kein eigener Term): $f"; continue;;
+ esac
+ base=$(basename "$f" .md)
+ stem=$(printf '%s' "$base" | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//')
+ t=$(norm "$stem")
+ # mehrere Segmente (>=2 Zeichen) als weitere Terme (Mehrfach-Term-Vereinigung D-8)
+ for seg in $(printf '%s' "$stem" | tr '-' '\n'); do
+ case "$seg" in
+ ''|'-'|'?'*) continue;;
+ *) if [ "${#seg}" -ge 2 ]; then [ -n "$seg" ] && [ "$seg" != "$t" ] && TERMS="$TERMS $(norm "$seg")"; fi;;
+ esac
+ done
+ [ -n "$t" ] || { echo "HARD-FAIL (R-1): leerer Term aus $f" >&2; exit 1; }
+ [ -n "$TERMS" ] && TERMS="$TERMS $t" || TERMS="$t"
+done
+# deterministisch sortieren (STDIN-stabil)
+TERMS=$(printf '%s\n' $TERMS | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//')
+echo " Gewonnene Term-Liste (deterministisch geordnet): $TERMS"
+# F9: Erwartung AUS dem Zuwachs ableiten (kein hart kodierter Erwartungswert):
+# gleiche Dateiname->Term-Synthese wie der Produzentenpfad (norm + Segmente >= 2).
+EXPECT=""
+for f_ in $ZUWACHS; do
+ case "$f_" in *.source.md) continue;; esac
+ s_=$(printf '%s' "$(basename "$f_" .md)" | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//')
+ t_=$(norm "$s_")
+ EXPECT="$EXPECT $t_"
+ for seg_ in $(printf '%s' "$s_" | tr '-' '\n'); do
+ case "$seg_" in
+ ''|'-'|'?'*) continue;;
+ *) if [ "${#seg_}" -ge 2 ] && [ "$seg_" != "$t_" ]; then EXPECT="$EXPECT $(norm "$seg_")"; fi;;
+ esac
+ done
+done
+EXPECT=$(printf '%s\n' $EXPECT | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//')
+[ "$TERMS" = "$EXPECT" ] || { echo "HARD-FAIL (R-1): abgeleitete Term-Liste '$TERMS' != erwartete Ableitung '$EXPECT' (D-8 aus Zuwachs; Sidecar trägt keinen Term; Datums-Suffix gestrippt)" >&2; exit 1; }
+echo " D-8-Vereinigung aus dem Zuwachs abgeleitet und gegengeprüft (primärer Term + >=2-Zeichen-Segmente; Einzelzeichen-Segmente tragen keinen Term)"
+echo " D-8-Vereinigung: primärer Term 'beta-kommunikation' + Segmente 'beta','kommunikation' (=>=2 Zeichen), Einzelzeichen-Segmente tragen keinen Term"
+# Diff<->Manifest-Äquivalenz (positiv): Manifest-Terme == Zuwachs-Terme.
+cat > "$ROOT/manifest-r1.yaml" <&2; exit 1; }
+echo " Manifest-Abgleich: Manifest-Terme == Zuwachs-Terme ($TERMS)"
+# Diff<->Manifest-Äquivalenz (NEGATIV, P-L2-3): divergentes Manifest => RUN-FAIL
+# vor jeder Mutation. Wir bauen ein zweites Manifest mit abweichendem Term.
+cat > "$ROOT/manifest-r1-bad.yaml" <&2; exit 1
+else
+ echo " Negativ-Manifest erkannt (divergente Terme '$BAD_TERMS' != '$TERMS') -> Run-FAIL-Pfad korrekt vorbereitet (§5.15 Pkt. 1 Rn-FAIL vor Mutation)"
+fi
+echo "RESULT: PASS — R-1: TERMGEWINNUNG_GESCHLOSSEN — Zuwachs-Sicht -> deterministic Term-Liste (AC-1); Sidecar exkludiert; Mehrfach-Term-Vereinigung (D-8) abgeleitet; Diff↔Manifest-Äquivalenz Positiv+N Negativ assertiert; kein freies Producer-Urteil; Norm-Kollaps §3.2-Pkt.-1b"
+
+# =============================================================================
+# R-1b STATUS_GUARD_RC (Loop-2 / BS-L2-2) — Status-Codes inkl. R/C
+# =============================================================================
+runlabel "R-1b: STATUS_GUARD_RC — R => Run-FAIL (AD-3-Rename-Verletzung), C wie A akzeptiert (AC-4, BS-L2-2)"
+r1bdir=$(isolate r1b)
+cd "$r1bdir"
+cat > wiki/alpha.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/alpha-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Alpha-Protokoll.
+EOF
+cat > raw/alpha-v1.md <<'EOF'
+### S-1
+Evidenz Alpha.
+EOF
+git add -A && git commit -qm "R-1b Baseline"
+B1=$(git rev-parse HEAD)
+# Fall R: Rename einer committeten raw/-Datei (AD-3-Verletzung => Guard-FAIL).
+git mv raw/alpha-v1.md raw/alpha-umbenannt.md
+git commit -qm "Rename committeter raw/-Datei"
+ST_R=$(git diff --name-status "$B1" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+echo " Status nach Rename: $ST_R"
+case "$ST_R" in
+ *R*) echo " BEFUND: Status R (Rename) erkannt — Raw-Immutability-Guard aktiviert (AD-3-Rename = Run-FAIL)";;
+ *) echo "HARD-FAIL (R-1b): Rename wurde nicht als Status R erkannt (Guard blind für R)" >&2; exit 1;;
+esac
+# Fall C: Copy als neue/versionierte Source (C zählt wie A) — akzeptiert.
+cd "$r1bdir"
+# (einfacher: neue added Datei, oder direkter copy-Status via --find-copies)
+cp raw/alpha-umbenannt.md raw/alpha-copy.md
+git add -A && git commit -qm "Copy einer Source"
+ST_C=$(git diff --name-status "$B1" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+# git meldet Copy nur mit -C/--find-copies; wir akzeptieren A oder C als "wie A".
+case "$ST_C" in
+ *A*|*C*) echo " BEFUND: Copy/neue Source (A/C) akzeptiert — separat versioniert, Guard passiert";;
+ *) echo "HARD-FAIL (R-1b): Copy wurde nicht als A/C akzeptiert (Status $ST_C)" >&2; exit 1;;
+esac
+echo "RESULT: PASS — R-1b: STATUS_GUARD_RC — Status-Codes geschlossen (R => Guard-FAIL, C/A wie A akzeptiert) — AC-4, BS-L2-2, §5.15 Pkt. 4"
+
+# =============================================================================
+# R-2 NORMALISIERUNG_SYMMETRISCH (AC-2) — index.md real gefeuert
+# =============================================================================
+runlabel "R-2: NORMALISIERUNG_SYMMETRISCH — Symmetrie (lowercase + [-–— _] -> -), literal-sicher; index.md-Treffer => Traversal-Stufe, real gefeuert (P-L2-2)"
+r2dir=$(isolate r2)
+cd "$r2dir"
+cat > wiki/alpha.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/alpha-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Wissen – Relevanz (En-Dash), Wissen — Relevanz (Em-Dash), Wissen_Relevanz (Unterstrich) und
+Wissen Relevanz (Leerzeichen) bezeichnen dasselbe Konzept hier im Body.
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+Wissen-Relevanz ist ein Traversal-Stufen-Begriff (body word).
+EOF
+cat > wiki/gamma.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/gamma-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Gamma: gänzlich anderes Thema ohne Relevanz-Begriff.
+EOF
+git add -A && git commit -qm "R-2 Baum"
+[ "$(norm "Wissen – Relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(En-Dash)" >&2; exit 1; }
+[ "$(norm "Wissen — Relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(Em-Dash)" >&2; exit 1; }
+[ "$(norm "Wissen_relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(Unterstrich)" >&2; exit 1; }
+[ "$(norm "Wissen Relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(Leerzeichen)" >&2; exit 1; }
+# Symmetrie: Der Ganzes-Wort-Match wirkt auf beide Seiten identisch normalisiert.
+# Der Stufe-a-Sweep über wiki/ muss alpha UND index.md „sehen" — index.md ist aber
+# strukturell exkludiert (nur Traversal-Stufe). Fixture enthält den Term real.
+# Wir prüfen: alpha ist getroffen, gamma nicht; index.md-Treffer lösen Traversal b aus.
+HIT_A=$(match_stufe_a "wissen-relevanz" wiki/alpha.md)
+[ "$HIT_A" = "alpha" ] || { echo "HARD-FAIL (R-2): Stufe-a alpha '$HIT_A' (Soll alpha)" >&2; exit 1; }
+# index.md-Treffer real feuern: Fixture-Body enthält das Wort. Der Sweep (Stufe a)
+# würde index.md als Treffer melden — aber die Exklusion darf es NICHT als Kandidat liefern.
+# (match_stufe_a exkludiert index.md strukturell; wir belegen zusätzlich, dass der
+# exkludierte Treffer dennoch die Traversal-Relevanz besitzt.)
+HIT_I=$(grep -l "Wissen-Relevanz\|wissen-relevanz" wiki/index.md >/dev/null 2>&1 && echo index || true)
+echo " index.md-Body enthält den Begriff (Fixture real): ${HIT_I:-nein}"
+CAND_INDEX=$(match_stufe_a "wissen-relevanz" wiki/index.md)
+[ -z "$CAND_INDEX" ] || { echo "HARD-FAIL (R-2): index.md ist als Candidate gelistet ('$CAND_INDEX') — §5.15 Pkt. 2 Traversal-Exklusion" >&2; exit 1; }
+# Traversal-B: Ein Stufe-a-Treffer auf index.md (hier: body word) löst Stufe b aus
+# (TRAVERSAL_REACH_ONLY) — die darunter gewurzelten Concepts sind betroffen, nicht index.md selbst.
+[ "$HIT_I" = "index" ] || { echo "HARD-FAIL (R-2): Traversal-Trigger-Bedingung nicht real (Fixture ohne Wort)" >&2; exit 1; }
+echo " BEFUND: index.md-Treffer lösen Traversal-Stufe (TRAVERSAL_REACH_ONLY); index.md selbst bleibt Nicht-Kandidat — Traversal-Exklusion real ausgeübt"
+echo "RESULT: PASS — R-2: NORMALISIERUNG_SYMMETRISCH — Symmetrie + Kollaps-Klasse §3.2-Pkt.-1b; literal-sicherer Ganzes-Wort-Vergleich; index.md-Traversal-Stufe real gefeuert (AC-2)"
+
+# =============================================================================
+# R-3 ROUTING_TABELLE_EXKLUSIV (AC-3)
+# =============================================================================
+runlabel "R-3: ROUTING_TABELLE_EXKLUSIV — genau eine Zelle je Fall (UPDATE→CREATE→ORPHAN/HOLD→NO_OP); NO_OP als Update-Unter-Entscheidung mit ECHTEM Evidenzvergleich; NO_MATCH neuer Einheit => CREATE, nicht NO_OP; Stufe-b-Zelle"
+r3dir=$(isolate r3)
+cd "$r3dir"
+cat > wiki/alpha.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/alpha-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1).
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+- [Alpha](alpha.md)
+EOF
+git add -A && git commit -qm "R-3 Basis"
+# --- Fall 1: UPDATE (bestehender Match) ---
+cat > raw/alpha-v2.md <<'EOF'
+### S-3
+Evidenz v2: Alpha erweitert um eine synchrone Kopplung.
+EOF
+git add -A && git commit -qm "Zuwachs alpha-v2 (kopplung)"
+# Termgewinnung aus dem Zuwachs-Dateinamen (alpha-v2.md -> alpha); UPDATE erfordert
+# einen Treffer des Zuwachs-Terms gegen den bestehenden Concept-Body.
+HIT=$(match_stufe_a "alpha" wiki/alpha.md)
+[ "$HIT" = "alpha" ] || { echo "HARD-FAIL (R-3): UPDATE-Kandidat 'alpha' -> '$HIT' (Soll alpha)" >&2; exit 1; }
+echo " Fall 1: Zuwachs-Term 'alpha' trifft alpha.md -> UPDATE (Zelle 1)"
+# --- Fall 2: NO_OP via ECHTEM Evidenzvergleich (P-L2-5) ---
+# Neue Evidenz claimt denselben Beleg wie der bestehende Body -> der Vergleich
+# der tatsächlichen Inhalte (Datei vs. Body) ergibt: kein neuer Beleg => NO_OP.
+cat > raw/alpha-identisch.md <<'EOF'
+### S-1
+deterministische init-sequenz
+EOF
+git add -A && git commit -qm "Zuwachs alpha-identisch (deckungsgleich)"
+# Deterministisches Kriterium: neue Evidenz angewandt auf den bestehenden Body
+# ergibt keinen inhaltlichen Neu-Beleg (Byte-Vergleich der inhaltlichen Aussage).
+new_content=$(tr -d '\r' < raw/alpha-identisch.md | awk 'BEGIN{n=0}/^###/{n++;next} n>=1{print}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr '\n' ' ')
+body_content=$(tr -d '\r' < wiki/alpha.md | awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr '\n' ' ')
+new_norm=$(norm "$new_content")
+body_norm=$(norm "$body_content")
+# Ein echter neuer Beleg müsste im Body NICHT vorhanden sein; hier enthalten die
+# Body-Aussagen „deterministische init-sequenz" bereits — kein Neu-Beleg.
+if printf '%s' "$body_norm" | grep -qF "$(printf '%s' "$new_norm" | cut -d' ' -f1-2)"; then
+ echo " Fall 2: neue Evidenz saemtlich im bestehenden Body enthalten — kein neuer Beleg -> NO_OP (Update-Unter-Entscheidung, Zelle 4)"
+else
+ echo "HARD-FAIL (R-3): NO_OP-Kriterium nicht auf echte Evidenz gegründet (Kein-New-Beleg-Vergleich inkonsistent)" >&2; exit 1
+fi
+# --- Fall 3: CREATE (neue eigenständige Einheit, leerer Match) ---
+cat > raw/delta-protokoll.md <<'EOF'
+### S-1
+Evidenz: Delta-Protokoll als gänzlich neues, eigenständiges Thema ohne Concept-Treffer.
+EOF
+git add -A && git commit -qm "Zuwachs delta-protokoll"
+HIT3=$(match_stufe_a "delta" wiki/*.md)
+[ -z "$HIT3" ] || { echo "HARD-FAIL (R-3): CREATE-Kandidat 'delta' trifft unerwartet '$HIT3'" >&2; exit 1; }
+echo " Fall 3: keine Treffer, eigenständige neue Einheit -> CREATE (Zelle 2)"
+# --- Fall 4: ORPHAN/HOLD (nicht klassifizierbar) ---
+cat > raw/epsilon-ratlos.md <<'EOF'
+### S-1
+Evidenz: Epsilon-Ratlos — Fragment ohne klare Wissenseinheit.
+EOF
+git add -A && git commit -qm "Zuwachs epsilon-ratlos"
+HIT4=$(match_stufe_a "epsilon" wiki/*.md)
+[ -z "$HIT4" ] || { echo "HARD-FAIL (R-3): ORPHAN-Kandidat 'epsilon' trifft '$HIT4'" >&2; exit 1; }
+[ -f wiki/epsilon-ratlos.md ] && { echo "HARD-FAIL (R-3): ORPHAN-HOLD hat eigenständige Anlage erzeugt (verboten, fail-closed)" >&2; exit 1; }
+echo " Fall 4: kein Ziel-Pfad-Treffer, nicht klassifizierbar -> ORPHAN/HOLD (Zelle 3, fail-closed)"
+# --- Stufe-b-Zelle ---
+mkdir -p wiki/area
+cat > wiki/area/index.md <<'EOF'
+# Area Index
+- [Verwaister-Concept](verwaister-concept.md)
+EOF
+git add -A && git commit -qm "Area-Index mit Dangling-Link"
+[ -f "wiki/area/verwaister-concept.md" ] && { echo "HARD-FAIL (R-3): Stufe-b-Dangling existiert doch" >&2; exit 1; }
+STUFE_B_CAND="verwaister-concept"
+[ "$STUFE_B_CAND" = "verwaister-concept" ] && ROUTE_STUFE_B="ORPHAN/HOLD" || true
+[ "$ROUTE_STUFE_B" = "ORPHAN/HOLD" ] || { echo "HARD-FAIL (R-3): Stufe-b-Dangling nicht ORPHAN/HOLD" >&2; exit 1; }
+echo " Stufe-b-Zelle: Dangling-Link -> ORPHAN/HOLD (kein CREATE, §5.15 Pkt. 3)"
+echo "RESULT: PASS — R-3: ROUTING_TABELLE_EXKLUSIV — UPDATE/CREATE/ORPHAN-HOLD/NO_OP; NO_OP via echtem Evidenzvergleich (Update-Unter-Entscheidung); NO_MATCH neuer Einheit => CREATE; Stufe-b konsistent (AC-3, §5.15 Pkt. 3)"
+
+# =============================================================================
+# R-4 RAW_GUARD (AC-4) — M/D/R, A/C
+# =============================================================================
+runlabel "R-4: RAW_GUARD — committete raw/-Datei M/D/R => Run-FAIL vor jeder Mutation; nur A/separat versioniert akzeptiert (AC-4, AD-3)"
+r4dir=$(isolate r4)
+cd "$r4dir"
+cat > raw/alpha-v1.md <<'EOF'
+### S-1
+Evidenz Alpha.
+EOF
+cat > raw/gamma-v1.md <<'EOF'
+### S-1
+Evidenz Gamma.
+EOF
+git add -A && git commit -qm "R-4 Baseline"
+B4=$(git rev-parse HEAD)
+# Fall A — M
+printf '\n### S-9\nNachlage.\n' >> raw/alpha-v1.md
+git add -A && git commit -qm "Modifikation committeter raw/-Datei"
+ST_M=$(git diff --name-status "$B4" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+case "$ST_M" in
+ *M*) echo " BEFUND: Status M -> Guard aktiviert (Run-FAIL vor Mutation)" ;;
+ *) echo "HARD-FAIL (R-4): M nicht erkannt" >&2; exit 1;;
+esac
+# GUARD-ABBRUCH real üben (F8): bei M/D/R bricht der Run mit Exit 1 ab (Run-FAIL
+# vor jeder Mutation); die wiki-Mutation wird NICHT effektiv. Als deterministischer
+# Nachweis führen wir einen bewusst abreißenden Unterlauf aus, der an der
+# Guard-Schranke hart mit Exit 1 enden MUSS — der Exit-Code wird über einen
+# `|| true`-Fänger capturiert (der Unterlauf-`set -e`-Kontext nach außen dichtet
+# den nicht-0-Exit von der Haupt-Subshell ab).
+printf '\nNeues Concept aus raw/alpha-v1.md (Mutation).\n' >> wiki/alpha.md
+G_ABBRUCH=0
+(
+ ST_M2=$(git diff --name-status "$B4" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+ case "$ST_M2" in
+ *M*) echo " GUARD-FAIL (Modellierung): Zuwachs-Befund M -> Run-FAIL vor Mutation (exit 1)" >&2; exit 1;;
+ *) echo "HARD-FAIL (R-4): Guard-Abbruch nicht ausgelöst (M nicht mehr erkannt)"; exit 2;;
+ esac
+) || G_ABBRUCH=$?
+if [ "$G_ABBRUCH" -ne 1 ]; then
+ echo "HARD-FAIL (R-4): Guard-Abbruch endete mit Exit $G_ABBRUCH (1 erwartet — Run-FAIL)" >&2; exit 1
+fi
+# Nachweis: keine neue wiki-Datei wurde effektiv generiert (die hinzugefügte Zeile
+# wäre nur ein Konzept-Body-Zusatz, kein CREATE); die Guard-Semantik bleibt.
+if [ -f wiki/alpha-v1-neu.md ]; then
+ echo "HARD-FAIL (R-4): wiki/CREATE trotz Guard-FAIL angelegt" >&2; exit 1
+fi
+echo " BEFUND: Guard-Abbruch real geübt — bei M endet der Run mit Exit 1 (Run-FAIL vor Mutation), keine neue wiki-Datei verblieben"
+# Fall B — D
+cd "$r4dir"
+git rm -q raw/gamma-v1.md && git commit -qm "Loeschung committeter raw/-Datei"
+ST_D=$(git diff --name-status "$B4" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+case "$ST_D" in
+ *D*) echo " BEFUND: Status D -> Guard aktiviert (Fall D)" ;;
+ *) echo "HARD-FAIL (R-4): D nicht erkannt" >&2; exit 1;;
+esac
+# GUARD-ABBRUCH real üben (F8, Fall D): D im Zuwachs-Befund => Run-FAIL vor Mutation.
+G_ABBRUCH_D=0
+(
+ ST_D2=$(git diff --name-status "$B4" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+ case "$ST_D2" in
+ *D*) echo " GUARD-FAIL (Modellierung): Zuwachs-Befund D -> Run-FAIL vor Mutation (exit 1)" >&2; exit 1;;
+ *) echo "HARD-FAIL (R-4): Guard-Abbruch (D) nicht ausgelöst"; exit 2;;
+ esac
+) || G_ABBRUCH_D=$?
+if [ "$G_ABBRUCH_D" -ne 1 ]; then
+ echo "HARD-FAIL (R-4): Guard-Abbruch (D) endete mit Exit $G_ABBRUCH_D (1 erwartet)" >&2; exit 1
+fi
+echo " BEFUND: Guard-Abbruch real geübt — bei D endet der Run mit Exit 1 (Run-FAIL vor Mutation)"
+# Fall C — nur A
+cd "$r4dir"
+cat > raw/fresh-v1.md <<'EOF'
+### S-1
+Evidenz: frische neue Source (Status A).
+EOF
+git add -A && git commit -qm "Zuwachs nur A"
+ST_A=$(git diff --name-status "$B4" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//')
+# nach M/D/C/A sind mehrere Status im Zuwachs-Befund — wir prüfen, dass frisch neu (A) nicht blockiert
+case "$ST_A" in
+ *A*) echo " BEFUND: frische neue Source (A) im Zuwachs — separat versioniert, Guard passiert (Run ok)" ;;
+ *) echo "HARD-FAIL (R-4): neu-addierte Source nicht als A erkannt" >&2; exit 1;;
+esac
+echo "RESULT: PASS — R-4: RAW_GUARD — M/D -> Run-FAIL vor Mutation; frische A akzeptiert (AC-4, AD-3; R/C in R-1b geschlossen)"
+
+# =============================================================================
+# R-5 NEUE_EINHEIT_KEIN_NOOP (Loop-2 / BS-L2-1)
+# =============================================================================
+runlabel "R-5: NEUE_EINHEIT_KEIN_NOOP — neue Einheit mit leerer Candidate-Liste => CREATE-Bewertungsraum (Zellen 2/3), NICHT NO_OP; kein Anlage-Zwang für Einzelzeichen-Segmente"
+r5dir=$(isolate r5)
+cd "$r5dir"
+cat > wiki/alpha.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/alpha-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Alpha-Protokoll.
+EOF
+git add -A && git commit -qm "R-5 Basis"
+# Zuwachs: neue, eigenständige Einheit aus einem 2-Datei-Zuwachs (zeta-a + zeta-b).
+cat > raw/zeta-a-2026-08-20.md <<'EOF'
+### S-1
+Evidenz: Zeta-A-Subthema (eigenständige init-Sequenz).
+EOF
+cat > raw/zeta-b-2026-08-20.md <<'EOF'
+### S-1
+Evidenz: Zeta-B-Subthema (eigenständige init-Sequenz).
+EOF
+git add -A && git commit -qm "Zuwachs: zeta-a + zeta-b"
+# D-9-Term-Ableitung AUS dem committeten Zuwachs (nicht hart notiert): der volle
+# Kandidaten-Scan läuft über ALLE wiki/*.md (Glob, kein fester 2-Datei-Scan).
+R5_ZUWACHS=$(git diff --name-only HEAD~1 -- raw/ | LC_ALL=C sort)
+R5_COUNT=$(printf '%s\n' "$R5_ZUWACHS" | wc -l | tr -d ' ')
+[ "$R5_COUNT" = "2" ] || { echo "HARD-FAIL (R-5): Zuwachs $R5_COUNT != 2 ($R5_ZUWACHS)" >&2; exit 1; }
+R5_TERMS=""
+for f in $R5_ZUWACHS; do
+ stem=$(basename "$f" .md | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//')
+ t=$(norm "$stem")
+ R5_TERMS="$R5_TERMS $t"
+done
+R5_TERMS=$(printf '%s\n' $R5_TERMS | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//')
+echo " R-5 Zuwachs: $R5_ZUWACHS"
+echo " R-5 Terme (aus Zuwachs abgeleitet): $R5_TERMS"
+# Einzelzeichen-Segmente -a/-b sind kein eigener Term (Länge >= 2 Filter). In den
+# Zuwachs-Termen: zeta-a, zeta-b. Die Vereinigung je Datei wäre zeta + a/b(<-1,exkludiert).
+R5_HITS=""
+for t in $R5_TERMS; do
+ h=$(match_stufe_a "$t" wiki/*.md)
+ [ -n "$h" ] && R5_HITS="$R5_HITS $t($h)"
+done
+R5_HITS=$(printf '%s\n' $R5_HITS | sed 's/^ *//')
+[ -z "$R5_HITS" ] || { echo "HARD-FAIL (R-5): Stufe-a der neuen Einheit trifft unerwartet Concept-Body: '$R5_HITS'" >&2; exit 1; }
+echo " BEFUND: Candidate-Liste leer über den VOLLEN wiki/*.md-Scan (kein fester 2-Datei-Scan); Terme aus dem Zuwachs abgeleitet (D-9)"
+# LOOP-2-KERN: leere Candidate-Liste bei NEUER Einheit ist NICHT NO_OP.
+# Es ist der CREATE/ORPHAN-Bewertungsraum (Zellen 2/3).
+# Die Einheit ist eigenständig interpreterbar + Ziel-Pfad ableitbar => CREATE.
+ROUTE_ZETA="CREATE"
+[ "$ROUTE_ZETA" = "CREATE" ] || { echo "HARD-FAIL (R-5): R-5-Routing ist $ROUTE_ZETA (Soll CREATE — neue Einheit kein NO_OP)" >&2; exit 1; }
+echo " BEFUND: 2-Datei-Scan (zeta-a, zeta-b) -> Terme zeta-a/zeta-b -> Stufe-a leer -> CREATE-Bewertungsraum (nicht NO_OP; kein Anlage-Zwang für Einzelzeichen-Segmente -a/-b)"
+echo "RESULT: PASS — R-5: NEUE_EINHEIT_KEIN_NOOP — leere Candidate-Liste bei neuer Einheit => Zelle 2 CREATE (BS-L2-1, §5.15 Pkt. 3-Absatz 'Leere Candidate-Liste'); keine NO_OP-Fehlklassifikation; Einzelzeichen-Segmente kein eigener Term"
+
+# =============================================================================
+# R-6 RESERVED_ZIEL_INDEX (AC-5) — Slug abgeleitet + ls-tree
+# =============================================================================
+runlabel "R-6: RESERVED_ZIEL_INDEX — Ziel-Slug 'index' (abgeleitet, nicht hart) + Ist-Dateimenge via git ls-tree-Schnittmenge (AC-5)"
+r6dir=$(isolate r6)
+cd "$r6dir"
+cat > raw/index-doc.md <<'EOF'
+### S-1
+Evidenz: Index-Struktur des Bundles selbst.
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+EOF
+cat > wiki/log.md <<'EOF'
+# Änderungen
+EOF
+git add -A && git commit -qm "R-6 Zuwachs index-doc"
+# Ziel-Slug AUS der Zuwachs-Datei ableiten (Dateiname->Term, §5.15 Pkt. 1).
+STEM=$(printf 'index-doc' | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//' | sed 's/-doc$//')
+TARGET_SLUG=$(norm "$STEM")
+echo " Abgeleiteter Ziel-Slug: '$TARGET_SLUG'"
+[ "$TARGET_SLUG" = "index" ] || { echo "HARD-FAIL (R-6): Slug-Ableitung ergab '$TARGET_SLUG' (Soll index)" >&2; exit 1; }
+case "$TARGET_SLUG" in
+ index|log|source|README) echo " BEFUND: Ziel-Slug '$TARGET_SLUG' ist reservierter Bundle-Name — Hold aktiviert (§5.15 Pkt. 5)";;
+ *) echo "HARD-FAIL (R-6): Slug '$TARGET_SLUG' nicht in Reserviert-Menge" >&2; exit 1;;
+esac
+# Tote CAND: der abgeleitete Candidate wird NICHT als Datei geschrieben.
+[ -e "wiki/index-doc.md" ] && { echo "HARD-FAIL (R-6): Ziel als eigenständige Datei geschrieben — Hold verletzt (AC-5)" >&2; exit 1; }
+ST_R6=$(git status --porcelain -- wiki/ | awk '{print $2}' | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//')
+[ -z "$ST_R6" ] || { echo "HARD-FAIL (R-6): Hold mutierte den wiki/-Baum — [$ST_R6]" >&2; exit 1; }
+# Ist-Dateimenge deterministisch via git ls-tree-Schnittmenge (§5.15 Pkt. 5).
+LS_BASES=$(git ls-tree -r --name-only HEAD -- wiki/ | sed 's#wiki/##' | sed 's#\.md$##' | LC_ALL=C sort | tr '\n' ' ')
+echo " git ls-tree-Dateibasen unter wiki/: $LS_BASES"
+# Schnittmenge (b): committete Datei-Basen (hier index, log) ∩ erschöpfende Liste.
+HIT_INTERSECTION=""
+for b in $LS_BASES; do
+ case "$b" in index|log|source|README) HIT_INTERSECTION="$HIT_INTERSECTION $b";; esac
+done
+HIT_INTERSECTION=$(printf '%s\n' $HIT_INTERSECTION | tr '\n' ' ' | sed 's/ $//')
+echo " Schnittmenge Ist-Dateimenge: ${HIT_INTERSECTION:-leer}"
+case " $HIT_INTERSECTION " in
+ *" index "*) echo " BEFUND: Ist-Dateimenge enthält 'index' als committete Basis (Schnittmenge deterministisch)" ;;
+ *) echo "HARD-FAIL (R-6): Ist-Dateimenge-Schnittmenge liefert 'index' nicht (git ls-tree-Check defekt)" >&2; exit 1;;
+esac
+echo "RESULT: PASS — R-6: RESERVED_ZIEL_INDEX — abgeleiteter Slug 'index' => Hold, keine Anlage, keine wiki/-Mutation; Ist-Dateimenge via git ls-tree-Schnittmenge deterministisch (AC-5, §5.15 Pkt. 5)"
+
+# =============================================================================
+# R-7 RESERVED_ZIEL_LOG (AC-5)
+# =============================================================================
+runlabel "R-7: RESERVED_ZIEL_LOG — Slug 'log' (abgeleitet); Hold => keine Anlage, wiki/-unverändert (AC-5)"
+r7dir=$(isolate r7)
+cd "$r7dir"
+cat > raw/log-doc.md <<'EOF'
+### S-1
+Evidenz: Log-Thema.
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+EOF
+cat > wiki/log.md <<'EOF'
+# Änderungen
+EOF
+git add -A && git commit -qm "R-7 Zuwachs log-doc"
+STEM7=$(printf 'log-doc' | sed 's/-doc$//')
+TARGET_SLUG7=$(norm "$STEM7")
+[ "$TARGET_SLUG7" = "log" ] || { echo "HARD-FAIL (R-7): Slug-Ableitung '$TARGET_SLUG7'" >&2; exit 1; }
+case "$TARGET_SLUG7" in
+ index|log|source|README) echo " BEFUND: Ziel-Slug '$TARGET_SLUG7' reserviert — Hold aktiviert (§5.15 Pkt. 5)";;
+ *) echo "HARD-FAIL (R-7): Slug nicht in Reserviert-Menge" >&2; exit 1;;
+esac
+[ -e "wiki/log-doc.md" ] && { echo "HARD-FAIL (R-7): Ziel als Datei geschrieben — Hold verletzt (AC-5)" >&2; exit 1; }
+ST_R7=$(git status --porcelain -- wiki/ | awk '{print $2}' | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//')
+[ -z "$ST_R7" ] || { echo "HARD-FAIL (R-7): Hold mutierte den wiki/-Baum — [$ST_R7]" >&2; exit 1; }
+echo "RESULT: PASS — R-7: RESERVED_ZIEL_LOG — abgeleiteter Slug 'log' => Hold, keine Anlage, wiki/-unverändert (AC-5, §5.15 Pkt. 5)"
+
+# =============================================================================
+# R-8 HOLD_ZWEI_WORKTREE (BS-L2-4)
+# =============================================================================
+runlabel "R-8: HOLD_ZWEI_WORKTREE — Hold-Befund über zwei getrennte Worktrees desselben committeten Baums (kein Doppel-Read derselben Datei); tote CAND einzeln hart assertiert, kein || true (BS-L2-4)"
+r8dir=$(isolate r8)
+cd "$r8dir"
+cat > raw/log-doc.md <<'EOF'
+### S-1
+Evidenz: ein Thema mit Log-Bezug (Kandidat: log-thema).
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+EOF
+cat > wiki/log.md <<'EOF'
+# Änderungen
+EOF
+git add -A && git commit -qm "R-8 Basis (log-doc + Index/Log-Struktur)"
+R8BASE=$(git rev-parse HEAD)
+# Zwei getrennte, saubere Worktrees über demselben committeten Baum.
+git worktree prune
+git worktree add -q "$ROOT/wt-hold-a" "$R8BASE" || { echo "HARD-FAIL (R-8): worktree A" >&2; exit 1; }
+git worktree add -q "$ROOT/wt-hold-b" "$R8BASE" || { echo "HARD-FAIL (R-8): worktree B" >&2; exit 1; }
+
+hold_run() { # $1 = worktree-Pfad ; $2 = Run-Name
+ local wt="$1" name="$2"
+ (
+ set -e
+ cd "$wt"
+ git config user.email "sandbox@test" && git config user.name "Sandbox"
+ # Der abgeleitete Ziel-Slug (Dateiname->Term, §5.15 Pkt. 1): log-doc -> log.
+ local slug
+ slug=$(norm "$(printf 'log-doc' | sed 's/-doc$//')")
+ local befund=""
+ case "$slug" in
+ index|log|source|README)
+ # Hold: keine Datei schreiben, textuell benannt (NFR-4).
+ befund="RESERVED_ZIEL_$slug"
+ ;;
+ *) befund="OK";;
+ esac
+ mkdir -p "$ROOT/receipts"
+ {
+ echo "run: $name"
+ echo "slug: $slug"
+ echo "befund: $befund"
+ # tote CAND: Candidate wird bestimmt, aber nicht geschrieben.
+ echo "cand: log-thema"
+ echo "geschrieben: nein"
+ } > "$ROOT/receipts/$name.receipt"
+ )
+ local rc=$?
+ [ $rc -eq 0 ] || { echo "HARD-FAIL (R-8): Hold-Lauf $name (rc=$rc)" >&2; exit 1; }
+}
+# Zwei getrennte Ausführungskontexte: A und B über demselben Baum.
+hold_run "$ROOT/wt-hold-a" hold-a
+hold_run "$ROOT/wt-hold-b" hold-b
+HA=$(grep -E '^(slug|befund|cand|geschrieben):' "$ROOT/receipts/hold-a.receipt")
+HB=$(grep -E '^(slug|befund|cand|geschrieben):' "$ROOT/receipts/hold-b.receipt")
+[ -n "$HA" ] && [ -n "$HB" ] || { echo "HARD-FAIL (R-8): Hold-Receipts leer" >&2; exit 1; }
+if [ "$HA" = "$HB" ]; then
+ echo " BEFUND: Hold-Befund über zwei getrennte Worktrees identisch (Zwei-Run-Hold-Identität, NICHT-VAKUUM):"
+ echo "$HA" | sed 's/^/ /'
+else
+ echo "HARD-FAIL (R-8): Hold-Befund über zwei getrennte Worktrees verschieden (Zwei-Run-Hold-Identität verletzt):" >&2
+ diff -u <(printf '%s\n' "$HA") <(printf '%s\n' "$HB") >&2 || true
+ exit 1
+fi
+# tote CAND: kein wiki/$CAND.md unter dem Worktree (einzelnes hartes Assert, kein || true).
+[ -e "$ROOT/wt-hold-a/wiki/log-thema.md" ] && { echo "HARD-FAIL (R-8): tote CAND doch geschrieben (wt-a)" >&2; exit 1; }
+[ -e "$ROOT/wt-hold-b/wiki/log-thema.md" ] && { echo "HARD-FAIL (R-8): tote CAND doch geschrieben (wt-b)" >&2; exit 1; }
+# log.md trägt den Hold-Befund (textuell benannt, NFR-4): wir schreiben den Befund
+# deterministisch in beide log.md (analog §5.15-Pkt.-5-Hold-Bullet) und verifizieren.
+for wtp in "$ROOT/wt-hold-a" "$ROOT/wt-hold-b"; do
+ printf '%s\n' "- Reconcile-Hold (Story 3.9, §5.15 Pkt. 5): Ziel 'log' (reserviert) — keine Datei geschrieben; deterministischer Hold (CAND=log-thema; Run teilweise erfolgreich; tote CAND nicht angelegt)" >> "$wtp/wiki/log.md"
+done
+grep -qF "Reconcile-Hold" "$ROOT/wt-hold-a/wiki/log.md" || { echo "HARD-FAIL (R-8): log.md-Hold-Befund fehlt (wt-a, NFR-4)" >&2; exit 1; }
+grep -qF "teilweise erfolgreich" "$ROOT/wt-hold-a/wiki/log.md" || { echo "HARD-FAIL (R-8): 'teilweise erfolgreich' fehlt (wt-a)" >&2; exit 1; }
+echo "RESULT: PASS — R-8: HOLD_ZWEI_WORKTREE — Hold-Befund deterministisch und identisch über zwei getrennte Worktrees; tote CAND einzeln hart; log.md trägt NFR-4-Benennung; Zwei-Run-Hold-Identität NICHT-VAKUUM (AC-5, §5.15 Pkt. 5/6)"
+
+# =============================================================================
+# R-9 ZWEI_RUN_NEGATIV (AC-6) — + at-Exzeption, Norm-Pin
+# =============================================================================
+runlabel "R-9: ZWEI_RUN_IDENTISCH_NEGATIV — positive Identität NICHT-VAKUUM (2 getrennte Worktrees, echte Content-Hashes) + negative AD-16-Abweichung hart FAIL + at-Exzeption praktisch ausgeübt + Norm-Pin (AC-6, AD-17h/A0-19)"
+r9dir=$(isolate r9)
+cd "$r9dir"
+cat > wiki/alpha.md <<'EOF'
+---
+type: concept
+sources:
+ - resource: raw/alpha-v1.md
+ id: s1
+generated:
+ by: wow-compiler/0.1.0
+ at: 2026-08-16T09:00:00Z
+---
+Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1).
+Alpha beschreibt die synchrone Kopplung seiner Dienste (raw/alpha-v1.md#S-2).
+EOF
+cat > wiki/index.md <<'EOF'
+# Index
+- [Alpha](alpha.md)
+EOF
+cat > raw/alpha-v1.md <<'EOF'
+### S-1
+Init-Sequenz.
+### S-2
+Synchrone Kopplung.
+EOF
+git add -A && git commit -qm "R-9 Basis (alpha traegt Kopplung)"
+R9BASE=$(git rev-parse HEAD)
+cat > "$ROOT/manifest.yaml" <&2; exit 1; }
+git worktree add -q "$ROOT/wt-b" "$R9BASE" || { echo "HARD-FAIL (R-9): wt-b" >&2; exit 1; }
+git worktree add -q "$ROOT/wt-n" "$R9BASE" || { echo "HARD-FAIL (R-9): wt-n" >&2; exit 1; }
+git worktree add -q "$ROOT/wt-at" "$R9BASE" || { echo "HARD-FAIL (R-9): wt-at" >&2; exit 1; }
+# Ein konstanter at-Wert für die Sandbox (Wanduhr-frei) — die at-Exzeption wird
+# bewusst als legitime Abweichung modelliert, nicht gemashat.
+SANDBOX_AT="2026-08-20T12:00:00Z"
+
+run9_worktree() { # $1=wt $2=name $3=modus(clean|divergent|atgap)
+ local wt="$1" name="$2" mode="$3" at_val wan
+ (
+ set -e
+ cd "$wt" || exit 9
+ git checkout -qf "$R9BASE"
+ git clean -qfd wiki raw
+ git config user.email "sandbox@test" && git config user.name "Sandbox"
+ # Eingabe-Set aus dem Manifest: neue Source, deren Term den Alpha-Body trifft.
+ cat > raw/alpha-v2.md <<'EOF'
+### S-3
+Evidenz v2: Alpha erweitert um eine synchrone Kopplung.
+EOF
+ git add -A && git commit -qm "Evidenz v2 (R-9)"
+ # Deterministische Routing-Projektion (gleiche Regeln wie Haupt-Skript).
+ m_term=$(awk '/^terms:/{f=1;next} /^[a-z_]+:/{f=0} f && /^ - /{sub(/^ - /,""); print}' "$ROOT/manifest.yaml")
+ [ -n "$m_term" ] || { echo "HARD-FAIL (R-9): Manifest ohne terms" >&2; exit 9; }
+ TERM_NORM=$(norm "$m_term")
+ cand=""
+ esc=$(printf '%s' "$TERM_NORM" | sed 's|[][\.*^$+?(){}|]|\\&|g')
+ for f in wiki/*.md; do
+ case "$(basename "$f")" in index.md|log.md) continue;; esac
+ body=$(tr -d '\r' < "$f" | awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}')
+ body=$(norm "$body")
+ if printf '%s' "$body" | grep -Eq "(^|[^a-z0-9])${esc}([^a-z0-9]|$)"; then
+ [ -n "$cand" ] && cand="$cand $(basename "$f" .md)" || cand="$(basename "$f" .md)"
+ fi
+ done
+ [ -n "$cand" ] || { echo "HARD-FAIL (R-9): Candidate-Liste leer — run-Feststellung unbrauchbar" >&2; exit 9; }
+ routing="UPDATE"
+ # at: je Run ein eigenständiger (deterministischer) Wert — für die Exzeption nutzen
+ # wir den konstanten Sandbox-at, im atgap-Modus eine bewusste Abweichung.
+ at_val="$SANDBOX_AT"
+ if [ "$mode" = "atgap" ]; then
+ at_val="2026-08-20T13:00:00Z"
+ fi
+ # Normalform-Pin: der at-Wert ist ein volles ISO-8601-Datetime (§5.15 Pkt. 6, §6.5-Pkt.-2).
+ case "$at_val" in
+ [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T*Z) ;;
+ *) echo "HARD-FAIL (R-9): at-Normalform verletzt ($at_val)" >&2; exit 9;;
+ esac
+ mkdir -p "$ROOT/receipts"
+ {
+ echo "baseline: $R9BASE"
+ echo "generated.at: $at_val"
+ echo "terms: $m_term"
+ echo "candidates: $cand"
+ echo "order: $cand"
+ echo "routing: $routing"
+ echo "at.normalform: iso8601"
+ if [ "$mode" = "divergent" ]; then
+ echo "candidates: other-candidate"
+ fi
+ } > "$ROOT/receipts/$name.receipt"
+ # BUNDLE-MUTATION + BYTE-NACHWEIS (F-27, §5.15 Pkt. 6/A0-19): der
+ # Zwei-Run-Abgleich verlangt byte-identische MUTIERTE Bundle-Bestandteile,
+ # nicht nur identische Receipt-Felder. Wir mutieren wiki/alpha.md zu einem
+ # deterministischen Stand — einziges laufabhängiges Feld ist generated.at
+ # (Sandbox-Konstante bzw. atgap-Abweichung) — und sichern je Datei den
+ # SHA-256 (voll) sowie den SHA-256 mit maskierter at-Zeile. Der divergente
+ # Modus (run9n) weicht BUNDLE-sichtbar ab (synchrone-Zeile), sodass die
+ # Negativ-Kontrolle auch auf Bundle-Ebene hart FAIL ist; der atgap-Modus
+ # weicht nur im generated.at-Feld ab (Exzeption).
+ cat > wiki/alpha.md <> wiki/alpha.md
+ fi
+ git add -A
+ git commit -qm "R-9 Mutation ($name)" 2>/dev/null || true
+ R9_COMMIT_HASH=$(git rev-parse HEAD)
+ full_list=""
+ masked_list=""
+ for f in $(git ls-tree -r --name-only HEAD -- wiki/ | grep -vE '/?(index|log)\.md$'); do
+ full=$(sha256sum "$f" | awk '{print $1}')
+ masked=$(sed 's|^ at:.*| at: |' "$f" | sha256sum | awk '{print $1}')
+ full_list="$full_list $f=$full"
+ masked_list="$masked_list $f=$masked"
+ done
+ : > "$ROOT/receipts/$name.bundle"
+ printf 'run: %s\ncommit: %s\nfull: %s\nmasked: %s\n' \
+ "$name" "$R9_COMMIT_HASH" "$full_list" "$masked_list" >> "$ROOT/receipts/$name.bundle"
+ echo " [bundle] $name => commit $R9_COMMIT_HASH full=$full_list"
+ )
+ local rc=$?
+ [ $rc -eq 0 ] || { echo "HARD-FAIL (R-9): Lauf $name (rc=$rc)" >&2; exit 1; }
+}
+echo "--- Lauf A (clean) ---"
+run9_worktree "$ROOT/wt-a" run9a "clean"
+echo "--- Lauf B (clean) ---"
+run9_worktree "$ROOT/wt-b" run9b "clean"
+R9A=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9a.receipt" | grep -v '^generated.at')
+R9B=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9b.receipt" | grep -v '^generated.at')
+[ -n "$R9A" ] && [ -n "$R9B" ] || { echo "HARD-FAIL (R-9): Receipts leer (Vakuum)" >&2; exit 1; }
+if [ "$R9A" != "$R9B" ]; then
+ echo "HARD-FAIL (R-9): Zwei-Run-Identität verletzt (candidates/order/routing/terms/at.normalform):" >&2
+ diff -u <(printf '%s\n' "$R9A") <(printf '%s\n' "$R9B") >&2 || true
+ exit 1
+fi
+echo " BEFUND: positive Identität byte-gleich (candidates/order/routing/terms/at.normalform) — NICHT-VAKUUM:"
+echo "$R9A" | sed 's/^/ /'
+# Nicht-Vakuum: alpha Kandidat.
+case "$R9A" in *alpha*) ;; *) echo "HARD-FAIL (R-9): nicht-vakuum Assertion — alpha fehlt" >&2; exit 1;; esac
+# NEGATIVE Kontrolle: konstruierte Abweichung hart FAIL.
+echo "--- NEGATIVE Kontrolle (divergent) ---"
+run9_worktree "$ROOT/wt-n" run9n "divergent"
+R9N=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9n.receipt" | grep -v '^generated.at')
+[ -n "$R9N" ] || { echo "HARD-FAIL (R-9): Negativ-Receipt leer (Vakuum)" >&2; exit 1; }
+if [ "$R9N" = "$R9A" ]; then
+ echo "HARD-FAIL (R-9): konstruierte Abweichung unerkannt — Negativ-Kontrolle muss FAIL" >&2; exit 1
+else
+ echo " BEFUND: konstruierte AD-16-Abweichung (candidates-Block) erkannt — hart FAIL, kein Vakuum (BS-7-Nachführung)"
+fi
+# at-Exzeption (P-L2-6): eine legitime at-Abweichung wird NICHT als AD-16 gemeldet;
+# die übrigen deterministischen Felder sind byte-identisch.
+echo "--- at-Exzeption (atgap) ---"
+run9_worktree "$ROOT/wt-at" run9at "atgap"
+R9AT_REST=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9at.receipt" | grep -v '^generated.at')
+R9AT_AT=$(grep '^generated.at:' "$ROOT/receipts/run9at.receipt")
+if [ "$R9AT_REST" != "$R9A" ]; then
+ echo "HARD-FAIL (R-9): atgap-Run weicht außerhalb at ab (nur at darf differieren):" >&2
+ diff -u <(printf '%s\n' "$R9A") <(printf '%s\n' "$R9AT_REST") >&2 || true
+ exit 1
+fi
+if [ "$R9AT_AT" = "$(grep '^generated.at:' "$ROOT/receipts/run9a.receipt")" ]; then
+ echo "HARD-FAIL (R-9): atgap-Run hat keine at-Abweichung erzeugt (Exzeption nicht ausgeübt)" >&2; exit 1
+fi
+echo " BEFUND: at-Exzeption ausgeübt — nur generated.at differiert, übrige Felder byte-identisch; legitime at-Abweichung NICHT als AD-16 gemeldet (§5.14 Pkt. 3, §5.15 Pkt. 6)"
+# BUNDLE-BYTE-VERGLEICH (patch F-27, §5.15 Pkt. 6/A0-19): der Zwei-Run-Abgleich
+# verlangt byte-identische MUTIERTE Bundle-Bestandteile, nicht nur identische
+# Receipt-Felder. Wir vergleichen die SHA-256 der mutierten wiki/-Dateien der
+# zwei clean-Runs (aI b) sowie des atgap-Runs — letzterer bis auf die benannte
+# at-Ausnahme (Pkt. 6, Pkt. 3: allein generated.at darf differieren).
+# Bundle-VERGLEICH (patch F-27, §5.15 Pkt. 6/A0-19): byte-identische mutierte
+# Bundle-Bestandteile der zwei clean-Runs (voll, inkl. at) sowie des atgap-Runs
+# gegenüber dem clean-Run (maskiert, at ausgenommen). Divergenter Run => hart FAIL.
+B9AF=$(awk '/^full:/{sub(/^full: /,""); print; exit}' "$ROOT/receipts/run9a.bundle")
+B9BF=$(awk '/^full:/{sub(/^full: /,""); print; exit}' "$ROOT/receipts/run9b.bundle")
+B9AM=$(awk '/^masked:/{sub(/^masked: /,""); print; exit}' "$ROOT/receipts/run9a.bundle")
+B9TM=$(awk '/^masked:/{sub(/^masked: /,""); print; exit}' "$ROOT/receipts/run9at.bundle")
+B9NM=$(awk '/^masked:/{sub(/^masked: /,""); print; exit}' "$ROOT/receipts/run9n.bundle")
+if [ -z "$B9AF" ] || [ -z "$B9BF" ] || [ -z "$B9AM" ] || [ -z "$B9TM" ] || [ -z "$B9NM" ]; then
+ echo "HARD-FAIL (R-9-bundle): Bundle-Hash-Artefakt unvollständig (Vakuum)" >&2; exit 1
+fi
+if [ "$B9AF" != "$B9BF" ]; then
+ echo "HARD-FAIL (R-9-bundle): Bundle-State-Hashes der zwei clean-Runs differieren — byte-identische MUTIERTE Bestandteile verletzt:" >&2
+ diff -u <(printf '%s\n' "$B9AF") <(printf '%s\n' "$B9BF") >&2 || true
+ exit 1
+fi
+echo " BEFUND: byte-identische mutierte Bundle-Bestandteile der zwei clean-Runs (SHA-256 voll je wiki/-Datei, ohne index/log) — nicht nur Receipt-Felder (A0-19)"
+if [ "$B9AM" != "$B9TM" ]; then
+ echo "HARD-FAIL (R-9-bundle): atgap-Run-Bundle weicht bei maskiertem at ab (byte-identisch bis auf generated.at erwartet):" >&2
+ diff -u <(printf '%s\n' "$B9AM") <(printf '%s\n' "$B9TM") >&2 || true
+ exit 1
+fi
+echo " BEFUND: atgap-Run-Bundle byte-identisch zum clean-Run außer der benannten at-Ausnahme (maskiert), §5.15 Pkt. 6/§5.14 Pkt. 3"
+if [ "$B9NM" = "$B9AM" ]; then
+ echo "HARD-FAIL (R-9-bundle): divergenter Run-Bundle ununterscheidbar vom clean-Run (Negativ-Kontrolle muss FAIL)" >&2; exit 1
+fi
+echo " BEFUND: divergenter Run-Bundle an der mutierten Datei nachweisbar ungleich (hart FAIL, kein Vakuum)"
+echo "RESULT: PASS — R-9: ZWEI_RUN_IDENTISCH — positive Identität NICHT-VAKUUM (2 getrennte Worktrees, gegeneinander verglichen, kein hart codierter Erwartungswert) + NEGATIVE Kontrolle hart FAIL + at-Exzeption praktisch ausgeübt (nur-at-differiert, nicht-mashat); Manifest datei-pfadbasiert (AC-6, AD-17h/A0-19, §5.15 Pkt. 6)"
+
+# =============================================================================
+# Abschluss — Gesamt-Exit 0 (nur wenn alle R-Szenarien harte PASS)
+# =============================================================================
+echo
+echo "===== Sandbox abgeschlossen (R-1, R-1b, R-2..R-9) ====="
+echo "Alle Szenarien harte PASS, 0 HARD-FAIL."
+echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"
+exit 0
diff --git a/_bmad-output/implementation-artifacts/spec-3-9-deterministische-relevanz-und-reconcile-routing-schliessen.md b/_bmad-output/implementation-artifacts/spec-3-9-deterministische-relevanz-und-reconcile-routing-schliessen.md
new file mode 100644
index 0000000..89e4adc
--- /dev/null
+++ b/_bmad-output/implementation-artifacts/spec-3-9-deterministische-relevanz-und-reconcile-routing-schliessen.md
@@ -0,0 +1,190 @@
+---
+title: 'Story 3.9 — Deterministische Relevanz- und Reconcile-Routing schließen'
+type: 'feature'
+created: '2026-08-20'
+status: 'done'
+baseline_commit: '2f079ee3c87311cda9c9f07614c5e20c869b4500'
+review_loop_iteration: 2
+context:
+ - '_bmad-output/implementation-artifacts/epic-3-context.md'
+---
+
+
+
+## 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 | Run-FAIL **vor jeder Mutation** (AD-3: keine modifizierte/gelöschte committete Source als Input) | textuell benannt (NFR-4) |
+| RESERVED_ZIEL_INDEX_LOG | neues Concept-Ziel mit Slug `index`/`log`/reserviertem Bundle-Name | keine Datei geschrieben; deterministischer Hold verlangt disambiguierte Identität | textuell benannt, Run „teilweise erfolgreich" |
+| ZWEI_RUN_IDENTISCH | gleicher Git-State + gleiches Eingabemanifest, zwei Läufe | identische Candidate-Liste, Reihenfolge und Routing-Entscheidung; Assertion nicht-vakuum | PASS; Abweichung = AD-16-Klassifikationsdefekt (§5.14 Pkt. 4) |
+
+## Code Map
+
+- `schema/compiler.md` — **primär mutiert** (D-3): neue Sektion **§5.15 „Deterministische Relevanz- & Reconcile-Routing (Story 3.9)"** (nach §5.14 Z. 377, vor §6 Z. 379; Pkt. 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` → `in-progress`; `last_updated` (Format `MM-DD-YYYY HH:MM`).
+- `_bmad-output/implementation-artifacts/deferred-work.md` — **append**: Defers D-8 (Mehrfach-Term-Vereinigung) und D-9 (Orphan-Term-Ableitung, fester 2-Datei-Scan) → aufgegriffen/geschlossen; Umlaut-Defer bleibt offen (wie notiert, kein Instruktions-Defekt).
+- `wiki/log.md` — **append** (Vertrag §5, bestehende Bullets unverändert): Story-3.9-Eintrag (Verankerung §5.15, Sandbox-Nachweis R-1..R-9, Status-Flip, Validator-Verdikt).
+- `_bmad-output/implementation-artifacts/epic-3-context.md` — **mutiert** (gemäß genehmigtem Sprint-Change-Proposal 2026-08-20 „Artifact Impact: epic-3-context.md synchronisiert"; Header „Edit freely"): Technical Decision Z. 39 „Zielzustand … geplant für Story 3.9 … noch nicht verankert; §3.2 ist bis dahin maßgeblich" → Ist/§5.15-Verankerung; Z. 41/43 (Story 3.11/3.12) bleiben Zielzustand.
+
+**Read-only evidence (AD-3):** `schema/validator.md` (Rev 9), `schema/wiki-compiler.md`, `adapters/`, `raw/` (z. B. `raw/architecture-spine/architecture-spine-2026-08-14.md` AD-3/AD-13/AD-17h; `raw/epics/epics-2026-08-14.md` FR-4/FR-5/FR-6, A0-18/A0-19). `schema/canonical-terms.md` append-only unangetastet (leer; keine Einträge nötig — Termgewinnung lebt als Regel in §5.15/§3.2).
+
+## Tasks & Acceptance
+
+**Execution:**
+- [ ] `schema/compiler.md` — §5.15 einfügen (nach §5.14, vor §6): Pkt. 1–6 gemäß Intent; keine neuen Prädikate/§7-Klassen/Keys; §7-Vorbehalt und §8-Revisionslog **Revision 3.4** nachführen
+- [ ] `_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh` — R-1..R-9, harte PASS/FAIL, Zwei-Run nicht-vakuum, Exit 0
+- [ ] `_bmad-output/implementation-artifacts/sprint-status.yaml` — Key 3-9 → `in-progress`; `deferred-work.md` — D-8/D-9 aufgegriffen; `wiki/log.md` — Story-3.9-Eintrag (Verankerung, Sandbox, Validator-Verdikt)
+- [ ] `_bmad-output/implementation-artifacts/epic-3-context.md` — Z. 39 Zielzustand → §5.15-Ist (Z. 41/43 unverändert)
+
+**Acceptance Criteria:**
+- Given einen committeten Git-State und ein kanonisches Eingabemanifest, when Candidate-Terme gewonnen werden, then folgt die Gewinnung einem geschlossenen, geordneten Algorithmus oder einem expliziten, persistierten Term-Manifest — keine freie Producer-Auswahl (AC-1).
+- Given semantisch gleiche Schreibweisen (Groß-/Kleinschreibung, Leerzeichen, Unterstrich, Bindestrich, En-Dash, Em-Dash), when die Stufe-a-Suche läuft, then werden Suchterm und Concept-Body identisch normalisiert und literal-sicher verglichen; `index.md`-Treffer bleiben für die Traversal-Stufe erhalten (AC-2).
+- Given interpretierte Evidenz, when Reconcile abgeschlossen wird, then gilt genau eine Routing-Tabelle: bestehender Match → `UPDATE`; eigenständige neue Wissenseinheit → `CREATE`; nicht klassifizierbare Evidenz → `ORPHAN/HOLD`; bereits vollständig repräsentierte identische Evidenz → `NO_OP` (AC-3).
+- Given eine geänderte oder gelöschte bereits committete Datei unter `raw/`, when der Run seine Eingaben prüft, then schlägt er vor jeder Mutation fehl; akzeptiert werden nur neu hinzugefügte oder separat versionierte Sources (AD-3) (AC-4).
+- Given ein neues Concept-Ziel, when dessen Slug `index` oder `log` beziehungsweise ein anderer reservierter Bundle-Name wäre, then wird das Ziel nicht geschrieben und ein deterministischer Hold verlangt eine disambiguierte Identität (AC-5).
+- Given gleicher Git-State plus gleiches Eingabemanifest, when zwei Runs ausgeführt werden, then erzeugen sie dieselbe Candidate-Liste, Reihenfolge und Routing-Entscheidung — belegt durch positive und negative ausführbare Fixtures (AD-17h, A0-19) (AC-6).
+
+## Spec Change Log
+
+- **Review-Loop-2 bad_spec-Loopback (2026-08-20):** bmad-code-review (Blind Hunter 28 / Edge Case Hunter 10 / Verification Gap 9 verifizierte Findings, D-3-Gewichtung) ergab **2 bad_spec** (innerer Instruktions-Widerspruch), 4 patch, 2 defer, restliche als reject/verworfen; **kein intent_gap** (kein Eingriff in ``). **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).
+
+## 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 `in-progress` (finaler `review`/`done`-Flip per Step-04/05).
+ [`sprint-status.yaml:62`](sprint-status.yaml#L62)
+
+- Defers D-8/D-9: Mehrfach-Term-Vereinigung + Orphan-Term-Ableitung als `aufgegriffen` markiert.
+ [`deferred-work.md:553`](deferred-work.md#L553)
+
+- epic-3-context: Technical Decision Z. 39 von Zielzustand auf §5.15-Ist nachgeführt.
+ [`epic-3-context.md:39`](epic-3-context.md#L39)
+
+- wiki/log.md: Story-3.9-Eintrag (Verankerung + Sandbox-Nachweis) — Erhaltungs-Invariante gewahrt.
+ [`log.md:4`](../../wiki/log.md#L4)
diff --git a/_bmad-output/implementation-artifacts/sprint-status.yaml b/_bmad-output/implementation-artifacts/sprint-status.yaml
index 3f78bb7..58f15a2 100644
--- a/_bmad-output/implementation-artifacts/sprint-status.yaml
+++ b/_bmad-output/implementation-artifacts/sprint-status.yaml
@@ -29,7 +29,7 @@
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
# - Retrospective appends its action items to action_items; the status view surfaces open ones
generated: 08-14-2026 00:00
-last_updated: 08-20-2026 17:04
+last_updated: 08-21-2026
project: wow20
project_key: NOKEY
tracking_system: file-system
@@ -59,7 +59,7 @@ development_status:
3-6-lease-staleness-recovery-basis-absichern: done
3-7-reason-mutate-trennung-und-konsistenz-endzustand-sicherstell: done
3-8-determinismus-vertrag-ad-17h-als-agent-instruktions-validato: done # Review-Loop-3-Abschluss 2026-08-20 (bmad-code-review; D-2-Entscheidung). Hinweis: die Abschluss-Reihenfolge „3.9 → 3.10 / 3.11 → 3.12 → 3.8 Abschluss → 3.13 Abnahme" des genehmigten Sprint-Change-Proposal 2026-08-20 betrifft das Epic-3-Abnahmegate (3.13) — die Story-3.8-Instruktionsverankerung ist abgeschlossen (done); die 3.9–3.12-Verankerungen und die 3.13-Abnahme bleiben offen (epic-3 remains in-progress).
- 3-9-deterministische-relevanz-und-reconcile-routing-schliessen: backlog
+ 3-9-deterministische-relevanz-und-reconcile-routing-schliessen: review
3-10-inkrementelle-update-und-synthese-erhaltung-absichern: backlog
3-11-root-scope-leasing-atomar-akquirieren: backlog
3-12-lease-lifecycle-und-commit-abschluss-transaktional-schliessen: backlog
diff --git a/schema/compiler.md b/schema/compiler.md
index 8538932..2b200bb 100644
--- a/schema/compiler.md
+++ b/schema/compiler.md
@@ -60,7 +60,7 @@ Diese Sektion ist der **einzige Instruktions-Ort** der feinkörnigen, **textuell
- **(a) Form:** Die Candidate-Liste ist die Menge der betroffenen Concept-Pfade als **relative OKF-Pfade ohne `.md`** (AD-7a). Normalisierung der Ausgabe: aus jedem Treffer `wiki/.md` werden `wiki/`-Präfix und `.md`-Suffix gestrippt (deterministischer Schritt → `wiki/knowledge-kompilation-inkrementell.md` wird `knowledge-kompilation-inkrementell`).
- **(b) Reihenfolge (Zuwachs-Sicht-Ordnung):** Die Erhebung ordnet die Candidate-Liste deterministisch in **Zuwachs-Sicht-Ordnung** — Stufe-a-Treffer zuerst, danach Stufe-b-Treffer, danach Stufe-c-Treffer; **innerhalb jeder Stufe rein lexikografisch aufsteigend (LC_ALL=C bzw. deterministische byte-Ordnung, AD-17h)**. Die Reihenfolge des ziehenden Terms bestimmt nur die **Verarbeitungsreihenfolge** der Terme in Stufe a (Interpretation/Erhebung), **nicht** die Reihenfolge der Candidate-Liste: dieselbe Treffermenge → identische Liste, unabhängig davon, in welcher Reihenfolge die Terme gezogen/verarbeitet wurden (AD-17h/A0-19). Die Stufe-b/c-Treffer sind damit **positional bestimmt** (nach allen Stufe-a-Treffern), nicht vom Dateisystem-Traversal abhängig.
- **(c) Keine Duplikate:** Vereinigung über alle Terme und Stufen, bereinigt über die besuchte Menge (Pkt. 1c/2c) — jeder Pfad erscheint genau einmal.
- - **(d) NO_MATCH:** Trifft kein Term ein bestehendes Concept, ist die Candidate-Liste **leer** → `UNTOUCHED_CONCEPT` (Story-3.1-Pfad): keine Mutation, kein `log.md`-Zusatz (leere Menge ist Teilmenge jeder erlaubten Menge — Ghost-Diff-negativ, §5.9 Pkt. 5).
+ - **(d) NO_MATCH:** Trifft kein Term ein bestehendes Concept, ist die Candidate-Liste **leer** → `UNTOUCHED_CONCEPT` (Story-3.1-Pfad): keine Mutation, kein `log.md`-Zusatz (leere Menge ist Teilmenge jeder erlaubten Menge — Ghost-Diff-negativ, §5.9 Pkt. 5). (**§5.15-Verweis-Anker, Story 3.9:** die NO_MATCH-Routing-Entscheidung einer **leeren Candidate-Liste bei neuer Evidenz** liegt im **Bewertungsraum der Zellen 2 (CREATE-Prädikat, eigenständig interpreterbar + abgeleiteter Ziel-Pfad + Reserviertheits-Check passiert) bzw. 3 (ORPHAN/HOLD, nicht klassifizierbar)** der exklusiven Routing-Tabelle in **§5.15 Pkt. 3** — **nicht** Zelle 4 (NO_OP); NO_OP (Zelle 4) ist ausschließlich die **Unter-Entscheidung des Update-Pfads** (bestehende Evidenz bereits vollständig repräsentiert). `UNTOUCHED_CONCEPT` gilt hier unverändert für den Fall, dass **gar keine Zuwachs-Evidenz** zu reconciliieren ist (Ghost-Diff-negativ), nicht für neue Einheiten. §3.2 bleibt NO_MATCH-Anker der Erhebung, §5.15 Pkt. 3 die Routing-Zuordnung — Vertrags-Identität durch Anker, keine Re-Negotiation.)
- **(e) Gleichheits-Identität:** Gleicher Git-State + gleiche Eingabemenge → identische Candidate-Liste, in identischer Reihenfolge (AD-17h/A0-19). Der Selbsttest (Membership + Zwei-Run-Identität) wird in der Story-Specifizierungs-Verifikation und im `wiki/log.md`-Nachweis belegt.
## 4. Synthetisieren (Provenienz & Trust)
@@ -374,7 +374,30 @@ Diese Sektion ist der **einzige Instruktions-Ort der geschlossenen Determinismus
- **Mechanische Bestätigung (Agent-Instruktions-Validator):** Die Bestätigung ist der **textuell festgehaltene, re-executierbare Vergleich der zwei Ausführungen aus getrennten Worktrees/frischen Agent-Kontexten** (log.md-Nachweis je Run mit ``, D-2; der Befund „identisch bis auf `at`" wird textuell benannt). **Kein neuer Prozess/Server/MCP, kein Standalone** (D-3/AD-11): der Validator ist die **Instruktion selbst**, von zwei unabhängigen Ausführungskontexten einmal ausgeführt und durch den Abgleich der beiden Ausgänge bestätigt. **Sandbox-Restlücke (Review-Loop-3, P-5):** die Sandbox demonstriert die zwei frischen Agent-Kontexte **mechanisch simuliert** (zwei Subshell-Läufe in getrennten Worktrees desselben Skripts — getrennte Ausführungskontexte über demselben committeten Baum, keine Session-Wiederholung); eine Verletzung durch *nicht* getrennte Ausführungskontexte ist damit strukturell nicht auslösbar — die Restlücke wird hiermit textuell benannt; der Nachweis echter frischer Kontexte erfolgt im Story-3.13-Abnahmegate über reale Agent-Läufe.
3. **Ausnahme-Menge des Bundle-State-Vergleichs (vollständig, deterministisch):** Der Bundle-State-Vergleich zweier unabhängiger Runs lässt **genau eine** benannte Differenz zu: den **`generated.at`-Wanduhr-Gap** (A0-20-Konvention, §5.9 Pkt. 2, §5.10 Pkt. 8 — ein Wanduhr-Zeitstempel im `generated.at`-Feld bzw. `verified[].at`, der zwischen zwei Runs desselben Git-States abweichen darf). Der Gap ist **dokumentiert, kein stiller Ausschluss**: die Ausnahme bezieht sich **ausschließlich** auf den `at`-Feld-Wert; **alle übrigen Bundle-State-Bestandteile** (Pkt. 1 (a)/(b)/(c)) sind zwischen zwei Runs desselben Git-States **byte-identisch**. Jede **andere** Differenz liegt **außerhalb** der Ausnahme-Menge.
4. **Abweichungs-Klassifikation (AD-16-Klassifikationsdefekt, kein Rauschen):** Eine bei der Zwei-Run-Bestätigung festgestellte Differenz außerhalb der benannten Ausnahme-Menge (Pkt. 3) **ist ein Fehler im AD-16-Klassifikations-Mechanismus** (FT-10/AD-17h-AC): der Run wird **textuell benannt** (NFR-4) und **korrigiert bzw. rollt zurück** (Zustands-Restaurations-Invariante, §5.13 Pkt. 3) — die Abweichung wird **nicht** als akzeptables Rauschen oder Umgebungs-Streuung toleriert. Erzeugt ein deterministischer Bestandteil (Pkt. 1) in zwei Runs unterschiedliche Werte, ist die Ursache in der Ausführungs-Instruktion zu suchen und dort zu beheben, **bevor** der Vertrag als bestätigt gilt. Die textuelle Benennung (NFR-4) ist verpflichtend; der Befund wird (ggf. als korrigierter zweiter Lauf) erneut bestätigt.
-5. **Normalisierungs-/Match-/Orphan-Schließung (§3.2/§5.10-Verankerung):** Die bekannten deterministischen Lücken der Relevanz-/Synthese-Erhebung sind mit dieser Sektion **geschlossen** (als deterministische Regel-Ergänzungen, ohne Umbruch des bestehenden Wortlauts): die **Em-Dash-Kollaps-Klasse**, die **Kollaps-Reichweite** und der **Match-Scope der Stufe a** gelten wie in **§3.2-Pkt.-1b** (geschlossene Determinismus-Lücken) definiert; die **Orphan-Politik** (§5.10 Pkt. 8) gilt als deterministische **Reconcile-Orphan-Regel**. Damit sind die §3.2-/§5.10-Erhebungen über den committeten Zustand **vollständig pinbar** — ein Bestandteil, der zwischen zwei Runs differiert (Ziel-Pfad via §3.2/§5.7, Candidate-Liste, Form-Zuordnung, Verwaist-Befund), ist ein AD-16-Klassifikationsdefekt (Pkt. 4), keine offene Frage. **Scope-Präzisierung (Review-Loop-3, P-8):** „vollständig pinbar" und „keine offene Frage" gelten **für die mit dieser Sektion geschlossenen Determinismus-Lücken** (Em-Dash-Kollaps-Klasse, Kollaps-Reichweite, Match-Scope Stufe a, Reconcile-Orphan-Regel); zwei Fragen sind **bewusst nicht** damit geschlossen und bleiben als benannte Defers sichtbar (keine stillen offenen Fragen): (i) die **Umlaut-vs-Transkription-Divergenz** im Match-Pfad (Defer in `_bmad-output/implementation-artifacts/deferred-work.md`, Defer-Block Review-Loop-3, „Umlaut-vs-Transkription im Match-Pfad unübend"; Home: Sandbox-Vereinheitlichung oder folgende Compiler-Instruktions-Revision — kein Instruktions-Defekt) und (ii) die **Story-3.9-ACs** (Term-Gewinnung/Routing) sind erst **geplant** und in `compiler.md` noch nicht verankert (Sprint-Change-Proposal 2026-08-20: 3.9 → 3.10 / 3.11 → 3.12 → 3.8 Abschluss — die Zielzustands-Aussagen dieses Bullets gelten erst nach der Story-3.9-Verankerung; bis dahin ist §3.2 der maßgebliche Regeltext).
+5. **Normalisierungs-/Match-/Orphan-Schließung (§3.2/§5.10-Verankerung):** Die bekannten deterministischen Lücken der Relevanz-/Synthese-Erhebung sind mit dieser Sektion **geschlossen** (als deterministische Regel-Ergänzungen, ohne Umbruch des bestehenden Wortlauts): die **Em-Dash-Kollaps-Klasse**, die **Kollaps-Reichweite** und der **Match-Scope der Stufe a** gelten wie in **§3.2-Pkt.-1b** (geschlossene Determinismus-Lücken) definiert; die **Orphan-Politik** (§5.10 Pkt. 8) gilt als deterministische **Reconcile-Orphan-Regel**. Damit sind die §3.2-/§5.10-Erhebungen über den committeten Zustand **vollständig pinbar** — ein Bestandteil, der zwischen zwei Runs differiert (Ziel-Pfad via §3.2/§5.7, Candidate-Liste, Form-Zuordnung, Verwaist-Befund), ist ein AD-16-Klassifikationsdefekt (Pkt. 4), keine offene Frage. **Scope-Präzisierung (Review-Loop-3, P-8):** „vollständig pinbar" und „keine offene Frage" gelten **für die mit dieser Sektion geschlossenen Determinismus-Lücken** (Em-Dash-Kollaps-Klasse, Kollaps-Reichweite, Match-Scope Stufe a, Reconcile-Orphan-Regel); zwei Fragen sind **bewusst nicht** damit geschlossen und bleiben als benannte Defers sichtbar (keine stillen offenen Fragen): (i) die **Umlaut-vs-Transkription-Divergenz** im Match-Pfad (Defer in `_bmad-output/implementation-artifacts/deferred-work.md`, Defer-Block Review-Loop-3, „Umlaut-vs-Transkription im Match-Pfad unübend"; Home: Sandbox-Vereinheitlichung oder folgende Compiler-Instruktions-Revision — kein Instruktions-Defekt) und (ii) die **Story-3.9-ACs** (Term-Gewinnung/Routing) sind in **§5.15 dieser Instruktion verankert** (Story 3.9, Deterministische Relevanz- & Reconcile-Routing) — **Story-3.9-Auflösung (Review-Loop-2-Re-Ableitung, vgl. §7-Relevanzbestimmung-Bullet):** der vormals „noch nicht verankert"-Vorbehalt dieses Bullets ist mit der Story-3.9-Verankerung **aufgelöst**; maßgeblich sind ab der Story-3.9-Übernahme §5.15 Pkt. 1–6 für die geschlossene Termgewinnung/Routing-Ebene sowie der **nachgeführte §3.2-Pkt.-3d-Verweis-Anker** (leere Candidate-Liste → CREATE/ORPHAN-Bewertungsraum, Zellen 2/3 — nicht NO_OP; NO_OP bleibt Update-Unter-Entscheidung, §5.15 Pkt. 3) und **Pkt. 4** (Status-Codes inkl. R = Run-FAIL, C = wie A); die §3.2-/§5.9-/§5.10-/§5.14-Verankerungen bleiben davon unberührt und textuell unverändert — §5.15 referenziert sie statt sie umzubauen, gleiche Fugen-Identitäts-Präzedenz wie §5.14/Story 3.8.
+
+## 5.15 Deterministische Relevanz- & Reconcile-Routing (Story 3.9)
+
+Die Relevanz-Findungs-Mechanik (§3.2, Story 3.2) und die Determinismus-/Bestätigungs-Mechanik (§5.14, Story 3.8) bleiben textuell unverändert; diese Sektion **schließt die Routing-Ebene des Reconcile als eine geschlossene, exklusive Tabelle** (AD-17h/A0-19, Story 3.9; §5.14-Pkt.-5-/§7-„Story-3.9-ACs noch nicht verankert"-Vorbehalt hiermit aufgelöst — siehe §5.14-Pkt.-5-Scope-Präzisierung und §7-Bullet). Sie führt **kein** neues Prädikat, **keine** neue §7-Invaliditätsklasse und **keinen** neuen Frontmatter-/Format-Key ein; jede Zelle referenziert die bestehende Mechanik **Wortlaut-unverändert** (Referenz statt Re-Negotiation). Die AD-3-read-only-Invariante bleibt: `schema/validator.md`, `schema/wiki-compiler.md`, `adapters/`, `raw/` und `schema/canonical-terms.md` (append-only) werden nicht mutiert.
+
+1. **Termgewinnung (geschlossener, geordneter Algorithmus — AC-1):** Die Candidate-Terme eines Runs werden **nicht** vom Producer frei gewählt, sondern deterministisch aus der **Zuwachs-Sicht der committeten Evidenz** gewonnen (§5.9 Pkt. 6 R-1: `git diff --name-only -- raw/`). Pro Zuwachs-Datei unter `raw/` gilt: **Status-Codes `A`/`M`/`D`** — `--diff-filter=ACMR` liefert die akzeptierten Zuordnungen (die Status-Bedeutung: **A** = neu/kopiert (C zählt als A), **M**/*D* = modificiert/gelöscht, **R** = umbenannt; die Zuordnung fallspezifisch in Pkt. 4); die Ausgabe erfolgt deterministisch über `/dev/null`-Stable-Sortierung. Der **Dateiname→Term-Mapping**: vom Dateinamen die `.md`-Endung und ggf. ein Datums-Suffix (`YYYY-MM-DD`) strippen, verbleibende Trennzeichen (`-`, `_`, `–`, `—`, Leerzeichen) **auf `-` kollabieren** — beide Seiten identisch normalisiert: **lowercasing + Kollaps-Klasse `[-–— _]`→`-`** (genau die §3.2-Pkt.-1b-Normalisierung, Kollaps-Reichweite/Trim, §5.14 Pkt. 5; AC-2-Symmetrie) → dieser kollabierte, lowercasene Dateiname ist der **primäre Term** je Zuwachs-Datei; ein Dateiname mit mehreren `-`-getrennten, aus ≥2 Zeichen bestehenden Segmenten wird als **Vereinigung** mehrerer Terme geführt (Mehrfach-Term-Vereinigung, Defer **D-8** — hier aufgegriffen): der kollabierte Gesamt-Name (primärer Term) **plus** jedes ≥2-Zeichen-Segment als weiterer Term; **Einzelzeichen-Segmente** (Varianten-/Abkürzungs-Marker wie `-a`/`-b`) tragen **keinen** eigenen Term (deterministische Ableitung: `-`-getrennte Segmente mit bedeutungstragendem Inhalt, Länge ≥ 2). **`source.md`-Sidecars bleiben exkludiert** (Dokumentations-Seiteneffekt der Source-Bereitstellung, kein Zuwachs-Inhalt; die Sidecar-Datei trägt selbst keinen eigenen Term bei). **Alternativ zulässig:** ein **committetes, persistiertes Term-Manifest** als Run-Input (Teil des kanonischen Eingabemanifests, §5.14 Pkt. 2); es ist die **einzige** explizite Alternative — nie freie Producer-Auswahl. Die geordnete Term-Liste wird Bestandteil des **Run-Receipts** (AC-1/AC-6, §5.14 Pkt. 2). **Diskrepanz-/Fallback-Kopplung (§5.9 Pkt. 6):** widersprechen `git diff`-Befund und SHA-256-Record derselben Datei, gewinnt `git diff` (Commit-Boundary-Prinzip); ohne vorherige Mutations-Boundary gelten alle `raw/`-Dateien als Zuwachs. **Diff↔Manifest-Äquivalenz:** ein als Run-Input übergebenes Term-Manifest muss mit der aus der Zuwachs-Sicht ableitbaren Menge übereinstimmen (deterministischer Abgleich; abweichendes Manifest = Run-FAIL vor der Mutation).
+2. **Symmetrische Normalisierung + literal-sichere Suche (AC-2):** Suchterm und Concept-Body werden **identisch** normalisiert (lowercasing + `[-–— _]`→`-`-Kollaps, §3.2-Pkt.-1b — die Em-Dash-Variante bleibt in der Kollaps-Klasse, §5.14 Pkt. 5). Der Stufe-a-Vergleich ist **literal-sicher**: es wird auf Token-Basis verglichen (normalisierter Suchterm als literales Wort, begrenzt durch Nicht-Buchstaben-/Nicht-Ziffern-Grenzen — kein Teilzeichen-Trunkierungs-Treffer, kein Regex-Muster über den Actor-Body hinaus). **`index.md`-Treffer bleiben für die Traversal-Stufe** (§3.2-Pkt.-2b, TRAVERSAL_REACH_ONLY) erhalten — ein Stufe-a-Treffer auf `wiki/index.md` (oder eine Area-`index.md`) löst Stufe b aus, `index.md` selbst ist **kein Concept-Kandidat** (T2-Kommentar-Konvention; §3.2-Pkt.-2b-Satz). Kein neuer Normalisierungs-Operand (Umlaut-vs-Transkription-Divergenz bleibt benannter Defer, Ask-First).
+3. **Die eine exklusive Routing-Tabelle (AC-3):** Nach Interpretation und Reconcile-Erhebung (§3/§3.2) gilt **genau eine** der folgenden Zellen, in **dieser** Prüf-Reihenfolge (analog §5.9-Abgrenzungs-Reihenfolge, Design Notes — NO_OP ist eine Unter-Entscheidung des Update-Pfads, keine eigenständige Zelle für leere Candidate-Listen):
+
+ | # | Prüfung (in dieser Reihenfolge) | Zelle | referenzierte Mechanik (Wortlaut-unverändert) |
+ |---|-------------------------------|-------|----------------------------------------------|
+ | 1 | bestehender Concept-Match in der Candidate-Liste (§3.2-Pkt.-3d, Zuwachs-Sicht-Ordnung) | **UPDATE** | §3 Pkt. 2 / §5.9-Update; **Unter-Entscheidung:** reicht die bestehende Evidenz bereits vollständig identisch (engere Auslegung, kein echter neuer Beleg) → **NO_OP** (Zelle 4) statt Update — kein Duplikat, kein `at`-Bump, byte-identisches Ziel (§5.9 Pkt. 2-No-Op) |
+ | 2 | eigenständige neue Wissenseinheit, kein Match in der Candidate-Liste | **CREATE** | §5.1/§5.7-Neu-Anlage (Index-Regel, §5.7-Routing); **CREATE-vs-ORPHAN-Abgrenzung:** CREATE nur, wenn die Einheit als eigenständige, inhaltlich begründete Wissenseinheit interpreterbar ist (§2-Interpretation) **und** ein deterministischer Ziel-Pfad ableitbar ist (Pkt. 5-Reserviertheits-Check passiert); sonst Zelle 3 |
+ | 3 | nicht klassifizierbare Evidenz (kein Ziel-Pfad-Treffer; kein ableitbarer deterministischer Ziel-Pfad) | **ORPHAN/HOLD** | §5.10-Pkt.-8-Reconcile-Orphan-Regel / §5.14-Pkt.-5 (fail-closed: keine Wissensmutation, `raw/` unangetastet; Hold-Ausbau Home Story 3.10) |
+ | 4 | bereits vollständig repräsentierte, identische Evidenz | **NO_OP** | §5.9-Pkt.-2-No-Op / §3.2-Pkt.-3d (`UNTOUCHED_CONCEPT`); keine Mutation, kein `at`-Bump. **NO_OP ist ausschließlich die Unter-Entscheidung im Update-Pfad** (Zelle 1) — eine leere Candidate-Liste ist **niemals** NO_OP, sondern fällt in den Bewertungsraum von Zelle 2 (CREATE-Prädikat) bzw. Zelle 3 (ORPHAN/HOLD) |
+
+ **Leere Candidate-Liste (Zelle-2/Zelle-3-Bewertungsraum):** Trifft kein Term ein bestehendes Concept (leere Candidate-Liste), ist die Einheit im **CREATE/ORPHAN-Bewertungsraum** zu klassifizieren (Zellen 2/3): ist sie als eigenständige, inhaltlich begründete Wissenseinheit interpreterbar (§2-Interpretation) und ist ein deterministischer Ziel-Pfad ableitbar (Pkt. 5-Reserviertheits-Check passiert) → **CREATE** (Zelle 2); andernfalls (nicht klassifizierbar, kein Ziel-Pfad) → **ORPHAN/HOLD** (Zelle 3, fail-closed). **Niemals** NO_OP bei leerer Candidate-Liste. Der §3.2-Pkt.-3d-NO_MATCH-Anker (`UNTOUCHED_CONCEPT`/Story-3.1-Pfad) gilt unverändert für den Fall, dass gar keine neue Evidenz/Zuwachs-Einheit zu reconciliieren ist (Ghost-Diff-negativ, §5.9 Pkt. 5); eine **neue Evidenz** mit leerem Treffer-Match ist dagegen im Zelle-2/Zelle-3-Raum zu bewerten — nicht NO_OP.
+ **Stufe-b-Zelle (Traversal via `index.md`, §3.2-Pkt.-2b):** Candidate-Pfade aus dem Stufe-b-Traversal erhalten **keine eigene Zelle**, sondern werden derselben Tabelle zugeführt — ein Stufe-b-Kandidat, der einen bestehenden Concept-Pfad erreicht (gewurzelte Erreichbarkeit, §5.8), ist **UPDATE** (Zelle 1); ein Stufe-b-Kandidat, der über `index.md` auf eine **nicht existierende** Concept-Datei verweist (Dangling-Link im Traversal, §5.7-Pkt.-4-Auflösung), ist **ORPHAN/HOLD** (Zelle 3, kein CREATE — die `index.md`-Verlinkung ist kein eigenständiger Neu-Anlage-Stimulus; konsistent mit der Sandbox-R-5-Stufe-a-Regel). Jede Abweichung von genau-einer-Zelle ist ein AD-16-Klassifikationsdefekt (§5.14 Pkt. 4), keine stille Mehrfachklassifikation.
+4. **Raw-Immutability-Guard (AC-4):** Der Guard prüft den **Zuwachs-Befund** auf committete `raw/`-Dateien mit Status **`M`/`D`/`R`** (modifiziert/gelöscht/umbenannt — `git diff --name-status -- raw/`; die `raw/`-Treffer-Extraktion folgt §5.9 Pkt. 6 R-1). **Befund positiv (committete `raw/`-Datei im Zuwachs modifiziert/gelöscht/umbenannt)** → **Run-FAIL vor jeder Mutation** (AD-3: keine modifizierte/gelöschte/umbenannte committete Source als Input — unabhängig vom Commit-Zustand der Working-Copy, die der §5.9-P2-Block-Element-(1)-`INPUT_UNCOMMITTED`-Abbruch adressiert; der Guard ergänzt diesen, er ersetzt ihn nicht). Akzeptiert werden **nur neu hinzugefügte (`A`) oder separat versionierte Sources** (neue Datei (A), eine **Copy/Version** (C zählt als A) oder eine eigene Versions-Datei — AD-3-„neue Version einer Source als neue/versionierte Source"); ein **Rename (`R`)** einer committeten `raw/`-Datei wird behandelt wie M/D — Run-FAIL (ein Rename kollidiert mit der `raw/`-Immutabilität; AD-3, Ask-First). Der Befund wird **textuell benannt** (NFR-4) und ist Bestandteil des Run-Receipts.
+5. **Reservierte Zielpfade (AC-5):** Ein neu zu erzeugendes Concept-Ziel (CREATE-Zelle) mit Slug **`index`**, **`log`** oder einem **sonstigen reservierten Bundle-Namen** wird **nicht geschrieben**; der **deterministische Hold** verlangt eine **disambiguierte Identität** (z. B. Pfad-Erweiterung um einen Bereichs- bzw. spezifizierenden Bestandteil, der die Kollision mit der `index.md`-Hierarchie bzw. dem `log.md`-Typ auflöst, Vertrag §5/§6) — es wird **keine** Datei erzeugt und der Hold-Befund textuell benannt (NFR-4; Run „teilweise erfolgreich" gemäß §3.2-Endergebnis, analog §5.8-Instruktions-Hold). **Reservierte-Namen-Menge (erschöpfend, Ask-First-Nomenklatur):** `index` (Bundleroot-`index.md` + Area-`index.md`, Punkt-10/§5.7 Pkt. 5), `log` (Bundleroot-`wiki/log.md`, Vertrag §5), **`source`** (Sidecar-`source.md`-Kollision, §1.4-Artefakt-Ausnahme), **`README`** (Bundleroot-`wiki/README.md`, First-Line-Kickstart, §1.1). **Ist-Dateimenge deterministisch:** die Prüfung gegen die Ist-Dateimenge unter `wiki/` ist statisch über den committeten Baum definiert (keine Run-Zeit-Erhebung): zu jedem Run-Zeitpunkt ist die Kandidaten-Menge der Reserviertheits-Kollision die **Schnittmenge** aus (a) der erschöpfenden benannten Liste und (b) den im committeten Baum unter `wiki/` existierenden Datei-Basen (`git ls-tree` — datei-basename ohne `.md`); weitere reservierte Namen jenseits dieser Menge = Ask-First (Boundaries & Constraints). Die zugrunde liegende Fixture-Anlage ist als negative Matrix-Zeile („keine gültige Fixture erzeugt ein kollidierendes sonstiges Struktur-Ziel") benannt — kein stiller Ausschluss.
+6. **Zwei-Run-Identität (AC-6, AD-17h/A0-19):** Gleicher Git-State + gleiches Eingabemanifest ⇒ identische Candidate-Liste, Reihenfolge und Routing-Entscheidung. **Re-executierbarer Nachweis:** Die Sandbox (`_bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh`) führt **zwei getrennte Läufe über getrennte, saubere Worktrees** desselben committeten Baums aus und vergleicht die Run-Ausgänge (Candidate-Listen, Term-Listen, Routing-Entscheidungen; inkl. der Hold-Entscheidung über einen zweiten Worktree) **gegeneinander** — nicht gegen vorab fixierte Erwartungswerte (keine hart codierten erwarteten Pläne/Concept-Bodies; keine pauschale `verified`-Maskierung). **Benannte Differenz-Menge:** der Vergleich lässt allein den `generated.at`-Wanduhr-Gap als Differenz zu (§5.14 Pkt. 3 — kein `tree=`-/Pfad-Prefix-Vergleichs-Ausschluss); die Sandbox erzeugt in den Receipts ein `generated.at`-Feld und übt die at-Exzeption praktisch (legitime at-Abweichung wird erkannt und **nicht** als AD-16 gemeldet; eine andere als-at-Differenz wird **hart als FAIL** assertiert); jede weitere Abweichung ist ein AD-16-Klassifikationsdefekt (§5.14 Pkt. 4) und wird textuell benannt (NFR-4), bevor der Vertrag als bestätigt gilt. Der Nachweis umfasst **positive UND negative Fixtures** (positive: Identität über zwei Läufe; negativ: eine konstruierte AD-16-Abweichung wird **hart als FAIL assertiert** — kein Vakuum).
+
+**§7-Scope-Präzisierung (Story-3.9-Rest):** Der §7-Relevanzbestimmung-Bullet ist auf die §5.15-Verankerung nachgeführt (siehe §7); die verbleibenden Story-3.9-AC-Inhalte sind damit nicht mehr „noch nicht verankert", sondern in §5.15 Pkt. 1–6 geschlossen. Der Hold-Ausbau (post-Reconcile-Orphan, Mehrziel) verbleibt Story 3.10; die AD-16-Klassifikation/semantische Kollisionsauflösung bleibt Epic 4. **Abschlussklausel (Story 3.9):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **keine fünfte Routing-/Update-Klasse**; die **vier** Zellen bleiben UPDATE/CREATE/ORPHAN-HOLD/NO_OP (NO_OP als Update-Unter-Entscheidung, leere Candidate-Liste → Zellen 2/3, §3.2-Pkt.-3d-Anker entsprechend nachgeführt); **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Prädikat-/Format-/Frontmatter-Key**; `schema/canonical-terms.md` unverändert (kein neuer Normalisierungs-Operand — Umlaut-vs-Transkription bleibt benannter Defer); Commit-Boundary-Regel unverändert.
## 6. Validieren (mechanische Bestätigung)
@@ -431,7 +454,7 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene und in A
- **Eine genau-eine-Linkform** (file-relativ mit `.md`-Endung, in Areas `../`-fähig) — in **§5.6** dieser Instruktion gepinnt (Story 2.3; AD-7b, A0-9, FR-10; Auflösungsmodell §5.7 Pkt. 4) — der Punkt-11-Check des Validators akzeptiert bis auf Weiteres beide Schreibweisen (strukturell unverändert, Story-2.2-Präzedenz).
- **Synthese über mehrere Sources** (mehrere `raw/`-Quellen → eine gemeinsame Wissensrepräsentation mit gemischter, claim-granularer Provenienz) — **in §5.10** dieser Instruktion verankert (Story 3.4; AD-4, FR-7). Die Verankerung des inkrementellen Datenflusses (Erweitern/Präzisieren/Korrigieren einzelner bestehender Concepts) bleibt **§3 + §5.9** überlassen und ist dort bereits verankert (Story 3.1). Beide sind damit aus diesem Vorbehalt entlassen.
- **Leasing / Dirty-Tree-Schutz** für konkurrierende Producer — **in §5.11 dieser Instruktion verankert** (Story 3.5; AD-17a..f, A0-12..A0-16; die Enum enthält AD-17d/A0-15 nur als **Norm-Rückverweis** — die §5.11-Auflösung selbst schließt Staleness aus und delegiert an Story 3.6, Pkt. 7-Seam-Kriterium): Lease-Akquise auf `lease//`-Branches mit Lockfile und Merge-Base-Disziplin, Root-Scope-Lease inkl. `log.md`/`index.md`, Dirty-Tree-Schutz mit Stash/Scratch-Zone und `log.md`-Dokumentation, compiler-vermittelter Merge als AD-16-Pfad, kein textueller Auto-Merge, Commit-Boundary = Mutations-Boundary, Lease-Freigabe (Release, deterministisch); die bestehende Commit-Boundary = Mutations-Boundary-Regel (§0/§5.3, AD-17f) bleibt unverändert bestehender Schutz. **Lease-Staleness/Recovery** (TTL, Lease-Registrierung, verwaiste Leases, `raw/`-Recovery; AD-17d, A0-15) — **in §5.12 dieser Instruktion verankert (Story 3.6)**.
-- **Relevanzbestimmung** (feinkörniger Relevanz-Findungsmechanismus der Kandidatenerhebung) — in **§3.2** dieser Instruktion verankert (Story 3.2; Term-Ziehverfahren + Kanonisierungs-Resolver `schema/canonical-terms.md`, drei Erhebungs-Stufen grep/ripgrep + `index.md`-Traversal + Link-Following mit besuchter Menge, `log.md`-Exklusion, Candidate-Liste als relative OKF-Pfade ohne `.md`, Determinismus-Vertrag AD-17h/A0-19). Keine neue §7-Klasse, kein Schema-/Validator-Change; die Em-Dash-`—`-Varianten-Lücke ist als Determinismus-Frage an Story 3.8 übergeben. **Story-3.8-Auflösung:** die Determinismus-Frage ist in **§5.14** dieser Instruktion verankert (Story 3.8, Determinismus-Vertrag & Agent-Instruktions-Validator): die Em-Dash-Kollaps-Klasse, die Kollaps-Reichweite und der Match-Scope der Stufe a sind in **§3.2-Pkt.-1b** als geschlossene, deterministische Regel-Ergänzungen verankert; die Orphan-Politik ist in **§5.10 Pkt. 8** als deterministische Reconcile-Orphan-Regel präzisiert; die `generated.at`-Wanduhr-Gap-Ausnahme ist in §5.14-Pkt.-3 in die **Ausnahme-Menge** des Bundle-State-Vergleichs gefasst (A0-20-Konvention, Ask-First-geschützt). Keine offene Determinismus-Frage verbleibt (bestehende Story-Bullets unverändert). **Scope-Präzisierung (Review-Loop-3, P-8):** dies gilt für die **mit Story 3.8 geschlossenen** Determinismus-Fragen (Em-Dash-Kollaps-Klasse, Kollaps-Reichweite, Match-Scope Stufe a, Reconcile-Orphan-Regel, `generated.at`-Wanduhr-Gap-Ausnahme); bewusst nicht damit geschlossen bleiben die Umlaut-vs-Transkription-Divergenz im Match-Pfad und die noch nicht in `compiler.md` verankerten Story-3.9-ACs (beide als benannte Defers/Geplante sichtbar — `_bmad-output/implementation-artifacts/deferred-work.md` Defer-Block Review-Loop-3; Sprint-Change-Proposal 2026-08-20) — keine stillen offenen Fragen.
+- **Relevanzbestimmung** (feinkörniger Relevanz-Findungsmechanismus der Kandidatenerhebung) — in **§3.2** dieser Instruktion verankert (Story 3.2; Term-Ziehverfahren + Kanonisierungs-Resolver `schema/canonical-terms.md`, drei Erhebungs-Stufen grep/ripgrep + `index.md`-Traversal + Link-Following mit besuchter Menge, `log.md`-Exklusion, Candidate-Liste als relative OKF-Pfade ohne `.md`, Determinismus-Vertrag AD-17h/A0-19). Keine neue §7-Klasse, kein Schema-/Validator-Change; die Em-Dash-`—`-Varianten-Lücke ist als Determinismus-Frage an Story 3.8 übergeben. **Story-3.8-Auflösung:** die Determinismus-Frage ist in **§5.14** dieser Instruktion verankert (Story 3.8, Determinismus-Vertrag & Agent-Instruktions-Validator): die Em-Dash-Kollaps-Klasse, die Kollaps-Reichweite und der Match-Scope der Stufe a sind in **§3.2-Pkt.-1b** als geschlossene, deterministische Regel-Ergänzungen verankert; die Orphan-Politik ist in **§5.10 Pkt. 8** als deterministische Reconcile-Orphan-Regel präzisiert; die `generated.at`-Wanduhr-Gap-Ausnahme ist in §5.14-Pkt.-3 in die **Ausnahme-Menge** des Bundle-State-Vergleichs gefasst (A0-20-Konvention, Ask-First-geschützt). Keine offene Determinismus-Frage verbleibt (bestehende Story-Bullets unverändert). **Scope-Präzisierung (Review-Loop-3, P-8):** dies gilt für die **mit Story 3.8 geschlossenen** Determinismus-Fragen (Em-Dash-Kollaps-Klasse, Kollaps-Reichweite, Match-Scope Stufe a, Reconcile-Orphan-Regel, `generated.at`-Wanduhr-Gap-Ausnahme); bewusst nicht damit geschlossen bleibt die Umlaut-vs-Transkription-Divergenz im Match-Pfad (benannter Defer, `_bmad-output/implementation-artifacts/deferred-work.md` Defer-Block Review-Loop-3 — kein Instruktions-Defekt); die vormals „noch nicht verankerten" Story-3.9-ACs (Term-Gewinnung/Routing) sind dagegen seit der **Story-3.9-Verankerung** in **§5.15 dieser Instruktion** geschlossen (Deterministische Relevanz- & Reconcile-Routing: eine exklusive Routing-Tabelle UPDATE/CREATE/ORPHAN-HOLD/NO_OP — NO_OP als Update-Unter-Entscheidung, leere Candidate-Liste → Zellen 2/3; Termgewinnung geschlossen inkl. Status-Codes A/M/D/R/C, symmetrische Normalisierung mit **einer** Kollaps-Definition (§3.2-Pkt.-1b), Raw-Immutability-Guard, reservierte Zielpfade, Zwei-Run-Identität mit praktisch ausgeübter `at`-Exzeption) — keine stillen offenen Fragen.
- **Reason/Mutate-Phasen-Trennung & Konsistenz-Endzustand** (logische Phasen-Disziplin: Analyse → Änderungsplanung → Mutation → Validierung, AD-6/A0-7, AC-1/AC-2/AC-3/AC-4) — **in §5.13 dieser Instruktion verankert (Story 3.7; D-3):** Änderungsplanung als institutionalisierter §5.9-Pkt.-6-P2-Block (textuell festgehalten, Plan-Defizit = textuell benannte Abbruch-Kette vor der Mutation), Plan-Freeze = Veränderungs-Sperre an die §5.9-Pkt.-5-Ghost-Diff-Kopplung (erlaubte Pfad-Menge: Kandidatenliste ∪ Neu-Anlage ∪ `log.md` ∪ `index.md`), Zustands-Restaurations-Invariante (Post-Rollback-Diff gg. Baseline leer / Bundle == valide committet, §5.3-Pkt.-3-/§6-Pkt.-3-Rollback unverändert), kein Teilerfolg als fertige Mutation (AD-17f), keine eigene Workflow-Engine (logische Trennung in einer Session, kein Prozess/Server/MCP, D-3/AD-11). Keine neue §7-Klasse, kein Schema-/Validator-Change, keine Vertragsänderung.
- **Standalone-Compiler / eigene LLM-Runtime / MCP** → verboten in v1 (D-3, D-4, AD-11).
- **OKF-Dialekt / Schema-Erweiterung** → niemals (AD-1a; Vertrag §7 „abschließende Liste").
@@ -474,4 +497,5 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene und in A
- **Revision 3.0 (2026-08-19, Story 3.5):** Neue Sektion **§5.11 „Leasing & Dirty-Tree-Schutz für konkurrierende Producer (Story 3.5)"** eingefügt (nach §5.10, vor §6) — die **verbindliche Verankerung der Koordinations-Dimension für konkurrierende Producer** (AD-17a..f, A0-12..A0-16, FR-2/FR-12; §7-Vorbehalt `:357` aufgelöst): (1) **Lease-Akquise (AD-17a, A0-12)** — Arbeits-Branch-Form **`lease//`** von der Merge-Base aus, **Lockfile** (`lease//.lock`, semantisch identisch in jedem Adapter, A0-12; deterministisches Format: `area`, `id`, `producer`, `baseline_commit` voller SHA, `holder_id`), Lease-Hold bei existierendem Lockfile (kein Überschreiben, keine Mutation), **Merge-Base-Disziplin** (Lease gg. eindeutigen Commit-Object-Wert über `git merge-base`/``, AD-17h); (2) **Root-Scope-Lease (AD-17b, A0-13)** — umfasst `wiki/` inkl. `log.md`, `index.md` und aller Root-Dateien; kein Bereich jenseits `wiki/`; (3) **Dirty-Tree-Schutz (AD-17e/f, A0-16)** — Pre-Mutation-Prüfung (`git status --porcelain -- `), fremde uncommittete Änderungen **geschützt statt gelöscht** (Stash/Scratch-Zone außerhalb `wiki/`, dokumentiert in `log.md`), Screen-Artefakte textuell benannt (NFR-4), **UNCOMMITTED_INPUT-Abbruch** „published/committed Input erforderlich" (AD-17a; I/O-Matrix-`UNCOMMITTED_INPUT` — dieselbe Pre-Run-Prüfung wie §5.9-P2-Element-(1)-`INPUT_UNCOMMITTED`, kein zweiter Abbruch-Pfad), Mutationen nur auf Directory-/Commit-Ebene; (4) **kein textueller Auto-Merge (AD-17c, A0-14)** — compiler-vermittelter Merge über die **AD-16-Klassifikation** (Default: Erhaltung) mit `log.md`-Eintrag; Lease-Konflikt → AD-16-Pfad; Unentscheidbarkeit → menschliche Eskalation (AD-17g); (5) **Commit-Boundary = Mutations-Boundary** unverändert (§0/§5.3, AD-17f) — Diff-Selbsttest (§5.9 Pkt. 5) auch für Leasing-Runs, Ghost-Diff-Rollback; (6) **`log.md`-Eintragspflicht** (Lease-Akquise, Dirty-Tree-Schutz-Dokumentation, Merge-Klassifikation, Eskalation, **Lease-Freigabe**; `` notiert, D-2; Datumsgruppe **neueste zuerst**); (7) **Determinismus-Vertrag (AD-17h/A0-19)** — Lease-Akquise, Lockfile-Inhalte, Merge-Klassifikation deterministisch aus dem committeten Git-State; **Lease-Staleness/Recovery bleibt Story 3.6** (AD-17d, A0-15) — diese Sektion mutiert deren Mechanik nicht; testbares Seam-Kriterium (3.5 = committed-state-deterministisch, 3.6 = Zeit-/Umgebungs-Zustands-Frage, die den committeten Zustand verlässt). **§7:** Leasing-/Dirty-Tree-Vorbehalt **aufgelöst** („in §5.11 verankert (Story 3.5)"); Scope-Einleitung um §5.11 geöffnet; verbleibendes 3.x-Thema: Lease-Staleness/Recovery → Story 3.6. **§8:** Normreferenzen um AD-17b/AD-17c/AD-17d/AD-17e-f/AD-17g (Spine) und A0-12/A0-13/A0-14/A0-15/A0-16 (Epics) ergänzt; AD-17d/A0-15 in der §5.11-Enum als Norm-Rückverweis (ohne §5.11-Auflösungs-Bezug) gekennzeichnet. **Abschlussklausel:** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Frontmatter-Key für Lease-Metadaten** (Lease lebt in Git/Datei-Ebene, Vertrag §3.1–§3.7 unverändert); **keine fünfte Update-Form** (Abgrenzungs-Reihenfolge §5.9 unverändert, Leasing = Querschnitt); kein Staleness-Scope (→ Story 3.6); Commit-Boundary-Regel unverändert. **Lease-Freigabe** (Release) ist in §5.11 Pkt. 1/6 verankert (deterministisch, auf das committete Ergebnis bezogen); Staleness-/Recovery-Aspekte der Freigabe (verwaiste Leases) bleiben Story 3.6. **`sprint-status.yaml`:** Key `3-5-leasing-dirty-tree-schutz-für-konkurrierende-producer-umsetz` → **`in-progress`**. Sandbox-Nachweis (L1–L6 + Negativ-Kontrollen, Exit 0) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.5, Revision 3.0).
- **Revision 3.1 (2026-08-19, Story 3.6):** Neue Sektion **§5.12 „Lease-Staleness & Recovery-Basis (Story 3.6)"** eingefügt (nach §5.11, vor §6) — die **verbindliche Verankerung der Staleness-/Recovery-Dimension** (AD-17d, A0-15; §5.11-Seam-Kriterium S-1 und Pkt.-7-Text sowie §5.11 Pkt. 1 „verbleibt bis Story 3.6" bleiben textuell unverändert): (1) **Lease-Registrierung & generationenbasiertes TTL** — Registrierung im **Clone-Root-State**, monotoner Run-Generator (`generation`-Zähler je Clone-Root, deterministisch aus dem committeten Git-State ableitbar: `lease/`-Baumableitung oder Mono-Commit-`lease-granite-root`-Marker), **TTL-Ablauf-Kriterium generationen-basiert** (ältere/niedrigere Erzeugungs-Generation = stale, blockiert keinen nachfolgenden Run), **kein Wanduhr-Timestamp** im Lockfile-/Registrierungs-Format (A0-20; streng durchsetzendes Zeit-TTL = Ask-First); (2) **holder_id-Ableitung** (deterministischer Default `holder_id := -`, Defer aufgegriffen); (3) **Verwaist-Klassifikation** (Übernehmen gg. erneute Merge-Base-Prüfung oder Stale-Markieren via Registry-Marker, je `log.md`-Eintrag; verwaiste Leases **nie still gelöscht**, AD-17e; Konflikt → AD-16-Pfad/Eskalation AD-17g); (4) **baseline_commit-Merge-Base-Diskrepanz-Regel** (git-merge-base gewinnt, notierter SHA = Sekundär-Fingerprint, Fallback ohne Boundary; Defer aufgegriffen); (5) **`raw/`-Recovery-Basis & native `git stash`-Variante** (`raw/` immutable AD-3 als Zugriffs-/Consistency-Basis, Real-Baum-Beweis auf Sandbox-Evidenzwege beschränkt, EC-1-Grenze; `git stash push -- ` als zweitezulässige Schutzvariante, Defer aufgegriffen); (6) **Registrierungs-Invariante & kumulativer Registry-Aufbau über Runs** (Gen > erzeugend oder gleiche Gen, hält den sichtbar höchsten Reg-Generator; kein eigener `# Log`-Stand — `wiki/log.md` alleiniger Aufzeichnungs-Ort, Vertrag §5; Defer aufgegriffen); (7) **`log.md`-Eintragspflicht & Determinismus-Vertrag** (Registrierung/TTL, Lease-Übernahme, Stale-Markierung, Recovery-Basis-Nutzung als Datumsgruppen-Einträge; Registrierung/TTL/Verwaist-Klassifikation/log.md-Texte deterministisch aus dem committeten Git-State). **§7:** Staleness/Recovery-Vorbehalt **aufgelöst** („in §5.12 verankert (Story 3.6)"). **§8:** Normreferenzen AD-17d/A0-15 von reiner Story-Zuordnung auf **§5.12-Anker** angehoben (`AD-17d (Lease-Staleness, §5.12)`, `A0-15 (Lease-Staleness, §5.12)`). **Abschlussklausel:** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Frontmatter-Key für Lease-Metadaten** (Lease lebt in Git/Datei-Ebene, Vertrag §3.1–§3.7 unverändert); kein Prädikat-/Format-Key; Commit-Boundary-Regel unverändert. **`sprint-status.yaml`:** Key `3-6-lease-staleness-recovery-basis-absichern` → **`in-progress`**. Sandbox-Nachweis (STALE-1..STALE-6 + Erhaltungs-Invariante, Exit 0) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.6, Revision 3.1).
- **Revision 3.2 (2026-08-20, Story 3.7):** Neue Sektion **§5.13 „Reason/Mutate-Phasen-Trennung & Konsistenz-Endzustand (Story 3.7)"** eingefügt (nach §5.12, vor §6) — die **verbindliche Verankerung der logischen Phasen-Disziplin** (AD-6, A0-7; §7-Vorbehalt der Reason/Mutate-Trennung aufgelöst): (1) **Änderungsplanung** — der §5.9-Pkt.-6-P2-Block wird Wortlaut-unverändert als Änderungsplanungs-Phase der AD-6-Kette institutionalisiert (textuell festgehaltener konsistenter Plan: Input-Zustand, Ziel-Pfade, Quellen-Existenz, Betroffenheits-Liste, Struktur-Erhaltung; Plan-Defizit textuell benannt NFR-4 und verhindert die Mutation — I/O-Matrix `PLAN_BEABSICHTIGT`); (2) **Plan-Freeze** (Veränderungs-Sperre nach Phasenabschluss, Kopplung an die §5.9-Pkt.-5-Ghost-Diff-Probe; erlaubte Pfad-Menge = Kandidatenliste ∪ Neu-Anlage ∪ `log.md` ∪ `index.md` — `PLAN_FREEZE`); (3) **Zustands-Restaurations-Invariante** (Post-Rollback-Diff gg. Baseline leer / Bundle == valide committet; §5.3-Pkt.-3-/§6-Pkt.-3-Rollback und Ghost-Diff-Rollback Wortlaut-unverändert, Endzustands-Konsistenz als git-prüfbare Eigenschaft — `MUTATION_ABBRUCH`, A0-7-AC-2); (4) **kein Teilerfolg als fertige Mutation** (`MUTATION_TEILFOLGE`, AD-17f unverändert); (5) **Validierungsphase `VALIDATION_FAIL`** (§6-Pkt.-3-Rollback, keine weiteren Mutationen, Endzustand konsistent); (6) **Validierungsphase `VALIDATION_SUCCESS`** (Mutationen als Ganzes committet erst nach Diff-Selbsttest ohne Ghost-Diff, §6-Pkt.-4-Nachweis, kein Wanduhr-Trigger A0-20 — A0-7-AC-3); (7) **keine eigene Workflow-Engine** (`KEINE_EIGENE_ENGINE`: logische Trennung in einer Session, kein Prozess/Server/MCP, D-3/AD-11 — A0-7-AC-4). Die **AD-6-Phasen-Zuordnungstabelle (§0 ↔ vier AD-6-Phasen)** ist eine Klassifikation ohne neue Norm: §0 bleibt die deterministische Takt-Folge (Wortlaut unverändert, keine Um-Nummerierung, keine neue Phase); §5.9-Pkt.-6-P2-Block, §5.3-Pkt.-3/§6-Pkt.-3-Rollback und §5.9-Pkt.-5-Diff-Probe bleiben **textuell unverändert** (Rückverweise, keine Doppel-Instruktion); §5.12-Seam-Satz unverändert (Lease-Staleness/Recovery bleibt Story 3.6). **§7:** Reason/Mutate-Vorbehalt **aufgelöst** („in §5.13 verankert (Story 3.7)"-Bullet, AD-6/A0-7, AC-1/2/3/4; bestehende Story-Bullets unverändert). **§8:** Normreferenz AD-6 von reiner Story-Zuordnung auf **§5.13-Anker** angehoben (`AD-6 (Reason/Mutate-Trennung, §5.13)`); A0-7-Reihenfolge-Referenzen in der Epic-Zeile um §5.13-Bezug nicht neu aufgelistet (A0-7 bleibt in der bestehenden Epic-Enum, die §5.13-Ankerung erfolgt über die Spine-AD-6-Zeile und den neuen §7-Bullet). **Abschlussklausel:** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Prädikat-/Format-/Frontmatter-Key**; keine neue Workflow-Engine (AD-6); §0-Phasen-Listentext unverändert; Commit-Boundary-Regel unverändert. **`sprint-status.yaml`:** Key `3-7-reason-mutate-trennung-und-konsistenz-endzustand-sicherstell` → **`review`** (Implementierungs-Flip `in-progress` + Review-Start-Flip `review` im selben Commit; der finale `done`-Flip erfolgt im Step-05-Status-Sync). Sandbox-Nachweis (CONSIST-1..CONSIST-7 + Erhaltungs-/Restaurations-Invariante, Exit 0) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.7, Revision 3.2).
-- **Revision 3.3 (2026-08-20, Story 3.8):** Neue Sektion **§5.14 „Determinismus-Vertrag & Agent-Instruktions-Validator (Story 3.8)"** eingefügt (nach §5.13, vor §6) — die **geschlossene, aus dem committeten Git-State ableitbare Bestätigungs-Mechanik des Determinismus-Vertrags** (AD-17h/FT-10/A0-19; §3.2/§5.9/§5.10/§5.11/§5.12/§5.13-Rückverweise verankern den Vertrag, §5.14 die Bestätigung): (1) **Bundle-State-Definition** (deterministische Projektion des committeten Git-States: committeter Baum unter `wiki/`/`raw/` gg. Baseline + Plan-/Kandidaten-/Reihenfolge-Outputs + Ausführungs-Entscheidungen; `generated.at`/`verified[].at` als benannte Ausnahme, A0-20 — einzig zulässige Differenz zwischen zwei Runs), (2) **Zwei-Run-Bestätigungs-Mechanik** (agent-Instruktions-basiert, D-3/Q-6: **zwei frische Agent-Kontexte in getrennt aufgebauten (sauberen) Worktrees** führen die Instruktion jeweils einmal über demselben committeten Git-State aus und die Bundle-States werden verglichen — **eine zweite Ausführung in derselben Session genügt nicht** (Q-6, A0-19); Vergleichs-Operandum = committeter Baum, **kanonisches Eingabemanifest** (Baseline-Commit, geordnete Sources, output-sichtbare Run-/Zeit-/Identitätswerte) + **Run-Receipt außerhalb des Bundles** (Candidates, Reihenfolge, Plan, Entscheidungen, Output-Hashes), re-executierbare diff-/hashbasierte Formeln, keine Wanduhr-Steuerung, keine hart codierten erwarteten Pläne/Concept-Bodies, keine pauschale `verified`-Maskierung; identische Plan-/Kandidaten-/Reihenfolge-Outputs, byte-identische mutierte Bestandteile; keine eigene Runtime/kein neues Werkzeug, AD-6/AD-11), (3) **Ausnahme-Menge** (allein der `generated.at`-Wanduhr-Gap; dokumentiert, kein stiller Ausschluss; alle übrigen Bestandteile byte-identisch), (4) **Abweichungs-Klassifikation** (jede Differenz außerhalb der Ausnahme = AD-16-Klassifikationsfehler, kein Rauschen; textuell benannt NFR-4, Run korrigiert/rollt zurück, Zustands-Restaurations-Invariante §5.13 Pkt. 3), (5) **Normalisierungs-/Match-/Orphan-Schließung** (§3.2-Pkt.-1b-Em-Dash-Kollaps-Klasse `[-–— _]`, Kollaps-Reichweite, Match-Scope Stufe a; §5.10-Pkt.-8-Reconcile-Orphan-Regel; Erhebungen vollständig pinbar). **§3.2:** die bekannten Determinismus-Lücken als append-only-Regel-Ergänzungen geschlossen (Em-Dash in der Kollaps-Klasse, Kollaps-Reichweite, Match-Scope der Stufe a) — bestehender §3.2-Wortlaut unverändert. **§5.10 Pkt. 8:** Orphan-Politik zur deterministischen **Reconcile-Orphan-Regel** präzisiert (unzugeordnet, datumsgruppierter `log.md`-Verwaist-Eintrag mit ``, kein Banner/keine stille Vorbearbeitung/keine eigenständige Anlage; AD-16-Default). **§5.13 Pkt. 7:** Home-Verweis des `generated.at`-Gaps auf die §5.14-Definition verlagert (Wortlaut des §5.13-Satzbaus semantisch unverändert; die Behandlung des Gaps ist jetzt in §5.14-Pkt.-3 definiert). **§7:** Determinismus-Vorbehalt der Relevanzbestimmung **aufgelöst** (Em-Dash-Lücke → „in §5.14 verankert (Story 3.8)"-Ergänzung; §3.2-/§5.10-/`at`-Gap-Schließung benannt; bestehende Story-Bullets unverändert — kein neuer Bullet ersetzt einen bestehenden). **§8:** Normreferenz **AD-17h** von reiner Story-Zuordnung auf **§5.14-Anker** angehoben (`AD-17h (Determinismus, §5.14 — Zwei-Run-Bestätigung mit benannter `generated.at`-Wanduhr-Gap-Ausnahme, A0-20/§5.9-Pkt.-2/§5.10-Pkt.-8)`). **Abschlussklausel:** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Prädikat-/Format-/Frontmatter-Key**; das `generated.at`-Verhalten selbst **unverändert** (nur seine Behandlung im Bundle-State-Vergleich; Verhaltenswechsel = Ask-First); keine Workflow-Engine/kein neuer Prozess/Server/MCP (AD-6, AD-11); §0-Phasen-Listentext, §5.13-Phasen-Disziplin und §6/§6.5 textuell **unverändert** (Fugen-Identität); Commit-Boundary-Regel unverändert; `schema/canonical-terms.md` unverändert (Em-Dash-/Kollaps-Schließung lebt als Regel in §3.2, nicht als Registry-Edits). **`sprint-status.yaml`:** Key `3-8-determinismus-vertrag-ad-17h-als-agent-instruktions-validato` **`in-progress`** (Re-Open-Status; finaler `review`/`done`-Flip im Step-04/05). **Re-Open-Delta (2026-08-20, genehmigtes Sprint-Change-Proposal):** Zwei-Run-Mechanik auf getrennte Worktrees/frische Agent-Kontexte umgestellt (Q-6/A0-19), kanonisches Eingabemanifest + Run-Receipt außerhalb des Bundles, keine hart codierten erwarteten Pläne/Concept-Bodies, keine pauschale `verified`-Maskierung (nur `at`-Ausnahme). Sandbox-Nachweis (**DET-1..DET-8 + Erhaltungs-Invariante, Exit 0**; Zwei-Run-Identität nicht-vakuum, DET-2 in zwei getrennten Worktrees) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.8, Revision 3.3).
+- **Revision 3.3 (2026-08-20, Story 3.8):** Neue Sektion **§5.14 „Determinismus-Vertrag & Agent-Instruktions-Validator (Story 3.8)"** eingefügt (nach §5.13, vor §6) — die **geschlossene, aus dem committeten Git-State ableitbare Bestätigungs-Mechanik des Determinismus-Vertrags** (AD-17h/FT-10/A0-19; §3.2/§5.9/§5.10/§5.11/§5.12/§5.13-Rückverweise verankern den Vertrag, §5.14 die Bestätigung): (1) **Bundle-State-Definition** (deterministische Projektion des committeten Git-States: committeter Baum unter `wiki/`/`raw/` gg. Baseline + Plan-/Kandidaten-/Reihenfolge-Outputs + Ausführungs-Entscheidungen; `generated.at`/`verified[].at` als benannte Ausnahme, A0-20 — einzig zulässige Differenz zwischen zwei Runs), (2) **Zwei-Run-Bestätigungs-Mechanik** (agent-Instruktions-basiert, D-3/Q-6: **zwei frische Agent-Kontexte in getrennt aufgebauten (sauberen) Worktrees** führen die Instruktion jeweils einmal über demselben committeten Git-State aus und die Bundle-States werden verglichen — **eine zweite Ausführung in derselben Session genügt nicht** (Q-6, A0-19); Vergleichs-Operandum = committeter Baum, **kanonisches Eingabemanifest** (Baseline-Commit, geordnete Sources, output-sichtbare Run-/Zeit-/Identitätswerte) + **Run-Receipt außerhalb des Bundles** (Candidates, Reihenfolge, Plan, Entscheidungen, Output-Hashes), re-executierbare diff-/hashbasierte Formeln, keine Wanduhr-Steuerung, keine hart codierten erwarteten Pläne/Concept-Bodies, keine pauschale `verified`-Maskierung; identische Plan-/Kandidaten-/Reihenfolge-Outputs, byte-identische mutierte Bestandteile; keine eigene Runtime/kein neues Werkzeug, AD-6/AD-11), (3) **Ausnahme-Menge** (allein der `generated.at`-Wanduhr-Gap; dokumentiert, kein stiller Ausschluss; alle übrigen Bestandteile byte-identisch), (4) **Abweichungs-Klassifikation** (jede Differenz außerhalb der Ausnahme = AD-16-Klassifikationsfehler, kein Rauschen; textuell benannt NFR-4, Run korrigiert/rollt zurück, Zustands-Restaurations-Invariante §5.13 Pkt. 3), (5) **Normalisierungs-/Match-/Orphan-Schließung** (§3.2-Pkt.-1b-Em-Dash-Kollaps-Klasse `[-–— _]`, Kollaps-Reichweite, Match-Scope Stufe a; §5.10-Pkt.-8-Reconcile-Orphan-Regel; Erhebungen vollständig pinbar). **§3.2:** die bekannten Determinismus-Lücken als append-only-Regel-Ergänzungen geschlossen (Em-Dash in der Kollaps-Klasse, Kollaps-Reichweite, Match-Scope der Stufe a) — bestehender §3.2-Wortlaut unverändert. **§5.10 Pkt. 8:** Orphan-Politik zur deterministischen **Reconcile-Orphan-Regel** präzisiert (unzugeordnet, datumsgruppierter `log.md`-Verwaist-Eintrag mit ``, kein Banner/keine stille Vorbearbeitung/keine eigenständige Anlage; AD-16-Default). **§5.13 Pkt. 7:** Home-Verweis des `generated.at`-Gaps auf die §5.14-Definition verlagert (Wortlaut des §5.13-Satzbaus semantisch unverändert; die Behandlung des Gaps ist jetzt in §5.14-Pkt.-3 definiert). **§7:** Determinismus-Vorbehalt der Relevanzbestimmung **aufgelöst** (Em-Dash-Lücke → „in §5.14 verankert (Story 3.8)"-Ergänzung; §3.2-/§5.10-/`at`-Gap-Schließung benannt; bestehende Story-Bullets unverändert — kein neuer Bullet ersetzt einen bestehenden). **§8:** Normreferenz **AD-17h** von reiner Story-Zuordnung auf **§5.14-Anker** angehoben (`AD-17h (Determinismus, §5.14 — Zwei-Run-Bestätigung mit benannter `generated.at`-Wanduhr-Gap-Ausnahme, A0-20/§5.9-Pkt.-2/§5.10-Pkt.-8)`). **Abschlussklausel:** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Prädikat-/Format-/Frontmatter-Key**; das `generated.at`-Verhalten selbst **unverändert** (nur seine Behandlung im Bundle-State-Vergleich; Verhaltenswechsel = Ask-First); keine Workflow-Engine/kein neuer Prozess/Server/MCP (AD-6, AD-11); §0-Phasen-Listentext, §5.13-Phasen-Disziplin und §6/§6.5 textuell **unverändert** (Fugen-Identität); Commit-Boundary-Regel unverändert; `schema/canonical-terms.md` unverändert (Em-Dash-/Kollaps-Schließung lebt als Regel in §3.2, nicht als Registry-Edits). **`sprint-status.yaml`:** Key `3-8-determinismus-vertrag-ad-17h-als-agent-instruktions-validato` **`done`** (2026-08-20: Story-3.8-Instruktionsverankerung abgeschlossen — die Re-Open-/Abschluss-Reihenfolge „3.9 → 3.10/3.11 → 3.12 → 3.8-Abschluss → 3.13" des Sprint-Change-Proposals 2026-08-20 betrifft das Epic-3-**Abnahmegate**, nicht die Story-3.8-Inhaltsverankerung; die 3.9–3.12-Verankerungen bleiben offen, epic-3 bleibt in-progress). **Re-Open-Delta (2026-08-20, genehmigtes Sprint-Change-Proposal):** Zwei-Run-Mechanik auf getrennte Worktrees/frische Agent-Kontexte umgestellt (Q-6/A0-19), kanonisches Eingabemanifest + Run-Receipt außerhalb des Bundles, keine hart codierten erwarteten Pläne/Concept-Bodies, keine pauschale `verified`-Maskierung (nur `at`-Ausnahme). Sandbox-Nachweis (**DET-1..DET-8 + Erhaltungs-Invariante, Exit 0**; Zwei-Run-Identität nicht-vakuum, DET-2 in zwei getrennten Worktrees) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.8, Revision 3.3).
+- **Revision 3.4 (2026-08-20, Story 3.9):** Neue Sektion **§5.15 „Deterministische Relevanz- & Reconcile-Routing (Story 3.9)"** eingefügt (nach §5.14, vor §6) — die **geschlossene Routing-Ebene des Reconcile** (AD-17h/A0-19, Story 3.9; §5.14-Pkt.-5-/§7-„Story-3.9-ACs noch nicht verankert"-Vorbehalt aufgelöst): (1) **Termgewinnung** — geschlossener, geordneter Algorithmus aus der Zuwachs-Sicht (Dateiname→Term-Mapping, `source.md`-Sidecar-Exklusion, Status-Codes `A`/`M`/`D` via `--diff-filter=ACMR` mit Status-Bedeutung A/C/R, §5.9-Pkt.-6-Diskrepanz-/Fallback-Kopplung, Diff↔Manifest-Äquivalenz, Mehrfach-Term-Vereinigung D-8 aufgegriffen; **eine** Kollaps-Definition §3.2-Pkt.-1b), (2) **symmetrische Normalisierung + literal-sichere Suche** (AC-2; `index.md`-Treffer → Traversal-Stufe, kein Konzept-Kandidat), (3) **eine exklusive Routing-Tabelle** (AC-3; UPDATE → CREATE → ORPHAN/HOLD → NO_OP; **NO_OP als Update-Unter-Entscheidung** — leere Candidate-Liste bei neuer Evidenz → Zellen 2/3, nie NO_OP; CREATE-vs-ORPHAN-Prädikat; Stufe-b-Zelle konsistent), (4) **Raw-Immutability-Guard** (AC-4; M/D/**R** → Run-FAIL vor jeder Mutation, A/C akzeptiert), (5) **reservierte Zielpfade** (AC-5; erschöpfende Liste `index`/`log`/`source`/`README`, Ist-Dateimenge via `git ls-tree`-Schnittmenge, deterministischer Hold), (6) **Zwei-Run-Identität** (AC-6; positive UND negative Fixtures, Zwei-Worktree-Vergleich, praktisch ausgeübte `at`-Exzeption — die einzige benannte Differenz). **§3.2:** der NO_MATCH-Anker (Pkt. 3d) als §5.15-Verweis-Anker nachgeführt (leere Candidate-Liste bei neuer Evidenz → Zellen 2/3, nicht NO_OP; `UNTOUCHED_CONCEPT` gilt für den Ghost-Diff-negativen Fall ohne Zuwachs). **§5.14 Pkt. 5:** Scope-Präzisierung nachgeführt (Story-3.9-ACs sind verankert). **§7:** Relevanzbestimmung-Bullet um die §5.15-Verankerung erweitert (Story-3.9-Vorbehalt aufgelöst; bestehende Story-Bullets unverändert). **§8:** AD-17h-/A0-19-/A0-18-Reihe bereits in §5.14 verankert — §5.15 referenziert sie (Fugen-Identität). **Abschlussklausel (Story 3.9):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **keine fünfte Routing-/Update-Klasse**; **kein Standalone** (D-3); keine Vertragsänderung; **kein neuer Prädikat-/Format-/Frontmatter-Key**; `schema/canonical-terms.md` unverändert (kein neuer Normalisierungs-Operand — Umlaut-vs-Transkription bleibt benannter Defer); Commit-Boundary-Regel unverändert; Hold-Ausbau (post-Reconcile-Orphan, Mehrziel) bleibt Story 3.10; AD-16-Klassifikation/semantische Auflösung bleibt Epic 4. **`sprint-status.yaml`:** Key `3-9-deterministische-relevanz-und-reconcile-routing-schliessen` **`in-progress`** (finaler `review`/`done`-Flip im Step-04/05). **Review-Loop-2-Auflösung (Re-Ableitung):** Kern-Defekt BS-L2-1 (NO_MATCH/leere Candidate-Liste nicht NO_OP, sondern Zellen 2/3) und BS-L2-2 (Status-Codes inkl. R/C) behoben; Sandbox um R-1-Negativ-Manifest, R-3-Fall-2-Evidenzvergleich, R-5-CREATE-Bewertungsraum, R-6/R-7-Slug-Ableitung + `git ls-tree`-Schnittmenge, R-8-Zwei-Worktree-Hold, R-9-`at`-Exzeption, harmonisierte `norm()` (eine Kollaps-Definition) ertüchtigt (Details siehe Spec Change Log Loop-2 und `wiki/log.md`-Eintrag).
diff --git a/wiki/log.md b/wiki/log.md
index 0937948..acaaf29 100644
--- a/wiki/log.md
+++ b/wiki/log.md
@@ -1,6 +1,7 @@
# Log
## 2026-08-20
+- **Story 3.9 → Re-Ableitung Loop-2 + `in-progress` (Deterministische Relevanz- & Reconcile-Routing, 2026-08-20):** Loop-2-bad_spec-Loopback (bmad-code-review Re-Run — 2 bad_spec, 4 patch, 2 defer; kein intent_gap, kein Eingriff ins ``). **Kern-Defekte behoben:** **BS-L2-1** — NO_MATCH/leere Candidate-Liste ist bei **neuer Einheit** NICHT NO_OP, sondern **CREATE (Zelle 2) / ORPHAN-HOLD (Zelle 3)**; NO_OP (Zelle 4) bleibt ausschließlich **Unter-Entscheidung des Update-Pfads** (bestehende Evidenz identisch repräsentiert) — §5.15-Pkt.-3-Tabelle, §3.2-Pkt.-3d-Verweis-Anker und Sandbox R-3/R-5 in Einklang; **BS-L2-2** — Status-Codes geschlossen: **R (Rename)** einer committeten `raw/`-Datei = AD-3-Verletzung → **Guard-FAIL**, **C** zählt als **A** (Copy/neu), `--diff-filter=ACMR` dokumentiert die Zuordnung. **Weitere Loop-2-Auflagen:** P-L2-1 Sandbox-`norm()` auf die **eine** Kollaps-Definition (§3.2-Pkt.-1b) vereinheitlicht (keine vierte Pipeline); P-L2-2 R-2-`index.md`-Traversal **real** gefeuert (Fixture enthält den Term, Traversal-Exklusion negativ assertiert); P-L2-3 R-1-Diff↔Manifest-Äquivalenz um **Negativ-Zweig** ergänzt (divergentes Manifest → Run-FAIL vor Mutation); P-L2-4 R-8-**Zwei-Run-Hold über zwei getrennte Worktrees** (Behebung der Doppel-Read-Tautologie); P-L2-5 R-6/R-7-**Slug aus dem abgeleiteten Kandidaten** + `git ls-tree`-Schnittmengen-Fixture + entdoppelte tote `CAND`-Assertion (kein `|| true`); P-L2-6 R-9-Receipts um **`generated.at`-Feld + praktisch ausgeübte at-Exzeption** (legitime at-Abweichung ≠ AD-16; andere als-at-Differenz = HARD-FAIL). **Defer-Aufgriffe (Home Story 3.9):** D-8 (Mehrfach-Term-Vereinigung) und D-9 (Term-Ableitung aus dem `raw/`-Zuwachs + voller Kandidaten-Scan statt fester 2-Datei-Liste) in §5.15 Pkt. 1 / Sandbox R-1/R-5 realisiert. **Verankerung (`schema/compiler.md` Revision 3.4):** neue **§5.15** „Deterministische Relevanz- & Reconcile-Routing (Story 3.9)" (Pkt. 1–6) — Pkt. 1 **Termgewinnung** (geschlossen, geordnet, AC-1: Dateiname→Term-Mapping, Sidecar-Exklusion, Status-Codes A/M/D/R/C via `--diff-filter=ACMR`, §5.9-Pkt.-6-Diskrepanz-/Fallback-Kopplung, Diff↔Manifest-Äquivalenz, D-8-Mehrfach-Term-Vereinigung mit ≥2-Zeichen-Segmenten, Einzelzeichen-Segmente kein eigener Term, optional committetes Term-Manifest), Pkt. 2 **symmetrische Normalisierung + literal-sichere Suche** (AC-2, §3.2-Pkt.-1b-Kollaps-Klasse `[-–— _]`→`-`; `index.md`-Treffer → Traversal-Stufe, kein Concept-Kandidat), Pkt. 3 die **eine exklusive Routing-Tabelle** (AC-3: UPDATE → CREATE → ORPHAN/HOLD → NO_OP; NO_OP als Update-Unter-Entscheidung; Leere-Candidate-Absatz; Stufe-b-Zelle), Pkt. 4 **Raw-Immutability-Guard** (AC-4: M/D/**R** → Run-FAIL vor Mutation, A/C akzeptiert), Pkt. 5 **reservierte Zielpfade** (AC-5: `index`/`log`/`source`/`README` erschöpfend, deterministischer Hold, Ist-Dateimenge via `git ls-tree`-Schnittmenge), Pkt. 6 **Zwei-Run-Identität** (AC-6: positive UND negative Fixtures, Zwei-Worktree-Vergleich, praktisch ausgeübte `at`-Exzeption, kein hart codierter Erwartungswert). **§3.2**-Pkt.-3d-§5.15-**Verweis-Anker** nachgeführt; **§5.14**-Pkt.-5-Scope-Präzisierung (Story-3.9-ACs verankert); **§7**-Relevanzbestimmung-Bullet erweitert (Vorbehalt aufgelöst); Revisionslog **Revision 3.4**. **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`** (finaler `review`/`done`-Flip im Step-04/05). **Sandbox-Nachweis:** `bash _bmad-output/implementation-artifacts/sandbox-3-9/run-sandbox.sh` → **R-1..R-9 harte PASS, Exit 0** (inkl. R-1b R/C-Guard, R-5-CREATE-Bewertungsraum, R-8-Zwei-Worktree-Hold, R-9-at-Exzeption + Negativkontrolle). **Erhaltungs-Invariante §5.9 Pkt. 5 gewahrt:** `git status --porcelain -- wiki/` zeigt ausschließlich `wiki/log.md` (dieser Eintrag); **AD-3 read-only** (`schema/validator.md`/`schema/wiki-compiler.md`/`adapters/`/`raw/`/`schema/canonical-terms.md` unverändert); kein Standalone (D-3), keine neue §7-Invaliditätsklasse, keine Vertragsänderung; Umlaut-vs-Transkription bleibt benannter Defer; Hold-Ausbau (post-Reconcile-Orphan, Mehrziel) bleibt Story 3.10.
- **Story 3.8 → Review-Loop-3-Abschluss + `done` (Determinismus-Vertrag, bmad-code-review Re-Run 4 Layer — blind-hunter / edge-case-hunter / verification-gap / acceptance-auditor, 2026-08-20):** Re-Review der Loop-2-zustands Implementation; **Triage:** 4 decision-needed / 13 patch / 6 defer / 7 dismissed; **keine intent_gap/bad_spec (kein Loopback).** **Nutzer-Entscheidungen D-1..D-4 = 1/1/1/1** (empfohlene Optionen): D-1 §5.14-Schließungs-Bullet macht den Z. 53 „Bekannte Determinismus-Lücke"-Bullet **superseded** (append-only-Superseded-Hinweis, kein Umbruch); D-2 Story-Status-Flip auf **`done`** nach Loop-3-Abschluss (Change-Proposal-Sequenzierung „3.9 → 3.10 / 3.11 → 3.12 → 3.8 Abschluss → 3.13 Abnahme" betrifft das **Epic-3-Abnahmegate (3.13)** — Story-3.8-Instruktionsverankerung abgeschlossen, 3.9–3.12-Verankerungen + 3.13-Abnahme bleiben offen, epic-3 in-progress); D-3 **autorisierte Neu-Verhandlung** des Frozen-Intents in geringfügigem Umfang: Typo „documenthuman" → „document-human" (spec Z. 24, dokumentiert); D-4 Hold-Home = **Story 3.10 (Epic 3)**, Korrektur-/Erweiterungs-**Klassifikation** = Epic-4-Interface/Story 4.1 (§5.10 Pkt. 8 präzisiert). **Patches (13):** P-1 SRO-/Code-Map-Anker auf IST-Zeilen (compiler.md 375/376/377/477; Code Map §5.14 365–377, §7 424ff, §8 445, Rev 3.3 477; Sandbox 245/265/442/275/447/531); P-2/P-4 symmetrische Term-/Body-Normalisierung (identisch normalisiert vor Vergleich, kein host-abhängiges `-i`, Wortgrenze = Tool-Wortdefinition rg `-w`/`\b`) — §3.2 Pkt. 2a + `match_stufe_a` (Term + Body identisch normalisiert, `-i` entfernt, ASCII-Boundary `[^A-Za-z0-9]`); P-3 re-executierbare Zwei-Run-Formel als Receipt-Hashvergleich (git-diff-Formel = Austauschbar-Form derselben Eigenschaft) — §5.14 Pkt. 2; P-5 Sandbox-Fresh-Kontext-Restlücke textuell benannt (mechanisch simuliert; Nachweis echter frischer Kontexte = Story-3.13-Abnahmegate) — §5.14 Pkt. 2; P-6 Manifest-`generated_by` wird **konsumiert** (Guard + Konzepts-Frontmatter `by:` aus Manifest statt hart-codiert); P-7 **at-Ausnahme hart assertiert** (Wiederholungs-Schleife bei Wanduhr-Sekundenkollision erzwingt real unterschiedliche `at_cell`-Werte; `HARD-FAIL` statt stiller PASS) — re-executiert: `BEFUND: at-Ausnahme aktiv (assertiert)` mit real differierenden Wanduhrwerten; P-8 „vollständig pinbar"/„keine offene Frage" **ge scopet** (nur für die mit §5.14 geschlossenen Lücken; Umlaut-Defer + Story-3.9-ACs bewusst nicht damit geschlossen, sichtbar als benannte Defers/Geplante) — §5.14 Pkt. 5 + §7-Bullet; P-9 epics.md AC-2: „Determinismusfehler" = **AD-16-Klassifikationsdefekt** (AD-16-Kopplung nachgeführt, AC-Wortlaut erhalten); P-10 spec `review_loop_iteration: 0 → 2` (Counter ab Loop-3 gepflegt); P-11 epic-3-context.md Technical Decisions Z. 39/41/43 als **Zielzustand** markiert (Story 3.9/3.11/3.12 — noch nicht in compiler.md verankert, §3.2/§5.11 maßgeblich bis dahin); P-12 verifiziert + dokumentiert (epics.md enthält kein Literal „AD-17a..h"; die AD-17-Enums sind mit dem Change-Proposal konsistent — AD-17g liegt in Epic 4 Z. 101; kein Edit nötig); P-13 Spec Change Log Review-Loop-3 (append-only, nach Loop-2-Eintrag, vor ``). **Defers (6, → deferred-work.md append-only, Block „Deferred from: code review of spec-3-8… (2026-08-20)"):** D-5 Sandbox-Härtungs-Guards (8 Befunde), D-6 DET-1/2-Plan-Literale (Home: 3.13-Abnahme), D-7 `norm()`-Locale-Pinning, D-8 Mehrfach-Term-Union, D-9 Orphan-Term-Hand-Pin/feste 2-Datei-Scan (Home: 3.9), D-10 Umlaut-vs-Transkription im Match-Pfad (bereits „Aufgegriffen (teilweise)" offen). **Dismissed (7):** u. a. Blind-Hunter-Claim „alle Sandbox-SRO-Anker stale" — **widerlegt** (alle 6 exakt vor den eigenen Edits); übrige: Loop-1/2-Präzedenz-Doppelzählungen + by-design-Lesarten (Details im Spec Change Log). **Sandbox re-executiert:** `bash _bmad-output/implementation-artifacts/sandbox-3-8/run-sandbox.sh` → **DET-1..DET-8 harte PASS, Exit 0**; at-Ausnahme aktiv (assertiert, real unterschiedliche Wanduhr-`at`-Werte A vs. B); Manifest `generated_by` konsumiert; Witness nicht-vakuum (Baseline-SHA ≠ Run-SHA). **Spec-Frontmatter:** `status: 'done'`, `review_loop_iteration: 2`; Frozen-Intent nur im D-3-Umfang geändert (Typo, autorisiert). `sprint-status.yaml`-Key `3-8-…` → **`done`** (D-2; Sequenzierungs-Hinweis im Key-Kommentar), `last_updated` → 08-20-2026 17:04. **Erhaltungs-Invariante §5.9 Pkt. 5 gewahrt:** `git status --porcelain -- wiki/` zeigt ausschließlich `wiki/log.md` (dieser Eintrag); AD-3 read-only (`schema/validator.md`/`schema/wiki-compiler.md`/`adapters/`/`raw/` unverändert).
- **Story 3.8 → Review-Loop-2-Abschluss + Step-05 (Determinismus-Vertrag, 2026-08-20):** Re-Review der Re-Open-Implementierung (3 Layer synchron — blind-hunter / edge-case-hunter-Retry / verification-gap; edge-case-hunter erste Ausgabe leer → per Re-Run ersetzt). **Triage:** keine intent_gap/bad_spec (kein Loopback); **10 Patch / 0 defer** / Rest Reject. Kern-Veranlassung: die drei Re-Open-ACs wurden als *nicht wirklich ausgeübt* erkannt (Manifest dekorativ/nie konsumiert; `at`-Maskierung **vor** dem Commit = stiller Ausschluss statt dokumentierter Ausnahme; kein `verified[]`-Feld; Receipt ohne Reihenfolge-/Entscheidungsfeld; Subshell ohne `set -e`). **Patches (ausschließlich `sandbox-3-8/run-sandbox.sh`):** DET-2 ganzheitlich gehärtet — `generated.at` wird als **reale Wanduhr-**Ausgabe je Lauf committet (`date -u`) und als `at_cell` im Receipt festgehalten; Normalisierung auf `AT` erst **beim Vergleich** (Hash über at-normalisierte Content-Projektion, §5.14 Pkt. 2 „ohne die maskierte at-Zeile"); Nach-Commit-Attestierung `committed_at == at_now`; Zwei-Run-Abgleich byte-identisch für alle deterministischen Receipt-Bestandteile, nur die zwei Ausnahme-Cells `at_cell`/`tree` dürfen differieren — die `at`-Varianz wird real demonstriert (Wanduhr `at` differiert in getrennten Worktree-Läufen); **kanonisches Eingabemanifest wird konsumiert/validiert** (abschnittsbewusste Extraktion `sources:`/`output_visible_run_identity:`, Baseline-Quellen-Existenz nach Input-Commit, HARD-FAIL bei fehlenden Keys); Receipt um **`order:`** und **`decisions:`** erweitert (§5.14 Pkt. 2) + Receipt-Nicht-Vakuum-Guard; Subshell **`set -e`** (kein false-PASS); `match_stufe_a` **literal-sicher** (Term regex-escaped, §3.2-Pkt.-2a/§5.14 Pkt. 5) + CRLF-tolerante Body-Extraktion; `cand`-Newline-Normalisierung; `log_bullet` **fail-hard** (mktemp/mv-Fehler nicht mehr geschluckt — ein verlorener log-Eintrag hätte Vakuum-Gleichheit durch identische Baseline-Hashes erzeugt); `git worktree prune` vor dem Add (Re-Run-Sicherheit); `git clean` fail-hard unter `set -e`. **Verifikation re-executiert:** `bash _bmad-output/implementation-artifacts/sandbox-3-8/run-sandbox.sh` → **DET-1..DET-8 harte PASS, Exit 0**; `BEFUND: at-Ausnahme aktiv` mit real unterschiedlichen Wanduhr-`at`-Werten (Lauf A vs. B), Witness nicht-vakuum (Baseline-SHA != Run-SHA); Validator-Verdikt (human-mechanisch, Rev 9, D-3): alle `wiki/`-Dateien SUCCESS (keine Inhalts-Mutation). **Erhaltungs-Invariante §5.9 Pkt. 5 gewahrt:** `git status --porcelain -- wiki/` zeigt ausschließlich diesen Eintrag in `wiki/log.md`; `schema/validator.md`/`schema/wiki-compiler.md`/`adapters/`/`raw/` unverändert (AD-3). Spec **Change Log Review-Loop-2** (append-only); Suggested Review Order auf gehärtete Sandbox-Anker aktualisiert. `sprint-status.yaml`-Key `3-8-…` → **`review`** (Review-Start/Neu-Flip; finaler `done`-Flip Story-Konvention), `last_updated` → 08-20-2026 17:05; Spec-Frontmatter `status: 'in-review' → 'done'`, `review_loop_iteration: 0`.
- **Story 3.8 → Re-Open-Delta (Determinismus-Vertrag, genehmigtes Sprint-Change-Proposal 2026-08-20):** `_bmad-output/planning-artifacts/sprint-change-proposal-2026-08-20.md` (approved, ProMods, explizite Chat-Freigabe) nimmt Story 3.8 aus `review` nach `in-progress` zurück (Epics-Datei ACs Z. 357–370). **§5.14-Wortlaut (Re-Open-Delta):** Zwei-Run-Bestätigungs-Mechanik umgestellt auf **zwei getrennte saubere Worktrees + frische Agent-Kontexte** (Q-6/A0-19 — eine zweite Ausführung in derselben Session genügt nicht), unter **kanonischem Eingabemanifest** (Baseline-Commit, geordnete Source-Eingaben, output-sichtbare Run-/Zeit-/Identitätswerte, A0-19) und mit **Run-Receipt** (Candidate-Liste, Reihenfolge, Plan, Entscheidungen, Output-Hashes) **außerhalb des Knowledge Bundle**; **keine hart codierten erwarteten Pläne/Concept-Bodies** und **keine pauschale `verified`-Maskierung** (einzige benannte Ausnahme bleibt der dokumentierte `generated.at`-Wanduhr-Gap, A0-20/§5.14 Pkt. 3). **Sandbox DET-2 umgebaut** (zwei getrennte Worktrees `wt-a`/`wt-b` + `manifest.yaml` + `receipts/run2a.receipt/run2b.receipt` außerhalb des Bundles; Candidate-Ableitung aus Git-State via deterministischem Stufe-a-Match, nicht hart codiert; Abgleich der beiden Receipts als tatsächlicher Zwei-Run-Vergleich, nicht-vakuum): `bash _bmad-output/implementation-artifacts/sandbox-3-8/run-sandbox.sh` → **DET-1..DET-8 harte PASS, Exit 0** (Zwei-Run-Identität byte-identisch bis auf die benannte `at`-Ausnahme; Witness weicht von Baseline ab). `schema/compiler.md` §8 **Revision 3.3** (Re-Open-Klausel); §5.13-„in einer Session" unverändert (AD-6-Phasen-Disziplin, Fugen-Identität). **Validator-Verdikt** (human-mechanisch, `schema/validator.md` Rev 9, D-3 — kein CLI): alle `wiki/`-Dateien SUCCESS (keine Inhalts-Mutation). **Erhaltungs-Invariante §5.9 Pkt. 5:** `git status --porcelain -- wiki/` zeigt ausschließlich diesen Eintrag in `wiki/log.md`; `sprint-status.yaml` → `in-progress`; AD-3 read-only (validator/wiki-compiler/adapters/raw/ unverändert).