Skip to content

Fix plan approval resume and worktree lifecycle races - #390

Merged
goldmar merged 5 commits into
mainfrom
agent/fix-stale-plan-approval-callback
Aug 2, 2026
Merged

Fix plan approval resume and worktree lifecycle races#390
goldmar merged 5 commits into
mainfrom
agent/fix-stale-plan-approval-callback

Conversation

@goldmar

@goldmar goldmar commented Aug 2, 2026

Copy link
Copy Markdown
Owner

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

  • Centralize exact plan-decision version resolution and resumed-plan state.
  • Preserve unresolved approval state across idle timeout, runtime eviction, restart recovery, and stable-ID replacement.
  • Treat an explicit bypass resume as approval only when an exact actionable plan version exists.
  • Make callback/resume races idempotent and consume only sibling tokens for the resolved plan version.
  • Keep superseded, revised, rejected, malformed, and wrong-version callbacks fail-closed.
  • Roll provisional approval state back when resume fails before reaching running.
  • Short-circuit terminal/worktree handling while a plan remains actionable.
  • Restore worktrees through the stable public session identity so resumes reuse the original path and branch.
  • Retire stale persisted backend indexes when a stable session ID is replaced.
  • Fail closed when persisted branch metadata points at a different worktree.
  • Prevent retention cleanup for resumable or plan-gated worktrees.
  • Suppress false no-change completion and follow-up noise while retaining genuine launch, approval-needed, resumed, terminal, PR, and failure signals.

Validation

  • pnpm verify
    • static guardrails
    • TypeScript
    • production bundle
    • complete repository test suite
  • Focused callback, respond, launch, session-store, session-manager, bootstrap, worktree-controller, and worktree-strategy regressions
  • pnpm check-plugin-security
  • pnpm audit --prod — no known vulnerabilities
  • git diff --check

Operational boundary

This PR does not restart the Gateway, modify live configuration, mutate active sessions, or merge/deploy itself.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Bundle Size Report

Runtime file Size
dist/chunks/agent-pr.js 0.6 KB
dist/chunks/chunk.js 110.1 KB
dist/chunks/npm-release-client.js 0.2 KB
dist/index.js 422.1 KB
Total 533.1 KB
Limit Status
600.0 KB ✅ Within limit

Complete bundle is within the 600.0 KB limit.

@goldmar
goldmar marked this pull request as ready for review August 2, 2026 00:20
@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown

Greptile Summary

The PR hardens plan-approval resume and worktree lifecycle handling.

  • Preserves unresolved plan-decision state across stable-session replacement and recovery.
  • Makes approval callbacks version-aware and idempotently consumes sibling decision tokens.
  • Restores retryable plan state after failed resumes without resurrecting cleaned worktree metadata.
  • Uses pending approval as the authoritative terminal gate and protects resumable worktrees from cleanup.
  • Restores resumed worktrees through the stable public session identity and retires stale persisted indexes.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

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]
Loading

Reviews (3): Last reviewed commit: "Preserve plan approval rollback on termi..." | Re-trigger Greptile

Comment thread src/plan-decision-state.ts
Comment thread src/session-lifecycle-service.ts Outdated
Comment thread src/session-manager.ts Outdated
Comment thread src/session-manager.ts Outdated
@goldmar
goldmar merged commit 8210577 into main Aug 2, 2026
11 checks passed
@goldmar
goldmar deleted the agent/fix-stale-plan-approval-callback branch August 2, 2026 01:24
@goldmar goldmar mentioned this pull request Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant