fix(creation): prevent duplicate workspaces and agents on retries - #4442
fix(creation): prevent duplicate workspaces and agents on retries#4442boudra wants to merge 5 commits into
Conversation
|
| Filename | Overview |
|---|---|
| packages/server/src/server/request-receipts/index.ts | Generalizes durable receipts across agent creation, workspace creation, and message delivery with operation-specific identities and replay validation. |
| packages/server/src/server/session.ts | Integrates workspace creation with durable receipts while preserving explicit handling for ambiguous interrupted provisioning. |
| packages/app/src/composer/draft/create-flow.ts | Restores active and failed creation state across remounts and blocks only genuinely active duplicate submissions. |
| packages/app/src/stores/create-flow-store.ts | Adds atomic duplicate suppression and retained failure details while allowing abandoned attempts to retry. |
| packages/app/src/screens/new-workspace-screen.tsx | Gives each workspace draft a stable workspace, agent, and initial-message creation identity. |
| packages/app/src/agent-creation/index.ts | Centralizes the two-receipt agent creation and initial-message delivery sequence. |
| packages/app/e2e/browser/creation-idempotency.spec.ts | Covers rapid submissions, transport replays, remount recovery, prompt acknowledgement loss, and independent concurrent drafts through user-level scenarios. |
| packages/server/src/server/file-observer/internal/native-recursive.ts | Records files first announced through native change notifications so later coalesced removals can be reconciled. |
| packages/app/src/screens/workspace/explorer-sidebar-tab-rail.tsx | Uses complete tab-target identity when toggling workspace-scoped plugin panels in Explorer. |
Sequence Diagram
sequenceDiagram
participant UI as Draft UI
participant Client as Daemon Client
participant Receipts as Request Receipts
participant Workspace as Workspace Provisioning
participant Agent as Agent Runtime
UI->>Client: create workspace(draft key)
Client->>Receipts: execute(create-workspace, key)
Receipts->>Workspace: provision once
Workspace-->>Receipts: workspace ID
Receipts-->>Client: durable result
UI->>Client: create agent(draft key)
Client->>Receipts: execute(create, key)
Receipts->>Agent: create once
Agent-->>Receipts: agent ID
Receipts-->>Client: durable result
UI->>Client: send initial prompt(message ID)
Client->>Receipts: execute(send, agent ID, message ID)
Receipts->>Agent: deliver once
Agent-->>Receipts: completed
Receipts-->>Client: acknowledgement
Reviews (6): Last reviewed commit: "fix(file-observer): track files announce..." | Re-trigger Greptile
709c0ad to
8f81ddc
Compare
ba95a79 to
ebab0b8
Compare
8340789 to
dc3c7d0
Compare
Linked issue
Closes #4327. Closes #4058. Closes #3217. Closes #4279. Closes #2673.
Refs #4039, which concerns duplicate sends in an already active session and remains a separate investigation.
Type of change
Reasoning
One submit could start several real agents doing the same work. Rapid clicks raced React rendering, remounted drafts lost their pending state, and retrying after a timeout could create another agent even though the first was already running.
The app now gives each draft a stable creation key and first-message ID. Agent creation and initial-prompt delivery use separate durable receipts. Workspace creation accepts an optional
idempotencyKeytoo, extending the existing daemon journal across socket sessions and restarts. Replaying a completed key returns the original resource; different arguments conflict. Interrupted workspace provisioning remains an explicit unknown outcome instead of treating a partial registry record as success. Completed workspace replays reject a missing checkout. A provider delivery with an unknown outcome is not blindly repeated.The app also consumes pending submissions correctly in Expo's emitted production code and restores an in-flight draft independently of the consumed handoff. Failed drafts can be submitted again. Remounted views rebuild their pending preview after model settings hydrate and unlock when the original request fails. Sending the first prompt still supplies the agent's initial title. Workspace creation hooks execute inside the receipt operation, so a replay does not rerun hooks.
Goals
Non-goals
Supersedes
These five PRs have been closed in favor of this PR.
QA
Before the fix, real browser/isolated daemon tests reported:
The browser regression file covers local and worktree creation, rapid agent submits, repeated new-workspace prompts, transport replays, a dropped first-prompt acknowledgement, initial naming, actual workspace eviction/remount, and concurrent independent drafts. Browser mechanics and resource cleanup live in helpers and fixtures; draft lifecycle assertions use the store directly.
Windows CI also exposed missed file-deletion notifications under churn. The native observer now classifies previously unknown paths announced only by a
changeevent, so subsequent reconciliation can recover coalesced deletions. A deterministic real-filesystem regression failed before this fix; all 16 observer tests passed in ten consecutive local runs afterward. The Windows server CI suite now passes ondc3c7d00c.Validation:
Final browser run (videos recorded):
Tests use real sockets, registries and Git worktrees with the test provider adapter; no live provider billing. Tested on Chromium/web and the Linux daemon. Native iOS/Android and packaged Electron were not exercised. No visual layout changes.
The new app requires the host's receipt capabilities for these creation flows and asks for a host update when unavailable. The wire fields remain optional for older clients.
Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatpasses