* fix(ui): open voice setup before history admission
The microphone remains enabled for dictation during initial history, but its
short-tap handler returned at the history submission fence before opening
unavailable capability settings. Catalog admission populated a closed picker:
two unavailable DOM rows existed, while accessible Configure menuitems were zero.
Open capability guidance before that fence. Actual Talk creation still waits
for accepted history. Keep the existing unavailable-settings unit case and
all E2E assertions; hold startup and catalog across the target's early click.
Synchronize the four other proven desktop Talk-start races with the existing
waitForTalkReady helper. Leave direct/hold dictation, explicit picker triggers,
mobile Talk and already-synchronized Talk cases unchanged. Document the behavior.
Introducing ordering: 0b52dc467b added the history submission fence before
picker opening; d769e31af2 now awaits foreground stream admission before
history/startup, exposing that window more often. Read the parent-relative
patches and the 94cbd1335d, 6b9da9dc02, f03d64f6a5 and e256cbef8a repairs.
Probe evidence on original production 49351700f3:
- Hold chat.startup and talk.catalog, click Start voice input, release both,
and await visible history: unavailable=2, Configure visible=0,
Configure including hidden=2, picker open=null. The original toBe(2)
assertion fails with expected +0 to be 2; 24.333s case, 197.12s wall.
- The pending-history unit variant fails with dropdown.open=false; the
ready-history variant passes. Extend the existing unit rather than adding
a duplicate case.
- Holding startup across the initial click also leaves talk.client.create
absent in transcript ordering, composer voice selection and both SDP cases;
all four controlled probes fail, while the settings-only sibling passes.
Validation:
- Four changed E2E files: three consecutive passes, 16/16 each;
313.04s, 293.49s and 340.02s command wall including isolated UI builds.
- One-worker dictation before/after: 11/11 each; 234.65s -> 181.54s wall,
file time 63.604s -> 48.819s, changed case 4.663s -> 3.583s.
- One-worker siblings before/after: 5/5 each; 210.09s -> 162.56s wall.
File times: ordering 13.101s -> 7.517s, voice selection 20.346s -> 13.522s,
SDP 13.446s -> 8.394s. These are cost samples, not a speedup claim.
- Existing full browser files exceed 30s because they exercise multiple real
composer/media flows and screenshots; no E2E cases or timers were added.
- Composer microphone, action and catalog owners: 80/80; 85.96s wall.
- Independent Codex autoreview: scoped-clean through P2.
- pnpm tsgo:ui passed in 85.05s; ui-e2e and ui-chat test graphs passed
in 106.07s. Targeted oxlint, oxfmt and git diff --check passed.
- Local check-changed --base origin/main passed its guards, formatting,
graph boundary and i18n, then stopped at inherited TS2741 in
src/gateway/session-row-projection.config-commits.test.ts:76: the fixture
omits the required scheduler. That untouched file is already repaired by
4bd105408c on main. The same gateway-root typecheck passes in 69.67s on
untouched origin/main snapshot 28340c41f8, materialized under this task's
artifacts with physically cloned, identical dependencies. No unrelated
source was changed. The full changed pipeline is not claimed green.
Release-note context: Control UI opens unavailable voice setup when the
microphone is clicked during chat startup, while preserving Talk admission.
* test(ui): rely on Talk readiness without a no-op startup hold
The sibling Talk cases held chat.startup only to release it immediately, which exercises no ordering. waitForTalkReady with the ready-history message is the synchronization, matching the landed e256cbef8a shape.