Skip to content

Terminal dispositions disagree on claim retention: stack-pop deletes, release-runbook and the fence retain #781

Description

@tobyhede

The execution loop's two terminal dispositions disagree about what happens to a run's claims, and the disagreement is observable to an orchestrator.

applyExecutionTerminalRelease (packages/cli/src/services/execution.ts):

  • release-runbookreleaseRunbook(runbookId, { retainClaimsAsTerminal: true }), with the rationale stated inline: "Natural child completion: retain the claim as a terminal tombstone so rd pass/fail --claim-id can confirm-or-conflict against the child's outcome (idempotent post-work commands). Explicit teardown (abort/stop/complete) keeps deleting the claim."
  • stack-popreleaseRunbook(runbookId), which takes the default and deletes every claim controlling the run (projectRunbookRelease, the else arm).

Meanwhile the fenced command mutation retains tombstones in both modes, with a comment saying explicitly that this must not be keyed on the mode.

So the same run reaching the same terminal state leaves a claim id resolving terminal or missing depending on which disposition the loop happened to be given — and stack-pop is the default for every non-claim-addressed run.

Why it is filed rather than fixed

PR #780 changed stack-pop from the positional popRunbook() to releaseRunbook(runbookId). Claim disposition was deliberately held constant there — the bare form deletes claims exactly as the positional pop did — because changing addressing and retention in one commit would make a regression in either untraceable to the other.

What to decide

  1. Whether stack-pop should retain tombstones like its sibling and like the fence. The argument for: an orchestrator holding a run-control claim gets the same answer regardless of which internal disposition ran. The argument against: stack-pop covers explicit teardown paths, and the release-runbook comment above draws the line at exactly that distinction — so the current split may be intentional and merely undocumented.
  2. Whether the mode union still earns its shape once both arms call the same method with the same addressing and differ only in one boolean. Note this is not a licence to collapse it to a boolean: the exhaustive switch carries a comment explaining that "not release-runbook" must not come to mean "stack-pop", and defer-to-caller is a third arm that releases nothing. Any collapse has to preserve that.

Acceptance

  • The retention rule is stated once, in a place both dispositions read from, rather than inferred from two call sites.
  • A test pins what a run-control claim resolves to after each disposition — terminal vs missing — so the contract is observable rather than implied.
  • If the split is intentional, the reason is recorded at the stack-pop arm; today only release-runbook explains itself.

Related: #597 (unify terminal session-release behind one machine-owned seam) and #734 — both concern which seam owns a terminal release, and this is the claim-disposition half of the same question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DelegationDelegation lifecycle remaining-work roadmap (2026-07-01)P2: mediumFeature / architectural cleanupbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions