Skip to content

web-ui: queue a mid-turn message by default; steer only on request - #429

Closed
ReganBell wants to merge 1 commit into
mainfrom
upstream-1694
Closed

web-ui: queue a mid-turn message by default; steer only on request#429
ReganBell wants to merge 1 commit into
mainfrom
upstream-1694

Conversation

@ReganBell

@ReganBell ReganBell commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Pressing Enter while a turn was running always steered — it redirected the live turn, which is destructive and was never explicitly asked for. Mid-turn sends now queue by default, with steering available as an explicit action. The queue is the core's durable one, not the browser's: core already parks a second web turn pending behind the running one, so the client's parallel localStorage queue (which could double-send from two tabs or lose a message when the tab died) is deleted and the core queue is rendered instead. RunStore gains inFlightForThread (every non-terminal run for a thread, oldest first — the tail is the queue) and withdraw (one guarded UPDATE so cancelling a queued turn either beats the worker's claim or reports it started, never both). Steering withdraws the queued run first, then signals, so a message is folded into the live turn or runs as its own — never both. Because the queue is durable, closing the tab no longer drops a message and a second tab sees the same queue.

Deployment notes

Release note: first boot rewrites the runs table to add seq (brief lock); mid-turn send now
queues by default
Schema: ALTER TABLE runs ADD COLUMN IF NOT EXISTS seq BIGSERIAL at boot. A BIGSERIAL
column has a volatile default (nextval), so Postgres does a full table rewrite under ACCESS
EXCLUSIVE lock — on a deployment with a large runs table this is a slow boot migration that
blocks run claiming; release notes should mention possible pause on first boot.
Blue-green: old instances insert runs without touching seq (default fills it); the claim query's
added 'seq ASC' tiebreak is compatible. Rollback safe — old code ignores the column.
Behavior flip: mid-turn Enter in the web UI now queues instead of steering; upstream users'
muscle memory changes (Steer becomes an explicit control). Deliberate fix, but zero opt-in.
Client-side localStorage queue deleted: any message sitting in a browser's local queue at
upgrade time is not migrated (edge case, tab-lifetime data).

Pressing Enter while a turn was running always steered — it redirected the live turn, which is destructive and was never explicitly asked for. Mid-turn sends now queue by default, with steering available as an explicit action. The queue is the core's durable one, not the browser's: core already parks a second web turn pending behind the running one, so the client's parallel localStorage queue (which could double-send from two tabs or lose a message when the tab died) is deleted and the core queue is rendered instead. RunStore gains inFlightForThread (every non-terminal run for a thread, oldest first — the tail is the queue) and withdraw (one guarded UPDATE so cancelling a queued turn either beats the worker's claim or reports it started, never both). Steering withdraws the queued run first, then signals, so a message is folded into the live turn or runs as its own — never both. Because the queue is durable, closing the tab no longer drops a message and a second tab sees the same queue. ⚠ BEFORE SENDING Fork PR body embeds an internal review-guide URL — rewrite the body, don't copy.
@ReganBell ReganBell closed this Aug 13, 2026
@ReganBell
ReganBell deleted the upstream-1694 branch August 13, 2026 20:30
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.

2 participants