Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6624e07d3b | ||
|
|
584676e387 | ||
|
|
02786f43e7 |
@@ -632,3 +632,19 @@ Noch nicht adressierte, aber real erkannte Arbeit — gesammelt aus Reviews. Ein
|
||||
|
||||
- DF1 — AC-3-`git stash push`-Variante und kombiniertes AC-5 „Fremd-Bytes restauriert" nie geübt: §5.18 Pkt. 3 benennt `git stash push -- <Pfad>` bzw. `stash push -u` als zulässige native Alternative zur Scratch-Zone; die Sandbox L-3/L-4 übt ausschließlich die Scratch-Zweige (der Stash-Ast — Sichern, Worktree-Bereinigung, byte-identischer Restore aus dem Stash — hat keinerlei Coverage/Guard). Zusätzlich wird AC-5s Clean-Input-Guard-Klausel „geschützte Fremd-Bytes sind restauriert" nur isoliert in L-3/L-4 bewiesen, nie kombiniert mit Release + Folge-Run im selben Szenario. Home: Sandbox-Härtung (Story-3.13-Abnahme-Gate deckt native-Varianten-Abdeckung über echte Bäume).
|
||||
- DF2 — `assert_no_wallclock` überbreit (trifft jedes `YYYY-MM-DD`-Zeichenmuster, inkl. legitimer `### YYYY-MM-DD`-Datumsgruppen des `wiki/log.md` — Konventionsdaten, keine Wanduhr-Steuerung): der A0-20-Check ist daher nur auf `registry/wiki` (L-1) anwendbar, nicht auf `log.md`; der L-1-Kommentar „kein Zeitstempel in Lock/Registry" behauptet breitere Coverage als die Funktion liefert. A0-20-Steuerung greift korrekt (nur auf Registry/Lock); Kommentarschärfe + eventuelle schärfere Regex (z. B. `T[0-9]{2}`-Pflicht) = Kosmetik. Home: Sandbox-Kosmetik (nächste Sandbox-Härtung).
|
||||
|
||||
|
||||
### Aufgegriffen: Story-3.13-Abnahme als Home der 3.13-namigen Defer (Gate-Runs realisiert; rd-Notiz-/Defer-Block unverändert) — Story 3.13, 2026-08-22
|
||||
|
||||
Der Epic-3-Abnahmegate-Lauf (`_bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh`, RUN_OK/Exit 0, PASS_COUNT=70, FAILED=0) realisiert das Home „Story-3.13-Abnahme" der folgenden Defer-Einträge einschlägig. Die Original-Blöcke bleiben historisch unverändert (nur das Home ist erledigt, Spec-3.13 Code-Map Pkt. 59; AD-17e).
|
||||
|
||||
- **DET-1/DET-2-Plan-/Form-Literale vs. AC-5 „nicht hart codiert"** (Story-3.8-Defer, Z. 551; Home: Story-3.13-Abnahme, echte Gate-Runs über die Instruktion) — aufgegriffen: Der 3.13-Gate-Kern E führt GEGEN die committete Fixture zwei echte frische Agent-Läufe (A/B, getrennte Worktrees auf demselben `$BASE`) über `schema/compiler.md` als einzige Instruktionsquelle aus; der Harness schreibt weder erwartete Bodies noch Receipts (AC-5); der A/B-Vergleich bestätigt bundle-State-Identität bis auf die `generated.at`-Ausnahme (§5.14 Pkt. 2). Die Nicht-Vakuum- und Determinismus-Last tragen die real erzeugten Bundle-Bäume (git diff A B -- wiki/, nur at-Zeilen) und die Negativ-Kontrolle G-6.
|
||||
- **Positive Zwei-Run-Identität strukturell trivial (R-9 clean A==B)** (Story-3.9-Defer, Z. 560; Home: Story-3.13-Abnahme) — aufgegriffen: Die Zwei-frische-Agenten-Bestätigung ist im 3.13-Gate real (getrennte Kontexte, getrennte Worktrees, gemeinsamer `$BASE`, Instruktion als einzige Quelle), nicht mehr aus Skript-Literalen abgeleitet; A==B-Identität wird über den realen Bundle-Baum-Vergleich assertiert.
|
||||
- **Externer Validator gegen das reale committete Bundle** (Story-3.10-Defer, Z. 576; Home: Story-3.13-Abnahmegate) — aufgegriffen: Abschnitt D des Gates startet einen frischen Agent-Kontext, der `schema/validator.md` (Rev 9) über alle 7 `wiki/`-Dateien der realen /tmp-Käfig-Kopie ausführt und Verdikte `SUCCESS`/`FAIL` je Datei ablegt; das Gate prüft Grammatik + Exhaustivität, urteilt nie selbst (D-3).
|
||||
- **Zwei-Producer-verschiedene-`<id>`-Gewinner** (Story-3.11-Defer, Z. 594; Home: Story-3.12-Lifecycle / Story-3.13-Abnahme) — aufgegriffen: sandbox-3-12 (Sub-Run im Gate, Abschnitt C) übt den atomaren Ownership-CAS-Takeover des `refs/leases/wiki`-Scope-Locks; das 3.13-Gate hebt die 12 Sandbox-Suiten in einen einzigen fail-fast-Abnahmelauf (AC-1).
|
||||
- **A-2 keine Synchronisations-Barriere / zeitliche Überlappung** (Story-3.11-Defer, Z. 597; Home: Sandbox-Härtung / Story-3.13-Abnahme) — aufgegriffen (Gate-Route): Der 3.13-E-Kern demonstriert die Real-Tree-Ausführung zweier unabhängiger Compiler-Runs in getrennten Worktrees; die atomare create-only-`git update-ref`-Semantik von sandbox-3-12 wird als Sub-Run des Abnahmegates re-ausgeführt. Die zwangsweise gleichzeitige (wanduhrgetaktete) Überlappung zweier Prozesse bleibt als benannter Rest-Term der Sandbox-Härtung (A0-20-rahmenkonform) bestehen.
|
||||
- **Rest-Vertiefung echte Zwei-Worktree-Überlappung** (Story-3.11-Aufgegriffen-Notiz, Z. 611) — aufgegriffen (Rest-Term wie im Original-Eintrag benannt): das 3.13-Gate führt die Zwei-frische-Agenten-Bestätigung real in getrennten Worktrees aus; eine wanduhr-synchronisierte Echt-Überlappung beider Produzenten bleibt Rest-Vertiefung der Sandbox-Härtung.
|
||||
- **Geteilter-Ref-Namespace-/Zwei-Worktree-Übernahme-Real-Beweis** (Story-3.12-Defer, Z. 629; Home: Story-3.13-Abnahme) — aufgegriffen: Das 3.13-Gate stellt den Clone-geteilten Käfig (ein `git init`-Repo, mehrere Worktrees auf demselben `$BASE`) bereit und führt die Zwei-frische-Agenten-Runs real aus — der Determinismus-/Takeover-Beweis läuft hier über echte unabhängige Worktrees statt über einen einzigen sequenziellen Worktree.
|
||||
- **DF1 — AC-3-`git stash push`-Variante + kombiniertes AC-5** (Story-3.12-Defer, Z. 633; Home: Sandbox-Härtung / Story-3.13-Abnahme-Gate) — aufgegriffen (Gate-Route): Das 3.13-Gate re-ausführt sandbox-3-12 L-1..L-9 (inkl. Scratch-Zone-/Restore-Klasse und Clean-Input-Guard) als Sub-Run im Gesamtabnahmekontext; die zusätzliche native `git stash`-Alternativ-Variante und die wanduhr-gekoppelte Kombination bleiben als Rest-Term der Sandbox-Härtung benannt (keine neue §-Semantik, keine Instruktions-/Validator-Änderung, AD-3).
|
||||
|
||||
- status: aufgegriffen (Home „Story-3.13-Abnahme" realisiert durch die echten Abnahmegate-Runs; Original-Defer-Blöcke unverändert; jeweils benannte Rest-Terme der weiterführenden Sandbox-Härtung bleiben offen — kein Instruktions-/Validator-Defekt, A0-20-konform)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Goal
|
||||
|
||||
Der Compiler verarbeitet neues Source Material gegen das bestehende Knowledge Bundle, statt das Wiki bei jedem Lauf aus sämtlichen Rohquellen neu aufzubauen (Compounding Knowledge). Bestehende Concepts werden durch neue Erkenntnisse erweitert, präzisiert oder in eindeutig belegten Fällen korrigiert; mehrere Sources werden zu einer gemeinsamen Wissensrepräsentation mit gemischter, claim-granularer Provenienz synthetisiert; unverändertes Wissen bleibt erhalten. Relevanzbestimmung und Reconcile-Routing sind textual-deterministisch ohne Embedding- oder Vector-Infrastruktur. Konkurrierende Producer koordinieren sich über eine atomare Root-Scope-Lease mit transaktionalem Dirty-Tree-, Rollback- und Release-Lifecycle. Klassifikationspflichtige Kollisionen und Widersprüche werden bis Epic 4 fail-closed als strukturierter Hold erhalten; der Determinismus-Vertrag wird mechanisch qualifiziert. Epic 3 gilt erst nach einem realen, unabhängigen Source→Compilation→Wiki-Abnahmegate als abgeschlossen (AD-5, AD-6, AD-13, AD-17a/b/d–h, A0-6/7/12–16/18/19).
|
||||
Der Compiler verarbeitet neues Source Material gegen das bestehende Knowledge Bundle, statt das Wiki bei jedem Lauf aus sämtlichen Rohquellen neu aufzubauen (Compounding Knowledge). Bestehende Concepts werden durch neue Erkenntnisse erweitert, präzisiert oder in eindeutig belegten Fällen korrigiert; mehrere Sources werden zu einer gemeinsamen Wissensrepräsentation mit gemischter, claim-granularer Provenienz synthetisiert; unverändertes Wissen bleibt erhalten. Relevanzbestimmung und Reconcile-Routing sind textual-deterministisch ohne Embedding- oder Vector-Infrastruktur. Konkurrierende Producer koordinieren sich über eine atomare Root-Scope-Lease mit transaktionalem Dirty-Tree-, Rollback- und Release-Lifecycle. Klassifikationspflichtige Kollisionen und Widersprüche werden bis Epic 4 fail-closed als strukturierter Hold erhalten; der Determinismus-Vertrag wird mechanisch qualifiziert. **Ist (Story 3.13, 2026-08-22): das reale, unabhängige Source→Compilation→Wiki-Abnahmegate ist ausgeführt — `_bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh` lief voll grün (PASS_COUNT=70, FAILED=0, RUN_OK/Exit 0): 12 Sandbox-Suiten fail-fast, vollständiger Validator (schema/validator.md Rev 9) über alle 7 wiki/-Dateien (7/7 SUCCESS), Zwei-frische-Agenten-Kontexte A/B mit byte-identischem Bundle-State bis auf die at-Ausnahme (§5.14 Pkt. 2), G-1..G-8 inkl. Epic-5-Consumer-Smoke und Porcelain-Check; siehe wiki/log.md Story-3.13-Eintrag.** Epic 3 ist damit abnahmegeeignet; die finale Retrospektive (Epic-3-retrospective) schließt das Epic ab (AD-5, AD-6, AD-13, AD-17a/b/d–h, A0-6/7/12–16/18/19).
|
||||
|
||||
## Stories
|
||||
|
||||
@@ -43,12 +43,12 @@ Der Compiler verarbeitet neues Source Material gegen das bestehende Knowledge Bu
|
||||
- **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.
|
||||
- **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. *Ist (Story 3.13, 2026-08-22): realisiert als `sandbox-3-13/run-sandbox.sh` — fail-fast-Orchestrierung (A Setup, B /tmp-Käfig, C 12 Sandbox-Sub-Runs, D Validator-Agent mit Verdikt-Grammatik/-Exhaustivität statt eigener Urteile, E Zwei-frische-Agenten A/B auf git-worktree-$BASE, F G-1..G-8 harte Assertions inkl. G-6 Negativ-Kontrolle Perturbation und G-7 Epic-5-Smoke, G Porcelain-Endzustands-Invariante). Der vollständige Gate-Lauf ist grün (PASS_COUNT=70, FAILED=0, RUN_OK/Exit 0); G-7 exkludiert den Bundleroot-Schema-Glossar (../schema/, compiler §5.6 „andere Schicht", AC-8 optionale Provenienz) und das log.md-Protokoll (§5.6 Pkt. 2).*
|
||||
- **Keine UX-/Design-Anteile relevant:** v1 ist datei-/CLI-basiert ohne GUI (PRD A-3, AD-11).
|
||||
|
||||
## Cross-Story Dependencies
|
||||
|
||||
- Baut auf dem Workspace aus Epic 1 auf (immutable `raw/`, Bundle-Root, Schema-Validierung) und konsumiert die in Epic 2 erzeugten OKF-konformen, verlinkten Concepts mit claim-granularer Provenienz als vorhandenes Wissen.
|
||||
- Story 3.9 liefert die deterministische Routing-Basis für Story 3.10; Story 3.11 liefert die atomare Lease-Basis für Story 3.12 (parallel). Story 3.8 wird nach 3.9–3.12 mit echten unabhängigen Runs abgeschlossen; Story 3.13 ist das finale Abnahmegate.
|
||||
- Story 3.9 liefert die deterministische Routing-Basis für Story 3.10; Story 3.11 liefert die atomare Lease-Basis für Story 3.12 (parallel). Story 3.8 ist nach 3.9–3.12 mit echten unabhängigen Runs abgeschlossen (done); **Story 3.13 ist das finale Abnahmegate — ausgeführt und grün (2026-08-22, PASS_COUNT=70, RUN_OK/Exit 0): die Zwei-frische-Agenten-Bestätigung (echte getrennte Worktrees auf demselben $BASE, bundle-State identisch bis auf at-Ausnahme) und der vollständige Validator-Lauf über das reale Bundle (7/7 SUCCESS) sind realisiert; siehe wiki/log.md Story-3.13-Eintrag.**
|
||||
- AD-17c/A0-14 sind geteilt: Epic 3 verantwortet Erkennung und fail-closed Erhaltung, Epic 4 Klassifikation und semantische Auflösung. AD-17g/A0-17 verbleiben vollständig in Epic 4. A0-21 ist ebenfalls geteilt: Story 3.10 verantwortet den Incrementality-Teil (Erhaltung unabhängigen Wissens), Story 4.3 die Human-Curation-Semantik (FT-9).
|
||||
- Das Leasing-/Dirty-Tree-Modell koordiniert Compiler-Runs mit menschlicher Bearbeitung und trägt die Git-Nachvollziehbarkeit, auf die Epic 5 aufsetzt.
|
||||
|
||||
@@ -0,0 +1,771 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================================
|
||||
# Sandbox Story 3.13 — Epic-3-Verifikations- und Abnahmegate
|
||||
# (spec-3-13-epic-3-verifikations-und-abnahmegate.md, 2026-08-22)
|
||||
#
|
||||
# Re-executierbar: bash run-sandbox.sh (ab Repo-Root)
|
||||
#
|
||||
# Zweck: das repositoryweite Epic-3-Gate — EIN Kommando führt alle Epic-3-
|
||||
# Szenarien fail-fast aus (AC-1):
|
||||
# (A) Setup Repo-/Bundle-/Referenz-Check, Sandbox-Liste 3-1..3-12,
|
||||
# git status --porcelain Pre-Check
|
||||
# (B) Käfig-Bau /tmp-Kopie des realen Clone-Baums (liest wiki/**/*.md,
|
||||
# kopiert schema/adapters/raw), git init + Baseline
|
||||
# (C) 12 Sandbox-Sub-Runs bash …/sandbox-3-N/run-sandbox.sh, Exit-Check
|
||||
# pausiert, fail-fast
|
||||
# (D) Validator-Agent frischer Sub-Agent liest schema/validator.md und
|
||||
# erzeugt SUCCESS/FAIL-Verdikte über alle wiki/Dateien;
|
||||
# das Gate prüft nur Grammatik/Exhaustivität (§5/§5.1),
|
||||
# urteilt nie selbst (D-3)
|
||||
# (E) Zwei-frische-Agenten zwei /tmp-Worktrees auf denselben $BASE-Commit,
|
||||
# CONFIRMING-Fixture (raw/alpha-v2.md#S-3 bestätigt
|
||||
# bestehende Aussage mit NEUEM Anker → deterministische
|
||||
# §5.16-Pkt.-4-Multi-Beleg-Konsolidierung), beide Läufe
|
||||
# führen schema/compiler.md aus; A/B-git diff -- wiki/
|
||||
# at-only; G-6 perturbed Negativ-Kontrolle
|
||||
# (F) G-1..G-8 harte Assertions (inkl. Epic-5-Consumer-Smoke G-7,
|
||||
# Porcelain-Check G-8)
|
||||
# (G) Nachweise/Porcelain Endzustands-Invariante
|
||||
#
|
||||
# Constraints (Spec):
|
||||
# - setup: set -u, kein set -e (negatives Assertions-Idiom); ROOT=$(mktemp
|
||||
# -d /tmp/sb313-XXXXXX); git config core.autocrlf false + core.filemode
|
||||
# false; harte pass()/fail(); End-Exit 0
|
||||
# - AC-2: keine sed -i (nur cp/printf/git); portabel macOS/BSD/Linux
|
||||
# - AC-4/AD-3: schema/compiler.md, validator.md, wiki-compiler.md,
|
||||
# adapters/, raw/ read-only; das Gate mutiert sie nie
|
||||
# - AC-5: das Gate schreibt KEINE erwarteten Wiki-Bodies/Lease-/Log-/Git-
|
||||
# Ausgänge; die beiden frischen Agent-Kontexte erzeugen die Wiki-/Receipt-
|
||||
# Ausgabe; das Gate vergleicht nur A vs B
|
||||
# - races ausschließlich als /tmp-Käfig des realen Clone-Baums (nie Ist-Baum)
|
||||
# - D-3: der Validator ist eine Instruktion; das Gate validiert nur
|
||||
# Verdikt-Grammatik/-Exhaustivität, urteilt nie fachlich
|
||||
# ============================================================================
|
||||
set -u
|
||||
|
||||
# ---------- Basis-Exit-/Pass-/Fail-Idiom (harte Assertions, kein set -e) ----------
|
||||
FAILED=0
|
||||
PASS_COUNT=0
|
||||
runlabel() { echo; echo "########## $1 ##########"; }
|
||||
pass() { PASS_COUNT=$((PASS_COUNT+1)); echo "PASS: $1"; }
|
||||
fail() { FAILED=$((FAILED+1)); echo "FAIL: $1" >&2; }
|
||||
cmd_or_fail() { # $1 = Beschreibung ; rest = Kommando — hart abbrechen wenn Kommando fehlschlägt
|
||||
local desc="$1"; shift
|
||||
if ! "$@"; then
|
||||
echo "HARD-FAIL: $desc" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# $* / "$@"
|
||||
# ShellCheck SC2034 not an issue here.
|
||||
|
||||
# ---------- A. Setup: Repo-/Bundle-/Referenz-Check ----------
|
||||
runlabel "A. SETUP — Repo-/Bundle-/Referenz-Check, Sandbox-Liste, Porcelain-Pre-Check"
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
# Sandbox-Skript liegt unter _bmad-output/implementation-artifacts/sandbox-3-13/
|
||||
# => drei Ebenen nach oben zur Repo-Root.
|
||||
echo "REPO_ROOT=$REPO_ROOT"
|
||||
|
||||
# Referenz-Sandboxen 3-1..3-12 müssen existieren
|
||||
SB_BASE="$REPO_ROOT/_bmad-output/implementation-artifacts"
|
||||
MISSING_SB=0
|
||||
for n in 01 02 03 04 05 06 07 08 09 10 11 12; do
|
||||
# normalisiere führende Null: 01 -> 1, ..., 09 -> 9, 10..12 bleiben
|
||||
case "$n" in
|
||||
0*) num="${n#0}";;
|
||||
*) num="$n";;
|
||||
esac
|
||||
d="$SB_BASE/sandbox-3-$num/run-sandbox.sh"
|
||||
if [ -f "$d" ]; then
|
||||
pass "Referenz-Sandbox sandbox-3-$num vorhanden ($d)"
|
||||
else
|
||||
echo "FAIL: Referenz-Sandbox sandbox-3-$num fehlt ($d)" >&2
|
||||
MISSING_SB=$((MISSING_SB+1))
|
||||
fi
|
||||
done
|
||||
[ "$MISSING_SB" -eq 0 ] || { echo "HARD-FAIL: $MISSING_SB Referenz-Sandbox(en) fehlen" >&2; exit 1; }
|
||||
|
||||
# Repo-/Bundle-/Referenz-Checks
|
||||
[ -f "$REPO_ROOT/schema/compiler.md" ] && pass "schema/compiler.md vorhanden" \
|
||||
|| { echo "HARD-FAIL: schema/compiler.md fehlt" >&2; exit 1; }
|
||||
[ -f "$REPO_ROOT/schema/validator.md" ] && pass "schema/validator.md vorhanden" \
|
||||
|| { echo "HARD-FAIL: schema/validator.md fehlt" >&2; exit 1; }
|
||||
[ -f "$REPO_ROOT/schema/wiki-compiler.md" ] && pass "schema/wiki-compiler.md vorhanden" \
|
||||
|| { echo "HARD-FAIL: schema/wiki-compiler.md fehlt" >&2; exit 1; }
|
||||
[ -f "$REPO_ROOT/schema/canonical-terms.md" ] && pass "schema/canonical-terms.md vorhanden" \
|
||||
|| { echo "HARD-FAIL: schema/canonical-terms.md fehlt" >&2; exit 1; }
|
||||
[ -d "$REPO_ROOT/wiki" ] && pass "wiki/ vorhanden" \
|
||||
|| { echo "HARD-FAIL: wiki/ fehlt" >&2; exit 1; }
|
||||
[ -d "$REPO_ROOT/raw" ] && pass "raw/ vorhanden" \
|
||||
|| { echo "HARD-FAIL: raw/ fehlt" >&2; exit 1; }
|
||||
[ -f "$REPO_ROOT/wiki/index.md" ] && pass "wiki/index.md vorhanden" \
|
||||
|| { echo "HARD-FAIL: wiki/index.md fehlt" >&2; exit 1; }
|
||||
|
||||
# git status --porcelain Pre-Check: sauberer Ist-Zustand (G-8 Vorabbedingung)
|
||||
PORCELAIN_PRE=$(git -C "$REPO_ROOT" status --porcelain --untracked-files=no 2>/dev/null || true)
|
||||
if [ -z "$PORCELAIN_PRE" ]; then
|
||||
pass "Porcelain Pre-Check: Ist-Baum frei von getrackten uncommitteten Änderungen (G-8-Vorbedingung)"
|
||||
else
|
||||
echo "HARD-FAIL: Porcelain Pre-Check — Ist-Baum hat getrackte uncommittete Änderungen:" >&2
|
||||
printf '%s\n' "$PORCELAIN_PRE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read-only-Invarianten vorab (AD-3): Schema-/raw-/adapters-Hashes gegen Baseline
|
||||
# (unterstützt den AD-3-Nachweis am Ende; Baseline-Stichprobe)
|
||||
echo "(Read-only-Invarianten AD-3 werden in G-8 hart geprüft — hier nur Stichprobe der Existenz)"
|
||||
|
||||
echo
|
||||
echo "SETUP abgeschlossen (PASS_COUNT=$PASS_COUNT, FAILED=$FAILED)"
|
||||
|
||||
# ==============================================================================
|
||||
# B. KÄFIG-BAU — /tmp-Kopie des realen Clone-Baums (nie Ist-Baum)
|
||||
# ==============================================================================
|
||||
runlabel "B. KAEFIG-BAU — /tmp-Kopie des realen Clone-Baums"
|
||||
|
||||
# ROOT: /tmp-Basis für ALLE Gate-Artefakte (Käfig, Worktrees, Receipts, Manifest)
|
||||
ROOT=$(mktemp -d /tmp/sb313-XXXXXX) || { echo "HARD-FAIL: mktemp ROOT fehlgeschlagen" >&2; exit 1; }
|
||||
CAGE="$ROOT/cage"
|
||||
mkdir -p "$CAGE" || { echo "HARD-FAIL: cage mkdir fehlgeschlagen" >&2; exit 1; }
|
||||
pass "Gate-Root $ROOT (loeschbar: rm -rf $ROOT)"
|
||||
|
||||
# (1) Bundle-Dateiliste aus der REALEN wiki/ lesen (nur Textquelle, §-Spec: "reales
|
||||
# wiki/ wird nur als Textquelle gelesen") — für die Exhaustivitäts-Nachführung
|
||||
# des Validators und den Epic-5-Smoke.
|
||||
echo "--- bundle-dateiliste (wiki/**/*.md) ---"
|
||||
WIKI_MD_LIST=$(cd "$REPO_ROOT" && find wiki -type f -name '*.md' | LC_ALL=C sort)
|
||||
[ -n "$WIKI_MD_LIST" ] || { echo "HARD-FAIL: keine wiki/**/*.md-Dateien im realen Bundle" >&2; exit 1; }
|
||||
printf '%s\n' "$WIKI_MD_LIST"
|
||||
WIKI_MD_COUNT=$(printf '%s\n' "$WIKI_MD_LIST" | wc -l | tr -d ' ')
|
||||
pass "Bundle-Dateiliste: $WIKI_MD_COUNT Markdown-Dateien unter wiki/ erfasst"
|
||||
|
||||
# (2) schema + adapters + raw in den Käfig kopieren (read-only Vorbild; AD-3).
|
||||
# Die /tmp-Kopie MUSS den echten Baum blatt-identisch abbilden, damit der
|
||||
# Validator-/Compiler-Agent über demselben Stand arbeitet wie der Ist-Baum.
|
||||
mkdir -p "$CAGE/schema" "$CAGE/adapters" "$CAGE/raw" "$CAGE/wiki" || exit 1
|
||||
for s in compiler.md validator.md wiki-compiler.md canonical-terms.md; do
|
||||
cp "$REPO_ROOT/schema/$s" "$CAGE/schema/$s" 2>/dev/null \
|
||||
|| { echo "HARD-FAIL: schema/$s in Käfig kopieren fehlgeschlagen" >&2; exit 1; }
|
||||
done
|
||||
pass "schema/ (compiler.md, validator.md, wiki-compiler.md, canonical-terms.md) in Käfig kopiert (AD-3 read-only Vorbild)"
|
||||
cp -r "$REPO_ROOT/adapters/." "$CAGE/adapters/" 2>/dev/null \
|
||||
|| { echo "HARD-FAIL: adapters/ in Käfig kopieren fehlgeschlagen" >&2; exit 1; }
|
||||
pass "adapters/ in Käfig kopiert (read-only Vorbild)"
|
||||
cp -r "$REPO_ROOT/raw/." "$CAGE/raw/" 2>/dev/null \
|
||||
|| { echo "HARD-FAIL: raw/ in Käfig kopieren fehlgeschlagen" >&2; exit 1; }
|
||||
pass "raw/ in Käfig kopiert (read-only Vorbild)"
|
||||
# wiki/ als Textquelle in den Käfig spiegeln (Grundlage Validator-/Compiler-Agent)
|
||||
cp -r "$REPO_ROOT/wiki/." "$CAGE/wiki/" 2>/dev/null \
|
||||
|| { echo "HARD-FAIL: wiki/ in Käfig kopieren fehlgeschlagen" >&2; exit 1; }
|
||||
pass "wiki/ als Textquelle in Käfig kopiert"
|
||||
|
||||
# (3) Käfig als git-Repo initialisieren (Baseline für Validator-Exhaustivität)
|
||||
# — Determinismus: autocrlf/filemode deaktiviert (LF-Blobs, AD-17h).
|
||||
cd "$CAGE" || exit 1
|
||||
git init -q || { echo "HARD-FAIL: cage git init fehlgeschlagen" >&2; exit 1; }
|
||||
git config core.autocrlf false
|
||||
git config core.filemode false
|
||||
git config user.email "gate@sandbox"
|
||||
git config user.name "Gate-Sandbox"
|
||||
git add -A
|
||||
git commit -qm "Käfig-Baseline" || { echo "HARD-FAIL: cage Baseline-Commit fehlgeschlagen" >&2; exit 1; }
|
||||
CAGE_BASE=$(git rev-parse HEAD)
|
||||
[ -n "$CAGE_BASE" ] && git cat-file -e "$CAGE_BASE^{commit}" 2>/dev/null \
|
||||
|| { echo "HARD-FAIL: Käfig-Baseline nicht verifiziert" >&2; exit 1; }
|
||||
pass "Käfig-Baseline committet (CAGE_BASE=$CAGE_BASE)"
|
||||
|
||||
echo
|
||||
echo "KAEFIG-BAU abgeschlossen (PASS_COUNT=$PASS_COUNT, FAILED=$FAILED)"
|
||||
|
||||
# ==============================================================================
|
||||
# C. 12 SANDOX-SUB-RUNS — fail-fast, Exit-Check je Sandbox (AC-1)
|
||||
# ==============================================================================
|
||||
runlabel "C. 12-SANDBOX-SUB-RUNS — je bash …/run-sandbox.sh, Exit-Check, fail-fast"
|
||||
# Jede Sandbox baut sich ihr EIGENES /tmp-sb3N-Repo (nie Ist-Baum). Die Gate-Root
|
||||
# bleibt der Aufrufer-Root (cd nicht nötig — Sandboxen sind standalone).
|
||||
C_FAILED=0
|
||||
C_RUN=0
|
||||
for n in 1 2 3 4 5 6 7 8 9 10 11 12; do
|
||||
C_RUN=$((C_RUN+1))
|
||||
s="$SB_BASE/sandbox-3-$n/run-sandbox.sh"
|
||||
echo "--- Sandbox-Sub-Run $n: $s ---"
|
||||
if timeout 900 bash "$s" > "$ROOT/sandbox-$n.out" 2>&1; then
|
||||
pass "Sandbox-Sub-Run $n (sandbox-3-$n) Exit 0"
|
||||
else
|
||||
rc=$?
|
||||
echo "FAIL: Sandbox-Sub-Run $n (sandbox-3-$n) rc=$rc" >&2
|
||||
echo "--- letzte Zeilen von $ROOT/sandbox-$n.out ---" >&2
|
||||
tail -20 "$ROOT/sandbox-$n.out" >&2 2>/dev/null || true
|
||||
C_FAILED=$((C_FAILED+1))
|
||||
# fail-fast (AC-1): erste fehlgeschlagene Sandbox bricht ab
|
||||
echo "HARD-FAIL: Sandbox-Sub-Run $n fehlgeschlagen (fail-fast)" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
[ "$C_FAILED" -eq 0 ] || { echo "HARD-FAIL: $C_FAILED Sandbox-Sub-Run(s) fehlgeschlagen" >&2; exit 1; }
|
||||
pass "Alle $C_RUN Sandbox-Sub-Runs Exit 0 (fail-fast-Sequenz)"
|
||||
|
||||
echo
|
||||
echo "12-SANDBOX-SUB-RUNS abgeschlossen (PASS_COUNT=$PASS_COUNT, FAILED=$FAILED)"
|
||||
|
||||
# ==============================================================================
|
||||
# D. VALIDATOR-AGENT — frischer Kontext führt schema/validator.md aus (AC-3/AC-4)
|
||||
# ==============================================================================
|
||||
runlabel "D. VALIDATOR-AGENT — frischer Kontext, Verdikte SUCCESS/FAIL über alle wiki/"
|
||||
# Der Validator-Agent ist der DIR-Exekutor für schema/validator.md (D-3): er liest
|
||||
# die Instruktion und erzeugt je wiki-Datei ein Verdikt (SUCCESS <pfad> bzw.
|
||||
# FAIL <pfad> <ursache>). Das Gate prüft NUR Grammatik (§5/§5.1) und Exhaustivität
|
||||
# (jede wiki/**/*.md hat genau ein Verdikt) — es urteilt nie fachlich (D-3).
|
||||
#
|
||||
# Ablage: verdict-<id>.md im Käfig-Root (außerhalb wiki/), damit der Agent die Datei
|
||||
# ohne wiki/-Berührung schreibt und das Gate sie als Report liest.
|
||||
VALIDATOR_CAGE="$CAGE"
|
||||
VALIDATOR_OUT="$ROOT/verdict-validator.md"
|
||||
[ -n "${CLAUDE_BIN:-}" ] || CLAUDE_BIN="/d/Apps/nodejs/claude.cmd"
|
||||
# -x schlägt unter MSYS/Windows für .cmd-Dateien fehl (Mode 0644 trotz Ausführbarkeit).
|
||||
# Daher nur Existenz prüfen; die tatsächliche Aufrufbarkeit zeigt der Agent-Lauf.
|
||||
[ -f "$CLAUDE_BIN" ] || { echo "HARD-FAIL: claude.cmd fehlt ($CLAUDE_BIN)" >&2; exit 1; }
|
||||
|
||||
# Frischer Validator-Agent-Kontext (liest schema/validator.md als EINZIGE normative
|
||||
# Quelle, KEINE Annahmen über erwartete Ergebnisse). Schreibt verdict-Datei.
|
||||
run_validator_agent() {
|
||||
local out="$1" cage="$2"
|
||||
local win_path
|
||||
win_path=$(cygpath -w "$out" 2>/dev/null || echo "$out")
|
||||
# Prompt-Datei: VERDICT_OUT-Placeholder wird deterministisch ersetzt (printf,
|
||||
# kein sed -i / keine Backslash-Falle durch Windows-Pfad), dann liest der
|
||||
# frische Kontext die Prompt-Datei und führt sie aus. Der Agent schreibt
|
||||
# ausschließlich die Verdikt-Datei (kein wiki//raw//schema/-Zugriff).
|
||||
local vprompt
|
||||
vprompt=$(mktemp "$ROOT/validator-prompt-XXXXXX.txt")
|
||||
printf '%s\n' \
|
||||
'Du bist ein frisch gestarteter Validator-Kontext des "wow-compiler". Arbeite ausschließlich in deinem aktuellen Arbeitsverzeichnis (ein /tmp-Käfig des Bundles). LIES die Datei schema/validator.md (Rev 9) — sie ist die EINZIGE normative Instruktionsquelle. Führe den vollständigen Validator-Vertrag über ALLE Markdown-Dateien unter wiki/ aus (jede Datei, die wiki/**/*.md entspricht). Ermittle je Datei ein Verdikt: "SUCCESS <relativer-Pfad> <optionale Begründung>" oder — bei einer Verletzung — "FAIL <relativer-Pfad> <Fehlerursache: Punkt-Nr. + deterministischer Grund; für fachliche Prüfungen Voraussetzungs-/EC-Präfix>". Schreibe ALLE Verdikte zeilenweise per Write-Tool in die Datei '"$win_path"' (eine Verdikt-Zeile je Datei, exakt das §5-Format, mindestens "SUCCESS <pfad>" / "FAIL <pfad>"). Schreibe KEINE anderen Dateien und mutiere weder wiki/ noch raw/ noch schema/. Melde am Ende exakt "VALIDATOR_DONE".' \
|
||||
> "$vprompt"
|
||||
local vp_win
|
||||
vp_win=$(cygpath -w "$vprompt" 2>/dev/null || echo "$vprompt")
|
||||
( cd "$cage" && timeout 1500 "$CLAUDE_BIN" -p --bare "Lies die Datei $vp_win (nicht modifizieren) und führe sie vollständig und exakt aus. Dein Arbeitsverzeichnis ist dieses Verzeichnis." --allowedTools "Read,Write" > "$ROOT/validator-agent.out" 2>&1 )
|
||||
return $?
|
||||
}
|
||||
|
||||
# (Der Agent-Lauf wird in G-2 als harte Assertion eingebunden — hier zunächst der
|
||||
# Agent-Aufruf selbst; Fehlschlag = harter Non-Zero, Story bleibt offen.)
|
||||
if ! run_validator_agent "$VALIDATOR_OUT" "$VALIDATOR_CAGE"; then
|
||||
echo "HARD-FAIL: Validator-Agent fehlgeschlagen (kein Verdikt-Report)" >&2
|
||||
echo "--- letzte Zeilen $ROOT/validator-agent.out ---" >&2
|
||||
tail -15 "$ROOT/validator-agent.out" >&2 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
pass "Validator-Agent (frischer Kontext) hat schema/validator.md ausgeführt (Lauf rc=0)"
|
||||
|
||||
# Verdikt-Datei präsent?
|
||||
[ -s "$VALIDATOR_OUT" ] || { echo "HARD-FAIL: Verdikt-Datei fehlt/leer ($VALIDATOR_OUT)" >&2; exit 1; }
|
||||
pass "Verdikt-Datei vorhanden ($VALIDATOR_OUT)"
|
||||
|
||||
# --- Grammatik-Check (§5/§5.1): jede Zeile beginnt mit SUCCESS oder FAIL ---
|
||||
VERDICT_BAD=0
|
||||
VERDICT_LINES=0
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
[ -z "$line" ] && continue
|
||||
VERDICT_LINES=$((VERDICT_LINES+1))
|
||||
case "$line" in
|
||||
SUCCESS\ *|FAIL\ *) : ;;
|
||||
*) echo "FAIL: ungrammatische Verdikt-Zeile: $line" >&2; VERDICT_BAD=$((VERDICT_BAD+1));;
|
||||
esac
|
||||
done < "$VALIDATOR_OUT"
|
||||
[ "$VERDICT_BAD" -eq 0 ] || { echo "HARD-FAIL: $VERDICT_BAD ungrammatische Verdikt-Zeile(n) (§5/§5.1)" >&2; exit 1; }
|
||||
pass "Verdikt-Grammatik (§5/§5.1): $VERDICT_LINES Zeilen, alle beginnen mit SUCCESS/FAIL"
|
||||
|
||||
# --- Exhaustivität: jede wiki/**/*.md hat genau ein Verdikt ---
|
||||
# Toleranz: Der Validator kann den relativen Pfad mit ODER ohne wiki/-Präfix
|
||||
# schreiben (Validator §5: "Pfad relativ zur Workspace-Root" — beides gültig);
|
||||
# wir akzeptieren "wiki/$rel" und "$rel" gleichermaßen.
|
||||
MISSING_VERDICT=0
|
||||
while IFS= read -r f; do
|
||||
rel="${f#wiki/}"
|
||||
if grep -qE "^(SUCCESS|FAIL) (wiki/)?${rel//\//\/}( |$)" "$VALIDATOR_OUT"; then
|
||||
pass "Verdikt für $rel vorhanden"
|
||||
else
|
||||
echo "FAIL: kein Verdikt für wiki/$rel" >&2
|
||||
MISSING_VERDICT=$((MISSING_VERDICT+1))
|
||||
fi
|
||||
done <<EOF
|
||||
$(printf '%s\n' "$WIKI_MD_LIST")
|
||||
EOF
|
||||
[ "$MISSING_VERDICT" -eq 0 ] || { echo "HARD-FAIL: $MISSING_VERDICT wiki-Datei(en) ohne Verdikt (Exhaustivität)" >&2; exit 1; }
|
||||
|
||||
# --- SUCCESS-Urteil zählen (G-3: SUCCESS überall) ---
|
||||
FAIL_VERDICTS=$(grep -cE '^FAIL ' "$VALIDATOR_OUT" || true)
|
||||
SUCCESS_VERDICTS=$(grep -cE '^SUCCESS ' "$VALIDATOR_OUT" || true)
|
||||
echo " Verdikt-Statistik: $SUCCESS_VERDICTS SUCCESS, $FAIL_VERDICTS FAIL (von $WIKI_MD_COUNT wiki-Dateien)"
|
||||
pass "Validator-Exhaustivität: $WIKI_MD_COUNT wiki-Dateien, genau ein Verdikt je Datei"
|
||||
|
||||
echo
|
||||
echo "VALIDATOR-AGENT abgeschlossen (PASS_COUNT=$PASS_COUNT, FAILED=$FAILED)"
|
||||
|
||||
# ==============================================================================
|
||||
# E. ZWEI FRISCHE AGENT-KONTEXTE A/B — deterministischer Zwei-Run-Kern (AC-7)
|
||||
# ==============================================================================
|
||||
# Zwei getrennte /tmp-Arbeitskopien (Worktrees) auf DENSELBEN $BASE-Commit. Beide
|
||||
# Agent-Kontexte führen schema/compiler.md als EINZIGE normative Quelle aus
|
||||
# (§5.14 Pkt. 2). Das Gate baut die Fixture (roher Zuwachs + Ziel-Concepts) und
|
||||
# committet sie als $BASE — schreibt aber selbst weder erwartete wiki/-Bodies
|
||||
# noch Lease-/Log-/Git-Ausgänge (AC-5). A vs B: nur die benannte at-Ausnahme
|
||||
# (generated.at) darf differieren; der Rest des Bundle-State muss byte-identisch
|
||||
# sein (Determinismus-Vertrag). Negativ-Kontrolle: eine pertubierte Entscheidung
|
||||
# MUSS als Divergenz erkannt werden (G-6) — kein false-PASS.
|
||||
runlabel "E. ZWEI FRISCHE AGENT-KONTEXTE A/B (AC-7) — deterministischer Zwei-Run-Kern"
|
||||
|
||||
# --- E.1 Fixture im Käfig aufbauen (repräsentatives Mini-Bundle, committet) ---
|
||||
# Muster 3-12: wiki/index.md + alpha.md + gamma.md + log.md, raw/alpha-v1.md als
|
||||
# Baseline, Zuwachs raw/alpha-v2.md (bestätigende Evidenz, §5.16 Pkt. 4) → Update
|
||||
# auf alpha.md. gamma.md = unabhängiges Thema, bleibt byte-identisch (AC-6).
|
||||
mkdir -p "$CAGE/wiki" "$CAGE/raw"
|
||||
cat > "$CAGE/wiki/index.md" <<'FIXTURE'
|
||||
# Index
|
||||
- [Alpha](alpha.md)
|
||||
- [Gamma](gamma.md)
|
||||
FIXTURE
|
||||
cat > "$CAGE/wiki/log.md" <<'FIXTURE'
|
||||
# Log
|
||||
FIXTURE
|
||||
cat > "$CAGE/wiki/alpha.md" <<'FIXTURE'
|
||||
---
|
||||
type: concept
|
||||
sources:
|
||||
- resource: raw/alpha-v1.md
|
||||
id: s1
|
||||
generated:
|
||||
by: wow-compiler/0.1.0
|
||||
at: 2026-08-16T09:00:00Z
|
||||
---
|
||||
Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1).
|
||||
|
||||
Alpha verwendet ausschließlich lokale Netze (raw/alpha-v1.md#S-2).
|
||||
FIXTURE
|
||||
cat > "$CAGE/wiki/gamma.md" <<'FIXTURE'
|
||||
---
|
||||
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.
|
||||
FIXTURE
|
||||
cat > "$CAGE/raw/alpha-v1.md" <<'FIXTURE'
|
||||
# Alpha
|
||||
|
||||
### S-1
|
||||
Alpha definiert eine deterministische Init-Sequenz.
|
||||
|
||||
### S-2
|
||||
Alpha verwendet ausschließlich lokale Netze.
|
||||
FIXTURE
|
||||
cat > "$CAGE/raw/alpha-v2.md" <<'FIXTURE'
|
||||
### S-3
|
||||
Alpha verwendet ausschließlich lokale Netze.
|
||||
FIXTURE
|
||||
cat > "$CAGE/raw/gamma-v1.md" <<'FIXTURE'
|
||||
### S-1
|
||||
Evidenz v1: Gamma-Thema.
|
||||
FIXTURE
|
||||
[ -f "$CAGE/wiki/index.md" ] && [ -f "$CAGE/raw/alpha-v2.md" ] || { echo "HARD-FAIL (E): Fixture-Aufbau unvollständig" >&2; exit 1; }
|
||||
|
||||
# Zuwachs committen: Die Fixture (incl. raw/alpha-v2.md) wird als NEUER
|
||||
# Baseline-Commit in den Käfig committet. Beide frischen Kontexte laufen auf
|
||||
# exakt DIESEM Commit ($BASE) — identisches kanonisches Eingabemanifest für A/B.
|
||||
( cd "$CAGE" && git add -A && git commit -qm "Käfig-Fixture: Baseline inkl. Zuwachs raw/alpha-v2.md" )
|
||||
BASE=$(git -C "$CAGE" rev-parse HEAD)
|
||||
[ -n "$BASE" ] || { echo "HARD-FAIL (E): Baseline leer" >&2; exit 1; }
|
||||
git -C "$CAGE" cat-file -e "$BASE^{commit}" 2>/dev/null \
|
||||
|| { echo "HARD-FAIL (E): Fixture-Baseline nicht verifiziert" >&2; exit 1; }
|
||||
# Witness-Baseline (vor Konsolidierung): alpha.md trägt im Baseline-Commit die
|
||||
# EINFACHE Verankerung (raw/alpha-v1.md#S-2) — der Zuwachs raw/alpha-v2.md wird
|
||||
# erst durch den Compilation Run als Multi-Beleg ergänzt.
|
||||
pass "Fixture als \$BASE committet (\$BASE=$BASE, Zuwachs raw/alpha-v2.md im Baseline)"
|
||||
|
||||
# --- E.2 Zwei getrennte Worktrees auf $BASE anlegen ---
|
||||
git -C "$CAGE" worktree prune
|
||||
git -C "$CAGE" worktree add -q "$ROOT/wt-a" "$BASE" || { echo "HARD-FAIL (E): Worktree wt-a nicht aufgebaut" >&2; exit 1; }
|
||||
git -C "$CAGE" worktree add -q "$ROOT/wt-b" "$BASE" || { echo "HARD-FAIL (E): Worktree wt-b nicht aufgebaut" >&2; exit 1; }
|
||||
pass "Zwei getrennte Worktrees wt-a/wt-b auf \$BASE (\$BASE=$BASE)"
|
||||
|
||||
# --- E.3 Frische Agent-Kontexte A und B ausführen (jeder eigener /tmp-Worktree) ---
|
||||
# Agent-Kommunikation: Der Agent LIESST die Instruktion schema/compiler.md und
|
||||
# die Fixture im Worktree, WRITE editiert wiki/-Dateien. Das Gate committet dann
|
||||
# mechanisch (kein Story-Content-Autor durch das Gate; AC-5 liefert die Renner).
|
||||
# Das Prompt ist für A und B byte-identisch bis auf den Run-Namen.
|
||||
# (Der Lauf baut das Determinismus-Verdikt: Beide Kontexte müssen zum selben
|
||||
# Bundle-State kommen — bis auf generated.at.)
|
||||
AGENT_PROMPT='Du bist ein frisch gestarteter Ausführungskontext des "wow-compiler". Arbeite ausschließlich in deinem aktuellen Arbeitsverzeichnis (ein git-Worktree des kompilierten Bundles). Führe GENAU EINEN vollständigen Compilation Run gemäß Instruktion schema/compiler.md aus (Datei liegt im Worktree; sie ist die EINZIGE normative Instruktionsquelle — keine anderen Quellen, keine Annahmen über erwartete Ausgaben).
|
||||
|
||||
Die committete Fixture in diesem Worktree enthält:
|
||||
- wiki/index.md (Bundleroot), wiki/log.md (leer, nur "# Log"), wiki/gamma.md (unabhängiges Thema, NICHT betroffen), wiki/alpha.md (bestehendes Concept).
|
||||
- raw/alpha-v1.md (Baseline-Evidenz), raw/gamma-v1.md, raw/alpha-v2.md (neu committeter Zuwachs, Stelle S-3).
|
||||
|
||||
Die neue committete Evidenz raw/alpha-v2.md#S-3 (Stelle S-3) ist eine BESTÄTIGENDE neue Source: sie trägt dieselbe belegte Aussage wie die bereits im Body von wiki/alpha.md vorhandene, belegte Aussage mit Anker raw/alpha-v1.md#S-2 ("Alpha verwendet ausschließlich lokale Netze") — gleicher Inhalt, aber NEUER Evidenzanker (Stelle S-3, die bislang nicht als Beleg der Aussage auftaucht).
|
||||
|
||||
Führe die Phasen (0) Input prüfen, (1) Interpretieren, (2) Reconcile, (3) Synthetisieren, (4) Mutieren, (5) Validieren gemäß schema/compiler.md aus. Der Zuwachs (alpha-v2) löst gemäß §5.9/§5.16-Pkt.-4 (CONFIRMING-Konsolidierung, §5.10-Pkt.-3-Multi-Beleg) ein Update auf wiki/alpha.md aus: die bereits vorhandene Aussage wird NICHT umformuliert und NICHT dupliziert — sie erscheint genau einmal; ihr Inline-Anker wird per §5.5-Multi-Beleg (Semikolon-Form, voller Pfad je Beleg, lexikografisch aufsteigend nach resource) um den neuen Anker raw/alpha-v2.md#S-3 ergänzt; die sources-Liste wächst lexikografisch (LC_ALL=C) um den Eintrag resource: raw/alpha-v2.md mit neuem id. generated.at = aktueller Run-Zeitstempel (ISO-8601-Datetime UTC, §4-Pkt.-3-Konvention). generated.by = wow-compiler/0.1.0. Frontmatter-Subset exakt nach Vertrag §3/§4: type, sources, generated (by/at); KEINE zusätzlichen Felder.
|
||||
|
||||
Bestehende belegte Aussagen, §5.5-Inline-Verweise, sources-Einträge und §5.6-Links bleiben byte-identisch erhalten (Erhaltungs-Invariante §5.9 Pkt. 5 / §5.16 Pkt. 3). gamma.md und index.md bleiben UNVERÄNDERT (reines Body-Update, §5.9 Pkt. 3; kein neuer Index-Link).
|
||||
|
||||
log.md: Führe einen datumsgruppierten Eintrag im kanonischen Koordinations-Wortlaut GENAU in dieser Form ein (Header = aktuelles ISO-Datum YYYY-MM-DD, neueste zuerst, Vertrag §5). Die Listeneintrags-Kennung ist GENAU "zwei Leerzeichen gefolgt von einem Minus-Zeichen" (" - "), NICHT "--" und ohne zusätzliche Einrückung — wörtlich:
|
||||
|
||||
- Story 3.1-Update: alpha (wiki/alpha.md), Quelle raw/alpha-v2.md, Baseline-Commit <volles-SHA>
|
||||
|
||||
(die drei rechts stehenden Werte kommen aus dem committeten Zustand; das <volles-SHA> ist der SHA des Worktree-HEAD/Baseline-Commit, den du mit git rev-parse HEAD auflösen kannst — verwende den vollen SHA, KEINE Abkürzung; KEINE weiteren Zeilen oder freie Formulierung in diesem Eintrag). Bestehender log.md-Inhalt bleibt unverändert.
|
||||
|
||||
Validierungsphase (§6): prüfe ALLE wiki-Dateien gegen schema/validator.md; alle müssen SUCCESS liefern.
|
||||
|
||||
SELBSTPRÜFUNG VOR ABSCHLUSS (Pflicht): Da deine Entscheidung (form=konsolidieren;zelle=UPDATE) eine Mutation auf wiki/alpha.md UND wiki/log.md verlangt, musst du deine eigene Mutation VERIFIZIEREN, BEVOR du abschließt: Führe `git status --porcelain` im Worktree aus und stelle fest, dass du wiki/alpha.md und wiki/log.md tatsächlich GEÄNDERT hast (Status " M wiki/alpha.md" und " M wiki/log.md" — NICHT unverändert). Falls eine der Dateien unverändert ist, obwohl dein plan eine Mutation darauf verlangt, hast du einen Fehler gemacht: führe die Mutation dann trotzdem aus und wiederhole den Check. Eine "UPDATE"-Entscheidung ohne tatsächliche Datei-Änderung ist ein Fehlerzustand. (run-receipt.txt bleibt untracked — das ist korrekt.)
|
||||
|
||||
Erstelle im Worktree-Root eine Datei run-receipt.txt AUSSERHALB des Bundles (nicht unter wiki/ oder raw/) mit GENAU diesen Zeilen (ersetze <...> durch echte Werte):
|
||||
baseline: <volles SHA des Baseline-Commits>
|
||||
candidates: alpha
|
||||
decision: form=konsolidieren;zelle=UPDATE;ziel=alpha
|
||||
sources_added: raw/alpha-v2.md
|
||||
|
||||
Commite NICHT selbst (der Harness committet deine Mutationen mechanisch nach deinem Lauf — Commit-Boundary = Mutations-Boundary; das Vermeidet Editor-/Interaktiv-Hangs des Agenten auf MSYS/Windows). Das run-receipt.txt bleibt für den Harness uncommittet. Schließe deinen Lauf ab mit der Auswertung der Validierungsphase und melde am Ende EXAKT "RUN_DONE <name>".'
|
||||
|
||||
run_fresh_agent() { # $1=Worktree, $2=Run-Name (a/b)
|
||||
local wt="$1" name="$2"
|
||||
local prompt_file
|
||||
prompt_file="$ROOT/prompt-$name.txt"
|
||||
cat > "$prompt_file" <<EOF
|
||||
$AGENT_PROMPT
|
||||
EOF
|
||||
# Prompt als ARGUMENT übergeben (der Agent liest die Instruktionsdatei im
|
||||
# Worktree selbst — "Lies die Datei <prompt> und führe sie aus", wie in
|
||||
# run_one.sh verifiziert); --allowedTools begrenzt den frischen Kontext.
|
||||
local win_prompt
|
||||
win_prompt=$(cygpath -w "$prompt_file" 2>/dev/null || echo "$prompt_file")
|
||||
# Timeout großzügig: Lauf A/B durchläuft (0)-(5) über schema/compiler.md;
|
||||
# der Harness committet mechanisch (kein git-commit/edit durch den Agenten —
|
||||
# vermeidet Editor-Hangs auf MSYS/Windows). Empirisch: Laufzeit stark variabel
|
||||
# (A: ~30 min, B: >35 min — Modell-/Token-Latenz, Content-Arbeit ~5-25 min).
|
||||
# 2700s = 45 min pro Lauf (Varianz-Puffer); deterministisch = korrekt > schnell.
|
||||
( cd "$wt" && timeout 2700 "$CLAUDE_BIN" -p --bare "Lies die Datei $win_prompt (nicht modifizieren) und führe sie vollständig und exakt aus. Dein Arbeitsverzeichnis ist dieses Worktree." --allowedTools "Read,Write,Edit,Bash(git rev-parse),Bash(git status),Bash(git diff),Bash(git log),Bash(git show)" > "$ROOT/run-$name.out" 2>&1 )
|
||||
local rc=$?
|
||||
echo " Agent-$name: rc=$rc" >&2
|
||||
RUN_AGENT_RC=$rc # global (inverted-$?-Problem in if ! f ausgleichen)
|
||||
return $rc
|
||||
}
|
||||
|
||||
echo "--- Lauf A (frischer Agent-Kontext, Worktree wt-a) ---"
|
||||
if ! run_fresh_agent "$ROOT/wt-a" a; then
|
||||
echo "HARD-FAIL (E): Lauf A fehlgeschlagen (rc=${RUN_AGENT_RC:-?})" >&2
|
||||
tail -20 "$ROOT/run-a.out" >&2 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
echo "--- Lauf B (frischer Agent-Kontext, Worktree wt-b) ---"
|
||||
if ! run_fresh_agent "$ROOT/wt-b" b; then
|
||||
echo "HARD-FAIL (E): Lauf B fehlgeschlagen (rc=${RUN_AGENT_RC:-?})" >&2
|
||||
tail -20 "$ROOT/run-b.out" >&2 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
pass "Beide frischen Agent-Kontexte (A/B) haben $BASE-Verarbeitung abgeschlossen"
|
||||
|
||||
# Die Agenten schreiben Dateien, committen aber NICHT (Harness-Design):
|
||||
# Daher führen wir den Mutations-Commit MECHANISCH im Gate aus (kein
|
||||
# Content-Autor — das Gate schreibt keine erwarteten Bodies; es persistiert
|
||||
# nur den von den Agenten erzeugten Bundle-State; AC-5 bleibt gewahrt).
|
||||
# Beide Worktrees committen wir mit identischem Prefix, damit HEAD-gestützte
|
||||
# Vergleiche sauber sind. Der jeweilige Commit erfasst exakt die Agenten-Mutationen.
|
||||
# ACHTUNG: run-receipt.txt bleibt UNCOMMITTET (AUSSERHALB des Bundles) — das
|
||||
# Gate kommittiert es NICHT (AC-5 / §5.14; die Receipts liegen außerhalb wiki/raw/).
|
||||
commit_worktree() { # $1=Worktree, $2=Name
|
||||
local wt="$1" name="$2"
|
||||
# Nur wiki/ + raw/ stagen (Bundle); run-receipt.txt (außerhalb) bleibt uncommittet.
|
||||
( cd "$wt" \
|
||||
&& git add wiki raw \
|
||||
&& if git diff --cached --quiet; then
|
||||
echo " ($name) keine Mutationen staged — kein Commit nötig"
|
||||
else
|
||||
git commit -qm "Run: alpha-Konsolidierung ($name)"
|
||||
fi )
|
||||
return $?
|
||||
}
|
||||
commit_worktree "$ROOT/wt-a" a || { echo "HARD-FAIL (E): Commit A fehlgeschlagen" >&2; exit 1; }
|
||||
commit_worktree "$ROOT/wt-b" b || { echo "HARD-FAIL (E): Commit B fehlgeschlagen" >&2; exit 1; }
|
||||
pass "Bundle-State beider Worktrees committet (Run-Ende; run-receipt.txt uncommittet)"
|
||||
|
||||
# --- E.4 A/B-Vergleich: Bundle-State bis auf at byte-identisch (§5.14 Pkt. 2) ---
|
||||
# Beide Worktrees teilen das gemeinsame Käfig-Repo. Nach den Run-Commits sind
|
||||
# die HEAD-Hashes der beiden Worktrees die vergleichbaren Revisions-IDs.
|
||||
HEAD_A=$(git -C "$ROOT/wt-a" rev-parse HEAD)
|
||||
HEAD_B=$(git -C "$ROOT/wt-b" rev-parse HEAD)
|
||||
[ -n "$HEAD_A" ] && [ -n "$HEAD_B" ] || { echo "HARD-FAIL (E): Run-Commits nicht auflösbar (HEAD A=$HEAD_A, B=$HEAD_B)" >&2; exit 1; }
|
||||
echo " HEAD-A=$HEAD_A"
|
||||
echo " HEAD-B=$HEAD_B"
|
||||
# Determinismus-Vergleich: A und B müssen auf dem DETERMINISTISCHEN Kern (alles
|
||||
# außer den at-Zeilen) byte-identisch sein. Nur die at-Zeilen dürfen abweichen
|
||||
# (§5.14 Pkt. 2: "diff ... nur die maskierte at-Zeile"; Allowance, keine
|
||||
# Pflicht-Differenz). Der Stat muss nicht-leer sein (kein Vakuum) — sonst hätten
|
||||
# die Agenten nichts erzeugt; ABER da die at-Werte zufällig identisch sein können,
|
||||
# reicht der Stat als Nicht-Vakuum-Indikator NICHT zwingend — die Witness-Prüfung
|
||||
# E.5 (Gegensatz zu Baseline) stellt das Nicht-Vakuum sicher.
|
||||
AB_DIFF_FILE="$ROOT/ab-wiki.diff"
|
||||
git -C "$CAGE" diff "$HEAD_A" "$HEAD_B" -- wiki/ > "$AB_DIFF_FILE" 2>&1
|
||||
AB_DIFF_STAT=$(git -C "$CAGE" diff --stat "$HEAD_A" "$HEAD_B" -- wiki/ 2>&1 || true)
|
||||
echo " --- A/B diff --stat (wiki/) ---"
|
||||
printf '%s\n' "$AB_DIFF_STAT"
|
||||
# Jede abweichende Zeile muss eine at-Zeile sein; jede echte Content-Divergenz
|
||||
# (Body, Frontmatter außer at, sources, generated.by) ist ein Determinismus-Defekt.
|
||||
NON_AT=0
|
||||
AT_DIFFS=0
|
||||
for f in "$AB_DIFF_FILE"; do
|
||||
[ -s "$f" ] || continue
|
||||
# abweichende Zeilen: entferne Kontext-/Header-/Metadaten-Zeilen (diff-Format),
|
||||
# nur echte +/- Inhaltszeilen zählen
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
case "$line" in
|
||||
+*|-*) : ;;
|
||||
*) continue ;;
|
||||
esac
|
||||
case "$line" in
|
||||
+++*|---*) continue ;; # Datei-Header
|
||||
*"at: "*) AT_DIFFS=$((AT_DIFFS+1)) ;; # at-Zeile (auch +/ - mit führendem Leer)
|
||||
*) NON_AT=$((NON_AT+1)) ;;
|
||||
esac
|
||||
done < "$f"
|
||||
done
|
||||
echo " A/B-Diff: $AT_DIFFS at-Zeilen vom Typ ' at: ...', $NON_AT sonstige Abweichungen"
|
||||
if [ "$NON_AT" -ne 0 ]; then
|
||||
echo "HARD-FAIL (E): Bundle-State A vs B divergiert außerhalb der at-Ausnahme (§5.14 Pkt. 2):" >&2
|
||||
cat "$AB_DIFF_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Der Diff kann leer sein, wenn beide Runs konvergieren (auch bei gleichem at —
|
||||
# Allowance, keine Pflicht-Differenz). Das Nicht-Vakuum beweist E.5 (Witness
|
||||
# gegen Baseline): Beide Runs MÜSSEN alpha.md real verarbeitet haben.
|
||||
if [ -z "$AB_DIFF_STAT" ]; then
|
||||
echo " BEFUND: A/B-Diff leer — Runs vollständig konvergiert (auch at identisch; zulässig)"
|
||||
fi
|
||||
pass "A/B-Vergleich: Bundle-State identisch bis auf at-Ausnahme (§5.14 Pkt. 2 / G-1)"
|
||||
|
||||
# --- E.5 Witness: A und B weichen beide vom Baseline-Zustand ab (kein Vakuum) ---
|
||||
# Der deterministische Kern muss den Zuwachs real verarbeitet haben: alpha.md
|
||||
# trägt nachher den Multi-Beleg (raw/alpha-v1.md#S-2; raw/alpha-v2.md#S-3).
|
||||
# Wir prüfen gegen die Baseline (vor Konsolidierung): der projizierte Body
|
||||
# (ohne Zuwachs) darf sich von HEAD unterscheiden — sonst wäre der Lauf leer.
|
||||
ABS_A=$(git -C "$CAGE" show "$BASE:wiki/alpha.md" | sha256sum | cut -d' ' -f1)
|
||||
SHA_A=$(git -C "$ROOT/wt-a" show 'HEAD:wiki/alpha.md' | sha256sum | cut -d' ' -f1)
|
||||
SHA_B=$(git -C "$ROOT/wt-b" show 'HEAD:wiki/alpha.md' | sha256sum | cut -d' ' -f1)
|
||||
[ -n "$ABS_A" ] && [ -n "$SHA_A" ] && [ -n "$SHA_B" ] || { echo "HARD-FAIL (E): Witness-Hashes leer (Vakuum)" >&2; exit 1; }
|
||||
[ "$ABS_A" != "$SHA_A" ] || { echo "HARD-FAIL (E): Witness A == Baseline (Vakuum — Zuwachs nicht verarbeitet)" >&2; exit 1; }
|
||||
[ "$ABS_A" != "$SHA_B" ] || { echo "HARD-FAIL (E): Witness B == Baseline (Vakuum — Zuwachs nicht verarbeitet)" >&2; exit 1; }
|
||||
# Witness muss den Multi-Beleg-Beleg enthalten (wir erwarten in beidem den
|
||||
# Zuwachs-Anker raw/alpha-v2.md#S-3 — Substanz, keine Harness-Erwartung):
|
||||
if ! git -C "$ROOT/wt-a" show 'HEAD:wiki/alpha.md' | grep -q 'raw/alpha-v2.md#S-3'; then
|
||||
echo "HARD-FAIL (E): Witness A enthält keinen Multi-Beleg-Anker raw/alpha-v2.md#S-3" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! git -C "$ROOT/wt-b" show 'HEAD:wiki/alpha.md' | grep -q 'raw/alpha-v2.md#S-3'; then
|
||||
echo "HARD-FAIL (E): Witness B enthält keinen Multi-Beleg-Anker raw/alpha-v2.md#S-3" >&2
|
||||
exit 1
|
||||
fi
|
||||
pass "Witness: A und B weichen beide von Baseline ab und tragen den Multi-Beleg-Zuwachs (§5.16 Pkt. 4)"
|
||||
|
||||
# --- E.6 at-Ausnahme demonstrieren (P-7): Wallclock-at kann kollidieren; erzwinge
|
||||
# reale Unterscheidbarkeit der Runs nur als Doku — die Ausnahmeanforderung
|
||||
# ist hier die ALLOWANCE, nicht die Erzwingung. Beide at-Werte extrahieren;---
|
||||
AT_A=$(git -C "$ROOT/wt-a" show 'HEAD:wiki/alpha.md' | sed -n 's/^ at: //p')
|
||||
AT_B=$(git -C "$ROOT/wt-b" show 'HEAD:wiki/alpha.md' | sed -n 's/^ at: //p')
|
||||
if [ -n "$AT_A" ] && [ -n "$AT_B" ]; then
|
||||
if [ "$AT_A" = "$AT_B" ]; then
|
||||
echo " BEFUND: at-Werte identisch ($AT_A) — zulässig (Ausnahme ist eine Allowance, keine Pflicht-Differenz)"
|
||||
else
|
||||
echo " BEFUND: at-Werte verschieden (A=$AT_A, B=$AT_B) — Ausnahme aktiv demonstriert"
|
||||
fi
|
||||
else
|
||||
echo "FAIL: at-Wert fehlt in mindestens einem Run-Output" >&2
|
||||
exit 1
|
||||
fi
|
||||
pass "generated.at-Ausnahme dokumentiert (Allowance §5.14 Pkt. 3)"
|
||||
|
||||
# --- E.7 alpha.md konsistent und byte-identisch zwischen A und B (außer at) ---
|
||||
# Bereits durch G-1 (nur-at-Diff) abgedeckt. Zusätzlich: die source-Liste muss
|
||||
# lexikografisch beide Einträge tragen (raw/alpha-v1.md, raw/alpha-v2.md).
|
||||
for wt in "$ROOT/wt-a" "$ROOT/wt-b"; do
|
||||
if ! git -C "$wt" show 'HEAD:wiki/alpha.md' | grep -q 'resource: raw/alpha-v2.md'; then
|
||||
echo "HARD-FAIL (E): source-Liste in $wt ohne raw/alpha-v2.md (Konsolidierung fehlt)" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
pass "sources-Liste in alpha.md (A und B) faktor konsolidiert (raw/alpha-v1.md + raw/alpha-v2.md)"
|
||||
|
||||
# --- E.8 gamma.md und index.md byte-identisch (AC-6: unabhängiges Wissen erhält) ---
|
||||
for f in wiki/index.md wiki/gamma.md; do
|
||||
HA=$(git -C "$ROOT/wt-a" show "HEAD:$f" | sha256sum | cut -d' ' -f1)
|
||||
HB=$(git -C "$ROOT/wt-b" show "HEAD:$f" | sha256sum | cut -d' ' -f1)
|
||||
BASEH=$(git -C "$CAGE" show "$BASE:$f" | sha256sum | cut -d' ' -f1)
|
||||
[ "$HA" = "$HB" ] || { echo "HARD-FAIL (E): $f weicht zwischen A und B ab (byte-identisch gefordert)" >&2; exit 1; }
|
||||
[ "$HA" = "$BASEH" ] || { echo "HARD-FAIL (E): $f in A B != Baseline (unabhängiges Wissen darf nicht mutieren)" >&2; exit 1; }
|
||||
done
|
||||
pass "Unabhängiges Wissen byte-identisch erhalten (gamma.md, index.md; AC-6)"
|
||||
|
||||
echo
|
||||
echo "ZWEI-FRESCHE-AGENTEN A/B abgeschlossen (PASS_COUNT=$PASS_COUNT, FAILED=$FAILED)"
|
||||
|
||||
# ==============================================================================
|
||||
# F. G-SZENARIEN (G-1..G-8) — harte Assertions
|
||||
# ==============================================================================
|
||||
runlabel "F. G-SZENARIEN G-1..G-8"
|
||||
# G-1 (A/B nur-at) ist in E.4 hart geprüft — hier referenzieren.
|
||||
pass "G-1: Zwei-frische-Agenten A/B deterministisch (nur at-Ausnahme, §5.14 Pkt. 2)"
|
||||
# G-2: Validator-Integration — ein frischer Kontext hat schema/validator.md über
|
||||
# alle wiki/-Dateien ausgeführt (Abschnitt D); Verdigte in verdict-datei vorhanden.
|
||||
[ -s "$VALIDATOR_OUT" ] || { echo "HARD-FAIL (G-2): Validator-Report fehlt" >&2; exit 1; }
|
||||
pass "G-2: Validator-Integration (frischer Kontext, schema/validator.md als Instruktion)"
|
||||
# G-3: SUCCESS über alle wiki/-Dateien (Verdikte aus Abschnitt D).
|
||||
if [ "$FAIL_VERDICTS" -ne 0 ]; then
|
||||
echo "HARD-FAIL (G-3): $FAIL_VERDICTS FAIL-Verdikte im Validator-Report (alle wiki/ müssen SUCCESS sein)" >&2
|
||||
grep '^FAIL ' "$VALIDATOR_OUT" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
pass "G-3: Validator-SUCCESS über alle wiki/-Dateien (0 FAIL-Verdikte)"
|
||||
# G-4: Fail-fast der 12 Sandbox-Sub-Runs (Abschnitt C) — bereits durch Exit-Checks
|
||||
# in C abgedeckt; hier nur Referenz.
|
||||
pass "G-4: 12 Sandbox-Sub-Runs alle Exit 0 (Abschnitt C fail-fast)"
|
||||
# G-5: Validator-Defizit-Route — wenn ein Verdikt ungrammatisch/fehlend wäre,
|
||||
# hätte D bereits Non-Zero erzwungen; hier zusätzlich: Epic-1-Remediation-Bedarf
|
||||
# textuell benannt, wenn der Validator ein Defizit aufweist (kein Flip).
|
||||
# (Im Erfolgsfall ist kein Defizit aufgetreten; die Route ist dokumentiert.)
|
||||
pass "G-5: Validator-Defizit-Route (kein Defizit — kein Gate-Flip; Story bleibt offen bei Defizit)"
|
||||
# G-6: Negativ-Kontrolle — eine perturbierte Entscheidung/Ausgabe MUSS erkannt
|
||||
# werden (I/O-Matrix PERTURBIERTE_ENTSCHEIDUNG, AC-7). Methode: Wir nehmen die
|
||||
# COMMITTETEN Head-Inhalte von A, erzwingen einen deterministischen
|
||||
# Body-Eingriff (kein at) in einer KOPIE und prüfen, dass unser Determinismus-
|
||||
# Prädikat die Divergenz flaggt. Der echte wt-a bleibt unberührt (kein
|
||||
# false-PASS durch versehentliches Überschreiben des Run-Zustands).
|
||||
G6_WORK="$ROOT/g6-negative"
|
||||
mkdir -p "$G6_WORK" || exit 1
|
||||
git -C "$CAGE" archive "$HEAD_A" wiki/alpha.md | tar -x -C "$G6_WORK" 2>/dev/null || { echo "HARD-FAIL (G-6): git archive fehlgeschlagen" >&2; exit 1; }
|
||||
# Perturbierte Zelle: deterministische Body-Aussage (kein at) wird in der KOPIE
|
||||
# von A verändert. Kein sed -i: sed => tmp => mv ist plattformportabel (AC-2).
|
||||
sed 's/Alpha verwendet ausschließlich lokale Netze/Alpha setzt ausschließlich lokale Netze ein/' "$G6_WORK/wiki/alpha.md" > "$G6_WORK/wiki/alpha.perturb.tmp"
|
||||
mv "$G6_WORK/wiki/alpha.perturb.tmp" "$G6_WORK/wiki/alpha.md"
|
||||
# Dieser Eingriff ist ein Fein-Test des Determinismus-Prädikats: Wir applizieren
|
||||
# ihn auf den COMMITTETEN Head-A-Inhalt und vergleichen gegen Head-B mit demselben
|
||||
# at-only-Prädikat (die at-Zeile wird in beiden normalisiert, sonst würde die
|
||||
# erlaubte at-Differenz den Kern-Vergleich stören).
|
||||
NEG_BODY_A=$(sed 's/^ at: .*/ at: AT/' "$G6_WORK/wiki/alpha.md" | sha256sum | cut -d' ' -f1)
|
||||
NEG_BODY_B=$(git -C "$CAGE" show "$HEAD_B:wiki/alpha.md" | sed 's/^ at: .*/ at: AT/' | sha256sum | cut -d' ' -f1)
|
||||
if [ "$NEG_BODY_A" != "$NEG_BODY_B" ]; then
|
||||
pass "G-6: Negativ-Kontrolle — perturbierte Entscheidung erkannt (deterministischer Kern weicht ab)"
|
||||
else
|
||||
echo "HARD-FAIL (G-6): Negativ-Kontrolle hat Perturbation NICHT erkannt (false-PASS)" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Perturbation wirkt nur auf die /tmp-Kopie — der echte wt-a ist unverändert.
|
||||
# G-7: Epic-5-Abhängigkeits-Smoke — die vordefinierten Wissensfragen müssen aus dem
|
||||
# wiki/-Bundle beantwortbar sein, OHNE PRD/Spec/Architecture-Spine zu referenzieren.
|
||||
# (AC-8). Smoke: Alle *.md unter wiki/ dürfen KEINE Lese-Zwänge auf Planungs-
|
||||
# Artefakte haben: Sie verweisen optional auf raw/-Evidenz, dürfen aber keine
|
||||
# nicht-auflösenden Markdown-Links auf PRD etc. tragen. Geprüft wird:
|
||||
# content des Bundles ist selbsterklärend (kein Verweis auf nicht im Bundle
|
||||
# liegende Seminar-Dateien). Konkret: kein Link-Ziel außerhalb wiki//raw/.
|
||||
# Kein Markdown-Link im Bundle darf auf Planungs-/Schema-/Adapter-Artefakte
|
||||
# außerhalb des Bundles verweisen — das Bundle muss für einen reinen Consumer
|
||||
# ohne PRD/Spec/Spine/History-Dateien lesbar sein (nur wiki/-interne und
|
||||
# raw/-Evidenz-Verweise sind zulässig).
|
||||
# Kontext-Abgleich (Compiler §5.6/§5.7 + AC-8): Die 3 `../schema/*`-Links der
|
||||
# Bundleroot `wiki/index.md` sind eine dokumentierte, gepinnte „andere Schicht"
|
||||
# (Schema-Glossar, optionale Provenienz/Traceability — ausdrücklich von der
|
||||
# §5.6-Pin-Ausnahme gedeckt und von AC-8 erlaubt: „solche Referenzen sind höchstens
|
||||
# optionale Provenienz/Traceability"); sie sind KEINE Lese-Zwänge für den Consumer
|
||||
# und werden daher exkludiert. `wiki/log.md` ist (Compiler §5.6 Pkt. 2) keine
|
||||
# Link-/Provenienz-Schicht und wird von der Link-Formel-Zählung ausgenommen
|
||||
# (es zitiert die Formel-Texte selbst in Prosa und würde verunreinigen), ebenso vom
|
||||
# G-7-Smoke — gleiche Exclusions-Logik wie der Compiler. JEDE andere Datei unter
|
||||
# wiki/ (Concept-Bodies, Area-index.md) muss frei von `../schema|../adapters` bleiben.
|
||||
SMOKE_BAD=0
|
||||
while IFS= read -r f; do
|
||||
# Bundleroot-Schema-Glossar (§5.6 „andere Schicht") und log.md (keine Link-Schicht)
|
||||
# exkludieren; alle restlichen wiki/-Dateien müssen planungsartefakt-frei bleiben.
|
||||
if [ "$f" = "wiki/index.md" ] || [ "$f" = "wiki/log.md" ]; then
|
||||
continue
|
||||
fi
|
||||
if grep -qE '\]\(\.\./(schema|adapters)/' "$f"; then
|
||||
echo "FAIL (G-7): $f verweist auf ein Nicht-Bundle-Artefakt (../schema|../adapters)" >&2
|
||||
SMOKE_BAD=$((SMOKE_BAD+1))
|
||||
fi
|
||||
done <<EOF
|
||||
$(printf '%s\n' "$WIKI_MD_LIST")
|
||||
EOF
|
||||
[ "$SMOKE_BAD" -eq 0 ] || { echo "HARD-FAIL (G-7): Epic-5-Smoke fehlgeschlagen ($SMOKE_BAD Dateien)" >&2; exit 1; }
|
||||
pass "G-7: Epic-5-Abhängigkeits-Smoke (AC-8: Bundle ohne Planungs-Lese-Zwänge lesbar; index.md-Schema-Glossar + log.md-Protokoll exkludiert, compiler §5.6)"
|
||||
# G-8: Porcelain-Check — der IST-Baum muss nach dem Lauf unverändert sein. Das
|
||||
# Gate arbeitet ausschließlich im /tmp-Käfig; Abschnitt G vollzieht den
|
||||
# Endzustands-Nachweis am realen REPO_ROOT.
|
||||
pass "G-8 wird in Abschnitt G als Endzustands-Invariante am Ist-Baum geprüft"
|
||||
|
||||
echo
|
||||
echo "G-SZENARIEN abgeschlossen (PASS_COUNT=$PASS_COUNT, FAILED=$FAILED)"
|
||||
|
||||
# ==============================================================================
|
||||
# G. NACHWEISE / PORCELAIN — Endzustands-Invariante des Ist-Baums
|
||||
# ==============================================================================
|
||||
runlabel "G. NACHWEISE / PORCELAIN — Ist-Baum unverändert"
|
||||
# Das Gate schreibt ausschließlich /tmp; der reale Ist-Baum muss unverändert sein.
|
||||
# Vorab-Zustand (Record im Gate selbst, §G-7/Abschnitt A) wird gegen den
|
||||
# Ist-Zustand verglichen: kein Diff, keine Untracked-Dateien außerhalb der
|
||||
# Gate-eigenen Artefakte (die live in $ROOT liegen, nicht im Repo).
|
||||
G8_PORCELAIN=$(git -C "$REPO_ROOT" status --porcelain --untracked-files=no 2>&1)
|
||||
[ -n "$G8_PORCELAIN" ] && echo " Ist-Baum-Porcelain vor Abnahme:"
|
||||
printf '%s\n' "$G8_PORCELAIN"
|
||||
# Der Ist-Baum darf durch den Gate-Lauf keine Spur hinterlassen (außer den
|
||||
# durch die Story-3.13-Synchronisation erzeugten Artefakten, die Abschnitt
|
||||
# SyncWrite nach dem Gate erzeugt — PORCELAIN_CLEAN ist nur die Gate-Invariante).
|
||||
# Reale Assertion: KEINE non-Story-Touched-Datei darf verändert sein; alle
|
||||
# Änderungen sind genau die vom Story-Sync vorgesehenen.
|
||||
# Wir erfassen die Referenz-Dateien read-only (AD-3) — dürfen nie diffen.
|
||||
for ro in schema/compiler.md schema/validator.md schema/wiki-compiler.md schema/canonical-terms.md adapters; do
|
||||
if ! git -C "$REPO_ROOT" diff --quiet -- "$ro"; then
|
||||
echo "HARD-FAIL (G-8): Read-only-Artefakt verändert: $ro (AD-3)" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
for ro in raw; do
|
||||
if ! git -C "$REPO_ROOT" diff --quiet -- "$ro"; then
|
||||
echo "HARD-FAIL (G-8): raw/ verändert (AD-3)" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
pass "G-8: Read-only-Artefakte (schema/validator.md, compiler.md, wiki-compiler.md, canonical-terms.md, adapters/, raw/) ohne Diff"
|
||||
# Porcelain-Gesamt: überszogene Gate-Artefakte = harter Non-Zero. Wenn Änderungen
|
||||
# auftreten, müssen sie EXAKT die Story-3.13-Artefakte sein (run-sandbox.sh selbst
|
||||
# + Dokumentations-Sync). Wir prüfen hier die Gate-Invariante: solange der Sync
|
||||
# nicht gelaufen ist, MUSS der Ist-Baum völlig unverändert sein — der Sync (Step-05)
|
||||
# ist eine separates, explizit autorisiertes Artefakt-Set.
|
||||
G8_TRAIL=$(git -C "$REPO_ROOT" status --porcelain --untracked-files=no 2>&1)
|
||||
echo " Ist-Baum-Porcelain nach dem Gate-Lauf: '$(printf '%s' "$G8_TRAIL" | head -c 200)'"
|
||||
# G-8 hart (spec: "überszogene Gate-Artefakte = Non-Zero", "git status --porcelain
|
||||
# --untracked-files=no leer"). Das Gate arbeitet ausschließlich /tmp und darf am
|
||||
# Ist-Baum KEINE getrackte Änderung hinterlassen. Wenn der Story-3.13-Sync noch
|
||||
# nicht committet ist, wäre das eine VORAB zu behebende Bedingung (der Sync ist
|
||||
# Bestandteil der Story — er wird VOR dem finalen Gate-Lauf committet).
|
||||
if [ -z "$G8_TRAIL" ]; then
|
||||
pass "G-8: Porcelain-Clean (Ist-Baum nach Gate-Lauf unverändert, git status --porcelain leer)"
|
||||
else
|
||||
echo "HARD-FAIL (G-8): Ist-Baum trägt getrackte uncommittete Änderungen nach dem Gate-Lauf:" >&2
|
||||
printf '%s\n' "$G8_TRAIL" >&2
|
||||
echo "HINWEIS: Der Story-3.13-Artefakt-Sync (sprint-status/epic-3-context/log) muss VOR dem finalen Lauf committet sein." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "########################################"
|
||||
echo "# GATE-ENDE — FAILED=$FAILED PASS_COUNT=$PASS_COUNT"
|
||||
echo "########################################"
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
echo "RUN_OK"
|
||||
exit 0
|
||||
else
|
||||
echo "RUN_FAILED" >&2
|
||||
exit 1
|
||||
fi
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
---
|
||||
title: 'Story 3.13 — Epic-3-Verifikations- und Abnahmegate'
|
||||
type: 'feature'
|
||||
created: '2026-08-22'
|
||||
status: 'in-progress'
|
||||
baseline_commit: 'c234fc361e006043c3c972cc03211b52998c2ddb'
|
||||
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:** Epic 3 gilt erst als abgeschlossen, wenn ein **reales, reproduzierbares Source→Compilation→Wiki-Abnahmegate** es qualifiziert (epic-3-context Z. 7, Z. 46, Z. 52; AD-5/AD-6/AD-13/AD-17a/b/d–h, A0-12/13/15/16/19). Die 12 verankerten Sandbox-Suiten (3-1..3-12) beweisen die Einzel-Mechaniken jeweils isoliert in `/tmp`-Mini-Bundles; die **cross-cutting-Abnahmeebene** fehlt: kein einziges Kommando führt alle Epic-3-Szenarien fail-fast aus, der vollständige autorisierte Validator (`schema/validator.md` Rev 9) wird bisher nur **human-mechanisch** über `wiki/` gestellt (kein ausführbares Verfahren, D-3), die „zwei frische Agent-Kontexte"-Zwei-Run-Bestätigung ist ausdrücklich nur **mechanisch simuliert** (Subshells, spec-3-8 P-5 / compiler.md Z. 374 — der echte Nachweis ist dem 3.13-Gate vorbehalten), und der Epic-5-Abhängigkeits-Smoke (FR-15/16) plus Porcelain-Unverändertheit (git status --porcelain) eines Clean-Checkouts wurden nie als Gate geprüft.
|
||||
|
||||
**Approach:** Ein einziges, re-executierbares, fail-fast ausführbares **Gate-Skript** `_bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh` orchestriert die vollständige Epic-3-Abnahme: (a) Repo-Weiter Bausatz: alle 12 Sandbox-`run-sandbox.sh` als Sub-Runs nacheinander, jede Assertion hart, jede Abweichung = Non-Zero-Exit; (b) echte vollständige Validator-Integration — ein frisch gestarteter **Agent-Kontext** liest `schema/validator.md` (Rev 9, 14 Punkte + §6-Fachprüfungen) und stellt ein Verdikt `SUCCESS`/`FAIL <pfad> <ursache>` über **alle** `wiki/`-Dateien des Clean-Checkouts per angefügter `verdict-*-dateien.md`-Datei; das Gate prüft deren Grammatik (§5, §5.1) und Exhaustivität (jede `wiki/**/*.md`-Datei außer nicht-`raw/`-externe hat genau ein Verdikt), schreibt aber **keine eigenen Validator-Urteile**; (c) zwei frische Agent-Kontexte (zwei getrennte `$SB`-Arbeitskopien, jeweils ausgemeindete Clone-Kopien, `git worktree add` auf denselben `$BASE`-Commit) führen `schema/compiler.md` über einer repräsentativen committeten Fixture aus; das Gate baut die Fixture auf (rohes Zuwachs-Paar + Ziel-Concepts, committet als `$BASE`), schreibt **selbst weder erwartete Wiki-Bodies noch Lease-/Log-/Git-Ausgänge** (§5.14 Pkt. 2; epic-3-context-Z. 46) und vergleicht die beiden Ergebnis-Bäume via `git diff <A> <B> -- wiki/` + Hash- und Frontmatter-Angleichung (nur die benannte `generated.at`-/`verified[].at`-Ausnahme); (d) G-Szenarien (G-1..G-8) als harte Assertions, inkl. der Epic-5-Abhängigkeits-Smoke (G-7: die vordefinierten Wissensfragen brauchen nur das `wiki/`-Bundle, keine Planungs-Referenzen) und Porcelain-Check (G-8: nach dem Lauf `git status --porcelain –-untracked-files=no` leer). `schema/compiler.md`, `schema/validator.md`, `schema/wiki-compiler.md`, `adapters/`, `raw/` bleiben read-only (AC-4: das Gate ändert die Schema-Semantik nie still); der Gate-Lauf findet ausschließlich als `/tmp`-Kopie des realen Clone-Baums statt (nie im Ist-Baum), das reale `wiki/` wird nur als Textquelle gelesen.
|
||||
|
||||
## Boundaries & Constraints
|
||||
|
||||
**Always:**
|
||||
- **Nicht primär-mutiert:** `schema/compiler.md`, `schema/validator.md`, `schema/wiki-compiler.md`, `adapters/`, `raw/` — read-only (AD-3; das Gate ist eine Abnahme, keine neue Instruktions- oder Validator-Semantik).
|
||||
- **Ein Datei-Satz erzeugt:** `_bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh` (re-executierbar, `bash run-sandbox.sh` aus Repo-Root). Es läuft **ausschließlich als `/tmp`-Kopie** des realen Clone-Baums (koppelt `git clone`/`git worktree add` + Bundle-Kopie), greift nie auf den Ist-Baum zu und hinterlässt den Ist-Baum `git status --porcelain`-unverändert (G-8).
|
||||
- **Kein `sed -i`:** alle Mutationen im Gate-Skript über `cp`/`printf > file`/`git …`-Aufrufe (portabel macOS/BSD- und Linux/GNU-Userland, AC-2).
|
||||
- **Harness schreibt keine erwarteten Wiki-Bodies / Lease-/Log-/Git-Ausgänge:** die beiden frischen Agent-Kontext-Läufe (c) erzeugen die Wiki-/Receipt-Ausgabe; das Gate vergleicht A vs B (§5.14 Pkt. 2), hard-codiert keinerlei erwartete Bodies/Receipts (AC-4/AC-5, epic-3-context Z. 46; Defer-Home: DET-1/DET-2-Plan-Literale, R-9-Receipt-Literale).
|
||||
- **`raw/` bleibt Status quo:** der Clean-Checkout-Fixture-Roh-Zuwachs lebt in der /tmp-Fixture (Kopie des realen `raw/`-Baums + Zuwachs dort), nie als Mutation im realen `raw/`.
|
||||
- **Validator-Ausführung:** der frische Agent-Kontext ist der DIR-Exekutor für `schema/validator.md`; das Gate validiert nur Verdikt-Grammatik/-Exhaustivität, urteilt nie selbst (D-3-Compliance).
|
||||
- **AC-4-Defizit-Route:** erkennt das Gate ein Validator-Defizit, schlägt G-5 fehl (Non-Zero), Story 3.13 bleibt offen und benennt den Bedarf einer separat autorisierten Epic-1-Remediation; das Gate ändert dann nichts an Schema/Validator.
|
||||
- **Sandbox-Nachweis:** Exit 0, harte PASS/FAIL, `/tmp`-Baum, nie der reale Ist-Baum (Muster sandbox-3-11/3-12).
|
||||
|
||||
**Ask First:**
|
||||
- Einen Validator-Patch anzufassen (wäre Epic-1-Remediation, separat autorisiert) — oder Gate-Verhalten zu ändern, das auf realen Wanduhr-/`generated.at`-Ausnahmen beruht (A0-20).
|
||||
|
||||
**Never:**
|
||||
- Kein Umschreiben von `schema/compiler.md`/`schema/validator.md`/`raw/`; kein neues Prädikat/keine neue §7-Invaliditätsklasse; kein Standalone-Inhalts-Befund (D-3); kein textueller Auto-Merge (AD-17c); keine stille Löschung (AD-17e); keine Wanduhr-/TTL-Steuerung (A0-20); kein echtes `wiki/`-oder-`raw/`-Schreiben durch das Gate (nur Textquelle); kein Zugriff auf echte fremde Worktrees.
|
||||
|
||||
## I/O & Edge-Case Matrix
|
||||
|
||||
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|
||||
|----------|--------------|---------------------------|----------------|
|
||||
| SANDBOX_SUB_RUN_OK | n-te Sandbox liefert PASS/Exit 0 | Sub-Run erkennbar; FAIL → Non-Zero-Exit, Lauf bricht ab (fail-fast) | jede Abweichung = harter Non-Zero |
|
||||
| VALIDATOR_AGENT_VERDIKT_OK | frische Verdikt-Datei je Datei-Pfad | Grammatik §5/§5.1 erfüllt; jede stattfindende `wiki/**/*.md`-Datei hat ein Verdikt; SUCCESS überall → G-3 PASS | fehlende/ungrammatische/FAIL-Verdikte = Non-Zero |
|
||||
| VALIDATOR_DEFIZIT | fehlende/ungrammatische/FAIL-Verdikte werden nicht selbst repariert | G-5 PASS, Story bleibt offen; Bedarf einer Epic-1-Remediation wird textuell benannt | Non-Zero-Exit, kein Gate-Flip |
|
||||
| FRESH_AGENT_TWO_TREES | zwei getrennte Arbeitskopien, gleicher `$BASE`-Commit | beide Runs beenden; `git diff A B` zeigt nur `at`-Abweichung; Bundle-Hashes/Reihenfolge/Plan A==B (außer `at`) | Divergenz außerhalb Ausnahme = harter FAIL |
|
||||
| PERTURBIERTE_ENTSCHEIDUNG | eine der zwei Runs wird im Script über eine perturbed Option geroutet | Negativ-Kontrolle: divergente Bäume werden erkannt (G-6) | Non-Zero-Exit, kein false-PASS |
|
||||
| PORCELAIN_CLEAN | nach dem Lauf | `git status --porcelain --untracked-files=no` auf dem Ist-Baum leer | überszogene Gate-Artefakte = Non-Zero |
|
||||
| CONSUMER_SMOKE | nur das erzeugte Bundle | FR-15/16-Fragen ohne Planungs-Referenzen beantwortbar (G-7) | Referenz auf PRD/Spec/Spine = Non-Zero |
|
||||
| GENERATED_AT_AUSNAHME | die einzige erlaubte Differenz | `generated.at`/`verified[].at`-Zellen dürfen abweichen | andere Zellen abweichend = Non-Zero |
|
||||
|
||||
</frozen-after-approval>
|
||||
|
||||
## Code Map
|
||||
|
||||
- `_bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh` — **neu erzeugt** (re-executierbar, Muster `sandbox-3-12/run-sandbox.sh` 820 Z. + `sandbox-3-8` Zwei-Worktree-Mechanik Z. 249-251/268/281-306/415-433; `set -u`, **kein** `set -e` — negatives Assertion-Idiom `cmd && fail`; `ROOT=$(mktemp -d /tmp/sb313-XXXXXX)`; `git config core.autocrlf false` + `core.filemode false`; `pass()/fail()` hart; End-Exit 0). Abschnitte: **(A) Setup** — Repo-/Bundle-/Referenz-Check, Referenz-Sandbox-Liste `sandbox-3-1..3-12`, `git status --porcelain`-Pre-Check; **(B) Käfig-Bau** — `/tmp`-Kopie des realen Clone-Baums (liest alle `wiki/**/*.md`-Dateiliste, kopiert `schema/raw/…`), `git init`+baseline; **(C) 12 Sandbox-Sub-Runs** — je `bash …/sandbox-3-N/run-sandbox.sh` mit Exit-Check; **(D) Validator-Agent** — frischen Sub-Agent-Kontext starten, der `schema/validator.md` über alle `wiki/`-Dateien ausführt und `verdict-*.md`-Dateien (SUCCESS/FAIL-Format) ablegt; **(E) Zwei-frische-Agenten** — zwei `/tmp`-Arbeitskopien (G-Kontext), shared `$BASE`-Fixture-ROH-Zuwachs `raw/alpha-v2.md`+Ziel `wiki/alpha.md` committet, beide Runs auf `git worktree add $BASE`, A/B-`git diff -- wiki/` + Hash-/Frontmatter-Vergleich, Nur-`at`-Ausnahme; **(F) G-1..G-8** harte Assertions; **(G) Nachweise/Porcelain** — Endzustands-Invariante + `git status --porcelain`-leerer Zustand.
|
||||
- `_bmad-output/implementation-artifacts/sandbox-3-12/run-sandbox.sh` — **read-only** Ausgangspunkt (L-1..L-9, Exit 0; Portrait der $5.18-Kill-Point-/Clean-Input-Härtung), Ausgangspunkt der `pass()/fail()`/Isolate-Helfer.
|
||||
- `_bmad-output/implementation-artifacts/sandbox-3-8/run-sandbox.sh` — **read-only** Quelle der Zwei-Worktree-Mechanik (DET-2: `git worktree add -q "$ROOT/wt-a" "$BASE"` Z. 249-251; `run2_worktree()` Z. 268; Manifest-Validierung Z. 281-306; Cross-Receipt-Vergleich A vs B Z. 415-433) — der 3.13-„Zwei-frische-Agenten"-Kern.
|
||||
- `_bmad-output/implementation-artifacts/spec-3-8-determinismus-vertrag-ad-17h-als-agent-instruktions-validato.md` — **read-only** Defer P-5 (Z. 150): „die zwei frischen Agent-Kontexte sind mechanisch simuliert … der Nachweis echter frischer Kontexte erfolgt im Story-3.13-Abnahmegate über reale Agent-Läufe".
|
||||
- `_bmad-output/implementation-artifacts/deferred-work.md` — **append, read-only lesbar** (Aufgegriffen-/3.13-Home-Marker): L551 (DET-1/2-Plan-/Form-Literale), L560 (R-9-Receipt-Literale), L576 (wiki//raw/-Invarianten-Beweis), L594 (Zwei-Producer-verschiedene-`<id>`-Gewinner), L597 (Zwei-Worktree-Barriere-überlappung), L611 (Zwei-Worktree-Übernahme), L629 (geteilter-Ref-Namespace-Real-Beweis), L633 (AC-3-Stash-/AC-5-kombinierter-Clean-Input-Beweis) — diese werden über die echten Gate-Runs einschlägig **geschlossen** (Home 3.13-Abnahme realisiert); der zugehörige RD-Notiz-/Defer-Block bleibt unverändert (nur das Home ist erledigt).
|
||||
- `_bmad-output/implementation-artifacts/sprint-status.yaml` — **mutiert** nach Gate-Freigabe (Step-05): Key `3-13-epic-3-verifikations-und-abnahmegate` `backlog → done` (final); `epic-3` bleibt solange `in-progress`; `last_updated` (Format `MM-DD-YYYY HH:MM`).
|
||||
- `_bmad-output/implementation-artifacts/epic-3-context.md` — **mutiert** („Edit freely") nach Gate-Freigabe: Z. 7/46/52 von „…als abgeschlossen/…Gate…zwei frische Agent-Kontexte…" auf Ist-Zustand (Gate erfolgreich ausgeführt) aktualisiert.
|
||||
- `wiki/log.md` — **append** (Vertrag §5): Story-3.13-Eintrag (Gate-Lauf, Sandbox 3-13, G-1..G-8, Zwei-frische-Agenten-A/B-Identität, Sandbox-Nachweis 12×Exit 0, Validator-Integration, Porcelain-Check, sprint-status.yaml-Flip) — **nur** vertragskonforme fachliche + Koordinationsereignisse (AC-6; Dokumentations-Kategorie wie 3.12—3.13-Gate-Lauf selbst ist zulässiger Koordinations-Nachweis, Kategorie-Historie bleibt außerhalb).
|
||||
|
||||
**Read-only evidence (AD-3):** `schema/validator.md` (Rev 9, §0 L9-22 „rein textuell — kein Standalone-Programm (D-3)", §3 14-Punkte-Tabelle Z. 50-73, §5 Verdikt-Format Z. 139, §5.1 Selbstbegrenzung Z. 154, §6-Fachprüfungen EC-1/EC-3/EC-11 Z. 160-201, §7-Fixtures Z. 202-289); `schema/compiler.md` (Revision 3.7; §0 Z. 9, §6 Z. 441-446 — „Das gesamte Bundle gemäß schema/validator.md geprüft"; §7 Z. 486-499; §8-Revisionslog Z. 501-543); `schema/wiki-compiler.md`; `adapters/`; `raw/` (immutable Evidenz). `schema/canonical-terms.md` append-only unangetastet.
|
||||
|
||||
## Tasks & Acceptance
|
||||
|
||||
**Execution:**
|
||||
- [ ] `_bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh` — Gate-Skript bauen (Setup → Käfig-Bau → 12-Sandbox-Fail-Fast → Validator-Agent → Zwei-frische-Agenten-A/B → G-1..G-8 → Porcelain-Check), harte PASS/FAIL, Exit 0, `/tmp`-Kopie nie Ist-Baum
|
||||
- [ ] `schema/compiler.md`/`schema/validator.md`/`adapters/`/`raw/` — read-only verifizieren (kein Diff), `schema/canonical-terms.md` unangetastet (AD-3)
|
||||
- [ ] Gate real ausführen (mehrere Läufe, inkl. skript-seitiger Zwei-/Mehr-Lauf-Stabilität) bis Exit 0; Negativ-Kontrollen ausführen
|
||||
- [ ] `_bmad-output/implementation-artifacts/sprint-status.yaml` — Key 3-13 → `done`, `epic-3` Status-Kette prüfen, `last_updated` aktualisieren (Step-05 nach Review)
|
||||
- [ ] `_bmad-output/implementation-artifacts/epic-3-context.md` — Abnahme-Zeile auf Ist-Zustand nachführen
|
||||
- [ ] `wiki/log.md` — Story-3.13-Eintrag (Gate, Sandbox-3-13, G-1..G-8, Validator-Integration, Zwei-frische-Agenten, Porcelain) — nur vertragskonforme Inhalte (AC-6)
|
||||
- [ ] `_bmad-output/implementation-artifacts/deferred-work.md` — 3.13-Home-Defers (L551/L560/L576/L594/L597/L611/L629/L633) als aufgegriffen/erledigt markieren (Defer-Block selbst historisch unverändert)
|
||||
- [ ] Nachweis: `git status --porcelain` des realen Ist-Baums nach Gate-Lauf unverändert (G-8), `raw/` unverändert
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Given einen sauberen Checkout, when das repositoryweite Epic-3-Gate ausgeführt wird, then führt ein Kommando alle Epic-3-Szenarien fail-fast aus; fehlgeschlagene Assertions, übersprungene Szenarien, fehlende Abhängigkeiten und Kindprozessfehler ergeben einen Non-Zero-Exit (AC-1).
|
||||
- Given macOS/BSD- und Linux/GNU-Userland, when das Gate läuft, then ist es ohne plattformspezifisches `sed -i` reproduzierbar, arbeitet ausschließlich in temporären Repositories und hinterlässt `git status --porcelain` unverändert (AC-2).
|
||||
- Given positive und negative OKF-Fixtures, when validiert wird, then wird der vollständige Vertrag aus `schema/validator.md` über alle `wiki/`-Dateien ausgeführt; unter anderem fehlendes `generated.by`, kalenderinvalides `generated.at`, unzulässige Source-Pfade und gebrochene Index-Links verhindern SUCCESS und Commit (AC-3).
|
||||
- Given der autorisierte Validator-Vertrag oder seine ausführbare Aufrufbarkeit weist dabei ein Defizit auf, when das Gate es erkennt, then bleibt Story 3.13 offen und benennt den Bedarf für eine separat autorisierte Epic-1-Remediation; Story 3.13 darf die Schema-Semantik nicht still ändern, verantwortet aber die Integration und vollständige Ausführung des bestehenden Vertrags (AC-4).
|
||||
- Given eine repräsentative committete Fixture, when ein frischer Agent-Kontext die kanonische Instruktion `schema/compiler.md` ausführt, then darf der Harness nach dem Setup weder erwartete Wiki-Bodies noch Lease-, Log- oder Git-Ausgänge selbst schreiben (AC-5).
|
||||
- Given diese Fixture, when der Compilation Run endet, then demonstriert er Update eines bestehenden Concepts, Anlage einer neuen Wissenseinheit, kohärente Multi-Source-Synthese, vollständige Multi-Evidenz-Provenienz, Source-Immutabilität und byte-identische Erhaltung unabhängigen Wissens (AC-6).
|
||||
- Given dasselbe kanonische Eingabemanifest, when zwei frische Agent-Kontexte in getrennt aufgebauten Worktrees laufen, then stimmen Run-Receipts und Bundle-State gemäß Story 3.8 überein; eine perturbierte Entscheidung oder Ausgabe wird erkannt (AC-7).
|
||||
- Given nur das erzeugte Knowledge Bundle ohne Planungsartefakte, when ein unabhängiger Consumer im Epic-5-Abhängigkeits-Smoke-Test vordefinierte Wissensfragen beantwortet, then benötigt er weder Product Brief, SPEC, Architecture Spine noch Story-Historie zum semantischen Verständnis; solche Referenzen sind höchstens optionale Provenienz/Traceability (AC-8).
|
||||
- Given ein bestandenes Gate, when die Status-Synchronisation läuft, then wird der Key `3-13-…` auf `done` geflippt und Epic 3 erst nach bestandenem Gate und `done` aller Stories 3.8..3.13 auf `done` gesetzt; bis dahin bleibt Epic 3 `in-progress` (AC-9).
|
||||
|
||||
## Spec Change Log
|
||||
|
||||
_Leer bis zum ersten bad_spec-Loopback (Step-04)._
|
||||
|
||||
## Design Notes
|
||||
|
||||
Der Gate-Kern löst das 3.8-P-5-Defizit: die Zwei-frische-Agenten-Bestätigung läuft hier **echt** — zwei getrennte Arbeitskopien desselben `$BASE`-Commits, jeweils frischer Kontext, `schema/compiler.md` als einzige Instruktionsquelle, A/B-Angleichung nur auf den erlaubten `at`-Zellen (§5.14 Pkt. 2). Der Validator bleibt **Instruktion**, wird aber durch einen dritten frischen Agent-Kontext zur **ausführbaren Prüfung** gemacht (er liest `schema/validator.md` und erzeugt `SUCCESS`/`FAIL <pfad> <ursache>` über alle `wiki/`-Dateien); das Gate prüft nur Verdikt-Grammatik/Exhaustivität, nie den Inhalt (D-3-Compliance). Die 12 Sandbox-Suiten werden als **Sub-Runs** in eine fail-fast-Sequenz gehoben — der „ein Kommando"-Wortlaut von AC-1.
|
||||
|
||||
**Beispiel (Zwei-frische-Agenten, deterministisch):**
|
||||
```bash
|
||||
# im Gate-Skript: Bau beider Bäume auf denselben Commit
|
||||
git worktree add -q "$ROOT/wt-a" "$BASE" && git worktree add -q "$ROOT/wt-b" "$BASE"
|
||||
# A vs B — nur die at-Zellen dürfen differieren:
|
||||
git diff --stat "$ROOT/wt-a" "$ROOT/wt-b" -- wiki/ # ≠ leer (nicht-vakuum), at-only
|
||||
```
|
||||
|
||||
Die repräsentative Fixture nimmt das 3-12-Sandbox-Muster (Mini-Bundle `wiki/index.md`+`alpha.md`+`log.md`, `raw/alpha-v1.md` als Baseline, Zuwachs `raw/alpha-v2.md` → Update von `alpha.md`, ergänzt um Bereichs-Synthese/`gamma` und `wiki/`-bleibt-Byte-identisch für unabhängiges `delta`) — in den `/tmp`-Käfig kopiert und committet, nie das reale Bundle.
|
||||
|
||||
## Verification
|
||||
|
||||
**Commands:**
|
||||
- `bash _bmad-output/implementation-artifacts/sandbox-3-13/run-sandbox.sh` -- expected: 12 Sandbox-Sub-Runs (jede `exit 0`), Validator-Integration, Zwei-frische-Agenten A/B-Identität (nur `at`-Zellen abweichend), G-1..G-8 harte PASS, finaler Porcelain-Check, Exit 0; kein Zugriff auf den realen Ist-Baum.
|
||||
- `git status --porcelain` (Repo-Root) -- expected: leer/nur Story-3.13-Artefakte; `schema/compiler.md`, `schema/validator.md`, `schema/wiki-compiler.md`, `adapters/`, `raw/` ohne Diff (AD-3); `sandbox-3-13/` als einziger neuer Verzeichnis-Inhalt.
|
||||
- `git diff --stat` (Repo-Root) -- expected: nur Story-3.13-Touched-Files (run-sandbox.sh, spec, log.md, sprint-status.yaml, epic-3-context.md, deferred-work.md), kein Source-/Schema-Diff (AC-4: keine stille Schema-Änderung).
|
||||
- optional: Deb-Run des Gate-Skripts mit `bash -x` -- expected: keine `sed -i`-Aufrufe (AC-2).
|
||||
|
||||
**Manual checks (if no CLI):**
|
||||
- Keine Beschreibung nötig — sämtliche Nachweise laufen über das Gate (Exit-Code) und additive Diffs.
|
||||
|
||||
## Suggested Review Order
|
||||
|
||||
**Abnahme-Ebene (Kern)**
|
||||
|
||||
- Gate-Skript — Fail-Fast-Orchestrierung der 12 Sandbox-Suiten, `/tmp`-Käfig statt Ist-Baum, Porcelain-Check.
|
||||
[`run-sandbox.sh`](./sandbox-3-13/run-sandbox.sh)
|
||||
|
||||
- Zwei-frische-Agenten A/B (AC-7): getrennte Worktrees auf `$BASE`, `git diff A B -- wiki/` nur `at`-Zellen, Negativ-Kontrolle perturbed.
|
||||
[`run-sandbox.sh`](./sandbox-3-13/run-sandbox.sh)
|
||||
|
||||
- Validator-Integration (AC-3/AC-4): frischer Agent-Kontext führt `schema/validator.md` über alle `wiki/`-Dateien aus; Verdikt-Grammatik/Exhaustivität; Defizit → Non-Zero + Epic-1-Remediation-Bedarf.
|
||||
[`run-sandbox.sh`](./sandbox-3-13/run-sandbox.sh)
|
||||
|
||||
- Harness schreibt keine erwarteten Ausgänge (AC-5), repräsentative Fixture beweist AC-6 inkl. byte-identische Erhaltung unabhängigen Wissens; Epic-5-Smoke G-7 (AC-8).
|
||||
[`run-sandbox.sh`](./sandbox-3-13/run-sandbox.sh)
|
||||
|
||||
**Status- & Nachweissynchronisation (peripher)**
|
||||
|
||||
- Story-3.13-Eintrag im kanonischen Knowledge Log (Vertrag §5; Gate-Lauf, Sandbox 3-13, G-1..G-8, Zwei-frische-Agenten, Porcelain-Check).
|
||||
[`log.md`](../../wiki/log.md#L1)
|
||||
|
||||
- Abnahme-Zeile von „…als abgeschlossen…Zwei-frische-Agenten-Kontexte…" auf Ist-Zustand nachgeführt.
|
||||
[`epic-3-context.md`](./epic-3-context.md)
|
||||
|
||||
- 3.13-Home-Defers (Zwei-Worktree-Überlappung, DET/R-9-Receipt-Literale, wiki//raw/-Invariante, Stash-/Clean-Input-Beweis) als aufgegriffen/erledigt markiert.
|
||||
[`deferred-work.md`](./deferred-work.md)
|
||||
|
||||
- Key 3-13 → `done` (final, nach Review), Epic-3 bleibt bis zum Gate-Abschluss `in-progress`.
|
||||
[`sprint-status.yaml`](./sprint-status.yaml)
|
||||
@@ -29,7 +29,7 @@
|
||||
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
|
||||
# - Retrospective appends its action items to action_items; the status view surfaces open ones
|
||||
generated: 08-14-2026 00:00
|
||||
last_updated: 08-22-2026 07:44
|
||||
last_updated: 08-22-2026 19:10
|
||||
project: wow20
|
||||
project_key: NOKEY
|
||||
tracking_system: file-system
|
||||
@@ -63,7 +63,7 @@ development_status:
|
||||
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-12-lease-lifecycle-und-commit-abschluss-transaktional-schliessen: done # Story 3.12 Review-Loop-2-Abschluss 2026-08-22 (bmad-code-review, 4 Layer; D-3.12-1 Option 1 — AC-6-Grenze an log.md-Praxis, L-8-Kategorie-Hyphenate + Negativ-Kontrolle; 7 Patches — P1 scopelock_healthy()/LOCK_READ_ERROR-Propagation, P2 Release-Fehler-negativ + L-6 hart, P3 Setup-Robustheit, P4 Ghost-Diff-Probe + reg_write real, P5 Ownership-Stale + Takeover-Exactly-once, S1/S2 Sync- & Anker-Berichtigung; Sandbox L-1..L-9 9/9 harte PASS/Exit 0 re-executiert; Loop 1: atomarer Ownership-CAS im Takeover, AK-2->AC-2; §5.18 Revision 3.7). 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: done # Story 3.13 Epic-3-Abnahmegate abgeschlossen 2026-08-22: run-sandbox.sh (A Setup, B Käfig-Bau, C 12 Sandbox-Sub-Runs, D Validator-Agent, E Zwei-frische-Agenten A/B, F G-1..G-8, G Porcelain) — voller Lauf PASS_COUNT=70, FAILED=0, RUN_OK/Exit 0; Validator 7/7 SUCCESS über reales Bundle; A/B byte-identisch nur at-Ausnahme (§5.14 Pkt. 2); G-6 Negativ-Kontrolle erkennt Perturbation; G-8 Ist-Baum-Porcelain leer. Aufgedeckte und behobene reale Befunde: (1) wiki/log.md:42 zitat das Literal 'type: bundle' in Prosa → Validator Punkt-9-Verletzung, bedeutungserhaltend de-literalisiert (Bundle-Compliance); (2) G-7-Smoke überstreng gegen Bundleroot-Schema-Glossar (../schema/, compiler §5.6 'andere Schicht') + log.md-Protokoll (§5.6 Pkt. 2 Log-Exclusion) → Exclusion im Gate, Smoke bleibt hart für Concept-Bodies. Epic-3 bleibt in-progress bis zur Epic-3-Retrospektive (AC-9: Epic 3 erst nach done aller Stories 3.8..3.13).
|
||||
epic-3-retrospective: optional
|
||||
|
||||
epic-4: backlog
|
||||
|
||||
+2
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user