test: shared model-level case matrix for cmux NEXT (cx-gkyi1)
Summary
Bead cx-gkyi1, for op-ci-tiers' PR fast tier, sharing one case list with op-next-replay's real-HID matrix (cx-hdyx4).
Packages/macOS/CmuxNext/Tests/Matrix/cases.json is that one case list: 90 model-level cases for cmux NEXT.
- Areas: workspace create from every entry, workspace and tab reorder, tab moves between panes and workspaces, split create/close/zoom.
- Each case gives:
- the action and the entry it comes from (palette, menu, context menu, shortcut, CLI, the strip's +, the sidebar's +, a drag);
- a seed preset with named objects (
$w1,$p1,$t2, …); - the invariant codes it expects (
item-set-kept,order-is,selected-is,focus-on,zoomed-is,layout-valid, …); - the steps on the daemon core (
core); - the tiers that run it.
- Runners: three read the file.
ModelMatrixTests(this PR): headless Swift, no window, no daemon, about 0.02 s.mux::tests::matrix: runs every case's core steps on the real daemon core in-process. Next PR.- The real-HID and monkey runners in op-next-replay's tools.
- Failure format: every failure starts with
MATRIX <case id>:.
ModelMatrixTests checks three things:
- The file: codes, presets,
$-refs, tiers, inputs and entries are declared. A headless case has core steps and no wall-clock codes. - Every case's entry reaches its action: the palette, CLI, right-click menu, main menu or default binding the case names really offers that action. For the strip's +, the sidebar's + and drags, a declared action list stands in for the catalog.
- Coverage: every entry a covered action offers has a case. If a menu item or shortcut is added to
splitRight, the suite fails until a case covers it.
Writing the file surfaced six cases that named a surface the action doesn't offer, so those cases are fixed:
newTabhas no CLI verb.closePanehas no default key or CLI verb.toggleSplitZoomhas no CLI verb.
Also of note: the sidebar's + calls WindowManager.newWorkspace directly, not an action. Its row close button goes through closeWorkspace. The file records the + as a non-catalog entry.
After review:
- The file now has a
vocabularyblock. It defines each code's exact arguments, what eachofmeans and whattargetmeans per entry: palette, menu and shortcut runs focus the target first, a context menu right-clicks it, the CLI passes it with--focus.ModelMatrixTestsrejects missing or unknown arguments. - Sidebar order is the app's personal order: the app computes the index (
AppActions+PersonalOrder) and the core only stores it. Workspace reorder, positioned creates (above, below, top, bottom), groups and pinning therefore run in the HID tiers only for now. cx-rq6i5 tracks a headless Swift runner for that logic. - 59 of the 90 cases run headless.
Testing
Command: cmux-ci run --class light --script scripts/ci/run-swift-testing-suites.sh --arg Packages/macOS/CmuxNext
On 0739a3d67176, CmuxNextActionsTests.ModelMatrixTests passes all three tests, in 0.017 s. KeybindingsFileRelaunchTests and PinnedPageTests fail as known base reds.
Review (Opus subagent): the file's expectations were checked against the handlers. Fixed: the ws3 count, the CLI focus semantics, a self-contradicting tab.move.toWorkspace, drag20 order, the zoom mode, argument validation and non-empty core. One must-fix, missing targets on split.close, lastTabClosesPane and fromPane, was a misread: those cases already name $p2/$t2. The target definition now says how HID runners use it.
This is a new contract test, not a fix, so there is no red commit. An offline run of the same checks against plans/cmux-next/action-surfaces.json caught the six wrong entries and eleven missing offered entries before the fix-up.
Changelog
none
🤖 Generated with Claude Code