acpmux: one typed protocol registry; generated web types and drift checks (hq#2025, no bead)
Summary
First step of a typed acpmux protocol (plan: manaflow-ai/cmuxterm-hq#2025; T3 Code's packages/contracts is the model). Rust is the source of truth, and the web gets generated types plus a typed request, with drift checks on both sides.
- Registry (
cmux-tui/crates/acpmux/src/protocol/).- Names all 121 methods and notifications acpmux serves or sends (ACP,
_acpmux/*,catalog.*, chats, transfer), with their kind. - Typed so far:
_acpmux/sessions,_acpmux/permission_respond,_acpmux/permission_groups,_acpmux/permission_group_respond,_acpmux/permission_chat_revoke, and the_acpmux/session_changedand_acpmux/permission_pendingnotifications. - Every other method is declared as any JSON until it is typed.
- Names all 121 methods and notifications acpmux serves or sends (ACP,
- The daemon builds from the types.
Hub::session_summarybuildsSessionSummary, and permission groups buildPermissionGroup.- Reviewed for wire equivalence against the old
json!output; no key, null or number changes. - One fix: a non-UTF-8 cwd is now lossy instead of a
json!panic.
- IR.
spec/acpmux-protocol.jsonholds JSON Schema 2020-12 from schemars. - Web.
webviews/scripts/acpmux-protocol-codegen.tsgeneratesagent-session/acpmux/protocol/generated/: one type per schema, plusAcpmuxRequests,AcpmuxNotificationsandACPMUX_METHODS.protocol/client.tsaddstypedRequestandisNotification.- The permission group client,
permission_respond, and thesession_changedandpermission_pendinghandlers now use them, and the hand-written permission types alias the generated ones.
- Drift checks.
- Rust:
protocol_ir_is_currentfails on a stale IR (bless withACPMUX_PROTOCOL_BLESS=1). - Rust:
protocol_registry_names_every_served_methodfails whenrpc::methodor a server literal names a method the registry lacks. - Web:
bun run checknow ends withacpmux-protocol:check, which fails on stale generated TS.
- Rust:
Follow-ups in hq#2025: type the rest (attach, detach, view, events, watch, then everything else); serve the IR from _acpmux/schema and retire the hand-written docs/acpmux-schema.json; Swift Codable.
Changelog
none
Verification
All of this ran on the private Linux builder, on the merged head (base 93d4ef26af52):
cargo test --locked -p acpmux --lib protocol_: 3 passed.cargo clippy --locked -p acpmux --all-targets -- -D warnings: clean.bun run checkin webviews: green, including the new drift check and the typecheck of 1318 files.bun test src/agent-session/acpmux/protocol: 4 pass.- Two non-browser permission and queue tests pass. The chromium tests were skipped on the builder (no browser installed there), so CI runs them.
The crash ratchet is ok.
No UI change.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Turns acpmux into a typed protocol: one Rust registry names every method and notification, and the web gets generated types plus a typed request from it.
- Typed so far: sessions, permission group, respond, and revoke, plus the
session_changedandpermission_pendingnotifications; the rest are any JSON. - The daemon builds
SessionSummaryandPermissionGroupfrom the types; a non-UTF-8 cwd is now lossy instead of ajson!panic. - The session summary carries the lane fields (
lane,inputSince,lastTurn.detail) and chat tools (tools,toolsMutable); the workspace field was dropped again with the branch's last merge. spec/acpmux-protocol.jsonholds the JSON Schema 2020-12 IR; codegen lives beside the pane protocol codegen, outside the pane sources, so pane-english does not scan its developer-facing errors.- Web views get generated types plus
typedRequestandisNotificationhelpers. - Drift checks fail on a stale IR or generated web types, and when the dispatcher serves a method the registry lacks (bless with
ACPMUX_PROTOCOL_BLESS=1); they caughtoffer_session,offer_respond,prompt_withdraw, the tools, stats, bookmark, and process methods, now registered as untyped requests. - Follow-ups: type the rest of the methods, serve the IR from
_acpmux/schema, add Swift Codable.
<pull_request_end>