Repository navigation
fix(webviews): relay local daemon peer state events - #26885
teamleaderleo wants to merge 6 commits into
Conversation
On base 1f723c6, bun test src/agent-session/acpmux/peerStateEvents.test.ts runs 7 tests: 3 fail and 4 pass. The client never reads peers and ignores the local state feed. Nonlocal and feature-absent fallback cases pass. Native validation is held by #26809. Agent-Session: https://cmux.com/deeplink/agent?id=aid-93c3a66aa0c6bbfa650c
Gate peer events on the advertised feature and local/app origin. Read once after watch at initialize/reconnect, retain exact daemon state, clear nullable metadata, deduplicate lag replay, and reject superseded sockets/reads. Add a zero-parameter pane snapshot relay filtered to name, state, lastSeen and error. Preserve picker presentation and policies. Linux web validation: 14 focused tests / 62 assertions pass; bun --bun run check passes including formatting, lint, typecheck (2933 files), and protocol checks. The focused regression was red before repair (3 failed / 4 passed). Native relay tests were added but native build/test/parse and CI dispatch remain held by #26809/HQ4779. No real-machine capture is claimed. Agent-Session: https://cmux.com/deeplink/agent?id=aid-93c3a66aa0c6bbfa650c
The replacement socket must initialize its own local/app origin and peerStateEvents feature before receiving peer notes; invalidate prior read tokens at open start. Focused Linux web tests: 15 pass, 66 assertions. Full bun --bun run check passes. Native verification and CI remain held by #26809/HQ4779. Agent-Session: https://cmux.com/deeplink/agent?id=aid-93c3a66aa0c6bbfa650c
Default changesThis pull request changes 1 default at
Needs a review. It passes with an independent review receipt on this commit: a comment or review whose first line is Regenerate the snapshot with |
|
Bead |
|
Found 37 test failures on Blacksmith runners: Failures
...and 27 more test failures. View all on Blacksmith: run 40995096762, run 40995096677
|
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Unclear: CI failed on
Failures:
Matched log linesNot re-run automatically: Written by red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: Stale: these images are of Gallery before/after for
States
Pick other states with a |
|
Owned by an agent session · session |
…r-events-source-1028
|
Review (codex-review-box/gpt-6-astra high, lane-place): BLOCK at 9ba799f BLOCK
|
The daemon drops peer_state_changed notices when a client lags and says so with _acpmux/lagged; resyncing only the selected chat left a machine that went down meanwhile shown as connected. Review P2 on #26885. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126
|
Review (codex gpt-6-astra high, review-router): BLOCK at fbb1240
|
|
This PR's lane is gone, so its work continues in #27971: these commits with their authorship, rebased onto current |
|
Superseded by #27971, which drain-acpmux carried with the review fixes (comment at 04:25Z). |
* test(webviews): reproduce missing local peer state events On base 1f723c6, bun test src/agent-session/acpmux/peerStateEvents.test.ts runs 7 tests: 3 fail and 4 pass. The client never reads peers and ignores the local state feed. Nonlocal and feature-absent fallback cases pass. Native validation is held by #26809. Agent-Session: https://cmux.com/deeplink/agent?id=aid-93c3a66aa0c6bbfa650c * fix(webviews): consume local peer state snapshots and events Gate peer events on the advertised feature and local/app origin. Read once after watch at initialize/reconnect, retain exact daemon state, clear nullable metadata, deduplicate lag replay, and reject superseded sockets/reads. Add a zero-parameter pane snapshot relay filtered to name, state, lastSeen and error. Preserve picker presentation and policies. Linux web validation: 14 focused tests / 62 assertions pass; bun --bun run check passes including formatting, lint, typecheck (2933 files), and protocol checks. The focused regression was red before repair (3 failed / 4 passed). Native relay tests were added but native build/test/parse and CI dispatch remain held by #26809/HQ4779. No real-machine capture is claimed. Agent-Session: https://cmux.com/deeplink/agent?id=aid-93c3a66aa0c6bbfa650c * fix(webviews): reset peer event capability before reconnect The replacement socket must initialize its own local/app origin and peerStateEvents feature before receiving peer notes; invalidate prior read tokens at open start. Focused Linux web tests: 15 pass, 66 assertions. Full bun --bun run check passes. Native verification and CI remain held by #26809/HQ4779. Agent-Session: https://cmux.com/deeplink/agent?id=aid-93c3a66aa0c6bbfa650c * fix(webviews): a lag notice reads the peer snapshot again The daemon drops peer_state_changed notices when a client lags and says so with _acpmux/lagged; resyncing only the selected chat left a machine that went down meanwhile shown as connected. Review P2 on #26885. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * test(webviews): reproduce a restarting peer dropped from the peer snapshot _acpmux/peers says `restarting` (peer_link.rs PeerState::as_str) while a peer's daemon restarts. The adapter drops that row, so the authoritative snapshot clears the peer's state and the picker reads it as ready. Red: bun test src/agent-session/acpmux/peerStateReducer.test.ts src/agent-session/acpmux/peerStateEvents.test.ts: 16 pass, 2 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): keep a restarting peer in the peer snapshot _acpmux/peers names every PeerState acpmux has, `restarting` included (peer_link.rs as_str), while peer_state_changed maps it to reconnecting. The adapter now accepts it, so a restarting peer keeps its state and reads not connected instead of falling back to ready in the picker. Green: bun test src/agent-session/acpmux/peerStateReducer.test.ts src/agent-session/acpmux/peerStateEvents.test.ts: 18 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(webviews): reproduce a listed peer the peer snapshot omits reading as ready A peer that _acpmux/status lists but the authoritative _acpmux/peers snapshot omits (removed between the two reads, or an invalid row) loses its state and `connected`, so environmentReady offers it as ready. Red: bun test src/agent-session/acpmux/peerStateEvents.test.ts: 10 pass, 1 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): a listed peer the peer snapshot omits reads not connected An authoritative _acpmux/peers snapshot replaced the peer maps with its own rows, so a peer the status read still lists lost its state and `connected` and the picker offered it as ready. Such a peer now reads not connected until a note or the next read says otherwise. Green: bun test src/agent-session/acpmux/peerStateEvents.test.ts: 11 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(webviews): reproduce an omitted peer losing its last-seen status When the authoritative peer snapshot omits a peer the status read lists, its peerStatus becomes only { connected: false }, so the offline banner (chatUnavailable) loses lastSeen and attempts. Red: bun test src/agent-session/acpmux/peerStateEvents.test.ts: 10 pass, 1 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): an omitted peer keeps its last-seen status The authoritative-snapshot branch replaced an omitted peer's status with { connected: false } alone. It now keeps lastSeen, attempts and error from the last read and drops only the stale state, so the offline banner still says when the machine was last seen. Green: bun test src/agent-session/acpmux/peerStateEvents.test.ts: 11 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(agent-pane-policy): reproduce _acpmux/peers missing from the Rust relay policy The web pane sends _acpmux/peers (zero parameters) and the macOS host admits it, but policy.json does not list it, so a Rust host refuses the request and its reply is not filtered. The cases also keep a numeric lastSeen, as the Swift .number shape does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(webviews): reproduce a stale restarting state and the snapshot on the first frame - A status read after a snapshot said `restarting` keeps it: a failed restart goes restarting -> reconnecting, both `reconnecting` on the wire, so no note says so and readPeers re-applies the snapshot. - connect awaits _acpmux/peers before the first frame, a second round trip after the one #27755 keeps it to (a held snapshot holds connect). - chatUnavailable calls a restarting peer offline instead of connecting. The initial snapshot is settled in the fixture, and the in-flight status test now races a real in-flight read. Red: bun test src/agent-session/acpmux/peerStateEvents.test.ts: 11 pass, 2 fail; bun test test/chat-unavailable.test.ts: 1 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(agent-pane-policy): admit _acpmux/peers in the Rust relay policy The web pane sends _acpmux/peers and the macOS host admits it with a zero-parameter rule and a name/state/lastSeen/error reply filter. policy.json now does the same, so a Rust host no longer refuses the request. ReplyShape gains Number (a finite number, never a boolean), mirroring Swift's .number, so lastSeen survives the filter. Red at a4b6b6e (cmux-ci, cargo test -p cmux-agent-pane-policy): parity replies FAILED, 15 passed, 1 failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): a status read clears a stale restarting state; the snapshot leaves the first frame - A _acpmux/status read now drops every peer event entry no note has updated since the read started (PeerStateEvents.statusRead), so a failed restart that the daemon reports only as a state (no note) reads reconnecting instead of restarting forever. - connect starts the _acpmux/peers snapshot once the list's watch answered and draws it when it lands, instead of awaiting it before the first frame (#27755's one round trip). - chatUnavailable counts a restarting peer as still connecting. Green: bun test peerStateEvents, peerStateReducer, environments and test/chat-unavailable.test.ts: 28 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(agent-pane-policy): _acpmux/peers passes; the escaped-name refusal samples another unlisted method frames.json sampled _acpmux/peers as a daemon method the pane never sends. The pane now sends it (policy.json admits it), so those two refusal cases move to _acpmux/peer_remove, which stays unlisted, and a pass case covers _acpmux/peers like _acpmux/status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(webviews): reproduce status and snapshot reads landing out of order The status-read fence and the snapshot fence are separate, so: - a snapshot that started before a status read, and landed after it, brings back the restarting state the status read cleared; - a status read that started before a snapshot, and landed after it, deletes the newer snapshot's state. Red: bun test src/agent-session/acpmux/peerStateEvents.test.ts: 13 pass, 2 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): order status and snapshot reads on one clock PeerStateEvents now ticks one clock for notes and for the start of every read (statusStarted, readStarted). A snapshot that landed after a status read started later is dropped, and a status read drops only entries written before it started, so an older read of either kind can neither bring back a cleared restarting state nor erase a newer snapshot. A status read clears the snapshot's authority only when it is newer. The reducer tests take the read's tick in place of a separate revision. Green: bun test peerStateEvents, peerStateReducer, environments and test/chat-unavailable.test.ts: 30 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): a replaced socket's replies still land; only its peer notes drop The stale-socket guard dropped every message from a socket the client had replaced, so a request asked on it never settled: the export that watches for a socket swap waited forever instead of rejecting (conversation/exportClient.test.ts timed out on this branch and passes on base). Only _acpmux/peer_state_changed from a replaced socket (or after close) is dropped now; everything else is received as on base. Red: bun test ./src/agent-session/acpmux/conversation/exportClient.test.ts times out at a01e4e5 (CI react-apps-check shard 1: TIMEOUT twice, passes replayed on base ad6de25). Green: 3 pass; peerStateEvents 15, reducer 8, chat-unavailable 7 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * test(webviews): reproduce an older status read overwriting a newer one readPeers writes each _acpmux/status reply into peers, peerConnected, peerStates and peerStatus before the clock fence runs, so of two refreshPeers calls the one asked first and answered last wins. The fixture's status read now answers with what the daemon knew when the read reached it. Red: bun test ./src/agent-session/acpmux/peerStateEvents.test.ts: 15 pass, 1 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 * fix(webviews): an older status read that lands late is dropped whole statusRead now says whether the read is newer than every status read that already landed (and than this connection); readPeers drops one that is not before it writes peers, peerConnected, peerStates or peerStatus, so two refreshPeers calls answered out of order keep the newer answer. Green: peerStateEvents 16, peerStateReducer 8, chat-unavailable 7, exportClient 3, chatOpenTrips 3, agent-pane-peer-copy 55, agent-pane-cached-chat-open 10 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c35ebd1681cf79649972 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Local daemon peer transitions currently do not reach the web session's peer state. This narrow source PR intentionally extracts and replaces the stale peer-state carrier in our existing remote-location strip draft #26796 (
b749e778f5bb2203333556be9a53ff1437095dc1), which also carries unlanded picker prerequisites. #26796 remains draft and must rebase onto this foundation and remove its superseded carrier hunks before review. This PR supplies the carrier foundation; remote-strip UI completion and real-machine proof remain outstanding.The owning overlap index covered 482 open PRs. The feature overlap is our own #26796; other overlaps are shared transport or native allowlist files, with no other peer-state adapter identified. This change leaves picker presentation, optional-project behavior, recent folders, defaults, colors, and glass untouched.
The adapter follows the merged daemon contracts from #26756 (honest initialize handshake), #26823 (peer-state events), and #26860 (origin privacy). It enables only when initialize advertises
peerStateEventsand reports the local origin used by LOCAL/APP connections. Peer, remote, missing, and unknown origins cannot request or consume peer topology._acpmux/peers {}once after initialization and on each reconnect, then apply_acpmux/peer_state_changedfrom that same connection. No polling.lastSeenanderrorvalues, and reset capability before a reconnect initializes._acpmux/peersrelay, accepting no parameters and filtering replies toname,state,lastSeen, anderror. Existing incoming notification forwarding carries the events. No daemon or session/auth fallback changes.Validation on Linux at
085467e71042c174e90a7b7a2d748e04e502be08over1f723c64fe2a70709ac21b88f10f4bc8bfdf0823: meaningful tests-first red was 3 failures / 4 passes; the repaired integration and reducer suites pass 15 tests / 66 assertions. Fullbun --bun run checkpasses. The supported scoped web prepush helper passes under Bun, and the permitted source-scanner prepush layers report no new violations across all eight changed files. Native policy tests are included but unrun.The #26809 hold is lifted. No real remote-machine transition, spinner/green/red, no-project Send, light/dark, or gallery capture has been verified. Root owns fresh independent exact-head review, required-check reconciliation, and the final landing loop. Our existing #26796 remains unchanged.
Agent session: agent session
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Relays local daemon peer state events to the web session's peer state, so peer transitions on the local machine show live instead of only at the last
_acpmux/statusread._acpmux/peersnative relay that filters replies toname,state,lastSeen, anderror._acpmux/peer_state_changednotifications; it never polls.peerStateEventsand the origin is local/app; other origins and older daemons keep the existing snapshot behavior.lastSeenanderroron repeated observations._acpmux/laggednotice, re-reads the snapshot so a peer that went down while the client lagged no longer shows as connected.Written for commit e60b18f. Summary will update on new commits.