#!/usr/bin/env bash # ============================================================================= # Sandbox Story 3.9 — Deterministische Relevanz- & Reconcile-Routing schließen # (Loop-2-Re-Ableitung nach bad_spec BS-L2-1/BS-L2-2 + Loop-3-Minimal-Härtung # D-3.9-3 Option 2: tautologische Szenarien => echte Mechanik/real gefeuerte # negative Kontrollen; strukturelle Restlimits als benannte Defers, Home 3.13) # # Re-executierbarer Nachweis der §5.15-Verankerung (schema/compiler.md, Rev 3.4). # Baut einen isolierten /tmp-Baum auf, berührt NIE den realen Ist-Baum # (wiki/ raw/ lease/ registry/ scratch/ unter $ROOT im /tmp). # Re-Run-idempotent: veraltete Worktrees/Admin-Verzeichnisse unter $ROOT werden # vor jedem Lauf hart entfernt (Loop-3/P-3.9-14). # Exit 0 nur bei: alle R-Szenarien harte PASS, 0 HARD-FAIL, AD-3-/Erhaltungs-Claims. # # R-1 TERMGEWINNUNG_GESCHLOSSEN (AC-1: Termgewinnung, Sidecar-Exklusion, # Status-Codes, Diff<->Manifest-Äquivalenz + Negativ-Manifest = echter # Run-FAIL-Sub-Run vor jeder Mutation, Loop-3/D-3.9-3) # R-1b STATUS_GUARD_RC (AC-4/BS-L2-2: R => Guard-FAIL, C wie A — # Status-Codes in sauberen je-Status-Sub-Runs geschlossen) # R-2 NORMALISIERUNG_SYMMETRISCH (AC-2: symmetrische Normalisierung + # literal-sichere Suche; index.md-Treffer => Traversal-Stufe, real gefeuert) # R-3 ROUTING_TABELLE_EXKLUSIV (AC-3: UPDATE/CREATE/ORPHAN-HOLD/NO_OP; # NO_OP als Update-Unter-Entscheidung mit echtem Full-Containment-Check; # NO_MATCH neuer Einheit => CREATE, nicht NO_OP; Stufe-b via echtem # index.md-Link-Parsing + Zielpfad-Existenz, Loop-3/D-3.9-3) # R-4 RAW_GUARD (AC-4: M/D/R => Run-FAIL vor jeder Mutation # — reale je-Status-Sub-Runs mit Mutation-Sentinel; A akzeptiert) # R-5 NEUE_EINHEIT_KEIN_NOOP (BS-L2-1: neue Einheit mit leerer # Candidate-Liste => CREATE-Bewertungsraum via echter route()-Funktion, # NICHT NO_OP; D-8-Vereinigung ausgeübt, Loop-3/D-3.9-3) # R-6 RESERVED_ZIEL_INDEX (AC-5: Slug 'index' rein aus committetem # Dateinamen abgeleitet (nur dokumentierte Regel), case-insensitive # Reserviertheits-Prüfung; git ls-tree-Ist-Dateimenge) # R-7 RESERVED_ZIEL_LOG (AC-5: Slug 'log', abgeleitet; Hold) # R-8 HOLD_ZWEI_WORKTREE (BS-L2-4: Hold über zwei getrennte Worktrees # statt Doppel-Read; Receipt aus echter Mechanik (Slug/CAND aus committetem # Zuwachs); tote CAND einzeln hart; Hold-Assert auf BEIDE Worktrees) # R-9 ZWEI_RUN_NEGATIV (AC-6/BS-L2-6: positive Identität NICHT-VAKUUM # + negative AD-16-Abweichung hart FAIL + at-Exzeption praktisch + Norm-Pin; # Bundle-Byte-Vergleich mit benannter, ankerter index/log-Ausnahme) # ============================================================================= set -u # P-1: set -e im Hauptkörper (sandbox-3-8-Härtung) — kein false-PASS. # Achtung: R-9 nutzt Subshell-Läufe; Fehler dort werden explizit geroutet. set -e # --- Ort & Halluzinations-Root ------------------------------------------------- SB_NAME="sb39" if [ -n "${1:-}" ]; then ROOT="$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" else ROOT="$(mktemp -d "${TMPDIR:-/tmp}/${SB_NAME}.XXXXXX")" fi BASE_DIR="$(cd "$(dirname "$0")" && pwd)" echo "Sandbox-Root: $ROOT" echo "SMOKE: $0" # Pfad des Skripts (für relokierte Aufrufe) SELF="$0" mkdir -p "$ROOT/raw" "$ROOT/wiki" "$ROOT/scratch" "$ROOT/receipts" runlabel() { echo; echo "### $1"; } # Eine deterministische Kollaps-Funktion — GENAU die §3.2-Pkt.-1b-Kollaps-Klasse. # (Loop-2/P-L2-1: eine Definition, keine vierte abweichende Pipeline.) norm() { printf '%s' "$1" \ | sed \ -e 's/[-–—_ ]/-/g' \ -e 's/--*/-/g' \ -e 's/^-*//' \ -e 's/-*$//' \ | tr 'A-Z' 'a-z' } # C-clean-Kollaps (Unterschied zwischen En-/Em-Dash-Hyphen vs. underscore+space): norm_pipe() { norm "$1"; } # Lokale lowercase-Hilfe (deterministisch auf ASCII-Bytes, wie §3.2-Pkt.-1b). tolower() { tr 'A-Z' 'a-z'; } # Stufe-a-Match: Symmetrie, Ganzes-Wort, Body-only, index/log-Exklusion. # Liefert getroffene wiki-Pfade ohne Präfix/Suffix. match_stufe_a() { # $1=Begriff $2=Datei-Liste local term="$1" file term_lc esc body term_lc=$(norm "$term") esc=$(printf '%s' "$term_lc" | sed 's|[][\.*^$+?(){}|]|\\&|g') local out="" for file in "${@:2}"; do case "$(basename "$file")" in index.md|log.md) continue;; # keine Concept-Kandidaten esac body=$(tr -d '\r' < "$file" | awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}') body=$(norm "$body") if printf '%s' "$body" | grep -Eq "(^|[^a-z0-9])${esc}([^a-z0-9]|$)"; then [ -n "$out" ] && out="$out $(basename "$file" .md)" || out="$(basename "$file" .md)" fi done printf '%s' "$out" } # --- Isolation: frische Kopie der Fixture-Dateien je Szenario ------------------- # Fixtures sind im Skript eingebettete Datei-Inhalte (kein realer Baum). # isolate legt ein frisches Verzeichnis an und git-init. isolate() { local name="$1" local dir="$ROOT/$name" rm -rf "$dir" mkdir -p "$dir/raw" "$dir/wiki" "$dir/scratch" : > "$dir/.gitkeep" git -C "$dir" init -q git -C "$dir" config user.email "sandbox@test" git -C "$dir" config user.name "Sandbox" echo "$dir" } # --- log_bullet: Befund-/Hold-Text (kapselt in $ROOT/log-bullets.txt; optional # in wklog, siehe R-8-Exploit: real only unter isolierten Worktrees). -------- log_bullet() { # $1 = Zeile printf '%s\n' "$1" >> "$ROOT/log-bullets.txt" } # ============================================================================= # R-1 TERMGEWINNUNG_GESCHLOSSEN (AC-1) # ============================================================================= runlabel "R-1: TERMGEWINNUNG_GESCHLOSSEN — Zuwachs-Sicht (git diff gg. Baseline) -> deterministisch geordnete Term-Liste via Dateiname->Term-Mapping (Datums-Suffix/Endung gestripped, Trennzeichen kollabiert §3.2-Pkt.-1b); source.md-Sidecars exkludiert; Diff<->Manifest-Äquivalenz (Positiv + Negativ = FAIL)" r1dir=$(isolate r1) cd "$r1dir" # Basis-Concepts (Baseline-Commit). cat > wiki/alpha.md <<'EOF' --- type: concept sources: - resource: raw/alpha-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Alpha: Init-Sequenz und lokale Netze (raw/alpha-v1.md#S-1/#S-2). EOF cat > wiki/index.md <<'EOF' # Index - [Alpha](alpha.md) EOF cat > wiki/log.md <<'EOF' # Änderungen EOF git add -A && git commit -qm "R-1 Baseline" BASE=$(git rev-parse HEAD) # Zuwachs: neue Source mit Datums-Suffix + Sidecar. cat > raw/beta-kommunikation-2026-08-20.md <<'EOF' ### S-1 Evidenz: Beta-Kommunikation als Zuwachs-Thema. EOF cat > raw/beta-kommunikation-2026-08-20.source.md <<'EOF' # Source Herkunft: Test-Evidenz (Sidecar-Konvention §1.4). EOF git add -A && git commit -qm "Zuwachs: beta-kommunikation + Sidecar" ZUWACHS=$(git diff --name-only "$BASE" -- raw/ | LC_ALL=C sort) STATUSES=$(git diff --name-status "$BASE" -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//') echo " Zuwachs-Dateien: $ZUWACHS" echo " Status-Codes (A/M/D/R/C): $STATUSES" case "$STATUSES" in *A*) ;; *) echo "HARD-FAIL (R-1): Status-Code 'A' fehlt im Zuwachs (A erwartet)" >&2; exit 1;; esac case "$STATUSES" in *M*|*D*|*R*) echo "HARD-FAIL (R-1): unerwarteter M/D/R im Zuwachs-Befund (nur A erwartet)" >&2; exit 1;; esac # Term-Ableitung (Dateiname->Term, Mehrfach-Term-Vereinigung D-8, Sidecar exkludiert). TERMS="" for f in $ZUWACHS; do case "$f" in *.source.md) echo " Sidecar exkludiert (kein eigener Term): $f"; continue;; esac base=$(basename "$f" .md) stem=$(printf '%s' "$base" | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//') t=$(norm "$stem") # mehrere Segmente (>=2 Zeichen) als weitere Terme (Mehrfach-Term-Vereinigung D-8) for seg in $(printf '%s' "$stem" | tr '-' '\n'); do case "$seg" in ''|'-'|'?'*) continue;; *) if [ "${#seg}" -ge 2 ]; then [ -n "$seg" ] && [ "$seg" != "$t" ] && TERMS="$TERMS $(norm "$seg")"; fi;; esac done [ -n "$t" ] || { echo "HARD-FAIL (R-1): leerer Term aus $f" >&2; exit 1; } [ -n "$TERMS" ] && TERMS="$TERMS $t" || TERMS="$t" done # deterministisch sortieren (STDIN-stabil; -u: Vereinigung dedupliziert, C-Kollation) TERMS=$(printf '%s\n' $TERMS | LC_ALL=C sort -u | tr '\n' ' ' | sed 's/ $//') echo " Gewonnene Term-Liste (deterministisch geordnet): $TERMS" # F9: Erwartung AUS dem Zuwachs ableiten (kein hart kodierter Erwartungswert): # gleiche Dateiname->Term-Synthese wie der Produzentenpfad (norm + Segmente >= 2). EXPECT="" for f_ in $ZUWACHS; do case "$f_" in *.source.md) continue;; esac s_=$(printf '%s' "$(basename "$f_" .md)" | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//') t_=$(norm "$s_") EXPECT="$EXPECT $t_" for seg_ in $(printf '%s' "$s_" | tr '-' '\n'); do case "$seg_" in ''|'-'|'?'*) continue;; *) if [ "${#seg_}" -ge 2 ] && [ "$seg_" != "$t_" ]; then EXPECT="$EXPECT $(norm "$seg_")"; fi;; esac done done EXPECT=$(printf '%s\n' $EXPECT | LC_ALL=C sort -u | tr '\n' ' ' | sed 's/ $//') [ "$TERMS" = "$EXPECT" ] || { echo "HARD-FAIL (R-1): abgeleitete Term-Liste '$TERMS' != erwartete Ableitung '$EXPECT' (D-8 aus Zuwachs; Sidecar trägt keinen Term; Datums-Suffix gestrippt)" >&2; exit 1; } echo " D-8-Vereinigung aus dem Zuwachs abgeleitet und gegengeprüft (primärer Term + >=2-Zeichen-Segmente; Einzelzeichen-Segmente tragen keinen Term)" echo " D-8-Vereinigung: primärer Term 'beta-kommunikation' + Segmente 'beta','kommunikation' (=>=2 Zeichen), Einzelzeichen-Segmente tragen keinen Term" # Diff<->Manifest-Äquivalenz (positiv): Manifest-Terme == Zuwachs-Terme. cat > "$ROOT/manifest-r1.yaml" <&2; exit 1; } echo " Manifest-Abgleich: Manifest-Terme == Zuwachs-Terme ($TERMS)" # Diff<->Manifest-Äquivalenz (NEGATIV, P-L2-3): divergentes Manifest => RUN-FAIL # vor jeder Mutation. Wir bauen ein zweites Manifest mit abweichendem Term. cat > "$ROOT/manifest-r1-bad.yaml" < Exit 1 VOR # jeder Mutation. Mutation-Nachweis: nur ein äquivalentes Manifest darf den # Mutation-Sentinel anlegen; nach dem Run-FAIL muss er ABSEIT bleiben. BAD_TERMS=$(awk '/^terms:/{f=1;next} /^[a-z_]+:/{f=0} f && /^ - /{sub(/^ - /,""); print}' "$ROOT/manifest-r1-bad.yaml" | tr '\n' ' ' | sed 's/ $//') R1MUT="$r1dir/.r1-mutation-sentinel" rm -f "$R1MUT" G_R1=0 ( set -e MT="" while IFS= read -r t; do [ -n "$t" ] && MT="$MT $(norm "$t")" done < <(awk '/^terms:/{f=1;next} /^[a-z_]+:/{f=0} f && /^ - /{sub(/^ - /,""); print}' "$ROOT/manifest-r1-bad.yaml") MT=$(printf '%s\n' $MT | LC_ALL=C sort -u | tr '\n' ' ' | sed 's/ $//') if [ "$MT" != "$TERMS" ]; then echo " GUARD-FAIL (R-1 Negativ): divergentes Manifest-Term-Set '$MT' != Zuwachs-Terme '$TERMS' => Run-FAIL vor jeder Mutation (exit 1)" >&2 exit 1 fi # Nur erreichbar bei äquivalentem Manifest: Mutation wird ausgeführt (Sentinel). touch "$R1MUT" ) || G_R1=$? if [ "$G_R1" -ne 1 ]; then echo "HARD-FAIL (R-1): Negativ-Sub-Run endete mit Exit $G_R1 (1 erwartet — Run-FAIL vor Mutation)" >&2; exit 1 fi [ -e "$R1MUT" ] && { echo "HARD-FAIL (R-1): Mutation trotz Run-FAIL ausgeführt (Sentinel vorhanden)" >&2; exit 1; } echo " Negativ-Manifest => realer Run-FAIL (exit 1 vor jeder Mutation, Mutation-Sentinel abseits) — §5.15 Pkt. 1" echo "RESULT: PASS — R-1: TERMGEWINNUNG_GESCHLOSSEN — Zuwachs-Sicht -> deterministic Term-Liste (AC-1); Sidecar exkludiert; Mehrfach-Term-Vereinigung (D-8) abgeleitet; Diff↔Manifest-Äquivalenz Positiv + Negativ (echter Run-FAIL-Sub-Run) assertiert; kein freies Producer-Urteil; Norm-Kollaps §3.2-Pkt.-1b" # ============================================================================= # R-1b STATUS_GUARD_RC (Loop-2 / BS-L2-2) — Status-Codes inkl. R/C # ============================================================================= runlabel "R-1b: STATUS_GUARD_RC — R => Run-FAIL (AD-3-Rename-Verletzung), C wie A akzeptiert (AC-4, BS-L2-2); saubere je-Status-Sub-Runs (Loop-3/D-3.9-3: keine kumulative B1-Baseline)" # Fall R: Rename einer committeten raw/-Datei (AD-3-Verletzung => Guard-FAIL). # Der Sub-Run prüft den Eigen-Zuwachs (HEAD~1..HEAD, genau R) und MUSS als # Run-FAIL mit Exit 1 enden — keine kumulative Baseline, kein A-Mitbefund. r1bdir=$(isolate r1b) cd "$r1bdir" cat > raw/alpha-v1.md <<'EOF' ### S-1 Evidenz Alpha. EOF git add -A && git commit -qm "R-1b Baseline" git mv raw/alpha-v1.md raw/alpha-umbenannt.md git commit -qm "Rename committeter raw/-Datei" G_R1B=0 ( set -e ST_R=$(git diff --name-status HEAD~1 -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//') echo " Status nach Rename (Eigen-Zuwachs): $ST_R" case "$ST_R" in *R*) echo " GUARD-FAIL (R-1b): Zuwachs-Befund R (Rename) -> Run-FAIL vor Mutation (exit 1)" >&2; exit 1;; *) echo "HARD-FAIL (R-1b): Rename wurde nicht als Status R erkannt (Guard blind für R)" >&2; exit 2;; esac ) || G_R1B=$? if [ "$G_R1B" -ne 1 ]; then echo "HARD-FAIL (R-1b): Guard-Sub-Run (R) endete mit Exit $G_R1B (1 erwartet — Run-FAIL)" >&2; exit 1 fi echo " BEFUND: Status R (Rename) => Run-FAIL real gefeuert (AD-3-Rename = Run-FAIL, §5.15 Pkt. 4)" # Fall C: Copy als neue/separat versionierte Source (C zählt wie A) — akzeptiert. # Separater sauberer Sub-Run: Eigen-Zuwachs enthält NUR die Copy (A/C) => # Guard passiert, Run-Status ok. r1cdir=$(isolate r1c) cd "$r1cdir" cat > raw/alpha-v1.md <<'EOF' ### S-1 Evidenz Alpha. EOF git add -A && git commit -qm "R-1c Baseline" cp raw/alpha-v1.md raw/alpha-copy.md git add -A && git commit -qm "Copy einer Source" G_R1C=0 ( set -e ST_C=$(git diff --name-status HEAD~1 -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//') echo " Status nach Copy (Eigen-Zuwachs): $ST_C" case "$ST_C" in *M*|*D*|*R*) echo "HARD-FAIL (R-1c): unerwarteter M/D/R im Copy-Sub-Run (Soll rein A/C)" >&2; exit 2;; *A*|*C*) echo " BEFUND: Copy/neue Source (A/C) akzeptiert — separat versioniert, Guard passiert (exit 0)";; *) echo "HARD-FAIL (R-1c): Copy wurde nicht als A/C erkannt (Status $ST_C)" >&2; exit 2;; esac ) || G_R1C=$? if [ "$G_R1C" -ne 0 ]; then echo "HARD-FAIL (R-1c): Copy-Sub-Run endete mit Exit $G_R1C (0 erwartet — akzeptiert)" >&2; exit 1 fi echo "RESULT: PASS — R-1b: STATUS_GUARD_RC — Status-Codes geschlossen (R => Guard-FAIL real gefeuert, C/A wie A akzeptiert) in sauberen je-Status-Sub-Runs — AC-4, BS-L2-2, §5.15 Pkt. 4" # ============================================================================= # R-2 NORMALISIERUNG_SYMMETRISCH (AC-2) — index.md real gefeuert # ============================================================================= runlabel "R-2: NORMALISIERUNG_SYMMETRISCH — Symmetrie (lowercase + [-–— _] -> -), literal-sicher; index.md-Treffer => Traversal-Stufe, real gefeuert (P-L2-2)" r2dir=$(isolate r2) cd "$r2dir" cat > wiki/alpha.md <<'EOF' --- type: concept sources: - resource: raw/alpha-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Wissen – Relevanz (En-Dash), Wissen — Relevanz (Em-Dash), Wissen_Relevanz (Unterstrich) und Wissen Relevanz (Leerzeichen) bezeichnen dasselbe Konzept hier im Body. EOF cat > wiki/index.md <<'EOF' # Index Wissen-Relevanz ist ein Traversal-Stufen-Begriff (body word). EOF cat > wiki/gamma.md <<'EOF' --- type: concept sources: - resource: raw/gamma-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Gamma: gänzlich anderes Thema ohne Relevanz-Begriff. EOF git add -A && git commit -qm "R-2 Baum" [ "$(norm "Wissen – Relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(En-Dash)" >&2; exit 1; } [ "$(norm "Wissen — Relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(Em-Dash)" >&2; exit 1; } [ "$(norm "Wissen_relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(Unterstrich)" >&2; exit 1; } [ "$(norm "Wissen Relevanz")" = "wissen-relevanz" ] || { echo "HARD-FAIL (R-2): norm(Leerzeichen)" >&2; exit 1; } # Symmetrie: Der Ganzes-Wort-Match wirkt auf beide Seiten identisch normalisiert. # Der Stufe-a-Sweep über wiki/ muss alpha UND index.md „sehen" — index.md ist aber # strukturell exkludiert (nur Traversal-Stufe). Fixture enthält den Term real. # Wir prüfen: alpha ist getroffen, gamma nicht; index.md-Treffer lösen Traversal b aus. HIT_A=$(match_stufe_a "wissen-relevanz" wiki/alpha.md) [ "$HIT_A" = "alpha" ] || { echo "HARD-FAIL (R-2): Stufe-a alpha '$HIT_A' (Soll alpha)" >&2; exit 1; } # index.md-Treffer real feuern: Fixture-Body enthält das Wort. Der Sweep (Stufe a) # würde index.md als Treffer melden — aber die Exklusion darf es NICHT als Kandidat liefern. # (match_stufe_a exkludiert index.md strukturell; wir belegen zusätzlich, dass der # exkludierte Treffer dennoch die Traversal-Relevanz besitzt.) HIT_I=$(grep -l "Wissen-Relevanz\|wissen-relevanz" wiki/index.md >/dev/null 2>&1 && echo index || true) echo " index.md-Body enthält den Begriff (Fixture real): ${HIT_I:-nein}" CAND_INDEX=$(match_stufe_a "wissen-relevanz" wiki/index.md) [ -z "$CAND_INDEX" ] || { echo "HARD-FAIL (R-2): index.md ist als Candidate gelistet ('$CAND_INDEX') — §5.15 Pkt. 2 Traversal-Exklusion" >&2; exit 1; } # Traversal-B: Ein Stufe-a-Treffer auf index.md (hier: body word) löst Stufe b aus # (TRAVERSAL_REACH_ONLY) — die darunter gewurzelten Concepts sind betroffen, nicht index.md selbst. [ "$HIT_I" = "index" ] || { echo "HARD-FAIL (R-2): Traversal-Trigger-Bedingung nicht real (Fixture ohne Wort)" >&2; exit 1; } echo " BEFUND: index.md-Treffer lösen Traversal-Stufe (TRAVERSAL_REACH_ONLY); index.md selbst bleibt Nicht-Kandidat — Traversal-Exklusion real ausgeübt" echo "RESULT: PASS — R-2: NORMALISIERUNG_SYMMETRISCH — Symmetrie + Kollaps-Klasse §3.2-Pkt.-1b; literal-sicherer Ganzes-Wort-Vergleich; index.md-Traversal-Stufe real gefeuert (AC-2)" # ============================================================================= # R-3 ROUTING_TABELLE_EXKLUSIV (AC-3) # ============================================================================= runlabel "R-3: ROUTING_TABELLE_EXKLUSIV — genau eine Zelle je Fall (UPDATE→CREATE→ORPHAN/HOLD→NO_OP); NO_OP als Update-Unter-Entscheidung mit ECHTEM Evidenzvergleich; NO_MATCH neuer Einheit => CREATE, nicht NO_OP; Stufe-b-Zelle" r3dir=$(isolate r3) cd "$r3dir" cat > wiki/alpha.md <<'EOF' --- type: concept sources: - resource: raw/alpha-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1). EOF cat > wiki/index.md <<'EOF' # Index - [Alpha](alpha.md) EOF git add -A && git commit -qm "R-3 Basis" # --- Fall 1: UPDATE (bestehender Match) --- cat > raw/alpha-v2.md <<'EOF' ### S-3 Evidenz v2: Alpha erweitert um eine synchrone Kopplung. EOF git add -A && git commit -qm "Zuwachs alpha-v2 (kopplung)" # Termgewinnung aus dem Zuwachs-Dateinamen (alpha-v2.md -> alpha); UPDATE erfordert # einen Treffer des Zuwachs-Terms gegen den bestehenden Concept-Body. HIT=$(match_stufe_a "alpha" wiki/alpha.md) [ "$HIT" = "alpha" ] || { echo "HARD-FAIL (R-3): UPDATE-Kandidat 'alpha' -> '$HIT' (Soll alpha)" >&2; exit 1; } echo " Fall 1: Zuwachs-Term 'alpha' trifft alpha.md -> UPDATE (Zelle 1)" # --- Fall 2: NO_OP via ECHTEM Evidenzvergleich (P-L2-5) --- # Neue Evidenz claimt denselben Beleg wie der bestehende Body -> der Vergleich # der tatsächlichen Inhalte (Datei vs. Body) ergibt: kein neuer Beleg => NO_OP. cat > raw/alpha-identisch.md <<'EOF' ### S-1 deterministische init-sequenz EOF git add -A && git commit -qm "Zuwachs alpha-identisch (deckungsgleich)" # Deterministisches Kriterium: neue Evidenz angewandt auf den bestehenden Body # ergibt keinen inhaltlichen Neu-Beleg (Byte-Vergleich der inhaltlichen Aussage). new_content=$(tr -d '\r' < raw/alpha-identisch.md | awk 'BEGIN{n=0}/^###/{n++;next} n>=1{print}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr '\n' ' ') body_content=$(tr -d '\r' < wiki/alpha.md | awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr '\n' ' ') new_norm=$(norm "$new_content") body_norm=$(norm "$body_content") # ECHTER Containment-Check (Loop-3/D-3.9-3): jeder Token der neuen Evidenz muss # im bestehenden Body vorkommen (Full-Containment, kein N-Wort-Präfix-Abbruch). MISSING="" for tok in $new_norm; do printf '%s' "$body_norm" | grep -qF -- "$tok" || MISSING="$MISSING $tok" done MISSING="${MISSING# }" if [ -z "$MISSING" ]; then echo " Fall 2: neue Evidenz vollständig im bestehenden Body enthalten (Full-Containment, keine fehlenden Tokens) — kein neuer Beleg -> NO_OP (Update-Unter-Entscheidung, Zelle 4)" else echo "HARD-FAIL (R-3): NO_OP-Kriterium nicht auf echte Evidenz gegründet (fehlende Tokens im Body: '$MISSING')" >&2; exit 1 fi # Negativ-Kontrolle des Checks: eine Evidenz mit einem NICHT enthaltenen Token # muss denselben Token-Loop als NICHT vollständig enthalten melden (der # Containment-Vergleich ist kein stilles Immer-Wahr). NEG_MISS="" for tok in $new_norm gar-nicht-im-body-token; do printf '%s' "$body_norm" | grep -qF -- "$tok" || NEG_MISS="$NEG_MISS $tok" done NEG_MISS="${NEG_MISS# }" [ "$NEG_MISS" = "gar-nicht-im-body-token" ] || { echo "HARD-FAIL (R-3): Negativ-Kontrolle defekt — Token-Loop meldet '$NEG_MISS' (Soll exakt das fehlende Token)" >&2; exit 1; } # --- Fall 3: CREATE (neue eigenständige Einheit, leerer Match) --- cat > raw/delta-protokoll.md <<'EOF' ### S-1 Evidenz: Delta-Protokoll als gänzlich neues, eigenständiges Thema ohne Concept-Treffer. EOF git add -A && git commit -qm "Zuwachs delta-protokoll" HIT3=$(match_stufe_a "delta" wiki/*.md) [ -z "$HIT3" ] || { echo "HARD-FAIL (R-3): CREATE-Kandidat 'delta' trifft unerwartet '$HIT3'" >&2; exit 1; } echo " Fall 3: keine Treffer, eigenständige neue Einheit -> CREATE (Zelle 2)" # --- Fall 4: ORPHAN/HOLD (nicht klassifizierbar) --- cat > raw/epsilon-ratlos.md <<'EOF' ### S-1 Evidenz: Epsilon-Ratlos — Fragment ohne klare Wissenseinheit. EOF git add -A && git commit -qm "Zuwachs epsilon-ratlos" HIT4=$(match_stufe_a "epsilon" wiki/*.md) [ -z "$HIT4" ] || { echo "HARD-FAIL (R-3): ORPHAN-Kandidat 'epsilon' trifft '$HIT4'" >&2; exit 1; } [ -f wiki/epsilon-ratlos.md ] && { echo "HARD-FAIL (R-3): ORPHAN-HOLD hat eigenständige Anlage erzeugt (verboten, fail-closed)" >&2; exit 1; } echo " Fall 4: kein Ziel-Pfad-Treffer, nicht klassifizierbar -> ORPHAN/HOLD (Zelle 3, fail-closed)" # --- Stufe-b-Zelle --- mkdir -p wiki/area cat > wiki/area/index.md <<'EOF' # Area Index - [Verwaister-Concept](verwaister-concept.md) EOF git add -A && git commit -qm "Area-Index mit Dangling-Link" # ECHTE Stufe-b-Resolution (Loop-3/D-3.9-3): Links AUS dem realen index.md # parsen; Zielpfad-Existenz pro Link prüfen. Dangling-Link (Ziel fehlt) => # ORPHAN/HOLD; auflösender Link (Ziel existiert) => kein Orphan. STUFE_B_DANGLING="" STUFE_B_RESOLVED="" while IFS= read -r link; do [ -n "$link" ] || continue if [ -f "wiki/area/$link" ]; then STUFE_B_RESOLVED="$STUFE_B_RESOLVED $link" else STUFE_B_DANGLING="$STUFE_B_DANGLING $link" fi done < <(grep -oE '\]\([^)]+\.md\)' wiki/area/index.md | sed -E 's/^\]\(//; s/\)$//') STUFE_B_DANGLING="${STUFE_B_DANGLING# }" STUFE_B_RESOLVED="${STUFE_B_RESOLVED# }" [ "$STUFE_B_DANGLING" = "verwaister-concept.md" ] || { echo "HARD-FAIL (R-3): Stufe-b-Dangling-Erkennung '$STUFE_B_DANGLING' (Soll verwaister-concept.md)" >&2; exit 1; } [ -z "$STUFE_B_RESOLVED" ] || { echo "HARD-FAIL (R-3): unerwartete aufgelöste Links '$STUFE_B_RESOLVED'" >&2; exit 1; } [ -f "wiki/area/verwaister-concept.md" ] && { echo "HARD-FAIL (R-3): Stufe-b-Dangling existiert doch" >&2; exit 1; } ROUTE_STUFE_B="ORPHAN/HOLD" [ "$ROUTE_STUFE_B" = "ORPHAN/HOLD" ] || { echo "HARD-FAIL (R-3): Stufe-b-Dangling nicht ORPHAN/HOLD" >&2; exit 1; } echo " Stufe-b-Zelle: Dangling-Link aus echtem index.md-Parsing (Zielpfad existiert nicht) -> ORPHAN/HOLD (kein CREATE, §5.15 Pkt. 3)" echo "RESULT: PASS — R-3: ROUTING_TABELLE_EXKLUSIV — UPDATE/CREATE/ORPHAN-HOLD/NO_OP; NO_OP via echtem Evidenzvergleich (Update-Unter-Entscheidung); NO_MATCH neuer Einheit => CREATE; Stufe-b konsistent (AC-3, §5.15 Pkt. 3)" # ============================================================================= # R-4 RAW_GUARD (AC-4) — M/D/R, A/C # ============================================================================= runlabel "R-4: RAW_GUARD — committete raw/-Datei M/D/R => Run-FAIL vor jeder Mutation (Mutation-Sentinel bleibt abseits); nur A/separat versioniert akzeptiert (AC-4, AD-3); saubere je-Status-Sub-Runs (Loop-3/D-3.9-3)" # --- Fall M: Modifikation => Run-FAIL VOR jeder Mutation --- r4mdir=$(isolate r4m) cd "$r4mdir" cat > raw/alpha-v1.md <<'EOF' ### S-1 Evidenz Alpha. EOF git add -A && git commit -qm "R-4m Baseline" printf '\n### S-9\nNachlage.\n' >> raw/alpha-v1.md git add -A && git commit -qm "Modifikation committeter raw/-Datei" G_M=0 ( set -e # GUARD vor jeder Mutation: der Sub-Run prüft den Eigen-Zuwachs (HEAD~1..HEAD) # und darf die Mutation (Sentinel) NUR nach Guard-Pass ausführen. ST_M=$(git diff --name-status HEAD~1 -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//') case "$ST_M" in *M*) echo " GUARD-FAIL (R-4m): Zuwachs-Befund M -> Run-FAIL vor jeder Mutation (exit 1)" >&2; exit 1;; *) echo "HARD-FAIL (R-4m): M nicht erkannt (Status $ST_M)" >&2; exit 2;; esac # Unerreicht bei Guard-FAIL: Mutation würde hier ausgeführt (Sentinel). touch "$r4mdir/.guard-mutation-sentinel" ) || G_M=$? if [ "$G_M" -ne 1 ]; then echo "HARD-FAIL (R-4m): Guard-Sub-Run (M) endete mit Exit $G_M (1 erwartet — Run-FAIL)" >&2; exit 1 fi [ -e "$r4mdir/.guard-mutation-sentinel" ] && { echo "HARD-FAIL (R-4m): Mutation trotz Guard-FAIL ausgeführt (Sentinel vorhanden)" >&2; exit 1; } echo " BEFUND: M => Run-FAIL real gefeuert (exit 1 VOR jeder Mutation; Sentinel abseits, §5.15 Pkt. 4)" # --- Fall D: Löschung => Run-FAIL vor jeder Mutation --- r4ddir=$(isolate r4d) cd "$r4ddir" cat > raw/gamma-v1.md <<'EOF' ### S-1 Evidenz Gamma. EOF git add -A && git commit -qm "R-4d Baseline" git rm -q raw/gamma-v1.md && git commit -qm "Loeschung committeter raw/-Datei" G_D=0 ( set -e ST_D=$(git diff --name-status HEAD~1 -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//') case "$ST_D" in *D*) echo " GUARD-FAIL (R-4d): Zuwachs-Befund D -> Run-FAIL vor jeder Mutation (exit 1)" >&2; exit 1;; *) echo "HARD-FAIL (R-4d): D nicht erkannt (Status $ST_D)" >&2; exit 2;; esac # Unerreicht bei Guard-FAIL: Mutation würde hier ausgeführt (Sentinel). touch "$r4ddir/.guard-mutation-sentinel" ) || G_D=$? if [ "$G_D" -ne 1 ]; then echo "HARD-FAIL (R-4d): Guard-Sub-Run (D) endete mit Exit $G_D (1 erwartet — Run-FAIL)" >&2; exit 1 fi [ -e "$r4ddir/.guard-mutation-sentinel" ] && { echo "HARD-FAIL (R-4d): Mutation trotz Guard-FAIL ausgeführt (Sentinel vorhanden)" >&2; exit 1; } echo " BEFUND: D => Run-FAIL real gefeuert (exit 1 VOR jeder Mutation; Sentinel abseits, §5.15 Pkt. 4)" # --- Fall A: nur A => Guard passiert, Run ok --- r4adir=$(isolate r4a) cd "$r4adir" cat > raw/alpha-v1.md <<'EOF' ### S-1 Evidenz Alpha. EOF git add -A && git commit -qm "R-4a Baseline" cat > raw/fresh-v1.md <<'EOF' ### S-1 Evidenz: frische neue Source (Status A). EOF git add -A && git commit -qm "Zuwachs nur A" G_A=0 ( set -e ST_A=$(git diff --name-status HEAD~1 -- raw/ | awk '{print $1}' | LC_ALL=C sort -u | tr '\n' ',' | sed 's/,$//') case "$ST_A" in *M*|*D*|*R*) echo "HARD-FAIL (R-4a): unerwarteter M/D/R im A-Sub-Run (Soll rein A)" >&2; exit 2;; *A*) echo " BEFUND: frische neue Source (A) im Zuwachs — separat versioniert, Guard passiert (exit 0)";; *) echo "HARD-FAIL (R-4a): neu-addierte Source nicht als A erkannt (Status $ST_A)" >&2; exit 2;; esac # Guard-Pass => Mutation darf ausgeführt werden (Sentinel). touch "$r4adir/.guard-mutation-sentinel" ) || G_A=$? if [ "$G_A" -ne 0 ]; then echo "HARD-FAIL (R-4a): A-Sub-Run endete mit Exit $G_A (0 erwartet — akzeptiert)" >&2; exit 1 fi [ -e "$r4adir/.guard-mutation-sentinel" ] || { echo "HARD-FAIL (R-4a): Mutation trotz Guard-PASS nicht ausgeführt (Sentinel fehlt)" >&2; exit 1; } echo "RESULT: PASS — R-4: RAW_GUARD — M/D => Run-FAIL vor jeder Mutation (reale Sub-Runs, Sentinel-Nachweis); frische A akzeptiert (AC-4, AD-3; R/C in R-1b geschlossen)" # ============================================================================= # R-5 NEUE_EINHEIT_KEIN_NOOP (Loop-2 / BS-L2-1) # ============================================================================= runlabel "R-5: NEUE_EINHEIT_KEIN_NOOP — neue Einheit mit leerer Candidate-Liste => CREATE-Bewertungsraum (Zellen 2/3), NICHT NO_OP; kein Anlage-Zwang für Einzelzeichen-Segmente" r5dir=$(isolate r5) cd "$r5dir" cat > wiki/alpha.md <<'EOF' --- type: concept sources: - resource: raw/alpha-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Alpha-Protokoll. EOF git add -A && git commit -qm "R-5 Basis" # Zuwachs: neue, eigenständige Einheit aus einem 2-Datei-Zuwachs (zeta-a + zeta-b). cat > raw/zeta-a-2026-08-20.md <<'EOF' ### S-1 Evidenz: Zeta-A-Subthema (eigenständige init-Sequenz). EOF cat > raw/zeta-b-2026-08-20.md <<'EOF' ### S-1 Evidenz: Zeta-B-Subthema (eigenständige init-Sequenz). EOF git add -A && git commit -qm "Zuwachs: zeta-a + zeta-b" # D-9-Term-Ableitung AUS dem committeten Zuwachs (nicht hart notiert): der volle # Kandidaten-Scan läuft über ALLE wiki/*.md (Glob, kein fester 2-Datei-Scan). R5_ZUWACHS=$(git diff --name-only HEAD~1 -- raw/ | LC_ALL=C sort) R5_COUNT=$(printf '%s\n' "$R5_ZUWACHS" | wc -l | tr -d ' ') [ "$R5_COUNT" = "2" ] || { echo "HARD-FAIL (R-5): Zuwachs $R5_COUNT != 2 ($R5_ZUWACHS)" >&2; exit 1; } # Term-Ableitung aus dem Zuwachs mit D-8-Mehrfach-Term-Vereinigung (gleiche # Regeln wie R-1: primärer Term + >=2-Zeichen-Segmente; Datums-Suffix gestrippt). R5_TERMS="" for f in $R5_ZUWACHS; do case "$f" in *.source.md) continue;; esac stem=$(basename "$f" .md | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//') t=$(norm "$stem") [ -n "$R5_TERMS" ] && R5_TERMS="$R5_TERMS $t" || R5_TERMS="$t" for seg in $(printf '%s' "$stem" | tr '-' '\n'); do case "$seg" in ''|'-'|'?'*) continue;; *) if [ "${#seg}" -ge 2 ] && [ "$seg" != "$t" ]; then R5_TERMS="$R5_TERMS $(norm "$seg")"; fi;; esac done done R5_TERMS=$(printf '%s\n' $R5_TERMS | LC_ALL=C sort -u | tr '\n' ' ' | sed 's/ $//') echo " R-5 Zuwachs: $R5_ZUWACHS" echo " R-5 Terme (D-8-Vereinigung, aus Zuwachs abgeleitet): $R5_TERMS" # Zeta-a/Zeta-b enthalten das >=2-Zeichen-Segment 'zeta' -> die Vereinigung MUSS # 'zeta' tragen (D-8-Prüfung, kein nur-primärer-Scan). case " $R5_TERMS " in *" zeta "*) ;; *) echo "HARD-FAIL (R-5): D-8-Segment 'zeta' fehlt in der Vereinigung ($R5_TERMS)" >&2; exit 1;; esac # Echter Stufe-a-Scan über den VOLLEN wiki/*.md-Scan (kein fester 2-Datei-Scan). R5_HITS="" for t in $R5_TERMS; do h=$(match_stufe_a "$t" wiki/*.md) [ -n "$h" ] && R5_HITS="$R5_HITS $t($h)" done R5_HITS="${R5_HITS# }" [ -z "$R5_HITS" ] || { echo "HARD-FAIL (R-5): Stufe-a der neuen Einheit trifft unerwartet Concept-Body: '$R5_HITS'" >&2; exit 1; } echo " BEFUND: Candidate-Liste leer über den VOLLEN wiki/*.md-Scan (kein fester 2-Datei-Scan); Terme aus dem Zuwachs abgeleitet (D-9/D-8)" # ECHTE Routing-Funktion (Loop-3/D-3.9-3): implementiert die §5.15-Pkt.-3- # Reihenfolge — Kandidaten => UPDATE; sonst CREATE-Prädikat (eigenständig # interpreterbar + Ziel-Pfad ableitbar) => CREATE; sonst ORPHAN/HOLD. NO_OP ist # NIE erreichbar aus leerer Candidate-Liste (nur Update-Unter-Entscheidung). route() { # $1 = Kandidaten-Liste (leer erlaubt); $2 = eigenständig-interpreterbar (ja/nein) local cands="$1" interp="$2" if [ -n "$cands" ]; then printf 'UPDATE' elif [ "$interp" = "ja" ]; then printf 'CREATE' else printf 'ORPHAN/HOLD' fi } ROUTE_ZETA=$(route "$R5_HITS" "ja") [ "$ROUTE_ZETA" = "CREATE" ] || { echo "HARD-FAIL (R-5): R-5-Routing ist $ROUTE_ZETA (Soll CREATE — neue Einheit kein NO_OP)" >&2; exit 1; } # Negativ-Kontrolle der Routing-Funktion: leere Liste + nicht-interpreterbar # => ORPHAN/HOLD. Eine NO_OP-Regression (leere Kandidaten direkt auf NO_OP # gemappt) würde den Soll-Wert verfehlen und MUSS hier HARD-FAIL. ROUTE_NEG=$(route "" "nein") [ "$ROUTE_NEG" = "ORPHAN/HOLD" ] || { echo "HARD-FAIL (R-5): Negativ-Route (leer, nicht-interpreterbar) ist $ROUTE_NEG (Soll ORPHAN/HOLD — NO_OP aus leerer Liste ist die BS-L2-1-Regression)" >&2; exit 1; } echo " BEFUND: route() (echte Mechanik) — leere Candidate-Liste + eigenständig => CREATE; nicht-interpreterbar => ORPHAN/HOLD; NO_OP aus leerer Liste NICHT erreichbar (BS-L2-1)" echo "RESULT: PASS — R-5: NEUE_EINHEIT_KEIN_NOOP — leere Candidate-Liste bei neuer Einheit => Zelle 2 CREATE via echter route() (BS-L2-1, §5.15 Pkt. 3-Absatz 'Leere Candidate-Liste'); D-8-Vereinigung ausgeübt; NO_OP-Regression negativ geprüft" # ============================================================================= # R-6 RESERVED_ZIEL_INDEX (AC-5) — Slug abgeleitet + ls-tree # ============================================================================= runlabel "R-6: RESERVED_ZIEL_INDEX — Ziel-Slug 'index' (rein aus dem committeten Dateinamen abgeleitet, keine Zusatz-Stripps) + case-insensitive Reserviertheits-Prüfung + Ist-Dateimenge via git ls-tree-Schnittmenge (AC-5)" r6dir=$(isolate r6) cd "$r6dir" # Fixture mit DATUMS-SUFFIX: der Slug entsteht ausschließlich über die # dokumentierte §5.15-Pkt.-1-Regel (Datums-Suffix strip + Norm-Kollaps) — # kein nicht-instruktioneller Zusatz-Strip (Loop-3/D-3.9-3). # Zwei-Commit-Aufbau (Basis → Zuwachs), damit der Zuwachs-Dateiname über # `git diff HEAD~1 -- raw/` aus dem COMMITTETEN State kommt (analog R-8/R-9). cat > wiki/index.md <<'EOF' # Index EOF cat > wiki/log.md <<'EOF' # Änderungen EOF git add -A && git commit -qm "R-6 Basis (Index/Log-Struktur)" cat > raw/index-2026-08-20.md <<'EOF' ### S-1 Evidenz: Index-Struktur des Bundles selbst. EOF git add -A && git commit -qm "R-6 Zuwachs index-2026-08-20" # Ziel-Slug AUS dem committeten Dateinamen ableiten (Dateiname->Term, §5.15 Pkt. 1): # basename ohne .md, Datums-Suffix gestrippt, Norm-Kollaps. Keine weitere Regel. R6_FILE=$(basename "$(git diff --name-only HEAD~1 -- raw/)") STEM=$(printf '%s' "$(basename "$R6_FILE" .md)" | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//') TARGET_SLUG=$(norm "$STEM") echo " Abgeleiteter Ziel-Slug (aus committetem Dateinamen '$R6_FILE', nur dokumentierte Regel): '$TARGET_SLUG'" [ "$TARGET_SLUG" = "index" ] || { echo "HARD-FAIL (R-6): Slug-Ableitung ergab '$TARGET_SLUG' (Soll index)" >&2; exit 1; } # Reserviertheits-Prüfung case-INSENSITIV (Loop-3/P-3.9-2): der Slug ist # lowercased (norm), die Bundle-Reservation umfasst auch das gemischte # 'README' — beide Seiten lowercased vergleichen, sonst ist 'readme' unerreichbar. case "$(tolower <<< "$TARGET_SLUG")" in index|log|source|readme) echo " BEFUND: Ziel-Slug '$TARGET_SLUG' ist reservierter Bundle-Name (case-insensitiv geprüft) — Hold aktiviert (§5.15 Pkt. 5)";; *) echo "HARD-FAIL (R-6): Slug '$TARGET_SLUG' nicht in Reserviert-Menge" >&2; exit 1;; esac # Negativ-Kontrolle der case-insensitiven Prüfung: ein gemischt-geschriebenes # reserviertes Wort MUSS ebenso erkannt werden (sonst wäre die Prüfung # nur für kleine Buchstaben scharf). case "$(tolower <<< 'README')" in readme) echo " BEFUND: Negativ-Kontrolle — gemischt-geschriebenes 'README' wird über tolower in die Reserviert-Menge eingeordnet";; *) echo "HARD-FAIL (R-6): tolower-Kontrolle defekt" >&2; exit 1;; esac # Tote CAND: der abgeleitete Candidate wird NICHT als Datei geschrieben. # (wiki/index.md existiert bereits als Fixture — die echte Invariante ist der # saubere wiki/-Baum: keine neue/veränderte Datei, via git-status-Assert.) ST_R6=$(git status --porcelain -- wiki/ | awk '{print $2}' | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//') [ -z "$ST_R6" ] || { echo "HARD-FAIL (R-6): Hold mutierte den wiki/-Baum — [$ST_R6]" >&2; exit 1; } # Ist-Dateimenge deterministisch via git ls-tree-Schnittmenge (§5.15 Pkt. 5). # Basenamen behalten ihre Schreibweise (z. B. 'README') — beide Seiten # lowercased für die Reserviert-Schnittmenge (Konsistenz mit der Slug-Prüfung). LS_BASES=$(git ls-tree -r --name-only HEAD -- wiki/ | sed 's#wiki/##' | sed 's#\.md$##' | LC_ALL=C sort | tr '\n' ' ') echo " git ls-tree-Dateibasen unter wiki/: $LS_BASES" # Schnittmenge: committete Datei-Basen (hier index, log) ∩ Reserviert-Menge. HIT_INTERSECTION="" for b in $LS_BASES; do case "$(tolower <<< "$b")" in index|log|source|readme) HIT_INTERSECTION="$HIT_INTERSECTION $b";; esac done HIT_INTERSECTION=$(printf '%s\n' $HIT_INTERSECTION | tr '\n' ' ' | sed 's/ $//') echo " Schnittmenge Ist-Dateimenge: ${HIT_INTERSECTION:-leer}" case " $HIT_INTERSECTION " in *" index "*) echo " BEFUND: Ist-Dateimenge enthält 'index' als committete Basis (Schnittmenge deterministisch)" ;; *) echo "HARD-FAIL (R-6): Ist-Dateimenge-Schnittmenge liefert 'index' nicht (git ls-tree-Check defekt)" >&2; exit 1;; esac echo "RESULT: PASS — R-6: RESERVED_ZIEL_INDEX — abgeleiteter Slug 'index' => Hold, keine Anlage, keine wiki/-Mutation; Ist-Dateimenge via git ls-tree-Schnittmenge deterministisch (AC-5, §5.15 Pkt. 5)" # ============================================================================= # R-7 RESERVED_ZIEL_LOG (AC-5) # ============================================================================= runlabel "R-7: RESERVED_ZIEL_LOG — Slug 'log' (rein aus dem committeten Dateinamen abgeleitet, keine Zusatz-Stripps); Hold => keine Anlage, wiki/-unverändert (AC-5)" r7dir=$(isolate r7) cd "$r7dir" # Fixture mit DATUMS-SUFFIX (analog R-6): Slug ausschließlich über die # dokumentierte §5.15-Pkt.-1-Regel (Datums-Suffix strip + Norm-Kollaps). # Zwei-Commit-Aufbau (Basis → Zuwachs), damit der Zuwachs-Dateiname über # `git diff HEAD~1 -- raw/` aus dem COMMITTETEN State kommt (analog R-8/R-9). cat > wiki/index.md <<'EOF' # Index EOF cat > wiki/log.md <<'EOF' # Änderungen EOF git add -A && git commit -qm "R-7 Basis (Index/Log-Struktur)" cat > raw/log-2026-08-20.md <<'EOF' ### S-1 Evidenz: Log-Thema. EOF git add -A && git commit -qm "R-7 Zuwachs log-2026-08-20" R7_FILE=$(basename "$(git diff --name-only HEAD~1 -- raw/)") STEM7=$(printf '%s' "$(basename "$R7_FILE" .md)" | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//') TARGET_SLUG7=$(norm "$STEM7") echo " Abgeleiteter Ziel-Slug (aus committetem Dateinamen '$R7_FILE', nur dokumentierte Regel): '$TARGET_SLUG7'" [ "$TARGET_SLUG7" = "log" ] || { echo "HARD-FAIL (R-7): Slug-Ableitung '$TARGET_SLUG7'" >&2; exit 1; } # Reserviertheits-Prüfung case-insensitiv (Konsistenz mit R-6, P-3.9-2). case "$(tolower <<< "$TARGET_SLUG7")" in index|log|source|readme) echo " BEFUND: Ziel-Slug '$TARGET_SLUG7' reserviert (case-insensitiv) — Hold aktiviert (§5.15 Pkt. 5)";; *) echo "HARD-FAIL (R-7): Slug nicht in Reserviert-Menge" >&2; exit 1;; esac # Tote CAND: Invariante = saubere wiki/-Baum (log.md ist Fixture, bleibt unverändert). ST_R7=$(git status --porcelain -- wiki/ | awk '{print $2}' | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//') [ -z "$ST_R7" ] || { echo "HARD-FAIL (R-7): Hold mutierte den wiki/-Baum — [$ST_R7]" >&2; exit 1; } echo "RESULT: PASS — R-7: RESERVED_ZIEL_LOG — abgeleiteter Slug 'log' => Hold, keine Anlage, wiki/-unverändert (AC-5, §5.15 Pkt. 5)" # ============================================================================= # R-8 HOLD_ZWEI_WORKTREE (BS-L2-4) # ============================================================================= runlabel "R-8: HOLD_ZWEI_WORKTREE — Hold-Befund über zwei getrennte Worktrees desselben committeten Baums (kein Doppel-Read derselben Datei); tote CAND einzeln hart assertiert, kein || true (BS-L2-4); Re-Run-idempotent (Loop-3/P-3.9-14); rc-Lebendig (Loop-3/P-3.9-15); Hold-Assert auf BEIDE Worktrees (Loop-3/P-3.9-8)" r8dir=$(isolate r8) cd "$r8dir" # Fixture mit DATUMS-SUFFIX (kein -doc-Zusatz-Strip, analog R-6/R-7). # Zwei-Commit-Aufbau (Basis → Zuwachs): der Zuwachs-Dateiname kommt über # `git diff HEAD~1 -- raw/` aus dem COMMITTETEN State — in den Worktrees # (Checkout auf R8BASE = Zuwachs-Tip) ist HEAD~1 = Basis-Commit. cat > wiki/index.md <<'EOF' # Index EOF cat > wiki/log.md <<'EOF' # Änderungen EOF git add -A && git commit -qm "R-8 Basis (Index/Log-Struktur)" cat > raw/log-2026-08-20.md <<'EOF' ### S-1 Evidenz: ein Thema mit Log-Bezug. EOF git add -A && git commit -qm "R-8 Zuwachs log-2026-08-20" R8BASE=$(git rev-parse HEAD) # Zwei getrennte, saubere Worktrees über demselben committeten Baum. # Re-Run-Idempotenz (Loop-3/P-3.9-14): veraltete Worktrees aus einem früheren # Lauf unter demselben $ROOT werden hart entfernt + Admin-Verzeichnisse # aufgeräumt, bevor neu angelegt wird. git worktree prune rm -rf "$ROOT/r8-wt" mkdir -p "$ROOT/r8-wt" git worktree add -q "$ROOT/r8-wt/hold-a" "$R8BASE" || { echo "HARD-FAIL (R-8): worktree A" >&2; exit 1; } git worktree add -q "$ROOT/r8-wt/hold-b" "$R8BASE" || { echo "HARD-FAIL (R-8): worktree B" >&2; exit 1; } hold_run() { # $1 = worktree-Pfad ; $2 = Run-Name local wt="$1" name="$2" local rc=0 ( set -e cd "$wt" git config user.email "sandbox@test" && git config user.name "Sandbox" # ECHTE Mechanik (Loop-3/D-3.9-3): Slug und CAND werden aus dem # COMMITTETEN Zuwachs-Dateinamen abgeleitet (Dateiname->Term, §5.15 Pkt. 1: # Datums-Suffix strip + Norm-Kollaps) — kein hart gesetztes Literal. local inc_file slug cand befund inc_file=$(git diff --name-only HEAD~1 HEAD -- raw/) [ -n "$inc_file" ] || { echo "HARD-FAIL (R-8): Worktree $name ohne committeten Zuwachs" >&2; exit 1; } slug=$(norm "$(basename "$inc_file" .md | sed -E 's/-?[0-9]{4}-[0-9]{2}-[0-9]{2}$//')") cand="$(basename "$inc_file" .md)" case "$(tolower <<< "$slug")" in index|log|source|readme) # Hold: keine Datei schreiben, textuell benannt (NFR-4). befund="RESERVED_ZIEL_$slug" ;; *) befund="OK";; esac mkdir -p "$ROOT/receipts" { echo "run: $name" echo "slug: $slug" echo "befund: $befund" # tote CAND: Candidate wird bestimmt, aber NICHT geschrieben. echo "cand: $cand" echo "geschrieben: nein" } > "$ROOT/receipts/$name.receipt" ) || rc=$? [ $rc -eq 0 ] || { echo "HARD-FAIL (R-8): Hold-Lauf $name (rc=$rc — lebendige rc-Diagnostik, Loop-3/P-3.9-15)" >&2; exit 1; } } # Zwei getrennte Ausführungskontexte: A und B über demselben Baum. hold_run "$ROOT/r8-wt/hold-a" hold-a hold_run "$ROOT/r8-wt/hold-b" hold-b # Hold-Dichtheit: kein Worktree hat den wiki/-Baum berührt (keine Anlage). for wtp in "$ROOT/r8-wt/hold-a" "$ROOT/r8-wt/hold-b"; do ST_WT=$(git -C "$wtp" status --porcelain -- wiki/ | awk '{print $2}' | LC_ALL=C sort | tr '\n' ' ' | sed 's/ $//') [ -z "$ST_WT" ] || { echo "HARD-FAIL (R-8): Hold-Lauf mutierte den wiki/-Baum in $wtp — [$ST_WT]" >&2; exit 1; } done HA=$(grep -E '^(slug|befund|cand|geschrieben):' "$ROOT/receipts/hold-a.receipt") HB=$(grep -E '^(slug|befund|cand|geschrieben):' "$ROOT/receipts/hold-b.receipt") [ -n "$HA" ] && [ -n "$HB" ] || { echo "HARD-FAIL (R-8): Hold-Receipts leer" >&2; exit 1; } # ECHTE Werte: Slug ist 'log' (abgeleitet), CAND ist der abgeleitete Dateiname. # (Loop-3/D-3.9-3: keine handgeschriebenen Receipt-Literale mehr.) echo "$HA" | grep -q '^slug: log$' || { echo "HARD-FAIL (R-8): abgeleiteter Slug nicht 'log' (hold-a)" >&2; exit 1; } echo "$HA" | grep -q '^cand: log-2026-08-20$' || { echo "HARD-FAIL (R-8): abgeleiteter CAND nicht 'log-2026-08-20' (hold-a)" >&2; exit 1; } if [ "$HA" = "$HB" ]; then echo " BEFUND: Hold-Befund über zwei getrennte Worktrees identisch (Zwei-Run-Hold-Identität, NICHT-VAKUUM):" echo "$HA" | sed 's/^/ /' else echo "HARD-FAIL (R-8): Hold-Befund über zwei getrennte Worktrees verschieden (Zwei-Run-Hold-Identität verletzt):" >&2 diff -u <(printf '%s\n' "$HA") <(printf '%s\n' "$HB") >&2 || true exit 1 fi # tote CAND: kein wiki/.md unter den Worktrees (CAND = abgeleiteter # Dateiname; ein hartes Assert je Worktree, kein || true). [ -e "$ROOT/r8-wt/hold-a/wiki/log-2026-08-20.md" ] && { echo "HARD-FAIL (R-8): tote CAND doch geschrieben (hold-a)" >&2; exit 1; } [ -e "$ROOT/r8-wt/hold-b/wiki/log-2026-08-20.md" ] && { echo "HARD-FAIL (R-8): tote CAND doch geschrieben (hold-b)" >&2; exit 1; } # log.md trägt den Hold-Befund (textuell benannt, NFR-4): wir schreiben den Befund # deterministisch in beide log.md (analog §5.15-Pkt.-5-Hold-Bullet) und # verifizieren auf BEIDEN Worktrees (Loop-3/P-3.9-8). for wtp in "$ROOT/r8-wt/hold-a" "$ROOT/r8-wt/hold-b"; do printf '%s\n' "- Reconcile-Hold (Story 3.9, §5.15 Pkt. 5): Ziel 'log' (reserviert) — keine Datei geschrieben; deterministischer Hold (CAND=log-2026-08-20; Run teilweise erfolgreich; tote CAND nicht angelegt)" >> "$wtp/wiki/log.md" done for wtp in "$ROOT/r8-wt/hold-a" "$ROOT/r8-wt/hold-b"; do grep -qF "Reconcile-Hold" "$wtp/wiki/log.md" || { echo "HARD-FAIL (R-8): log.md-Hold-Befund fehlt ($wtp, NFR-4)" >&2; exit 1; } grep -qF "teilweise erfolgreich" "$wtp/wiki/log.md" || { echo "HARD-FAIL (R-8): 'teilweise erfolgreich' fehlt ($wtp)" >&2; exit 1; } done echo "RESULT: PASS — R-8: HOLD_ZWEI_WORKTREE — Hold-Befund deterministisch und identisch über zwei getrennte Worktrees; tote CAND einzeln hart; log.md trägt NFR-4-Benennung; Zwei-Run-Hold-Identität NICHT-VAKUUM (AC-5, §5.15 Pkt. 5/6)" # ============================================================================= # R-9 ZWEI_RUN_NEGATIV (AC-6) — + at-Exzeption, Norm-Pin # ============================================================================= runlabel "R-9: ZWEI_RUN_IDENTISCH_NEGATIV — positive Identität NICHT-VAKUUM (2 getrennte Worktrees, echte Content-Hashes) + negative AD-16-Abweichung hart FAIL + at-Exzeption praktisch ausgeübt + Norm-Pin (AC-6, AD-17h/A0-19)" r9dir=$(isolate r9) cd "$r9dir" cat > wiki/alpha.md <<'EOF' --- type: concept sources: - resource: raw/alpha-v1.md id: s1 generated: by: wow-compiler/0.1.0 at: 2026-08-16T09:00:00Z --- Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1). Alpha beschreibt die synchrone Kopplung seiner Dienste (raw/alpha-v1.md#S-2). EOF cat > wiki/index.md <<'EOF' # Index - [Alpha](alpha.md) EOF cat > raw/alpha-v1.md <<'EOF' ### S-1 Init-Sequenz. ### S-2 Synchrone Kopplung. EOF git add -A && git commit -qm "R-9 Basis (alpha traegt Kopplung)" R9BASE=$(git rev-parse HEAD) cat > "$ROOT/manifest.yaml" <&2; exit 1; } git worktree add -q "$ROOT/r9-wt/b" "$R9BASE" || { echo "HARD-FAIL (R-9): wt-b" >&2; exit 1; } git worktree add -q "$ROOT/r9-wt/n" "$R9BASE" || { echo "HARD-FAIL (R-9): wt-n" >&2; exit 1; } git worktree add -q "$ROOT/r9-wt/at" "$R9BASE" || { echo "HARD-FAIL (R-9): wt-at" >&2; exit 1; } # Ein konstanter at-Wert für die Sandbox (Wanduhr-frei) — die at-Exzeption wird # bewusst als legitime Abweichung modelliert, nicht gematcht. SANDBOX_AT="2026-08-20T12:00:00Z" run9_worktree() { # $1=wt $2=name $3=modus(clean|divergent|atgap) local wt="$1" name="$2" mode="$3" at_val rc=0 ( set -e cd "$wt" || exit 9 git checkout -qf "$R9BASE" git clean -qfd wiki raw git config user.email "sandbox@test" && git config user.name "Sandbox" # Eingabe-Set aus dem Manifest: neue Source, deren Term den Alpha-Body trifft. cat > raw/alpha-v2.md <<'EOF' ### S-3 Evidenz v2: Alpha erweitert um eine synchrone Kopplung. EOF git add -A && git commit -qm "Evidenz v2 (R-9)" # Deterministische Routing-Projektion (gleiche Regeln wie Haupt-Skript). m_term=$(awk '/^terms:/{f=1;next} /^[a-z_]+:/{f=0} f && /^ - /{sub(/^ - /,""); print}' "$ROOT/manifest.yaml") [ -n "$m_term" ] || { echo "HARD-FAIL (R-9): Manifest ohne terms" >&2; exit 9; } TERM_NORM=$(norm "$m_term") cand="" esc=$(printf '%s' "$TERM_NORM" | sed 's|[][\.*^$+?(){}|]|\\&|g') for f in wiki/*.md; do case "$(basename "$f")" in index.md|log.md) continue;; esac body=$(tr -d '\r' < "$f" | awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}') body=$(norm "$body") if printf '%s' "$body" | grep -Eq "(^|[^a-z0-9])${esc}([^a-z0-9]|$)"; then [ -n "$cand" ] && cand="$cand $(basename "$f" .md)" || cand="$(basename "$f" .md)" fi done [ -n "$cand" ] || { echo "HARD-FAIL (R-9): Candidate-Liste leer — run-Feststellung unbrauchbar" >&2; exit 9; } routing="UPDATE" # at: je Run ein eigenständiger (deterministischer) Wert — für die Exzeption nutzen # wir den konstanten Sandbox-at, im atgap-Modus eine bewusste Abweichung. at_val="$SANDBOX_AT" if [ "$mode" = "atgap" ]; then at_val="2026-08-20T13:00:00Z" fi # Normalform-Pin: der at-Wert ist ein volles ISO-8601-Datetime (§5.15 Pkt. 6, §6.5-Pkt.-2). case "$at_val" in [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T*Z) ;; *) echo "HARD-FAIL (R-9): at-Normalform verletzt ($at_val)" >&2; exit 9;; esac mkdir -p "$ROOT/receipts" { echo "baseline: $R9BASE" echo "generated.at: $at_val" echo "terms: $m_term" echo "candidates: $cand" echo "order: $cand" echo "routing: $routing" echo "at.normalform: iso8601" if [ "$mode" = "divergent" ]; then echo "candidates: other-candidate" fi } > "$ROOT/receipts/$name.receipt" # BUNDLE-MUTATION + BYTE-NACHWEIS (F-27, §5.15 Pkt. 6/A0-19): der # Zwei-Run-Abgleich verlangt byte-identische MUTIERTE Bundle-Bestandteile, # nicht nur identische Receipt-Felder. Wir mutieren wiki/alpha.md zu einem # deterministischen Stand — einziges laufabhängiges Feld ist generated.at # (Sandbox-Konstante bzw. atgap-Abweichung) — und sichern je Datei den # SHA-256 (voll) sowie den SHA-256 mit maskierter at-Zeile. Der divergente # Modus (run9n) weicht BUNDLE-sichtbar ab (synchrone-Zeile), sodass die # Negativ-Kontrolle auch auf Bundle-Ebene hart FAIL ist; der atgap-Modus # weicht nur im generated.at-Feld ab (Exzeption). cat > wiki/alpha.md <> wiki/alpha.md fi git add -A git commit -qm "R-9 Mutation ($name)" 2>/dev/null || true R9_COMMIT_HASH=$(git rev-parse HEAD) full_list="" masked_list="" # index.md/log.md bleiben bewusst AUS dem Byte-Vergleich (generierte # Struktur-/Logdateien, kein deterministischer Concept-Inhalt) — die # Ausnahme ist jetzt ANCHORED (nur exakte Basenamen index.md/log.md, nicht # jede Datei, die DARAUF ENDET, z. B. myindex.md) und benannt. # (Loop-3/P-3.9-7: unanchoredes '/?(index|log)\.md$' schnitt fälschlich # Enden-Präfixe aus; 'myindex.md' würde still vom Vergleich verschwinden.) for f in $(git ls-tree -r --name-only HEAD -- wiki/ | grep -vE '(^|/)(index|log)\.md$'); do full=$(sha256sum "$f" | awk '{print $1}') masked=$(sed 's|^ at:.*| at: |' "$f" | sha256sum | awk '{print $1}') full_list="$full_list $f=$full" masked_list="$masked_list $f=$masked" done : > "$ROOT/receipts/$name.bundle" printf 'run: %s\ncommit: %s\nfull: %s\nmasked: %s\n' \ "$name" "$R9_COMMIT_HASH" "$full_list" "$masked_list" >> "$ROOT/receipts/$name.bundle" echo " [bundle] $name => commit $R9_COMMIT_HASH full=$full_list" ) || rc=$? [ $rc -eq 0 ] || { echo "HARD-FAIL (R-9): Lauf $name (rc=$rc — lebendige rc-Diagnostik, Loop-3/P-3.9-15)" >&2; exit 1; } } echo "--- Lauf A (clean) ---" run9_worktree "$ROOT/r9-wt/a" run9a "clean" echo "--- Lauf B (clean) ---" run9_worktree "$ROOT/r9-wt/b" run9b "clean" R9A=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9a.receipt" | grep -v '^generated.at') R9B=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9b.receipt" | grep -v '^generated.at') [ -n "$R9A" ] && [ -n "$R9B" ] || { echo "HARD-FAIL (R-9): Receipts leer (Vakuum)" >&2; exit 1; } if [ "$R9A" != "$R9B" ]; then echo "HARD-FAIL (R-9): Zwei-Run-Identität verletzt (candidates/order/routing/terms/at.normalform):" >&2 diff -u <(printf '%s\n' "$R9A") <(printf '%s\n' "$R9B") >&2 || true exit 1 fi echo " BEFUND: positive Identität byte-gleich (candidates/order/routing/terms/at.normalform) — NICHT-VAKUUM:" echo "$R9A" | sed 's/^/ /' # Nicht-Vakuum: alpha Kandidat. case "$R9A" in *alpha*) ;; *) echo "HARD-FAIL (R-9): nicht-vakuum Assertion — alpha fehlt" >&2; exit 1;; esac # NEGATIVE Kontrolle: konstruierte Abweichung hart FAIL. echo "--- NEGATIVE Kontrolle (divergent) ---" run9_worktree "$ROOT/r9-wt/n" run9n "divergent" R9N=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9n.receipt" | grep -v '^generated.at') [ -n "$R9N" ] || { echo "HARD-FAIL (R-9): Negativ-Receipt leer (Vakuum)" >&2; exit 1; } if [ "$R9N" = "$R9A" ]; then echo "HARD-FAIL (R-9): konstruierte Abweichung unerkannt — Negativ-Kontrolle muss FAIL" >&2; exit 1 else echo " BEFUND: konstruierte AD-16-Abweichung (candidates-Block) erkannt — hart FAIL, kein Vakuum (BS-7-Nachführung)" fi # at-Exzeption (P-L2-6): eine legitime at-Abweichung wird NICHT als AD-16 gemeldet; # die übrigen deterministischen Felder sind byte-identisch. echo "--- at-Exzeption (atgap) ---" run9_worktree "$ROOT/r9-wt/at" run9at "atgap" R9AT_REST=$(grep -E '^(candidates|order|routing|terms|at.normalform):' "$ROOT/receipts/run9at.receipt" | grep -v '^generated.at') R9AT_AT=$(grep '^generated.at:' "$ROOT/receipts/run9at.receipt") if [ "$R9AT_REST" != "$R9A" ]; then echo "HARD-FAIL (R-9): atgap-Run weicht außerhalb at ab (nur at darf differieren):" >&2 diff -u <(printf '%s\n' "$R9A") <(printf '%s\n' "$R9AT_REST") >&2 || true exit 1 fi if [ "$R9AT_AT" = "$(grep '^generated.at:' "$ROOT/receipts/run9a.receipt")" ]; then echo "HARD-FAIL (R-9): atgap-Run hat keine at-Abweichung erzeugt (Exzeption nicht ausgeübt)" >&2; exit 1 fi echo " BEFUND: at-Exzeption ausgeübt — nur generated.at differiert, übrige Felder byte-identisch; legitime at-Abweichung NICHT als AD-16 gemeldet (§5.14 Pkt. 3, §5.15 Pkt. 6)" # BUNDLE-BYTE-VERGLEICH (patch F-27, §5.15 Pkt. 6/A0-19): der Zwei-Run-Abgleich # verlangt byte-identische MUTIERTE Bundle-Bestandteile, nicht nur identische # Receipt-Felder. Wir vergleichen die SHA-256 der mutierten wiki/-Dateien der # zwei clean-Runs (aI b) sowie des atgap-Runs — letzterer bis auf die benannte # at-Ausnahme (Pkt. 6, Pkt. 3: allein generated.at darf differieren). # Bundle-VERGLEICH (patch F-27, §5.15 Pkt. 6/A0-19): byte-identische mutierte # Bundle-Bestandteile der zwei clean-Runs (voll, inkl. at) sowie des atgap-Runs # gegenüber dem clean-Run (maskiert, at ausgenommen). Divergenter Run => hart FAIL. B9AF=$(awk '/^full:/{sub(/^full: /,""); print; exit}' "$ROOT/receipts/run9a.bundle") B9BF=$(awk '/^full:/{sub(/^full: /,""); print; exit}' "$ROOT/receipts/run9b.bundle") B9AM=$(awk '/^masked:/{sub(/^masked: /,""); print; exit}' "$ROOT/receipts/run9a.bundle") B9TM=$(awk '/^masked:/{sub(/^masked: /,""); print; exit}' "$ROOT/receipts/run9at.bundle") B9NM=$(awk '/^masked:/{sub(/^masked: /,""); print; exit}' "$ROOT/receipts/run9n.bundle") if [ -z "$B9AF" ] || [ -z "$B9BF" ] || [ -z "$B9AM" ] || [ -z "$B9TM" ] || [ -z "$B9NM" ]; then echo "HARD-FAIL (R-9-bundle): Bundle-Hash-Artefakt unvollständig (Vakuum)" >&2; exit 1 fi if [ "$B9AF" != "$B9BF" ]; then echo "HARD-FAIL (R-9-bundle): Bundle-State-Hashes der zwei clean-Runs differieren — byte-identische MUTIERTE Bestandteile verletzt:" >&2 diff -u <(printf '%s\n' "$B9AF") <(printf '%s\n' "$B9BF") >&2 || true exit 1 fi echo " BEFUND: byte-identische mutierte Bundle-Bestandteile der zwei clean-Runs (SHA-256 voll je wiki/-Datei, ohne index/log) — nicht nur Receipt-Felder (A0-19)" if [ "$B9AM" != "$B9TM" ]; then echo "HARD-FAIL (R-9-bundle): atgap-Run-Bundle weicht bei maskiertem at ab (byte-identisch bis auf generated.at erwartet):" >&2 diff -u <(printf '%s\n' "$B9AM") <(printf '%s\n' "$B9TM") >&2 || true exit 1 fi echo " BEFUND: atgap-Run-Bundle byte-identisch zum clean-Run außer der benannten at-Ausnahme (maskiert), §5.15 Pkt. 6/§5.14 Pkt. 3" if [ "$B9NM" = "$B9AM" ]; then echo "HARD-FAIL (R-9-bundle): divergenter Run-Bundle ununterscheidbar vom clean-Run (Negativ-Kontrolle muss FAIL)" >&2; exit 1 fi echo " BEFUND: divergenter Run-Bundle an der mutierten Datei nachweisbar ungleich (hart FAIL, kein Vakuum)" echo "RESULT: PASS — R-9: ZWEI_RUN_IDENTISCH — positive Identität NICHT-VAKUUM (2 getrennte Worktrees, gegeneinander verglichen, kein hart codierter Erwartungswert) + NEGATIVE Kontrolle hart FAIL + at-Exzeption praktisch ausgeübt (nur-at-differiert, nicht gematcht); Manifest datei-pfadbasiert (AC-6, AD-17h/A0-19, §5.15 Pkt. 6)" # ============================================================================= # Abschluss — Gesamt-Exit 0 (nur wenn alle R-Szenarien harte PASS) # ============================================================================= echo echo "===== Sandbox abgeschlossen (R-1, R-1b, R-2..R-9) =====" echo "Alle Szenarien harte PASS, 0 HARD-FAIL." echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)" exit 0