Repository navigation
Conversation
The parked cancel is unregistered before an operator's decision is delivered, so an interrupt that bumped the generation while the decision waited on the session queue skipped it silently. Nothing reached either agent, the call was marked handed over so a later recovery ignored it, and the rebuilt agent answered it with "approval timed out" at the old deadline.
A decision handed to a reactor that closes before running the call, such as an interrupt landing while the loop is busy, left the call parked on disk with nothing to settle it: rehydration announces no gate, recovery ignores a correlation it handed over, and no drop was recorded. The rebuilt agent answered it with "approval timed out" at the old deadline. A handed-over decision is tracked like a drop until a rebuilt store shows its call closed.
There was a problem hiding this comment.
Review · Request changes
This records an approval that an interrupt skipped, or that was handed to an agent which closed before the tool ran, and settles it on the rebuilt session so it does not later time out as if nobody decided.
The case where delivery hands the decision over and then times out while watching for acceptance is handled on this branch: that call is kept and settled after the rebuild.
bun test --config ./bunfig.toml src/session/approval-resume-interrupt.test.ts src/session/approval-resume.test.ts src/tui/approval-delivery.test.ts src/tui/runner/exit.test.ts src/tui/runner/queued-approval-delivery.test.ts — 174 pass, 0 fail. Those tests cover the skipped, unrun, and failed deliveries this branch settles. They do not cover an approved tool that has already started.
What is still wrong: an approval you already gave can be recorded as denied if the session is rebuilt while that tool is still running.
Every decision handed to the agent is marked unfinished (src/session/approval-resume.ts:613), approval or rejection. On the next rebuild, a call that is still saved with no result is rejected as dropped (src/session/approval-resume.ts:771). The tool's result is not saved until the tool finishes. Approve a call, let the tool start, then interrupt before that result is written, and the rebuilt agent is told the call was denied. The tool may already have done its work. The transcript says it was dropped, so the model can try the same call again, and a grant saved before the interrupt can allow that retry without asking again.
A call whose result is already saved is left alone. The hole is the stretch after the tool starts and before its result is saved.
A deliverer gives up waiting to observe a decision's acceptance only after it has handed the decision to the agent, so the reactor may still hold it, but a delivery that threw was never tracked for the rebuild settle. An interrupt then rebuilt with the call still parked and nothing to settle it, and the rebuilt agent answered it with "approval timed out" at the old deadline. A decision whose delivery throws is tracked like a handed-over one, whether it failed before or after the hand-over, since either way the call stays parked.
|
Fixed in c0eccec. I didn't split pre-handoff failures from post-handoff ones. A pre-handoff failure, like a failed agent build, leaves the call just as parked, and without tracking the rebuilt agent answers it with "approval timed out" at the old deadline. The silent settle is the right outcome there too, and tracking every throw keeps the session layer from having to recognize Tests:
|
Summary
createQueuedApprovalDeliveris the deliver seam the TUI and the tests share.Verification
bun run checkpasses on each commit (9527 tests at the tip)Fixes CL-11433