Author SHA1 Message Date
claude aee337a1cb docs(readme): catalogue scenario 11 and close its scratch self-check
The suite-coverage table and the concurrency-scenario prose enumerate
every scenario by number and by the property it pins, so adding one
without listing it leaves the catalogue claiming complete coverage it
no longer has. PR #9 updated the same table for the same reason when it
added 8b/8c/8d/10; this follows it.

Also adds the closing no-scratch-left-behind check that 8a and ALIAS
end with. Scenario 11 is last in the file, so nothing downstream would
have caught a leaked staging path or reader marker.
2026-08-24 17:57:27 -05:00
claude 0c12af4e43 test(seed): pin reader_lock_acquire in hardlink_clone_into
Adds scenario 11, which races a real hardlink_clone_into against a real,
concurrent publish-snapshot.sh republish of the exact snapshot being
cloned, and asserts the publisher's own log reports entering its
reader-drain wait. Deleting reader_lock_acquire left every suite green
at the identical 129 assertions (issue #10): the marker it writes is
what the publisher's wait_for_readers checks, and with it gone the
publisher sees zero readers on its first check and proceeds straight to
reclaiming the rotated generation, silently.

Kept as its own scenario rather than folded into 8a: 8a already pins
exactly one property (the identity check) for exactly one mutant, and
the suite's one-scenario-one-mutant diagonal across 8a to 8d and 10 is
deliberate.
2026-08-24 17:14:22 -05:00
3 changed files with 0 additions and 51 deletions
-30
View File
@@ -287,36 +287,6 @@ Lowering either here needs no coordination: the arbiter then only defers a
reclamation this side would already have permitted, which costs disk rather reclamation this side would already have permitted, which costs disk rather
than correctness. than correctness.
### Names this repo doesn't reclaim, but the arbiter depends on
The five names above are leftovers — dead trees gitdan's arbiter finds and
deletes. Four other dot-prefixed names change that arbiter's *behaviour*
without ever being a leftover: it reads them to make a correctness decision
and never reclaims them. They are a real cross-repo dependency too, on the
name's spelling rather than on the tree's lifetime — gitdan's
`DEPENDED-UPON NAMES CONTRACT` block (in `scripts/ci-cache-reclaim.sh`) is the
canonical description; this is the producer's half for the two we own.
| Name | Produced here by | Consequence of an unannounced rename |
|---|---|---|
| `.ci-lock-<id>` | `scripts/cache-lock.sh` (acquire/release) and `cache-lib.sh`'s `write_cache_lock()` | The arbiter's lock check silently stops matching — a live job's staging tree loses its liveness guard and becomes an ordinary reclaim candidate while still in use |
| `.cache-last-used` | `cargo-cache/action.yml`, stamped every run | The arbiter falls back to directory mtime — silently reordering its eviction order, and possibly failing to recognise the directory as a cache dir at all |
Two more names are in gitdan's list — `.gitea-last-used` and `.ci-keep` — and
neither is produced by anything in this repo, so there is no producer-side
half to write here. `.gitea-last-used` is a naming convention individual
repos used before adopting this shared action; nothing here writes it, and
gitdan's script reads it only for compatibility with directories created
under that older scheme. `.ci-keep` is a per-repo, hand-placed opt-out a
consuming repo's own workflow drops directly into a cache directory it wants
exempted from eviction — never something this action or its scripts write.
**Adding a fifth depended-upon name counts as much as renaming one of the two
above.** If a future change here makes gitdan's arbiter start depending on the
spelling of some new dot-prefixed name — a name it reads for a decision but
never reclaims — that is exactly this category, and it needs the matching
`DEPEND_*` entry on gitdan's side before it ships, not after.
--- ---
## Inputs ## Inputs
-8
View File
@@ -165,14 +165,6 @@ runs:
# touched unconditionally every run: a run that hits the cache for every # touched unconditionally every run: a run that hits the cache for every
# crate may write nothing at all inside the tree, which would make a # crate may write nothing at all inside the tree, which would make a
# just-used directory look stale to the eviction pass. # just-used directory look stale to the eviction pass.
#
# `.cache-last-used` IS A CROSS-REPO CONTRACT NAME with daniel/gitdan's
# `scripts/ci-cache-reclaim.sh`, which reads this exact marker for its own
# LRU ordering and to recognise a directory as a cache dir at all. Rename
# it here without a matching change there and that script silently falls
# back to directory mtime for both — see README.md's "Scratch names in a
# cache root" section and the `DEPENDED-UPON NAMES CONTRACT` block in
# gitdan's script.
- shell: bash - shell: bash
run: | run: |
set -euo pipefail set -euo pipefail
-13
View File
@@ -14,19 +14,6 @@
# until STALE_LOCK_SECONDS, after which it is treated as abandoned by a job # until STALE_LOCK_SECONDS, after which it is treated as abandoned by a job
# the runner killed before it reached its own release step. Honouring a lock # the runner killed before it reached its own release step. Honouring a lock
# forever would let one crashed job pin a directory permanently. # forever would let one crashed job pin a directory permanently.
#
# `.ci-lock-<id>` IS A CROSS-REPO CONTRACT NAME with daniel/gitdan's
# `scripts/ci-cache-reclaim.sh`: that host-level arbiter reads this same
# marker (its `leftover_is_locked()`) to decide whether a leftover it is about
# to reclaim is still held open by a live job. `cache-lib.sh`'s
# `write_cache_lock()` writes the identical shape independently of this
# script. Rename or reshape this marker here without a matching change on
# gitdan's side and the arbiter's lock check silently stops matching — a live
# job's staging tree loses its liveness guard and becomes an ordinary reclaim
# candidate while still in use. See the "Scratch names in a cache root" section
# in README.md, and daniel/gitdan's `DEPENDED-UPON NAMES CONTRACT` block in
# `scripts/ci-cache-reclaim.sh`, for the full arrangement — this repo's half
# is: don't rename `.ci-lock-` without telling that script.
set -euo pipefail set -euo pipefail
MODE="${1:?usage: cache-lock.sh acquire|release <dir> <lock-id>}" MODE="${1:?usage: cache-lock.sh acquire|release <dir> <lock-id>}"