Skip to content

fix(vendor): open a message run when parked work resumes with none open - #139

Merged
TheGreatAxios merged 3 commits into
mainfrom
cl-12080-open-a-turn-for-a-resumed-approval-in-vendored-interchange
Nov 4, 2026
Merged

TheGreatAxios merged 3 commits into
mainfrom
cl-12080-open-a-turn-for-a-resumed-approval-in-vendored-interchange

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When the coordinator asks for approval, it parks and waits. If the approval is decided after the hub restarts, or after the turn that asked has already closed, the coordinator picks the work back up but never reports that a turn started or ended. The project page and the hub's activity read then show the coordinator as "working" until the next message arrives, even though it already finished.

The same thing happens when an approval times out, or when a reply to an async tool call arrives late.

Fix

In vendored Interchange's reactor, resumed work now opens its own turn (message.run.started / message.run.ended) whenever no turn is open. The turn is named after the message that resumed it, if there is one. If a turn is already open when the work resumes, the work joins it as it did before.

A follow-up commit makes sure the resuming message also survives a rare timing case: the gate clears while the reactor is still saving the park.

Nothing in Builder reads which message a turn belongs to. The web app and the hub only use the start and end to decide whether the coordinator is working, so a turn with no message name (from a timeout) changes nothing for them.

Vendoring

This changes vendor/interchange (the reactor, plus comments in gates.ts and inference-events.ts), and vendor/interchange.manifest.json records the new files. Upstream Interchange is not changed yet. That's tracked in INTR-721, and once it lands upstream this patch can be dropped.

Verification

  • bun run lint, format:check, typecheck, test, pins:verify and vendor:verify pass.
  • All 193 vendored reactor tests pass. Ten new tests cover resumed work: approved, rejected and timed-out approvals and a late async reply, both after a restart and after the original turn closed. They also cover a resumed turn that waits without replying, and an approval decided while its turn is still open. Every resume test fails against main; the still-open control passes on both.

Closes CL-12080

Parked work resumed while no message run is open (after a restart, or
after the run that parked it closed) never opened a run, so it reported
no start and no end and consumers saw the agent as working forever. The
resumed work opens a run when none is open, named for the message that
resumed it when there is one; a resume that arrives while a run is open
stays in that run. This covers decided and timed-out approvals and
answered async correlations.
@linear-code

linear-code Bot commented Nov 4, 2026

Copy link
Copy Markdown

CL-12080

@brianjfox brianjfox self-assigned this Nov 4, 2026
@brianjfox
brianjfox marked this pull request as ready for review November 4, 2026 09:53
@corbits-triage

corbits-triage Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Triage: In progress

Triage is waiting for code review before it decides. This comment shows the verdict once it has.

A gate clear that lands while its suspend is still committing is replayed
after reactor.gate.blocked. The replay dropped the correlated message, so a
run opened for that resume would carry no message id or inference options.
Today the suspending run is always still open when the replay lands, so this
only keeps the vendored patch consistent.
@TheGreatAxios
TheGreatAxios added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 59d69dd Nov 4, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants