test: correct the sabotage predictions to the population split they taught
The suite's first run: T3/T4/T5 red as predicted; T1/T2/TA mispredicted, and the mispredictions are the finding. The ACCOUNTING protects UNSTAGED carriers (prose/markdown files are never staged, so graph closure structurally cannot see them); GRAPH CLOSURE protects STAGED files (a site dropped inside a touched file leaves residue only closure sees). The two layers PARTITION the population rather than backing each other up -- my original legs treated them as redundant layers over one population and predicted the wrong arms.
Re-cut: T1 (accounting tolerated -> b6 red, the unstaged-carrier refusals vanish), T2 (no sites at all + accounting -> b5 red on content asserts: nothing is staged, no layer inside the product can see it, the arm's own file reads are the catch), T2c (first-site-only + accounting -> b5 red WITH the closure signature: staged residue is closure's own population). TA's plant moves the marker inside a string literal -- the first spelling's mid-expression comment swallowed the closing parens and killed the whole probe at parse, which surfaced as an EMPTY arm set, the worst red shape. All plants re-dry-verified to land uniquely.
test/sabotage-f3b.sh | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 60 insertions(+), 19 deletions(-)test/sabotage-f3b.shmodified
# sets), plant landed by hash + marker, planted tree must build, restores by# git checkout verified by hash, full gate re-run green at the end.## Legs:# T1 raw-vs-semantic ACCOUNTING tolerated -> the graph-closure check# catches the stale referrer: b5-rename red (closure signature)# T2 T1 + closure check disabled -> the stale referrer PUBLISHES:# b5-rename red on its own content asserts (BOTH layers had to fall)# Legs (see the population-split comment before T1 -- the first run's# mispredictions are what taught it):# T1 raw-vs-semantic ACCOUNTING tolerated -> b6 red: the prose/markdown# carriers are UNSTAGED, so only the accounting can refuse for them# T2 semantic pass returns NO sites + accounting tolerated -> b5 red on# its CONTENT asserts (referrers never touched; closure cannot see# unstaged files either)# T2c semantic pass keeps only the FIRST site per file + accounting# tolerated -> b5 red WITH the closure signature (staged residue is# closure's own population)# T3 delete ignores referrers -> b7-delete red# T4 recovery goes silent (recover-root! returns '() doing nothing) -># b3-recovery-completes red (completion never happens, manifest stays)# T5 recovery TOLERATES an unprovable state (the first-pass proof clause# always passes) -> gate arm 5 red (the corrupt-temp driver observes# recovery proceeding over garbage instead of refusing to a human)# T2c semantic pass drops sites after the first per file (accounting# tolerated) -> b5 red WITH the closure signature (staged residue)# TA assertion layer: flip the bystander hash expectation -> b12 redset -u [ "$2" -eq 0 ] && { reds=$((reds + 1)); echo "SAB-F3B LEG $1: RED AS PREDICTED"; }}# ---------------------------------------------------------------------------# THE POPULATION SPLIT THESE THREE LEGS DEMONSTRATE (learned from this# suite's own first run, whose predictions had it backwards): the ACCOUNTING# protects UNSTAGED carriers -- a prose or markdown file is never staged, so# graph closure structurally cannot see it; only the raw-vs-semantic# arithmetic can refuse for it. GRAPH CLOSURE protects STAGED files -- a# rewrite site dropped inside a touched file leaves residue closure sees.# The two layers partition the population rather than backing each other up,# and each leg below fells exactly one.# ---------------------------------------------------------------------------echo "SAB-F3B LEG T1: raw-vs-semantic accounting tolerated"echo " PREDICT RED: b5-rename -- via the GRAPH CLOSURE check (the dropped"echo " accounting lets a semantically-invisible occurrence"echo " through, closure sees the residue and refuses)"echo " PREDICT GREEN: b1, b7 (delete's guard reads semantic+raw directly)"echo " PREDICT RED: b6-rename-refusals (the prose and markdown occurrences"echo " are silently dropped, the renames PROCEED, and b6's"echo " expected refusals never come -- closure cannot help:"echo " those files are never staged)"echo " PREDICT GREEN: b5 (every occurrence in ITS web is rewritable), b1, b7"sed -i 's/(if (= accounted (length hits))/(if #t ;; SAB-T1/' src/folio/doc/structural.sglif plant_landed T1 "$ST" "$h_st" "SAB-T1" 1 && build_planted T1; then run_battery T1 || true ok=0 expect T1 b5-rename RED || ok=1 grep -q "closure" "$work/bat-T1.log" || { fail_leg T1 "red, but not with the closure signature"; ok=1; } expect T1 b6-rename-refusals RED || ok=1 expect T1 b5-rename GREEN || ok=1 expect T1 b1-stand-down GREEN || ok=1 expect T1 b7-delete GREEN || ok=1 leg_result T1 $okrestore_all || exit 3# ---------------------------------------------------------------------------echo "SAB-F3B LEG T2: accounting tolerated AND closure disabled -- the stale"echo " referrer PUBLISHES; b5's content asserts catch it (both layers fell)"echo " PREDICT RED: b5-rename (residue assert); b6 may cascade -- only b5 is"echo " asserted"echo "SAB-F3B LEG T2: the semantic pass returns NO sites (total silent loss)"echo " with the accounting tolerated -- referrer files are never touched at"echo " all, so closure (staged-only) cannot see it either; b5's own CONTENT"echo " asserts on the referrer files are what catches it"echo " PREDICT RED: b5-rename (residue in ref files)"echo " PREDICT GREEN: b1"sed -i 's/(if (= accounted (length hits))/(if #t ;; SAB-T1/' src/folio/doc/structural.sglsed -i 's/(if (pair? leak)/(if #f ;; SAB-T2/' src/folio/doc/structural.sglsed -i 's/(walk rest (if f (cons (list n f) out) out))/(walk rest out) ;; SAB-T2/' src/folio/doc/structural.sglif plant_landed T2 "$ST" "$h_st" "SAB-T2" 1 && build_planted T2; then run_battery T2 || true ok=0 expect T2 b5-rename RED || ok=1 expect T2 b1-stand-down GREEN || ok=1 leg_result T2 $okfirestore_all || exit 3# ---------------------------------------------------------------------------echo "SAB-F3B LEG T2c: the semantic pass drops every site AFTER the first per"echo " file (accounting tolerated) -- ref-two stays TOUCHED with one of its"echo " two sites stale, which is exactly the residue GRAPH CLOSURE exists"echo " to catch"echo " PREDICT RED: b5-rename WITH the closure signature"sed -i 's/(if (= accounted (length hits))/(if #t ;; SAB-T1/' src/folio/doc/structural.sglsed -i 's/(walk rest (if f (cons (list n f) out) out))/(walk rest (if (and f (null? out)) (cons (list n f) out) out)) ;; SAB-T2C/' src/folio/doc/structural.sglif plant_landed T2c "$ST" "$h_st" "SAB-T2C" 1 && build_planted T2c; then run_battery T2c || true ok=0 expect T2c b5-rename RED || ok=1 grep -q "closure" "$work/bat-T2c.log" \ || { fail_leg T2c "red, but not via the closure check"; ok=1; } leg_result T2c $okfirestore_all || exit 3# ---------------------------------------------------------------------------echo "SAB-F3B LEG T3: delete ignores referrers"echo " PREDICT RED: b7-delete (a referenced delete publishes; the arm"# ---------------------------------------------------------------------------echo "SAB-F3B LEG TA: assertion layer -- flip the bystander hash expectation"echo " PREDICT RED: b12-bystander"sed -i 's/(equal? (revision-of-file (rooted "bystander.md")) bystander-hash)/(not (equal? (revision-of-file (rooted "bystander.md")) bystander-hash)) ;; SAB-TA/' test/f3b-probe.sglif plant_landed TA "$PROBE" "$h_probe" "SAB-TA" 1; then# The marker lives INSIDE a string literal: the first spelling appended a# `;;` comment mid-expression, which swallowed the closing parens and killed# the whole probe at parse (observed: an EMPTY arm set, the worst red shape).sed -i 's/(equal? (revision-of-file (rooted "bystander.md")) bystander-hash)/(equal? "SAB-TA-impossible" (revision-of-file (rooted "bystander.md")))/' test/f3b-probe.sglif plant_landed TA "$PROBE" "$h_probe" "SAB-TA-impossible" 1; then run_battery TA || true ok=0 expect TA b12-bystander RED || ok=1echo "---"echo "F3B_SABOTAGE legs=$legs red=$reds setup_failed=$setup_fails"[ "$legs" -eq 6 ] && [ "$reds" -eq 6 ] && [ "$setup_fails" -eq 0 ] && exit 0[ "$legs" -eq 7 ] && [ "$reds" -eq 7 ] && [ "$setup_fails" -eq 0 ] && exit 0exit 1