fix(prune): stop protecting publisher target dirs under disk pressure #25

Merged
claude merged 1 commits from fix/prune-unprotect-target into main 2026-09-22 16:07:53 +00:00
Collaborator

Summary

A publisher branch's target-<ref> is no longer protected from eviction —
it's an ordinary pressure-pass candidate now, reseeded from the snapshot on
the branch's next run. snapshot-<ref> and the running job's own target dir
stay protected exactly as before.

Why

Protecting both meant one branch's target dir sat permanently beside its
snapshot with no room for a second branch to seed; every PR needed a hand
eviction between runs (#24).

Unprotecting the target dir alone surfaces a second issue: a branch's tip is
trivially its own ancestor, so the merged-branch check would delete a
protected ref's target dir unconditionally, every run, once nothing skipped
it first. is_protected_from_liveness keeps it out of that check alone,
leaving it an ordinary pressure-pass candidate elsewhere. Selftest scenario
3b red-proves this.

Also corrects the header's inode-sharing claim, measured false on the live
volume — see daniel/zemyna#1073.

Cost: dev's target dir can now be evicted under pressure and reseeds
from the snapshot next run.

Closes #24.

## Summary A publisher branch's `target-<ref>` is no longer protected from eviction — it's an ordinary pressure-pass candidate now, reseeded from the snapshot on the branch's next run. `snapshot-<ref>` and the running job's own target dir stay protected exactly as before. ## Why Protecting both meant one branch's target dir sat permanently beside its snapshot with no room for a second branch to seed; every PR needed a hand eviction between runs (#24). Unprotecting the target dir alone surfaces a second issue: a branch's tip is trivially its own ancestor, so the merged-branch check would delete a protected ref's target dir unconditionally, every run, once nothing skipped it first. `is_protected_from_liveness` keeps it out of that check alone, leaving it an ordinary pressure-pass candidate elsewhere. Selftest scenario 3b red-proves this. Also corrects the header's inode-sharing claim, measured false on the live volume — see daniel/zemyna#1073. **Cost**: `dev`'s target dir can now be evicted under pressure and reseeds from the snapshot next run. Closes #24.
claude added the bug label 2026-09-22 15:49:57 +00:00
claude added 1 commit 2026-09-22 15:49:58 +00:00
fix(prune): stop protecting publisher target dirs under disk pressure
CI / shellcheck + selftests (pull_request) Successful in 1m48s
dc473f0d0c
A publisher branch's target-<ref> was protected identically to its
snapshot-<ref>, so it was never a pressure-pass candidate however old
and however tight the disk. With one branch's target dir permanently
resident alongside its snapshot, a second branch had no room to seed,
and every PR that night needed a hand eviction between runs
(daniel/gitdan-actions#24).

A publisher's target dir is a convenience cache its own next run
reseeds from the snapshot, so losing it under pressure is cheap;
nothing downstream depends on it surviving. Only the snapshot stays
protected in the pressure and self-clear passes.

Unprotecting the target dir outright surfaced a second bug the fix
would otherwise have shipped: a branch's tip is trivially an ancestor
of itself, so once a protected ref's target dir was no longer skipped
before reaching the merged-branch check, pass 1 read it as "merged
into itself" and deleted it unconditionally on every run, independent
of disk pressure. is_protected_from_liveness keeps a protected ref's
target dir out of pass 1 alone, so it stays an ordinary pressure-pass
candidate without ever reaching that check. Scenario 3b in the
selftest red-proves this against the unprotect-only version of the
fix.

Also corrects the header's inode-sharing claim, measured false on the
live volume by daniel/zemyna#1073: publish-snapshot.sh unshares every
executable after its cp -al, and executables are most of the tree by
bytes, so a snapshot eviction is a real, large disk cost rather than
the near-free one the old text described — the target-before-snapshot
ordering still holds, now for the warm-start reason alone plus that
cost.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UkSjXXtU6JYcN2vPntWhfb
claude-reviewer approved these changes 2026-09-22 16:00:57 +00:00
claude merged commit 21dffdb725 into main 2026-09-22 16:07:53 +00:00
claude deleted branch fix/prune-unprotect-target 2026-09-22 16:07:53 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: daniel/gitdan-actions#25