Skip to content

Remove the reconciler's background session stops (rest-stop and stop-on-finalise) - #187

Merged
MJohnson459 merged 1 commit into
mainfrom
remove-reconciler-stops
Aug 20, 2026
Merged

Remove the reconciler's background session stops (rest-stop and stop-on-finalise)#187
MJohnson459 merged 1 commit into
mainfrom
remove-reconciler-stops

Conversation

@MJohnson459

Copy link
Copy Markdown
Contributor

Reconciliation ran two background stops: the rest-stop released any session on a
needs-input/review/waiting task whose listing entry read done, and
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. Both call sites go, along with
rest_stop, stop_finalised and the now-unused imports. Every stop Voro makes
now hangs off something the operator just did: a closing verdict (Accept,
Abort, Abandon, via stop_closed_session in cli.rs/app.rs) or the send
that 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 gone
rather 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
(sessions listings, logs cap 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 stop verb has always had — and
the 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.rs and voro-core's agent.rs that named the
reconciler 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 warnings clean; cargo fmt --all --check clean. The
reconcile tests that pinned the removed behaviour are replaced by ones pinning
its absence — a_finalised_dead_session_is_not_stopped and
a_healed_stale_session_is_not_stopped (the row closes, the marker the stop
verb 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_rest and
a_failed_release_refuses_the_send_and_commits_nothing.

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
MJohnson459 merged commit 7b1f897 into main Aug 20, 2026
7 checks passed
@MJohnson459
MJohnson459 deleted the remove-reconciler-stops branch August 20, 2026 21:39
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.
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.

1 participant