acpmux: send --class block|question|result|fyi
Leo, 2026-10-29: "What are we gonna do with these 200 fing messages? You never end a fing turn. As soon as it comes in, it fing, like, occupies you for another fing turn." and "you can't you just deal with this? Like ACPmux can't be this stuff. How do swarms work?"
What
First piece of the coordinator inbox. A message now carries its class: what it asks of the session it is sent to. The coordinator inbox mode (follow-up PR) uses the class to decide which messages wake a coordinator (blocks and questions) and which wait for its inbox digest (results and FYIs).
acpmux send --class block|question|result|fyi, andclasson the acpmux MCPsendtool, set_meta.acpmux.class.- The daemon accepts only these four values. Anything else is refused as invalid params, with
data.reason class.value_refused. The MCP tool refuses it before sending. - New
prompt_class.rsholdsPromptClassanddeclared(), the one definition shared with the inbox-digest renderer. - Only another agent's message keeps a class (
digest.rsagent_sender):- with no class it counts as
result; - a lane's report (
lane_reports.rs) and a lane's task result card (tasks.rs) count asresult; - another session's message (
session_messageprovenance) keeps its sender, and so its class, when a paused agent pair releases it (agent_pairs.rs). - the person's own prompt has none, whatever it sends.
- with no class it counts as
- The class is stored on the queued prompt (
PromptRun.class) and written to itsqueuedrecord, so a restart rebuilds it. A record from before this change reads asresultfor an agent's message. - A send that only the mesh relay reaches refuses any class but
result(mesh.no_class): the relay cannot carry it. The class is checked before a peer's prompt is forwarded and when_acpmux/send_queuetakes a send. - A
queue_editupdate makes the prompt the person's, so the class is dropped along withfromAgent. - Queue rows show it as
class:SessionSummary.queue(QueuedPromptSummary) and the_acpmux/composersqueue. Each message inagent_digestprovenance names its class. docs/acpmux-schema.json,spec/acpmux-protocol.jsonand the generated web types are updated.- The spec bless also adds
_acpmux/mesh_control, which base's committed IR was missing.
- The spec bless also adds
Tests
- Red first: commit 97169ec (tests only) fails 3/3 of
hub_integration prompt_class::*(fleet job 66f78bcb3b8a9298f05aec66, after Actions run 40935272800 was cancelled for queueing). - Green at the fix (run 40935684163, then a fmt-only amend):
acpmux --lib: 1912 passed;hub_integration: 546 passed, 2 failed, both base reds (below);- clippy
-D warningsclean.
- Review fixes, red first again:
- round 1: the mesh relay, pre-forward validation, agent-pair holds keeping the class (fbbf5c4; run 40938537656);
- round 2: a released agent-pair message and a task result card lost their sender, so their class. Tests-only commit d8a77c3 fails all 3 new checks on the missing
fromAgent(run 40942026978); the fix 8603302 passes them (run 40942124836:--lib1914 passed,hub_integration548 passed with the same 2 base reds,mesh_relay16 passed, fmt and clippy clean).
- Load flakes seen once in run 40938537656 (
stop::a_cancel_ends...at 229 ms against a 200 ms budget,held_queue::agent_messages_joined_to_a_send_whose_agent_cannot_start_are_not_heldtiming out) pass 5 of 5 alone at both the head and base (run 40939960419). - New tests:
hub_integration/prompt_class.rs: rows, the composers queue,queuedrecords, an edit dropping the class, refusal of other values, and the class surviving a restart;- an
acpmux_mcpsend test; - a CLI parse test and a
PromptId::paramstest; - a lane report queues as
result; agent_pairs::a_released_message_keeps_its_sender_and_its_classandtasks::a_result_card_is_the_lanes_message_and_a_result;- unit tests in
prompt_class.rs.
- Base reds, the same test failing with the same error at base plus the tests-only commit, 3 runs out of 3 (run for source 7fd0a4a9):
auto_resume::retry::stop_before_a_retrys_turn_starts_prevents_it: auto_resume_retry.rs:222, "the turn was stopped before this prompt reached the agent";transcript_events::orchestration_fields_reach_subagent_events_and_session_summary: transcript_events.rs:721,Null != 1234.
No capture: the only webviews change is the generated protocol types (a new optional class field on queue rows); no component reads it, so nothing on screen changes.
Risk
Low. The change is additive: one new optional wire field, and one new field in queue rows that defaults to null for a peer on an older acpmux. Delivery is unchanged: nothing reads the class to steer, queue or start a turn yet.
The one new refusal: a session/prompt whose _meta.acpmux.class is not one of the four values. No client sent that field before this change.
Agent session: agent session
š¤ Generated with Claude Code