CmuxTabsKit: build only nearby grid cards; dormant hidden grid

AZ
9d ago
+463-34

Summary

CmuxTabsKit's tab grid builds only the cards near the screen and does no body work while it is hidden. These are the kit-only commits of the cmux-next iOS lists rebuild (manaflow-ai/cmux PR against feat-cmux-next from feat-cmux-next-ios-smooth-lists), proposed here so Packages/iOS/CmuxTabsKit stays identical on both branches.

  • Card residency (CardResidency, CardResidencyPlan): cards on screen are built at once, cards within 3 screens are built one per frame while the grid rests, cards past 4 screens are released. Scrolling never re-runs the grid's body.
  • Hidden grid (DormantGate): while a page shows, the grid stays mounted but holds its updates, and the active card's content is not built under its page.
  • overviewIdleChanged(_:): new source hook with a default no-op (additive; nothing public removed or changed). README updated.
  • Accessibility: a card outside the built band is a bare accessibility element in its slot (same label as the built card; activating opens the tab), so VoiceOver swiping reaches every tab.

Measurements (60 Hz iPhone 17 Pro simulator, iOS 26.5, list rig on aws-m4pro-6, before = feat-cmux-next at 4e28d9cf44d9, after = the app branch head, 2 runs each)

CaseScroll hitch ms/s (before / after)Main CPU ms/sGrid open, worst frameMemory
30 tabs0 / 0-1.5213-265 / 160-167540-584 / 86-317 ms185 / 59 MB
30 tabs, one chat streaming173-396 / 0-1.7930-1014 / 158-163509-546 / 84 ms217-222 / 61 MB
80 tabs18-75 / 0-5.2469-709 / 204-227679-779 / 79-92 ms395 / 66 MB

The after numbers include the app-side host changes (stored tabs, per-tab observation, agent cards as pictures), which stay in the app branch.

Testing

  • swift test in Packages/iOS/CmuxTabsKit on aws-m4pro-5: 62 tests in 13 suites passed (new CardResidencyPlanTests).
  • CmuxTabsKitDemo builds for the iOS simulator (aws-m4pro-6, Xcode 26.6).
  • In the app: WorkspaceTabsSourceListTests, WorkspaceTabsSourceUpdateTests on an iOS simulator, 16 passed.

Observed / Not run

  • Observed: rig frame logs, videos and stills in the app PR's report; the demo host was built, not run.
  • Not run: VoiceOver itself over the grid (the stand-in elements were checked in code only).

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

The tab grid now builds only cards near the screen and stays dormant while hidden, so scrolling and page updates never re-run the grid's body.

  • Cards on screen build at once; cards within 3 screens build one per frame while the grid rests; cards past 4 screens are released.
  • Unbuilt cards remain in the accessibility tree as bare elements with the same label, so VoiceOver reaches every tab.
  • While a page shows, the grid stays mounted but holds parent updates (DormantGate), and the active card's content is not built under its page.
  • Adds overviewIdleChanged(_:) to TabsDataSource as an additive default no-op; nothing public was removed or changed.