Skip to content

Quick-message a task's session: a sends headlessly, A attaches - #120

Merged
MJohnson459 merged 1 commit into
mainfrom
quick-message-session
Aug 5, 2026
Merged

Quick-message a task's session: a sends headlessly, A attaches#120
MJohnson459 merged 1 commit into
mainfrom
quick-message-session

Conversation

@MJohnson459

Copy link
Copy Markdown
Contributor

Quick-message a task's session without leaving the cockpit

Saying one sentence to an agent cost a full attach round-trip: suspend the
TUI, type, navigate back, ctrl-C. That price is paid on the cheapest
interaction there is — answering a needs-input question, adding a line of
review feedback — so it was routinely not paid at all.

a now collects one line in the same inline input the refine note uses and
sends it into the task's recorded session headlessly, fire-and-forget; the
TUI never suspends. The interactive jump-in moves to A, the same
lowercase-quick, uppercase-interactive pairing as r/R.

Agents declare the capability with a new optional message verb carrying
both {session} and {prompt_file}, built in for claude as its resume
plus -p. The near-duplication between those two verb bodies is deliberate
and not factored: a verb is an opaque per-agent contract, which is exactly
what lets codex define no message and degrade one verb at a time rather
than losing its jump-in with it.

The key applies to the three states whose session is open and between turns
needs-input, review, waiting — and refuses the rest: running and
refining are mid-turn with no injection channel, and stalled has a dead
session, where a headless resume would restart the work with no tracked pid
and no session row, invisible to the reconciler. A liveness probe refuses a
session still running for the same reason. On a review or waiting task the
message is the rejection: RejectWork is applied before the send, so the
feedback is in the body and the event log first and a refused transition
sends nothing. There is no separate "just asking" mode — a second channel
that spoke to the agent without recording it would put the task's body and
its session out of step. A needs-input task transitions not at all; the
answer belongs to the transcript and the agent's own voro resume moves it.

The send borrows the refine round's detached-spawn plumbing (stamped prompt
and log in the runtime dir, launch-log breadcrumb, detached reaper), factored
out of spawn_expansion as spawn_logged, but records no session row and
tracks no pid: it joins a conversation Voro already knows about.

One knock-on: the new a/A slot would have pushed the cockpit key line to
eleven slots on a review row, past the ten §9 allows. d/D dispatch is now
advertised only where dispatch can act — ready or stalled — instead of on
any selection, which both restores the budget and stops the line offering a
verb whose only answer is the state it refuses.

DESIGN.md §6/§8/§9 and docs/agent-integration.md updated in the same change.

Verified: cargo test --workspace and cargo clippy --workspace --all-targets -- -D warnings pass. New tests cover the verb's placeholder
validation and its refusal of the launch placeholders, override_missing_verbs
reporting a dropped message, one-pass rendering of the two bindings, the
state gate, and the key itself driven against stub agents through a real
spawn: a review task's message rejects with feedback and lands in the launch
log, a needs-input task's sends with no transition, a live session is
refused, and a missing verb, a missing ref, and a missing session each report.
The TUI could not be driven under tmux here — this session's write guard
refuses the VORO_DB/XDG_CONFIG_HOME redirection the scratch harness needs
— so the key-line and key-map changes are covered by render tests instead.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01JWjypXGmxq2NXuChFfhRdi

Saying one sentence to an agent cost a full attach round-trip: suspend the
TUI, type, navigate back, ctrl-C. That price is paid on the cheapest
interaction there is — answering a `needs-input` question, adding a line of
review feedback — so it was routinely not paid at all.

`a` now collects one line in the same inline input the refine note uses and
sends it into the task's recorded session headlessly, fire-and-forget; the
TUI never suspends. The interactive jump-in moves to `A`, the same
lowercase-quick, uppercase-interactive pairing as `r`/`R`.

Agents declare the capability with a new optional `message` verb carrying
both `{session}` and `{prompt_file}`, built in for `claude` as its `resume`
plus `-p`. The near-duplication between those two verb bodies is deliberate
and not factored: a verb is an opaque per-agent contract, which is exactly
what lets `codex` define no `message` and degrade one verb at a time rather
than losing its jump-in with it.

The key applies to the three states whose session is open and between turns
— `needs-input`, `review`, `waiting` — and refuses the rest: `running` and
`refining` are mid-turn with no injection channel, and `stalled` has a dead
session, where a headless resume would restart the work with no tracked pid
and no session row, invisible to the reconciler. A liveness probe refuses a
session still running for the same reason. On a review or waiting task the
message *is* the rejection: `RejectWork` is applied before the send, so the
feedback is in the body and the event log first and a refused transition
sends nothing. There is no separate "just asking" mode — a second channel
that spoke to the agent without recording it would put the task's body and
its session out of step. A `needs-input` task transitions not at all; the
answer belongs to the transcript and the agent's own `voro resume` moves it.

The send borrows the refine round's detached-spawn plumbing (stamped prompt
and log in the runtime dir, launch-log breadcrumb, detached reaper), factored
out of `spawn_expansion` as `spawn_logged`, but records no session row and
tracks no pid: it joins a conversation Voro already knows about.

One knock-on: the new `a/A` slot would have pushed the cockpit key line to
eleven slots on a review row, past the ten §9 allows. `d/D dispatch` is now
advertised only where dispatch can act — `ready` or `stalled` — instead of on
any selection, which both restores the budget and stops the line offering a
verb whose only answer is the state it refuses.

DESIGN.md §6/§8/§9 and docs/agent-integration.md updated in the same change.

Verified: `cargo test --workspace` and `cargo clippy --workspace
--all-targets -- -D warnings` pass. New tests cover the verb's placeholder
validation and its refusal of the launch placeholders, `override_missing_verbs`
reporting a dropped `message`, one-pass rendering of the two bindings, the
state gate, and the key itself driven against stub agents through a real
spawn: a review task's message rejects with feedback and lands in the launch
log, a `needs-input` task's sends with no transition, a live session is
refused, and a missing verb, a missing ref, and a missing session each report.
The TUI could not be driven under tmux here — this session's write guard
refuses the `VORO_DB`/`XDG_CONFIG_HOME` redirection the scratch harness needs
— so the key-line and key-map changes are covered by render tests instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JWjypXGmxq2NXuChFfhRdi
@MJohnson459
MJohnson459 force-pushed the quick-message-session branch from e68b25f to b13b7b0 Compare August 5, 2026 11:48
@MJohnson459
MJohnson459 merged commit d6d9ae5 into main Aug 5, 2026
6 checks passed
@MJohnson459
MJohnson459 deleted the quick-message-session branch August 5, 2026 11:55
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