fix: Story 3.13 Review-Loop-1-Auflösung (D-3.13-1..7 = 1/1/2/1/1/1/1, P-1..P-15; Status-Revert in-progress, Gate gehärtet 839 Z., Status-Sync spec/sprint-status/log.md; VALIDATOR_DEFIZIT-Matrix-Zeile = Renegotiation-Kandidat)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#!/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)
|
||||
# Review-Loop-2-Härtung (Story 3.13, D/Patch P-1): harte Assertions mit Exit-Pfaden —
|
||||
# jede Erwartung wird geassertet (Abweichung = Non-Zero-Exit), konsistent mit 3-2..3-12.
|
||||
set -u
|
||||
ROOT=$(mktemp -d /tmp/sb31-XXXXXX)
|
||||
SB="$ROOT/sb"
|
||||
@@ -9,6 +11,12 @@ cd "$SB"
|
||||
git init -q
|
||||
git config user.email "sandbox@test"
|
||||
git config user.name "Sandbox"
|
||||
FAILED=0
|
||||
PASS_COUNT=0
|
||||
pass() { PASS_COUNT=$((PASS_COUNT+1)); echo "PASS: $1"; }
|
||||
fail() { FAILED=$((FAILED+1)); echo "FAIL: $1" >&2; }
|
||||
# hardfail: Setup-/Infrastrukturfehler brchen sofort ab (kein Szenario-Exit).
|
||||
hardfail() { echo "HARD-FAIL: $1" >&2; exit 1; }
|
||||
|
||||
# ---------- Basis-Baum (committete Ausgangslage = Baseline-Commit) ----------
|
||||
cat > wiki/index.md <<'EOF'
|
||||
@@ -50,8 +58,9 @@ cat > raw/beta-v1.md <<'EOF'
|
||||
Evidenz v1: Beta-Thema (Stelle S-1).
|
||||
EOF
|
||||
git add -A
|
||||
git commit -qm "Baseline"
|
||||
git commit -qm "Baseline" || hardfail "Baseline-Commit fehlgeschlagen"
|
||||
BASE=$(git rev-parse HEAD)
|
||||
[ -n "$BASE" ] || hardfail "Baseline-Commit nicht auflösbar"
|
||||
echo "BASELINE-COMMIT: $BASE"
|
||||
echo
|
||||
runlabel() { echo; echo "########## $1 ##########"; }
|
||||
@@ -61,6 +70,12 @@ isolate() { git checkout -q -b "$1" "$BASE" 2>/dev/null || git checkout -q "$1";
|
||||
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
|
||||
}
|
||||
# expect_eq: $1=Beschreibung, $2=erwartet, $3=ist (jeweils mehrzeilig)
|
||||
expect_eq() {
|
||||
if [ "$2" = "$3" ]; then pass "$1"; else
|
||||
fail "$1 — erwartet: [$2], ist: [$3]"
|
||||
fi
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
runlabel "S1: HAPPY_PATH_UPDATE (bestehendes Concept wird im bestehenden Pfad aktualisiert)"
|
||||
@@ -68,7 +83,7 @@ runlabel "S1: HAPPY_PATH_UPDATE (bestehendes Concept wird im bestehenden Pfad ak
|
||||
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"
|
||||
git add -A; git commit -qm "Zuwachs raw/alpha-v2.md" || hardfail "Zuwachs-Commit fehlgeschlagen"
|
||||
# Reconcile: Kandidatenliste (textuell-deterministisch, AD-13)
|
||||
echo "--- Kandidaten-Erhebung: rg -l 'quanten-protocol-schlüssel' wiki/ ---"
|
||||
RG -l 'quanten-protocol-schlüssel' wiki/ || true
|
||||
@@ -81,11 +96,17 @@ cat >> wiki/log.md <<EOF
|
||||
- Story 3.1-Update: alpha (raw/alpha-v2.md; Baseline $BASE)
|
||||
EOF
|
||||
echo "--- Probe (git diff --name-only <BASE> -- 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"
|
||||
S1_PROBE=$(probe)
|
||||
echo "$S1_PROBE"
|
||||
expect_eq "S1 Probe: genau alpha + log betroffen, beta NICHT" "$(printf 'alpha\nlog')" "$S1_PROBE"
|
||||
# Keine neue Datei (Duplikat-Kontrolle): kein ?? unter wiki/
|
||||
S1_UNTRACKED=$(git status --porcelain -- wiki/ | grep -c '^??' || true)
|
||||
[ "$S1_UNTRACKED" -eq 0 ] && pass "S1 keine neue Datei unter wiki/ (kein Duplikat)" \
|
||||
|| fail "S1 unerwartete untracked wiki/-Datei(en): $S1_UNTRACKED"
|
||||
# alpha.md existiert exakt 1x
|
||||
S1_ALPHA_COUNT=$(git ls-files wiki/alpha.md | wc -l | tr -d ' ')
|
||||
[ "$S1_ALPHA_COUNT" -eq 1 ] && pass "S1 alpha.md ist exakt 1x getrackt" \
|
||||
|| fail "S1 alpha.md getrackt: $S1_ALPHA_COUNT (erwartet 1)"
|
||||
|
||||
# =====================================================================
|
||||
runlabel "S2: UNTOUCHED_CONCEPT (neue Evidenz betrifft kein bestehendes Concept)"
|
||||
@@ -96,10 +117,13 @@ 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)"
|
||||
# Folge: keine Mutation, kein log.md-Zusatz (UNTOUCHED_CONCEPT)
|
||||
S2_PROBE=$(probe)
|
||||
echo "--- Probe: [$S2_PROBE] ---"
|
||||
expect_eq "S2 Probe: leer (kein Ghost-Diff, UNTOUCHED_CONCEPT)" "" "$S2_PROBE"
|
||||
S2_LOG_DIFF=$(git diff "$BASE" -- wiki/log.md | wc -l | tr -d ' ')
|
||||
[ "$S2_LOG_DIFF" -eq 0 ] && pass "S2 log.md unverändert (kein Eintrag ohne Kandidat)" \
|
||||
|| fail "S2 log.md mutierte ohne Kandidat (S2_LOG_DIFF=$S2_LOG_DIFF)"
|
||||
|
||||
# =====================================================================
|
||||
runlabel "S3: CONCEPT_COLLISION_BESTEHEND (Zielpfad belegt -> Update-Routing, kein Duplikat)"
|
||||
@@ -109,16 +133,26 @@ 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)"
|
||||
test -f wiki/alpha.md && echo "JA — Update-Routing (kein Duplikat, kein stummer Ueberschreiben)" \
|
||||
|| fail "S3 Zielpfad wiki/alpha.md nicht belegt (Szenario-Setup verletzt)"
|
||||
echo "--- Vor-Mutation-Zustand (muss leer sein) ---"
|
||||
git status --porcelain -- wiki/; echo "(leer)"
|
||||
echo "--- Mutation im bestehenden Pfad (Update) ---"
|
||||
S3_PRE=$(git status --porcelain -- wiki/)
|
||||
echo "$S3_PRE"
|
||||
[ -z "$S3_PRE" ] && pass "S3 Vor-Mutation-Zustand leer" || fail "S3 Vor-Mutation-Zustand nicht leer: $S3_PRE"
|
||||
# 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
|
||||
S3_PORC=$(git status --porcelain -- wiki/)
|
||||
echo "$S3_PORC"
|
||||
S3_UNTRACKED=$(echo "$S3_PORC" | grep -c '^??' || true)
|
||||
[ "$S3_UNTRACKED" -eq 0 ] && pass "S3 keine ??-Einträge (kein Duplikat)" \
|
||||
|| fail "S3 unerwartete ??-Einträge: $S3_PORC"
|
||||
S3_ONLY_M=$(echo "$S3_PORC" | grep -cv '^ M ' || true)
|
||||
[ -n "$S3_PORC" ] && [ "$S3_ONLY_M" -eq 0 ] && pass "S3 nur M-Einträge (Update im bestehenden Pfad)" \
|
||||
|| fail "S3 Porcelain enthält Einträge außerhalb ' M ' (nur-$S3_ONLY_M-Andere)"
|
||||
S3_PROBE=$(probe)
|
||||
expect_eq "S3 Probe: genau alpha + log" "$(printf 'alpha\nlog')" "$S3_PROBE"
|
||||
|
||||
# =====================================================================
|
||||
runlabel "S4: CHANGE_DETECTION (R-1: nur der Zuwachs wird als Evidenz interpretiert)"
|
||||
@@ -128,22 +162,35 @@ Evidenz v2: nur diese Datei ist neu (Stelle S-2).
|
||||
EOF
|
||||
git add -A; git commit -qm "Zuwachs"
|
||||
echo "--- git diff --name-only <BASE> -- raw/ ---"
|
||||
git diff --name-only "$BASE" -- raw/
|
||||
echo "--- Erwartet: AUSSCHLIESSLICH raw/alpha-v2.md (alpha-v1.md/beta-v1.md bleiben aussen) ---"
|
||||
S4_ADD=$(git diff --name-only "$BASE" -- raw/)
|
||||
echo "$S4_ADD"
|
||||
expect_eq "S4 Zuwachs: ausschließlich raw/alpha-v2.md" "raw/alpha-v2.md" "$S4_ADD"
|
||||
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) ---"
|
||||
S4_SHA_NOW=$(sha256sum raw/alpha-v1.md | cut -d' ' -f1)
|
||||
S4_SHA_BASE=$(git show "$BASE:raw/alpha-v1.md" | sha256sum | cut -d' ' -f1)
|
||||
echo "$S4_SHA_NOW / $S4_SHA_BASE"
|
||||
[ -n "$S4_SHA_NOW" ] && [ "$S4_SHA_NOW" = "$S4_SHA_BASE" ] \
|
||||
&& pass "S4 raw/alpha-v1.md byte-identisch zur Baseline (Immutabilität)" \
|
||||
|| fail "S4 raw/alpha-v1.md weicht von der Baseline ab ($S4_SHA_NOW != $S4_SHA_BASE)"
|
||||
|
||||
# =====================================================================
|
||||
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
|
||||
if [ -f wiki/index.md ]; then
|
||||
echo "OK"
|
||||
fail "S5 V-1-Vorbedingung: wiki/index.md fehlt nicht — Szenario-Setup verletzt"
|
||||
else
|
||||
echo "Run-FAIL (V-1, Vertrag §2): wiki/index.md fehlt — keine Mutation darf erfolgen"
|
||||
pass "S5 V-1-Check löst Run-FAIL (fehlende Bundleroot)"
|
||||
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)"
|
||||
S5_PORC=$(git status --porcelain -- wiki/)
|
||||
echo "$S5_PORC"
|
||||
[ -z "$S5_PORC" ] && pass "S5 Zustand nach Abbruch leer (keine Mutation erfolgt)" \
|
||||
|| fail "S5 Zustand nach Abbruch nicht leer: $S5_PORC"
|
||||
|
||||
# =====================================================================
|
||||
runlabel "S6: INPUT_UNCOMMITTED (D-3: Working-Copy vs. HEAD-Check -> benannter Abbruch)"
|
||||
@@ -151,10 +198,22 @@ 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
|
||||
if [ -z "$DIRTY" ]; then
|
||||
echo "OK — published/committed Input"
|
||||
fail "S6 Dirty-Tree nicht erkannt (Abbruch hätte greifen müssen)"
|
||||
else
|
||||
echo "Abbruch: published/committed Input erforderlich (AD-17a) — ungepublishter Zustand:"
|
||||
echo "$DIRTY"
|
||||
pass "S6 INPUT_UNCOMMITTED-Abbruch greift (benannter Abbruch, keine Mutation)"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"
|
||||
echo "########## EMBEDDED-EXIT ##########"
|
||||
echo "FAILED=$FAILED PASS_COUNT=$PASS_COUNT"
|
||||
if [ "$FAILED" -eq 0 ]; then
|
||||
echo "SANDBOX-3-1-OK"
|
||||
exit 0
|
||||
else
|
||||
echo "SANDBOX-3-1-FAILED" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user