Remove the reconciler's background session stops (rest-stop and stop-on-finalise) - #187
Merged
Conversation
Reconciliation ran two background stops. The rest-stop released any session on a needs-input/review/waiting task whose listing entry read done, on every pass; stop_finalised retired the registry entry of every session a pass finalised. Both fired unprompted, at whatever the pass found, on every read of the store — which is every TUI refresh and every CLI verb. At the operator's desk that reaches into sessions nobody asked about. The separate Claude window flickers, moves and gets reset even when the task being reconciled is not the one in focus, and a stop landing in a live session is a plausible source of prompt-cache churn. No reading of a listing is worth doing that to a desk, so both call sites go. Every stop Voro makes now hangs off something the operator just did: a closing verdict (Accept, Abort, Abandon, via stop_closed_session) or the send that needs the hold released. The quick-message path already released a held session inline, waited on, because the operator could outrun a reconcile tick. That inline release is now the only one, and it covers the same ground: the rest test — task at rest, listing entry reads done — is read on the keypress that needs the hold gone rather than swept in the background, and the invariant that a message only ever reaches a session that has explicitly handed back is unchanged. Mid-turn the liveness gate still refuses the send; between turns the send releases the hold itself and refuses outright if that release fails. The capped-session sweep's unconditional release is untouched, as are the reconciler's read-only probes. The accepted cost is what Voro did before it stopped anything: a session reconciliation finalises keeps its entry in the agent's own listing until the verdict that closes the task, and a handed-back session keeps its entry until the first message into it. That is a lingering listing entry and nothing broken — the same degradation an agent defining no stop verb has always had — and the operator's close still clears the common case. DESIGN.md §8 moves with the code: the release paragraph, the rest rule, the delivery invariant, the recorded trade, and which closes stop. Verified: cargo test --workspace (916 pass), clippy --all-targets -D warnings clean, fmt clean. The reconcile tests that pinned the removed behaviour are replaced by ones pinning its absence — a finalised dead session and a healed stale row both close without a stop, and a task at rest in all three states keeps its registration — and the send-path tests (a_send_releases_a_session_the_agent_still_holds_at_rest, a_send_makes_no_stop_when_the_session_is_not_listed_at_rest) still pass unchanged. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
MJohnson459
added a commit
that referenced
this pull request
Aug 21, 2026
…oved #187 took both background stops out — the rest-stop that released a held session on every pass, and the retire-on-finalise — leaving every stop hanging off an operator action. It carried no changelog entry, so the entry describing the feature still promised the behaviour that had just gone: that the reconciler retires a dead or stale session's entry, and that a session on needs-input, review or waiting is retired at handover. Neither is true on main. `Action::stops_session` is `Accept | Abort | Abandon`, and the only other stop is the hold the quick-message path releases inline when the operator sends. cargo-dist builds the GitHub release body from this section verbatim, so the claim would have shipped as the release notes for the feature it misdescribes. Rewritten to say what stops and when, and to keep the reason the background stops went, which is the half a reader can observe: no unrelated window flickering while they work. No entry is added for #187 itself — it fixes behaviour that has never been in a release, which this section leaves out by policy.
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.
Reconciliation ran two background stops: the rest-stop released any session on a
needs-input/review/waitingtask whose listing entry readdone, andstop_finalisedretired the registry entry of every session a pass finalised.Both fired unprompted, at whatever the pass found, on every read of the store —
which is every TUI refresh and every CLI verb.
At the operator's desk that reaches into sessions nobody asked about: the
separate Claude window flickers, moves and gets reset even when the task being
reconciled is not the one in focus, and a stop landing in a live session is a
plausible source of prompt-cache churn. Both call sites go, along with
rest_stop,stop_finalisedand the now-unused imports. Every stop Voro makesnow hangs off something the operator just did: a closing verdict (
Accept,Abort,Abandon, viastop_closed_sessionincli.rs/app.rs) or the sendthat needs the hold released.
The quick-message path already released a held session inline and waited on,
because the operator could outrun a reconcile tick. That inline release is now
the only one, and it covers the same ground: the rest test — task at rest,
listing entry reads
done— is read on the keypress that needs the hold gonerather than swept in the background. The invariant that a message only ever
reaches a session that has explicitly handed back is unchanged: mid-turn the
liveness gate refuses the send, between turns the send releases the hold itself
and refuses outright if that release fails. The capped-session sweep's
unconditional release is untouched, as are the reconciler's read-only probes
(
sessionslistings,logscap readings).The accepted cost is what Voro did before it stopped anything: a session
reconciliation finalises keeps its entry in the agent's own listing until the
verdict that closes the task, and a handed-back session keeps its entry until
the first message into it. That is a lingering listing entry and nothing broken
— the same degradation an agent defining no
stopverb has always had — andthe operator's close still clears the common case.
DESIGN.md §8 moves with the code: the in-place-resume paragraph, the rest rule
(now stated as happening on the send, with a new paragraph recording why no
sweep makes it), the delivery invariant, the recorded trade (which now runs the
other way), and which closes stop. Doc comments in
dispatch.rs,session_probe.rs,app.rsandvoro-core'sagent.rsthat named thereconciler as a stop caller are updated to name the send path instead.
Verified:
cargo test --workspace— 916 pass, 0 fail;cargo clippy --workspace --all-targets -- -D warningsclean;cargo fmt --all --checkclean. Thereconcile tests that pinned the removed behaviour are replaced by ones pinning
its absence —
a_finalised_dead_session_is_not_stoppedanda_healed_stale_session_is_not_stopped(the row closes, the marker thestopverb would write never appears) and
a_session_at_rest_is_left_registered(all three rest states, with the store's events and the session's ref asserted
unmoved). The send-path tests still pass unchanged:
a_send_releases_a_session_the_agent_still_holds_at_rest,a_send_makes_no_stop_when_the_session_is_not_listed_at_restanda_failed_release_refuses_the_send_and_commits_nothing.