Document the producer half of the leftover naming contract with daniel/gitdan #7

Closed
opened 2026-08-24 17:42:13 +00:00 by claude · 0 comments
Collaborator

The producer half of a cross-repo contract whose consumer half already shipped
in daniel/gitdan#28. That PR
deliberately scoped this side out — a sibling agent was working in this repo at
the time — and it was never filed. This is that follow-up.

The contract, and why only one side of it is written down

daniel/gitdan's host-level cache arbiter (scripts/ci-cache-reclaim.sh)
reclaims dot-prefixed leftovers that this repo's scripts create inside the
cache volumes it scans:

  • .stage-<tag>cache-lib.sh's hardlink_clone_into staging path.
    <tag> is unique per job per run, so a job killed between staging and the
    atomic rename strands a full hardlink tree that nothing here ever sweeps.
  • .evicting-<name>-<pid>prune-cache.sh's eviction rename-aside.
    This one has its own sweeper, so it is the milder case.
  • .reading-<source>-<tag>reader_lock_acquire's marker. Not
    garbage: the arbiter reads these to decide whether a leftover is live, and
    never deletes one.

gitdan's script now carries a LEFTOVER NAMING CONTRACT block naming each
shape, the function that produces it, the condition that strands it, and this
rule:

no new dot-prefixed entry under a cache root without a matching prefix in
scripts/ci-cache-reclaim.sh

Nothing in this repo says any of that. A contributor here can add a fourth
dot-prefixed shape — or rename an existing one — with no local signal that
anything outside the repo depends on the spelling. The arbiter enumerates by
explicit prefix rather than dotglob (deliberately, so it never sees
.reading-* markers as candidates), which means an unannounced fourth shape
is simply invisible to it: gitdan#28 returning by a different route.

The staleness half has a direction

gitdan mirrors two constants from here — CACHE_READ_STALE_SECONDS
(cache-lib.sh) and STALE_LOCK_SECONDS (prune-cache.sh), both 7200. Its
copies must be ours, never below:

  • If we raise ours (longer jobs) and gitdan stays at 7200, its arbiter
    reads a marker whose owner still considers it live as stale, and deletes the
    tree under an in-flight clone. Its minimum-age guard does not back-stop
    that — a clone holding a 3h-old marker has a ~3h-old staging tree, so both
    its guards pass.
  • The reverse drift only costs disk.

So raising either constant here is a change that requires a matching change
there, and lowering one is safe. That asymmetry is documented on gitdan's side
and nowhere on ours.

Ask

Add the producer's half, sited where someone changing these names will
actually see it — cache-lib.sh for the marker and staging shapes,
prune-cache.sh for the aside, and a short section in README.md tying them
together. State:

  1. Which names are part of the contract, and which function produces each.
  2. That .reading-* is read by the arbiter and must never be deleted by it —
    so it is a protective marker, not garbage.
  3. Adding a shape counts as much as renaming one, and what to do about it
    (add the matching prefix in gitdan's ci-cache-reclaim.sh).
  4. That raising CACHE_READ_STALE_SECONDS or STALE_LOCK_SECONDS requires
    raising gitdan's mirrors first, and why lowering is safe.

Point at daniel/gitdan's block rather than restating it in full — one side
should be the canonical description and the other a pointer with the local
obligations spelled out.

Acceptance criteria

  • Each of the three dot-prefixed shapes is documented at its producing
    site, naming the contract.
  • The add-a-shape rule is stated, not just the rename rule.
  • The staleness-constant direction is stated with its asymmetry.
  • README.md carries a short section a newcomer would find before adding
    a scratch directory under a cache root.
  • No behaviour change: comments and docs only.
The producer half of a cross-repo contract whose consumer half already shipped in [`daniel/gitdan#28`](https://gitdan.com/daniel/gitdan/issues/28). That PR deliberately scoped this side out — a sibling agent was working in this repo at the time — and it was never filed. This is that follow-up. ## The contract, and why only one side of it is written down `daniel/gitdan`'s host-level cache arbiter (`scripts/ci-cache-reclaim.sh`) reclaims dot-prefixed leftovers that **this repo's scripts create** inside the cache volumes it scans: - **`.stage-<tag>`** — `cache-lib.sh`'s `hardlink_clone_into` staging path. `<tag>` is unique per job per run, so a job killed between staging and the atomic rename strands a full hardlink tree that nothing here ever sweeps. - **`.evicting-<name>-<pid>`** — `prune-cache.sh`'s eviction rename-aside. This one has its own sweeper, so it is the milder case. - **`.reading-<source>-<tag>`** — `reader_lock_acquire`'s marker. **Not** garbage: the arbiter reads these to decide whether a leftover is live, and never deletes one. gitdan's script now carries a `LEFTOVER NAMING CONTRACT` block naming each shape, the function that produces it, the condition that strands it, and this rule: > no new dot-prefixed entry under a cache root without a matching prefix in > `scripts/ci-cache-reclaim.sh` **Nothing in this repo says any of that.** A contributor here can add a fourth dot-prefixed shape — or rename an existing one — with no local signal that anything outside the repo depends on the spelling. The arbiter enumerates by explicit prefix rather than `dotglob` (deliberately, so it never sees `.reading-*` markers as candidates), which means an unannounced fourth shape is simply invisible to it: gitdan#28 returning by a different route. ## The staleness half has a direction gitdan mirrors two constants from here — `CACHE_READ_STALE_SECONDS` (`cache-lib.sh`) and `STALE_LOCK_SECONDS` (`prune-cache.sh`), both 7200. Its copies must be **≥** ours, never below: - If we **raise** ours (longer jobs) and gitdan stays at 7200, its arbiter reads a marker whose owner still considers it live as stale, and deletes the tree under an in-flight clone. Its minimum-age guard does **not** back-stop that — a clone holding a 3h-old marker has a ~3h-old staging tree, so both its guards pass. - The reverse drift only costs disk. So raising either constant here is a change that requires a matching change there, and lowering one is safe. That asymmetry is documented on gitdan's side and nowhere on ours. ## Ask Add the producer's half, sited where someone changing these names will actually see it — `cache-lib.sh` for the marker and staging shapes, `prune-cache.sh` for the aside, and a short section in `README.md` tying them together. State: 1. Which names are part of the contract, and which function produces each. 2. That `.reading-*` is read by the arbiter and must never be deleted by it — so it is a protective marker, not garbage. 3. **Adding a shape counts as much as renaming one**, and what to do about it (add the matching prefix in gitdan's `ci-cache-reclaim.sh`). 4. That raising `CACHE_READ_STALE_SECONDS` or `STALE_LOCK_SECONDS` requires raising gitdan's mirrors first, and why lowering is safe. Point at `daniel/gitdan`'s block rather than restating it in full — one side should be the canonical description and the other a pointer with the local obligations spelled out. ## Acceptance criteria - [ ] Each of the three dot-prefixed shapes is documented at its producing site, naming the contract. - [ ] The add-a-shape rule is stated, not just the rename rule. - [ ] The staleness-constant direction is stated with its asymmetry. - [ ] `README.md` carries a short section a newcomer would find before adding a scratch directory under a cache root. - [ ] No behaviour change: comments and docs only.
claude added the enhancement label 2026-08-24 17:42:13 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: daniel/gitdan-actions#7