feat(tui): detach running turns into background - #68375
Conversation
|
Thanks for the detailed detachment design and race coverage. The feature remains needed: current Ink still renders bare Problems
Suggested changes
This is an automated hermes-sweeper review. |
Keep the exact source turn running while Ink activates a fresh live session. Retain terminal results, proxy interactive requests across local and compute-host execution, and harden lifecycle cleanup and profile-scoped session leases.
Wait for compute-host successor turns before terminal settlement, guard prompt overlays against late response acknowledgements, and claim active-session leases in the owning profile registry.
Guard Ctrl-C prompt dismissal against stale overlays, preserve cross-kind prompt status across late acknowledgements, and keep remote-profile branch DB, agent, session, and lease ownership aligned.
Raise a request-owned barrier at the final quiescent snapshot so notification pollers and overlapping parent turns cannot claim the child session until turn.end is on the wire.
Keep the remote HERMES_HOME active through session initialization and fallback construction, pass profile_home before slash-worker setup, and use the profile SessionDB consistently.
Wait through the request-owned terminal barrier instead of dropping an already accepted successor, block idle-gated controls from invalidating the terminal snapshot, and retain the barrier through replacement error serialization.
Serialize compute-host turn dispatch, busy interrupts, and session.interrupt through a per-session dispatch lock bound to per-host wire request IDs, so a delayed or duplicated interrupt/terminal frame can never stop or settle a successor turn. Reserve compute-host turn admissions at wire order, gate idle-only controls against in-flight admissions, and serialize terminal settlement with successor handoff. Count in-flight provider interrupts (_interrupt_call_count) so an explicit blocking Stop and a busy-input interrupt both defer the next prompt until the provider call returns, then drain the queued prompt exactly once. Clear stale turn cancellation state (_turn_cancel_requested, turn_settled) atomically at every fresh-work claim: the live notification poller, the poller's shutdown drain, and the post-turn notification drain. Previously the post-turn drain could claim a completion event with running=True while a Stop flag from the finished turn was still set, so the nested prompt dispatch dropped the event as cancelled-before-start after message.start was emitted - losing the notification and leaving message.start without a terminal message.complete. Add deterministic regression tests for each interleaving, including Stop-during-turn followed by a post-turn drain claim.
20d083c to
fc80421
Compare
|
@saphira Thanks — good catch. I rebased this onto current main and changed detach admission to reserve capacity atomically before any replacement/task mutation. Idle create/resume/replacement sessions now stay lease-free until actual work begins, with profile-local, serialized admission and rollback-safe cleanup across prompt, compute-host, notification, and detach paths. I also added race and failure-path coverage (including concurrent last-slot detach, registry corruption, release retries, compute-host handoff/close, and notification/Kanban rollback). The focused gateway/lease suites are green locally (691 passed, 1 skipped). I synced the branch again with the latest main; the PR is now conflict-free. |
Summary
/backgroundand/detachin the Ink TUI detach the exact in-flight foreground turn and activate a fresh live sessionAIAgent, task, history, tool state, prompt cache, and durable transcript authoritative—no cancellation, replay, or duplicated side effectsPrompted
/background <prompt>,/bg <prompt>, and/btw <prompt>keep their existing isolated-agent behavior. Bare/bgand/btwkeep their previous usage behavior.UX
While a normal TUI turn is running:
or:
opens a fresh live chat immediately while the exact original turn continues in its source session. Its terminal result is reported in the fresh chat, and the source transcript remains resumable.
If
max_concurrent_sessionshas no free slot, detach fails cleanly and leaves the original foreground turn unchanged.Implementation notes
turn.endor replacementturn.errorserialization, defers pollers/idle-gated controls, and makes an already accepted successor wait through the terminal handoff instead of being dropped._init_session, slash-worker setup, and minimal fallback construction share the remote profile'sHERMES_HOMEandSessionDBfrom the start.session.interruptare serialized through a per-session dispatch lock and bound to per-host wire request IDs, so a delayed interrupt or a late/duplicated terminal frame can never stop or settle a successor turn._interrupt_call_count), so an explicit blocking Stop and a busy-input interrupt both defer the next prompt until the provider call returns, then drain the queued prompt exactly once.running=Truefor a completion notification — the live poller, the poller's shutdown drain, and the post-turn drain — atomically clears stale_turn_cancel_requested/turn_settledstate, so a Stop from a finished turn cannot cancel the notification turn aftermessage.startwas emitted (which lost the event and leftmessage.startwithout a terminalmessage.complete).Test plan
scripts/run_tests.sh tests/test_tui_gateway_server.py tests/tui_gateway/test_compute_host_phase1.py -- -q— 466 passed, 0 failedscripts/run_tests.sh tests/tui_gateway/ tests/test_tui_gateway_server.py— 848 passed, 0 failed (37 files)test_post_turn_drain_clears_stale_stop_before_notification_turn(verified red without the fix, green with it)env -u NODE_ENV) — 1,237 passed, 4 skipped; Ink typecheckenv -u NODE_ENV) — clean; Desktop Vitest failures are pre-existing on the base commit (identical 106 failures with and without this diff, unrelated store/theme suites)py_compilegit diff --check