Repository navigation
arch: inject the peer approver, Cloud machines and remote sidebar instead of app-wide statics - #28268
Conversation
…tead of app-wide statics AcpmuxMacApprover.shared, AgentPanePeerApprovals.enroll/daemons and AgentPaneCloudMachines.shared become instances made once at the composition root: AppDelegate makes the app's AgentPanePeerApprover (key, Enroll this Mac, the daemons its key went to) and hands it to AppServices, which gives it to AgentTabStore; the store hands it to every AcpmuxHost it makes (its own, the Chief home's, ChiefHomeDirectory's) and to every pane's transport in makeView, beside its own AgentPaneCloudMachines. RemoteMachinesSidebar.shared goes: nothing binds it (65c9441), so its one caller, activateClientItem, never matched a row. No behavior change. Tests make their own instances.
|
Fleet compile-check of head 75d6838: job |
|
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)
Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by web and size checks: green Shipped in:
|
…cName Fleet compile a36a982b6a263d490f09cf9d at 75d6838 failed: AgentPanePeerApprovals.swift:56:26: error: cannot find 'MacName' in scope. The registration moved here from AcpmuxMacApprover.swift, which imports CmuxNextCompat; this file did not.
|
Found 1 test failure on Blacksmith runners: Failure
|
AgentTabs+Wiring.swift: kept feat's machine-link wiring; the Cloud machines stay the store's own instance (tabs.cloudMachines.wire). ChatsFeed+Start.swift (6ba8e71, #26786): removed the new caller of the deleted RemoteMachinesSidebar.shared. Nothing binds that sidebar (65c9441), and peerStateChanged starts with `guard laneWatch != nil else { return }`, so the call did nothing; with turns.peerStateChanged nil the feed's optional call does nothing either. No behavior change.
|
Review (independent review subagent, arch-rise): SHIP at 0937e42 Re-review after the merge 31728ff (origin/feat-cmux-next) and 0937e42 (one declaration per line, no behavior change):
|
…se-pane-approvals AgentPaneCloudMachineRequest.swift: feat's recoveryList/attach/complete/account reply, read through the PR's optional injected machines (machines?.). AgentPaneHost.swift: feat's removal of the unresponsive watch (#28083) and its shared-lookup daemonReady task, plus the PR's injected peerApprover passed to findOrStart. AgentTabs+Wiring.swift: feat's machineTargets/moveAgentToMachine wiring, plus the PR's peerApprover argument to AgentTabStore. AppDelegate.swift: feat's keyWindowSource/appActiveSource arguments, plus the PR's peerApprover: PeerApprovalsApp.approver(). AppServices.swift: feat's keyWindowSource/appActiveSource assignment, plus the PR's peerApprover assignment.
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. |
…se-pane-approvals No conflicts. Takes in a582ddf (the Glass.swift keepsActiveLook base compile fix).
|
Review (Claude Opus 5.5 reviewer): SHIP at 291e0a2 Scope: Findings:
|
|
Review (Claude Opus 5.5 independent reviewer): SHIP at 291e0a2 Scope:
Not verified (read only): no Swift test was run (on this VM, agents do not run tests locally). The peer-route Allow and Enroll paths have not been tried in a running app. |
|
Red checks at head 291e0a2, classified (merge agent):
Compile of this exact head: fleet compile-check 0c88eda6f4824615527d3384 passed (CmuxNext and app). |
Conflicts: feat removed AcpmuxUnresponsiveWatch (#28083), so AcpmuxLocalDaemons drops its watch and AcpmuxHost its restartsUnresponsive toggle; the host keeps feat's AcpmuxDaemonStop (Restart agent service) beside the injected daemons. feat's peer approver (#28268) and this PR's daemons/updates both flow through AgentTabStore, ChiefHomeAcpmux, resolvePane and the ChiefHomeDirectory ownHost. ChatsFeed drops both removed statics (peerStateChanged's sidebar, the peerSessionChanged static). New feat tests (AcpmuxDaemonStopTests, AcpmuxSlowDaemonTests, AgentChatPeersPendingTests, CloudLinkEndedHeaderTests) pass their own AcpmuxLocalDaemons / DaemonUpdateBoard.
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Summary
Five arch-ratchet sites that rose on
feat-cmux-nextbecome instances made once at the composition root and injected. No behavior change.AgentPanePeerApproverat launch (PeerApprovalsApp.approver()inAppDelegate). It holds this Mac's approver key, the Enroll this Mac command and the local daemons that got the key.AppServicesgets it through its init and gives it toAgentTabStorethrough its init. The store gives it to everyAcpmuxHostit makes (its own host, the Chief home hosts inChiefHomeAcpmux, and the default hosts ofChiefHomeDirectory), and to every pane transport inmakeView. The host registers the key with each daemon it connects. The transport signs with the key. The view runs Enroll through the same object.AgentTabStoreowns oneAgentPaneCloudMachines(as it ownsreadAloud). It wires it inwired(to:)and gives it to every page model inmakeView. The palette's destinations read it from the store.RemoteMachinesSidebar.sharedis removed. Nothing binds the sidebar (65c9441, Lawrence 2026-10-26), so it draws no rows and follows no lanes. It had two callers, and both did nothing:WhatsNewPage.activateClientItemcould not match an id, because the sidebar draws no rows.ChatsFeed+Start.swiftturns.peerStateChanged(added by 6ba8e71, cmux NEXT: one machine link state for the sidebar and the agent pane; a down machine reconnects on use #26786, after this branch began; removed in the merge commit).peerStateChangedstarts withguard laneWatch != nil else { return }, andlaneWatchis set only bybind. With the hook nil, the feed's optional call also does nothing.A future binding constructs the sidebar at the root and injects it.
Sites fixed (paths under
Packages/macOS/CmuxNext/Sources/):CmuxNextAgentPane/AcpmuxMacApprover.swift:25static let shared(and its authorlint:allow)CmuxNextAgentPane/AgentPanePeerApprovals.swift:16static var enrollCmuxNextAgentPane/AgentPanePeerApprovals.swift:20static var daemonsCmuxNextAgentPane/AgentPaneCloudMachineRequest.swift:71static let shared = AgentPaneCloudMachines()CmuxNextAgentLanes/RemoteMachinesSidebar.swift:25static let shared = RemoteMachinesSidebar()Ratchet (
arch_counts.py --delta origin/feat-cmux-next HEAD):stateful_singletons -3(CmuxNextAgentPane -2, CmuxNextAgentLanes -1),global_mutable_statics -2(CmuxNextAgentPane -2),app_lines +0, all other rows +0.arch-ratchet.py --base origin/feat-cmux-next --head HEAD: no count rises.arch-ratchet.jsonis not changed in this PR.Owners: Performance Lead. PL-acpmux for the approver key path (
AcpmuxMacApprover,AgentPanePeerApprover.register).Takes back #26201: its
AcpmuxMacApprover.sharedsingleton (and thePeerApprovalsApp.install()call inAppDelegate.swift,AgentPaneHost.swiftreading it) becomes one approver made at launch and injected; the signed-Allow behavior stays.Takes back #26202: its
AgentPanePeerApprovalsstaticsenrollanddaemonsmove onto that injected approver; Enroll this Mac runs through the same object.Takes back #26786: the
turns.peerStateChangedhook it added inChatsFeed+Start.swiftcalledRemoteMachinesSidebar.shared, which is unbound and does nothing (laneWatchis nil); the hook is removed with the singleton. The machine link state #26786 added is untouched.No capture: no UI change; the same objects are injected instead of read from statics (no view, layout or string changes).
Performance
No perf numbers: an architecture change (singletons and mutable statics become injected instances); no speed claim. perf claim: none.
Testing
The tests that used the statics now make their own instances:
AgentPanePeerApprovalsNoticeTests(the Enroll closure and the daemons map go on a test approver),AgentPaneRelayedAllowTests(each peer chat gets its own memory key),RemoteMachinesSidebarTests(its own sidebar).Observed / Not run
prepush-gate.pyreports no new violations.lint-ios-package-conventions.sh --namespace-fixreports no violations.arch-ratchet.pyandarch_counts.py --deltagive the numbers above.a36a982b6a2of 75d6838 failed:MacNamewas not in scope inAgentPanePeerApprovals.swift. Commit ed0ebc9 adds theCmuxNextCompatimport.600bd68b6d084034d4258dc1of head 0937e42 (the merge of feat-cmux-next). No result yet.Changelog
none
Fleet red / green
No fleet red/green: a refactor (statics become instances injected from the composition root); it fixes no bug, production behavior is unchanged, and the removed RemoteMachinesSidebar callers did nothing (nothing binds the sidebar). Test assertions are unchanged (independent review).