fix(focus): the reopen key hold also waits for a restored browser tab's page; Cmd-L reaches its address bar (REOPEN-F4 browser case)
Summary
After Cmd-Q (Keep) and a reopen with a browser page focused, a person's Cmd-L typed right away opens a new New Tab page, and the text typed after it goes there instead of into the address bar. Journey reopen-browser-first-key (kit cp/reopen-video-kit@9c22661888, review SHIP) on feat c569f95 (build 6661b995): 3 of 5 cycles lost the real Cmd-L + marker (lost at 106-122 ms after main, kept at 297-312 ms). STATUS 5871.
Cause (input journal + code): a restored Chromium tab gets its page from an async start (TabContentCache.browser -> makeCEFTab in a Task; nil until onBrowserReady, about 300-400 ms after main). In that gap the focus already names the browser page, but the pane has no browser content. Cmd-L is Focus Location Bar (PaneController.focusLocation), whose "not a browser" branch opens a New Tab page (cx-e2aa). It is the same class as REOPEN-F4 fault 2 (#31707): focused content whose view is not ready, here a page instead of a terminal.
Fix: the #31707 key hold also waits for a focused browser tab whose page is not made yet.
AwaitedContent(new, CmuxNextFocusUI, a pure policy): the decision "the focus names content its pane does not show yet", for a terminal (unchanged rule) and now a browser page. The coordinator's old inline decision moves there (commit 1, no behavior change).CreationInputBuffer.awaitContent: a page hold has no terminal lane. Every key but a close waits (Cmd-L needs the page), at mostholdLimit(2 s) from the hold's start.- The hold ends when the page is presented (contentPresented -> focus settle -> flush). The keys then run again as typed: Cmd-L focuses the address bar, and the letters after it go there. At the bound they run as typed too.
FocusState.awaitableContent(CmuxNextFocus) maps the focus to the content keys are for. Net CmuxNextApp −4 lines.
Not part of this PR: the smoke gate's step-70 "reopened window not key" (STATUS 5612/5810) is a gate gap, not this fault. With #31684 the restored page keeps the keyboard in its Chromium page window. The harness owner's fix is on cp/smoke-known-gap (37fb4ba6272).
Testing
AwaitedContentTests(CmuxNextAppTests): the terminal rule (commit 1, green), thenaRestoredBrowserTabIsAwaitedUntilItsPageExists(commit 561522e6e3e, red: the browser tab is not awaited, and its keys would get a terminal lane).
Fleet runs (package-test-lane.sh suite,AwaitedContentTestsnamed 5 times, throughproof-step.py):- Red 561522e6e3e (browser test, policy without the browser rule), job 58bdcdfb8862a3f5a07af639:
aRestoredBrowserTabIsAwaitedUntilItsPageExistsfails 5 of 5; the terminal tests pass. - Red 9249761ae90 (review: shortcut test,
pageHoldKeepsstubbed to true), job d165e0a6eb3f1a9dbdbc618f:aPageHoldLetsAppShortcutsPassWhileEmptyButKeepsPageActionsfails 5 of 5. (The first try 2244fcce ran on the Blacksmith overflow and failed with no test output: an infra run, rerun at the same sha.) - Green at the head ee0fb3ca578, job 38290ab3c58dae522b6c03ca: all 5 tests pass 5 of 5. Compile of the head: job 50816a586ed681f9c011db7a passed.
- End result (REOPEN VIDEO owner, STATUS 6007), build 4611f6ba740b7f1d7900687e of the first fix (d64f06a4fb0):
reopen-browser-first-key(kit 9c22661888) 3 of 3 rounds, 9 of 9 cycles (Cmd-L + marker reached the address bar 9/9; Cmd-N + Ctrl-made a terminal in a new workspace 9/9);reopen-first-key` (kit ff80174a568) 1 round, 0 keys lost in 5 cycles, kill-all line reached the shell. Base feat c569f95: 3 of 5 cycles lost.
Merge of feat (head a919ea996a0, PR was DIRTY; one conflict with #32098 in flush, both changes kept): compile of the head passes for the app and cmux-tui; the CmuxNext tests at the head fail only on the feat tip red AgentPaneRelayedAllowTests.swift:328 (#32113, STATUS 6262). Proof ref 5c124146a70 = head + that one file from before #32113 (proof only): compile a2a839d605bbdfcd740ae77b passed; AwaitedContentTests x5 job d1dd75af548b663e429c0d58: all 5 tests pass 5 of 5. Display proof: the end-result journey above is the real-app proof (REOPEN VIDEO, real HID keys on a mini's console session); AwaitedContentTests is a pure policy and needs no display.
Review: SHIP at a919ea996a0 (comment 6575617084); earlier SHIP at ee0fb3ca578 (comment 6573991292). Its first FIX (a cold Chromium tab's page hold delayed app shortcuts) and its notes are fixed in 9249761ae90 / 37c96ebaf20 / ee0fb3ca578.
Observed / Not run
- Observed: the journals of rounds
rbk2-feat-c569f95/a1-a3(lost cycles: Cmd-L key-down at 106-122 ms, the pane shows apending_tab, thenagentPage, the marker goes there). Code read ofTabContentCache.browserandfocusLocation. Pre-push gate: no new violations. - Not run on the final head: the journeys ran on d64f06a4fb0 (before the review fixes). The review fixes narrow the hold (app shortcuts pass while it is empty; a tab whose hold reached its bound gets no new hold until its page arrives); they do not touch the Cmd-L path the journey drives.
- The last test (
aTabExcludedAfterItsBoundIsHeldAgainOnceItsPageArrived) is in the same commit as its fix (ee0fb3ca578), not committed red first. - Follow-up (review note): split the one-line
pageArrived(key); for ...at AppServices.swift:742 into a coordinator method; not done here because it adds App lines the arch ratchet refuses. - Not covered: plain keys (no Cmd-L) typed into a restored page before it exists run again into the shell window's responder, not the Chromium page window; the observed case is Cmd-L first.
Changelog
Fixed: After cmux reopens with a browser tab focused, Cmd-L and what you type right away go to its address bar instead of opening a new tab
Proof
No capture: input routing; the proof is the tests and the reopen journey.