Repository navigation
fix(questions): keep the questions card open until the person answers - #212
Closed
TheGreatAxios wants to merge 4 commits into
Closed
TheGreatAxios wants to merge 4 commits into
TheGreatAxios wants to merge 4 commits into
Conversation
When one model response made several calls that need approval, each call parked, but the send settled on the first suspension. The others never got an approval card or a tool result, and the run waited on them forever. An answered call no longer wakes the model while a sibling from the same response still waits: the reactor announces the next parked call instead, so the model continues only once every call has its result. The calls surface one at a time, because a workflow step parks on one signal. Every gated call of a batch is now also parked durably before the first one is announced. The announcement settles the send, and the agent's state is mirrored at that point, so a sibling persisted only afterwards could be lost to a restore. The results of calls from the same response that ran or were refused land in that same commit. The siblings queue behind the announced call with no armed gate, so each one's deadline starts when it is announced rather than running out while it waits its turn. The batch is recorded on each pending operation, so a restored reactor still finds the next one.
When one of several gated calls from the same model response timed out, its error result went straight to the director, so the model continued while a sibling call was still parked. That sibling never got an approval card or a tool result. A timed-out call is now treated like an approved or rejected one: while a sibling from its response still waits, the reactor announces that sibling instead of waking the model.
A parked call could only be approved to run or rejected. A tool whose result is the person's own input, such as a set of questions, needs a third way out: the person supplies the result. A tool declares `approval: "respond"` to opt in, and its approval snapshot is marked respondable. POST /approvals/:id/respond resolves only such a call: the decision carries the result, the row records the responded status, and the reactor answers the parked call with it as a normal tool result without running the tool. A respondable call is responded to or rejected once; the approve route refuses it, and the reject route refuses a standing rejection, so it can never run or block later questions. Such a call waits for the person with no deadline, as the hub's approval does. Before, the reactor answered any parked call "approval timed out" after an hour, which would have closed questions a person left open. A gated call whose arguments fail its tool's own check, the new optional ToolBundle.check, is answered with that error at once and never parks. A check that throws is answered with its error, as a throwing before-tool extension is.
ask_questions returned "Asked." at once and the answers followed as the person's next message, so the page had to guess from later turns which card was still open, and the card was gone after a reload. The call now parks like an approval. The card is drawn from the pending approval, so it survives a reload and leaving the project. Its answers, or words typed in the composer while it is open, resolve the parked call through the respond route as JSON (answers per question, or reply), so they are the call's tool result. The conversation shows that result as the person's turn, so the answers stay in the thread after a reload. Files sent or an approach picked while questions are open answer them too, instead of waiting unseen until the questions are answered. Malformed questions are refused before the call parks, so every waiting set of questions shows on its card and is never approved to run. Open questions are not a safe point for a coordinator upgrade.
TheGreatAxios
marked this pull request as draft
November 6, 2026 17:35
Contributor
Author
|
Closing: this needs further exploration into its Interchange touch points before we land it. The write-up and decision are on CL-12168. |
Contributor
Author
|
The cleaned-up proposal is on two branches, without PRs, while the decision on CL-12168 is open:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The questions card no longer disappears after a reload: the question is now a tool call that waits for the person's answer, and that answer becomes its result. Needed a vendored Interchange change, which also stops a second approval in one reply from being dropped.
Verification
Scripted model, 2 runs each. All checks pass, including e2e.
Closes CL-12168