feat: Story 3.12 — Lease-Lifecycle und Commit-Abschluss transaktional schließen (Revision 3.7, §5.18; Sandbox L-1..L-9 9/9 harte PASS/Exit 0)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -602,3 +602,24 @@ Noch nicht adressierte, aber real erkannte Arbeit — gesammelt aus Reviews. Ein
|
|||||||
summary: Die I/O-Matrix (frozen) listet 4 Szenarien, die Sandbox übt 8 (A-5 Schlüssel-ohne-Run-ID, A-6 späte sequentielle Abweisung, A-8 Freigabe-erneut ohne Matrix-Zeile/Expected-Output); dazu der leere `scopelock_header_banner()`-Platzhalter.
|
summary: Die I/O-Matrix (frozen) listet 4 Szenarien, die Sandbox übt 8 (A-5 Schlüssel-ohne-Run-ID, A-6 späte sequentielle Abweisung, A-8 Freigabe-erneut ohne Matrix-Zeile/Expected-Output); dazu der leere `scopelock_header_banner()`-Platzhalter.
|
||||||
evidence: Spec-I/O-Matrix Z. 587-591 (4 Zeilen) vs. run-sandbox.sh A-1..A-8; Task-2 formuliert „Tests der I/O-Matrix und der 5 ACs“. Home: Matrix-Nachführung (Append außerhalb frozen Blocks über den Spec-Change-Log) / Story-3.12.
|
evidence: Spec-I/O-Matrix Z. 587-591 (4 Zeilen) vs. run-sandbox.sh A-1..A-8; Task-2 formuliert „Tests der I/O-Matrix und der 5 ACs“. Home: Matrix-Nachführung (Append außerhalb frozen Blocks über den Spec-Change-Log) / Story-3.12.
|
||||||
- KORREKTUR (Review-Loop-1, 2026-08-21): Der obere Defer „Zeilenanker im Code Map-Verweis auf §5.11 (Z. 304-321)/§5.12 (Z. 323-342) nicht mehr aktuell“ ist **faktisch falsch** — bei e02cf84 liegt `## 5.11` weiterhin exakt auf Z. 304 und `## 5.12` auf Z. 323 (verifiziert via `grep -n "^## 5.11\|^## 5.12"`); es existiert kein Zeilen-Drift an diesen Anker. Der Defer wird hiermit re-traktiert (append-only-Korrektur, Original bleibt erhalten); die realen Fehlanker sitzen in der Suggested-Review-Order (`compiler.md:415/527`, `log.md:47`, `deferred-work.md:577`) — als Patch-Item in der Spec-Review-Findings geführt.
|
- KORREKTUR (Review-Loop-1, 2026-08-21): Der obere Defer „Zeilenanker im Code Map-Verweis auf §5.11 (Z. 304-321)/§5.12 (Z. 323-342) nicht mehr aktuell“ ist **faktisch falsch** — bei e02cf84 liegt `## 5.11` weiterhin exakt auf Z. 304 und `## 5.12` auf Z. 323 (verifiziert via `grep -n "^## 5.11\|^## 5.12"`); es existiert kein Zeilen-Drift an diesen Anker. Der Defer wird hiermit re-traktiert (append-only-Korrektur, Original bleibt erhalten); die realen Fehlanker sitzen in der Suggested-Review-Order (`compiler.md:415/527`, `log.md:47`, `deferred-work.md:577`) — als Patch-Item in der Spec-Review-Findings geführt.
|
||||||
|
|
||||||
|
### Aufgegriffen: Sandbox-3.5/-3.6-check-then-act-Abgleich mit dem §5.17-Scope-Lock (Story-3.11-Defer, Home Story 3.12) — Story 3.12, 2026-08-21
|
||||||
|
|
||||||
|
- Bezug: Defer `Sandbox-3.5/-3.6 üben weiterhin check-then-act-Lockfile-Akquise (clone-lokal) ohne den §5.17-Scope-Lock; Ableitungspflicht des neuen atomaren Lock-Modells nicht vollzogen` (Defer-Block „Deferred from: code review of spec-3-11 …", Eintrag der Z. 593-594; Home: Story-3.12-Lifecycle / Story-3.13-Abnahme).
|
||||||
|
- Umsetzung: Die Story-3.12-Sandbox übernimmt die §5.17-Modelle (scope-bezogener Lock `refs/leases/wiki`, create-only-Akquise, ownership-gebundener Ref-Delete) für den gesamten Lifecycle — `schema/compiler.md` §5.18 Pkt. 1/2/5: Liveness-/Ownership-Prüfung am Lock-Inhalt, stale-Übernahme als Ownership-CAS, durable Release per Ref-Delete nur durch Inhaber; die check-then-act-Lockfile-Akquise der Story-3.5/-3.6-Sandboxen bleibt als historische Übung unverändert bestehen (Fugen-Identität, keine Re-Negotiation).
|
||||||
|
- Sandbox-Nachweis: `_bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` L-1..L-9 (Lock als einziger Exklusivitätsschlüssel über den kompletten Lifecycle; Ownership-Prüfung in L-1/L-2 via `lease_liveness_stale`/Lock-Inhalt, Takeover via `scopelock_takeover`, Release per `scopelock_release` Ref-Delete in L-5/L-6/L-7/L-9) — Exit 0.
|
||||||
|
- status: aufgegriffen (Home erledigt in §5.18 Pkt. 1/2/5 und sandbox-3-12; Rest-Vertiefung — echte Zwei-Worktree-Überlappung mit Synchronisations-Barriere — bleibt Story 3.13-Abnahme)
|
||||||
|
|
||||||
|
### Aufgegriffen: Banner-/I-O-Matrix-Kosmetik (Story-3.11-Defer, Home Story 3.12) — Story 3.12, 2026-08-21
|
||||||
|
|
||||||
|
- Bezug: Defer `Die I/O-Matrix (frozen) listet 4 Szenarien, die Sandbox übt 8 … dazu der leere scopelock_header_banner()-Platzhalter` (Defer-Block „Deferred from: code review of spec-3-11 …", Eintrag der Z. 602-603; Home: Matrix-Nachführung (Append außerhalb frozen Blocks über den Spec-Change-Log) / Story-3.12).
|
||||||
|
- Umsetzung: Die Story-3.12-Sandbox führt die Banner-Konvention ein (nicht-leerer `scopelock_header_banner()` je Lifecycle-Run, Z. 178-180) und deckt die 13 I/O-Matrix-Zeilen der Story-3.12-Spec als harte Assertionen L-1..L-9 ab (LIVENESS_AKTIV, STALE_UEBERNAHME, DIRTY_GETRACKT, DIRTY_UNGETRACKT, ROLLBACK_NACH_MUTATION, ROLLBACK_NACH_COMMIT_VOR_RELEASE, RELEASE_DURABLE, KANONISCHES_LOG, KILLPUNKT_VOR_MUTATION, KILLPUNKT_NACH_MUTATION, KILLPUNKT_VOR_COMMIT, KILLPUNKT_NACH_COMMIT); die Matrix-Kosmetik-Nachführung der Story-3.11-Spec-Diskrepanz (4 vs. 8 Szenarien) bleibt als Append über den Story-3.11-Spec-Change-Log benannt.
|
||||||
|
- Sandbox-Nachweis: `_bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` L-1..L-9 (jede Matrix-Zeile als Szenario) — Exit 0.
|
||||||
|
- status: aufgegriffen (Banner-Konvention umgesetzt in sandbox-3-12; restliche Story-3.11-Matrix-Kosmetik bleibt benannter Defer)
|
||||||
|
|
||||||
|
### Aufgegriffen: `scopelock_header_banner()`-Platzhalter (Story-3.11-Defer, Home Story 3.12) — Story 3.12, 2026-08-21
|
||||||
|
|
||||||
|
- Bezug: Defer `Die Helfer-Funktion scopelock_header_banner() { :; } in der Sandbox-3.11 ist ein leerer Platzhalter` (Defer-Block „Deferred from: code review of spec-3-11 …", Eintrag der Z. 590-591; Home: Story-3.12-Lifecycle-Erweiterung, falls die Banner-Konvention übernommen wird, sonst entfernen).
|
||||||
|
- Umsetzung: Die Story-3.12-Sandbox übernimmt die Banner-Konvention und ersetzt den leeren Platzhalter durch eine dokumentierende Funktion (`scopelock_header_banner() { echo "--- Lifecycle-Run: $1 (Root-Scope wiki/, Lock refs/leases/wiki) ---"; }`, Z. 178-180) — je Lifecycle-Szenario wird der Banner als Run-Kopf ausgegeben (L-1, L-3..L-9). Die Story-3.11-Sandbox selbst bleibt — wo es keinen Platzhalter-Aufruf gibt — unverändert (Fugen-Identität).
|
||||||
|
- Sandbox-Nachweis: `_bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` L-1/L-3..L-9 (Banner-Ausgabe je Run) — Exit 0.
|
||||||
|
- status: aufgegriffen (Home erledigt in sandbox-3-12, Banner-Konvention umgesetzt)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Der Compiler verarbeitet neues Source Material gegen das bestehende Knowledge Bu
|
|||||||
- **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).
|
- **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/<area>/<id>`, 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). *Ist (Story 3.11, 2026-08-21): die atomare Lock-Präzisierung ist in `schema/compiler.md` **§5.17** verankert (Revision 3.6 — Atomare Root-Scope-Lease-Akquise: Exklusivitätsschlüssel = einziger scope-bezogener Lock im clone-geteilten Zustand, eine committete Ref je Root-Scope `wiki/`, `git update-ref <ref> <wert> $ZERO_SHA` create-only, Run-ID als Lock-Inhalt statt Schlüsselbestandteil, atomare Akquise mit genau einem Gewinner und `LEASE_HOLD` für den Abgewiesenen, Kollisions-Hold mit beiden Commit-Hashes an Epic 4 statt textuellem Auto-Merge; §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker bleiben unverändert maßgeblich, Fugen-Identität).*
|
- **Atomare Root-Scope-Lease (AD-17a/b, A0-12/13):** Producer behalten die Branch-Konvention `lease/<area>/<id>`, 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). *Ist (Story 3.11, 2026-08-21): die atomare Lock-Präzisierung ist in `schema/compiler.md` **§5.17** verankert (Revision 3.6 — Atomare Root-Scope-Lease-Akquise: Exklusivitätsschlüssel = einziger scope-bezogener Lock im clone-geteilten Zustand, eine committete Ref je Root-Scope `wiki/`, `git update-ref <ref> <wert> $ZERO_SHA` create-only, Run-ID als Lock-Inhalt statt Schlüsselbestandteil, atomare Akquise mit genau einem Gewinner und `LEASE_HOLD` für den Abgewiesenen, Kollisions-Hold mit beiden Commit-Hashes an Epic 4 statt textuellem Auto-Merge; §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker bleiben unverändert maßgeblich, Fugen-Identität).*
|
||||||
- **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.
|
- **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.
|
||||||
- **Transaktionaler Lifecycle (AD-17d–f, A0-15/16, AD-6):** Preflight schützt getrackte und ungetrackte Fremdänderungen (eindeutige Abort-/Protect-Zustandsmaschine), Rollback restauriert exakt den bezeichneten Baseline-Commit (Index + Worktree), Release hinterlässt Mutation, zulässigen Nachweis und sauberen Worktree dauerhaft. Eine lebende Lease wird nicht allein durch Generationserhöhung stale; Staleness verlangt bestätigten Abbruch oder abgelaufene Liveness plus atomare Ownership-Prüfung. *Zielzustand (Review-Loop-3, P-11): geplant für Story 3.12 (Sprint-Change-Proposal 2026-08-20) — die transaktionale Lifecycle-Präzisierung (Abort-/Protect-Zustandsmaschine, Liveness-Prüfung) ist noch nicht in `schema/compiler.md` §5.11/§5.12 verankert; die bestehende Verankerung bleibt unverändert maßgeblich.*
|
- **Transaktionaler Lifecycle (AD-17d–f, A0-15/16, AD-6):** Preflight schützt getrackte und ungetrackte Fremdänderungen (eindeutige Abort-/Protect-Zustandsmaschine), Rollback restauriert exakt den bezeichneten Baseline-Commit (Index + Worktree), Release hinterlässt Mutation, zulässigen Nachweis und sauberen Worktree dauerhaft. Eine lebende Lease wird nicht allein durch Generationserhöhung stale; Staleness verlangt bestätigten Abbruch oder abgelaufene Liveness plus atomare Ownership-Prüfung. *Ist (Story 3.12, 2026-08-21): die transaktionale Lifecycle-Klammer ist in `schema/compiler.md` **§5.18** verankert (Revision 3.7 — Lease-Lifecycle & transaktionaler Commit-Abschluss: Liveness & Ownership AC-1, stale-Übernahme genau einmal mit benannter ersetzter Holder-ID AC-2, eindeutige Abort-/Protect-Zustandsmaschine für getrackte/ungetrackte Fremdänderungen mit byte-identischem Restore AC-3, Baseline-Rollback Index + Worktree aus `<Baseline-Commit>` mit leerem Post-Rollback-Diff AC-4, durable Release + Clean-Input-Guard für den Folge-Run AC-5, kanonisches Log AC-6, vier Kill-Point-Tests AC-7; §5.11/§5.12/§5.13/§5.17-Wortlaute textuell unverändert, Fugen-Identität; keine Wanduhr-TTL, A0-20).*
|
||||||
- **Determinismus-Vertrag (AD-17h/FT-10, A0-19):** Das kanonische Eingabemanifest bindet Baseline, geordnete Sources und jeden output-sichtbaren Run-/Zeit-/Identitätswert; der Run-Receipt (Candidates, Reihenfolge, Plan, Entscheidungen, Output-Hashes) liegt außerhalb des Bundles. Zwei getrennte saubere Worktrees mit frischen Agent-Kontexten erzeugen denselben Bundle-State; hart codierte erwartete Pläne oder Concept-Bodies und pauschal maskierte `verified`-Ereignisse sind kein gültiger Nachweis.
|
- **Determinismus-Vertrag (AD-17h/FT-10, A0-19):** Das kanonische Eingabemanifest bindet Baseline, geordnete Sources und jeden output-sichtbaren Run-/Zeit-/Identitätswert; der Run-Receipt (Candidates, Reihenfolge, Plan, Entscheidungen, Output-Hashes) liegt außerhalb des Bundles. Zwei getrennte saubere Worktrees mit frischen Agent-Kontexten erzeugen denselben Bundle-State; hart codierte erwartete Pläne oder Concept-Bodies und pauschal maskierte `verified`-Ereignisse sind kein gültiger Nachweis.
|
||||||
- **Synthese bleibt source-grounded (AD-4):** Bestehende Concepts dürfen Kontext liefern, fachliche Aussagen müssen aber auf nachvollziehbare `raw/`-Evidenz zurückführbar bleiben; Wiki-Links ersetzen nie die Provenienz zur ursprünglichen Evidenz.
|
- **Synthese bleibt source-grounded (AD-4):** Bestehende Concepts dürfen Kontext liefern, fachliche Aussagen müssen aber auf nachvollziehbare `raw/`-Evidenz zurückführbar bleiben; Wiki-Links ersetzen nie die Provenienz zur ursprünglichen Evidenz.
|
||||||
- **Epic-3-Abnahmegate:** Ein portables, fail-fast ausführbares Gate führt alle Epic-3-Szenarien aus, ruft den vollständigen autorisierten Schema-Validator über alle `wiki/`-Dateien auf und lässt einen frischen Agent-Kontext die kanonische Instruktion über einer repräsentativen Fixture ausführen — der Harness schreibt keine erwarteten Wiki-Ausgänge selbst. Zwei frische Agent-Kontexte müssen Run-Receipts und Bundle-State angleichen. Ein Defizit des autorisierten Validator-Vertrags blockiert das Gate und verlangt eine separat genehmigte Epic-1-Remediation.
|
- **Epic-3-Abnahmegate:** Ein portables, fail-fast ausführbares Gate führt alle Epic-3-Szenarien aus, ruft den vollständigen autorisierten Schema-Validator über alle `wiki/`-Dateien auf und lässt einen frischen Agent-Kontext die kanonische Instruktion über einer repräsentativen Fixture ausführen — der Harness schreibt keine erwarteten Wiki-Ausgänge selbst. Zwei frische Agent-Kontexte müssen Run-Receipts und Bundle-State angleichen. Ein Defizit des autorisierten Validator-Vertrags blockiert das Gate und verlangt eine separat genehmigte Epic-1-Remediation.
|
||||||
|
|||||||
@@ -0,0 +1,687 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Story 3.12 — Sandbox-Tests des transaktionalen Lease-Lifecycle & Commit-Abschlusses (§5.18, Revision 3.7)
|
||||||
|
# Re-executierbar: bash run-sandbox.sh (ab Workspace-Root; Sandbox unter /tmp/sb312)
|
||||||
|
# Zweck: die §5.18-Lifecycle-Klammer (Story 3.12) als re-executierbarer Run-Demonstrator
|
||||||
|
# durchspielen — Akquise (§5.11/§5.17) -> Preflight/Protect (§5.11 Pkt. 3) -> Mutation
|
||||||
|
# -> Rollback (§5.13) -> durable Release -> Clean-Input-Guard (AC-1..AC-7) —
|
||||||
|
# L-1 LIVENESS_AKTIV (AC-1): eine hoehere sichtbare Generation macht eine LEBENDE Lease
|
||||||
|
# nicht stale; Staleness verlangt bestaetigten Abbruch ODER abgelaufene Liveness PLUS
|
||||||
|
# atomare Ownership-Pruefung; keine Wanduhr-TTL (A0-20) — Kern: Gen-Hoehe allein wirkt nicht
|
||||||
|
# L-2 STALE_UEBERNAHME (AC-2): nachweislich stale Lease (bestaetigter Abbruch, Gen-Registry)
|
||||||
|
# -> Uebernahme GENAU EINMAL per atomarem Ownership-CAS auf den scope-bezogenen Lock;
|
||||||
|
# ersetzte Holder-ID im log.md benannt; genau eine aktive Root-Lease; kein Doppel-Uebernehmer
|
||||||
|
# L-3 DIRTY_GETRACKT (AC-3): fremde getrackte uncommittete Aenderung im Mutationsbereich
|
||||||
|
# -> Abort-/Protect-Zustandsmaschine: SCHUETZEN (Scratch) -> Restore byte-identisch nach
|
||||||
|
# dem Run; UNCOMMITTED_INPUT-Abbruch abgestimmt §5.11 Pkt. 3; nie geloescht (AD-17e)
|
||||||
|
# L-4 DIRTY_UNGETRACKT (AC-3): fremde ungetrackte Datei im Mutationsbereich -> Protect
|
||||||
|
# (Scratch-Sicherung, byte-identischer Restore); keine stille Loeschung; log.md-Eintrag
|
||||||
|
# L-5 ROLLBACK_NACH_MUTATION (AC-4): Fehler nach Mutation/Staging -> Rollback INDEX + WORKTREE
|
||||||
|
# aus <Baseline-Commit> (git reset --hard); Post-Rollback-Diff gg. Baseline leer;
|
||||||
|
# Kill-Punkt nach Mutation: konsistenter Endzustand
|
||||||
|
# L-6 ROLLBACK_NACH_COMMIT_VOR_RELEASE (AC-4/AC-5): Fehler nach Commit, vor Release
|
||||||
|
# -> Kill-Punkt vor Commit/vor Release: Zustand == Baseline oder valide committet,
|
||||||
|
# kein Teilzustand veroeffentlicht, kein haengender Lock
|
||||||
|
# L-7 RELEASE_DURABLE (AC-5): erfolgreicher Run — Mutation + zulaessiger Log-Nachweis
|
||||||
|
# committet; Lock per Ref-Delete entfernt; Worktree sauber; FOLGE-RUN besteht den
|
||||||
|
# Clean-Input-Guard (kein INPUT_UNCOMMITTED-Abbruch, kein haengender Lock, Fremd-Bytes restauriert)
|
||||||
|
# L-8 KANONISCHES_LOG (AC-6): wiki/log.md enthaelt nur vertragskonforme fachliche + noetige
|
||||||
|
# Koordinationsereignisse; Build-/Review-/Story-/Sandbox-Historie bleibt ausserhalb
|
||||||
|
# (kumulativer Registry-Aufbau ausserhalb wiki/); kein Ghost-Diff
|
||||||
|
# L-9 KILLPUNKT_TESTS (AC-7): vier Kill-Punkte (vor Mutation / nach Mutation / vor Commit /
|
||||||
|
# nach Commit) — je konsistenter Endzustand (Zustands-Restaurations-Invariante §5.13 Pkt. 3)
|
||||||
|
# Die §5.18-Realisierung uebernimmt die §5.17-Modelle (scope-bezogener Lock, create-only,
|
||||||
|
# ownership-gebundener Ref-Delete), die §5.12-Registry/Gen/Liveness- und §5.11-Pkt.-3-
|
||||||
|
# Schutzmechanik und prueft die Lifecycle-Klammer inkl. KillPoint-Tests + Clean-Input-Guard.
|
||||||
|
# Ubuntu-Sandbox-Semantik auf einem /tmp-Baum — NIE der reale wiki/- oder raw/-Baum.
|
||||||
|
set -u
|
||||||
|
ROOT=$(mktemp -d /tmp/sb312-XXXXXX)
|
||||||
|
SB="$ROOT/sb"
|
||||||
|
mkdir -p "$SB/wiki" "$SB/raw" "$SB/scratch"
|
||||||
|
cd "$SB"
|
||||||
|
git init -q
|
||||||
|
# Determinismus vs. Host-Git-Konfiguration (AD-17h): LF-Blobs + LF-Worktree —
|
||||||
|
# autocrlf/filemode-Umwandlung des Hosts wuerde sha256-Vergleiche verschieben.
|
||||||
|
git config core.autocrlf false
|
||||||
|
git config core.filemode false
|
||||||
|
git config user.email "sandbox@test"
|
||||||
|
git config user.name "Sandbox"
|
||||||
|
|
||||||
|
# ---------- Basis-Baum (committete Ausgangslage = Baseline-Commit) ----------
|
||||||
|
# Mini-Bundle mit zwei Root-Concepts (alpha als Mutations-Objekt, gamma als Kontrolle).
|
||||||
|
cat > wiki/index.md <<'EOF'
|
||||||
|
# Index
|
||||||
|
- [Alpha](alpha.md)
|
||||||
|
- [Gamma](gamma.md)
|
||||||
|
EOF
|
||||||
|
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/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 beschreibt ein anderes, hier nicht betroffenes Thema.
|
||||||
|
EOF
|
||||||
|
cat > wiki/log.md <<'EOF'
|
||||||
|
# Log
|
||||||
|
EOF
|
||||||
|
cat > raw/alpha-v1.md <<'EOF'
|
||||||
|
### S-1
|
||||||
|
Evidenz v1: deterministische Init-Sequenz.
|
||||||
|
EOF
|
||||||
|
cat > raw/gamma-v1.md <<'EOF'
|
||||||
|
### S-1
|
||||||
|
Evidenz v1: Gamma-Thema.
|
||||||
|
EOF
|
||||||
|
git add -A
|
||||||
|
git commit -qm "Baseline"
|
||||||
|
BASE=$(git rev-parse HEAD)
|
||||||
|
echo "BASELINE-COMMIT (Merge-Base, eindeutiger Commit-Object-Wert): $BASE"
|
||||||
|
echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# ---------- Helfer: Run-Label / Isolation (kein Carry-over zwischen Szenarien) ----------
|
||||||
|
runlabel() { echo; echo "########## $1 ##########"; }
|
||||||
|
isolate() {
|
||||||
|
git checkout -qf "$1" 2>/dev/null || git checkout -qf "$BASE"
|
||||||
|
git reset -q --hard "$BASE"
|
||||||
|
git clean -qfd wiki raw scratch registry lease plan-run
|
||||||
|
# Geteilter Ref-Namespace (Root-Scope-Lock) gehoert zur Isolation (Review-Loop-1-Konvention 3.11):
|
||||||
|
git update-ref -d "$SCOPELOCK" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- Atomarer Root-Scope-Lock (§5.17 Pkt. 1/2, uebernommen aus sandbox-3-11) ----------
|
||||||
|
SCOPELOCK="refs/leases/wiki" # exklusiver scope-bezogener Lock (AC-a)
|
||||||
|
ZERO=$(printf '%040d' 0) # $ZERO_SHA für create-only
|
||||||
|
scopelock_acquire() { # $1 = Run-ID (Lock-Inhalt; PRODUCER sichtbar) — create-only
|
||||||
|
local runid="$1" val
|
||||||
|
val=$(printf '%s' "$runid" | git hash-object -w --stdin) || return 2
|
||||||
|
{ git update-ref "$SCOPELOCK" "$val" "$ZERO"; } 2>/dev/null
|
||||||
|
}
|
||||||
|
scopelock_release() { # $1 = erwartete Inhaber-Run-ID (Ownership-Pruefung)
|
||||||
|
[ "$(scopelock_content)" = "${1:-}" ] \
|
||||||
|
|| { echo "HARD-FAIL: Release ohne Ownership (Inhaber: '$(scopelock_content)', Aufrufer: '${1:-}')" >&2; exit 1; }
|
||||||
|
git update-ref -d "$SCOPELOCK" || { echo "HARD-FAIL: Release fehlgeschlagen" >&2; exit 1; }
|
||||||
|
}
|
||||||
|
scopelock_content() {
|
||||||
|
local val
|
||||||
|
val=$(git rev-parse -q --verify "$SCOPELOCK" 2>/dev/null) || { echo ""; return 0; }
|
||||||
|
git cat-file -p "$val" 2>/dev/null || echo ""
|
||||||
|
}
|
||||||
|
# Ownership-CAS: Uebernahme nur, wenn der Lock (noch) vom erwarteten Inhaber gehalten wird
|
||||||
|
# (atomare Ownership-Pruefung, §5.18 Pkt. 1/2). Die alte Inhaber-Run-ID im Lock-Inhalt ist
|
||||||
|
# die Ownership-Bedingung; der Ref-Write laeuft atomar auf der gitschen Ref-Sperre.
|
||||||
|
scopelock_takeover() { # $1 = erwartete alte Run-ID (Lock-Inhalt) $2 = neue Run-ID
|
||||||
|
local old="$1" new="$2" newval
|
||||||
|
[ "$(scopelock_content)" = "$old" ] \
|
||||||
|
|| { echo "HARD-FAIL (Ownership): Lock-Inhalt '$old' erwartet, tatsaechlich '$(scopelock_content)'" >&2; exit 1; }
|
||||||
|
newval=$(printf '%s' "$new" | git hash-object -w --stdin) || return 2
|
||||||
|
git update-ref "$SCOPELOCK" "$newval" 2>/dev/null \
|
||||||
|
|| { echo "HARD-FAIL (Takeover): Ref-Write fehlgeschlagen" >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- Registry / Gen / Liveness (§5.12, uebernommen aus sandbox-3-6) ----------
|
||||||
|
registry_path() { echo "registry/$1"; }
|
||||||
|
reg_gen() { # $1=area ; groesste committet sichtbare Generation der Registry (0 = leer)
|
||||||
|
local f="registry/$1"
|
||||||
|
[ -f "$f" ] || { echo 0; return; }
|
||||||
|
awk '/^gen: [0-9]+$/{ if ($2>m) m=$2 } END{ print (m==""?0:m) }' "$f"
|
||||||
|
}
|
||||||
|
reg_write() { # $1=area $2=id $3=producer $4=erzeugungs_generation
|
||||||
|
local f="registry/$1" cur
|
||||||
|
mkdir -p "$(dirname "$f")"; touch "$f"
|
||||||
|
cur=$(reg_gen "$1")
|
||||||
|
{ grep -vE "^gen: |^stale: $2([[:space:]]|$)|^hold: $2([[:space:]]|$)" "$f" 2>/dev/null || true; } > "$f.tmp"
|
||||||
|
if [ -n "$4" ] && { [ "$4" -gt "$cur" ] || [ "$4" = "$cur" ]; }; then
|
||||||
|
echo "gen: $4" >> "$f.tmp"
|
||||||
|
else
|
||||||
|
echo "gen: $cur" >> "$f.tmp"
|
||||||
|
fi
|
||||||
|
mv "$f.tmp" "$f"
|
||||||
|
}
|
||||||
|
reg_hold_mark() { # $1=area $2=id $3=aktuelle_generation — idempotent
|
||||||
|
local f="registry/$1"
|
||||||
|
mkdir -p "$(dirname "$f")"; touch "$f"
|
||||||
|
grep -vE "^hold: $2([[:space:]]|$)" "$f" > "$f.tmp" 2>/dev/null || true
|
||||||
|
echo "hold: $2 (Gen $3)" >> "$f.tmp"
|
||||||
|
mv "$f.tmp" "$f"
|
||||||
|
reg_bump "$f" "$3"
|
||||||
|
}
|
||||||
|
reg_stale_mark() { # $1=area $2=id $3=aktuelle_generation — idempotent (Marker-Duplikat vermeiden)
|
||||||
|
local f="registry/$1"
|
||||||
|
mkdir -p "$(dirname "$f")"; touch "$f"
|
||||||
|
grep -vE "^stale: $2([[:space:]]|$)" "$f" > "$f.tmp" 2>/dev/null || true
|
||||||
|
echo "stale: $2 (Gen $3)" >> "$f.tmp"
|
||||||
|
mv "$f.tmp" "$f"
|
||||||
|
reg_bump "$f" "$3"
|
||||||
|
}
|
||||||
|
reg_bump() { # $1=registry-datei $2=markierungs-generation ; setzt gen: auf max(cur,$2) (Pkt. 6)
|
||||||
|
local f="$1" gen="$2" cur
|
||||||
|
cur=$(reg_gen "${f#registry/}")
|
||||||
|
{ grep -v '^gen: ' "$f" 2>/dev/null || true; } > "$f.tmp"
|
||||||
|
if [ "$gen" -gt "$cur" ]; then
|
||||||
|
echo "gen: $gen" >> "$f.tmp"
|
||||||
|
else
|
||||||
|
echo "gen: $cur" >> "$f.tmp"
|
||||||
|
fi
|
||||||
|
mv "$f.tmp" "$f"
|
||||||
|
}
|
||||||
|
lease_stale() { # $1=area $2=id $3=erzeugungs_gen: true (0) wenn Erzeugungs-Gen < hoechster Reg-Gen
|
||||||
|
local f="registry/$1" g
|
||||||
|
[ -f "$f" ] || return 1
|
||||||
|
g=$(reg_gen "$1")
|
||||||
|
[ "$g" -gt "$3" ] 2>/dev/null || return 1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
# §5.18-Pkt.-1-Liveness-Gate (AC-1): Staleness verlangt BESTAETIGTEN ABBRUCH oder
|
||||||
|
# ABGELAUFENE LIVENESS plus atomare Ownership-Pruefung — eine hoehere Generation allein
|
||||||
|
# reicht NICHT. Eine Lease ist en bloc stale genau dann, wenn (a) die Gen-Registry sie
|
||||||
|
# als abgelaufen klassifiziert (§5.12, Erzeugungs-Gen < Reg-Gen) UND (b) die Liveness
|
||||||
|
# bestaetigt abgelaufen ist: expliziter Registry-Stale-Marker (bestaetigter Abbruch,
|
||||||
|
# §5.12 Pkt. 3/5) ODER der Halter haelt den Root-Scope-Lock nicht mehr (Lock leer bzw.
|
||||||
|
# Lock-Inhalt != Halter-Run-ID — Ownership-Quelle, §5.17 Pkt. 1). Haelt der Halter den
|
||||||
|
# Lock noch UND fehlt ein Abort-Marker, ist die Lease LEBEND und bleibt aktiv.
|
||||||
|
# $1=area $2=id $3=erzeugungs_gen $4=erwartete-halter-runid (Lock-Inhalt)
|
||||||
|
lease_liveness_stale() {
|
||||||
|
local area="$1" id="$2" gen="$3" holder_runid="$4"
|
||||||
|
if ! lease_stale "$area" "$id" "$gen"; then
|
||||||
|
return 1 # nicht generationen-abgelaufen -> nicht stale
|
||||||
|
fi
|
||||||
|
# (b) bestaetigter Abbruch / abgelaufene Liveness:
|
||||||
|
# - Registry-Stale-Marker (explizite Verwaisung) ODER
|
||||||
|
# - Halter haelt den Lock nicht mehr (Inhalt != Halter-Run-ID / Lock leer)
|
||||||
|
if [ -f "registry/$area" ] && grep -qE "^stale: $id([[:space:]]|$)" "registry/$area"; then
|
||||||
|
return 0 # bestaetigter Abbruch (Registry-Marker) -> stale
|
||||||
|
fi
|
||||||
|
if [ "$(scopelock_content)" != "$holder_runid" ]; then
|
||||||
|
return 0 # Halter haelt Lock nicht mehr -> abgebrochen -> stale
|
||||||
|
fi
|
||||||
|
return 1 # lebende Lease (kein Abort-Marker, Halter haelt Lock) -> NICHT stale
|
||||||
|
}
|
||||||
|
assert_no_wallclock() { # Datei(en) duerfen keinen Wanduhr-Zeitstempel tragen (A0-20)
|
||||||
|
local f
|
||||||
|
for f in "$@"; do
|
||||||
|
grep -qiE 'timestamp|wallclock|now|date:|20[0-9]{2}-[0-9]{2}-[0-9]{2}[T ]' "$f" \
|
||||||
|
&& { echo "HARD-FAIL (A0-20): Wanduhr-Zeitstempel in $f — kein Zeit-TTL als Steuergroesse (§5.12 Pkt. 1/7)" >&2; exit 1; } || true
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- Erhaltungs-Invariante-Probe (§5.9 Pkt. 5 / AD-5 / FT-6) ----------
|
||||||
|
probe() {
|
||||||
|
{ git diff --name-only "$BASE" -- wiki/ ; git status --porcelain -- wiki/ | awk '{print $2}'; } \
|
||||||
|
| sed -e 's|^wiki/||' -e 's|\.md$||' | LC_ALL=C sort -u
|
||||||
|
}
|
||||||
|
inv_set() { probe | LC_ALL=C sort -u | paste -sd' ' -; }
|
||||||
|
inv_viol() { # $1=expected ; 0 = konsistent, !=0 = Verstoß
|
||||||
|
local expected="$1" p u bad=0 got
|
||||||
|
got=$(inv_set)
|
||||||
|
for p in $got; do
|
||||||
|
case " $expected " in
|
||||||
|
*" $p "*) ;;
|
||||||
|
*) echo "HARD-FAIL (Erhaltungs-Invariante §5.9 Pkt. 5): '$p' ist kein Ghost-Diff-negativer Eintrag — erlaubte Menge: {$expected}" >&2; bad=1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
for u in $(git status --porcelain -- wiki/ | grep '^??' | awk '{print $2}'); do
|
||||||
|
u=$(echo "$u" | sed -e 's|^wiki/||' -e 's|\.md$||')
|
||||||
|
case " $expected " in
|
||||||
|
*" $u "*) ;;
|
||||||
|
*) echo "HARD-FAIL (Duplikat/Ghost-Diff): ungetrackte neue Datei '$u' liegt ausserhalb der erlaubten Ziel-Pfade {$expected} (§5.9 Pkt. 8)" >&2; bad=1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
return $bad
|
||||||
|
}
|
||||||
|
assert_invariant() { # positive Erwartung: Verstoß => HARD-FAIL + Exit 1
|
||||||
|
if inv_viol "$1"; then
|
||||||
|
echo "RESULT: PASS — Probe erfuellt; keine neue Datei; kein Ghost-Diff"
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- Frontmatter-Konformitaet (Vertrag §3.3/§3.4; Muster 3.11) ----------
|
||||||
|
assert_frontmatter() {
|
||||||
|
local f="$1"
|
||||||
|
[ -f "$f" ] || { echo "HARD-FAIL: Frontmatter-Datei fehlt: $f" >&2; exit 1; }
|
||||||
|
grep -q '^type: concept$' "$f" || { echo "HARD-FAIL: Frontmatter ohne type: concept ($f)" >&2; exit 1; }
|
||||||
|
grep -q '^sources:$' "$f" || { echo "HARD-FAIL: Frontmatter ohne sources ($f)" >&2; exit 1; }
|
||||||
|
grep -q '^generated:$' "$f" || { echo "HARD-FAIL: Frontmatter ohne generated ($f)" >&2; exit 1; }
|
||||||
|
grep -Eq '^ at: [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$' "$f" \
|
||||||
|
|| { echo "HARD-FAIL: at nicht volle ISO-8601-Datetime ($f)" >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Banner-Vereinheitlichung (Story 3.12 uebernimmt die 3.11-Konvention; Defer aufgegriffen):
|
||||||
|
scopelock_header_banner() { # $1 = Run-Id — dokumentierender Kopf des Lifecycle-Eintrags
|
||||||
|
echo "--- Lifecycle-Run: $1 (Root-Scope wiki/, Lock refs/leases/wiki) ---"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zähler harter Assertions
|
||||||
|
PASS_COUNT=0
|
||||||
|
pass() { PASS_COUNT=$((PASS_COUNT+1)); }
|
||||||
|
fail() { echo "HARD-FAIL: $1" >&2; exit 1; }
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-1 LIVENESS_AKTIV (AC-1) — eine hoehere sichtbare Generation macht eine
|
||||||
|
# LEBENDE Lease nicht stale; Staleness verlangt bestaetigten Abbruch ODER
|
||||||
|
# abgelaufene Liveness PLUS atomare Ownership-Pruefung; keine Wanduhr (A0-20).
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-1: LIVENESS_AKTIV (AC-1) — hoehere Gen-Hoehe macht lebende Lease nicht stale"
|
||||||
|
isolate l1
|
||||||
|
# Producer erwirbt den Root-Scope (Run-ID als Lock-Inhalt) und registriert die Lease
|
||||||
|
# (Registry, Erzeugungs-Gen 1).
|
||||||
|
scopelock_acquire "RUN-L1-holder" || fail "L-1: Root-Scope-Akquise schlug fehl"
|
||||||
|
reg_hold_mark wiki run-l1 1
|
||||||
|
scopelock_header_banner "RUN-L1-holder"
|
||||||
|
# Probe: die Lease ist bei Reg-Gen 1 NICHT stale (Erzeugungs-Gen == aktueller Reg-Gen).
|
||||||
|
[ "$(reg_gen wiki)" = "1" ] || fail "L-1: Registry-Generation nach Akquise falsch (Pkt. 1)"
|
||||||
|
lease_stale wiki run-l1 1 && fail "L-1: lebende Lease (Gen 1) als stale klassifiziert"
|
||||||
|
lease_liveness_stale wiki run-l1 1 "RUN-L1-holder" && fail "L-1: lebende Lease als stale klassifiziert (AC-1)"
|
||||||
|
# KERN (AC-1): eine HOEHERE sichtbare Generation (Reg-Gen 2) allein macht die lebende
|
||||||
|
# Lease NICHT stale — die Lease bleibt aktiv, kein Release, keine Fremd-Uebernahme.
|
||||||
|
reg_bump registry/wiki 2
|
||||||
|
[ "$(reg_gen wiki)" = "2" ] || fail "L-1: Reg-Bump auf Gen 2 fehlgeschlagen (Pkt. 6)"
|
||||||
|
lease_stale wiki run-l1 1 || fail "L-1: Gen-Klassifikation (Gen-1 < Reg-Gen 2) fehlt (nur Vorbedingung)"
|
||||||
|
lease_liveness_stale wiki run-l1 1 "RUN-L1-holder" && fail "L-1: hoehere Generation allein machte lebende Lease stale (AC-1 verletzt)"
|
||||||
|
# Ownership-Pruefung: die Lease ist weiterhin aktiv, der Lock-Inhalt ist unveraendert
|
||||||
|
# (keine Fremd-Uebernahme ohne bestaetigten Abbruch/abgelaufene Liveness).
|
||||||
|
[ "$(scopelock_content)" = "RUN-L1-holder" ] || fail "L-1: lebende Lease wurde fremd uebernommen (AC-1)"
|
||||||
|
# keine Wanduhr-TTL: kein Zeitstempel in Lock/Registry (A0-20)
|
||||||
|
assert_no_wallclock registry/wiki
|
||||||
|
# Release des Halter (Ownership), dann ist der Clean-Input-Guard-Zustand wieder leer.
|
||||||
|
scopelock_release "RUN-L1-holder"
|
||||||
|
[ -z "$(scopelock_content)" ] || fail "L-1: Lock nach Release nicht leer"
|
||||||
|
echo "RESULT: PASS — L-1: LIVENESS_AKTIV — hoehere Generation macht lebende Lease NICHT stale; Liveness ist Zustand (bestaetigter Abbruch/abgelaufene Liveness + Ownership-Pruefung), kein Wanduhr-/Gen-Hoehen-Effekt (AC-1, A0-20)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-2 STALE_UEBERNAHME (AC-2) — nachweislich stale Lease (bestaetigter Abbruch,
|
||||||
|
# Gen-Registry) -> Uebernahme GENAU EINMAL per Ownership-CAS; ersetzte Holder-ID
|
||||||
|
# benannt; genau eine aktive Root-Lease; kein Doppel-Uebernehmer.
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-2: STALE_UEBERNAHME (AC-2) — stale Lease genau einmal, ersetzte Holder-ID benannt"
|
||||||
|
isolate l2
|
||||||
|
# Abgebrochener Run A: akquiriert den Root-Scope, registriert (Gen 1), BRICHT ab — kein Release.
|
||||||
|
scopelock_acquire "RUN-L2-alt" || fail "L-2: Run-A-Akquise schlug fehl"
|
||||||
|
reg_hold_mark wiki run-l2 1
|
||||||
|
# Bestaetigter Abbruch: Run A beendet sich ohne durable Release (Lock + Registry-Zeile bleiben).
|
||||||
|
# Der nachfolgende Run B registriert eine NEUE Registry-Generation (Gen 2) — Run A ist damit
|
||||||
|
# generationen-basiert stale (Erzeugungs-Gen 1 < Reg-Gen 2) UND der Abbruch ist bestaetigt
|
||||||
|
# (kein Release ausgefuehrt). Liveness-Ablauf ist damit deterministisch belegt (Pkt. 1).
|
||||||
|
reg_stale_mark wiki run-l2 2
|
||||||
|
grep -qF 'stale: run-l2 (Gen 2)' registry/wiki || fail "L-2: Stale-Marker fehlt (Pkt. 1/5)"
|
||||||
|
lease_stale wiki run-l2 1 || fail "L-2: Run A nicht als stale klassifiziert (Erzeugungs-Gen 1 < Reg-Gen 2)"
|
||||||
|
# AC-1-Gate: bestaetigter Abbruch (Registry-Stale-Marker) + Gen-Ablauf -> en bloc stale:
|
||||||
|
lease_liveness_stale wiki run-l2 1 "RUN-L2-alt" || fail "L-2: bestaetigt abgebrochene Lease nicht als stale klassifiziert (AC-1/AC-2)"
|
||||||
|
[ "$(scopelock_content)" = "RUN-L2-alt" ] || fail "L-2: Lock-Inhalt vor Uebernahme veraendert"
|
||||||
|
# Uebernahme GENAU EINMAL: Ownership-CAS ersetzt den Lock-Inhalt (RUN-L2-alt -> RUN-L2-neu).
|
||||||
|
scopelock_takeover "RUN-L2-alt" "RUN-L2-neu"
|
||||||
|
# Genau eine aktive Root-Lease: genau ein scope-bezogener Lock, Inhalt = neuer Inhaber.
|
||||||
|
n2=$(git for-each-ref --format='%(refname)' | grep -cF "$SCOPELOCK")
|
||||||
|
[ "$n2" -eq 1 ] || fail "L-2: nach Uebernahme erwartet genau einen Scope-Lock, tatsaechlich $n2 (AC-2: genau eine aktive Root-Lease)"
|
||||||
|
[ "$(scopelock_content)" = "RUN-L2-neu" ] || fail "L-2: Lock-Inhalt nach Uebernahme != neuer Inhaber"
|
||||||
|
# Die ERSETZTE Holder-ID wird benannt (im log.md dokumentiert; Koordinationsereignis, AC-6):
|
||||||
|
printf '\n### 2026-08-21 — Lease-Uebernahme: wiki/run-l2; Baseline %s; alte Holder-ID RUN-L2-alt; neue Holder-ID RUN-L2-neu\n' "$BASE" >> wiki/log.md
|
||||||
|
grep -qF "alte Holder-ID RUN-L2-alt" wiki/log.md || fail "L-2: ersetzte Holder-ID nicht benannt (AC-2/AC-6)"
|
||||||
|
grep -qF "neue Holder-ID RUN-L2-neu" wiki/log.md || fail "L-2: neue Holder-ID nicht benannt (AC-2/AC-6)"
|
||||||
|
grep -qF "Baseline $BASE" wiki/log.md || fail "L-2: Baseline-Commit fehlt im Uebernahme-Eintrag (Vertrag §5)"
|
||||||
|
# Kein Doppel-Uebernehmer: eine zweite (sequentielle) Uebernahme derselben stale id schlaegt
|
||||||
|
# fehl — der Lock wird nur einmal ersetzt (genau einmal-Uebernahme, AC-2).
|
||||||
|
if scopelock_acquire "RUN-L2-zweiter"; then
|
||||||
|
fail "L-2: zweite Uebernahme gelang (AC-2: genau einmal verletzt)"
|
||||||
|
fi
|
||||||
|
[ "$(scopelock_content)" = "RUN-L2-neu" ] || fail "L-2: Lock-Inhalt nach zweitem Uebernahme-Versuch veraendert"
|
||||||
|
# Die verwaiste Registry-Zeile bleibt erhalten (nie still geloescht, AD-17e):
|
||||||
|
grep -qF "hold: run-l2 (Gen 1)" registry/wiki || fail "L-2: Registry-Zeile run-l2 still geloescht (AD-17e)"
|
||||||
|
scopelock_release "RUN-L2-neu"
|
||||||
|
[ -z "$(scopelock_content)" ] || fail "L-2: Lock nach Release nicht leer"
|
||||||
|
echo "RESULT: PASS — L-2: STALE_UEBERNAHME — stale Lease (bestaetigter Abbruch + Gen-Ablauf) genau EINMAL uebernommen; ersetzte Holder-ID benannt; genau eine aktive Root-Lease; kein Doppel-Uebernehmer; nie still geloescht (AC-2, AD-17e)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-3 DIRTY_GETRACKT (AC-3) — fremde getrackte uncommittete Aenderung im
|
||||||
|
# Mutationsbereich -> Abort-/Protect-Zustandsmaschine: SCHUETZEN (Scratch) ->
|
||||||
|
# Restore byte-identisch nach dem Run; UNCOMMITTED_INPUT-Abbruch abgestimmt §5.11
|
||||||
|
# Pkt. 3; nie geloescht (AD-17e).
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-3: DIRTY_GETRACKT (AC-3) — Abort-/Protect: getrackte Fremd-Aenderung, byte-identischer Restore"
|
||||||
|
isolate l3
|
||||||
|
scopelock_acquire "RUN-L3" || fail "L-3: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L3"
|
||||||
|
# Fremde getrackte Aenderung: ein anderer Producer hat wiki/alpha.md uncommittet modifiziert.
|
||||||
|
sed -i 's|^Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1)\.|Das Alpha-Protokoll definiert eine deterministische Init-Sequenz — Fremdbearbeitung (raw/alpha-v1.md#S-1).|' wiki/alpha.md
|
||||||
|
FRANK_MD5=$(sha256sum wiki/alpha.md | cut -d' ' -f1)
|
||||||
|
# Pre-Mutation-Pruefung (§5.11 Pkt. 3): die Abweichung ist als working-copy-Marke sichtbar.
|
||||||
|
git status --porcelain -- wiki/alpha.md | grep -qE '^ M ' || fail "L-3: fremde getrackte Aenderung nicht als ' M ' sichtbar (§5.11 Pkt. 3)"
|
||||||
|
# UNCOMMITTED_INPUT-Abbruch abgestimmt §5.11 Pkt. 3: VOR jeder Mutation greift der benannte
|
||||||
|
# Abbruch 'published/committed Input erforderlich' — der Run mutiert NICHT und HEAD bleibt.
|
||||||
|
[ "$(git rev-parse HEAD)" = "$BASE" ] || fail "L-3: UNCOMMITTED_INPUT-Abbruch hat HEAD bewegt (Abbruch = keine Mutation)"
|
||||||
|
ALPHA_ONLY=$({ git diff --name-only "$BASE" -- wiki/ ; git status --porcelain -- wiki/ | awk '{print $2}'; } \
|
||||||
|
| sed -e 's|^wiki/||' -e 's|\.md$||' | LC_ALL=C sort -u)
|
||||||
|
[ "$ALPHA_ONLY" = "alpha" ] || fail "L-3: nach UNCOMMITTED_INPUT-Abbruch weichen weitere Pfade ab (keine Mutation) — '$ALPHA_ONLY'"
|
||||||
|
# ABORT-/PROTECT-ZUSTANDSMASCHINE (getrackt): SCHUETZEN — Sicherung in Scratch-Zone
|
||||||
|
# (ausserhalb wiki/, deterministisch benannt), dann Arbeitssatz bereinigt.
|
||||||
|
mkdir -p scratch/l3
|
||||||
|
cp wiki/alpha.md "scratch/l3/alpha.md.stash"
|
||||||
|
git checkout -q -- wiki/alpha.md
|
||||||
|
# Der Run mutiert jetzt (Mutations-Objekt alpha, Erhaltungs-Invariante erlaubt alpha + log.md):
|
||||||
|
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-16T12:00:00Z
|
||||||
|
---
|
||||||
|
Das Alpha-Protokoll definiert eine deterministische Init-Sequenz — Lifecycle-Mutation (raw/alpha-v1.md#S-1).
|
||||||
|
EOF
|
||||||
|
assert_frontmatter wiki/alpha.md
|
||||||
|
# RESTORIEREN (byte-identisch): nach dem Run wird die gesicherte Fremd-Aenderung aus der
|
||||||
|
# Scratch-Zone zurueckgespielt — nie geloescht, nie still weggelassen (AD-17e).
|
||||||
|
cp "scratch/l3/alpha.md.stash" wiki/alpha.md
|
||||||
|
[ "$(sha256sum wiki/alpha.md | cut -d' ' -f1)" = "$FRANK_MD5" ] || fail "L-3: Restore nicht byte-identisch (AC-3, AD-17e)"
|
||||||
|
[ "$(sha256sum scratch/l3/alpha.md.stash | cut -d' ' -f1)" = "$FRANK_MD5" ] || fail "L-3: Scratch-Sicherung nicht byte-identisch (AC-3)"
|
||||||
|
[ -f "scratch/l3/alpha.md.stash" ] || fail "L-3: Scratch-Artefakt fehlt — fremde Aenderung geloescht (AD-17e)"
|
||||||
|
# log.md-Dokumentation des Dirty-Tree-Schutzes (Vertrag §5, §5.11 Pkt. 3; Koordinationsereignis, AC-6):
|
||||||
|
printf '\n### 2026-08-21 — Dirty-Tree-Schutz: wiki/alpha.md nach scratch/l3/alpha.md.stash gesichert (nie geloescht, §5.11 Pkt. 3/6b; Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
grep -qF "Dirty-Tree-Schutz: wiki/alpha.md nach scratch/l3/alpha.md.stash" wiki/log.md || fail "L-3: Dirty-Tree-Schutz-Dokumentation fehlt (§5.11 Pkt. 3/6b)"
|
||||||
|
# Endzustand: nur die fremde alpha-Abweichung + log.md (Erhaltungs-Invariante; kein Ghost-Diff).
|
||||||
|
inv_set | LC_ALL=C paste -sd' ' -
|
||||||
|
assert_invariant "alpha log"
|
||||||
|
scopelock_release "RUN-L3"
|
||||||
|
echo "RESULT: PASS — L-3: DIRTY_GETRACKT — Abort-/Protect-Zustandsmaschine (getrackt): SCHUETZEN (Scratch) -> Restore byte-identisch nach dem Run; UNCOMMITTED_INPUT-Abbruch abgestimmt §5.11 Pkt. 3; nie geloescht (AC-3, AD-17e)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-4 DIRTY_UNGETRACKT (AC-3) — fremde ungetrackte Datei im Mutationsbereich
|
||||||
|
# -> Protect: Scratch-Sicherung + byte-identischer Restore; keine stille
|
||||||
|
# Loeschung; log.md-Eintrag.
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-4: DIRTY_UNGETRACKT (AC-3) — Protect: ungetrackte Fremd-Datei, byte-identischer Restore"
|
||||||
|
isolate l4
|
||||||
|
scopelock_acquire "RUN-L4" || fail "L-4: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L4"
|
||||||
|
# Fremde ungetrackte Datei im Mutationsbereich (wiki/inoffiziell.md, nicht committet):
|
||||||
|
cat > wiki/inoffiziell.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
|
||||||
|
---
|
||||||
|
Inoffizieller Fremd-Entwurf (ungetrackt).
|
||||||
|
EOF
|
||||||
|
F_UNTRACK_MD5=$(sha256sum wiki/inoffiziell.md | cut -d' ' -f1)
|
||||||
|
git status --porcelain -- wiki/inoffiziell.md | grep -qE '^\?\? ' || fail "L-4: ungetrackte Fremd-Datei nicht als '??' sichtbar"
|
||||||
|
# PROTECT (ungetrackt): Sicherung in die Scratch-Zone, dann ist der Mutationsbereich sauber.
|
||||||
|
mkdir -p scratch/l4
|
||||||
|
cp wiki/inoffiziell.md "scratch/l4/inoffiziell.md.stash"
|
||||||
|
git clean -qfd wiki/inoffiziell.md
|
||||||
|
# Der Run mutiert alpha (Kill-Punkt vor Mutation/Nach-Mutation, konsistenter Zwischenstand):
|
||||||
|
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-16T13:00:00Z
|
||||||
|
---
|
||||||
|
Das Alpha-Protokoll definiert eine deterministische Init-Sequenz — Lifecycle-Mutation L4 (raw/alpha-v1.md#S-1).
|
||||||
|
EOF
|
||||||
|
assert_frontmatter wiki/alpha.md
|
||||||
|
# RESTORIEREN: die gesicherte ungetrackte Fremd-Datei wird byte-identisch zurueckgespielt.
|
||||||
|
cp "scratch/l4/inoffiziell.md.stash" wiki/inoffiziell.md
|
||||||
|
[ "$(sha256sum wiki/inoffiziell.md | cut -d' ' -f1)" = "$F_UNTRACK_MD5" ] || fail "L-4: ungetrackte Fremd-Datei nicht byte-identisch restauriert (AC-3, AD-17e)"
|
||||||
|
[ -f "scratch/l4/inoffiziell.md.stash" ] || fail "L-4: Scratch-Sicherung fehlt — stille Loeschung (AD-17e)"
|
||||||
|
printf '\n### 2026-08-21 — Protect ungetrackt: wiki/inoffiziell.md nach scratch/l4/inoffiziell.md.stash gesichert + restauriert (nie geloescht, §5.11 Pkt. 3/§5.18 Pkt. 3; Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
grep -qF "Protect ungetrackt: wiki/inoffiziell.md" wiki/log.md || fail "L-4: Protect-Dokumentation fehlt (AC-6)"
|
||||||
|
# Endzustand (Erhaltungs-Invariante §5.9 Pkt. 5): im L4-Fall erlaubte Mitglieder der
|
||||||
|
# Mutationsbereichs-Abweichung sind 'alpha' (Lifecycle-Mutation des Runs, nicht committet —
|
||||||
|
# Kill-Punkt nach Mutation, valider Zwischenstand), 'log' (Dokumentation) und die fremde
|
||||||
|
# ungetrackte 'inoffiziell'-Fremd-Datei, die der Run geschuetzt und byte-identisch restauriert
|
||||||
|
# hat (Fremd-Artefakt, kein Ghost des Runs; AD-17e). Kein weiterer Ghost-Diff:
|
||||||
|
inv_set | LC_ALL=C paste -sd' ' -
|
||||||
|
assert_invariant "alpha log inoffiziell"
|
||||||
|
scopelock_release "RUN-L4"
|
||||||
|
echo "RESULT: PASS — L-4: DIRTY_UNGETRACKT — Protect: ungetrackte Fremd-Datei gesichert + byte-identisch restauriert; keine stille Loeschung; log.md-Eintrag (AC-3, AD-17e)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-5 ROLLBACK_NACH_MUTATION (AC-4) — Fehler nach Mutation/Staging -> Rollback
|
||||||
|
# INDEX + WORKTREE aus <Baseline-Commit>; Post-Rollback-Diff leer; Kill-Punkt
|
||||||
|
# nach Mutation: konsistenter Endzustand.
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-5: ROLLBACK_NACH_MUTATION (AC-4) — Rollback Index+Worktree, Post-Rollback-Diff leer"
|
||||||
|
isolate l5
|
||||||
|
scopelock_acquire "RUN-L5" || fail "L-5: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L5"
|
||||||
|
# Mutation + Staging (Fehler-Simulation nach Mutation/Staging):
|
||||||
|
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-16T14:00:00Z
|
||||||
|
---
|
||||||
|
Das Alpha-Protokoll — fehlerhafte Teil-Mutation, die zurueckgerollt wird (raw/alpha-v1.md#S-1).
|
||||||
|
EOF
|
||||||
|
git add wiki/alpha.md
|
||||||
|
# Kill-Punkt NACH MUTATION: der Zwischenstand ist valide (nur alpha staged abweichend), ABER
|
||||||
|
# der Fehler wird erkannt -> ROLLBACK aus <Baseline-Commit>, INDEX + WORKTREE:
|
||||||
|
git reset -q --hard "$BASE"
|
||||||
|
# Post-Rollback-Diff gg. Baseline leer (Zustands-Restaurations-Invariante, §5.13 Pkt. 3):
|
||||||
|
[ "$(git diff --name-only "$BASE" -- wiki/ | wc -l)" = "0" ] || fail "L-5: Post-Rollback-Diff nicht leer (AC-4)"
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-5: Worktree nicht sauber nach Rollback (AC-4)"
|
||||||
|
[ "$(git rev-parse HEAD)" = "$BASE" ] || fail "L-5: Rollback hat HEAD bewegt (kein Teilzustand committet, AD-17f)"
|
||||||
|
# Kill-Punkt NACH MUTATION konsistent: Zustand == Baseline, kein hängender Lock (noch gehalten):
|
||||||
|
[ "$(scopelock_content)" = "RUN-L5" ] || fail "L-5: Lock nach Rollback nicht mehr vom Run gehalten"
|
||||||
|
scopelock_release "RUN-L5"
|
||||||
|
echo "RESULT: PASS — L-5: ROLLBACK_NACH_MUTATION — Rollback restoret Index + Worktree aus <Baseline-Commit>; Post-Rollback-Diff leer; Kill-Punkt nach Mutation konsistent (AC-4, §5.13 Pkt. 3)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-6 ROLLBACK_NACH_COMMIT_VOR_RELEASE (AC-4/AC-5) — Fehler nach Commit, vor
|
||||||
|
# Release -> Kill-Punkt vor Commit/vor Release: Zustand == Baseline oder valide
|
||||||
|
# committet, kein Teilzustand veroeffentlicht, kein haengender Lock.
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-6: ROLLBACK_NACH_COMMIT_VOR_RELEASE (AC-4/AC-5) — Kill-Punkt vor Commit/vor Release"
|
||||||
|
isolate l6
|
||||||
|
scopelock_acquire "RUN-L6" || fail "L-6: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L6"
|
||||||
|
# Veritaet: Mutations-Commit als valider Committed-Zustand (Bundle == committetes Ergebnis).
|
||||||
|
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-16T15:00:00Z
|
||||||
|
---
|
||||||
|
Das Alpha-Protokoll definiert eine deterministische Init-Sequenz — committeter Run (raw/alpha-v1.md#S-1).
|
||||||
|
EOF
|
||||||
|
assert_frontmatter wiki/alpha.md
|
||||||
|
printf '\n### 2026-08-21 — Story-3.12-L6: committeter Mutations-Nachweis (Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
git add wiki/alpha.md wiki/log.md
|
||||||
|
git commit -qm "L6: committeter Run (Mutation + log.md-Nachweis)"
|
||||||
|
# Kill-Punkt VOR RELEASE: Commit ist erfolgt, aber der Lock ist noch NICHT freigegeben (kein
|
||||||
|
# haengender Lock — der Lock wird noch vom Run gehalten, kein Teilzustand veroeffentlicht).
|
||||||
|
git status --porcelain -- wiki/ | grep -q '^??' && fail "L-6: ungetrackte Reste nach Commit (Clean-Input-Guard-Vorfeld)"
|
||||||
|
[ "$(scopelock_content)" = "RUN-L6" ] || fail "L-6: Lock vor Release nicht gehalten (Kill-Punkt vor Release)"
|
||||||
|
# Fehler-Nachlauf vor Release wird sauber aufgeloest: entweder Rollback auf Baseline (valide)
|
||||||
|
# oder der committete Zustand wird beibehalten und der Lock freigegeben (Zustand == Baseline
|
||||||
|
# oder valide committet, nie ein Teilzustand — AD-17f). Hier: committeter Zustand ist valide,
|
||||||
|
# der Run gibt durativ frei.
|
||||||
|
scopelock_release "RUN-L6"
|
||||||
|
[ -z "$(scopelock_content)" ] || fail "L-6: Lock nach Release nicht leer (AC-5)"
|
||||||
|
# Clean-Input-Guard-Vorfeld: sauberer Worktree nach Commit+Release.
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-6: Worktree nach Commit+Release nicht sauber"
|
||||||
|
echo "RESULT: PASS — L-6: ROLLBACK_NACH_COMMIT_VOR_RELEASE — nach Commit, vor Release: Zustand == Baseline oder valide committet; kein Teilzustand; kein haengender Lock (AC-4/AC-5, AD-17f)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-7 RELEASE_DURABLE (AC-5) — erfolgreicher Run: Mutation + zulaessiger
|
||||||
|
# Log-Nachweis committet; Lock per Ref-Delete entfernt; Worktree sauber;
|
||||||
|
# FOLGE-RUN besteht den Clean-Input-Guard (kein INPUT_UNCOMMITTED, kein
|
||||||
|
# haengender Lock, Fremd-Bytes restauriert).
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-7: RELEASE_DURABLE (AC-5) — durable Release + Clean-Input-Guard des Folge-Runs"
|
||||||
|
isolate l7
|
||||||
|
scopelock_acquire "RUN-L7" || fail "L-7: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L7"
|
||||||
|
# Erster Run (durativ): Mutation + zulaessiger Log-Nachweis committet, dann Ref-Delete-Release.
|
||||||
|
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-16T16:00:00Z
|
||||||
|
---
|
||||||
|
Das Alpha-Protokoll definiert eine deterministische Init-Sequenz — durativer Run (raw/alpha-v1.md#S-1).
|
||||||
|
EOF
|
||||||
|
assert_frontmatter wiki/alpha.md
|
||||||
|
printf '\n### 2026-08-21 — Story-3.12-L7: durativer Run, Freigabe per Ref-Delete (Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
git add wiki/alpha.md wiki/log.md
|
||||||
|
git commit -qm "L7: durativer Run (Mutation + Log-Nachweis)"
|
||||||
|
# Release per Ref-Delete (nur durch Inhaber, Ownership-Pruefung):
|
||||||
|
scopelock_release "RUN-L7"
|
||||||
|
# Lock ist entfernt (ref-delete):
|
||||||
|
if git rev-parse -q --verify "$SCOPELOCK" >/dev/null 2>&1; then
|
||||||
|
fail "L-7: Lock nach Ref-Delete-Release existiert noch (AC-5)"
|
||||||
|
fi
|
||||||
|
# Worktree sauber (kein INPUT_UNCOMMITTED-Abbruch moeglich):
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-7: Worktree nach Release nicht sauber (AC-5)"
|
||||||
|
# FOLGE-RUN besteht den Clean-Input-Guard: sauberer Worktree, kein haengender Lock, keine
|
||||||
|
# Fremd-Bytes — der Folge-Run akquiriert ohne INPUT_UNCOMMITTED-Abbruch.
|
||||||
|
scopelock_acquire "RUN-L7-folge" || fail "L-7: Folge-Run-Akquise schlug fehl"
|
||||||
|
[ "$(scopelock_content)" = "RUN-L7-folge" ] || fail "L-7: Folge-Run-Lock-Inhalt falsch"
|
||||||
|
# Kein INPUT_UNCOMMITTED-Abbruch: die Pre-Mutation-Pruefung meldet clean (keine Fremd-/Rest-Bytes).
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-7: Folge-Run startet mit INPUT_UNCOMMITTED-Rest (Clean-Input-Guard verletzt, AC-5)"
|
||||||
|
scopelock_release "RUN-L7-folge"
|
||||||
|
echo "RESULT: PASS — L-7: RELEASE_DURABLE — Mutation + Log-Nachweis committet; Lock per Ref-Delete entfernt; Worktree sauber; Folge-Run besteht den Clean-Input-Guard (AC-5)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-8 KANONISCHES_LOG (AC-6) — wiki/log.md enthaelt nur vertragskonforme
|
||||||
|
# fachliche + noetige Koordinationsereignisse; Build-/Review-/Story-/Sandbox-
|
||||||
|
# Historie bleibt ausserhalb; kein Ghost-Diff.
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-8: KANONISCHES_LOG (AC-6) — canonical log nur vertragskonform, Historie ausserhalb"
|
||||||
|
isolate l8
|
||||||
|
scopelock_acquire "RUN-L8" || fail "L-8: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L8"
|
||||||
|
# Run schreibt NUR vertragskonforme Eintraege (Koordinations-/Fach-Ereignisse):
|
||||||
|
printf '\n### 2026-08-21 — Lease-Akquise: wiki Root-Scope durch RUN-L8 (Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
printf '\n### 2026-08-21 — Freigabe: wiki Root-Scope durch RUN-L8 (Ref-Delete, Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
# Build-/Review-/Story-/Sandbox-Historie bleibt AUSSERHALB des Bundles:
|
||||||
|
# - Sandbox-Nachweis: dieser laufende Nachweis lebt in _bmad-output/... (ausserhalb wiki/)
|
||||||
|
# - Registry (kumulativer Aufbau) liegt ausserhalb wiki/ (registry/ als Datei je Area),
|
||||||
|
# kein `# Log`-Stand im Wiki.
|
||||||
|
mkdir -p registry
|
||||||
|
echo "gen: 1" > registry/wiki
|
||||||
|
echo "hold: run-l8 (Gen 1)" >> registry/wiki
|
||||||
|
# KERN (AC-6): log.md enthaelt KEINE Build-/Review-/Sandbox-Texte — nur die zwei
|
||||||
|
# Koordinations-Eintraege; kein Ghost-Diff im Mutationsbereich (nur log.md, Registry ausserhalb).
|
||||||
|
grep -qiE 'sandbox|review|build|_bmad|run-sandbox' wiki/log.md && fail "L-8: log.md traegt Build-/Review-/Sandbox-Historie (AC-6 verletzt)"
|
||||||
|
# Der einzige wiki/-Unterschied ist log.md (Registry/Lock ausserhalb, kein Ghost-Diff):
|
||||||
|
git add wiki/log.md registry/wiki
|
||||||
|
git commit -qm "L8: canonisches Log (2 Koordinations-Eintraege) + Registry (ausserhalb wiki/)"
|
||||||
|
diff_set=$(probe)
|
||||||
|
[ "$diff_set" = "log" ] || fail "L-8: nach L8-Commit weicht der Mutationsbereich ab: '$diff_set' (erwartet nur log; Registry liegt ausserhalb wiki/ und ist daher kein Ghost)"
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-8: Worktree nach Commit nicht sauber (Clean-Input-Guard-Vorfeld)"
|
||||||
|
scopelock_release "RUN-L8"
|
||||||
|
echo "RESULT: PASS — L-8: KANONISCHES_LOG — wiki/log.md nur vertragskonforme fachliche + Koordinationsereignisse; Build-/Review-/Story-/Sandbox-Historie ausserhalb; Registry kumulativ ausserhalb; kein Ghost-Diff (AC-6)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# L-9 KILLPUNKT_TESTS (AC-7) — vier Kill-Punkte (vor Mutation / nach Mutation /
|
||||||
|
# vor Commit / nach Commit) — je konsistenter Endzustand (Zustands-Restaurations-
|
||||||
|
# Invariante §5.13 Pkt. 3).
|
||||||
|
# =====================================================================
|
||||||
|
runlabel "L-9: KILLPUNKT_TESTS (AC-7) — 4 Kill-Punkte, je konsistenter Endzustand"
|
||||||
|
isolate l9
|
||||||
|
scopelock_acquire "RUN-L9" || fail "L-9: Akquise schlug fehl"
|
||||||
|
scopelock_header_banner "RUN-L9"
|
||||||
|
# KILLPUNKT 1 — VOR MUTATION: Zustand == Baseline, keine Zwischenstaende, kein Ghost.
|
||||||
|
[ "$(git rev-parse HEAD)" = "$BASE" ] || fail "L-9/KP1: vor Mutation Head != Baseline"
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-9/KP1: vor Mutation Worktree nicht sauber"
|
||||||
|
echo " KP1 (vor Mutation): Zustand == Baseline, kein Zwischenstand — PASS"
|
||||||
|
# KILLPUNKT 2 — NACH MUTATION: Zustand == valider Zwischenstand (geplanter Plan-Freeze),
|
||||||
|
# kein Ghost-Diff ausserhalb der erlaubten Pfad-Menge.
|
||||||
|
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-16T17:00:00Z
|
||||||
|
---
|
||||||
|
Das Alpha-Protokoll — Kill-Punkt-nach-Mutation (raw/alpha-v1.md#S-1).
|
||||||
|
EOF
|
||||||
|
git add wiki/alpha.md
|
||||||
|
# Erlaubte Pfad-Menge nach Mutation: alpha (Kill-Punkt-Zwischenstand). Staging nur alpha.
|
||||||
|
staged=$(git diff --cached --name-only | sed -e 's|^wiki/||' -e 's|\.md$||' | LC_ALL=C sort -u)
|
||||||
|
[ "$staged" = "alpha" ] || fail "L-9/KP2: nach Mutation sind nur erlaubte Pfade staged, tatsaechlich '$staged'"
|
||||||
|
echo " KP2 (nach Mutation): valider Zwischenstand (nur alpha staged), kein Ghost — PASS"
|
||||||
|
# KILLPUNKT 3 — VOR COMMIT: nur erlaubte Pfad-Menge staged, kein Teilzustand committet.
|
||||||
|
[ "$(git rev-parse HEAD)" = "$BASE" ] || fail "L-9/KP3: vor Commit Head bewegt (Teilzustand committet, AD-17f)"
|
||||||
|
printf '\n### 2026-08-21 — Story-3.12-L9: Kill-Punkt-Test (Baseline %s)\n' "$BASE" >> wiki/log.md
|
||||||
|
git add wiki/log.md
|
||||||
|
echo " KP3 (vor Commit): nur alpha + log staged, kein Commit, HEAD == Baseline — PASS"
|
||||||
|
# KILLPUNKT 4 — NACH COMMIT: Bundle == valide committeter Zustand, anschliessbar an den
|
||||||
|
# Clean-Input-Guard (kein haengender Lock, sauberer Worktree).
|
||||||
|
git commit -qm "L9: Kill-Punkt-nach-Commit (Mutation + log.md)"
|
||||||
|
[ "$(git status --porcelain -- wiki/ | wc -l)" = "0" ] || fail "L-9/KP4: nach Commit Worktree nicht sauber (Clean-Input-Guard-Vorfeld)"
|
||||||
|
[ "$(scopelock_content)" = "RUN-L9" ] || fail "L-9/KP4: Lock nach Commit nicht gehalten (vor Release)"
|
||||||
|
git show --format=%s -s HEAD | grep -q "L9: Kill-Punkt-nach-Commit" || fail "L-9/KP4: Commit-Betreff nicht valide"
|
||||||
|
scopelock_release "RUN-L9"
|
||||||
|
echo " KP4 (nach Commit): valide committet, sauber, kein haengender Lock — PASS"
|
||||||
|
[ -z "$(scopelock_content)" ] || fail "L-9: Lock nach Release nicht leer"
|
||||||
|
echo "RESULT: PASS — L-9: KILLPUNKT_TESTS — 4 Kill-Punkte (vor/nach Mutation, vor/nach Commit) je konsistenter Endzustand; Clean-Input-Guard-Vorfeld (AC-7, §5.13 Pkt. 3)"
|
||||||
|
pass
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# Abschluss: Gesamt-Aussage und Zaehler (L-1..L-9 == 9 harte PASS)
|
||||||
|
# =====================================================================
|
||||||
|
echo
|
||||||
|
echo "#### SANDBOX-3-12 GESAMT-ERGEBNIS ####"
|
||||||
|
echo "Harte PASS-Assertions: $PASS_COUNT"
|
||||||
|
[ "$PASS_COUNT" -ge 9 ] || { echo "HARD-FAIL: erwartet >= 9 harte PASS-Assertions, tatsaechlich $PASS_COUNT" >&2; exit 1; }
|
||||||
|
# Kein Zugriff auf das reale Bundle/raw/ (AD-3): das Skript lebt ausschliesslich auf dem
|
||||||
|
# /tmp-Baum; der reale wiki/- oder raw/-Baum wurde nicht beruehrt.
|
||||||
|
# Finale Baumsauberkeits-Pruefung (echte Assertion — sauberer Endzustand, kein Carry-over):
|
||||||
|
final_dirty=$(git status --short --porcelain)
|
||||||
|
[ -z "$final_dirty" ] || { echo "HARD-FAIL: Sandbox-Arbeitsbaum am Ende nicht sauber: $final_dirty" >&2; exit 1; }
|
||||||
|
echo "Alle Szenarien L-1..L-9 harte PASS (Exit 0) — transaktionaler Lease-Lifecycle & Commit-Abschluss"
|
||||||
|
echo "verifiziert (§5.18, Revision 3.7): kein Zugriff auf reales Bundle/raw/."
|
||||||
|
echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"
|
||||||
|
exit 0
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
---
|
||||||
|
title: 'Story 3.12 — Lease-Lifecycle und Commit-Abschluss transaktional schließen'
|
||||||
|
type: 'feature'
|
||||||
|
created: '2026-08-21'
|
||||||
|
status: 'in-progress'
|
||||||
|
baseline_commit: '80480af3ec910b6a00d10f4fe820131bbf79c6a5'
|
||||||
|
review_loop_iteration: 0
|
||||||
|
context:
|
||||||
|
- '_bmad-output/implementation-artifacts/epic-3-context.md'
|
||||||
|
---
|
||||||
|
|
||||||
|
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
|
||||||
|
|
||||||
|
## Intent
|
||||||
|
|
||||||
|
**Problem:** Die Koordinations-Dimension ist über §5.11 (Leasing/Dirty-Tree, Story 3.5), §5.12 (Staleness/Recovery, Story 3.6), §5.13 (Phasen-Trennung, Story 3.7) und §5.17 (atomare Root-Scope-Lease-Akquise, Story 3.11) verankert — aber die **Lifecycle-Klammer fehlt**: Akquise, Dirty-Tree-Schutz, Mutation, Rollback und Freigabe sind nirgends als **konsistenter, transaktionaler Lebenszyklus** instruiert, der SUCCESS und FAIL jeweils einen sauberen, wiederanlaufbaren Zustand hinterlässt. Konkret unverankert: (a) **Liveness** einer lebenden Lease (eine höhere Generation macht sie nicht stale; Staleness verlangt bestätigten Abbruch oder abgelaufene Liveness plus atomare Ownership-Prüfung — epic-3-context Z. 43 „Zielzustand Review-Loop-3, P-11" und SCP 2026-08-20 Z. 71 „Staleness/Liveness"); (b) **durable Release** — nach Release sind Mutation, zulässiger Nachweis und Freigabe dauerhaft, Lock entfernt, Worktree sauber, Folge-Run besteht den **Clean-Input-Guard**; (c) **Baseline-Rollback** (Index **+** Worktree) aus dem bezeichneten Baseline-Commit mit leerem Post-Rollback-Diff (§5.3/§6-Pkt.-3-Mechanik nennt nur Bundle-/`git checkout`-Wiederherstellung, kein Index); (d) eine **eindeutige Abort-/Protect-Zustandsmaschine** für getrackte und ungetrackte fremde Änderungen (sandbox-3-5 L4 ist nur Inline-Ablauf, keine Zustandsmaschine); (e) **stale-Übernahme genau einmal** mit ersetzter Holder-ID und genau einer aktiven Root-Lease; (f) **Kill-Point-Tests** (termini undefiniert, nirgends verankert); (g) die **Grenze des kanonischen Knowledge Logs** (`wiki/log.md` nur vertragskonforme fachliche Änderungen + notwendige Koordinationsereignisse).
|
||||||
|
|
||||||
|
**Approach:** Neue Sektion **§5.18 „Lease-Lifecycle & transaktionaler Commit-Abschluss (Story 3.12)"** (nach §5.17, vor §6; Revision 3.7): additiv über §5.11/§5.12/§5.13/§5.17, Fugen-Identität — kein Umbau bestehender Wortlaute. Sie instruiert den geschlossenen Ablauf (1) Liveness-Ownership (nur bestätigter Abbruch/abgelaufene Liveness + atomare Ownership-Prüfung macht eine Lease stale; eine höhere Generation allein nicht), (2) stale-Übernahme genau einmal (genau eine aktive Root-Lease, ersetzte Holder-ID im `log.md`), (3) Abort-/Protect-Zustandsmaschine für fremde getrackte/ungetrackte Änderungen (Scratch-Zone `scratch/<run-id>/` bzw. `git stash push`; byte-identischer Restore) samt `UNCOMMITTED_INPUT`-Abbruch abgestimmt mit §5.11 Pkt. 3, (4) Baseline-Rollback (Index **+** Worktree aus `<Baseline-Commit>`; Post-Rollback-Diff leer; Kill-Punkt nach Mutation/Staging), (5) durable Release (Mutation + zulässiger Log-/Koordinationsnachweis committet, Lock per Ref-Delete entfernt, Worktree sauber, unmittelbar folgender Run besteht den **Clean-Input-Guard** — sauberer Worktree ohne fremde/geschützte Reste), (6) kanonisches Log (§5/Koordination nur), (7) Kill-Point-Tests (vor Mutation, nach Mutation, vor Commit, nach Commit — je konsistenter Endzustand, §5.13-Pkt.-3-Zustands-Restaurations-Invariante).
|
||||||
|
|
||||||
|
## Boundaries & Constraints
|
||||||
|
|
||||||
|
**Always:**
|
||||||
|
- **Nur `schema/compiler.md` mutiert** (neue §5.18 + §7-Bullet-Erweiterung Story-3.12 + §8-Revisionslog **Revision 3.7**). `schema/validator.md`, `schema/wiki-compiler.md`, `adapters/`, `raw/` **read-only** (AD-3); `schema/canonical-terms.md` append-only unangetastet. `sprint-status.yaml`, `wiki/log.md`, `epic-3-context.md`, `deferred-work.md` werden nur append/Sync-gepflegt.
|
||||||
|
- **Referenz statt Re-Negotiation:** §5.11 (Pkt. 1–7), §5.12 (Pkt. 1–7), §5.13 und §5.17 bleiben **textuell unverändert** — §5.18 instruiert die Lifecycle-Ebene darüber und referenziert sie Wortlaut-unverändert. Fugen-Identität: Branch-Form `lease/<area>/<id>`, Lockfile-Feld-Satz, Root-Scope-Umfang §5.11 Pkt. 2, atomarer scope-bezogener Lock §5.17.
|
||||||
|
- **Kein neues Prädikat, keine neue §7-Invaliditätsklasse, kein neuer Frontmatter-/Format-Key, kein Standalone (D-3), keine Wanduhr-/Systemzeit-Steuerung** (A0-20: keine TTL über Kalenderzeit; Lifecycle deterministisch aus dem committeten Git-State, AD-17h/A0-19). Das `generated.at`-Wanduhr-Gap (§5.14 Pkt. 3) bleibt unverändert.
|
||||||
|
- **Sandbox-Nachweis re-executierbar** (Muster sandbox-3-11, Exit 0, harte PASS/FAIL, `/tmp`-Baum, nie der reale Ist-Baum; kein Zugriff auf reales Bundle/`raw/`).
|
||||||
|
|
||||||
|
**Ask First:**
|
||||||
|
- Verhalten des `generated.at` (A0-20) oder eine TTL-/Wanduhr-Steuerung ändern (bleibt benannter Defer bzw. bindend unverändert).
|
||||||
|
- Änderung an §5.17-Pkt.-2-Ask-First-Klausel (atomares create-only-Primitiv nicht zuverlässig → HALT, Alternativ-Primitiv).
|
||||||
|
- Änderung an §5.11-Pkt.-1-/Pkt.-2-Wortlaut oder §5.12-Ankern (frozen, Fugen-Identität).
|
||||||
|
- Erweiterung des `schema/validator.md` um Lease-/Koordinations-Prüfpunkte (wäre Epic-1-Vertragsänderung — nicht Teil dieser Story).
|
||||||
|
|
||||||
|
**Never:**
|
||||||
|
- Kein Umschreiben bestehender §5.11/§5.12/§5.13/§5.17-Wortlaute; keine Wanduhr-TTL; keine stille Löschung fremder uncommitteter/geschützter Änderungen (AD-17e); keine Wissensmutation bei Orphan/Hold (AD-16-Default); kein textueller Auto-Merge (AD-17c); keine neue eigene LLM-Runtime/Workflow-Engine (AD-11, D-3); kein Standalone; keine Validator-Erweiterung ohne Autorisierung.
|
||||||
|
|
||||||
|
## I/O & Edge-Case Matrix
|
||||||
|
|
||||||
|
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|
||||||
|
|----------|--------------|---------------------------|----------------|
|
||||||
|
| LIVENESS_AKTIV | lebende Lease mit höherer Generation sichtbar | Lease bleibt aktiv; keine Stale-werdung allein durch Generationshöhe (AC-1) | kein Release, keine Fremd-Übernahme |
|
||||||
|
| STALE_UEBERNAHME | nachweislich stale Lease (bestätigter Abbruch / abgelaufene Liveness) | Übernahme gelingt genau einmal; ersetzte Holder-ID benannt; genau eine aktive Root-Lease (AC-2) | Ownership-Prüfung vor Übernahme; kein Doppel-Übernehmer |
|
||||||
|
| DIRTY_GETRACKT | fremde getrackte Änderung im Mutationsbereich | Abort-/Protect-Zustandsmaschine: schützen (Scratch/Stash), Restore byte-identisch nach Run (AC-3) | UNCOMMITTED_INPUT-Abbruch abgestimmt §5.11 Pkt. 3; nie gelöscht |
|
||||||
|
| DIRTY_UNGETRACKT | fremde ungetrackte Datei im Mutationsbereich | Protect: sichern + Restore; keine stillen Löschungen (AC-3) | nie gelöscht; log.md-Eintrag |
|
||||||
|
| ROLLBACK_NACH_MUTATION | Fehler nach Mutation/Staging | Rollback aus `<Baseline-Commit>`: Index **+** Worktree restauriert; Post-Rollback-Diff leer (AC-4) | Kill-Punkt nach Mutation: konsistenter Endzustand |
|
||||||
|
| ROLLBACK_NACH_COMMIT_VOR_RELEASE | Fehler nach Commit, vor Release | Kill-Punkt vor Commit/vor Release: Zustand == Baseline oder valide committet; kein Teilzustand veröffentlicht (AC-4) | Commit-Boundary = Mutation-Boundary (AD-17f) |
|
||||||
|
| RELEASE_DURABLE | erfolgreicher Run | Mutation + zulässiger Log-/Koordinationsnachweis committet; Lock per Ref-Delete entfernt; Worktree sauber; Folge-Run besteht Clean-Input-Guard (AC-5) | Release-Fehler = HARD-FAIL; Lock nie hängend |
|
||||||
|
| KANONISCHES_LOG | Run-Historie schreiben | `wiki/log.md` nur vertragskonforme fachliche Änderungen + notwendige Koordinationsereignisse; Build-/Review-/Story-/Sandbox-Historie außerhalb (AC-6) | Verstoß = textuell benannt (NFR-4) |
|
||||||
|
| KILLPUNKT_VOR_MUTATION | vor erster Mutation | Zustand == Baseline; keine Zwischenstände (AC-7) | konsistenter Endzustand, Determinismus |
|
||||||
|
| KILLPUNKT_NACH_MUTATION | nach Mutation | Zustand == valider Zwischenstand (geplanter Plan-Freeze); kein Ghost-Diff außerhalb erlaubter Menge (AC-7) | §5.9-Pkt.-5-Ghost-Diff-Rollback |
|
||||||
|
| KILLPUNKT_VOR_COMMIT | nach Staging, vor Commit | nur erlaubte Pfad-Menge staged; kein Teilzustand committet (AC-7) | Commit-Boundary = Mutation-Boundary |
|
||||||
|
| KILLPUNKT_NACH_COMMIT | nach Commit | Bundle == valide committeter Zustand; anschließbar an Clean-Input-Guard (AC-7) | kein hängender Lock, sauberer Worktree |
|
||||||
|
|
||||||
|
## Code Map
|
||||||
|
|
||||||
|
- `schema/compiler.md` — **primär mutiert** (D-3): neue Sektion **§5.18 „Lease-Lifecycle & transaktionaler Commit-Abschluss (Story 3.12)"** (nach §5.17 Z. 415–424, vor §6 Z. 426; Pkt. 1–7); **§7-Bullet-Erweiterung** (Story-3.12-Verankerung analog §5.17-/§5.15-Ergänzung bei Z. 471ff); **§8-Revisionslog Revision 3.7** (Z. 486ff, nach Z. 527). Bestehende §5.11 (Z. 304–321)/§5.12 (Z. 323–342)/§5.13 (Z. 344–363)/§5.17 (Z. 415–424) bleiben **textuell unverändert** (Fugen-Identität; §5.17-Pkt.-1-Z. 419 „Lifecycle-Regie Story 3.12" und Pkt.-6-Z. 424 „bleibt Story 3.12" sind die Anschluss-Sutur).
|
||||||
|
- `_bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` — **neu** (re-executierbar, Muster `sandbox-3-11/run-sandbox.sh` 544 Z., Exit 0): Lifecycle-Szenarien L-1..L-9 (Matrix-Zeilen als harte Assertionen); übernimmt die 3-11-Bausteine (`isolate()` Z. 99–109, `scopelock_acquire()` Z. 124–131, `scopelock_release()` Z. 132–141 mit Ownership-Prüfung, `scopelock_content()` Z. 142–148, `assert_frontmatter()` Z. 164–173, `runlabel`/`pass`/`fail` Z. 98/179–180) und ergänzt: **Abort-/Protect-Zustandsmaschine** (aus sandbox-3-5-L4-Inline Z. 379–434: `db_check` Z. 223–234, Stash/Scratch Z. 416–421, Restore Z. 422–425), **Registry/Gen/Liveness** (aus sandbox-3-6: `reg_gen` Z. 219–224, `lease_stale` Z. 277–283, `reg_write`/`reg_bump` Z. 233–256, `reg_stale_mark` Z. 257–264, `free_lease` Z. 338–343), **Baseline-Rollback Index+Worktree** (via §5.13-Pkt.-3 Z. 359 „Post-Rollback-Diff gg. Baseline leer"), **Kill-Point-Tests** (4 Konsistenz-Assertions), **Clean-Input-Guard** (Worktree-Sauberkeitsprüfung nach Release). Kein Zugriff auf reales Bundle/`raw/`.
|
||||||
|
- `_bmad-output/implementation-artifacts/sandbox-3-11/run-sandbox.sh` — **read-only Vorbild** (Ableitungs-Pflicht: `scopelock_release`-Ownership, `isolate`-Ref-Reset, A-8-Relase-erneut Z. 501–523; Defer „scopelock_header_banner" Z. 166/175 → Home 3.12).
|
||||||
|
- `_bmad-output/implementation-artifacts/sandbox-3-5/run-sandbox.sh` — **read-only Quelle** der Dirty-Tree-Mechanik (L4 Z. 379–434: `db_check` Z. 223–234, UNCOMMITTED_INPUT-Abbruch Z. 395–415, Stash/Scratch Z. 416–421, Restore Z. 422–425, NIE-gelöscht Z. 426–428).
|
||||||
|
- `_bmad-output/implementation-artifacts/sandbox-3-6/run-sandbox.sh` — **read-only Quelle** der Registry/Stale-/Recovery-Mechanik (Registry Z. 216–245, Gen Z. 219–224/246–256, `lease_stale` Z. 277–283, Stale-Mark/Übernahme Z. 257–264/346–478, `raw/`-Recovery STALE-4 Z. 451–478, `assert_no_wallclock` Z. 294–300).
|
||||||
|
- `_bmad-output/implementation-artifacts/sprint-status.yaml` — **mutiert**: Key `3-12-lease-lifecycle-und-commit-abschluss-transaktional-schliessen` `backlog` → `review` (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach konvergiertem Review-Loop); `last_updated` (Format `MM-DD-YYYY HH:MM`).
|
||||||
|
- `wiki/log.md` — **append** (Vertrag §5): Story-3.12-Eintrag (Verankerung §5.18, Sandbox L-1..L-9, Status-Flip, Validator-Verdikt) — **nur** vertragskonforme fachliche + Koordinationsereignisse (AC-6).
|
||||||
|
- `_bmad-output/implementation-artifacts/deferred-work.md` — **append**: Story-3.12-relevante Defers aus Review-Loop-1-Story-3.11 als aufgegriffen markieren („Sandbox-3.5/-3.6-check-then-act-Abgleich", „Banner-/I-O-Matrix-Kosmetik", „scopelock_header_banner"-Platzhalter) bzw. benannte Home-Zuordnung.
|
||||||
|
- `_bmad-output/implementation-artifacts/epic-3-context.md` — **mutiert** („Edit freely"): Technical Decision Z. 43 „Transaktionaler Lifecycle" von „Zielzustand… nicht verankert" auf Ist-Zustand (§5.18) aktualisieren.
|
||||||
|
|
||||||
|
**Read-only evidence (AD-3):** `schema/validator.md` (Rev 9 — prüft **keine** Lease-/Koordinationszustände, Z. 194/195 nur `stale_after`-Lebenszyklus-WARN; Validator-Erweiterung nicht Teil dieser Story), `schema/wiki-compiler.md`, `adapters/`, `raw/` (z. B. `raw/prd/…`, `raw/epics/…`). `schema/canonical-terms.md` append-only unangetastet.
|
||||||
|
|
||||||
|
## Tasks & Acceptance
|
||||||
|
|
||||||
|
**Execution:**
|
||||||
|
- [x] `schema/compiler.md` — §5.18 einfügen (nach §5.17, vor §6): Pkt. 1–7 gemäß Intent; §7-Bullet und §8-Revisionslog **Revision 3.7** nachführen; bestehende §5.11/§5.12/§5.13/§5.17 textuell unverändert (Fugen-Identität)
|
||||||
|
- [x] `_bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` — L-1..L-9 (Lifecycle, Abort-/Protect-Zustandsmaschine, Baseline-Rollback Index+Worktree, Kill-Point-Tests, Clean-Input-Guard), harte PASS/FAIL, Exit 0, `/tmp`-Baum, nie realer Ist-Baum
|
||||||
|
- [x] `_bmad-output/implementation-artifacts/sprint-status.yaml` — Key 3-12 → `review` (Impl-Commit; finaler `done`-Flip Step-05); `last_updated` aktualisieren
|
||||||
|
- [x] `wiki/log.md` — Story-3.12-Eintrag (Verankerung, Sandbox, Status-Flip, Validator-Verdikt) — nur vertragskonforme Inhalte (AC-6)
|
||||||
|
- [x] `_bmad-output/implementation-artifacts/deferred-work.md` — relevante Story-3.12-Home-Defers als aufgegriffen markieren/zuordnen
|
||||||
|
- [x] `_bmad-output/implementation-artifacts/epic-3-context.md` — Technical Decision Z. 43 auf Ist-Zustand (§5.18) aktualisieren
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
- Given einen lebenden Lease-Halter, when eine höhere Generation sichtbar wird, then bleibt seine Lease aktiv; Staleness verlangt bestätigten Abbruch oder abgelaufene Liveness sowie atomare Ownership-Prüfung (AC-1).
|
||||||
|
- Given eine nachweislich stale Lease, when sie übernommen wird, then gelingt die Übernahme genau einmal, nennt die ersetzte Holder-ID und hinterlässt genau eine aktive Root-Lease (AC-2).
|
||||||
|
- Given getrackte oder ungetrackte fremde Änderungen im Mutationsbereich, when der Preflight läuft, then folgt er einer eindeutigen Abort-/Protect-Zustandsmaschine und stellt geschützte Bytes nach dem Run vollständig wieder her (AC-3).
|
||||||
|
- Given einen Fehler nach Mutation oder Staging, when Rollback läuft, then restauriert er explizit aus dem bezeichneten Baseline-Commit sowohl Index als auch Worktree; der Post-Rollback-Diff gegen die Baseline ist leer (AC-4).
|
||||||
|
- Given einen erfolgreichen Run, when er freigegeben wird, then sind Mutation, zulässiger Log-/Koordinationsnachweis und Release dauerhaft, der aktive Lock ist entfernt, der Worktree ist sauber und der unmittelbar folgende Run besteht den Clean-Input-Guard (AC-5).
|
||||||
|
- Given `wiki/log.md`, when ein Run protokolliert wird, then enthält das kanonische Knowledge Log nur vertragskonforme fachliche Änderungen und notwendige Koordinationsereignisse; Build-, Review-, Story- und Sandbox-Historie liegt außerhalb des Knowledge Bundle (AC-6).
|
||||||
|
- Given ein Lifecycle, when Kill-Point-Tests vor Mutation, nach Mutation, vor Commit und nach Commit laufen, then beweisen sie den jeweils konsistenten Endzustand (AC-7).
|
||||||
|
|
||||||
|
## Spec Change Log
|
||||||
|
|
||||||
|
## Design Notes
|
||||||
|
|
||||||
|
Der Lifecycle ist der **geschlossene transaktionale Rahmen** der Koordinations-Dimension: Akquise (§5.11/§5.17) → Preflight/Protect (§5.11 Pkt. 3) → Mutation (§5.9/§5.10/§5.16) → Rollback (§5.13) → durable Release (§5.11 Pkt. 1/§5.17 Pkt. 1 Ref-Delete) → Clean-Input-Guard (Nachfolger-Bedingung). §5.18 ordnet die bestehenden Mechaniken in eine Zustandsmaschine und ergänzt nur die fehlenden Klammern (Liveness/Ownership, Abort-/Protect-Zustandsmaschine, Index+Worktree-Rollback, durable Release + Clean-Input-Guard, kanonisches Log, Kill-Point-Tests).
|
||||||
|
|
||||||
|
**Kernprinzipien:**
|
||||||
|
- **Keine Wanduhr-TTL:** Staleness folgt nie aus Kalenderzeit (A0-20), sondern aus committeten Zuständen (Gen-Registry, §5.12) **plus** bestätigtem Abbruch / abgelaufener Liveness (deterministisch belegt, z. B. Halter-Branch-Verlust/Registry-Status) — Liveness ist ein beobachtbarer, kein zeitlicher Zustand.
|
||||||
|
- **Ownership-Prägung:** Akquise (create-only-Existenz, §5.17), Übernahme (atomare Ownership-Prüfung: Inhaber-Run-ID muss Lock-Inhalt tragen) und Release (Ref-Delete nur durch Inhaber) sind einheitlich ownership-gebunden.
|
||||||
|
- **Rollback = Baseline-Punkt:** Index **+** Worktree werden aus `<Baseline-Commit>` restauriert (`git reset --hard <Baseline-Commit>` ist zulässiges Beispiel — deterministisch, ohne Wanduhr); Post-Rollback-Diff leer (§5.13 Pkt. 3 Zustands-Restaurations-Invariante).
|
||||||
|
- **Clean-Input-Guard:** Nach Release muss ein Folge-Run ohne `INPUT_UNCOMMITTED`-Abbruch starten — d. h. sauberer Worktree, kein hängender Lock, geschützte Fremd-Bytes sind restauriert. Kill-Punkt „nach Commit" antizipiert genau diesen Zustand.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
**Commands:**
|
||||||
|
- `bash _bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` -- expected: L-1..L-9 harte PASS, Exit 0, kein Zugriff auf reales Bundle/`raw/`.
|
||||||
|
- `grep -n "## 5.18" schema/compiler.md` und `grep -n "Revision 3.7" schema/compiler.md` -- expected: §5.18-Überschrift und §8-Revisionslogeintrag vorhanden; bestehende §5.11/§5.12/§5.13/§5.17-Texte unverändert (diff prüft nur additive/berichtigte Zeilen).
|
||||||
|
- `git diff --stat` (Repo-Root) -- expected: nur Story-3.12-Touched-Files (compiler.md, sandbox-3-12, spec, log.md, sprint-status.yaml, deferred-work.md, epic-3-context.md); `schema/validator.md`/`schema/wiki-compiler.md`/`adapters/`/`raw/` ohne Diff (AD-3); `git status --porcelain -- wiki/` zeigt nur `wiki/log.md`.
|
||||||
|
|
||||||
|
**Manual checks (if no CLI):**
|
||||||
|
- Keine Beschreibung nötig — sämtliche Nachweise laufen über die Sandbox (Exit-Code) und additive Diffs.
|
||||||
|
|
||||||
|
## Suggested Review Order
|
||||||
|
|
||||||
|
**Design-Intent (normative Instruktion)**
|
||||||
|
|
||||||
|
- Einstieg: die §5.18-Lifecycle-Sektion — Liveness/Ownership, Abort-/Protect-Zustandsmaschine, Baseline-Rollback Index+Worktree, durable Release + Clean-Input-Guard, kanonisches Log, Kill-Point-Tests (AC-1..7).
|
||||||
|
- Abgrenzungsklausel — Fugen-Identität §5.11/§5.12/§5.13/§5.17; Anschluss-Sutur §5.17-Pkt.-1-Z. 419 / Pkt.-6-Z. 424 („Lifecycle-Regie Story 3.12").
|
||||||
|
|
||||||
|
**Lifecycle-Mechanik (Sandbox)**
|
||||||
|
|
||||||
|
- Abort-/Protect-Zustandsmaschine (getrackt/ungetrackt; byte-identischer Restore) — abgeleitet aus sandbox-3-5-L4, gehärtet als Zustandsmaschine.
|
||||||
|
- Baseline-Rollback Index+Worktree + Kill-Point-Tests (vor Mutation/nach Mutation/vor Commit/nach Commit; Post-Rollback-Diff leer).
|
||||||
|
- Liveness/Ownership + stale-Übernahme genau einmal (Gen-Registry §5.12-Mechanik; ersetzte Holder-ID; genau eine aktive Root-Lease).
|
||||||
|
- Durable Release + Clean-Input-Guard (Lock per Ref-Delete; Worktree sauber; Folge-Run ohne INPUT_UNCOMMITTED-Abbruch).
|
||||||
|
|
||||||
|
**Status- & Nachweissynchronisation (peripher)**
|
||||||
|
|
||||||
|
- Revisionsnachweis Story 3.12 in der Laufzeitakte (Verankerung, Sandbox, Abschlussklausel, Erhaltungs-Invariante).
|
||||||
|
- epic-3-context Z. 43 auf Ist-Zustand nachgeführt; Defer-Homes Story-3.12 in deferred-work.md markiert.
|
||||||
|
|
||||||
|
### Review Findings
|
||||||
|
|
||||||
|
_Bmad-code-review Loop 1 (2026-08-21), 4 Layer (blind-hunter/edge-case-hunter/verification-gap/acceptance-auditor). Triage: **noch offen** — Findings werden nach dem Loop im Spec-Change-Log festgehalten._
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
|
# - 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
|
# - Retrospective appends its action items to action_items; the status view surfaces open ones
|
||||||
generated: 08-14-2026 00:00
|
generated: 08-14-2026 00:00
|
||||||
last_updated: 08-21-2026 15:10
|
last_updated: 08-21-2026 20:45
|
||||||
project: wow20
|
project: wow20
|
||||||
project_key: NOKEY
|
project_key: NOKEY
|
||||||
tracking_system: file-system
|
tracking_system: file-system
|
||||||
@@ -62,7 +62,7 @@ development_status:
|
|||||||
3-9-deterministische-relevanz-und-reconcile-routing-schliessen: done # Review-Loop-3-Abschluss 2026-08-21 (bmad-code-review, 4 Layer; D-3.9-1/2/3 = 1/1/2 — empfohlene Optionen; kein Loopback). Hinweis: der finale `done`-Flip ist der Step-05-Status-Sync nach konvergiertem Review-Loop (Präzedenz Story 3.7/3.8); die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
3-9-deterministische-relevanz-und-reconcile-routing-schliessen: done # Review-Loop-3-Abschluss 2026-08-21 (bmad-code-review, 4 Layer; D-3.9-1/2/3 = 1/1/2 — empfohlene Optionen; kein Loopback). Hinweis: der finale `done`-Flip ist der Step-05-Status-Sync nach konvergiertem Review-Loop (Präzedenz Story 3.7/3.8); die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
||||||
3-10-inkrementelle-update-und-synthese-erhaltung-absichern: done # Story 3.10 Abschluss 2026-08-21 (bmad-code-review, 3 Layer; Patch-Kaskade, keine intent_gap/bad_spec — Sandbox E-1..E-9 nach Härtung 9/9 harte PASS/Exit 0, §5.16 Rev 3.5). Hinweis: die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
3-10-inkrementelle-update-und-synthese-erhaltung-absichern: done # Story 3.10 Abschluss 2026-08-21 (bmad-code-review, 3 Layer; Patch-Kaskade, keine intent_gap/bad_spec — Sandbox E-1..E-9 nach Härtung 9/9 harte PASS/Exit 0, §5.16 Rev 3.5). Hinweis: die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
||||||
3-11-root-scope-leasing-atomar-akquirieren: done # Story 3.11 Review-Loop-1-Abschluss 2026-08-21 (bmad-code-review, 4 Layer; D-3.11-1 „Konstruktiv + härten", D-3.11-2 „Intentionalen Mutationsversuch bauen"; 20 Patches angewendet — A-2-Sampler wirksam, A-4 Worktree-Beobachtung, A-7 MERGE_OK hart abgewiesen + Post-Merge-State + Baseline im Hold-Eintrag, §5.17 Pkt. 1/4/5-Berichtigungen; Sandbox A-1..A-8 8/8 harte PASS/Exit 0 re-executiert). Hinweis: der finale `done`-Flip ist der Step-05-Status-Sync nach konvergiertem Review-Loop (Präzedenz Story 3.7/3.8/3.9); die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
3-11-root-scope-leasing-atomar-akquirieren: done # Story 3.11 Review-Loop-1-Abschluss 2026-08-21 (bmad-code-review, 4 Layer; D-3.11-1 „Konstruktiv + härten", D-3.11-2 „Intentionalen Mutationsversuch bauen"; 20 Patches angewendet — A-2-Sampler wirksam, A-4 Worktree-Beobachtung, A-7 MERGE_OK hart abgewiesen + Post-Merge-State + Baseline im Hold-Eintrag, §5.17 Pkt. 1/4/5-Berichtigungen; Sandbox A-1..A-8 8/8 harte PASS/Exit 0 re-executiert). Hinweis: der finale `done`-Flip ist der Step-05-Status-Sync nach konvergiertem Review-Loop (Präzedenz Story 3.7/3.8/3.9); die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
||||||
3-12-lease-lifecycle-und-commit-abschluss-transaktional-schliessen: backlog
|
3-12-lease-lifecycle-und-commit-abschluss-transaktional-schliessen: review # Story 3.12 Implementierung 2026-08-21 (§5.18 Revision 3.7, Sandbox L-1..L-9 9/9 harte PASS/Exit 0). Hinweis: der finale `done`-Flip ist der Step-05-Status-Sync nach konvergiertem Review-Loop (Präzedenz Story 3.7/3.8/3.9/3.10/3.11); die Epic-3-Abnahme (3.13) bleibt offen (epic-3 remains in-progress).
|
||||||
3-13-epic-3-verifikations-und-abnahmegate: backlog
|
3-13-epic-3-verifikations-und-abnahmegate: backlog
|
||||||
epic-3-retrospective: optional
|
epic-3-retrospective: optional
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -423,6 +423,21 @@ Die §5.11-Lease-Akquise (Pkt. 1 — Lockfile `lease/<area>/<id>.lock`, Merge-Ba
|
|||||||
5. **Kollisions-Hold an Epic 4 (AC-e, AD-17c/A0-14):** Zwei Branches mit **ungleichen Änderungen am selben Concept-Pfad** werden **nie textuell automatisch gemerged** (§5.11 Pkt. 4 bleibt textuell unverändert — kein textueller Auto-Merge, AD-17c). Erkennt der Run die Kollision, wird ein **strukturierter Kollisions-Hold mit beiden Commit-Hashes und dem Scope** an Epic 4 übergeben — in die benannte Hold-Mechanik (§5.16 Pkt. 8/§5.10 Pkt. 8): **Ablage-Stelle ist der datumsgruppierte `log.md`-Eintrag** (Header `YYYY-MM-DD`, neueste zuerst — Vertrag §5; Form: Quell-Pfad + `<Baseline-Commit>` + beide Commit-Hashes + Scope, §5.10-Pkt.-8-Form) — **keine Wissensmutation** statt eines automatischen Merges; **AD-16-Klassifikation und semantische Auflösung bleiben Epic 4 / Story 4.x**. Commit-Boundary = Mutations-Boundary (AD-17f, §0/§5.3/§5.11 Pkt. 5 unverändert); `log.md`-Eintragspflicht (Vertrag §5, §5.11 Pkt. 6 unverändert).
|
5. **Kollisions-Hold an Epic 4 (AC-e, AD-17c/A0-14):** Zwei Branches mit **ungleichen Änderungen am selben Concept-Pfad** werden **nie textuell automatisch gemerged** (§5.11 Pkt. 4 bleibt textuell unverändert — kein textueller Auto-Merge, AD-17c). Erkennt der Run die Kollision, wird ein **strukturierter Kollisions-Hold mit beiden Commit-Hashes und dem Scope** an Epic 4 übergeben — in die benannte Hold-Mechanik (§5.16 Pkt. 8/§5.10 Pkt. 8): **Ablage-Stelle ist der datumsgruppierte `log.md`-Eintrag** (Header `YYYY-MM-DD`, neueste zuerst — Vertrag §5; Form: Quell-Pfad + `<Baseline-Commit>` + beide Commit-Hashes + Scope, §5.10-Pkt.-8-Form) — **keine Wissensmutation** statt eines automatischen Merges; **AD-16-Klassifikation und semantische Auflösung bleiben Epic 4 / Story 4.x**. Commit-Boundary = Mutations-Boundary (AD-17f, §0/§5.3/§5.11 Pkt. 5 unverändert); `log.md`-Eintragspflicht (Vertrag §5, §5.11 Pkt. 6 unverändert).
|
||||||
6. **Abgrenzung (keine neue Dimension):** Keine Wanduhr-/Systemzeit in der Akquise (A0-20); keine Staleness-/TTL-/Recovery-Logik (bleibt §5.12/Story 3.6 und Story 3.12); keine Verwaist-/Stale-Behandlung und kein Lease-Branch-Lifecycle nach Übernahme (bleibt Story 3.12) — diese Sektion präzisiert ausschließlich die **Akquise-Atomarität** des Root-Scope im clone-geteilten Zustand; die §5.11-Pkt.-1-Formen (Branch, Lockfile, Merge-Base, Freigabe) und die §5.12-Dimension bleiben unverändert maßgeblich.
|
6. **Abgrenzung (keine neue Dimension):** Keine Wanduhr-/Systemzeit in der Akquise (A0-20); keine Staleness-/TTL-/Recovery-Logik (bleibt §5.12/Story 3.6 und Story 3.12); keine Verwaist-/Stale-Behandlung und kein Lease-Branch-Lifecycle nach Übernahme (bleibt Story 3.12) — diese Sektion präzisiert ausschließlich die **Akquise-Atomarität** des Root-Scope im clone-geteilten Zustand; die §5.11-Pkt.-1-Formen (Branch, Lockfile, Merge-Base, Freigabe) und die §5.12-Dimension bleiben unverändert maßgeblich.
|
||||||
|
|
||||||
|
## 5.18 Lease-Lifecycle & transaktionaler Commit-Abschluss (Story 3.12)
|
||||||
|
|
||||||
|
Die Koordinations-Dimension ist über §5.11 (Leasing/Dirty-Tree, Story 3.5), §5.12 (Staleness/Recovery, Story 3.6), §5.13 (Phasen-Trennung, Story 3.7) und §5.17 (atomare Root-Scope-Lease-Akquise, Story 3.11) verankert — diese Sektion ist die **geschlossene, transaktionale Lifecycle-Klammer** darüber (D-3, Story 3.12; AC-1..AC-7; A0-20 — keine Wanduhr-/Systemzeit-Steuerung, Lifecycle deterministisch aus dem committeten Git-State, AD-17h/A0-19): sie ordnet Akquise (§5.11/§5.17), Preflight/Protect (§5.11 Pkt. 3), Mutation (§5.9/§5.10/§5.16), Rollback (§5.13) und durable Release (§5.11 Pkt. 1/§5.17 Pkt. 1) in eine **eindeutige Zustandsmaschine**, so dass SUCCESS und FAIL je einen sauberen, wiederanlaufbaren Zustand hinterlassen. **Fugen-Identität:** §5.11 (Pkt. 1–7), §5.12 (Pkt. 1–7), §5.13 und §5.17 bleiben **textuell unverändert** — die Lifecycle-Regie ist die von §5.17 Pkt. 1/6 benannte Fortsetzung („Lifecycle-Regie Story 3.12"). Sie fügt **kein** Prädikat, **keine** neue §7-Invaliditätsklasse, **keinen** `schema/wiki-compiler.md`-/`schema/validator.md`-/`adapters/`-/`raw/`-Change (AD-3), **keinen** neuen Frontmatter-/Format-Key (Vertrag §3.1–§3.7 unverändert), **keinen** Standalone (D-3) und **keine** Wanduhr-/Systemzeit hinzu (A0-20).
|
||||||
|
|
||||||
|
1. **Liveness & Ownership — Staleness verlangt bestätigten Abbruch/abgelaufene Liveness plus atomare Ownership-Prüfung (AC-1):** Eine lebende Lease wird durch eine **höhere sichtbare Generation allein nicht stale** — Staleness folgt nie aus Kalenderzeit (A0-20: keine Time-To-Live über Wanduhr) und nie allein aus der Gen-Registry (§5.12), sondern aus **committeten Zuständen plus bestätigtem Abbruch oder abgelaufener Liveness**: die Lease gilt als stale (i) wenn der Halter seine Liveness **bestätigt abgebrochen** hat (deterministisch belegt aus dem committeten Git-State, z. B. Halter-Branch-Verlust, abgebrochener Run ohne durable Release, Registry-Status) oder (ii) wenn die **Liveness abgelaufen** ist — ein beobachtbarer Zustand, der aus den committeten Registrierungs-/Markierungs-Zuständen ableitbar ist (§5.12 Gen-/Stale-Marker), nicht aus einem Zeitstempel. **Keine Fremd-Staleness ohne Ownership-Prüfung:** die Stale-Bewertung selbst ist eine **atomare Ownership-Prüfung** — sie verifiziert gegen den geltenden Halter-Zustand (Lock-Inhalt/Inhaber-Run-ID, §5.17 Pkt. 1) und den Registry-Status, bevor irgendeine Übernahme-/Freigabe-Entscheidung greift. Eine höhere Generation führt nur dann zu einer Stale-Klassifikation, wenn zugleich der bestätigte Abbruch/die abgelaufene Liveness vorliegt (Verwaist-Klassifikation, §5.12 Pkt. 3 — Determinismus aus dem committeten Zustand, AD-17h/A0-19).
|
||||||
|
2. **Stale-Übernahme genau einmal — benannte ersetzte Holder-ID, genau eine aktive Root-Lease (AC-2):** Ist eine Lease nachweislich stale (Pkt. 1), übernimmt ein neuer Producer den Root-Scope **genau einmal** — nie zwei Übernehmer, nie zwei aktive Root-Leases (AK-2: die Übernahme ist ownership-gebunden: nur wer den Root-Scope-Lock (§5.17 Pkt. 1) nach der atomaren Ownership-Prüfung erwirbt, wird neuer Inhaber; die Ersetzung erfolgt als **Ref-Schreibvorgang auf den scope-bezogenen Lock** mit neuem Lock-Inhalt — die **ersetzte Holder-ID wird im datumsgruppierten `log.md`-Eintrag benannt** (Vertrag §5; Form: Quell-/Scope-Pfad + `<Baseline-Commit>` + alte Holder-ID + neue Holder-ID), so dass die Übernahme vollständig nachvollziehbar ist und **genau eine** aktive Root-Lease bestehen bleibt (Kardinalität 1, §5.17 Pkt. 2). Die verwaiste Lease wird **nie still gelöscht** (AD-17e): die Registry-Zeile und der per-Lease-Lockfile-/Branch-Ablage-Zustand (§5.11 Pkt. 1) bleiben als Verwaist-/Stale-Nachweis erhalten (§5.12 Pkt. 3/6).
|
||||||
|
3. **Eindeutige Abort-/Protect-Zustandsmaschine für fremde getrackte/ungetrackte Änderungen (AC-3):** Vor jeder Mutation läuft der Preflight (§5.11 Pkt. 3 — Pre-Mutation-Prüfung `git status --porcelain -- <Mutationsbereich>`; `UNCOMMITTED_INPUT`-Abbruch „published/committed Input erforderlich" bleibt §5.11 Pkt. 3-/§5.9-P2-Element-(1)-gebunden, kein zweiter Abbruch-Pfad) und versetzt den Run in eine **eindeutige Abort-/Protect-Zustandsmaschine** für **fremde** (nicht dem Run gehörende, producer-fremde) uncommittete Änderungen im Mutationsbereich:
|
||||||
|
- **getrackte fremde Änderung** (modifizierte committete Datei): **Schützen** — Sicherung in die **Scratch-Zone `scratch/<run-id>/`** (außerhalb `wiki/`, deterministisch benannt) oder via **`git stash push -- <Pfad>`** (§5.12 Pkt. 5 zulässige native Variante); der Arbeitssatz wird für den Run bereinigt; **Restore nach Run-Ende byte-identisch** aus der Sicherung (SHA-256-/Byte-Identitäts-Prüfung in beide Richtungen) — nie gelöscht (AD-17e). Abort-Pfad: greift die Schutz-Sicherung nicht (z. B. Sicherung nicht byte-identisch restaurierbar), **HALT des Runs** mit textuell benannter Ursache (NFR-4) und Zustands-Restaurations-Invariante (§5.13 Pkt. 3).
|
||||||
|
- **ungetrackte fremde Datei** im Mutationsbereich: **Protect** — die Datei wird in die Scratch-Zone gesichert (bzw. via `git stash push -u` eingeschlossen) und nach dem Run **byte-identisch restauriert**; **keine stille Löschung** (AD-17e); der Schutz wird im `log.md`-Eintrag dokumentiert (Vertrag §5, §5.11 Pkt. 3 „Dirty-Tree-Schutz-Dokumentation").
|
||||||
|
- **Nicht betroffene Bereiche/Dateien unverändert:** nur die benannten fremden Dateien werden geschützt/restauriert — kein Eingriff darüber hinaus (Erhaltungs-Invariante §5.9 Pkt. 5). Diese Zustandsmaschine ersetzt den Inline-Ablauf der Story-3.5-Sandbox (L4) durch eine eindeutige, je Zustand definierte Überführung (UNCOMMITTED_INPUT → SCHUETZEN → MUTIEREN → RESTORIEREN).
|
||||||
|
4. **Baseline-Rollback — Index + Worktree aus `<Baseline-Commit>`, Post-Rollback-Diff leer (AC-4):** Tritt ein Fehler **nach Mutation oder Staging** auf (I/O-Matrix `ROLLBACK_NACH_MUTATION`, Kill-Punkt nach Mutation), rollt der Run aus dem **bezeichneten Baseline-Commit `<Baseline-Commit>`** zurück — **Index und Worktree** werden explizit restauriert: `git reset --hard <Baseline-Commit>` stellt beide wieder her (deterministisch, ohne Wanduhr — zulässige Realisierung; die §5.3-/§6-Pkt.-3-Mechanik nennt nur Bundle-/`git checkout`-Wiederherstellung, hier wird der Index **explizit** mitgeführt). **Post-Rollback-Diff gg. Baseline leer:** nach dem Rollback ist der Diff gegen `<Baseline-Commit>` leer (Zustands-Restaurations-Invariante, §5.13 Pkt. 3). **Kill-Punkt nach Mutation/Staging** (Pkt. 7): auch an diesem Kill-Punkt endet der Run in einem konsistenten Zustand — entweder Zustand == Baseline (Rollback) oder valide committet, nie ein Teilzustand (Commit-Boundary = Mutations-Boundary, AD-17f unverändert).
|
||||||
|
5. **Durable Release (AC-5):** Erst nach dem durativen Abschluss ist die Lease frei: (1) die **Mutation** ist committet (Bundle == valide committeter Zustand, Commit-Boundary = Mutations-Boundary, AD-17f unverändert), (2) der **zulässige Log-/Koordinationsnachweis** (Vertrag-§5-/§5.11-Pkt.-6-Einträge: Lease-Akquise, Dirty-Tree-Schutz, Merge-Klassifikation, Eskalation, Freigabe; `<Baseline-Commit>` notiert) ist committet — `wiki/log.md` ist die einzige Aufzeichnungs-Stelle im Bundle (kumulativer Registry-Aufbau liegt außerhalb, §5.12 Pkt. 6), (3) der **aktive scope-bezogene Lock wird per Ref-Delete entfernt** (`git update-ref -d <lock-ref>`) — **nur durch den Inhaber** (Ownership: der Lock-Inhalt muss die Run-ID des freigebenden Producers tragen, §5.17 Pkt. 1/3 — „entfernt keine fremde Lease"), (4) der **Worktree ist sauber** (geschützte Fremd-Bytes restauriert, keine uncommitteten Reste, kein hängender Lock). **Clean-Input-Guard (Nachfolger-Bedingung):** der **unmittelbar folgende Run** muss ohne `INPUT_UNCOMMITTED`-Abbruch starten können — d. h. sauberer Worktree, kein hängender Lock, geschützte Fremd-Bytes sind restauriert (Kill-Punkt „nach Commit" antizipiert genau diesen Zustand, Pkt. 7). **Release-Fehler (Ref-Delete scheitert, Lock bleibt hängen, Worktree verschmutzt) = HARD-FAIL:** der Run endet nicht durativ; der Zustand wird textuell benannt (NFR-4) und bis zur Zustands-Restaurations-Invariante (§5.13 Pkt. 3) korrigiert — der Lock hängt nie.
|
||||||
|
6. **Kanonisches Log (AC-6):** Das kanonische Knowledge Log `wiki/log.md` enthält **nur vertragskonforme fachliche Änderungen und die notwendigen Koordinationsereignisse** (Vertrag §5; §5.11 Pkt. 6; §5.12 Pkt. 7): Lease-Akquise, Dirty-Tree-Schutz-/Preflight-Dokumentation, Stale-/Liveness-/Übernahme-/Freigabe-Ereignisse, Merge-/Eskalations-/Hold-Klassifikationen, fachliche Update-/Synthese-/Neu-Anlage-Einträge. **Build-, Review-, Story- und Sandbox-Historie liegen außerhalb des Knowledge Bundle** (Run-Receipts außerhalb des Bundles, §5.14 Pkt. 2; Sandbox-Nachweise in `_bmad-output/...`; Sprint-/Status-Akten außerhalb `wiki/`). Ein Verstoß gegen die kanonische Grenze wird **textuell benannt** (NFR-4) und vor dem Commit korrigiert.
|
||||||
|
7. **Kill-Point-Tests (AC-7):** Der Lifecycle wird an **vier Kill-Punkten** auf konsistente Endzustände geprüft (je Kill-Punkt deterministisch, AD-17h/A0-19, Zustands-Restaurations-Invariante §5.13 Pkt. 3): (a) **vor Mutation** — Zustand == Baseline, keine Zwischenstände, kein Ghost-Diff (Probe §5.9 Pkt. 5), (b) **nach Mutation** — Zustand == valider Zwischenstand (geplanter Plan-Freeze, §5.13 Pkt. 2), kein Ghost-Diff außerhalb der erlaubten Pfad-Menge (Kandidatenliste ∪ Neu-Anlage ∪ `log.md` ∪ nachgeführte `index.md`), (c) **vor Commit** — nur die erlaubte Pfad-Menge ist staged, kein Teilzustand veröffentlicht (Commit-Boundary = Mutations-Boundary, AD-17f unverändert), (d) **nach Commit** — Bundle == valide committeter Zustand, anschließbar an den Clean-Input-Guard (Pkt. 5: kein hängender Lock, sauberer Worktree, geschützte Fremd-Bytes restauriert). Jeder Kill-Punkt beweist damit den **jeweils konsistenten Endzustand** — nie einen Teilzustand als fertige Mutation (§5.13 Pkt. 4, AD-17f unverändert).
|
||||||
|
|
||||||
## 6. Validieren (mechanische Bestätigung)
|
## 6. Validieren (mechanische Bestätigung)
|
||||||
|
|
||||||
1. Nach Abschluss aller Mutationen wird das gesamte Bundle gemäß `schema/validator.md` geprüft (§3 14 Punkte je Datei + §6-Fachprüfungen; Verdikt-Grammatik §5).
|
1. Nach Abschluss aller Mutationen wird das gesamte Bundle gemäß `schema/validator.md` geprüft (§3 14 Punkte je Datei + §6-Fachprüfungen; Verdikt-Grammatik §5).
|
||||||
@@ -477,7 +492,7 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene und in A
|
|||||||
- **Progressive Discovery über `index.md`** (Navigation, Area-Indizes) — in **§5.8** dieser Instruktion verankert (Story 2.5; AD-9, FR-11, AD-13, NFR-3). **Suche** bleibt konsumenten-/extern-seitig (Consumer-grep über `wiki/`, §5.8 Pkt. 4 — kein Bundle-/Instruktions-Thema mehr). Keine neue §7-Klasse, kein Schema-/Validator-Change.
|
- **Progressive Discovery über `index.md`** (Navigation, Area-Indizes) — in **§5.8** dieser Instruktion verankert (Story 2.5; AD-9, FR-11, AD-13, NFR-3). **Suche** bleibt konsumenten-/extern-seitig (Consumer-grep über `wiki/`, §5.8 Pkt. 4 — kein Bundle-/Instruktions-Thema mehr). Keine neue §7-Klasse, kein Schema-/Validator-Change.
|
||||||
- **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).
|
- **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.
|
- **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/<area>/<id>`-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)**. **Story-3.11-Verankerung:** die atomare Root-Scope-Lease-Akquise ist in **§5.17 dieser Instruktion** verankert (Story 3.11, Atomare Root-Scope-Lease-Akquise): der Exklusivitätsschlüssel ist ein einziger, scope-bezogener Lock im clone-geteilten Zustand (geteilter Git-Ref-/Objektnamespace aller Worktrees und Prozesse eines Clones — `git update-ref <lock-ref> <wert> $ZERO_SHA`, create-only), die Run-ID ist Lock-Inhalt statt Schlüsselbestandteil (AC-a), die Akquise ist atomar mit genau einem Gewinner und `LEASE_HOLD` für den Abgewiesenen (AC-b/c, §5.11-Pkt.-1-Lease-Hold unverändert), Kollisions-Hold mit beiden Commit-Hashes an Epic 4 statt textuellem Auto-Merge (AC-e, AD-17c/A0-14). Keine neue §7-Klasse, kein Schema-/Validator-Change, keine Vertragsänderung; keine Wanduhr/Systemzeit (A0-20), keine Staleness-/Recovery-Logik (bleibt §5.12/Story 3.12); §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker bleiben unverändert (Fugen-Identität).
|
- **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/<area>/<id>`-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)**. **Story-3.11-Verankerung:** die atomare Root-Scope-Lease-Akquise ist in **§5.17 dieser Instruktion** verankert (Story 3.11, Atomare Root-Scope-Lease-Akquise): der Exklusivitätsschlüssel ist ein einziger, scope-bezogener Lock im clone-geteilten Zustand (geteilter Git-Ref-/Objektnamespace aller Worktrees und Prozesse eines Clones — `git update-ref <lock-ref> <wert> $ZERO_SHA`, create-only), die Run-ID ist Lock-Inhalt statt Schlüsselbestandteil (AC-a), die Akquise ist atomar mit genau einem Gewinner und `LEASE_HOLD` für den Abgewiesenen (AC-b/c, §5.11-Pkt.-1-Lease-Hold unverändert), Kollisions-Hold mit beiden Commit-Hashes an Epic 4 statt textuellem Auto-Merge (AC-e, AD-17c/A0-14). Keine neue §7-Klasse, kein Schema-/Validator-Change, keine Vertragsänderung; keine Wanduhr/Systemzeit (A0-20), keine Staleness-/Recovery-Logik (bleibt §5.12/Story 3.12); §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker bleiben unverändert (Fugen-Identität). **Story-3.12-Verankerung:** der geschlossene Lifecycle (Akquise → Preflight/Protect → Mutation → Rollback → durable Release → Clean-Input-Guard) ist in **§5.18 dieser Instruktion** verankert (Story 3.12, Lease-Lifecycle & transaktionaler Commit-Abschluss): Liveness & Ownership — eine höhere Generation allein macht eine lebende Lease nicht stale, Staleness verlangt bestätigten Abbruch/abgelaufene Liveness plus atomare Ownership-Prüfung (AC-1); stale-Übernahme genau einmal mit benannter ersetzter Holder-ID und genau einer aktiven Root-Lease (AC-2); eindeutige Abort-/Protect-Zustandsmaschine für getrackte/ungetrackte fremde Änderungen mit byte-identischem Restore (AC-3); Baseline-Rollback **Index + Worktree** aus `<Baseline-Commit>` mit leerem Post-Rollback-Diff (AC-4); durable Release (Mutation + zulässiger Log-/Koordinationsnachweis committet, Lock per Ref-Delete, Worktree sauber, Folge-Run besteht den Clean-Input-Guard, AC-5); kanonisches Log — `wiki/log.md` nur vertragskonforme fachliche Änderungen + notwendige Koordinationsereignisse (AC-6); Kill-Point-Tests vor Mutation/nach Mutation/vor Commit/nach Commit je konsistenter Endzustand (AC-7). Keine neue §7-Klasse, kein Schema-/Validator-Change, keine Vertragsänderung; keine Wanduhr/Systemzeit (A0-20); §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker bleiben unverändert (Fugen-Identität).
|
||||||
- **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. **Story-3.10-Verankerung:** die Erhaltungs-Absicherung des laufenden, gemischten Runs und der Hold-Ausbau sind in **§5.16 dieser Instruktion** verankert (Story 3.10, Inkrementelle Update- & Synthese-Erhaltung + Hold-Ausbau): Kontinuitäts-Garantie (AC-1), Korrigieren mit Run-Receipt-Trace (AC-2), Schutzbestandteile & Byte-Identität (AC-3), CONFIRMING-Konsolidierung (AC-4 — bestätigende neue Source mit neuem Evidenzanker ist Konsolidierungs-Update, kein NO_OP), gemeinsame Wissensrepräsentation als Synthese-Erhaltung (AC-5), byte-erhaltender NO_OP (AC-6 — nur bei vollständiger Evidenzanker-Menge), Provenienz-/Link-Selbsttest aus aktuellem Run (AC-7 — Baseline = `<Baseline-Commit>`, keine historischen Zählwerte normativ), benannter Hold (AC-8 — post-Reconcile-Orphan über alle Erhebungs-Stufen a/b/c, Mehrziel-Auflösung, beide Evidenzpfade im Run-Receipt; NFR-7). Keine neue §7-Klasse, kein Schema-/Validator-Change, keine Vertragsänderung; AD-16-Klassifikation bleibt Epic 4; die §5.9-Abgrenzungs-Reihenfolge bleibt die einzige Form-Wahl.
|
- **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. **Story-3.10-Verankerung:** die Erhaltungs-Absicherung des laufenden, gemischten Runs und der Hold-Ausbau sind in **§5.16 dieser Instruktion** verankert (Story 3.10, Inkrementelle Update- & Synthese-Erhaltung + Hold-Ausbau): Kontinuitäts-Garantie (AC-1), Korrigieren mit Run-Receipt-Trace (AC-2), Schutzbestandteile & Byte-Identität (AC-3), CONFIRMING-Konsolidierung (AC-4 — bestätigende neue Source mit neuem Evidenzanker ist Konsolidierungs-Update, kein NO_OP), gemeinsame Wissensrepräsentation als Synthese-Erhaltung (AC-5), byte-erhaltender NO_OP (AC-6 — nur bei vollständiger Evidenzanker-Menge), Provenienz-/Link-Selbsttest aus aktuellem Run (AC-7 — Baseline = `<Baseline-Commit>`, keine historischen Zählwerte normativ), benannter Hold (AC-8 — post-Reconcile-Orphan über alle Erhebungs-Stufen a/b/c, Mehrziel-Auflösung, beide Evidenzpfade im Run-Receipt; NFR-7). Keine neue §7-Klasse, kein Schema-/Validator-Change, keine Vertragsänderung; AD-16-Klassifikation bleibt Epic 4; die §5.9-Abgrenzungs-Reihenfolge bleibt die einzige Form-Wahl.
|
||||||
- **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.
|
- **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).
|
- **Standalone-Compiler / eigene LLM-Runtime / MCP** → verboten in v1 (D-3, D-4, AD-11).
|
||||||
@@ -525,3 +540,4 @@ Diese Instruktion ist auf die **Erzeugung neuer Concepts auf Root-Ebene und in A
|
|||||||
- **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`/`R`/`C` via `--diff-filter=ACMR` mit der Akzeptanz-Regel A/C (akzeptiert) vs. M/D/R (Run-FAIL) aus Pkt. 4, §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` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3). **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).
|
- **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`/`R`/`C` via `--diff-filter=ACMR` mit der Akzeptanz-Regel A/C (akzeptiert) vs. M/D/R (Run-FAIL) aus Pkt. 4, §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` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3). **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).
|
||||||
- **Revision 3.5 (2026-08-21, Story 3.10):** Neue Sektion **§5.16 „Inkrementelle Update- & Synthese-Erhaltung + Hold-Ausbau (Story 3.10)"** eingefügt (nach §5.15, vor §6) — die **operationelle Erhaltungs-Klammer** über den textuell unveränderten §5.9/§5.10/§5.15-Mechaniken (D-3, Story 3.10; A0-21-Incrementality-Teil, FR-4/FR-6/FR-12, AD-4/AD-5; §5.15-Zelle-3-/§5.15-Scope-Präzisierung-/§5.10-Pkt.-8-D-4-Hold-Home hierin verankert): (1) **Kontinuitäts-Garantie** (AC-1; in-place Update/Synthese, kein Duplikat, Identität + Index-Link erhalten), (2) **Korrigieren mit Run-Receipt-Trace** (AC-2; ersetzte Wortlautfolge + Source-Basis im Run-Receipt außerhalb des Bundles, §5.14 Pkt. 2; mehrdeutig → benannter Hold Epic 4), (3) **Schutzbestandteile & Byte-Identität** (AC-3; gültige belegte Aussagen, §5.5-Inline-Verweise, `sources` gültiger Belege, §5.6-Links, human-`verified` bleiben erhalten; nicht betroffene Concepts byte-identisch, §5.9 Pkt. 5), (4) **CONFIRMING-Konsolidierung** (AC-4; bestätigende neue Source mit neuem Evidenzanker → Aussage genau einmal, alle Anker via §5.5-Multi-Beleg, `sources`-Zuwachs, `at`-Bump, **kein NO_OP** — Stellen-Abgleich auf den Anker, nicht auf den Inhalt), (5) **gemeinsame Wissensrepräsentation als Synthese-Erhaltung** (AC-5; §5.10-Pkt.-2/3/5, Update auf bestehendes Concept = Erweiterung, keine Neuschreibung), (6) **byte-erhaltender NO_OP** (AC-6; nur bei vollständig identischer Evidenz **samt vollständiger Evidenzanker-Menge** — kein `at`-Bump, kein `sources`-Zusatz, kein `log.md`-Eintrag; fehlender Anker → Pkt. 4), (7) **Provenienz- & Link-Selbsttest aus aktuellem Run** (AC-7; Baseline = `<Baseline-Commit>` des aktuellen Runs, erwartete Delta-Menge = Kandidatenliste ∪ Neu-Anlage ∪ `log.md` ∪ nachgeführte `index.md`; kein historischer Commit/globaler Zählwert normativ), (8) **benannter Hold** (AC-8/NFR-7; post-Reconcile-Orphan über **alle** Erhebungs-Stufen a/b/c — die Story-3.9-Sandbox übte nur Stufe a (§5.15-Pkt.-6-Scope-Präzisierung aufgegriffen) —, Mehrziel-Auflösung via D-8-Mehrfach-Term-Vereinigung auf eine primäre Ziel-Repräsentation, sonst fail-closed Hold; widersprüchliche/klassifikationspflichtige Evidenz ohne Wissensmutation; beide Evidenzpfade im Run-Receipt). **§5.15:** Zelle-3-Zeile und Scope-Präzisierung auf die §5.16-Verankerung nachgeführt („in §5.16 verankert, Story 3.10"). **§5.10 Pkt. 8:** D-4-Bullet um die §5.16-Verankerung des Hold selbst ergänzt (Hold-Ausbau: Stufen a/b/c, Mehrziel, benannter Hold). **§7:** Relevanzbestimmung-Bullet um die **Story-3.10-Verankerung** erweitert (§5.16; bestehende Story-Bullets unverändert). **AD-16-Klassifikation/semantische Auflösung bleibt Epic 4.** **Abschlussklausel (Story 3.10):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **keine fünfte Update-/Routing-Form**; die §5.9-Abgrenzungs-Reihenfolge `Korrigieren → Präzisieren → Erweitern → No-Op` bleibt die **einzige** Form-Wahl (textuell unverändert); **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, Ask-First); Commit-Boundary-Regel unverändert; `generated.at`-Verhalten unverändert (A0-20-Konvention). **`sprint-status.yaml`:** Key `3-10-inkrementelle-update-und-synthese-erhaltung-absichern` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3/3.4). Sandbox-Nachweis (**E-1..E-9, Exit 0**; CONFIRMING ≠ NO_OP byte-bewiesen, NO_OP byte-erhaltend, Korrigieren-Receipt-Trace, aktueller-Run-Selbsttest, Orphan über Stufe-a/b/c, Mehrziel-Konsolidierung/-Hold, Zwei-Run-Identität nicht-vakuum) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.10, Revision 3.5).
|
- **Revision 3.5 (2026-08-21, Story 3.10):** Neue Sektion **§5.16 „Inkrementelle Update- & Synthese-Erhaltung + Hold-Ausbau (Story 3.10)"** eingefügt (nach §5.15, vor §6) — die **operationelle Erhaltungs-Klammer** über den textuell unveränderten §5.9/§5.10/§5.15-Mechaniken (D-3, Story 3.10; A0-21-Incrementality-Teil, FR-4/FR-6/FR-12, AD-4/AD-5; §5.15-Zelle-3-/§5.15-Scope-Präzisierung-/§5.10-Pkt.-8-D-4-Hold-Home hierin verankert): (1) **Kontinuitäts-Garantie** (AC-1; in-place Update/Synthese, kein Duplikat, Identität + Index-Link erhalten), (2) **Korrigieren mit Run-Receipt-Trace** (AC-2; ersetzte Wortlautfolge + Source-Basis im Run-Receipt außerhalb des Bundles, §5.14 Pkt. 2; mehrdeutig → benannter Hold Epic 4), (3) **Schutzbestandteile & Byte-Identität** (AC-3; gültige belegte Aussagen, §5.5-Inline-Verweise, `sources` gültiger Belege, §5.6-Links, human-`verified` bleiben erhalten; nicht betroffene Concepts byte-identisch, §5.9 Pkt. 5), (4) **CONFIRMING-Konsolidierung** (AC-4; bestätigende neue Source mit neuem Evidenzanker → Aussage genau einmal, alle Anker via §5.5-Multi-Beleg, `sources`-Zuwachs, `at`-Bump, **kein NO_OP** — Stellen-Abgleich auf den Anker, nicht auf den Inhalt), (5) **gemeinsame Wissensrepräsentation als Synthese-Erhaltung** (AC-5; §5.10-Pkt.-2/3/5, Update auf bestehendes Concept = Erweiterung, keine Neuschreibung), (6) **byte-erhaltender NO_OP** (AC-6; nur bei vollständig identischer Evidenz **samt vollständiger Evidenzanker-Menge** — kein `at`-Bump, kein `sources`-Zusatz, kein `log.md`-Eintrag; fehlender Anker → Pkt. 4), (7) **Provenienz- & Link-Selbsttest aus aktuellem Run** (AC-7; Baseline = `<Baseline-Commit>` des aktuellen Runs, erwartete Delta-Menge = Kandidatenliste ∪ Neu-Anlage ∪ `log.md` ∪ nachgeführte `index.md`; kein historischer Commit/globaler Zählwert normativ), (8) **benannter Hold** (AC-8/NFR-7; post-Reconcile-Orphan über **alle** Erhebungs-Stufen a/b/c — die Story-3.9-Sandbox übte nur Stufe a (§5.15-Pkt.-6-Scope-Präzisierung aufgegriffen) —, Mehrziel-Auflösung via D-8-Mehrfach-Term-Vereinigung auf eine primäre Ziel-Repräsentation, sonst fail-closed Hold; widersprüchliche/klassifikationspflichtige Evidenz ohne Wissensmutation; beide Evidenzpfade im Run-Receipt). **§5.15:** Zelle-3-Zeile und Scope-Präzisierung auf die §5.16-Verankerung nachgeführt („in §5.16 verankert, Story 3.10"). **§5.10 Pkt. 8:** D-4-Bullet um die §5.16-Verankerung des Hold selbst ergänzt (Hold-Ausbau: Stufen a/b/c, Mehrziel, benannter Hold). **§7:** Relevanzbestimmung-Bullet um die **Story-3.10-Verankerung** erweitert (§5.16; bestehende Story-Bullets unverändert). **AD-16-Klassifikation/semantische Auflösung bleibt Epic 4.** **Abschlussklausel (Story 3.10):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **keine fünfte Update-/Routing-Form**; die §5.9-Abgrenzungs-Reihenfolge `Korrigieren → Präzisieren → Erweitern → No-Op` bleibt die **einzige** Form-Wahl (textuell unverändert); **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, Ask-First); Commit-Boundary-Regel unverändert; `generated.at`-Verhalten unverändert (A0-20-Konvention). **`sprint-status.yaml`:** Key `3-10-inkrementelle-update-und-synthese-erhaltung-absichern` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3/3.4). Sandbox-Nachweis (**E-1..E-9, Exit 0**; CONFIRMING ≠ NO_OP byte-bewiesen, NO_OP byte-erhaltend, Korrigieren-Receipt-Trace, aktueller-Run-Selbsttest, Orphan über Stufe-a/b/c, Mehrziel-Konsolidierung/-Hold, Zwei-Run-Identität nicht-vakuum) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.10, Revision 3.5).
|
||||||
- **Revision 3.6 (2026-08-21, Story 3.11):** Neue Sektion **§5.17 „Atomare Root-Scope-Lease-Akquise (Story 3.11)"** eingefügt (nach §5.16, vor §6) — die **operationelle Atomaritäts-Präzisierung der Root-Scope-Akquise** über der textuell unveränderten §5.11-/§5.12-Mechanik (D-3, Story 3.11; AD-17b/A0-13; §5.11 Pkt. 1/2 und §5.12-Anker sind Fugen-Identität, Revision 3.6): (1) **Exklusivitätsschlüssel = scope-bezogener Lock im clone-geteilten Zustand** (AC-a; der geteilte Git-Ref-/Objektnamespace ist der einzige von allen Worktrees/Prozessen eines Clones gemeinsam gesehene Zustand; eine deterministisch benannte, committete Ref je Root-Scope `wiki/`, z. B. `refs/leases/wiki`; die **Run-ID ist Lock-Inhalt und nicht Bestandteil des Exklusivitätsschlüssels** — der Ref-Name trägt keine Run-ID; die bisherige `<id>`-Ablage §5.11 Pkt. 1 bleibt per-Lease-Ablage ohne alleinige Exklusivität), (2) **atomare Akquise (create-only) — genau ein Gewinner** (AC-b; `git update-ref <lock-ref> <wert> $ZERO_SHA` schlägt fehl, sobald der Ref existiert, und berührt einen existierenden Lock nicht; gits Ref-Sperre serialisiert zwei Worktrees/Prozesse desselben Clones; **Ask-First-Pflicht**: nicht sicher atomar belegbar auf Windows/Git-Bash → HALT, Alternativ-Primitiv zur Autorisierung), (3) **`LEASE_HOLD`-Semantik** (AC-c; abgewiesener Producer verändert weder `wiki/` noch den Lock, erzeugt keinen Compilation Commit, entfernt keine fremde Lease, beendet sauber, AD-16-Pfad), (4) **Determinismus** (AD-17h/A0-19; clone-geteilter Zustand = eindeutige Gewinner-/Verlierer-Entscheidung; Lock-Inhalt dokumentierender Ablage-Wert, kein Schlüsselbestandteil), (5) **Kollisions-Hold an Epic 4** (AC-e/AD-17c/A0-14; kein textueller Auto-Merge, strukturierter Kollisions-Hold mit beiden Commit-Hashes und Scope an Epic 4 via §5.16-Pkt.-8-/§5.10-Pkt.-8-Hold-Mechanik; AD-16-Klassifikation bleibt Epic 4; Commit-Boundary = Mutations-Boundary und `log.md`-Eintragspflicht unverändert), (6) **Abgrenzung** (keine Wanduhr/Systemzeit A0-20, keine Staleness-/Recovery-Logik — bleibt §5.12/Story 3.6 und Story 3.12 —, keine Verwaist-/Stale-Behandlung/kein Branch-Lifecycle nach Übernahme — Story 3.12). **§7:** Leasing-Bullet um die **Story-3.11-Verankerung** erweitert (§5.17; bestehende Story-Bullets unverändert). **§8:** AD-17b/A0-13 bleiben über die bestehende §5.11-Zuordnung verankert — §5.17 referenziert sie (Fugen-Identität). **Abschlussklausel (Story 3.11):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein neuer Frontmatter-Key für Lease-Metadaten** (Vertrag §3.1–§3.7 unverändert); **kein neuer Prädikat-/Format-Key**; **kein Standalone** (D-3); keine Vertragsänderung; §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker **textuell unverändert** (additive Präzisierung, Fugen-Identität); keine Wanduhr/Systemzeit (A0-20); keine Staleness-/Recovery-Logik (Story 3.6/3.12); Commit-Boundary-Regel unverändert; AD-16-Klassifikation bleibt Epic 4. **`sprint-status.yaml`:** Key `3-11-root-scope-leasing-atomar-akquirieren` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3/3.4/3.5). Sandbox-Nachweis (**A-1..A-8, Exit 0**; Zwei-Worktree-/Zwei-Prozess-Überlappung mit Zwischenzustands-Sampling („niemals zwei aktive Root-Leases" **konstruktiv belegt** — eine scope-bezogene Ref + atomarer create-only-Write, keine zwei Refs/Werte im Überlappungs-Fenster), `LEASE_HOLD`-Nicht-Mutation, Kollisions-Hold mit beiden Commit-Hashes) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.11, Revision 3.6).
|
- **Revision 3.6 (2026-08-21, Story 3.11):** Neue Sektion **§5.17 „Atomare Root-Scope-Lease-Akquise (Story 3.11)"** eingefügt (nach §5.16, vor §6) — die **operationelle Atomaritäts-Präzisierung der Root-Scope-Akquise** über der textuell unveränderten §5.11-/§5.12-Mechanik (D-3, Story 3.11; AD-17b/A0-13; §5.11 Pkt. 1/2 und §5.12-Anker sind Fugen-Identität, Revision 3.6): (1) **Exklusivitätsschlüssel = scope-bezogener Lock im clone-geteilten Zustand** (AC-a; der geteilte Git-Ref-/Objektnamespace ist der einzige von allen Worktrees/Prozessen eines Clones gemeinsam gesehene Zustand; eine deterministisch benannte, committete Ref je Root-Scope `wiki/`, z. B. `refs/leases/wiki`; die **Run-ID ist Lock-Inhalt und nicht Bestandteil des Exklusivitätsschlüssels** — der Ref-Name trägt keine Run-ID; die bisherige `<id>`-Ablage §5.11 Pkt. 1 bleibt per-Lease-Ablage ohne alleinige Exklusivität), (2) **atomare Akquise (create-only) — genau ein Gewinner** (AC-b; `git update-ref <lock-ref> <wert> $ZERO_SHA` schlägt fehl, sobald der Ref existiert, und berührt einen existierenden Lock nicht; gits Ref-Sperre serialisiert zwei Worktrees/Prozesse desselben Clones; **Ask-First-Pflicht**: nicht sicher atomar belegbar auf Windows/Git-Bash → HALT, Alternativ-Primitiv zur Autorisierung), (3) **`LEASE_HOLD`-Semantik** (AC-c; abgewiesener Producer verändert weder `wiki/` noch den Lock, erzeugt keinen Compilation Commit, entfernt keine fremde Lease, beendet sauber, AD-16-Pfad), (4) **Determinismus** (AD-17h/A0-19; clone-geteilter Zustand = eindeutige Gewinner-/Verlierer-Entscheidung; Lock-Inhalt dokumentierender Ablage-Wert, kein Schlüsselbestandteil), (5) **Kollisions-Hold an Epic 4** (AC-e/AD-17c/A0-14; kein textueller Auto-Merge, strukturierter Kollisions-Hold mit beiden Commit-Hashes und Scope an Epic 4 via §5.16-Pkt.-8-/§5.10-Pkt.-8-Hold-Mechanik; AD-16-Klassifikation bleibt Epic 4; Commit-Boundary = Mutations-Boundary und `log.md`-Eintragspflicht unverändert), (6) **Abgrenzung** (keine Wanduhr/Systemzeit A0-20, keine Staleness-/Recovery-Logik — bleibt §5.12/Story 3.6 und Story 3.12 —, keine Verwaist-/Stale-Behandlung/kein Branch-Lifecycle nach Übernahme — Story 3.12). **§7:** Leasing-Bullet um die **Story-3.11-Verankerung** erweitert (§5.17; bestehende Story-Bullets unverändert). **§8:** AD-17b/A0-13 bleiben über die bestehende §5.11-Zuordnung verankert — §5.17 referenziert sie (Fugen-Identität). **Abschlussklausel (Story 3.11):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein neuer Frontmatter-Key für Lease-Metadaten** (Vertrag §3.1–§3.7 unverändert); **kein neuer Prädikat-/Format-Key**; **kein Standalone** (D-3); keine Vertragsänderung; §5.11-Pkt.-1/2-Wortlaut und §5.12-Anker **textuell unverändert** (additive Präzisierung, Fugen-Identität); keine Wanduhr/Systemzeit (A0-20); keine Staleness-/Recovery-Logik (Story 3.6/3.12); Commit-Boundary-Regel unverändert; AD-16-Klassifikation bleibt Epic 4. **`sprint-status.yaml`:** Key `3-11-root-scope-leasing-atomar-akquirieren` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3/3.4/3.5). Sandbox-Nachweis (**A-1..A-8, Exit 0**; Zwei-Worktree-/Zwei-Prozess-Überlappung mit Zwischenzustands-Sampling („niemals zwei aktive Root-Leases" **konstruktiv belegt** — eine scope-bezogene Ref + atomarer create-only-Write, keine zwei Refs/Werte im Überlappungs-Fenster), `LEASE_HOLD`-Nicht-Mutation, Kollisions-Hold mit beiden Commit-Hashes) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.11, Revision 3.6).
|
||||||
|
- **Revision 3.7 (2026-08-21, Story 3.12):** Neue Sektion **§5.18 „Lease-Lifecycle & transaktionaler Commit-Abschluss (Story 3.12)"** eingefügt (nach §5.17, vor §6) — die **geschlossene, transaktionale Lifecycle-Klammer** der Koordinations-Dimension über der textuell unveränderten §5.11-/§5.12-/§5.13-/§5.17-Mechanik (D-3, Story 3.12; AC-1..AC-7; A0-20 — keine Wanduhr-/Systemzeit-Steuerung, Lifecycle deterministisch aus dem committeten Git-State, AD-17h/A0-19; §5.17-Pkt.-1-Z. 419-„Lifecycle-Regie Story 3.12" und Pkt.-6-Z. 424-„bleibt Story 3.12" sind die Anschluss-Sutur, Fugen-Identität): (1) **Liveness & Ownership** (AC-1; eine höhere Generation allein macht eine lebende Lease nicht stale — Staleness verlangt bestätigten Abbruch oder abgelaufene Liveness plus atomare Ownership-Prüfung; kein Wanduhr-TTL, A0-20), (2) **stale-Übernahme genau einmal** (AC-2; ownership-gebunden über den §5.17-Scope-Lock, ersetzte Holder-ID im `log.md` benannt, genau eine aktive Root-Lease, nie still gelöscht — AD-17e), (3) **eindeutige Abort-/Protect-Zustandsmaschine** (AC-3; getrackte fremde Änderung → Scratch-Zone `scratch/<run-id>/` oder `git stash push`, ungetrackte fremde Datei → Protect, byte-identischer Restore, `UNCOMMITTED_INPUT`-Abbruch abgestimmt §5.11 Pkt. 3, nie gelöscht), (4) **Baseline-Rollback Index + Worktree** (AC-4; `git reset --hard <Baseline-Commit>`, Post-Rollback-Diff gg. Baseline leer, §5.13 Pkt. 3), (5) **durable Release** (AC-5; Mutation + zulässiger Log-/Koordinationsnachweis committet, Lock per Ref-Delete nur durch Inhaber, Worktree sauber, Clean-Input-Guard — Folge-Run ohne `INPUT_UNCOMMITTED`-Abbruch; Release-Fehler = HARD-FAIL), (6) **kanonisches Log** (AC-6; `wiki/log.md` nur vertragskonforme fachliche + notwendige Koordinationsereignisse, Build-/Review-/Story-/Sandbox-Historie außerhalb), (7) **Kill-Point-Tests** (AC-7; vor Mutation/nach Mutation/vor Commit/nach Commit je konsistenter Endzustand, §5.13-Pkt.-3-Zustands-Restaurations-Invariante). **§7:** Leasing-Bullet um die **Story-3.12-Verankerung** erweitert (§5.18; bestehende Story-Bullets unverändert). **§8:** AD-17b/A0-13/A0-15/A0-16-/AD-17e/f-Anker bleiben über die bestehende §5.11-/§5.12-Zuordnung verankert — §5.18 referenziert sie (Fugen-Identität). **Abschlussklausel (Story 3.12):** Keine Änderung an `schema/wiki-compiler.md`/`schema/validator.md`/`adapters/`/`raw/` (AD-3); **keine neue §7-Invaliditätsklasse**; **kein neuer Frontmatter-/Format-Key** (Vertrag §3.1–§3.7 unverändert); **kein Standalone** (D-3); keine Vertragsänderung; §5.11-Pkt.-1-7-/§5.12-Pkt.-1-7-/§5.13-/§5.17-Wortlaute **textuell unverändert** (additive Präzisierung, Fugen-Identität); keine Wanduhr/Systemzeit (A0-20, keine TTL über Kalenderzeit); keine stille Löschung fremder uncommitteter/geschützter Änderungen (AD-17e); keine Wissensmutation bei Orphan/Hold (AD-16-Default); kein textueller Auto-Merge (AD-17c); `generated.at`-Verhalten unverändert; Commit-Boundary-Regel unverändert; AD-16-Klassifikation bleibt Epic 4. **`sprint-status.yaml`:** Key `3-12-lease-lifecycle-und-commit-abschluss-transaktional-schliessen` auf **`review`** geflippt (Implementierungs-Commit; finaler `done`-Flip im Step-05-Status-Sync nach abgeschlossenem Review-Loop — Präzedenz Revision 3.2/3.3/3.4/3.5/3.6). Sandbox-Nachweis (**L-1..L-9, Exit 0**; Lifecycle-Zustandsmaschine, Abort-/Protect-Zustandsmaschine getrackt/ungetrackt byte-identisch, Baseline-Rollback Index+Worktree mit leerem Post-Rollback-Diff, Kill-Point-Tests an vier Punkten, durable Release + Clean-Input-Guard, stale-Übernahme genau einmal) und per-Datei-Validator-Verdikt siehe `wiki/log.md`-Eintrag (Story 3.12, Revision 3.7).
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user