fix(cli): stop replaying completed operation deliveries - #322
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Bind delivery assistant history to the stable completion system turn so reconciliation can consume it across intervening user turns without claiming user dispatch state. Model: gpt-5
4f6f45d to
26e4737
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 26e4737d3d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Persist attempt ownership and settle Deliveries only from execution outcomes so teardown-finalized Assistant entries cannot masquerade as completion. Bound interrupted recovery to one retry. Model: gpt-5
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66718a55ff
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Keep the owning Assistant turn as an immutable settlement identity while steer advances the visible prompt tail. Add lifecycle coverage for A-to-B-to-C steering. Model: gpt-5
Make Worker boot identity and attempt identity jointly fence Delivery settlement and interruption. Recover old-boot orphans only after Worker startup, and stop permanently after two unsettled attempts. Model: gpt-5
Acquire an exclusive Delivery finalization claim before writing configuration or exhaustion results. Token-match terminal consumption and repair stale non-started history when recovered execution begins. Model: gpt-5
Keep worker fencing, exclusive claims, bounded attempts, and handled versus interrupted settlement while removing redundant acknowledgement metadata. Backfill legacy pending deliveries as one unknown prior attempt. Model: gpt-5
Related issue
Same-repository branch; no intake Issue was created per repository policy.
Incident / impact
A finished Operation could leave its completion Delivery pending. Each later reconciliation wake then started the requester session ACP again, including Custom ACP providers, even though the Operation itself had already finished.
Early repairs inferred completion from the stable Assistant entry. That was unsafe in both directions: the entry is created before prompt execution, while teardown can mark an interrupted entry as
finishedwithendedAt.Root cause
Delivery had no durable success acknowledgement owned by the execution path. Session history represented turn lifecycle, not successful continuation settlement.
The first attempt-token implementation also left two check-then-act races:
CONFIGURATION_UNAVAILABLEto history after another coordinator had claimed and started execution. The guarded SQLite consume rejected the stale mutation, but the history write had already happened.A Host lease alone cannot distinguish Worker generations in daemon mode because the supervisor keeps that lease while replacing its child Worker.
Resolution
Delivery mutation now uses three fencing layers:
workerBootId. The daemon supervisor waits for the previous child to exit before spawning its replacement; foreground startup crosses the Host-lease barrier. A new Worker performs orphan recovery once at startup.Execution claims increment
attemptCount; terminal claims do not. Configuration-unavailable, attempts-exhausted, and expired-stale paths must claim before any history or consume side effect. A static failure is written while that claim is held, then consumed only whenworkerBootId + claimIdstill match.Acknowledgement and interruption use the same pair. Claim contention exits before Assistant history, failure bookkeeping, or ACP startup. A late acknowledgement, release, or terminal consume from an old Worker cannot alter a current claim.
If a Worker exits while holding either claim kind, replacement-Worker startup clears the old token without resetting
attemptCount. If a crash left a staticnot_startedmarker before consume, a later valid execution removes that stale marker when it begins.Unknown execution interruption gets one replacement-Worker retry. If two attempts end without durable settlement, lifecycle-safe reconciliation claims terminal ownership, writes
DELIVERY_ATTEMPTS_EXHAUSTED, consumes the Delivery, and never starts a third ACP.completedacknowledgement and consumefailedacknowledgement and consumeVerification
pnpm checkon Node 22: PASSpnpm format:check: PASSContext handoff
Instructions for reviewing agents
not_startedmetadata.Authoring context