* fix(native-chat): offer Submit on the last question step after skipping
The last step's footer label came from the current question only, so a
skipped last question showed an outlined Skip even when earlier answers
would be submitted. Label the last step Submit whenever any question is
answered; an all-skipped prompt keeps Skip, which still dismisses.
* test(native-chat): add skipped-last-step question card fixture
* fix(files): phone file opens no longer switch the desktop's view
files.open and files.openDiff passed an absent navigation target straight
to the window, which treats absence as a host switch. Phones send none,
so every phone file or diff open moved the desktop to that workspace and
the editor. Resolve an absent target to caller at the RPC; host/all from
the CLI's --focus still move the window.
* fix(mobile): Open in session selects the diff on the phone itself
The review screen relied on the desktop switching to the opened diff,
which only reached phones still following the host. Select the opened
diff for this phone before going to the session.
* fix(mobile): select only the working-tree diff and stop when the review screen closes
* test: drop type casts the changed-code gate flags
* fix(mobile-relay): resolve on persistent 4404 and make deferral logs readable
* fix(mobile-relay): bound 4404 director resolves for a desktop that stays offline
Review follow-up:
- Resolve on the 2nd consecutive 4404 of an episode, then the 4th, 8th, 16th,
and never twice within 5 minutes per host. A sleeping laptop with a
foregrounded phone now costs 6 resolves in 30 minutes, not ~1 per 2 dials.
- If the director names the same cell and epoch, keep the normal 4404 wait:
no re-route and no immediate redial.
- The streak ends on any other outcome (including aborts), when the phone has
connected since the last 4404 (a direct-path win), or after a 2-minute gap.
- Clear the gate reprobe due time with its timer so the deferral log never
reports a stale remainingMs.
* fix(mobile-relay): double the gap between 4404 resolves while the desktop stays offline
The 5-minute floor alone set the pace (12 resolves/hour, forever). After each
resolve the minimum gap now doubles, 5 -> 10 -> 20 -> 40 -> 60 min, and
returns to 5 min after a successful relay dial or any connection. A laptop
asleep for two hours with the phone in the foreground costs 5 resolves.
* refactor(mobile-relay): namespace the supervisor's diagnostic log import to stay within max-lines
Desktop: drop IPv4 169.254.0.0/16 (and, as before, IPv6 fe80::/10)
addresses from the pairing interface list, so an APIPA or idle adapter is
never the QR's direct endpoint. When nothing else is usable the offer
already omits the direct address (Relay carries the invite; LAN-only
refuses). Among non-Tailscale candidates, an adapter known to hold the
default route now wins ties.
Mobile: a relay-paired host whose stored endpoint is link-local seeds its
logical client with a never-dialing 'reconnecting' stand-in and disables
the direct return probe, so already-paired phones go straight to Relay
instead of redialing the dead address. Relay-less hosts still dial.
* feat(native-chat): show each subagent's model, current tool and result in the roster
Subagent roster rows now carry the child's role, model, reasoning effort,
the tool it is running and the last thing it said, so a row says what the
subagent is doing and, once done, what it found. Codex children take model
and effort from the spawn call; Claude children take the model from their
own messages. A hover card shows the longer text.
* feat(native-chat): name subagent models and roles the way people say them
Show Opus 5.5 · High instead of claude-opus-5-5 · high, reusing the
model-id label and effort picker copy, and General purpose instead of
general-purpose.
* fix(native-chat): read Codex subagent model and effort from its started activity
Current Codex announces a spawn only through subAgentActivity, which carries
the model and reasoning effort the child resolved to.
* fix(native-chat): use the hover card's own spacing variant for the subagent preview
* fix(native-chat): show a subagent's reply as plain text in its roster row and preview
Its last message is markdown; the row now drops backticks, emphasis, list
and heading marks and joins lines into one readable line.
* test: remove low-value push and relay coverage
* test: delete orphaned fixture and closure support
* test: trim runner and mobile recording matrices
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
The tab bar built every tab's sheet row, including the agent preview over
each terminal's last message, on every tab snapshot and 60 s tick, and the
always-mounted closed sheet ran its own clock and row elements. The bar now
builds only the title/dot/group summary it draws; the sheet's clock, frozen
groups and detail rows live in content mounted only while the drawer is
shown.
The queued list cached each row's height by message id for the life of the
chat, so a long conversation kept one entry per message ever queued and a
requeued id could place a failed row by the height it left with. Keep heights
only for queued ids, and drop a layout a departed row reports late.