test: shared model-level case matrix for cmux NEXT (cx-gkyi1)

Merged
TE
24d ago
+4633-0

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:

  • newTab has no CLI verb.
  • closePane has no default key or CLI verb.
  • toggleSplitZoom has 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 vocabulary block. It defines each code's exact arguments, what each of means and what target means per entry: palette, menu and shortcut runs focus the target first, a context menu right-clicks it, the CLI passes it with --focus. ModelMatrixTests rejects 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