#!/usr/bin/env bash # Story 3.1 — Sandbox-Edge-Tests der I/O-Matrix (fünf Szenarien) + D-3-Abbruch-Kontrolle # Re-executierbar: bash run-sandbox.sh (ab Workspace-Root; Sandbox unter /tmp/sb31) set -u ROOT=$(mktemp -d /tmp/sb31-XXXXXX) SB="$ROOT/sb" mkdir -p "$SB/wiki" "$SB/raw" cd "$SB" git init -q git config user.email "sandbox@test" git config user.name "Sandbox" # ---------- Basis-Baum (committete Ausgangslage = Baseline-Commit) ---------- cat > wiki/index.md <<'EOF' # Index - [Alpha](alpha.md) - [Beta](beta.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 verwendet quanten-protocol-schlüssel für die Authentifizierung. EOF cat > wiki/beta.md <<'EOF' --- type: concept sources: - resource: raw/beta-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Beta beschreibt ein anderes, hier nicht betroffenes Thema. EOF cat > wiki/log.md <<'EOF' # Log EOF cat > raw/alpha-v1.md <<'EOF' Evidenz v1: quanten-protocol-schlüssel (Stelle S-1). EOF cat > raw/beta-v1.md <<'EOF' Evidenz v1: Beta-Thema (Stelle S-1). EOF git add -A git commit -qm "Baseline" BASE=$(git rev-parse HEAD) echo "BASELINE-COMMIT: $BASE" echo runlabel() { echo; echo "########## $1 ##########"; } RG() { if command -v rg >/dev/null; then rg "$@"; else grep -rln "$@"; fi; } # Isolation: Worktree auf BASE zuruecksetzen (kein Carry-over ueber Szenarien) isolate() { git checkout -q -b "$1" "$BASE" 2>/dev/null || git checkout -q "$1"; git reset -q --hard "$BASE"; git clean -qfd wiki raw; } probe() { # Pkt. 5-Probe (D-1-Form): Baseline-Diff + porcelain, normalisiert (wiki/-Praefix + .md gestrippt) { 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 } # ===================================================================== runlabel "S1: HAPPY_PATH_UPDATE (bestehendes Concept wird im bestehenden Pfad aktualisiert)" # Zuwachs: neue committierte Evidenz mit Term-Ueberschneidung cat > raw/alpha-v2.md <<'EOF' Evidenz v2: quanten-protocol-schlüssel erfaehrt eine Rotation (Stelle S-2). EOF git add -A; git commit -qm "Zuwachs raw/alpha-v2.md" # Reconcile: Kandidatenliste (textuell-deterministisch, AD-13) echo "--- Kandidaten-Erhebung: rg -l 'quanten-protocol-schlüssel' wiki/ ---" RG -l 'quanten-protocol-schlüssel' wiki/ || true # Update-Pfad: Mutation im BESTEHENDEN Pfad (Erweitern) + log.md cat >> wiki/alpha.md <<'EOF' Seit der Rotation (raw/alpha-v2.md#S-2) gelten die Schlüssel neu. EOF cat >> wiki/log.md < -- wiki/ + git status --porcelain -- wiki/, normalisiert) ---" probe echo "--- Erwartet: log, alpha (betroffen); beta NICHT; keine neue Datei (porcelain o.??) ---" git status --porcelain -- wiki/ echo "--- Duplikat-Check: existiert alpha.md weiterhin exakt 1x? ---" ls wiki/alpha.md; git status --porcelain -- wiki/ | grep -c '^??' || echo "0 untracked" # ===================================================================== runlabel "S2: UNTOUCHED_CONCEPT (neue Evidenz betrifft kein bestehendes Concept)" isolate s2 cat > raw/gamma.md <<'EOF' Evidenz: vollstaendig neues gamma-observatorium-thema (Stelle S-1). EOF git add -A; git commit -qm "Zuwachs raw/gamma.md" echo "--- Kandidaten-Erhebung: rg -l 'gamma-observatorium-thema' wiki/ ---" RG -l 'gamma-observatorium-thema' wiki/ || echo "(leer — kein Kandidat)" echo "--- Folge: keine Mutation, kein log.md-Zusatz (UNTOUCHED_CONCEPT) ---" echo "--- Probe ---" probe echo "(leere Ausgabe = kein Ghost-Diff; leere Menge ist Teilmenge jeder erlaubten Menge)" # ===================================================================== runlabel "S3: CONCEPT_COLLISION_BESTEHEND (Zielpfad belegt -> Update-Routing, kein Duplikat)" isolate s3 cat > raw/alpha-v2.md <<'EOF' Evidenz v2: quanten-protocol-schlüssel (Stelle S-2, ergaenzend). EOF git add -A; git commit -qm "Zuwachs" echo "--- Vor-Mutation-Check: Ziel-Pfad wiki/alpha.md belegt? ---" test -f wiki/alpha.md && echo "JA — Update-Routing (kein Duplikat, kein stummer Ueberschreiben)" echo "--- Vor-Mutation-Zustand (muss leer sein) ---" git status --porcelain -- wiki/; echo "(leer)" echo "--- Mutation im bestehenden Pfad (Update) ---" echo "Ergaenzung (raw/alpha-v2.md#S-2)." >> wiki/alpha.md echo "## 2026-08-19" >> wiki/log.md; echo "- Story 3.1-Update: alpha (raw/alpha-v2.md)" >> wiki/log.md echo "--- Nach-Mutation: nur M-Eintraege, KEIN ?? (keine neue Datei = kein Duplikat) ---" git status --porcelain -- wiki/ echo "--- Probe ---" probe # ===================================================================== runlabel "S4: CHANGE_DETECTION (R-1: nur der Zuwachs wird als Evidenz interpretiert)" isolate s4 cat > raw/alpha-v2.md <<'EOF' Evidenz v2: nur diese Datei ist neu (Stelle S-2). EOF git add -A; git commit -qm "Zuwachs" echo "--- git diff --name-only -- raw/ ---" git diff --name-only "$BASE" -- raw/ echo "--- Erwartet: AUSSCHLIESSLICH raw/alpha-v2.md (alpha-v1.md/beta-v1.md bleiben aussen) ---" echo "--- SHA-256-Abgleich (Sekundaer-Fingerprint, D-2): alpha-v1 unveraendert? ---" sha256sum raw/alpha-v1.md git show "$BASE:raw/alpha-v1.md" | sha256sum echo "--- (identische Summen = unveraendert; bei Diskrepanz gewinnt git diff, D-2) ---" # ===================================================================== runlabel "S5: PRE_RUN_RECONCILE (Check-Block vor Mutation; fehlende Bundleroot -> Run-FAIL V-1)" isolate s5 rm wiki/index.md # Szenario-Setup: Bundleroot fehlt (simuliert, kein Run-Zustand) echo "--- Check-Block: (4) wiki/index.md-V-1-Vorbedingung ---" if [ -f wiki/index.md ]; then echo "OK"; else echo "Run-FAIL (V-1, Vertrag §2): wiki/index.md fehlt — keine Mutation darf erfolgen"; fi git checkout -q "$BASE" -- wiki/index.md # Setup-Rueckstellung (kein Run-Zustand) echo "--- Zustand nach Abbruch + Rueckstellung (muss leer sein — der Run selbst mutierte nichts) ---" git status --porcelain -- wiki/; echo "(leer)" # ===================================================================== runlabel "S6: INPUT_UNCOMMITTED (D-3: Working-Copy vs. HEAD-Check -> benannter Abbruch)" isolate s6 echo "uncommittete Zwischenstunde" >> raw/alpha-v1.md # simuliert Dirty-Tree echo "--- Check-Block: Working-Copy vs. HEAD fuer raw/ + wiki/ ---" DIRTY=$(git status --porcelain -- raw/ wiki/) if [ -z "$DIRTY" ]; then echo "OK — published/committed Input"; else echo "Abbruch: published/committed Input erforderlich (AD-17a) — ungepublishter Zustand:" echo "$DIRTY" fi echo echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"