Appendix A - 19. Tombstone commits (lifecycle close records)
The Structure of Tombstone commits (lifecycle close records) — its shape at a glance:
The tombstone at the branch tip records the disposition; a dedup event serializes concurrent closers, a live-marker guard refuses a working agent, and cleanup reads the record as its safe-to-reclaim proof.
flowchart LR
Close[/Worktree close/] --> Guard{Live marker present?}
Guard -->|yes| Refuse([Refuse to tombstone])
Guard -->|no| Write[Write tombstone + disposition]
Write --> Cleanup{Tombstone + all commits landed?}
Cleanup -->|yes| Reclaim([Safe to reclaim])
Accessible description: a worktree close first checks the live marker and refuses to tombstone a working agent; otherwise it writes a tombstone carrying the disposition, and cleanup reclaims the directory only when a tombstone tips the branch and every non-tombstone commit is cherry-picked or declared skipped.
Projected from the catalogue entry lifecycle-and-observability / Tombstone commits (lifecycle close records).
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — A tombstone commit written at a worktree's branch tip that durably records its lifecycle close and disposition (cherry-picked / declared-skipped), so cleanup can prove a worktree is safely reclaimable instead of guessing.
Motivation
Reclaiming a worktree safely requires knowing its work is fully accounted for — every commit either cherry-picked to main or deliberately skipped. Without a durable close record, cleanup faces a dilemma: delete eagerly and risk destroying unlanded work, or never delete and leak worktrees forever. The failure is one of those two, and it recurs at every agent completion.
Applicability
- A place to write the close record — here, a commit at the branch tip.
- A disposition vocabulary (cherry-picked / skipped) so the record is machine-checkable.
- A dedup mechanism (the registry
tombstoning_startedevent) to serialize concurrent closers. - The live-worktree guard so a still-working agent can never be tombstoned.
Structure
The Structure diagram appears at the top of this page.
Sample Code
The tombstone records the disposition, so cleanup can verify a precise predicate rather than guess off a "looks finished" heuristic. A dedup event serializes concurrent closers, and the reclaim predicate demands both the tip tombstone and full accounting of every other commit.
def safe_to_reclaim(branch_commits, is_landed) -> bool:
"""Reclaim only if a tombstone tips the branch AND every other commit is landed or skipped."""
if not branch_commits or not branch_commits[-1].is_tombstone:
return False
return all(is_landed(c) or c.declared_skipped
for c in branch_commits if not c.is_tombstone)
def write_tombstone(agent_id, disposition, marker_exists, dedup_claim) -> int:
if marker_exists(agent_id): # live-worktree guard: never close a working agent
print(f"REFUSE: agent {agent_id} is still live"); return 1
if not dedup_claim(agent_id): # registry event serializes concurrent closers
print(f"REFUSE: another closer already started for {agent_id}"); return 78
# ... append a tombstone commit carrying `disposition` at the branch tip ...
return 0
Consequences
- Bypass-prefix hole.
tombstone:commits skip the pre-commit hook by design — needed for the mechanism, but a gap that rests on honest use. - Dedup depends on the registry. If the
tombstoning_startedevent is missed, two closers can race. - A wrong disposition is dangerous. A tombstone that mis-records "skipped" for un-landed work would greenlight an unsafe reclaim — the reclaim trusts the record's correctness.
- Mass-tombstone id-lists are manual. The
--id-filediscipline is a human step (deliberately, to prevent runtime enumeration).
Example use within DocAble
- The tombstone tool — writes the disposition-bearing close record.
- The dedup event (
tombstoning_started, exit 78); the explicit-id-list + live-worktree guard. - The
cleanup-stalepredicate (tombstone-at-tip AND all commits cherry-picked/skipped).
Related Patterns
- Consumer — reads agent-registry live markers before writing a close record (the live-worktree guard).
- Enabler —
worktree.py cleanup-staleverifies the record it writes before reclaiming a directory. - Counterpart — the live-worktree guard (hard) prevents this audit record from ever being written for an agent that is still working.