Skip to content

fix(cli): stop replaying completed operation deliveries - #322

Open
wibus-wee wants to merge 6 commits into
mainfrom
fix/operation-completion-delivery-replay
Open

fix(cli): stop replaying completed operation deliveries#322
wibus-wee wants to merge 6 commits into
mainfrom
fix/operation-completion-delivery-replay

Conversation

@wibus-wee

@wibus-wee wibus-wee commented Sep 3, 2026

Copy link
Copy Markdown
Member

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 finished with endedAt.

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:

  • A coordinator could overwrite an active attempt owned by another coordinator.
  • Configuration resolution is asynchronous. A coordinator could observe no active attempt, later resolve the configuration as unavailable, and write CONFIGURATION_UNAVAILABLE to 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:

  • Host: the existing Host lease excludes other daemon runners, Electron Hosts, and foreground Hosts for one installation.
  • Worker: every CLI Worker process has a fresh 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.
  • Claim: execution attempts and no-execution terminal settlement share one exclusive token slot. Every claim has a fresh id and is conditional on both active-token columns being empty. A foreign or lost claim is normal contention.

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 when workerBootId + claimId still 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 static not_started marker 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.

Execution result Delivery behavior
Normal output Durable completed acknowledgement and consume
Durable execution failure or no output Durable failed acknowledgement and consume
Shutdown, cancellation, crash, or missing settlement No acknowledgement; release or recover the orphan
First unknown interruption One retry after the Worker lifecycle barrier
Second unknown interruption Fenced static exhaustion result; no third ACP
Configuration disappears during a competing execution Terminal claim loses; no history mutation
Claim lost to another Worker Silent contention; no Assistant, failure, or ACP
Requester machine/session unavailable Remains pending until runnable

Verification

  • pnpm check on Node 22: PASS
  • pnpm format:check: PASS
  • Focused changed-area suites: 156 tests passed (Coordinator 41, store 25, execution 78, model 12).
  • Existing supervisor suite: 49 tests passed, including the replacement-child exit barrier.
  • Deterministic regressions cover config-sync contention, terminal-claim versus execution exclusion, orphaned terminal claims, stale history repair, two-Worker execution exclusion, stale acknowledgement/release, graceful teardown, hard crashes, steering identity, and permanent stop after two unsettled attempts.

Context handoff

Instructions for reviewing agents

  • Review focus: Verify that every Delivery-side history or consume mutation first owns the exclusive token, orphan recovery occurs only at Worker startup, and all settlement operations match Worker plus claim identity.
  • Decisions to challenge: Confirm config resolution cannot write history after losing a terminal claim, terminal claims do not spend the two-attempt budget, and recovered execution removes stale not_started metadata.
  • Plausible failures / evidence gaps: A crash after external ACP side effects but before local acknowledgement can cause one retry; the two-attempt bound prevents infinite replay.

Authoring context

  • User goal / directives: Stop completed Operation notifications from repeatedly waking a Custom ACP provider without silently dropping interrupted Delivery work or corrupting continuation history.
  • Constraints / non-goals: Preserve offline pending delivery and ordinary user-dispatch ownership. Generic Assistant terminal fields are not success evidence.
  • Risk-bearing decisions: Host, Worker, and claim identity are separate fences. Terminal history and consumption occur under the same claim as execution exclusion.
  • Destructive or irreversible behavior: Exhausted Delivery is consumed only after writing a durable static failure while holding terminal ownership.
  • Deliberately not changed: Remote machine availability and routing policy.
  • Confidence: Crash and contention windows are covered deterministically; no test relies on sleeps or scheduler timing.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T15:55:49.741860Z a500e6e New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@wibus-wee
wibus-wee requested a review from zxch3n September 3, 2026 02:00
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
@wibus-wee
wibus-wee force-pushed the fix/operation-completion-delivery-replay branch from 4f6f45d to 26e4737 Compare September 3, 2026 10:56

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread apps/cli/src/orchestration/operation-coordinator.ts Outdated
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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread apps/cli/src/orchestration/operation-coordinator.ts Outdated
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
Comment thread apps/cli/src/orchestration/operation-store.ts Outdated
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant