fix(app): closing a pending split keeps the keys held for another terminal (P0 1193)
Summary
P0 1193 family (lead 21:2xZ, re-ranked from the review of #29693, low finding 1): when the person closed a pending split (Cmd-W on its stand-in) and no other creation waited any more, CreationInputBuffer.cancel(tab:) dropped every held key, including a line held for another terminal. That is lost input.
Cause: if pending.isEmpty, awaited.isEmpty { events.removeAll() } (514770ead3c, 2026-10-18), written before keys had lanes: then a held key had no terminal of its own. With #29301's lanes, a key held for another terminal is that terminal's.
Fix: when nothing waits any more, drop only keys typed for no creation (lane nil: the same rule as before for them, never typed into whatever has the focus). A key with another terminal's lane stays, and goes to that terminal when the hold ends; the coordinator already ends the hold right after a cancel (drop(tab:in:) -> scheduleFlush).
Base: stacked on #29301's branch fix/p0-1193-key-lanes; after #29301 merges, the base moves to feat-cmux-next (no rebase).
Testing
Red-first, a unit test of the buffer: CreationInputHoldTests.closingAPendingSplitKeepsTheKeysHeldForAnotherTerminal (A's line held, A's reply came, B's split pending with its own key, B closed: A's key must stay).
| Ref | What it is | Job | Result |
|---|---|---|---|
| 65faf5dd0ea | #29301's branch + the test only | 7178b4a892d4daa51ad1c8c0 | the new test fails on its outcome: take() == [] ("the line held for terminal A was dropped with the closed split of terminal B"); 5 others pass |
| 7174f852a75 (this head) | the fix | 30ac51b76972455d4c43236c | CreationInputHoldTests 6 of 6, SecondCreationKeysTests 6 of 6 (no regression in #29301's tests) |
Both ran as display steps (console session, CMUX_TEST_REQUIRE_GUI=1). Compiles: head f64555ec4856256a29d96199, red 1dcbb5e94e9160d935958e06.
Observed / Not run
Observed: the two runs above, logs read before counting.
Not run: an end-to-end test (Cmd-D twice, Cmd-W on the second split, then the first terminal's line arrives); the buffer test covers the rule, and the coordinator path after a cancel is unchanged.
Performance
No perf numbers: a correctness fix in a filter on held keys. perf claim: none.
Changelog
Fixed: Closing a new pane while it is still opening no longer drops what was typed for another pane
Proof
No capture: key routing inside the hold; the evidence is the fleet tests above.
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes closing a pending split so keys typed for another terminal are no longer lost.
- When no creation is pending,
cancel(tab:)now only removes keys typed for no creation; keys held for a specific terminal stay and are delivered when that hold ends. - Adds a unit test covering the case where terminal A's line is held while terminal B's pending split is closed.