Repository navigation
Description
Problem
Opening or switching a mobile session tab did not reliably leave terminal input focused or open the keyboard.
Root cause
_shouldFocusTerminalForTabSwitch()only allowed touch focus when KeyboardHandler already reported the keyboard visible. With the keyboard hidden, an explicit tap blurred stale input but selection declined to focus the terminal.- Selecting the already-active session returned before terminal focus.
- The fork's mobile tab sheet scheduled search autofocus after 180 ms without cancelling it on selection/close. Reproduction: terminal focused immediately after a quick selection; 240 ms later the offscreen search field in the closed sheet held focus.
Fix and delivery
Explicit mobile selection now synchronously focuses terminal input, including the active tab. App-driven restore remains passive when the keyboard is hidden. Tab-sheet close cancels and guards delayed search focus before routing selection through the ordinary stale-focus reset.
Branch fix/35-mobile-tab-keyboard, implementation 2ec3797f, fork PR #36, merge 57e7c5cd, version 1.47.0. Built from an isolated clean worktree and deployed frontend assets only. Every existing backend artifact hash and all five unrelated dirty assistant files were preserved; existing backend service restarted to load the new index. Rollback static assets retained outside the checkout at /opt/projects/.codeman-public-before35-20261031.
Upstream PR: Ark0N#746 (branch fix/mobile-tab-keyboard-focus, commit 15e27275, based on upstream f1f7eec4). It contains the shared focus policy and tests; the fork-only sheet timer change is omitted because upstream has no mobile tab sheet.
Verification
- Fork: 6 focused Chromium DOM/focus checks and 172 related tests passed; required static checks and isolated build passed.
- Fresh isolated full mobile UI: ordinary switch and quick active-tab selection both retained xterm textarea focus after the timer; no page errors.
- Fresh production UI: the same two scenarios passed using only disposable shell sessions, which were removed afterward. Served app.e8e8184f.js and mobile-tabs.a2c91e12.js.
- Upstream: 5 focused browser checks, 107 related tests and required static checks passed.
- Fork broad smoke: 84 passed, 2 known long-scrollback wheel failures, 1 remote skip. Upstream broad smoke: 79 passed, 7 failures, 1 skip: two fork-runner 100000-vs-upstream-50000 scrollback expectations, three screenshot attachment-history checks with zero metadata entries, and two long-scrollback wheel failures. No browser page/console errors. These are limitations, not claimed passing gates.
- Fork GitHub static CI passed; broader unit CI and upstream CI were pending at last inspection.
- Native iOS keyboard presentation is not proven by Chromium emulation. WebKit is not installed here; physical iPhone verification remains necessary. Screenshots and RCA notes are in docs/reports/mobile-tab-keyboard/.
Activity
johoja12 commentedon Oct 31, 2026
Reopened after the user reports the native keyboard still fails and seems worse. Pausing further production changes while running baseline/current full mobile keyboard/tab suites, smoke and a broader full-page matrix. Confirmed additional gaps: returning from a webview focuses a display:none terminal synchronously (rejected) and only focuses successfully after await; a lingering touch-selection guard rejects both selection focus attempts. Existing shell-only tests missed both. Native keyboard is not proven by DOM focus.
johoja12 commentedon Oct 31, 2026
Reopened: confirmed focus lifecycle defects; native keyboard remains unverified
The previous fix was incomplete. A full-page baseline/deployed/candidate comparison reproduced:
Candidate d9386f3 on investigate/35-mobile-keyboard-rca reveals the input before synchronous focus, clears the prior selection guard only for an explicit tab choice, uses the mobile input helper, and avoids late mobile refocus. It is staged locally, not merged or deployed. Production remains 57e7c5c / app.e8e8184f.js. Upstream PR Ark0N#746 has been converted to draft with a warning about these gaps.
All 12 deployed mobile-suite failures also occur on the baseline. The additional baseline failure is its obsolete preserveKeyboard assertion. The two smoke failures are long-scrollback wheel navigation. Historical baselines also exhibited them, but the fresh baseline was green; their relationship to this patch is not established. The smoke gate remains red, not waived.
Candidate typecheck, lint, formatting, lockfile and frontend JS syntax checks pass. No additional production changes during this investigation. Temporary matrix sessions and servers have been cleaned up; unrelated shared-checkout assistant WIP was preserved.
Limits: Chromium DOM focus does not prove native keyboard display. WebKit binaries and dependency libraries were prepared in temporary directories without system package changes; WebKit launched but page creation timed out, so no valid WebKit matrix passed. Claude auth freshly reports not logged in; live Claude and remote-host coverage were not established. The phone/browser clarification remains unanswered and is needed for the native keyboard reproduction.
Detailed report and raw focus observations: docs/reports/mobile-tab-keyboard/lifecycle-rca/ in the candidate branch. Run logs retained at /tmp/codeman-35-*.
docs: record requested mobile candidate deployment and complete test …
johoja12 commentedon Oct 31, 2026
User explicitly requested candidate production deployment after the RCA and red smoke gate were reported.
Deployed candidate FRONTEND ONLY from d9386f3 (docs update 1794975), served as app.aa05c7b6.js. The clean isolated build passed. All pre-existing backend artifact hashes and the five unrelated shared-checkout assistant WIP files were preserved. Source checkout remains local at 57e7c5c; this is a branch frontend test deployment, not a merge of draft PR #37. Static rollback retained at /opt/projects/.codeman-public-before35-lifecycle-20261031.
Fresh production full-page focus matrix: 7/7 assertions passed with zero page errors, using only disposable shell sessions, which were removed. Verified hidden keyboard, active tab, webview return (first visible synchronous focus), CJK input, retired selection guard, stale helper coordinates, and retaining another input deliberately selected during a delayed load. This is DOM/focus proof; native phone keyboard display is still unverified.
Final candidate full mobile keyboard/tab suite: 76 passed, 12 failed (88 cases), identical to deployed source before this candidate. Original baseline was 75 passed/13 failed. Focused checks: 9 browser, 172 related tests passed. Frozen smoke: original baseline 86/0/1 skip; deployed and candidate 84/2/1 skip. The two scroll failures remain unresolved. Static checks passed; GitHub broader CI is separate.
Issue #35 and both draft PRs remain open pending native-device validation. No claim that the native keyboard is fixed. Reload the phone page to load the new asset and test the reported flow.
johoja12 commentedon Oct 31, 2026
The reporter identified the top-right header menu as the workaround. Full-page comparison now reproduces its focus-state effect:
The old
_mobileKeyboardIsUptrusted both retained textarea focus andKeyboardHandler.keyboardVisible. Native dismissal can leave both stale when its viewport-resize event is missed. The menu takes focus to a button, making a later terminal focus fresh. The candidate instead checks current same-width viewport geometry against the canonical resize detector's existing hide thresholds, invokes that detector to repair stale visibility, then allows the existing helper to blur/refocus synchronously. A genuinely shrunken keyboard viewport is not cycled.11 focused browser tests and 172 related tests pass. One old mobile test set only keyboardVisible=true with a full-height viewport, which now models the regression rather than a real open keyboard; its fixture was corrected to represent a 300px keyboard shrink and its unchanged second-tap-dismiss assertion passes. Full keyboard-suite rerun and clean isolated build are underway.
Bounded KEYBOARD_RECHECK / KEYBOARD_FOCUS breadcrumbs record flag, viewport, focus and activation state without typed text. The exact header handler is exercised in the browser test. Full-page comparison used only disposable shell sessions, which were deleted; no page errors. Native OS keyboard opening still requires phone verification.
fix: reconcile stale keyboard visibility before terminal focus (#35)
johoja12 commentedon Oct 31, 2026
Deployed the header-menu follow-up from 92e8dc7 (candidate frontend branch). Served terminal-ui.f6f7b9f3.js; existing backend artifact hashes and shared-checkout assistant WIP preserved. No merge of draft PR #37 or close of #35; native phone reliability is still awaiting the reporter's confirmation.
Fresh production comparison with the actual header-menu handler:
KEYBOARD_RECHECK and KEYBOARD_FOCUS breadcrumbs now capture focus, activation and viewport/cache state without typed text, for actual phone follow-up. The reporter should reload the phone page so it loads the new terminal UI asset.
johoja12 commentedon Oct 31, 2026
Repeated open/close follow-up: commit
2ded578aoninvestigate/35-mobile-keyboard-rcachanges the canonical keyboard-hide handler to release retained terminal input focus. The next tap no longer depends on blur/refocus in one event; other focused editors are preserved.Validated so far: 12 browser tests (including 25 repeated dismiss/reopen cycles), 172 related regressions, build and typecheck. A full-page isolated session also completed 12 cycles/36 states without focus-state mismatches or offscreen input. These simulate viewport changes; native phone keyboard reliability is still unverified. Full mobile suite and realistic smoke are running. No new production deployment yet. Issue stays open.
johoja12 commentedon Oct 31, 2026
Repeated-dismiss candidate
2ded578ais committed locally. Validation completed:Deployment readiness is NO while those runtime smoke checks fail. This follow-up has not been pushed or deployed; production remains on the previous frontend candidate. Native phone keyboard visibility remains unverified. Issue and draft PR remain open.
Artifacts:
/tmp/codeman-35-repeat-keyboard.log,/tmp/codeman-35-repeat-browser.log,/tmp/codeman-35-repeat-fixed.log,/tmp/codeman-dev-smoke-artifacts-2026-10-31T18-02-59-903Z-p2720596-r635f64c5ba254a54ba4616068f3dc0b0/summary.json.fix(mobile): release terminal focus after keyboard dismiss (#35)
johoja12 commentedon Oct 31, 2026
Deployed the requested branch for phone testing at
2ded578a(frontend assets only). Production returns HTTP 200 and servesmobile-handlers.90de8d54.js, byte-for-byte matching the isolated build. Service is active. Existing backend artifact hashes and unrelated shared-checkout WIP hashes are unchanged; previous static assets are backed up at/opt/projects/.codeman-public-before35-repeat-20261031.Fresh production-page probe: 12 simulated open/close cycles, 36 states, zero focus mismatches and zero offscreen helper inputs. Its disposable session was removed. This tests DOM focus and viewport handling, not native keyboard visibility. Actual phone confirmation is still needed; issue and PR stay open/draft.
The broader smoke remains unresolved: correcting the temporary runner's reversed fallback wheel direction did not clear its long-scrollback return failure. Deployment is an explicitly requested candidate for phone testing, not a claim of green runtime gates. GitHub PR checks are pending.
johoja12 commentedon Oct 31, 2026
Deep RCA follow-up: two lifecycle defects are now reproduced using the actual deployed handlers.
onKeyboardHide(), whose new unconditional blur cancels the fresh focus. Prior repeated-cycle tests always waited for hide to complete, so they missed this ordering.forceKeyboardHidden()sets the keyboard-free baseline to that shrunken height. Subsequent focus at the same height remains classified keyboard=false. Reproducer: baseline 750 / viewport 420 / visible -> return -> baseline 420 / viewport 420 / hidden.Fresh phone breadcrumbs contain 12 focus requests on the latest retained page: 11 focused=true/gesture=true at height=763/baseline=763, and one at height=449/baseline=449/minimum=0. The latter is consistent with the calibration defect. Existing diagnostics cannot establish the exact native event ordering, device/browser, or loaded phone build. Server assets match the candidate, but phone asset identity is not recorded.
The broad claim that successful DOM focus validates keyboard opening is incorrect. Native-device verification is still missing. The current unit/integration CI also fails at
test/opencode-mobile-font.test.ts:910after the new hide-handler side effect reaches the blur path in an incomplete fixture; static checks passed.Repair direction: separate open/dismiss intent from passive geometry changes, prevent old transitions from blurring newer focus requests, preserve keyboard-free calibration during lifecycle recovery, and trace input focus/blur + viewport transitions with request/build identity. No timed focus retries. Validate rapid interleavings and actual native keyboard/input on the reporter's phone.
Detailed report and deterministic state output are in
docs/reports/mobile-tab-keyboard/lifecycle-rca/deep-analysis-2026-11-01.mdandkeyboard-lifecycle-repro.json(analysis commit22ac4b77). No production behavior was changed during this analysis. Issue remains open and PR #37 draft.docs: record mobile keyboard lifecycle races (#35)
12 remaining items
fix(mobile): transfer settled tab keyboard dismissal ownership (#35)
johoja12 commentedon Nov 1, 2026
Deployed follow-up fix 5905558 (v8 diagnostics, package version remains 1.47.0).
RCA: tab/search selection advances the terminal focus generation while the existing keyboard remains visible. No new viewport shrink occurs to refresh dismissal ownership. Its next hide therefore skips release because the owner still refers to the old generation.
Fix: after an explicit session-tab request survives the 350 ms focus-settle interval, transfer dismissal ownership to that request only if its target, generation and keyboard-open viewport geometry remain unchanged. This timer never focuses or blurs. Closing geometry, another editor, another request, hidden page or cleared keyboard ownership prevents adoption. Late-close protection remains in place while settling.
Validation:
Retest artifact: /tmp/codeman-touch-tabs-prod-v8-20261101/report.json (runner, logs and screenshots alongside). The first production attempt stopped on a transient post-resize history classification; retained in attempt-1/. The completed run polls for the actual valid touch target up to 1.8 s without forced scrolling, forced clicks or programmatic focus. It still asserts keyboard dismissal releases focus.
Native keyboard appearance remains unverified: Chromium touch events and viewport simulation prove web focus/state/input behavior, not the iPhone OS keyboard. Issue stays open and PR stays draft for device confirmation. Current GitHub Actions run 41298300037 is still in progress; local gates above passed. No upstream repository writes and no merge to local were made in this follow-up.
johoja12 commentedon Nov 1, 2026
Follow-up phone report: user still needs the header menu before keyboard reopening. Latest native phone beacon at 10:56:41 UTC contains KEYBOARD_STATE v7 throughout; no v8 native trace has arrived yet. Production serves v8 assets. Header menu toggles layout classes and dispatches resize; it does not perform a browser reload. Asked for one browser Reload followed by open/dismiss/reopen to obtain current-build native evidence. The v7 trace shows a focus request remains active/onscreen/editable without native viewport shrink, then a menu detour permits a later native show. Do not treat the emulation pass as native resolution. Issue remains open; no speculative additional code or deployment in this follow-up. GitHub Actions run 41298300037 for 5905558 is now successful.
johoja12 commentedon Nov 1, 2026
Native v8 failure confirmed after browser reload (fresh page mvxrd5we-yi6poa). First show/owned dismissal succeeds; later request-5 remains terminal-focused with visible=false at 1000 ms and editable, clipped-in 1px input at y650. Menu opens at 11:40:19; request-6 at 11:40:20 then produces real viewport-show at 11:40:21. This is not the settled tab ownership bug and not stale assets. Investigating native input layout invalidation: candidate will rebuild the same hidden textarea layout synchronously before an iOS reopen after observed dismissal, preserving DOM/listeners/value/selection and never focusing from timers. Need native phone verification; Chromium focus tests alone do not prove resolution.
fix(mobile): revalidate native input layout on iOS keyboard reopen (#35)
johoja12 commentedon Nov 1, 2026
Deployed candidate 8e2d26f, diagnostic build v9 (package 1.47.0).
The fresh real-phone v8 reproduction disproved native resolution: release:true on dismissal, then later terminal focus remains active/onscreen/editable without a keyboard show; menu reflow followed by a tap succeeds. This is distinct from the earlier generation mismatch. Native trace is preserved privately at /tmp/codeman-35-v8-reloaded-phone.json.
Candidate recovery: remember the exact input released on owned native dismissal. On a subsequent iOS opening gesture, while it is unfocused and the keyboard is hidden, temporarily remove and restore that input's display with synchronous layout reads before focus. Preserve the same DOM node, listeners, value, selection and original inline display/priority. A real keyboard show clears the marker. No focus retries from timers and no terminal resize, menu toggle or unrelated editor focus changes. This tests the layout-invalidation hypothesis suggested by the menu workaround; the native internal cause is not proven.
Validation:
Artifacts: /tmp/codeman-touch-tabs-prod-v9-20261101/report.json, runner/log/screenshots alongside; /tmp/codeman-35-v9-{browser,unit,smoke,build}.log.
Native acceptance remains pending: asked user to reload into v9 and reproduce. No v9 native beacon has arrived yet. Do not mark this resolved from Chromium emulation. Issue remains open and PR remains draft. GitHub Actions run 41303431017 is still in progress. No merge to local or upstream writes in this follow-up.
johoja12 commentedon Nov 1, 2026
Native v9 remains broken per user. Phone trace confirms layout revalidation ran before request-6 after menu, but that does not establish why requests 2-5 failed; later menu/typing replaced their observations in the bounded buffer. Real keyboard dismissal also reports pageFocus=false, distinct from activeElement; later successful requests after menu report pageFocus=true. Page-focus recovery is a hypothesis, not established RCA. Requested one failed reopen followed by returning to chat without the menu so the failed state survives. No new speculative behavioral patch/deployment in this follow-up. Private snapshot: /tmp/codeman-35-v9-native-failure.json (0600). Keep issue open and PR draft; automated focus/input results do not establish native keyboard reliability.
johoja12 commentedon Nov 1, 2026
Captured decisive no-menu failure at 13:46:05 (private /tmp/codeman-35-v9-failure-no-menu.json). Request-3: textarea active, editable, rendered, clipped-in at y650, but pageFocus=false immediately and at 350/1000 ms; no viewport-show. Later menu-assisted request-19 has pageFocus=true and real viewport-show. Native page/window focus is a distinct missing state; current helper only restores activeElement. Implementing synchronous window.focus() before input focus in an explicit visible iOS opening gesture; removing the disproven display/layout-rebuild candidate. Native effectiveness still requires phone confirmation.
fix(mobile): restore page focus before reopening the iOS keyboard (#35)
johoja12 commentedon Nov 1, 2026
Captured native failure and deployed 5ee9a00 (diagnostic v10; package 1.47.0) to production.
Native evidence: fresh no-menu request-3 at 13:46:05 shows active, editable, rendered, clipped-in textarea, but document.hasFocus()=false immediately and at 350/1000 ms, with no keyboard show. In the same preserved trace request-2 from session-tab has pageFocus=true and does show the keyboard. Later menu-assisted request-19 also has pageFocus=true and a real viewport-show. Snapshot /tmp/codeman-35-v9-failure-no-menu.json is private (0600). This identifies missing page/window focus independently of activeElement; it does not prove a browser focus request will be accepted on the phone.
Change: request window.focus() before focusing the terminal input when iOS reports the page unfocused. Gated on visible page plus active user gesture, and skipped for already-focused pages/non-iOS/background/no-gesture paths. No timers or loops retry focus; browser rejection is logged and the input gesture proceeds. Removed the unsuccessful v9 display/layout-rebuild method, dismissal marker and its tests. Diagnostic builds/boxes consistently identify v10 and log the page-focus request outcome.
Validation:
Artifacts: /tmp/codeman-touch-tabs-prod-v10-20261101/report.json, runner/log/screenshots alongside; /tmp/codeman-35-v10-{browser,unit,smoke,build}.log.
Asked user to reload into v10 and repeat without menu; if it fails, stop before menu to preserve the native page-focus outcome. Native acceptance pending; issue stays open and PR draft. GitHub Actions run 41313311244 is still in progress. No merge to local and no upstream writes.
johoja12 commentedon Nov 1, 2026
Native v10 still fails. At 15:17:11.505/11.804, KEYBOARD_PAGE_FOCUS requested=true after=false; request-13 remains pageFocus=false at 350/1000 ms. Menu close at 15:17:12.833 has pageFocus=true; request-14 then produces viewport-show. Private snapshot /tmp/codeman-35-v10-native-failure.json (0600). Removing ineffective script window.focus path. Candidate v11 permits the native compatibility mouse default only for an armed lost-page-focus keyboard tap, stops mouse propagation to xterm/CLI, then focuses input on its trusted click. Generation/session/target/expiry/selection/editor checks fence recovery. Normal touch/selection defaults remain suppressed. Controlled browser regression failed before patch (mousedown default cancelled), passes after with zero CLI mouse events. This validates event routing, not physical iOS acceptance; native confirmation is still required.
fix(mobile): allow native page activation during keyboard recovery (#35)
johoja12 commentedon Nov 1, 2026
Deployed candidate 15dc142 (v11 diagnostics, package 1.47.0) after the native v10 failure.
Evidence: at 15:17:11.505/11.804 the phone logs KEYBOARD_PAGE_FOCUS requested=true after=false. Request-13 stays DOM-focused but pageFocus=false and visible=false at 350/1000 ms. Menu close at 15:17:12.833 has pageFocus=true; request-14 then produces a real keyboard viewport-show. Private snapshot /tmp/codeman-35-v10-native-failure.json (0600). Script window.focus was ineffective on this phone.
Change: remove script window.focus retries. For a visible iOS page that remains unfocused after an explicit terminal-input touch, arm a short-lived native-click recovery for the exact target, session and generation. Permit default browser activation on the following trusted compatibility mouse events while stopping propagation to xterm/CLI; refocus from its trusted click. Normal touch/selection mouse suppression remains. A new gesture, newer request, session switch, another editor, active selection, open keyboard or expiration prevents stale recovery. A content touch on an unfocused iOS page no longer pre-cancels that native activation path; actionable TUI taps still do not arm input recovery. OpenCode container capture skips only an armed recovery, retaining its ordinary click fallback.
Validation:
Artifacts: /tmp/codeman-touch-tabs-prod-v11-20261101/report.json and runner/log/screenshots; /tmp/codeman-35-v11-{red,browser-final,unit-final,smoke,build-final}.log.
User asked to reload into v11 and repeat without menu, stopping on failure if necessary. Native acceptance remains pending; issue stays open and PR stays draft. GitHub Actions run 41321387041 is still in progress. No merge to local and no upstream writes.
fix(mobile): recover keyboard focus across dismissals and tab changes (…
johoja12 commentedon Nov 3, 2026
Updated the existing upstream keyboard PR Ark0N#746 through fork branch
fix/mobile-tab-keyboard-focus, commit9a595fe85bc0cfdbc7b8d2d2bc993ef2597f8d8c. It now carries the shared v11 focus-generation, stale-focus/viewport and trusted native-click recovery, excluding fork-only UI and unrelated backend work.Verified on the upstream branch: 32 focused Chromium browser tests, 246 related unit tests, and static checks pass. Broader mobile suite: 48 pass, five fail; all five reproduced on previous PR head
15e27275. Isolated Codex/shell smoke: 103 pass, three screenshot attachment-history failures; no browser page/serious console errors. Claude-enabled smoke was blocked by expired OAuth preflight. Temporary smoke instances/sessions were cleaned up.PR remains draft for physical-device verification. Production and the shared checkout were not changed by this upstream update. Fresh CI is separate from these local results.