Skip to content

refactor: settle handed-off cleanup runs by direct absence (#16011) - #16036

Merged
atomantic merged 2 commits into
mainfrom
claim/issue-16011
Nov 14, 2026
Merged

atomantic merged 2 commits into
mainfrom
claim/issue-16011

Conversation

@atomantic

@atomantic atomantic commented Nov 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

Third slice of #16011. It retires the last multi-generation post-absence settlement sub-machine: settling a predecessor once a successor proves it delivered the same head.

Done ✓

  • A completed cleanup run whose task has moved to another owner now settles its own physical cleanup directly, once all of these hold:
    • its checkout path(s), local branch and worktree entry are gone;
    • no live run owns the branch.
  • Its execution result is unchanged. The ledger records already-absent-after-handoff, with no integration claim, so the agent card shows the worktree as cleaned up without saying the code merged.
  • The writer settles a captured checkout only once the move is final: the task has completed, or it names another cleanup owner. None of the ownership writers can hand either state back to the run. An unowned task, the run's own pending handoff, or an unreadable task stays pending, because agentFinalization writes a run's cleanup handoff after the run is marked complete.
  • The periodic completion sweep now settles these runs too. Before, only a matching checkout:retired receipt could, through settleSeededPredecessor.
  • Removed:
    • settleSeededPredecessor;
    • its 25-hop explicitSameHeadResume chain walk;
    • the moved-predecessor matching and newest-first ordering in the checkout:retired wake;
    • recordSuccessorCheckoutRetirement and the successor branch of the retirement writer;
    • inspectAbsentCheckout in heldCheckoutRecovery.js, whose only caller was settleSeededPredecessor.
  • settleAbsentSeedRetirement and the new handed-off settlement share one absence/owner check, settleAbsentScope.
  • Compatibility: archived records the old successor writer already settled are terminal (cleanup and verification both completed). Nothing re-selects them, so no migration is needed.

Remaining ▢ (tracked on #16011)

Found while tracing ownership: #16037. The pre-existing own-seed absence settlement can strand a cleanup-held task whose owner's capture never completed. It predates #16032 and is filed separately; this PR does not change that path.

Local review

The configured required reviewer (gpt-6.1-terra, ~max=2) ran 2 rounds.

  • Round 1 (cf93291) raised one finding, accepted and fixed in c6dcb28. The finding: a bare cleanup-owner-changed verdict can be transient right after completion, because the run's own cleanup handoff is written to the task after completeAgent. Settling in that window could leave the task without a delivery verifier. The fix: the writer now settles a captured checkout only once the task completed or names another cleanup owner. The writer test pins this.
  • Round 2 (c6dcb28, the published head) was clean, with no findings.

Test plan

  • agentRepoStateVerification: a new case covers settlement through both the sweep and the receipt wake. It also covers each hold: the run still owns cleanup, a live owner, the checkout present in either path spelling, the local ref present, a registered worktree. It fails on the pre-change source.
  • cosAgentLifecycle: a new writer contract case covers a completed task, another named owner, a pending handoff, the run's own handoff, a missing task, a CAS refusal, the wrong path and a non-cleanup run. Its three refusal states fail without the ownership guard.
  • Green: the agentRepoStateVerification, cosAgentLifecycle, heldCheckoutRecovery and completedCheckoutEvidence suites, plus 19 adjacent completion, retirement and held-checkout suites (653 tests).
  • npm run pregate passed.

Refs #16011

A cleanup run whose task has moved to another owner no longer waits for a
successor to prove it delivered the exact same captured head. Once the
run's own checkout, local branch and worktree entry are gone and no live
run owns the branch, its physical cleanup settles directly. The run keeps
its original result, and its cleanup line reports the local worktree as
cleaned up without claiming the code merged.

The periodic completion sweep now settles these runs as well; before, only
a matching retirement receipt could. This removes settleSeededPredecessor
with its 25-hop resume-chain proof, the moved-predecessor receipt wake, the
successor retirement writer, and the now-unused inspectAbsentCheckout.

Refs #16011
A cleanup run can briefly look handed off right after it completes,
because its own cleanup handoff is written to the task after the run is
marked complete. Settling its physical cleanup in that window would leave
the task waiting on a run that no longer verifies delivery.

The absent-checkout writer now re-reads the task as it settles a captured
checkout and proceeds only when the task has completed or names another
cleanup owner. Neither state can be handed back to the run, so an unowned
task, the run's own pending handoff or an unreadable task stays pending
for the next pass.

Refs #16011
@atomantic atomantic added implementer:opus-5-5 PR opened by the opus-5-5 model reviewer:gpt-6-1-terra Locally reviewed by the gpt-6-1-terra model labels Nov 14, 2026
@atomantic
atomantic enabled auto-merge November 14, 2026 06:06
@atomantic
atomantic merged commit d5bbe56 into main Nov 14, 2026
17 checks passed
@atomantic
atomantic deleted the claim/issue-16011 branch November 14, 2026 06:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

implementer:opus-5-5 PR opened by the opus-5-5 model reviewer:gpt-6-1-terra Locally reviewed by the gpt-6-1-terra model

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants