556 lines
34 KiB
Bash
556 lines
34 KiB
Bash
#!/usr/bin/env bash
|
|
# Story 3.6 — Sandbox-Tests der Lease-Staleness-/Recovery-Dimension (§5.12, Revision 3.1)
|
|
# Re-executierbar: bash run-sandbox.sh (ab Workspace-Root; Sandbox unter /tmp/sb36)
|
|
# Zweck: die Staleness-/Recovery-Mechanik (§5.12) als re-executierbarer Run-Demonstrator
|
|
# durchspielen —
|
|
# STALE-1 STALE_ABLAUF (AC-1, AD-17d, A0-15): abgebrochener Run hinterlaesst Lease +
|
|
# Registrierung ohne Freigabe; nachfolgender Run klassifiziert sie generationen-basiert
|
|
# als stale (Erzeugungs-Gen < aktueller Reg-Generator), sie blockiert NICHT
|
|
# (I/O-Matrix STALE_ABLAUF, kein Blockade-fail); nie still geloescht (AD-17e);
|
|
# kein Wanduhr-Timestamp im Registrierungs-/Marker-Format (A0-20)
|
|
# STALE-2 VERWAIST_UEBERNEHMEN (AC-3): neuer Run uebernimmt die verwaiste Lease gegen
|
|
# die erneute Merge-Base-Pruefung (§5.11 Pkt. 1 + Pkt.-4-Diskrepanz-Regel);
|
|
# Uebernahme protokolliert (§5.12 Pkt. 6b); verwaiste Lease nie still geloescht (AD-17e)
|
|
# STALE-3 VERWAIST_STALE_MARKIEREN (AC-3): verwaiste Lease wird als stale markiert
|
|
# (Registry-Marker der aktuellen Generation, Pkt. 1/5); Blockade aufgehoben; log.md-Eintrag
|
|
# STALE-4 RECOVERY_RAW_BASIS (AD-3, AD-17d/A0-15): raw/ bleibt bei Recovery unveraendert
|
|
# (SHA-256-Assertion; EC-1-Grenze: Beweis auf Sandbox-Evidenzweg beschraenkt);
|
|
# native git stash-Variante als zweite zulaessige Schutzform (§5.11 Pkt. 3 + §5.12 Pkt. 5;
|
|
# Defer aufgegriffen); Restore byte-identisch
|
|
# STALE-5 REGISTRIERUNGS-INVARIANTE (Pkt. 6): Gen > erzeugend oder gleiche Gen; hoechster
|
|
# Reg-Generator wird gehalten; verwaiste Kanten (Lockfile + Registry-Zeile) NIE geloescht;
|
|
# HOLD-gegen-HEAD deterministisch (§5.11 Pkt. 1, kein Abbruch-Text)
|
|
# STALE-6 DETERMINISMUS (AD-17h/A0-19): gleicher committeter Baum-Input -> identische
|
|
# Registrierungs-/Stale-Markierungs-/log.md-Outputs (Zwei-Run-Identitaet).
|
|
# Erhaltungs-Invariante (§5.9 Pkt. 5 / AD-5 / FT-6) als HARDE Assertion je lauffaehigem
|
|
# Run; Frontmatter-Konformitaet (Vertrag §3.3/§3.4-Subset) je erzeugtem/aktualisiertem Concept.
|
|
# Ubuntu-Sandbox-Semantik auf einem /tmp-Baum — NIE der reale wiki/- oder raw/-Baum.
|
|
set -u
|
|
ROOT=$(mktemp -d /tmp/sb36-XXXXXX)
|
|
SB="$ROOT/sb"
|
|
mkdir -p "$SB/wiki" "$SB/raw" "$SB/lease" "$SB/registry" "$SB/scratch"
|
|
cd "$SB"
|
|
git init -q
|
|
# Determinismus vs. Host-Git-Konfiguration (AD-17h): die Sandbox erzeugt LF-Blobs und
|
|
# LF-Worktree — autocrlf/filemode-Umwandlung des Hosts wuerde stash-Roundtrips und
|
|
# sha256-Vergleiche wort-wirksam verschieben (STALE-4). Repo-Reparatur schliesst das aus.
|
|
git config core.autocrlf false
|
|
git config core.filemode false
|
|
git config user.email "sandbox@test"
|
|
git config user.name "Sandbox"
|
|
|
|
# ---------- Basis-Baum (committete Ausgangslage = Baseline-Commit = Merge-Base) ----------
|
|
# Mini-Bundle mit zwei Root-Concepts (alpha als Mutations-Objekt, gamma als Kontrolle).
|
|
cat > wiki/index.md <<'EOF'
|
|
# Index
|
|
- [Alpha](alpha.md)
|
|
- [Gamma](gamma.md)
|
|
EOF
|
|
cat > wiki/alpha.md <<'EOF'
|
|
---
|
|
type: concept
|
|
sources:
|
|
- resource: raw/alpha-v1.md
|
|
id: s1
|
|
generated:
|
|
by: wow-compiler/0.1.0
|
|
at: 2026-08-16T09:00:00Z
|
|
---
|
|
Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1).
|
|
Alpha verwendet ausschließlich lokale Netze (raw/alpha-v1.md#S-2).
|
|
EOF
|
|
cat > wiki/gamma.md <<'EOF'
|
|
---
|
|
type: concept
|
|
sources:
|
|
- resource: raw/gamma-v1.md
|
|
id: s1
|
|
generated:
|
|
by: wow-compiler/0.1.0
|
|
at: 2026-08-16T09:00:00Z
|
|
---
|
|
Gamma beschreibt ein anderes, hier nicht betroffenes Thema.
|
|
EOF
|
|
cat > wiki/log.md <<'EOF'
|
|
# Log
|
|
EOF
|
|
cat > raw/alpha-v1.md <<'EOF'
|
|
### S-1
|
|
Evidenz v1: deterministische Init-Sequenz.
|
|
### S-2
|
|
Evidenz v1: ausschließlich lokale Netze.
|
|
EOF
|
|
cat > raw/gamma-v1.md <<'EOF'
|
|
### S-1
|
|
Evidenz v1: Gamma-Thema.
|
|
EOF
|
|
git add -A
|
|
git commit -qm "Baseline"
|
|
BASE=$(git rev-parse HEAD)
|
|
echo "BASELINE-COMMIT (Merge-Base, eindeutiger Commit-Object-Wert): $BASE"
|
|
echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"
|
|
echo
|
|
|
|
runlabel() { echo; echo "########## $1 ##########"; }
|
|
# Isolation: Worktree auf BASE zuruecksetzen (kein Carry-over ueber Szenarien);
|
|
# jede Akquise startet von derselben Merge-Base aus (deterministisch, AD-17h).
|
|
isolate() {
|
|
git checkout -qf -B "$1" "$BASE"
|
|
git for-each-ref --format='%(refname:short)' refs/heads/lease refs/heads/tmp 2>/dev/null | while read b; do
|
|
git branch -D "$b" >/dev/null 2>&1 || true
|
|
done
|
|
git reset -q --hard "$BASE"
|
|
git clean -qfd wiki raw lease registry scratch granite
|
|
}
|
|
|
|
# Erhaltungs-Invariante-Probe (§5.9 Pkt. 5 / AD-5 / FT-6): Baseline-Diff + porcelain,
|
|
# normalisiert (wiki/-Praefix + .md-Suffix gestrippt, LC_ALL=C-sortiert).
|
|
probe() {
|
|
{ git diff --name-only "$BASE" -- wiki/ ; git status --porcelain -- wiki/ | awk '{print $2}'; } \
|
|
| sed -e 's|^wiki/||' -e 's|\.md$||' | LC_ALL=C sort -u
|
|
}
|
|
inv_set() { probe | LC_ALL=C sort -u | paste -sd' ' -; }
|
|
|
|
# ---------- Harte Assertion der Erhaltungs-Invariante (§5.9 Pkt. 5) ----------
|
|
inv_viol() { # $1=expected ; 0 = konsistent, !=0 = Verstoß (msg stderr)
|
|
local expected="$1" p u bad=0
|
|
got=$(inv_set)
|
|
for p in $got; do
|
|
case " $expected " in
|
|
*" $p "*) ;;
|
|
*) echo "HARD-FAIL (Erhaltungs-Invariante §5.9 Pkt. 5): '$p' ist kein Ghost-Diff-negativer Eintrag — erlaubte Menge: {$expected}" >&2; bad=1;;
|
|
esac
|
|
done
|
|
for u in $(git status --porcelain -- wiki/ | grep '^??' | awk '{print $2}'); do
|
|
u=$(echo "$u" | sed -e 's|^wiki/||' -e 's|\.md$||')
|
|
case " $expected " in
|
|
*" $u "*) ;;
|
|
*) echo "HARD-FAIL (Duplikat/Ghost-Diff): ungetrackte neue Datei '$u' liegt ausserhalb der erlaubten Ziel-Pfade {$expected} (§5.9 Pkt. 8)" >&2; bad=1;;
|
|
esac
|
|
done
|
|
return $bad
|
|
}
|
|
assert_invariant() { # positive Erwartung: Verstoß => HARD-FAIL + Exit 1
|
|
if inv_viol "$1"; then
|
|
echo "RESULT: PASS — Probe erfüllt; keine neue Datei; kein Ghost-Diff"
|
|
else
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ---------- Frontmatter-Konformitaet (Vertrag §3.3/§3.4, §6.5; Muster Story-3.4) ----------
|
|
assert_frontmatter() {
|
|
local f="$1"; shift
|
|
local v
|
|
v=$(awk '
|
|
/^---$/{n++; if(n==2) exit; next}
|
|
/^[A-Za-z_][A-Za-z0-9_-]*:/{
|
|
k=$0; sub(/:.*/,"",k)
|
|
if (k=="sources") top="sources"
|
|
else if (k=="generated" || k=="verified") top="genver"
|
|
else top="other"
|
|
if (k!="type" && k!="sources" && k!="generated" && k!="verified" && k!="status" && k!="stale_after") print "TOP_UNBEFUGT:" k
|
|
if (seenk[k]++) print "DUP_KEY:" k
|
|
r=0
|
|
if (k=="type") r=1; else if (k=="sources") r=2; else if (k=="generated") r=3
|
|
else if (k=="verified") r=4; else if (k=="status") r=5; else if (k=="stale_after") r=6
|
|
if (r>0 && r<lastr) print "ORDER_VIOLATION:" k
|
|
if (r>0) lastr=r
|
|
next
|
|
}
|
|
/^[[:space:]]/{
|
|
gsub(/^[[:space:]]+/,""); sub(/^- /,""); gsub(/^[[:space:]]+/,"");
|
|
if (match($0, /^[A-Za-z_][A-Za-z0-9_-]*:/)) {
|
|
ik=substr($0,1,RLENGTH-1)
|
|
if (top=="sources" && ik!="resource" && ik!="id" && ik!="title" && ik!="author" && ik!="usage_count" && ik!="last_modified") print "INNER_UNBEFUGT:" ik
|
|
if (top=="genver" && ik!="by" && ik!="at") print "INNER_UNBEFUGT:" ik
|
|
if (top=="other") print "INNER_UNBEFUGT:" ik
|
|
}
|
|
}
|
|
' "$f")
|
|
if [ -n "$v" ]; then
|
|
echo "HARD-FAIL (Frontmatter-Subset, Vertrag §3.3/§3.4/§3.5): $v in $f" >&2
|
|
exit 1
|
|
fi
|
|
grep -qE '^type: concept$' "$f" || { echo "HARD-FAIL: type=concept fehlt in $f" >&2; exit 1; }
|
|
grep -qE "^ at: [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:?[0-9]{2})$" "$f" || { echo "HARD-FAIL: generated.at ist keine volle ISO-8601-Datetime in $f" >&2; exit 1; }
|
|
for r in "$@"; do
|
|
grep -qF " - resource: $r" "$f" || { echo "HARD-FAIL: sources-Eintrag 'resource: $r' fehlt in $f" >&2; exit 1; }
|
|
done
|
|
echo "RESULT: PASS — Frontmatter-Konformitaet $f (Subset ok, generated.at volles Datetime)"
|
|
}
|
|
|
|
# ---------- Leasing-Helfer (§5.11; deterministisch, AD-17h/A0-19) ----------
|
|
# Lockfile-Format (Pkt. 1: semantisch identisch in jedem Adapter, A0-12):
|
|
# area: <area> / id: <id> / producer: <producer> / baseline_commit: <SHA> / holder_id: <id>
|
|
lock_write() { # $1=area $2=id $3=producer $4=holder_id $5=baseline_commit
|
|
local f="lease/$1/$2.lock"
|
|
{ echo "area: $1"; echo "id: $2"; echo "producer: $3"; echo "baseline_commit: $5"; echo "holder_id: $4"; } > "$f"
|
|
}
|
|
lock_exists() { [ -f "lease/$1/$2.lock" ]; }
|
|
lock_holder() { grep '^holder_id:' "lease/$1/$2.lock" 2>/dev/null | awk '{print $2}'; }
|
|
lock_baseline() { grep '^baseline_commit:' "lease/$1/$2.lock" 2>/dev/null | awk '{print $2}'; }
|
|
|
|
# akquire: Lease-Akquise (Pkt. 1) — prueft Lockfile (Lease-Hold, kein Ueberschreiben) UND die
|
|
# generationen-basierte Staleness-Klassifikation (Pkt. 1/3): ein existierendes Lockfile
|
|
# verweigert die Akquise, SOFERN die Lease NICHT als stale klassifiziert ist
|
|
# (Erzeugungs-Gen < aktuell hoechster Reg-Generator). Eine stale-markierte/verwaiste Lease
|
|
# blockiert keinen nachfolgenden Run (TTL-Ablauf-Äquivalent, STALE_ABLAUF).
|
|
# Erzeugungs-Gen wird beim Aufruf uebergeben (Default = aktueller Reg-Generator).
|
|
akquire() { # $1=area $2=id $3=producer $4=holder_id [$5=erzeugungs_gen]
|
|
local area="$1" id="$2" producer="$3" holder="$4" gen="${5:-$(reg_gen "$1")}"
|
|
if lock_exists "$area" "$id"; then
|
|
if lease_stale "$area" "$id" "$gen"; then
|
|
echo "BEFUND (STALE): Lease lease/$area/$id.lock existiert, ist aber generationen-basiert STALE (Erzeugungs-Gen $gen < Reg-Gen $(reg_gen "$area")) — blockiert NICHT, Akquise faehrt fort (Pkt. 1/3, kein Blockade-fail)"
|
|
else
|
|
echo "HARD-FAIL (Lease-Hold): Lockfile lease/$area/$id.lock existiert bereits und ist NICHT stale — Akquise verweigert, kein Ueberschreiben (Pkt. 1/3)" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
mkdir -p "lease/$area"
|
|
lock_write "$area" "$id" "$producer" "$holder" "$BASE"
|
|
return 0
|
|
}
|
|
|
|
# ---------- Staleness-/Recovery-Helfer (§5.12) ----------
|
|
# Registry: Clone-Root-State unter registry/ (AUSSERHALB wiki/ und raw/). Der Registry-
|
|
# Aufbau ist kumulativ ueber Runs (Pkt. 6); die Marker sind Git-/Datei-Ebene.
|
|
# KEIN Wanduhr-Timestamp im Format (A0-20).
|
|
registry_path() { echo "registry/$1"; } # $1 = area
|
|
reg_gen() { # $1=area ; groesste committet sichtbare Generation der Registry (0 = leer)
|
|
local f="registry/$1"
|
|
[ -f "$f" ] || { echo 0; return; }
|
|
awk '/^gen: [0-9]+$/{ if ($2>m) m=$2 } END{ print (m==""?0:m) }' "$f"
|
|
}
|
|
# lease_active: eine als stale markierte Lease gilt NICHT als aktiver Lease-Hold (§5.12
|
|
# Pkt. 1/3: Verwaist-Klassifikation statt Blockade).
|
|
lease_active() { # $1=area $2=id ; 0 = aktiv (kein Stale-Marker), !=0 = stale
|
|
local f="registry/$1"
|
|
[ -f "$f" ] || return 0
|
|
grep -qE "^stale: $2([[:space:]]|$)" "$f" && return 1
|
|
return 0
|
|
}
|
|
reg_write() { # $1=area $2=id $3=producer $4=erzeugungs_generation
|
|
local f="registry/$1" cur
|
|
mkdir -p "$(dirname "$f")"
|
|
touch "$f"
|
|
cur=$(reg_gen "$1")
|
|
{ grep -vE "^gen: |^stale: $2([[:space:]]|$)|^hold: $2([[:space:]]|$)" "$f" 2>/dev/null || true; } > "$f.tmp"
|
|
if [ -n "$4" ] && { [ "$4" -gt "$cur" ] || [ "$4" = "$cur" ]; }; then
|
|
echo "gen: $4" >> "$f.tmp"
|
|
else
|
|
echo "gen: $cur" >> "$f.tmp"
|
|
fi
|
|
mv "$f.tmp" "$f"
|
|
}
|
|
reg_bump() { # $1=registry-datei $2=markierungs-generation ; setzt gen: auf max(cur,$2) (Pkt. 6)
|
|
local f="$1" gen="$2" cur
|
|
cur=$(reg_gen "${f#registry/}")
|
|
{ grep -v '^gen: ' "$f" 2>/dev/null || true; } > "$f.tmp"
|
|
if [ "$gen" -gt "$cur" ]; then
|
|
echo "gen: $gen" >> "$f.tmp"
|
|
else
|
|
echo "gen: $cur" >> "$f.tmp"
|
|
fi
|
|
mv "$f.tmp" "$f"
|
|
}
|
|
reg_stale_mark() { # $1=area $2=id $3=aktuelle_generation — idempotent (Marker-Duplikat vermeiden, Pkt. 1/5)
|
|
local f="registry/$1"
|
|
mkdir -p "$(dirname "$f")"; touch "$f"
|
|
grep -vE "^stale: $2([[:space:]]|$)" "$f" > "$f.tmp" 2>/dev/null || true
|
|
echo "stale: $2 (Gen $3)" >> "$f.tmp"
|
|
mv "$f.tmp" "$f"
|
|
reg_bump "$f" "$3"
|
|
}
|
|
reg_hold_mark() { # $1=area $2=id $3=aktuelle_generation — idempotent (Marker-Duplikat vermeiden, Pkt. 1/5)
|
|
local f="registry/$1"
|
|
mkdir -p "$(dirname "$f")"; touch "$f"
|
|
grep -vE "^hold: $2([[:space:]]|$)" "$f" > "$f.tmp" 2>/dev/null || true
|
|
echo "hold: $2 (Gen $3)" >> "$f.tmp"
|
|
mv "$f.tmp" "$f"
|
|
reg_bump "$f" "$3"
|
|
}
|
|
# lease_stale / holder-derivation (Pkt. 2) / Registry-Zaehl-Helfer (Pkt. 6):
|
|
# lease_stale: generationen-basierte TTL-Klassifikation — true (0) wenn die Erzeugungs-
|
|
# Generation < aktuell hoechster Reg-Generator (Gen kleiner = aelter = stale, Pkt. 1/3);
|
|
# false (1) wenn keine Registry oder keine Reg-Generation erzeugt wurde (nicht stale).
|
|
lease_stale() { # $1=area $2=id $3=erzeugungs_gen
|
|
local f="registry/$1" g
|
|
[ -f "$f" ] || return 1
|
|
g=$(reg_gen "$1")
|
|
[ "$g" -gt "$3" ] 2>/dev/null || return 1
|
|
return 0
|
|
}
|
|
# holder-Derivation (Pkt. 2): holder_id := <producer>-<id> — deterministisch abgeleitet, nicht literal.
|
|
holder_derived() { # $1=producer $2=id
|
|
printf '%s-%s' "$1" "$2"
|
|
}
|
|
lock_holder_derived() { # $1=area $2=id ; abgeleitet aus den Lockfile-Feldern producer + id
|
|
local producer
|
|
producer=$(grep '^producer:' "lease/$1/$2.lock" 2>/dev/null | awk '{print $2}')
|
|
[ -n "$producer" ] || return 1
|
|
printf '%s-%s' "$producer" "$2"
|
|
}
|
|
assert_no_wallclock() { # Datei(en) duerfen keinen Wanduhr-Zeitstempel tragen (A0-20)
|
|
local f
|
|
for f in "$@"; do
|
|
grep -qiE 'timestamp|wallclock|now|date:|20[0-9]{2}-[0-9]{2}-[0-9]{2}[T ]' "$f" \
|
|
&& { echo "HARD-FAIL (A0-20): Wanduhr-Zeitstempel in $f — kein Zeit-TTL als Steuergroesse (§5.12 Pkt. 1/7)" >&2; exit 1; } || true
|
|
done
|
|
}
|
|
|
|
# ---------- log.md-Eintraege (§5.12 Pkt. 6/7; Header-Bullet-Paar je Eintrag, datumsgruppiert) ----------
|
|
# Datumsgruppen-/Reihenfolge-Konvention (Vertrag §5, §5.12 Pkt. 7 neueste zuerst): ein neuer
|
|
# Bullet wird in die BESTEHENDE Datumsgruppe `## 2026-08-19` (bzw. YYYY-MM-DD) eingefuegt —
|
|
# nach deren Header, vor etwaigen Gruppen-Bullets — sonst wird ein neuer Header oben erzeugt.
|
|
# Deterministisch (kein Wanduhr): die Gruppe wird aus der Tageskonstante der Sandbox gebildet.
|
|
log_bullet() { # $1 = Bullet-Text (eine Zeile, printf-% escaped); Datumsgruppe/Reihenfolge (Pkt. 7 neueste zuerst)
|
|
local day="2026-08-19" # getrennt gesetzt — set -u: gleiche-local-Zeilen-RHS darf day nicht vor Setzung referenzieren
|
|
local header="## $day" line="$1"
|
|
if grep -qxF "$header" wiki/log.md; then
|
|
# einfuegen direkt nach dem bestehenden Header (der erste Header-Auftritt ab Dateianfang)
|
|
tmp=$(mktemp)
|
|
awk -v h="$header" -v l="$line" '
|
|
BEGIN{p=0}
|
|
{ if (!p && $0==h) { print; print l; p=1; next } print }
|
|
' wiki/log.md > "$tmp" && mv "$tmp" wiki/log.md
|
|
else
|
|
# kein Header da: neuen Header voranstellen (neueste zuerst), darunter der Bullet
|
|
tmp=$(mktemp)
|
|
{ printf '%s\n' "$header"; printf '%s\n' "$line"; cat wiki/log.md; } > "$tmp" && mv "$tmp" wiki/log.md
|
|
fi
|
|
}
|
|
log_stale_reg() { # $1=area $2=id $3=gen
|
|
log_bullet "- Lease-Staleness/Registrierung (TTL): $1/$2 erzeugt bei Gen $3, aktueller Reg-Generator hoher — gilt als stale (kein Blockade-fail, §5.12 Pkt. 1/6a/7a; Baseline $BASE)"
|
|
}
|
|
log_stale_take() { # $1=area $2=id $3=neuer_holder $4=merge_base
|
|
log_bullet "- Lease-Uebernahme (verwaist): $1/$2 durch $3 gegen Merge-Base-Pruefung $4 (§5.12 Pkt. 3/4/6b/7b)"
|
|
}
|
|
log_stale_mark() { # $1=area $2=id $3=gen
|
|
log_bullet "- Lease-Stale-Markierung: $1/$2 als stale markiert (Registry-Marker Gen $3, Blockade aufgehoben; §5.12 Pkt. 3/6c/7c)"
|
|
}
|
|
log_stale_recovery() { # $1=pfad $2=weg
|
|
log_bullet "- Recovery-Basis-Nutzung: $1 gesichert/wiederhergestellt via $2 (raw/ unveraendert, AD-3; §5.12 Pkt. 5/6d/7d)"
|
|
}
|
|
log_release() { # $1=area $2=id $3=holder
|
|
log_bullet "- Lease-Freigabe: $1/$2 durch $3 (Release nach committetem Run, §5.11 Pkt. 1/6e)"
|
|
}
|
|
free_lease() { # $1=area $2=id $3=holder
|
|
local f="lease/$1/$2.lock"
|
|
[ -f "$f" ] || { echo "HARD-FAIL (free_lease): Lockfile existiert nicht — Release einer unakquirierten Lease (Pkt. 1)" >&2; return 1; }
|
|
log_release "$1" "$2" "$3"
|
|
rm -f "$f"
|
|
}
|
|
|
|
# =====================================================================
|
|
runlabel "STALE-1: STALE_ABLAUF (AC-1, AD-17d, A0-15) — abgebrochener Run hinterlaesst Lease + Registrierung (Erzeugungs-Gen 1) ohne Freigabe; nachfolgender Run (aktuelle Reg-Gen) klassifiziert sie generationen-basiert als stale — sie blockiert NICHT (kein Blockade-fail); nie still geloescht (AD-17e); kein Wanduhr-Timestamp (A0-20)"
|
|
isolate stale1
|
|
echo "--- Run A (abgebrochen): akquiriert Lease auf lease/wiki/run-a und registriert sie im Clone-Root-State (registry/wiki, Erzeugungs-Generation 1) — dann BRICHT der Run AB, ohne Freigabe (Lockfile + Registry-Zeile bleiben zurueck) ---"
|
|
git checkout -q -b lease/wiki/run-a "$BASE"
|
|
akquire wiki run-a "producerA" "run-a-holder"
|
|
reg_hold_mark wiki run-a 1
|
|
[ "$(reg_gen wiki)" = "1" ] || { echo "HARD-FAIL (STALE-1): Registry-Generation nach Run A fehlt/falsch (Pkt. 1)" >&2; exit 1; }
|
|
grep -qF 'hold: run-a (Gen 1)' registry/wiki || { echo "HARD-FAIL (STALE-1): Registry-Zeile der Lease run-a fehlt (Pkt. 1)" >&2; exit 1; }
|
|
assert_no_wallclock lease/wiki/run-a.lock registry/wiki
|
|
echo "--- Run B (nachfolgend): moechte in wiki/ arbeiten — die verwaiste Lease ist generationen-basiert als STALE klassifiziert (Erzeugungs-Gen 1 < aktuelle Reg-Gen), blockiert den nachfolgenden Run NICHT (I/O-Matrix STALE_ABLAUF) ---"
|
|
if akquire wiki run-b "producerB" "run-b-holder" 2>/dev/null; then
|
|
echo "BEFUND: Akquise run-b trotz verwaister run-a-Lease erfolgreich (kein Blockade-fail, STALE_ABLAUF)"
|
|
else
|
|
echo "HARD-FAIL (STALE-1): verwaiste Lease blockiert den nachfolgenden Run (Pkt. 1/3, generationenbasiertes TTL)" >&2; exit 1
|
|
fi
|
|
reg_hold_mark wiki run-b 1
|
|
echo "--- KERN-ASSERTION TTL-ABLAUF (Pkt. 1/3, STALE_ABLAUF): eine verwaiste Lease DERSELBEN id wird nach Generationen-Ablauf nicht mehr blockieren ---"
|
|
echo " (a) vor Generationen-Ablauf: dieselbe id run-a erneut akquirieren -> Lease-Hold (nicht stale bei Reg-Gen 1)"
|
|
if akquire wiki run-a "producerB" "run-b-holder" 1 2>/dev/null; then
|
|
echo "HARD-FAIL (STALE-1): nicht-stale verwaiste Lease run-a (Reg-Gen 1) wurde ueberschrieben (Pkt. 1/3)" >&2
|
|
exit 1
|
|
else
|
|
echo " BEFUND: nicht-stale run-a blockiert (Lockfile-Hold, Pkt. 1) — Erwartung"
|
|
fi
|
|
echo " (b) naechster Run hebt die Registry-Generation an (monotoner Zaehler, Pkt. 1/6): reg_bump auf 2"
|
|
reg_bump registry/wiki 2
|
|
echo " (c) DANN: dieselbe id run-a erneut akquirieren muessen Gen-2-Sicht als stale klassifizieren -> Akquise gelingt (TTL-Ablauf, kein Blockade-fail)"
|
|
if akquire wiki run-a "producerB" "run-b-holder" 1 2>/dev/null; then
|
|
echo " BEFUND: run-a als stale (Erzeugungs-Gen 1 < Reg-Gen 2) akquiriert — TTL-Ablauf-Entscheidung durchgesetzt (Pkt. 1/3, STALE_ABLAUF)"
|
|
else
|
|
echo "HARD-FAIL (STALE-1): generationen-basiertes TTL greift NICHT — stale (Gen 1 < Reg-Gen 2) blockiert weiter (Pkt. 1)" >&2
|
|
exit 1
|
|
fi
|
|
[ -f lease/wiki/run-a.lock ] || { echo "HARD-FAIL (STALE-1): verwaiste Lease run-a wurde still geloescht (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-a (Gen 1)' registry/wiki || { echo "HARD-FAIL (STALE-1): Registry-Zeile run-a wurde still entfernt (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-b (Gen 1)' registry/wiki || { echo "HARD-FAIL (STALE-1): Registry-Zeile run-b fehlt (kumulativer Registry-Aufbau, Pkt. 6)" >&2; exit 1; }
|
|
log_stale_reg wiki run-a 1
|
|
grep -qF 'Lease-Staleness/Registrierung (TTL): wiki/run-a erzeugt bei Gen 1' wiki/log.md || { echo "HARD-FAIL (STALE-1): log.md-TTL-Eintrag fehlt (§5.12 Pkt. 6a/7a)" >&2; exit 1; }
|
|
echo "--- Probe (Erhaltungs-Invariante §5.9 Pkt. 5): nur log.md (Registry/Lockfile ausserhalb wiki/) ---"; probe
|
|
assert_invariant "log"
|
|
echo "RESULT: PASS — STALE-1: verwaiste Lease (Lockfile+Registry-Zeile) blockiert nachfolgenden Run NICHT (generationenbasiertes TTL, AC-1); nie geloescht (AD-17e); kein Wanduhr-Timestamp (A0-20); log.md-TTL-Eintrag"
|
|
|
|
# =====================================================================
|
|
runlabel "STALE-2: VERWAIST_UEBERNEHMEN (AC-3) — neuer Run uebernimmt die verwaiste Lease gegen die erneute Merge-Base-Pruefung (§5.11 Pkt. 1 + Pkt.-4-Diskrepanz-Regel); Uebernahme protokolliert (§5.12 Pkt. 6b); verwaiste Lease nie still geloescht (AD-17e)"
|
|
isolate stale2
|
|
git checkout -q -b lease/wiki/run-a "$BASE"
|
|
akquire wiki run-a "producerA" "run-a-holder"
|
|
reg_hold_mark wiki run-a 1
|
|
# Pkt.-4-Kontext: der uebernehmende Run steht auf einem DESCENDANT der Merge-Base (echter
|
|
# Graph-Zusammenhang, kein Tautologie-Fall) — HEAD ist ein Kind-Commit von $BASE.
|
|
git commit --allow-empty -qm "run-c: Descendant der Merge-Base (Pkt.-4-Diskrepanz-Kontext)"
|
|
echo "--- neuer Run findet die verwaiste run-a-Lease vor und UEBERNIMMT sie: angestrebte Merge-Base ist $BASE; die Pkt.-4-Diskrepanz-Regel validiert die Uebernahme gegen die Aufloesung ---"
|
|
# Pkt.-4-Diskrepanz-Konstruktion (STALE-2, echter Konflikt statt Tautologie):
|
|
# (1) verwaiste Lease notiert einen von der Merge-Base ABWEICHENDEN baseline_commit (Decoy-SHA);
|
|
# (2) der uebernehmende Run steht auf einem abgeleiteten Commit (Descendant der Merge-Base);
|
|
# (3) der Laufzeit-`git merge-base` (Determinismus aus dem committeten Git-State, AD-17h) GEWINNT
|
|
# gegen den notierten Decoy-SHA — der notierte Wert bleibt Sekundaer-Fingerprint (Pkt. 4).
|
|
MB=$(git merge-base HEAD "$BASE")
|
|
DECOY_SHA=$(printf 'decoy-%s' "$BASE" | sha256sum | cut -d' ' -f1)
|
|
lock_write wiki run-a "producerC" "run-c-holder" "$DECOY_SHA"
|
|
echo " Pkt.-4-Befund: Lockfile-notierter baseline_commit = $DECOY_SHA (Decoy) ; Laufzeit-git merge-base = $MB"
|
|
echo " Regel: git merge-base GEWINNT (Commit-Boundary-Prinzip), notierter SHA bleibt Sekundaer-Fingerprint"
|
|
[ "$MB" = "$BASE" ] || { echo "HARD-FAIL (STALE-2): merge-base ableitbar gegen decoy SHAs (Pkt. 4)" >&2; exit 1; }
|
|
[ "$(lock_baseline wiki run-a)" = "$DECOY_SHA" ] || { echo "HARD-FAIL (STALE-2): baseline_commit des Lockfiles nicht als Decoy gesetzt (Pkt. 4)" >&2; exit 1; }
|
|
reg_hold_mark wiki run-a 1
|
|
log_stale_take wiki run-a "run-c-holder" "$MB"
|
|
grep -qF -- '- Lease-Uebernahme (verwaist): wiki/run-a durch run-c-holder gegen Merge-Base-Pruefung' wiki/log.md || { echo "HARD-FAIL (STALE-2): Uebernahme-Eintrag fehlt in log.md (Pkt. 6b/7b)" >&2; exit 1; }
|
|
[ "$(lock_holder wiki run-a)" = "run-c-holder" ] || { echo "HARD-FAIL (STALE-2): holder_id nicht deterministisch uebernommen (Pkt. 2, holder_id-Ableitung)" >&2; exit 1; }
|
|
[ -f lease/wiki/run-a.lock ] || { echo "HARD-FAIL (STALE-2): Lockfile wurde bei Uebernahme still geloescht (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-a (Gen 1)' registry/wiki || { echo "HARD-FAIL (STALE-2): Registry-Zeile run-a wurde still geloescht (AD-17e)" >&2; exit 1; }
|
|
echo "--- Probe: nur log.md; Lockfile/Registry ausserhalb wiki/ ---"; probe
|
|
assert_invariant "log"
|
|
echo "RESULT: PASS — STALE-2: verwaiste Lease uebernommen gegen erneute Merge-Base-Pruefung (Pkt. 4); Uebernahme protokolliert (Pkt. 6b); holder_id-Ableitung deterministisch (Pkt. 2); nichts still geloescht (AD-17e)"
|
|
|
|
# =====================================================================
|
|
runlabel "STALE-3: VERWAIST_STALE_MARKIEREN (AC-3) — verwaiste Lease wird als stale markiert (Registry-Marker der aktuellen Generation); Blockade aufgehoben; log.md-Eintrag (Pkt. 6c/7c)"
|
|
isolate stale3
|
|
git checkout -q -b lease/wiki/run-a "$BASE"
|
|
akquire wiki run-a "producerA" "run-a-holder"
|
|
reg_hold_mark wiki run-a 1
|
|
echo "--- neuer Run entscheidet, die verwaiste run-a-Lease als STALE zu markieren statt sie zu uebernehmen: Registry-Marker der aktuellen Generation (Pkt. 3/5), Blockade aufgehoben ---"
|
|
reg_stale_mark wiki run-a 2
|
|
if lease_active wiki run-a; then
|
|
echo "HARD-FAIL (STALE-3): stale-markierte Lease wird noch als aktiv gewertet (Blockade nicht aufgehoben, Pkt. 3)" >&2; exit 1
|
|
else
|
|
echo "BEFUND: stale-Marker wirkt — Blockade aufgehoben (lease_active = false fuer run-a)"
|
|
fi
|
|
log_stale_mark wiki run-a 2
|
|
grep -qF 'stale: run-a (Gen 2)' registry/wiki || { echo "HARD-FAIL (STALE-3): Registry-Marker fehlt (Pkt. 1/5)" >&2; exit 1; }
|
|
[ "$(reg_gen wiki)" = "2" ] || { echo "HARD-FAIL (STALE-3): Registry-Generation regrediert (Invariante Gen > erzeugend oder gleiche Gen, Pkt. 6)" >&2; exit 1; }
|
|
echo " KERN-ASSERTION (Pkt. 3): nach der Stale-Markierung gelingt DIE AKQUISE DERSELBEN id (Blockade aufgehoben, VG-1)"
|
|
if akquire wiki run-a "producerC" "run-c-holder" 1 2>/dev/null; then
|
|
echo " BEFUND: stale-markierte run-a akquiriert — Blockade-Aufhebung durchgesetzt (Pkt. 3, VERWAIST_STALE_MARKIEREN)"
|
|
else
|
|
echo "HARD-FAIL (STALE-3): stale-Markierung hebt die Lockfile-Blockade nicht auf (Pkt. 3)" >&2; exit 1
|
|
fi
|
|
grep -qF 'Lease-Stale-Markierung: wiki/run-a als stale markiert (Registry-Marker Gen 2' wiki/log.md || { echo "HARD-FAIL (STALE-3): log.md-Stale-Markierungs-Eintrag fehlt (Pkt. 6c/7c)" >&2; exit 1; }
|
|
[ -f lease/wiki/run-a.lock ] || { echo "HARD-FAIL (STALE-3): Lockfile wurde bei Stale-Markierung still geloescht (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-a (Gen 1)' registry/wiki || { echo "HARD-FAIL (STALE-3): Registry-Zeile run-a wurde still geloescht (AD-17e)" >&2; exit 1; }
|
|
assert_no_wallclock lease/wiki/run-a.lock registry/wiki
|
|
echo "--- Probe: nur log.md ---"; probe
|
|
assert_invariant "log"
|
|
echo "RESULT: PASS — STALE-3: verwaiste Lease als stale markiert (Registry-Marker Gen 2); Blockade aufgehoben (lease_active false); log.md-Eintrag; nie still geloescht (AD-17e); Gen-Invariante gehalten"
|
|
|
|
# =====================================================================
|
|
runlabel "STALE-4: RECOVERY_RAW_BASIS (AD-3, AD-17d/A0-15) — raw/ bleibt bei jedem Recovery-Vorgang unveraendert (SHA-256-Assertion; EC-1-Grenze: Beweis auf Sandbox-Evidenzweg beschraenkt); native git stash-Variante als zweite zulaessige Schutzform (§5.11 Pkt. 3 + §5.12 Pkt. 5; Defer aufgegriffen); Restore byte-identisch"
|
|
isolate stale4
|
|
git checkout -q -b lease/wiki/run-a "$BASE"
|
|
akquire wiki run-a "producerA" "run-a-holder"
|
|
echo "--- raw/-Referenzwert (Unveraenderlichkeits-Orakel): SHA-256 der raw/-Dateien VOR allen Recovery-Vorgaengen ---"
|
|
find raw -type f | LC_ALL=C sort | xargs -r sha256sum > raw.sha256
|
|
echo "--- Fremd-Zustand: ein nicht-laufender Producer hat wiki/alpha.md worktree-modifiziert zurueckgelassen (abgebrochener Run) — die Recovery-Basis ist raw/ (unveraendert, committete Evidenz, AD-3) und die Wiedersicherung nutzt die native git stash-Variante (Pkt. 5, Defer aufgegriffen) ---"
|
|
sed -i 's|^Das Alpha-Protokoll definiert eine deterministische Init-Sequenz (raw/alpha-v1.md#S-1)\.|Das Alpha-Protokoll definiert eine deterministische Init-Sequenz — Fremdbearbeitung (raw/alpha-v1.md#S-1).|' wiki/alpha.md
|
|
FRANK_MD5=$(sha256sum wiki/alpha.md | cut -d' ' -f1)
|
|
git stash push -q -m "stale4 fremde alpha-Bearbeitung" -- wiki/alpha.md
|
|
git stash pop -q
|
|
[ "$(sha256sum wiki/alpha.md | cut -d' ' -f1)" = "$FRANK_MD5" ] || { echo "HARD-FAIL (STALE-4): git stash-Restore nicht byte-identisch (Pkt. 5, AD-17e)" >&2; exit 1; }
|
|
log_stale_recovery "wiki/alpha.md" "git stash push/pop (native Variante, §5.12 Pkt. 5)"
|
|
find raw -type f | LC_ALL=C sort | xargs -r sha256sum > raw.sha256.after
|
|
diff -q raw.sha256 raw.sha256.after >/dev/null || { echo "HARD-FAIL (STALE-4): raw/-Dateien haben sich bei Recovery geaendert (AD-3, raw/ immutable)" >&2; exit 1; }
|
|
echo "BEFUND: raw/-SHA-256 vor/nach Recovery identisch (raw/ immutable, AD-3; Sandbox-Evidenzweg, EC-1-Grenze)"
|
|
echo "--- Recovery-Basis LESEND aus raw/ (AD-17d/A0-15): Zugriffs-/Consistency-Basis — jede abgeleitete resource-Referenz der restaurierten wiki/-Datei auf die Evidenz-Basis bleibt gegen die raw/-Dateien aufgeloest; Konformitaet gegen die Basis re-bestaetigt ---"
|
|
RSRC=$(grep -oE '\(raw/[^)#]+' wiki/alpha.md | tr -d '(' | LC_ALL=C sort -u)
|
|
[ -n "$RSRC" ] || { echo "HARD-FAIL (STALE-4): wiki/alpha.md verweist auf keine raw/-Basis-Ressource (Zugriffsanker fehlt)" >&2; exit 1; }
|
|
for res in $RSRC; do
|
|
[ -f "$res" ] || { echo "HARD-FAIL (STALE-4): abgeleitete Referenz '$res' fehlt in der raw/-Basis (Consistency-Basis, AD-3)" >&2; exit 1; }
|
|
done
|
|
echo " BEFUND: lesender Zugriff — raw/-Basis-Ressourcen aufgeloest ($RSRC), Konsistenz-/Zugriffsbasis re-bestaetigt (EC-1-Grenze)"
|
|
grep -qF 'Recovery-Basis-Nutzung: wiki/alpha.md gesichert/wiederhergestellt via git stash' wiki/log.md || { echo "HARD-FAIL (STALE-4): log.md-Recovery-Eintrag fehlt (Pkt. 6d/7d)" >&2; exit 1; }
|
|
echo "--- Probe: alpha (Fremd-Abweichung, Y-Zweig) + log (Dokumentation) — kein Ghost-Diff ---"
|
|
inv_set | LC_ALL=C paste -sd' ' -
|
|
assert_invariant "alpha log"
|
|
echo "RESULT: PASS — STALE-4: raw/ unveraendert (SHA-256-Assertion, AD-3, EC-1-Grenze); native git stash-Variante sichert+wiederhert byte-identisch (Pkt. 5, Defer aufgegriffen); nie geloescht (AD-17e); log.md-Recovery-Eintrag; Recovery-Basis LESEND aus raw/ aufgeloest (Zugriffs-/Consistency-Basis, AD-17d/A0-15)"
|
|
|
|
# =====================================================================
|
|
runlabel "STALE-5: REGISTRIERUNGS-INVARIANTE (Pkt. 6) — Gen > erzeugend oder gleiche Gen; hoechster Reg-Generator wird gehalten; verwaiste Kanten (Lockfile + Registry-Zeile) werden NIE geloescht; HOLD-gegen-HEAD deterministisch (§5.11 Pkt. 1, kein Abbruch-Text)"
|
|
isolate stale5
|
|
# Aufbau eines kontinuierlichen Registry-Verlaufs ueber mehrere Runs (kumulativ, Pkt. 6)
|
|
akquire wiki run-a "producerA" "run-a-holder"; reg_hold_mark wiki run-a 1
|
|
akquire wiki run-b "producerB" "run-b-holder"; reg_hold_mark wiki run-b 2
|
|
akquire wiki run-c "producerC" "run-c-holder"; reg_hold_mark wiki run-c 3
|
|
echo "--- Assertion Invariante (Pkt. 6): sichtbar hoechster Reg-Generator == 3 ---"
|
|
[ "$(reg_gen wiki)" = "3" ] || { echo "HARD-FAIL (STALE-5): Registrierung haelt NICHT den hoechsten Reg-Generator (Pkt. 6)" >&2; exit 1; }
|
|
# Regression versuchen: reg_write mit aelterer (niedrigerer) Gen darf die Sicht nicht absenken
|
|
reg_write wiki run-d "producerD" 1
|
|
[ "$(reg_gen wiki)" = "3" ] || { echo "HARD-FAIL (STALE-5): Registrierung regredierte auf Gen 1 (Invariante Gen > erzeugend oder gleiche Gen verletzt, Pkt. 6)" >&2; exit 1; }
|
|
echo "--- Assertion AD-17e: ALLE verwaisten Kanten (run-a/run-b/run-c Lockfiles + Registry-Zeilen) existieren nach dem Run-Zyklus unveraendert ---"
|
|
[ -f lease/wiki/run-a.lock ] && [ -f lease/wiki/run-b.lock ] && [ -f lease/wiki/run-c.lock ] || { echo "HARD-FAIL (STALE-5): verwaiste Lockfiles wurden still geloescht (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-a (Gen 1)' registry/wiki || { echo "HARD-FAIL (STALE-5): Registry-Zeile run-a fehlt (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-b (Gen 2)' registry/wiki || { echo "HARD-FAIL (STALE-5): Registry-Zeile run-b fehlt (AD-17e)" >&2; exit 1; }
|
|
grep -qF 'hold: run-c (Gen 3)' registry/wiki || { echo "HARD-FAIL (STALE-5): Registry-Zeile run-c fehlt (AD-17e)" >&2; exit 1; }
|
|
echo "--- Assertion HOLD-gegen-HEAD deterministisch (§5.11 Pkt. 1 / §5.12 Pkt. 3): SAME-ID-A/B-Kontrast — eine AKTIVE Lease verweigert die zweite Akquise, eine als stale MARKIERTE derselben id laesst sie zu (nur stale blockiert nicht); kein Abbruch-Text, kein Wanduhr ---"
|
|
echo " A (aktiv): akquire run-c bei Reg-Gen 3 ueberschreibt die aktive (nicht stale) Lease nicht"
|
|
if akquire wiki run-c "producerD" "run-d-holder" 2>/dev/null; then
|
|
echo "HARD-FAIL (STALE-5): aktive Lease wurde ueberschrieben (HOLD gegen HEAD deterministisch, §5.11 Pkt. 1)" >&2; exit 1
|
|
else
|
|
echo " BEFUND: aktive run-c verweigert (HOLD), Lockfile unveraendert"
|
|
fi
|
|
[ "$(lock_holder wiki run-c)" = "run-c-holder" ] || { echo "HARD-FAIL (STALE-5): aktive Lease wurde beim HOLD ueberschrieben (Pkt. 1)" >&2; exit 1; }
|
|
echo " B (stale): run-c als stale markieren (Gen 4) — DANN gelingt die Akquise derselben id (Erzeugungs-Gen 3 < Reg-Gen 4)"
|
|
reg_stale_mark wiki run-c 4
|
|
if akquire wiki run-c "producerD" "run-d-holder" 3 2>/dev/null; then
|
|
echo " BEFUND: stale-markierte run-c (Gen 4) akquiriert — Blockade aufgehoben (Pkt. 3, nur stale blockiert nicht)"
|
|
else
|
|
echo "HARD-FAIL (STALE-5): stale-markierte Lease blockiert noch (aktiv-vs-stale-Kontrast fehlt, §5.12 Pkt. 3)" >&2; exit 1
|
|
fi
|
|
grep -qiE 'timestamp|wallclock|now|date:' lease/wiki/run-c.lock && { echo "HARD-FAIL (A0-20): Wanduhr im Lockfile" >&2; exit 1; } || true
|
|
grep -qiE 'timestamp|wallclock|now|20[0-9]{2}-[0-9]{2}-[0-9]{2}' registry/wiki && { echo "HARD-FAIL (A0-20): Wanduhr in Registry" >&2; exit 1; } || true
|
|
echo "--- Probe: kein wiki/-Eintrag (Registry/Lockfiles ausserhalb) ---"; probe
|
|
assert_invariant ""
|
|
echo "RESULT: PASS — STALE-5: Registrierungs-Invariante (gen 3 == hoechster, keine Regression); verwaiste Kanten nie geloescht (AD-17e); HOLD gegen aktive Lease deterministisch; kein Wanduhr-Timestamp (A0-20)"
|
|
|
|
# =====================================================================
|
|
runlabel "STALE-6: DETERMINISMUS (AD-17h/A0-19) — gleicher committeter Baum-Input -> identische Registrierungs-/Stale-Markierungs-/log.md-Outputs (Zwei-Run-Identitaet)"
|
|
# Zwei vollstaendig unabhaengige, identische Runs ueber denselben Basis-Zustand (BASE).
|
|
stale_run() { # $1 = Branchname; identischer Ablauf: 2 Leases + 1 Stale-Markierung + logs
|
|
isolate "$1"
|
|
git checkout -q -b lease/wiki/run-a "$BASE"
|
|
akquire wiki run-a "producerA" "run-a-holder"; reg_hold_mark wiki run-a 1
|
|
git checkout -q -b lease/wiki/run-b "$BASE"
|
|
akquire wiki run-b "producerA" "run-b-holder"; reg_hold_mark wiki run-b 2
|
|
reg_stale_mark wiki run-a 3
|
|
log_stale_reg wiki run-a 1
|
|
log_stale_mark wiki run-a 3
|
|
}
|
|
stale_state() { # voller Observable-Zustand zweier identischer Runs (Determinismus, Pkt. 1/6/7)
|
|
local out=""
|
|
out="$out registry=$(sha256sum registry/wiki | cut -d' ' -f1)"
|
|
out="$out log=$(sha256sum wiki/log.md | cut -d' ' -f1)"
|
|
out="$out lockfiles=$(find lease -type f | LC_ALL=C sort | xargs -r sha256sum | sha256sum | cut -d' ' -f1)"
|
|
out="$out leasebranches=$(git for-each-ref --format='%(refname)' refs/heads/lease | LC_ALL=C sort | sha256sum | cut -d' ' -f1)"
|
|
printf '%s' "$out"
|
|
}
|
|
stale_run s6a
|
|
S6A=$(stale_state)
|
|
stale_run s6b
|
|
S6B=$(stale_state)
|
|
echo "Run A: $S6A"
|
|
echo "Run B: $S6B"
|
|
[ "$S6A" = "$S6B" ] || { echo "HARD-FAIL (STALE-6): voller Observable-Zustand zweier identischer Runs weicht ab (AD-17h/A0-19, §5.12 Pkt. 1/6/7)" >&2; exit 1; }
|
|
echo "--- Probe (Erhaltungs-Invariante §5.9 Pkt. 5, auch in STALE-6 — Header verspricht sie je lauffaehigem Run): nur log.md ---"
|
|
probe
|
|
assert_invariant "log"
|
|
grep -qF 'stale: run-a (Gen 3)' registry/wiki || { echo "HARD-FAIL (STALE-6): Stale-Markierungs-Klassifikation fehlt (Pkt. 3)" >&2; exit 1; }
|
|
assert_no_wallclock registry/wiki
|
|
echo "RESULT: PASS — STALE-6: voller Observatory-State (Registry/Lockfiles/Lease-Branches/log.md) zweier identischer Runs byte-identisch (AD-17h/A0-19, §5.12 Pkt. 1/6/7); Erhaltungs-Invariante; generationenbasiertes TTL-Ablauf-Kriterium deterministisch"
|
|
|
|
echo
|
|
echo "===== Sandbox abgeschlossen (STALE-1..STALE-6) ====="
|
|
echo "Sandbox-Root: $ROOT (loeschbar: rm -rf $ROOT)"
|