docs(readme): correct the scenario census and the #5 citation

Review of #9 found the methodology section falsified by that PR and owned by
nobody — the scoping that fenced it off was wrong, #8 never touches these
paragraphs.

Three fixes:

* The PATH-stub paragraph named 8a and 8b as the seed suite's stubs. It is now
  four scenarios on two commands: 8a/8b/8c stub `cp` at the clone, 10 stubs it
  one level down at the per-file unshare, and 8d stubs `stat` — a mechanism
  the paragraph did not mention at all, and the only way to make an identity
  that could not be READ the sole witness.

* The assert-which-guard-fired paragraph cited issue #5 as a live example of a
  surviving mutation. #5 is the issue this PR closes, so a reader following
  that citation landed on "removing it leaves every suite green", which is no
  longer true. Scenario 9's own sentence stands — the matrix confirms it
  survives every mutant — so it now says WHY it survives (an unreadable source
  leaves the staging dir at mode 000, and the unshare pass aborts the clone
  before the copy's exit status is consulted) instead of citing a closed
  issue.

* Added the mutual-masking hazard the sweep turned up, since it is the general
  lesson rather than a fact about two particular terms: two guards that can
  each catch the same fault make each other unnecessary, so no fixture built
  around that fault pins either one.

Also names scenario 8d for what it is in its own comment — a regression guard
on a defensive term, not a reproduction of a reachable state. Every route to
the state it constructs is closed off (a rotation hands the witness to 8a, a
genuinely absent source hands it to 8c), which is the reason it is worth
pinning rather than a reason to doubt it.
This commit is contained in:
2026-08-24 14:02:10 -05:00
parent bd60b430e0
commit eb7878b822
2 changed files with 39 additions and 11 deletions
+12 -1
View File
@@ -52,7 +52,9 @@
# identity read is reported as the string `missing`, so two of them
# compare equal to each other; without the term that rejects the
# sentinel, a clone whose source could not be identified at either end
# is published on the strength of two errors.
# is published on the strength of two errors. A regression guard on a
# defensive term rather than a reproduction of a reachable state — see
# the scenario's own comment.
# All four scenarios force their interleaving rather than racing for it,
# and each asserts WHICH check caught the tear, so none stays green if
# the check it exercises is removed.
@@ -486,6 +488,15 @@ echo "=== 8d: an identity that could not be read at either end ==="
# would differ from `missing` and the identity COMPARISON would become the
# witness instead — 8a's property, not this one. The assertion that the stub
# fired is therefore a count rather than a flag.
#
# So be clear about what this scenario is. It is NOT a reproduction of a state
# a CI job reaches: every route to it is closed off — a rotation hands the
# witness to 8a, and a source that is genuinely gone fails `cp -al` and hands
# it to 8c. It is a REGRESSION GUARD ON A DEFENSIVE TERM, and the thing it
# defends against is a sentinel comparing equal to itself, which is a property
# of the code rather than of the filesystem. That is worth pinning precisely
# because nothing else can reach it: a term no fixture exercises is the one a
# refactor drops without argument.
IDENT=$(cache_key feat/identity-unreadable)
IDENT_BASE=$(cache_key release/3)
make_wide_tree "$root/snapshot-$IDENT_BASE" identgen 4