Repository navigation
acpmux: the sidebar Priority view's ranking and lane windows with row diffs (A6, PR 1) - #31839
lawrencecchen wants to merge 12 commits into
Conversation
… not moved yet) The Mac app ranks every acpmux lane it mirrors (AgentPriorityRanking.swift) on the main thread at each lane change. This commit adds the acpmux side of the move: the lane model, the person's marks, the window over the lanes (_acpmux/priority_window, row diffs with a revision) and its server task, with the Swift tests of the rule ported as Rust tests (AgentPriorityRankingTests, AgentLanesTests). Red on purpose: Ranking::entries returns the lanes unranked and next_change returns None, so the ported ranking tests fail. The next commit moves the rule.
…om AgentPriorityRanking.swift) Ranking::entries orders the lanes as the app did: needs-you, unseen result, failed or lost, Red CI, working, idle; pinned first in a tier, then the newest change, then the id; a dragged chat at its place; snoozed and archived chats out, idle ones past the horizon out unless pinned or placed. next_change says when a snooze ends or an idle chat ages out.
|
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)
Probably yours: CI failed on
Failures:
Matched log linesNot re-run automatically: Written by red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 18de50c to compare; do not merge until green; see lane-rules Gallery before/after for
States
Pick other states with a |
|
Found 18 test failures on Blacksmith runners: Failures
...and 8 more test failures. View all on Blacksmith
|
… a mark at once An end-to-end test over a served connection: a new chat and its turn reach an open window with no new request, only the rows whose value changed are sent, a pin and a drag change the rows at once, Go to Next Agent Needing Input stops only at a chat that asks, a mark on an unknown chat is refused and an older spec of the window is stale.
…ght, and the daemon owns the marks Review of #31839 (NOT SHIP at d9cb270): - The task woke at nextChangeMs only by chance: open and mark now wake it, so it reads the window's next wake time after its first message. Test: a snooze of 400 ms ends with no other change, in two windows. - A peer link lag (summary null) removed that peer's lanes: it now reads every lane again. A peer's question changes no lane. - A peer's purge wrote the removed row's lane back: a purge now removes the lane, peer or not. - A peer's row never replaces or removes this daemon's lane of the same id; this daemon's lane is read by its exact id, not a prefix. - The marks were the client's, sent again with each spec (two writers): they are now the daemon's, one copy for every window of every connection (hub/priority_marks.rs), kept in $ACPMUX_HOME/priority-marks.json. A spec's importMarks hands over the app's saved copy (its JSONEncoder shape: a snooze's Date as seconds since 2001) only while acpmux has none. - Rows name their machine as the app did: localMachine and peerNames in the spec. - Archive needs a chat the window lists, as the app's did; refreshes skip when no lane changed. - The stamp test uses fixed values; the ownership table names the new owner.
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
…le lane-neutral records arrive (red) Review of #31839 at 790308a, finding 1: a record that changes no lane, drained in the same turn as a marks change, made refresh return before it recomputed the windows, so the mark never showed in another connection's window while the daemon was busy. Four connections write tags back to back while a fifth pins and unpins a chat twenty times; each mark must reach the second window. The snooze test's snooze is 3 s, so a slow runner still sees it before it ends.
…e Priority windows refresh returned before it recomputed the windows when the lane records it was given changed no lane, even when a marks change, an open or the clock had woken it in the same turn: the mark was lost until a later lane change. It now returns early only when lane records alone woke it. Also: the marks module says its file is read once at first use, and that a client sends importMarks with its first open.
|
Review (claude-reviewer): SHIP at 3fef388 Checked by reading only (no cargo or swift on this machine), over three rounds (d9cb270, 790308a, 3fef388):
|
The app refused Archive for a chat no acpmux socket of its own listed (another machine's chat tab) and kept it for this daemon's and the Chief home's (AgentPriorityChats.archive). The window accepted it for any chat it listed. Lead decision on #31839: a move keeps behavior.
… app did A reported lane carries archivable when the client has its owning acpmux's socket (the Chief home's); this daemon's own lanes are always archivable. Another machine's chat tab is not: the app had no acpmux to archive it (AgentPriorityChats.archive).
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (claude-reviewer): SHIP at 127885c I read the code changed since my SHIP at 3fef388 (dcf36ba red test, 127885c fix). I did not compile or run tests on this machine.
|
…ion/agent-activity
|
Review (next-review patch-id; carried): SHIP at 5875cbc The independent SHIP at 127885c carries to this head: the PR's own change ( |
|
Review (next-review patch-id; carried): SHIP at 61d9fab The independent SHIP at 127885c carries to this head: the PR's own change ( |
|
Review (next-review patch-id; carried): SHIP at 9967317 The independent SHIP at 127885c carries to this head: the PR's own change ( |
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (codex gpt-6.1-sol xhigh, next-review): BLOCK at 028f414 BLOCK at 028f414
Rust tests could not run because Cargo is unavailable. Follow-ups:
|
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Summary
The Mac app copies every acpmux lane into
AgentLaneStoreand ranks all of them for the sidebar's Priority view on the main thread (AgentPriorityRanking.swift). It does this at each lane change, and lanes change many times a second while agents work. Layer ownership (plans/cmux-next/layer-ownership.md, rule 1 and L7) says acpmux must own this list and send a client only its visible window as row diffs.This PR is the Rust half (rust-migration A6, PR 1 of 2). It changes acpmux only. The app does not use it yet.
hub/priority.rs: the lane model read from a session summary'slane, and the ranking. The rules are the same as the Swift code: needs-you, then unseen result, then failed or lost, then Red CI, then working, then idle. Inside a tier: pinned first, then the newest change, then the id. A dragged chat stays at its place. Snoozed and archived chats are left out. Idle chats past the 24 h horizon are left out unless pinned or placed. A read or snooze mark holds only for the lane state it was made on. The stamp text is the same as the app's (state@<ms>). Also here: Go to Next Agent Needing Input's order and its wrap-around.hub/priority_marks.rs: the person's marks (pinned, read, snoozed, archived, dragged place, folded). acpmux owns one copy for every window of every connection, kept in$ACPMUX_HOME/priority-marks.json. A client hands the app's saved copy over one time (importMarks, the app's JSONEncoder shape), and acpmux takes it only while it has no marks of its own. So a client sendsimportMarkswith its first open. The ownership table in layer-ownership.md has the new row.hub/priority_window.rs: a window over the lanes with row diffs and a revision, in the_acpmux/chats_windowpattern. It has two kinds:priority: the Priority view. The client sends the ids with failing checks, the ids open in a tab, whether the view is shown, how rows name machines (localMachine,peerNames), and the lanes it reads from other owners (the Chief home's acpmux, other machines' trees, witharchivablewhen the client has the owner's socket). Each message also carriesneedingInput,attentionCountandnextChangeMs.links: the session tree's per-session links and state. A new step of an agent sends nothing.server/priority_windows.rs:_acpmux/priority_window,_acpmux/priority_window_close,_acpmux/priority_markand_acpmux/priority_next, on the local unix socket only.spec/acpmux-protocol.json, the generated web method list) and advertised as capabilitypriority-window-v1.PR 2 (Swift reads the window, deletes
AgentPriorityRanking, the UserDefaults marks store and the whole-store reads) waits for rm-sidebar-mapping and shortcut-latency SL-5, as the lead decided. For PR 2: the archive mark only hides the chat. The app still sends_acpmux/archiveto the owner and unarchives when that fails, as today. The Agent Activity page half of A6 is deferred (A6a: its data owner is cmux-cua, not acpmux).No app FFI change, so there is no pin step.
Known differences from the Swift rule (accepted by the lead)
sessionId,nameorpeerstring in a summary is dropped. Swift kept it.Testing
The Swift tests of the rule (
AgentPriorityRankingTests,AgentLanesTests) are ported ashub/priority_tests.rs, with the same lanes, marks, clock and expected orders. The window, the marks store and the event classification have unit tests (hub/priority_window_tests.rs,hub/priority_marks.rs,server/priority_windows.rs).tests/priority_window.rsruns the windows over served connections with a stand-in agent.All steps run
scripts/ci/cmux-tui-rust-check.shon Linux.b6bb0607cc3priority91a2f7a280372d027bcf0f7d: 13 of 20 priority tests failed, as planned9360dbbb5fepriorityf4a02dc5a747686d29044d84: 40 run, 40 passedd9cb27046d2priority6d239bed93415f76b67c1f20: passed790308af0f0priority12288c440f3e2560d5a42132: passed1f8d5493864a_mark_shows_in_another_windowd991b11b5feedce52a207724: failed as planned. It ran exactly 1 test (1 test run: 0 passed, 1 failed), which timed out attests/priority_window.rs:59: the mark never reached the second windowdcf36ba201earchive_is_refused55045f843324743cf1a261ff: failed as planned athub/priority_window_tests.rs:353(another machine's chat was archived)127885c3ba2priority0fdef5232d4438855d105cd5: passed (done 06:19:56Z)127885c3ba2a_mark_shows16e6b6170da62332ae7c5e9c: cancelled by me at 06:20Z, because the merge of feat-cmux-next (head5875cbc0368) replaced that head (fleet rule 5)5875cbc0368clippy9c018fb38d749bc7567a9175: failed only on a new base red from #31770 (3 errors incmux-tui-core/src/mux/agent_chat_notices.rs, fixed by #31907); nothing in acpmux7b0399ef2bd=5875cbc0368+ #31907'se7ecb66ba00clippyff6fa7fd4d1663977d53947a: passed.cargo clippy --workspace --all-targets -- -D warningslinted acpmux (its build line is in the log) and reported 0 errors, exit 0. Branchrust-migration/scratch-agent-activity-clippyis listed as never-merge; #31907's commit is not in this PR5875cbc0368priority603a0a8027cde404b9cf36ff: passed (49 run, 49 passed; done 06:34:25Z)5875cbc0368priority_windowe8ecda1f98c8abf8e63e4647,4aa19f83460771b28584bf78,7a12b9d5133620e835319759,7b411dd810d3cd01e636f9ce,8eaa1c46e2a5f6a9a0567854: 5 of 5 passed (15 run, 15 passed each). This filter matches test names, not the test binary, so it does not select the two timed integration tests5875cbc0368a_mark_shows(selects the 2 timed tests)ec8a7197cbd5db368496a56c: no verdict, infra (Blacksmith run 41401447028 stopped in a git fetch before cargo ran; no test ran); rerun once as85fab18d74bc2074d69a9be8(--tag infra-rerun, fleet rule 14): PENDING. Run 2caf85298b1866ad8113383f9: 2 tests run, 2 passed. Run 3ced610a222e4b7eab076322d: PENDING. Run 449a6761f911b42acd9eae7f6: PENDING. Run 5ee2a4f283e9b6c4e14bdff37: PENDING. The lead's rule: 5 real passes of the 2 timed testsClippy at
d9cb27046d2(3e456ce82e287751163697e5),790308af0f0(bccb0d8b6cb5073c5bef02d3) and127885c3ba2(983f4338f463c5d38e289818) failed only atcrates/cmux-tui/src/plugin_manager.rs:233(suspicious_open_options). That is a base red, which #31697 on feat-cmux-next fixes. Head5875cbc0368merges feat-cmux-next (with #31697) by a merge commit. This PR's own diff against feat-cmux-next is the same before and after that merge, and the protocol codegen check passes.Observed / Not run
--checkon every changed Rust file,prepush-gate.py(no new violations),scripts/web-lint.sh(passed),acpmux-protocol:codegenregenerated, and the god-file check on the new files (clean).Changelog
none
Proof
No capture: daemon only; no UI reads the window yet.