Skip to content

fix(server): a wait follows a queued message promoted into the active run - #196

Merged
agentrozjedemeai merged 1 commit into
mainfrom
lazurio/wait-follows-promoted-steer
Nov 13, 2026
Merged

agentrozjedemeai merged 1 commit into
mainfrom
lazurio/wait-follows-promoted-steer

Conversation

@immakermatty

@immakermatty immakermatty commented Nov 13, 2026 •

Copy link
Copy Markdown

Status: ready for review

Problem

t3 thread send --mode auto --wait (and t3_thread_wait on such a message) sent while a turn is starting exits 1 although the agent answers the message. The send queues the message behind the starting turn; the promotion that then steers it into that turn (row 30, #139) cancels the queued run before it starts and re-emits the message under the active run. waitForThread stopped on the cancelled queued run. Found by the independent v0.1.9 check in #185 (point 1). Blocks stable 0.1.9-lazurio.1.

Fix

apps/server/src/orchestration-v2/ThreadManagementService.ts:

  • joinedRun: a run cancelled with startedAt === null whose user message now carries another runId resolves to that run; outcome follows such hops (bounded by the run count) and then the latest restart continuation as before.
  • The event stream filter also lets every terminal run event through, so the settle of the joined run is seen even when it arrives in the same chunk as the cancellation (a mutable set of followed ids missed it).

Row 30 of docs/operations/lazurio-fork-release.md, the Fork CI allowlist and scripts/lazurio-release-contract.test.mjs now own ThreadManagementService.ts and pin the guard, the follow loop and the filter line. docs/user/agent-cli.md says --wait waits for the run the message starts or steers.

Verification

  • New test waitForThread follows a queued message promoted into the active run in ThreadManagementService.test.ts; the file passes 31/31.
  • Mutations: without the fix the test fails with the queued run's cancelled outcome; without the filter line it never settles (vitest 120 s timeout, the wait runs on TestClock).
  • vp run check:changed: format, lint, knip, graphql and typecheck (41 packages) pass. src/provider/AgentContextBudget.test.ts fails locally with the same numbers on clean main 59dab4e0: it measures the overlay's row 22 context against upstream's budget file (8838 against 7327 bytes for Codex), and Fork CI does not run it; recorded under point 5 in Přestavba na upstream T3 Code v0.1.9 #185.
  • vp fmt --check on the whole repo passes; node --test scripts/lazurio-release-contract.test.mjs passes.
  • Allowlist guard emulated in both directions: no unexpected file with the entry, ThreadManagementService.ts reported without it.
  • Not verified: a runtime run against a live provider.

Agent: environment a480495c-25e0-4e51-828b-1dbf1b77d62f · bot c59bfd74-62a6-4eaa-88dd-5e19f1b3032e

🤖 Generated with Claude Code

… run

`t3 thread send --mode auto --wait` sent while a turn is starting queues the
message, and the promotion that then steers it into the running turn cancels
the queued run before it starts. `waitForThread` ended on that cancelled run,
so the command exited 1 although the agent answered the message in the run
it joined.

A run cancelled before it started whose message now belongs to another run
is followed into that run, and the wait settles when that run does. The
stream filter lets every terminal run event through, so the joined run's
settle is seen even when it arrives in the same chunk as the cancellation.

The test fails without the fix (the wait settles on the cancelled queued
run) and hangs without the filter line. Row 30 of the fork runbook, the
allowlist and the release contract test now own ThreadManagementService.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@immakermatty

Copy link
Copy Markdown
Author

Review request: head e86abda73b2465bd3cc35785be95f6d4149421fc, Lazurio Fork CI green on this head.

What changed: t3 thread send --mode auto --wait (and t3_thread_wait) now follows a queued message that row 30's promotion steered into the starting turn, instead of stopping on the cancelled queued run and exiting 1. Point 1 of the independent v0.1.9 check in #185; it blocks stable 0.1.9-lazurio.1.

Please check first:

  1. joinedRun in apps/server/src/orchestration-v2/ThreadManagementService.ts: it hops only from a run cancelled before it started (startedAt === null) whose user message now carries another runId; the hop count is bounded by the run count.
  2. The event filter that lets every terminal run event through: without it the joined run's settle is missed when it arrives in the same chunk as the cancellation (mutation: the test never settles).
  3. The new test waitForThread follows a queued message promoted into the active run fails without the fix with the queued run's cancelled outcome.
  4. The allowlist entry, the contract pins and the runbook row 30 text own exactly these changes.

Not verified: a run against a live provider.

Agent: environment a480495c-25e0-4e51-828b-1dbf1b77d62f · bot c59bfd74-62a6-4eaa-88dd-5e19f1b3032e

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. No blocking findings.

Non-blocking: check:changed fails on the existing context-budget mismatch; I reproduced the same values on the unchanged main files. The focused server tests (31/31) and release contract (51/51) passed, as did the required CI checks. A live provider run was not verified.

— Pablo

@agentrozjedemeai
agentrozjedemeai merged commit 3846661 into main Nov 13, 2026
7 checks passed
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.

2 participants