Fix plan approval resume and worktree lifecycle races - #390
Merged
Conversation
Bundle Size Report
|
goldmar
marked this pull request as ready for review
August 2, 2026 00:20
Greptile SummaryThe PR hardens plan-approval resume and worktree lifecycle handling.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/plan-decision-state.ts | Centralizes plan-version resolution, exact resumed-plan approval, duplicate-approval detection, and cleanup-aware rollback state. |
| src/session-manager.ts | Tracks provisional approval claims through startup and rolls them back after pre-running terminal failures while preserving terminal worktree cleanup. |
| src/session-lifecycle-service.ts | Makes pendingPlanApproval the authoritative terminal waiting gate and centralizes idle-timeout approval reminders. |
| src/session-worktree-controller.ts | Prevents cleanup and no-change classification when worktree ownership metadata is mismatched or the session remains resumable or plan-gated. |
| src/tools/agent-launch.ts | Carries resumed plan state and stable-session worktree identity into non-fork launches. |
| src/callback-handler.ts | Handles repeated exact-version approval callbacks idempotently and consumes matching decision tokens. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Resume stable session] --> B{Pending plan approval?}
B -- No --> C[Resume normally]
B -- Yes --> D{Exact actionable version and bypass requested?}
D -- No --> E[Preserve plan gate]
D -- Yes --> F[Apply approval and claim resume]
F --> G{Reached running?}
G -- Yes --> H[Consume matching decision tokens]
G -- No --> I[Run terminal handling]
I --> J[Restore retryable plan state]
J --> K[Preserve authoritative worktree cleanup]
Reviews (3): Last reviewed commit: "Preserve plan approval rollback on termi..." | Re-trigger Greptile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix the end-to-end lifecycle race that let a valid plan approval prompt outlive the deterministic session state, and harden adjacent plan, resume, worktree, cleanup, and notification paths.
Root cause
A non-fork resume reuses the public OCA session ID. Stable-ID replacement previously created a fresh runtime row with default approval state and could restore worktree context through the backend conversation ID rather than the stable session record. A callback racing that replacement then saw
pendingPlanApproval=false, while the original Plan vN buttons and tokens were still visible. Separately, terminal handling evaluated worktree strategy before recognizing that a plan-only run was still awaiting approval, so an actionable/resumable plan could be misclassified as a terminal no-change run, cleaned, and announced twice through canonical plus orchestrator completion paths.What changed
Validation
pnpm verifypnpm check-plugin-securitypnpm audit --prod— no known vulnerabilitiesgit diff --checkOperational boundary
This PR does not restart the Gateway, modify live configuration, mutate active sessions, or merge/deploy itself.