# fix\(server\): withdraw a stopped turn's pending approvals · PR \#22023 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/22023)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: open

Source repository: Unavailable fork

Source branch: fix/21935-withdraw-approvals-on-turn-end

Target branch: main

Head commit: b3dbe20998016d0755b2053369797fc8571d2fc3

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/22023)

[Commits](https://git.cafe/pingdotgg/t3code/pull/22023/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/22023/diffs?format=markdown)

## Description

---

## Problem

A delegated task cancelled while waiting for command approval can finish as interrupted while its approval remains pending. This occurs when the provider's terminal event commits before interruption cleanup, leaving the old approval actionable and the thread needing attention.

## Change

Withdraw the stopped turn's pending native approvals alongside questions, marking approvals cancelled and non-resumable and cancelling their associated nodes and timeline items. Preserve requests belonging to other turns and approvals on completed or failed root turns, whose background subagents may still need them. Recheck pending state inside the write transaction so cleanup cannot overwrite a concurrent answer.

## Scope and approval

Fixes #21935
GitCafe: https://git.cafe/pingdotgg/t3code/issues/21935
Triaged bug via the automated issue flow. Existing contributor implementation and author credit retained. Approval lifecycle changes require Julius's review. The PR has `bugfix`; it has not been merged or labeled `land`.

## Verification

- Main snapshot `3b95e7831b`: minimal ingestor regression test fails in both interrupted terminal paths with `expected 'pending' to equal 'cancelled'`; completed-turn control passes.
- Candidate `b3dbe20998`, after merging that main snapshot: ingestor, SQL/in-memory projection store, and turn-control suites pass, **63/63 tests**. Includes concurrent-answer protection.
- Targeted lint on the six changed files passes. `vp run typecheck` in `apps/server` exits 0 with no TypeScript errors. `git diff --check` passes.
- [Historical real Codex cancellation reproduction](https://github.com/pingdotgg/t3code/pull/22023#issuecomment-6280767665) demonstrates the terminal-event ordering behind the bug.
- Seven preserved local provider attempts cleared approvals normally; they do not reproduce the race. A new real-app attempt on the main snapshot was blocked by VM event-loop stalls, disconnects, and `EnvironmentNotRegisteredError` after pairing.

[Sanitized red/green server evidence](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c77fcc387663a600/issue21935-sanitized-server-evidence.txt).

Evidence: server tests prove the state transition; **fresh before/after interaction recordings are missing**. Proof audit is incomplete. Pending approval → parent cancellation → cleared child/parent UI, live child approval after normal root completion, and reconnect after cancellation remain unverified in a real client. Web, desktop/Electron, mobile, OpenCode v2 and Muse runtime behavior remain unverified. No UI capture or complete end-to-end verification is claimed.

Original implementation: Claude Sonnet 5.5 via T3 Code. Integration and verification: GPT-6.1-Sol and Claude Opus 5.5 through Codex and Claude harnesses in T3 Code.

