Skip to content

fix(core): reject approval resumes of a running turn before freezing it - #511

Closed
MachineLearning-Nerd wants to merge 2 commits into
truefoundry:mainfrom
MachineLearning-Nerd:fix-approval-resume-running-turn
Closed

fix(core): reject approval resumes of a running turn before freezing it#511
MachineLearning-Nerd wants to merge 2 commits into
truefoundry:mainfrom
MachineLearning-Nerd:fix-approval-resume-running-turn

Conversation

@MachineLearning-Nerd

@MachineLearning-Nerd MachineLearning-Nerd commented Aug 30, 2026

Copy link
Copy Markdown

Fixes #508.

SessionHandle.createTurn freezes the previous turn with cancelled-for-next-turn before the new request is validated, and there is no rollback. A request that later fails validation therefore kills the in-flight turn and leaves no successor. The issue has a live repro: a duplicate Allow click sends a second user.tool_approval turn, the server rejects it with 422, and the turn that is executing the approved tool is cancelled anyway, after the tool's side effect already ran.

The fix leans on an existing invariant: approval and tool-response items answer the required actions of a completed turn, and a running turn cannot have any. So when the input consists only of approval or tool-response items, createTurn now peeks at the previous turn read-only and throws InvalidAgentSendInputError if it is still running, before the freeze. The running turn is untouched. Inputs containing a user message keep today's barge-in behavior, and valid resumes are unaffected because their previous turn is always terminal.

Added a test covering both sides: an approval-only resume of a running turn is rejected and the turn stays running, while a user message still cancels it with cancelled-for-next-turn. Full trueforge-core jest suite (389 passing), tsc, and eslint are clean.

On process: I know CONTRIBUTING asks community PRs to wait for maintainer approval. Opening this anyway since it is small and directly tied to the repro in #508; happy to close it or rework the approach if you prefer to handle it differently.


Note

Medium Risk
Changes turn-lifecycle ordering in a core session path; behavior is narrowly scoped to approval/tool-response resumes but affects concurrency and cancellation semantics.

Overview
Fixes a race where SessionHandle.createTurn froze the previous turn with cancelled-for-next-turn before validating the new input, so a rejected duplicate approval (e.g. second Allow click → 422) could cancel an in-flight turn after the tool had already run (#508).

createTurn now, for input that is only approval or client tool-response messages, does a read-only check on the previous turn and throws InvalidAgentSendInputError if it is still running, before any freeze. Invalid resumes no longer touch the executing turn; user-message barge-in and valid resumes (previous turn already terminal) behave as before.

Adds a session test that an approval-only resume against a running turn is rejected and stays running, while a user message still cancels with cancelled-for-next-turn. Patch changeset for @truefoundry/trueforge / trueforge-core.

Reviewed by Cursor Bugbot for commit 2a56d1a. Bugbot is set up for automated code reviews on this repo. Configure here.

An approval or tool-response input can only answer the required actions
of a completed turn. Check the previous turn state read-only before the
cancelled-for-next-turn freeze, so an invalid resume such as a duplicate
approval no longer cancels the turn it races.

Fixes truefoundry#508
@changeset-bot

changeset-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a56d1a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@truefoundry/trueforge Patch
@truefoundry/trueforge-core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 87ed621. Configure here.

Comment thread packages/trueforge-core/src/agent-session/SessionHandle.ts

Copilot AI 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.

Pull request overview

Fixes a turn-lifecycle bug in trueforge-core where SessionHandle.createTurn() could cancel an in-flight turn before validating a new turn request, causing a duplicate approval/tool-response submission to truncate the running turn with no successor created.

Changes:

  • Add a pre-freeze, read-only guard in SessionHandle.createTurn() that rejects approval/tool-response-only inputs when the previous turn is still running.
  • Add a regression test asserting approval-only resumes don’t cancel a running turn, while user-message barge-in still cancels with cancelled-for-next-turn.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/trueforge-core/src/agent-session/SessionHandle.ts Adds a pre-freeze validation to prevent approval/tool-response resumes from cancelling a still-running previous turn.
packages/trueforge-core/tests/agent-session/sessions.test.ts Adds coverage for the “approval-only resume vs user-message barge-in” behavior around running turns.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/trueforge-core/src/agent-session/SessionHandle.ts
Comment thread packages/trueforge-core/src/agent-session/SessionHandle.ts
@MachineLearning-Nerd

Copy link
Copy Markdown
Author

Verified end to end in the UI as well: ran the server from this branch, went through a full approval flow, and double clicked Allow at the pause. The duplicate is rejected and the turn streams to completion with all post-approval output intact. The same double click on the published 0.1.4 build cancels the turn mid-stream as described in #508.

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.

createTurn cancels the in-flight turn before validating the new request — a duplicate approval submission can truncate the approved turn mid-stream

2 participants