acpmux and cmux-tui report their capabilities offline; bundles record them

Merged
TE
15d ago
+598-32

Reviewed SHIP at 9c88df149e (after the lander's base merge). CI at that head: the Debug compile and the PR's own suites pass. The remaining reds are base findings: ClassicUpgradeSimulationTests ordering and the perf gate's relaunch pane_snapshots 4.0 > 1 both fail the same way on the unrelated chat-reconnect PR (run 39693319330). The (same-tree) Debug-compile status is left over from the superseded run 39683743843.

Part (a) of the daemon-update work agreed with web-ota (#22777): a daemon build states what it serves, so the app and OTA can check abi/protocol before handing off to a new daemon, without starting it.

What changes

  • acpmux capabilities [--json] and cmux-tui __daemon-capabilities [--json] print the capability ids of this build. No daemon runs. The cmux-tui mode is private and not in help, because cmux capabilities stays the classic verb that asks the app (system.capabilities). A test holds that.
  • bundle-cmux-tui.sh insists on the file only for a build of this checkout's own tree. A pull request on a fallback tree (an older published tree via CMUX_TUI_TREE_KEY) gets a warning, so unrelated PRs stay green. The condition matches the workflow's in-tree acpmux step. The local-client install path writes the file too, and the script is on the release surface.
  • acpmux has one source for the list, the CAPABILITIES const in capabilities.rs. Each id names the methods and notifications the agent pane relies on. A test fails when a covered name leaves the protocol registry.
    • The same list is in _acpmux/status (capabilities) and in the initialize reply (_meta.acpmux.capabilities). A test checks that all three agree.
    • The ids are acpmux-v1 (the base a chat needs) plus queue-edit-v1, permission-groups-v1, session-handoff-v1, processes-v1, harness-health-v1, start-mode-v1, folder-trust-v1, agent-pairs-v1, subagent-stop-v1 and session-offers-v1.
  • cmux-tui prints the ids identify always serves, which is static_capabilities(), the part of identify_capabilities split out. Ids a daemon adds only at runtime (cloud, WebSocket listen, the reaper) are left out, so the list never claims more than a bundled daemon serves. identify itself does not change.
  • Bundles write Contents/Resources/bin/daemon-capabilities.json ({"cmuxTui": [...], "acpmux": [...]}) by running the bundled binaries.
    • Same-tree bundles, from bundle-cmux-tui.sh, fail without the file.
    • A pinned, cached or published-tree binary that predates the command leaves no file and logs a warning. This covers install-cmux-tui-client.sh, and write-cmux-tui-version.sh for nightly and release, since nightly can ship an older published tree.

Tests

These ran on huge-blue:

  • cargo test -p acpmux --lib capabilities: 3 passed.
  • cargo test -p cmux-tui-core --lib static_capabilit: 1 passed.
  • cargo test -p cmux-tui --lib capabilities_prints_the_static_identify_list: 1 passed.
  • The new scripts/cmux-next/tests/write-daemon-capabilities.test.sh passed. It is registered in the checks job's Script tests. The other bundle and install script tests also passed.
  • A debug cmux-tui run through its cmux-tui and acpmux symlinks wrote the file with --require: 198 cmux-tui ids and 11 acpmux ids.

Observed / Not run

  • Clippy with -D warnings stops on four lints in files this PR doesn't touch. With those allowed, it is clean on acpmux, cmux-tui-core and cmux-tui.
  • No Swift reads the file yet. Part (b), the app-side check, comes after #22777.

Changelog

none

Agent session: cosmic-gray

🤖 Generated with Claude Code