Commit Graph
1437 Commits
Author SHA1 Message Date
Brennan BensonandClaude Fable 5.1 002e975e96 Open chats move to the account you switch to, before their next message (#30955)
* fix(native-chat): an open chat moves to the account you switch to before its next message

A running chat's agent read its account only when it started, and nothing compared it with the
account a start would use now, so open chats kept answering on the old account after a switch.

The agent a chat runs now records the account its launch used, and the host's replace-before-the-
next-send check replaces an idle one whose account is no longer what a start would use. A chat
mid-reply finishes on the old account first. Claude chats follow; agents whose chats keep the
account they were created on are never compared.

A chat's model-list reads and saves now use the account it runs on, so a moved chat no longer
writes its new account's list under its first account (STA-11281).

Tracked in STA-11211.

* fix(native-chat): declare the launch-account read for the runtime layer that wires the host

* fix(claude): find custom chat history before managed-account resume

* test(claude): assign the complete custom account home

* Preserve unknown account model facts and legacy option replay

* Clarify terminal account-switch feedback in translated locales

* Keep option mutation plans checked against their contract

* Cover unknown model choices across chat consumers

* Keep consumer fixtures aligned with canonical types

* Match the mobile picker label in its consumer test

* fix: clarify terminal scope in translated Claude account settings

* Update integration tests for current session and remote client contracts

* Keep native worker replies on their receiving account

* Preserve receiving accounts across cold starts and nested reports

* Preserve the delivery receiver when reading chat commands

* Clarify native reply matching and consolidate imports

* Resolve catalog scope without re-entering conversation queues

Give owned option mutations and delivery settlement a resolved catalog input while external reads acquire scope once. Preserve account routing, catalog lifetime and current response obligations.

* Align catalog and mobile test fixtures with current contracts

Explain the existing timeout budgets and provide the idle turn identity and truthful model-only picker label in the mobile fixture.

* Align receiving-account readers and fixtures with typed contracts

* Repair account-switch fixtures and measure receiving work

* Use the checked account-home path in catalog tests

* Restore executed-option recorder context

* Control receiving catalog deadline test clock

* Align unknown-model consumer fixtures with send capture

* Consolidate session host type imports

* Align cross-version catalog fixtures with host read contracts

* test(native-chat): bind Runs through the current start authority in receiving fixtures

Main now resolves a worker start lazily through bindRun with objective and task references, and creating a Run no longer unbinds a coordinator's earlier Runs; run-use does. The receiving fixtures follow the same production owners so every original scenario, input and bound is exercised unchanged. The receiving runtime subclass moves verbatim into its own support module.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(native-chat): follow the selected account before its folder exists

A live Claude chat compared its account against the selected one only after that account's folder passed an availability check, so an account still being set up (or whose setup failed) left the chat silently answering on the previous account, and a resting chat refused its start before preparation could run. The retirement comparison and the start pre-read now ask the router for the selected route as identity, through the existing resolver purposes; catalog, create and probe reads keep checking availability. Preparation, typed launch failure and parking are unchanged.

Session History details show the account a chat was last launched under when the host recorded one, else its founding home.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(ai-vault): build the stale acquisition receipt without a type assertion

The History account case now reads the fixture receipt through the typed acquisition reader instead of spreading the record field through a cast; the three assertions and their inputs are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(native-chat): narrow the rig acquisition link before relinking it

The account-setup cases spread an optional link, which typed its id as possibly undefined; the rig always links a handle, so a guard that cannot fire narrows it. No assertion or input changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(native-chat): follow main's chat admission in fixtures and bound the History account projection

Chat admission no longer reads an experimental host setting, so the continuation-context test drops the spy main dropped in its own fixtures. The two History consumers that install a minimal chat host give their fake store the record accessor and host id the real store has, since the projection now reads the acquisition receipt. An operation-count contract holds the production History projection to one roster read and one record lookup per owned row at 10 and 100 rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(native-chat): give the declared-effort catalog fake its capture port

The declared-effort fixture builds a catalog service without the capture member the options reader asks every catalog for, which failed its desktop, catalog and phone consumers; it now supplies the inert test operation like the other fakes. The History projection contract also drops an unused map parameter.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Consume main's outcome change feed in the receiving-account index

Main's keyed journal records deliver each change after an epoch's frozen prefix as an
outcome sequence naming touched keys instead of typed rows. The receiving-account index
now re-reads those keys at their current values: queue cards by id, a deleted submission
retires its exact notice, and a deleted item drives the existing recovery rebuild, with
Stop marks still excluded. The in-process read row exposes the already-persisted
queue.cards keys and per-key deletion facts; itemIds and submissionIds keep listing every
touched key. The mobile unknown-consumer test mocks MobileSwitch as main's picker test does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 04:33:16 -07:00
Brennan Benson 0d94c0ba8f Native chat: queue messages sent while the agent works (on by default, Settings toggle, Cmd/Ctrl+Enter to send one now) (#36588)
* Advertise mid-turn queueing as queued-messages.v2

Released clients read the v1 name with an unfinished queue UI; they never
see v2 and keep sending immediately.

(cherry picked from commit f39382e090)

* Let each desktop send choose queue or steer while the agent works

The follow-up choice is now a Queue / Steer setting saved under
nativeChatFollowUpBehavior, Steer by default; the old
nativeChatQueueFollowUps switch, which every install saved as true
while queueing was dark, is retired on load. Every reader goes through
native-chat-follow-up-behavior.

While the agent works, Enter follows the setting and Cmd/Ctrl+Enter
sends the draft the other way; the alternate flips the setting before
the queue's own rules (a waiting command still queues, prompts no one
here can answer still send now) and never applies while Stopping.
Cmd/Ctrl+Shift+Enter steers the head card only and leaves the draft.
An idle agent's card reads Send, and the card menu no longer offers
"Turn off queueing".

(cherry picked from commit 55b48694e7)

* Hold Send on the phone to queue or steer a message mid-turn

While the agent works on a host that queues, holding Send opens a
Queue / Steer sheet; a choice other than the host's setting sends the
alternate, resolved against the chat as it is when it lands, by the
desktop's rule. Release and dismiss send nothing. The phone reads the
host's new follow-up setting (absent reads as Steer), and an idle
agent's card reads Send.

(cherry picked from commit db87cf51ea)

* Read the follow-up default from one place on desktop and phone

(cherry picked from commit 8e1438bfb6)

* Keep phone follow-up choices aligned with live host state

(cherry picked from commit dc9215be3d)

* Update stream and wire fixtures for live follow-up preferences

(cherry picked from commit e4d038cf0b)

* Document minimal runtime test fixture assertions

(cherry picked from commit 254f751ef3)

* Keep mobile preference tests in the mobile compiler project

(cherry picked from commit ae2aa8910e)

* feat(native-chat): queue follow-ups by default with a toggle

(cherry picked from commit 70969d6a43)

* test(mobile): assert shared preference renders on real changes

(cherry picked from commit 3f50de9b2a)

* Remove obsolete follow-up option translations

(cherry picked from commit b87b360cf3)

* Describe Cmd/Ctrl+Enter relative to the Queue follow-ups switch

The Settings description said Cmd/Ctrl+Enter sends into the running
turn, which is wrong while the switch is off. Describe it as doing the
opposite for one message, in every language.

* Show what a mid-turn phone Send does, and offer the other way only when it differs

While the agent works, the phone's Send button now shows Queue or Steer.
Holding it lists that action first with a check and the other second,
each with a one-line description, and appears only when both choices
would actually lead to different sends. A waiting command or prompts
nobody here can answer make a hold behave like a tap.

* Steer the head card once while its shortcut is held

Holding Cmd/Ctrl+Shift+Enter auto-repeats the key, which steered each
card that became the head in turn. Ignore the repeats.

* Show beside Stop what Enter does while the agent works

While a turn runs and the draft has something to send, a send control
now sits beside Stop. Its icon and label say whether Enter queues the
message or steers it into the running turn, and its tooltip names Enter
and, when it would send differently, Cmd/Ctrl+Enter. Clicking it sends
as Enter does. Stop keeps its place and nothing changes while Stopping,
with an empty draft, or before the host says it queues.

The phone and desktop now read what a send does from one shared helper
over the send's own resolver.

* Test the send keys and Queue follow-ups search against real wiring

One desktop test drives Enter and Cmd+Enter through the real composer,
transport and session to the outgoing send and checks its delivery with
queueing on and off. Settings search is checked against the capability
list this build's host advertises.

* Move the composer's send-hold check into its own helper

The pane had grown past the file length limit after the main merge.

* Disable the mid-turn Queue/Steer button whenever Send would be disabled

While an image is still loading, another device holds the input, or a send is blocked for a stated reason, the button beside Stop is now disabled and says why, the same way the idle Send button does. Before, it stayed clickable and a click did nothing.

* Hide the mid-turn Queue/Steer button in goal mode

In goal mode Enter sets the goal, so a button promising to queue or steer the message was wrong. It is now hidden there, as it already is while editing a queued message.

* Fix the Russian queue hint to say the message runs after this turn

It read as queueing until the end of this turn.

* Stub window.api without a type assertion in the Queue follow-ups settings search test

* Pass sendHeld to the composer field in tests and drop an unknown setting from the German Queue test

* Let Cmd-click (Ctrl-click elsewhere) on the mid-turn Queue/Steer button send the other way, like Cmd/Ctrl+Enter

The button shows the other action while the modifier is held, and its tooltip names the click. Only when the other way would send differently; otherwise a modified click is a plain send.

* Merge the duplicate composer-types import and give the composer's round buttons a Button size instead of restyling them

The focused code-quality check rejects importing one module twice, and the design-system check rejects rounded-full on a <Button>, which the new Queue/Steer button copied from Send. Both composer buttons now use a round icon size on the Button primitive and render as before.

* Share one window key listener across every chat's Queue/Steer button, and count Cmd/Ctrl as held only from its own key press

Each mounted chat with a mid-turn draft used to add its own window key listeners, so every keystroke did work per chat, hidden tabs included. One shared listener set now serves them all and wakes a button only when the held state really changes.

Other keys can now only clear the held state, so a dictation paste that leaves the Cmd flag on later key events no longer flips the button with Cmd up. Also tests the Ctrl-click on Windows and Linux.

* Remove the desktop Queue/Steer button shown beside Stop while the agent works

While the agent works, the desktop composer goes back to its usual
controls: Stop, with Enter and the send shortcuts doing what they did.
Enter still follows the queue setting, Cmd/Ctrl+Enter still sends one
message the other way, and Cmd/Ctrl+Shift+Enter still steers the first
queued card.

This also removes what only that button used: its Cmd/Ctrl-click
alternate, the shared Cmd/Ctrl key listener, the extra round Button
size, the send-preview value the desktop session passed to the
composer, and the button's text in every language. The phone is
unchanged.

* Put the composer's send-hold checks back inline in the pane

The separate send-hold helper only existed because the removed mid-turn
Queue/Steer button pushed the pane over the file-length limit. Without the
button the pane fits again, so it goes back to main's inline code.
2026-10-31 02:01:32 -07:00
Brennan Benson 4a8114375d Share chat option writes across desktop and phone (#36624)
* Share chat option writes across desktop and phone

* Restore main's failure notice scope for chat option picks

Held launch refusals toast again while the transport is still closed, desktop
notices follow only the chat's presentation scope so a fence or status change
on the same chat still reports, and the phone banner no longer depends on the
read record.
2026-10-31 01:56:55 -07:00
Brennan Benson 84aed85c7c Share chat options read ownership across desktop and phone (#36582)
* Share chat options read ownership across desktop and phone

* Start a new chat context's options read at once

Reads were coalesced on one queue for the whole view, so after a reconnect, provider restart, phone path change or chat switch the current read waited behind the previous context's request, up to the transport timeout. Each attachment now has its own queue: reads still coalesce to one active and one trailing request within a context, while a new context reads immediately and the old context's reply stays inert. Restores the shared option refresh contract and the reopen test to their original expectations.

* Let desktop options tests wait for the shared read queue

The shared read queue starts a read one microtask after it is scheduled, where the old desktop runner started it synchronously. The selection lifetime and context usage tests now wait for each read to start before asserting on it, keeping every original assertion, including one active and one trailing refresh. The paired server test compares transport targets by value, since the options view memoizes an equal target per environment.

* Keep chat support projections stable between options answers

Desktop and phone rebuilt the conversation, image and command support objects every render, and a host that omits commands produced a fresh empty list each time. Project them once per accepted answer.

* Import options wire types once in the selection reads performance test

* Keep chat support visible across a controller change

Replacing the selection controller, as a desktop re-pair does, cleared the last accepted support, so slash commands, the goal row and the context meter disappeared until the next options answer. On the phone, returning to a chat before the other chat answered showed fallbacks. The support stays tagged with its session and every consumer already filters by session, so it is now kept, as before the shared owner.

* Coalesce phone options rereads across turns and status changes

Each new turn or host status change re-attached the phone's options reader, so a quick run of turns sent one parallel options request per turn. These changes now reread within the current context, as on desktop: one request runs and at most one waits behind it, and only the latest answer publishes. A status change that arrives while a read is in flight now waits for that read, which the transport bounds.

* Restore the phone status wake assertion and type the burst test commands

A refused pick is dropped rather than kept as a finished operation, and the path change replaced the options record, so no revalidation read is in flight when the status wake arrives. The wake therefore reads at once, as the original test asserted. The burst test's superseded answer now carries a real conversation command.
2026-10-30 23:32:00 -07:00
Kelvin Amoaba d618a85ffd feat(mobile): redesign sheets, pickers and list screens (#36585)
Sheets slide on iOS's curve over their own height, ease when their content
changes, and paint a lighter surface with grouped rows and a drawn switch.
Create worktree, the model picker, the GitHub issue sheet, file preview,
Agent Session History and the task list take the redesign draft's layouts
at the app's smaller type sizes.
2026-10-31 04:35:07 +00:00
Brennan Benson a1f658cc32 Keep settled permission notices compact on desktop and phone (#36304)
* fix(chat): collapse settled permission notices

* Keep notice scroll addresses unique per rendered row

* test(native-chat): cover notice scroll bounds and shared classification

* fix(mobile): preserve notice summary long-press actions

* Preserve mobile notice selection and caret rendering

* Use type imports in mobile notice web tests

* Resolve real SVG test host from mobile dependencies
2026-10-30 21:24:27 -07:00
Brennan Benson 6e70de5892 fix(mobile): allow next-message model picks during structured replies (#36451) 2026-10-30 20:57:06 -07:00
Brennan Benson e9a376267c Stop attributing recovered ACP replies to outside activity (#36302)
* fix(acp): separate recovered history from outside activity

* Fix repeated recovered history divider corrections

* Compose ACP replay targets before checked settlement

* Explain ACP scaling fixture timeout

* Complete ACP fixture types and runtime English catalog

* Type exported ACP fixture warning mock

* Restore ACP history without an extra notice
2026-10-30 20:56:50 -07:00
Brennan Benson ae09815770 Support automations in Orca Mobile (#31617)
* Add host-owned automations flow to mobile

* fix: resolve initial mobile automation CI failures

* Preserve automation target identity and mobile action state

* Preserve selected automation targets through discovery and terminal launch

* Cover draft reversion after uncertain automation creation

* Preserve automation target and submitted action authority

* Preserve selected hosts and editor operations across restored state

* Refresh mobile web bundle measurements for merged routes

* Fix automation history observation and catalog scaling

* Fix automation mobile presentation and merged launch bindings

* Refresh measured mobile bundle sweep and correct automation test inputs

* Move real-module test loads to collection and consolidate imports

* Use typed row access to count worktree ownership reads

* Refresh selected automation history on matching host events

* Fix automation contract types and merged test imports

* Fix automation theme updates and committed history ownership

* Update folder terminal contract fixtures for canonical host catalogs

* Consolidate historical session activation fixture imports

* Repair automation contract project boundaries and owner type ports

* Preserve acquired automation folder owners and fix integration lint

* Retain terminal pane owners captured at connect

* Use checked pane manager context in owner retention test

* fix: adapt merged editor and terminal test contracts

* fix: preserve captured automation targets and terminal owners

* fix: honor explicit automation source clears and refusal contracts

* test: construct terminal transport mocks with checked types

* test: supply retained-owner context in terminal fixtures

* test: align terminal fixtures with callable mocks and store ports

* fix(mobile): localize automation screens and run details

* fix(mobile): use automation translations in context

* fix: preserve editor owner checks and automation repair guidance

* fix: reconcile captured workspace contracts after main sync

* Repair automation integration tests and retained target diagnostics

* Keep test support owned by registered unit roots

* Expose full blocked automation run reasons in menus

* Anchor mobile bundle envelope to measured route sweep

* fix(mobile): localize coded automation run failures

* fix: preserve automation decisions and captured resource ownership

* fix: qualify remaining automation workspace owner consumers

* fix: preserve resolved watch and child editor owners

* fix(editor): share qualified worktree watch ownership

* fix(editor): reuse immutable repo ownership lookup

* fix: preserve host ownership without duplicate catalog scans

* fix: align automation destination host types and ratchets

* fix: align mobile bundle envelope with measured sweep

* fix(mobile): resolve automation setup policy before save

* test(mobile): qualify reconciled automation target inspection

* fix(mobile): keep server setup consent within its authority

* fix: accept narrow qualified workspace owner snapshots

* fix: reuse qualified owner state for workspace directories

* fix(mobile): localize known automation orphan reasons

* Correct automation controller and Chat harness types

* Refresh editor requests after paired host restart

* Refresh measured mobile web bundle envelope
2026-10-30 20:40:04 -07:00
Kelvin Amoaba 97582248e7 feat(mobile): rebuild Home around what needs you, with actions pinned at the bottom (#36520) 2026-10-31 02:47:49 +00:00
Kelvin Amoaba 5e6c0494b3 feat(mobile): compact top bar, bottom search and filter chips (#36535)
* feat(mobile): compact top bar, bottom search and filter chips

Every list screen gets one compact bar (back, centred title, at most two
buttons, the rest in a ⋯ pull-down), with search moved to a wide bar at
the bottom and filters as chips. The workspaces page shows the host name
at the top of the list and folds it into the bar as you scroll.

* test(mobile): pass the Tasks bar's accessory in the host subtitle test

* fix(mobile): stretch filter chips to fill the row; follow moved header controls in render checks
2026-10-31 02:47:30 +00:00
Brennan Benson a62f1e4955 Keep declared default effort visible for every chat agent (#36455)
* Show declared default effort consistently across chat agents

* Leave unmappable reported effort defaults unknown

* Separate default effort context from launch policy

* Cover configured effort declarations without changing current input

* Fix declared effort context through live options readers

* Load declared effort fixtures outside test callbacks

* Combine host catalog test imports
2026-10-30 18:28:43 -07:00
Kelvin Amoaba 36a9024a0b fix(mobile): draw Claude Code's ⏵⏵ mode marker in the Android terminal (#36516)
* fix(mobile): draw Claude Code's ⏵⏵ mode marker on Android terminals

Android ships no font with U+23F4-23F7, so the terminal drew boxes.
Bundle a 664-byte Noto Sans Symbols 2 subset, inline it in both
terminal hosts, append it to the Android font stack only, and load it
with the Nerd font before the WebGL atlas first paints.

* fix(mobile): spell the terminal font probe glyphs as escapes

* refactor(mobile): tidy terminal symbols font wiring
2026-10-31 01:16:24 +00:00
Brennan Benson 852391da0f Show a details card when tapping phone session tabs (#36395)
* feat(mobile): tap the session title to see its full name, path and host

A sideways phone caps the title at 160pt beside the tabs, so long worktree names were cut off with no way to read them. Tapping the title now opens a card under the top bar, built like desktop's tab hover card, with the full name, the worktree's path and the host. It fades and slides in over 150ms (fade only with Reduce Motion), and any tap outside closes it.

* fix(mobile): keep the worktree-name reset effect unchanged; type-only View import; lazy card animation value

* fix(mobile): preserve title card bounds and execution host identity

* test(mobile): complete title card platform mocks

* fix(mobile): separate detail card from title trigger

* style(mobile): apply pinned formatter wrapping

* fix(mobile): reopen session details during the closing animation

* style(mobile): wrap the session title imports

* Keep session title activation on one target through card exit

* Host session details above page navigation and retain input scope

* Keep the title target clear as its layout changes

* Clarify title-card types and observer cleanup for checks

* Keep mobile title-card requests and visual exits under one owner

* Make the existing mobile title an explicit web click target

* Keep mobile title details nonmodal through their visual exit

* Follow the active mobile palette in session title details

* Use array syntax for title card motion fixture

* Localize the mobile workspace details hint

* test(mobile): cover title card release to a higher sheet

* Refresh measured mobile web chunk envelope

* Show session tab details on phone taps

* Keep phone tab details current through layout and handoff

* Refresh cached phone tab footer colors with appearance

* Use checked fixture state and top-level test owner types

* Supply app visibility in the title card Surface fixture

* fix(mobile): keep empty terminal detail titles readable
2026-10-30 17:57:28 -07:00
Kelvin Amoaba eb7631ccc5 fix(mobile): keep Markdown editor selection visible deep in long files (#36505)
* fix(mobile): keep Markdown editor selection visible deep in long files

iOS WebKit stopped drawing the selection highlight and handles about two
screens into the rich Markdown editor because the editable element was
scrolled by its non-editable host. Make the editable element scroll itself.

* test(mobile): find the editor's document rule by a property it still has
2026-10-31 00:45:04 +00:00
Jinjing 70e8ef7f3b fix(i18n): translate recent desktop and mobile copy (#36489) 2026-10-30 16:16:54 -07:00
Kelvin Amoaba 17cace4f22 fix(mobile): lead workspace-list agent rows with the conversation name (#36464)
* fix(mobile): lead workspace-list agent rows with the conversation name

* fix(mobile): name a same-tab child once its parent row is gone

* refactor(runtime): share the structured chat tab id parser

* test(runtime): build the row-name summary without a cast

* perf(runtime): read each worktree's session once per worktree.ps pass
2026-10-30 22:07:24 +00:00
Kelvin Amoaba a079f51991 feat(mobile): unify corner radii across the app (#36437)
* feat(mobile): give every corner one of three shapes

Corners had drifted to 17 different radii, so a screen mixed 6 pt
buttons, 14 pt cards, 12 pt groups and 4 pt badges. Every corner now
comes from the shape of what it is:

- control (12): anything you tap — buttons, icon buttons, fields,
  pickers, segmented controls, key caps.
- surface (16): anything that holds content — cards, groups, sheets,
  banners, code boxes. Dialogs and the composer box use floating (24).
- pill: badges, chips, status pills, dots, avatars and the composer's
  own round buttons.
- tile (10) for icon squares and mark (4) for inline code and check
  squares; nested shapes take the parent's radius minus the gap.

Every rounded style also asks for the continuous (squircle) corner
curve; iOS draws it, Android and the web ignore it.

* fix(mobile): keep circles and pills on the circular corner curve

The continuous curve squares off a corner radius that reaches half the element's size, so the FAB, dots, avatars and the composer's round buttons stopped being round on iOS.

* fix(mobile): put the anchored detail card on the surface radius

* fix(mobile): keep the circular curve on unclipped bordered styles

React Native strokes an unclipped visible border on a circular path while it fills the background with the continuous curve, so the two edges drifted apart at the corners.
2026-10-30 21:27:30 +00:00
Brennan Benson 6a9b1d786f feat(mobile): tap the session title to see its full name, path and host (#30389)
* feat(mobile): tap the session title to see its full name, path and host

A sideways phone caps the title at 160pt beside the tabs, so long worktree names were cut off with no way to read them. Tapping the title now opens a card under the top bar, built like desktop's tab hover card, with the full name, the worktree's path and the host. It fades and slides in over 150ms (fade only with Reduce Motion), and any tap outside closes it.

* fix(mobile): keep the worktree-name reset effect unchanged; type-only View import; lazy card animation value

* fix(mobile): preserve title card bounds and execution host identity

* test(mobile): complete title card platform mocks

* fix(mobile): separate detail card from title trigger

* style(mobile): apply pinned formatter wrapping

* fix(mobile): reopen session details during the closing animation

* style(mobile): wrap the session title imports

* Keep session title activation on one target through card exit

* Host session details above page navigation and retain input scope

* Keep the title target clear as its layout changes

* Clarify title-card types and observer cleanup for checks

* Keep mobile title-card requests and visual exits under one owner

* Make the existing mobile title an explicit web click target

* Keep mobile title details nonmodal through their visual exit

* Follow the active mobile palette in session title details

* Use array syntax for title card motion fixture

* Localize the mobile workspace details hint

* test(mobile): cover title card release to a higher sheet

* Refresh measured mobile web chunk envelope
2026-10-30 13:48:10 -07:00
Brennan Benson f06399f5fc Keep refreshed Linear Tasks rows current (#34591)
* Keep Linear refresh results authoritative in Tasks

* Preserve scoped Linear edits through read settlement

* Complete Linear consumer entry and source teardown

* Fix scoped Linear read lifecycle and external refresh

* Complete Linear terminal reads and causal refresh dispatch

* Cover cached Linear read reconciliation under pending writes

* Fix cold Linear lookup invalidation

* Make Linear regression fixtures deterministic

* Align Linear test fixture naming with lint policy

* Consolidate Linear test imports

* Keep Linear saved publications coherent through React replay

* Preserve confirmed Linear accounts through unavailable checks

* fix(linear): retire recovered credential errors on acknowledgement

* fix(linear): keep runtime cache reset on account acknowledgement

* Fix Linear CI fixtures after final main integration

* Correct Linear mobile fixtures and scoped lint annotations

* Keep the mobile fixture assertion annotation on its expression

* Fix Linear static contracts and integration test boundaries

* Complete audited Linear static gates and preserve no-op selection

* Separate Linear selection decisions from observations and preserve create completion

* Name exported Linear fixture mock types with public annotations

* Preserve exact submitted drafts through create settlement

* Read draft retention mode from its committed snapshot

* Publish the current closing draft after queued form replay

* Type Linear create attempts from their form owner

* fix: supply complete task creation test fixtures

* fix: complete checked Linear creation metadata fixtures

* test: complete Linear dialog fixture composition

* test: use host-qualified workspace keys for board sync fixture
2026-10-30 12:51:35 -07:00
Brennan Benson bd82832a53 fix(native-chat): keep model picker choices stable during discovery (#36113)
* fix(native-chat): keep model picker choices stable during discovery

* Preserve unknown model inventory across session option reads

* Preserve explicit picker choices and discard refused opens

* Exercise recorded empty ACP inventory through host and picker

* test(chat): align mobile picker contracts with descriptive inventory

* perf(chat): skip effort fallback scans when already resolved

* test(native-chat): align synthetic model consumer expectations

* test: preserve accepted launch seed payload contracts
2026-10-30 12:35:02 -07:00
Jinwoo Hong a1f7f97671 Orchestration v3: coordinators end their turn and Orca wakes them (#36137)
* fix(orchestration): keep a terminal's mail from being consumed by another terminal, and let settled structured workers take further tasks

A plain orchestration check consumed the named terminal's mail whatever terminal ran it, so a
coordinator checking a worker's handle took the worker's message. A consuming check from a
terminal whose own live pane is a different terminal's is now refused; --peek and --all still read
it without consuming.

worker-start --terminal and dispatch --inject routed a structured worker (structworker_ handle) as
a terminal and failed with terminal_unsupported_for_agent_session. Any agent-session party now
takes its task as a send into its session, while a structured worker keeps the pane and process
authority its first Dispatch had.

* fix(orchestration): fence check by live terminal incl. acks; defer injecting structured workers

Review fixes for the mail fence and structured worker reuse:
- The check fence compares the caller's and the mailbox's live terminal process instead of
  recorded panes, so exited terminals keep the old behaviour and two processes sharing a
  recorded pane are told apart. It also covers --ack in every read mode. The caller lookup is
  shared with the lifecycle caller fence.
- dispatch --inject to a structured worker stays refused as before: an injected Dispatch takes
  no custody, so releasing the first Dispatch could close a session working on the second.
  worker-start --terminal reuse transfers custody and stays supported.
- worker-start decides pane-less chat authority from the resolved party and passes the session
  down, so delivery and next commands no longer re-derive it from the address spelling.
- Receipts name an agent session, not a chat.

* fix(orchestration): an exited caller's env pane names no caller

The caller lookup fell back to the env pane key whenever the env handle was not live, so an
exited terminal's pane resolved to whatever terminal now occupies it, and a tmux worker's own
check was refused. The pane fallback now applies only when the env handle is not proven exited.

* fix(terminal): keep surviving terminals streaming to main after a restart

Main now attaches every live local daemon session it adopts at startup,
not only ones a window pane or remote view is showing, and re-attaches
after a daemon endpoint drop. The attach snapshot seeds main's screen,
tail and title, and an attached-but-silent agent gets an output clock so
readiness can see it has gone quiet. Waits on a survivor main could not
attach fail at once instead of timing out.

* fix(terminal): restore only pane-less streams after endpoint loss; one attach state

- Endpoint loss re-attaches in main only sessions no renderer view reports; a pane restores its own.
- The attach hide skips views mid-attach and leaves a pane's own hidden claim alone on failure.
- One per-session stream state (attaching, attached, lost) replaces three sets and is forgotten on exit.
- Waits retry the attach before failing, including after a failed re-attach.
- The output clock starts wherever a reattach result is seeded, so pane reattaches get it too.

* refactor(terminal): attach survivors at inventory adoption only; waits on unattached survivors fail at once; one ptyId output clock

* test(e2e): scope the restart attach spec's terminal listing to the unopened workspace

* fix(terminal): narrow survivor attach: waits behave as on main, one quiet clock per generation, keep main's hidden mark on failed attach

* Teach the orchestration guide when to hand off and to end the turn after dispatch

* Rewrap a messaging reference line

* Keep the original placement default and skill trigger; keep the accuracy fixes

* Point DAG retries at --retry-of and drop the last blocking-wait instruction

* Check the served orchestration guide by its new worker heading

* Apply council review: best-effort wake, full completion rule, restored safety rules, fixed scope and settled wording

* Say when the orchestration skill applies, and prefer own subagents otherwise

* Name the polling, steering, checkout, and worker fan-out habits to avoid

* fix(orchestration): wake a coordinator whose turn ended while its program still reports working

Claude Code keeps its OSC 7501 report on working while an agent-teams
teammate is alive, even after the lead's own turn ends. The mailbox gate,
idle edges and tui-idle all read that report, so worker mail was stored and
never typed. A hook turn end newer than the program's working report now
counts as rest; hook rows re-classify the PTY so the existing idle edge
delivers. Agent Teams panes now join their claude hook rows.

* fix(orchestration): compare the lead's own turn end, not the row's receipt

A child's hook restamps the row's receivedAt while the lead's turn is still
the old one, which could mark rest under a newer program working report.
Use the lead's turn-end stamp on this runtime's clock, after the latest input.

* feat(orchestration): a consuming check marks the batch it returns as handled

* Say why watch scripts and open waits block the wake

* feat(orchestration): release settled workers automatically after a grace period

* fix(orchestration): use checked row reads for delivery cursors

* fix(orchestration): trust a live own-process turn end instead of comparing clocks

Drop programActivitySince and the turn-end clock mapping: replays and SSH
host clocks made the comparison unreliable. A Claude lead counts as at rest
under a program working report when its hook turn end is a live transition
from this pane's host and launch, past the existing input and respawn floors.

* test(orchestration): drop cast in ack no-op check

* test(orchestration): seed legacy outstanding batch for held chat nudges

* test(orchestration): built CLI check hands its batch over

* test(orchestration): annotate unchanged casts and stub the keep item in tab menu tests

* fix(orchestration): let real input, explicit release and host releases converge with automatic release

- Record worker takeover at the owning runtime when it accepts UI input, before the bytes reach the PTY.
- Run remote attachment releases through the same per-resource single-flight as local ones.
- Apply the confirmed-release home projection when host observation reports a host-side release, and carry the host deadline in fleet snapshots.
- Prove restart recovery with a file-backed database reopened by a fresh runtime.

* test(orchestration): classify the keep RPC's worker fields instead of counting methods

* fix(orchestration): checked delivery reads and observer and recovery help

* refactor(orchestration): end a check when it hands over a batch; wake rides the wait result

* fix(orchestration): refuse an automatic close after real input, join remote releases, converge the home

- An automatic close checks the terminal's last driving-input time right before closing and keeps a worker someone typed into after worker_done; typing itself does no orchestration database work.
- Remote releases share the per-resource single-flight with local release, so a home worker-release joins the host timer's close.
- Host fleet snapshots and federationShow report released and the pending deadline; the home applies the existing release projection inside its observation fence.
- Real restart tests: a file-backed database reopened by a fresh runtime releases a missed deadline once and finishes interrupted requests.

* fix(orchestration): receipt a shared wake batch on arrival and report the applied Run ack

* fix(orchestration): deliver the wake to a working coordinator; agents queue mid-turn input

The wake was typed only into a live idle pane, so a Claude lead whose program
status stayed working (teammate alive) never got it. Agents queue or steer text
typed mid-turn, so a pane takes mail when live idle or working; dialogs,
permission prompts, exited agents, unsettled panes and cold-parked Enter still
hold it. Drops the held-batch Enter deferral and the per-turn-end hook logic.

* fix(orchestration): record each remote release request before joining, publish archives only through the conditional commit

- Each remote release caller records its own request before joining a close under way, and the close decides on the current row, so an explicit release that overlaps the host timer clears the automatic deadline.
- Remote capture publishes its archive through commitWorkerTerminalArchiveForRelease, so a retain during capture leaves no stale archive for worker-read.
- Remote worker-show projects the fenced host deadline and its next action.
- The input guard lives in its own module instead of the scheduler.

* feat(orchestration): start a worker in one step; worker-start creates the coordinator's Run when none is bound

worker-start --spec now creates and binds a Run for a root coordinator with
no bound Run, through the same path run-create uses, and names the Run it
created or joined in every receipt. Workers on a Dispatch keep starting
helpers in their own Run and never get a new one. A new CLI against an older
runtime runs run-create and retries; old CLIs need no change.

* fix(orchestration): drop the older-runtime fallback; check the spec before a Run is created

The CLI fallback matched a refusal text the client decorates, could not
prove the caller was a root coordinator on an older runtime, and recovered
an inner run-create under the worker-start command. Older runtimes keep
their refusal and the guide says to run-create first there. The prompt
budget check now runs before worker-start can create a Run.

* Route report-back requests to coordinators, complete the steer command, and label the wake loop branches

* Say workers are done only when worker_done confirms, wait for helpers to settle, and let bare-shell workers exit

* Route report-back requests away from handoff and steer supervised workers through their mailbox

* docs(orchestration): teach auto-handled check, retry-request and inbox recovery in the guides

* Describe the mid-turn wake in the messaging reference

* docs(orchestration): say terminal workers are released 2 minutes after worker_done

- The guide's Completion section, the reuse recipe and the recovery reference now describe the automatic release and its autoReleaseAt deadline: reuse or worker-retain before it; explicit worker-release still works and is required for chat workers and workers without a deadline.
- The worker preamble says the terminal stays available until Orca releases it, about 2 minutes after worker_done unless retained.
- Regenerated the bundled guides.

* feat(orchestration): receipts say when to end the turn

* feat(orchestration): tell the coordinator when a worker stops without worker_done

* test+docs: worker stop reports

* fix(orchestration): judge the empty-check stop with execution-host verdicts

* test: drop casts from worker stop tests

* Say that report-back requests still mean end the turn

* Say that report-back requests still mean end the turn

* fix(orchestration): stop reports wait for children, keep their Dispatch, and relay intact

* fix(orchestration): a stop belongs to the Dispatch active when it was seen; restored stamps announce nothing

* fix(orchestration): never say to stop while a remote worker runs

* Shrink the orchestration guide to the end-state workflow

* fix(orchestration): stop reports quote the agent's last words, or the screen for errors and prompts

* fix(orchestration): withhold the stop while chat failure mail is off

* test: a clean finish quotes the agent's last words

* fix(orchestration): stop asking workers for heartbeats

Workers are no longer told to send periodic heartbeats. A heartbeat that
still arrives from an older worker or peer only records last_heartbeat_at:
it is stored already handled, so it never lands in a coordinator inbox and
never wakes a coordinator or a check --wait. Removes the stale-heartbeat
warning and the heartbeat interval plumbing that only fed the preamble.

* fix(settings): remove the worker heartbeat controls

The Worker heartbeats switch and Heartbeat interval field only changed the
worker preamble text, which no longer mentions heartbeats. Saved values are
dropped on load as retired settings.

* fix(orchestration): wake a coordinator that reports program status but never sets a title

Program status only re-classified a pane that had a title, so a titleless
agent (agy) never got a live status and the wake gate refused it.

* fix(orchestration): a new Run no longer cuts a coordinator off from its earlier Run

* test(orchestration): drop heartbeat-batch cases the handled heartbeat row removed

* fix(orchestration): redact capabilities from a stop report's quoted output

* fix(orchestration): never wake a mailbox for a heartbeat

One rule at the runtime notification entry replaces per-call-site read
checks, so mutation replay and federated control-mail import stay silent
for heartbeats too.

* Shrink the orchestration references and worker preamble to the end-state workflow

* Name the older-Orca bind refusal as worker-start prints it

* Owner-fence test: a refused foreign ack changes nothing, whatever the worker's own check already handled

* Integration: drop the duplicate consumingCheck after merging #34043 and #35293

* Integration: await the worker-start next receipt before naming its Run

* Apply review round 1: drain to zero, release without auto-release, retry after stop, Run before a DAG

* Apply review round 2: start ready DAG Tasks, block when no failure wake, replay sends by request ID

* Apply review round 3: one receipt-based wait rule for starts and wakes

* fix(orchestration): a worker stopped without reporting needs action, and stop keeps its output

worker-list projected a stop-reported attempt as live, in_progress, no action. It now
projects finished_unverified with a worker-read recovery until mail reaches the worker.
worker-stop closed the terminal before anything archived it, so release reported the
archive unavailable; stop now archives the output first.

* Revert "Owner-fence test: a refused foreign ack changes nothing, whatever the worker's own check already handled"

This reverts commit 336ff91737.

* Revert "Merge #34043 (terminal mail guard, chat worker reuse) into integration"

This reverts commit 9c01b1a06e, reversing
changes made to d4b0c6c5f7.

* Revert "Merge #33720 (restart: attach surviving terminals) into integration"

This reverts commit d4b0c6c5f7, reversing
changes made to 53f9735bfe.

* Integration: restore #35293's check-methods after removing #34043

* fix(orchestration): bound the pre-stop archive and keep it through retain

* fix(orchestration): a failed pre-stop archive never blocks the stop

* fix(orchestration): answering a question says to end the turn while the worker runs

* fix(orchestration): a settled worker whose terminal moved owes nothing

* Cut the orchestration guide to what Orca does not already enforce or explain

* Drop the terminal-send recovery the CLI already prints

* Restore a short never-do block: no polling, no terminal steering, no hand-made checkouts

* Trigger on named-agent review requests, define failure in specs, show the reuse commands

* Restore six guide rules from the cut review and drop the preamble heartbeat block

* Integration: drop the removed heartbeat interval from preamble tests

* Drop the outside-Orca wait and run-use lines; Orca's errors teach both

* Release finished chat workers like terminal workers unless the user touched them

A finished chat worker now closes ~2 min after its accepted worker_done, like a
terminal worker. Clients report a touch when a chat is on screen at rest (opened
idle, or its turn ends on screen); the owning host keeps a finished worker's
chat on that report, until its automatic release commits the archive and closes
in the same tick. Chat workers arm only while every connected client advertises
the touch capability; old clients keep today's manual release.

* Decide an automatic chat close in the session lane, recheck clients there, re-touch after reconnect

The automatic close now asks the database in the chat's session lane right before
Stop: a touch until then keeps the chat, and a client that cannot report touches
(joined during the grace or after a restart) sends it back to manual release.
Touch reports wait for a read chat, so a reconnect re-reads and reports again.

* Keep explicit chat releases eager and re-touch a desktop chat after lost contact

* Resolve a chat touch by durable worker identity, so a closing chat's hidden tab stays touchable

* Keep the mobile touch report free of route and app-state hooks: shown counts as seen

* List workerChatTouch's identity fields and the close's optional admission in their census tests

* Release a settled remote worker from the home when its host predates automatic release

* Replace Keep Worker Open with an auto-close setting, and tell agents when an older server needs a Run

The coordinator's runtime decides whether finished workers close: it gates local arming, the
settlement ack's autoRelease opt-in to a remote host, and the home deadline for older hosts.
worker-start and run-create name an older server's one-Run-per-coordinator behaviour instead
of failing or rebinding silently.

* Escalate a parent's prompt or error even while its helper is open

* Report a chat touch when a worker chat is opened while working, and on each turn edge

* Record worker takeover when the host admits a person's chat send, so mobile sends keep the worker

* End a reported worker stop when the worker resumes, not only when Dispatch mail arrives

* Recheck a chat mail notice at admission so mail a check consumed starts no turn

* Type the resumed-turn stop test's pane move directly

* Keep the stop decision in an empty check, report muted chat failures as stops, and bind a new Run only once a start passes preflight

A start or reply receipt now sends the caller to drain its mail with check instead of ending its turn, so a mid-batch answer cannot skip a later report and a replayed receipt carries no stale stop. With chat error mail off, a failed chat request still reports a plain stop through the existing stop report path. worker-start creates and binds its Run just before the Task and Dispatch, so a start refused in preflight leaves no Run behind. worker-release help no longer says chats never auto-release.

* Reuse a Run a parallel first start bound, refuse dependencies before creating a Run, and relay a paired-server worker exit home as a stop report

* Read a reported worker stop against live agent status instead of recording resume observations

A stop report is mail the coordinator reads once. Whether a worker shows as
finished now comes from its live status: a fresh working agent status (local
pane, chat session, or the execution host's fleet snapshot) outranks the
report, so nothing needs clearing on resume.

* Drop agent steps Orca already covers: start receipts say Orca wakes you, a check asks for another only when a capped batch leaves mail, workers get no mail-check or ack lines, and chat errors always report with the exact error

* Keep the home's remote auto-release deadline until the host answers, and let a retain win at the send

Claiming a due deadline postpones it instead of moving it to a releasing state, so a restart or
a failed attempt runs it again; the release send rechecks the deadline with no await before it.
A host that cannot be asked at settlement still gets the deadline, and a host upgraded since
settlement is released by the home, since it never armed its own.

* Close a finished worker automatically only if the user never opened it

Seeing a worker's terminal or chat now writes the user's Keep record (owned,
retained) on its host, at any point before its close is admitted, so a worker
seen while it worked is never armed and a pending automatic close is cancelled;
the coordinator can still release, stop or re-engage it. Desktop reports from
the on-screen attention scan for every on-screen terminal pane and chat once a
present user is on that workspace; mobile reports the tab a session opens on
and each tab switch. The weaker chat-only touch hooks are removed. A chat send
admitted after the automatic close committed its archive now keeps the chat.

* Show only live facts for a worker that reported a stop

A stop report is escalation mail that wakes the coordinator once. worker-list
and worker-show no longer project it as finished_unverified with a recovery
action, so the live-working override that cleared that label goes too.

* Report a paired-server worker's process exit home even while its ask or check --wait is still registered

* Report a seen worker until its host records the keep, including chats shown before custody and mobile auto-selections

The touch reply now says pending while a structured worker's custody row is
not yet recorded; desktop and mobile keep a subject unreported after a
failed or pending reply and retry on the next scan, snapshot or reconnect.
Mobile reports whichever terminal or chat is displayed, tapped or selected
by a snapshot, instead of only the first per workspace.

* Record a person's chat send or command takeover inside the session lane

Takeover moves from the RPC wrappers into the host's in-lane acceptance
of userSend sends, /compact and /clear, so a close queued behind an
accepted send cannot admit before the keep, including during /compact's
handover wait. Host orchestration sends never set userSend.

* Say which stop reports a deliberate wait suppresses

* Align merged tests with the shorter preamble and the fixed start hint

* Retry an unrecorded mobile worker touch when the phone reconnects

* Drop the removed worker check line from the CLI boundary test

* fix(orchestration): wake a coordinator that survived an app restart

After a restart, main typed the mail wake only into an agent whose status it
had seen live since starting, so a coordinator whose turn had already ended
never woke. At reattach, take the agent's own last hook report, which the hook
server restores from disk and from its offline spool, as that observation while
an agent still holds the surviving process.

* fix(orchestration): restore the lead's own turn, hold a restored draft, fence respawns

Read the lead agent's turn from the restored report so background work does
not hide an ended turn, keep the wake out of a composer that still holds text
typed before the restart, and drop a restore that a respawn has overtaken.

* fix(orchestration): restore a reattached status only from a current screen without a draft

The whole-screen accessor hides a model the provider still owns after attach, so a
draft there read as none. Read the screen the way wait gates do, provider image
included, and decline the restoration when it is unavailable.

* fix(orchestration): restore a reattached status without reading the screen

After a restart main has no record of typing, so the existing draft hold cannot
apply; a screen read here could miss a draft and, when slow, strand the
coordinator for good. A draft left before the restart now meets the same rule
as an abandoned one.

* fix(orchestration): let a slow foreground probe still restore a reattached status

A probe answering after the interactive two-second bound was dropped for good,
stranding the coordinator. Restoration has no caller waiting, so it takes the
real answer; the existing fences still guard application.

* test(orchestration): mark the slow foreground probe as fake-clock driven

* Report a terminal worker whose agent died while its shell lives

A killed agent sends no stop hook and its shell keeps the PTY open, so its
Dispatch stayed open and the coordinator was never woken. The shell's
command-finished already retires the PTY's launched-agent authority; the
panes it retires now go to the worker stop reporter as an 'exited' stop
(same mail and wake as a PTY exit, once per Dispatch, none once settled).

* refactor(orchestration): key mail, waits and settle checks by terminal

Reapplies #34056 on the integrated orchestration work: mail delivery, the
settle recheck and terminal waits are keyed by ptyId instead of the window
pane, deleting the pane-keyed leaf lane and the headless-only PTY lane.

Keeps #34706's delivery rule (a terminal taking input, idle or mid-turn,
gets the wake; dialogs, permission prompts and unsent drafts hold it; the
cold-park fence still defers a parked Enter) and #35274's multi-Run
coordinator mailboxes.

* fix(orchestration): keep best-effort delivery's catch; stage the remount e2e

deliverForHandle keeps the integration branch's catch: ownership resolution
still reads SQLite, and a notification queued before teardown must not throw.

The remount e2e now asserts each stage on its own (mid-turn mail before the
workspace opens, the wait across the remount, mail after it), since #34706
types mail mid-turn and the old single mail check could pass before the
remount happened.

* refactor(orchestration): settle a new terminal wait from its first reading

A wait now keeps the PTY record it resolved, and nothing runs between the
first evaluation and the waiter's registration, so the second evaluation
re-read the same evidence. Starts the poll from the first verdict instead.

Deletes the leaf wait-result builders the leaf lane left without callers,
and adds a unit test that a tui-idle wait survives its pane remounting
(the e2e cannot order the wait's registration before the remount).

* Report a dead worker agent only once its shell is proven alone

A command-finished marker alone does not prove the launched agent exited: a
nested interactive shell in a live worker emits the same marker. The exit
report now waits for the execution host's shell-alone proof and is fenced to
the Dispatch and launch seen at the marker, so a relaunch in the pane is not
reported by an older completion. It no longer hangs on launch-authority
retirement, so a nested completion that retires metadata does not stop a later
real death from being reported. The agent-exited fact feeds the same path for
shells without OSC 133.

The shell-alone report and a paired-server worker's PTY exit share one exit
entry point and key, so the Run home gets one report per process.

* fix(orchestration): resolve a terminal's mailbox across every pane that shows it

Two panes can show one PTY; ownership read only the first listed pane, so a
Run bound to the other was never woken. The mailbox terminal now carries
every pane alias and ownership, discovery and the delayed-Enter recheck
consult them all.

* Report a killed worker agent from its launch's exit receipt

The launch command now ends with a per-shell marker the shell prints once
the agent returns, however it ended. The execution host scans it before
thinning (main and daemon), checks it against the PTY's current launch and
incarnation, and reports through reportWorkerExit. A nested shell has no
receipt and a relaunch names a new one, so the shell-alone inference is gone.
A later local PTY exit reuses the same exit message id, so it settles the
Dispatch without a second report.

* Revert "Revert "Merge #33720 (restart: attach surviving terminals) into integration""

Reapplies survivor attach (72b3b79fd3, fe906ea2a2, f46777ba18) so the
#33720 merge that follows carries it; integration reverted it in 2f945fa715.
The output clock now feeds v3's terminal-keyed wait path; the leaf lane it
also fed is gone in v3.

* test(orchestration): give exit-path DB stubs the remote-attachment lookup

The paired-server exit relay now asks the Orchestration DB for an active remote
attachment on every local pty exit; partial stubs without it threw.

* Report a worker killed after a restart from its Dispatch's launch commitment

The exit receipt ID is now derived from the launch-token hash a Dispatch
persists, so a PTY reattached after restart (no launch token in memory)
accepts its receipt when the pane's active Dispatch committed that launch
in the same shell process.

* test(orchestration): stub main's session-dispatch presentation read in the stale-leaf DB

Main's projection scope now reads listSessionDispatchesForPresentation on every
projection; v3's hand-rolled stub predates it.

* test(orchestration): drop the stale-leaf stub key integration's merge now supplies

* test(orchestration): align main's new tests with integration's mid-turn mail, admitted close and nameless worktrees

Main's titleless-turn test assumed mail waits for Stop; v3 types it into a working agent.
Main dropped the --name requirement, so that preflight case now fails on the missing repo.
The evict close now forwards the session lane's admitClose.

* perf(orchestration): read the next federated release deadline through its partial index

The armed-state filter alone cannot use the non-null partial index, so every rearm walked retained federation history.

* perf(terminal): keep unviewed restart survivors to the daemon's live window

Main now attaches every surviving terminal at startup; each mirror took the full
5,000-row depth with no viewer. A survivor nobody views keeps the 1,000 rows the
daemon itself holds, and grows to full depth from those rows once a view subscribes.

* chore(orchestration): clear check:changed findings on the main merge

Format a listing statement, prune the flaky-pattern baseline, and justify or remove the
test casts the changed-code gate flags.

* Revert the unviewed-survivor mirror cap: it can lose desktop history after a restart

A capped survivor mirror is still served as complete history to desktop recovery, and a desktop pane
added after inventory never lifts the cap. Restart memory for unviewed survivors moves to a follow-up
that defers the screen model instead of truncating it.

This reverts commit 4ea934ca7f.

* Key main's new null-agent idle-wait test by terminal, as integration's waits are

* fix(orchestration): type mid-turn mail only into a recognized agent

An unrecognized terminal's working verdict may be a running program reading stdin,
so null-agent panes keep waiting for quiet before the pointer is typed.

* Remove killed-worker exit receipts from orchestration v3

The launch-bound receipt added a visible printf to every agent launch line. Owner decision: ship v3
without killed-worker detection (behaves as main does today) and revisit it later, e.g. by watching the
agent's hook-reported process.

This reverts merge b9a30b6e74.

* Stop re-arming a delivery recheck once the quiet window has passed

A refusal that outlives the quiet window (an unrecognized terminal still reading as working) is not
time-bound, so a 50 ms recheck spun forever. The next output, title or mail edge rechecks it.

* Keep retrying deliverable mail past the quiet window; gate mid-turn delivery on terminal agent identity

A refusal outliving the quiet window can wait on a hook final-frame deadline or a late foreground
recognition, neither of which emits a delivery edge, so poll slowly while that terminal still has
deliverable mail and stop once none is pending. Mid-turn delivery now asks whether the terminal agent
is recognized at all, not whether it has readiness rules, so a recognized reusable agent keeps it.

* Keep structured-agent-session.ts within the 300-line cap

* fix(orchestration): arm delivery rechecks only for actionable delivery work

The recheck predicate now counts persisted pointer reservations awaiting
recovery as well as selectable new mail, and gates every recheck (quiet
window, post-quiet, and holds) on it, using the canonical output clock.

* Check the served orchestration guide by a heading the v3 guide keeps

* test(e2e): launch the mail-pane fake under its agent CLI's name

v3 types mid-turn mail only into a recognized terminal agent, and a title alone no longer
recognizes one, so the fake runs as `node …/codex` (or cursor-agent) like an npm shim.
The hold-while-working case now models the unrecognized program that contract still holds for.

* test(e2e): align idle mail delivery spec with v3 auto-ack, mid-turn Enter and multi-Run coordinators

A consuming check now marks its batch handled (8fbb395a32), so the live
waiter's mail is pulled once returned and the held-batch case is seeded
as an older Orca leaves it. Agents queue mid-turn input (e0cb9a68d2), so
the held reminder's Enter is no longer withheld. A coordinator keeps its
earlier Run (#35274), so Run A direct mail is pointed with --run A.

* Wake a Run's coordinator through its pane when the Run's stored terminal handle belongs to the pane's previous PTY

* Make check --ack acknowledge only, so it never takes new mail

A check carrying --ack acknowledged that Delivery and then took (and,
since checks now acknowledge what they show, consumed) the next batch.
A caller that discarded the output lost that mail. --ack now returns
after acknowledging; newer mail stays unread, so the wake path still
fires and the next plain check shows it. The receipt says --ack is not
needed. Removes the ack-then-take receipts this made dead.

* Print every message body and payload in a plain orchestration check, since current hosts acknowledge the batch on read

* Keep acknowledge-then-take for check --ack --wait, and reject --ack on direct mail

A waiting caller reads what the wait takes, so --ack --wait acknowledges
and then waits for and takes the next batch, as before; --ack alone
stays acknowledge-only. Direct mail has no Delivery, so --ack there now
fails as a foreign delivery instead of consuming the mail.

* Keep a user-kept worker terminal kept when a new Dispatch reuses it, since its on-screen pane reports only once

* Tell a coordinator to check a remote worker itself when its host cannot report turn stops

* Find a Run's pane terminal for mail without re-issuing its handle mid-reload

* Keep the original ack-then-take path for check --ack --wait

Composing an ack with a second check lost the acknowledged consumer
generation and persisted subcall receipts. --ack --wait now runs the
original single-generation path unchanged; only --ack without --wait
returns after acknowledging, and direct mail still rejects --ack.

* Settle the e2e agent idle before newer mail so the mid-turn pointer cannot race the idle title

* Record a user's view of a worker terminal as user_seen so only it, not a coordinator's retain, survives reuse by a new Dispatch

* Let a worker ask, end its turn, and be woken with the answer

* Drop casts from the ask tests and the pending-question query

* Tell agents to run a plain check after acknowledging a held Delivery

--ack without --wait no longer takes newer mail, so the held-delivery
pointer now names the follow-up check for the new messages.

* Deliver Run and Dispatch mail to the pane's current PTY, issuing its handle only when none exists

* Wait for a PTY's exported handle before mail, and wake it when that handle is adopted

* Keep a cancelled ask from taking its answer, scope the asked-question stop mute to the asking turn, and end a waiting ask when its Dispatch settles

* Order the asked-question stop mute by message sequence, not same-second timestamps

* Wake a PTY's deferred mail whenever it gets a handle, by any path

* Make the headless Dispatch adoption test hold in both layout modes

* Mock the finished-worker strip states with neutral pane and chat notice fixtures

* Mock the temporary-worker strip with the owner's copy and the Allow auto-close tab menu item

* Mock chat workers with a goal-style composer strip instead of the composer notice

* Keep a worker open only by Keep open; hold its countdown while its agent works again

* Remove viewing and typing as implicit keeps on desktop and mobile

* Update the routing specs to acknowledge a held Delivery, then take with a plain check

* Show the temporary-worker strip with Keep open and its countdown, and Allow Auto-Close in tab menus

* Share the worker auto-close poll and key its read to the subject

* Re-read kept workers often so Allow Auto-Close shows its countdown promptly

* Hold auto-close through every turn, refuse stopping kept workers before anything changes, and read worker state only for known workers

* Keep a claimed close final, check the agent before claiming, refuse remote stops without a Keep open answer, and keep re-reading known workers

* Classify workerChatTouch caller fields and drop a test-only cast
2026-10-30 14:20:02 -04:00
Brennan Benson 527e7082b6 Reduce whole-app hitches when many chats are running (#35624)
* Move chat journal checkpoints off the host thread

* Apply checkpoint lifecycle style and teardown test checks

* Wake journal checkpoints for cleanup writes and retire fixture owners

* Use fixed time in attachment checkpoint fixture

* Derive checkpoint timer handles and check unref capability

* Preserve journal test close completion and event typing

* test: await journal close before fixture reuse and cleanup

* test: await registered journal fixture cleanup

* test: integrate goal sweep fixture with journal ownership

* Simplify journal checkpoint worker lifecycle
2026-10-30 11:13:21 -07:00
Brennan Benson 3881fbcda9 Keep pending questions through agent notices and undelivered replies (#36306)
* Keep pending blocking questions through non-answer rows

* Use a canonical delivered human row in blocking question tests

* Remove redundant live-status question test
2026-10-30 10:46:10 -07:00
Brennan Benson d59d6229cc Refresh phone tab streams when capabilities change (#36321)
* Refresh live client projections when connection capabilities change

* Skip unchanged tab stream frames on capability change and test the phone socket wiring

* Keep Pi status audiences on their opening capabilities

* Merge duplicate test import, restore comment placement and cover a skipped capability change

* Say which streams read live client capabilities

* Mark the tab stream test's runtime stub cast with the casting directive
2026-10-30 10:13:51 -07:00
a803cbead8 feat(mobile): iPhone Duo key rail with D-pad, split terminal panes and half-fold layout (#35177)
Carries over #33221 and #33210. Replaces our #34484 Duo support with the community design, on top of main's rebuilt terminal key bar (#36166).

Fixes #33200

Co-authored-by: Takeshi Matsumoto <zytakeshi520@gmail.com>
Co-authored-by: Lars Keggenhoff <lars@kghf.io>
2026-10-30 16:35:12 +00:00
OrcaWinandOrcaWin 5a925965d5 fix(git): compare staged renames against their HEAD source (#34779)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 06:25:03 -07:00
OrcaWinandOrcaWin 5f155d3df8 fix(source-control): hide discard for present submodule gitlinks (#34991)
* fix(source-control): hide discard for present submodule gitlinks

Parent git restore --worktree without --recurse-submodules leaves a dirty or moved submodule untouched, so Discard reported success while the row stayed. Hide row/section discard for present gitlinks and submodule children; deleted submodule dirs and staged gitlink discard (which unstages) keep working.

* fix(source-control): keep submodule discard when submodule.recurse is on

Plain git restore recurses into active submodules when submodule.recurse=true, so status now stamps restoreRecurses on gitlink entries and the shared discard guards keep those rows discardable.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 05:31:21 -07:00
OrcaWinandOrcaWin fad768d9fc fix(mobile): fully unstage renamed files (#34955)
Unstaging a staged rename from the Source Control row or diff review
reset only the new path, leaving the old path staged as a deletion.
Send both paths through git.bulkUnstage, matching desktop.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 03:09:55 -07:00
Brennan Benson ca84c49b35 Keep cancelled async questions hidden and show new ones (#35870)
* fix(chat): show each repeated async question

* fix(chat): keep async question identity stable across readbacks

* test(chat): preserve async question fixture types

* Keep async question cancellation scoped to individual occurrences

* Use checked types in async question test fixtures

* Share sender-aware async question retirement across chat views
2026-10-30 00:36:11 -07:00
Brennan Benson f26fb1cfda Keep async question controls available after agent notices (#35758)
* fix(chat): keep async questions open across agent notices

* test(chat): cover answering async questions after agent notices
2026-10-29 22:33:23 -07:00
Kelvin Amoaba 9b4c899dc8 feat(mobile): match every text input to the chat composer and rebuild the terminal dock (#36166)
* feat(mobile): give every text input the chat composer's look

Adds shared MessageBox, TextField and ComposerSendButton built from the
composer's own styles, and moves chat, form, search, Tasks, PR, review and
commit inputs onto them. The commit message becomes multi-line, every input
is 16pt (no page zoom on focus), and focus rings are gone. The terminal and
browser typing docks are unchanged.

* feat(mobile): rebuild the terminal dock around Keys and Message modes

Agent tabs open in Message mode, where you write in the chat composer and
Send types it into the terminal. Shell tabs open in Keys mode, where each
letter goes straight to the terminal through the live field. A pick made on
an agent tab lasts until the agent quits. The shell/agent rule is the one
keyboard dismissal already used, now shared.

The key row carries sticky ctrl, alt and shift (tap for the next key,
double tap to lock) and one arrow pad (tap a side, or hold and drag to
repeat through the existing held-key repeat). Paste, attachments, the
display width, the remaining keys and custom keys move to a ⋯ sheet. Return
in the composer adds a line; Send sends.

* fix(mobile): read arrow-pad taps from the pad and keep every key reachable from ⋯

A touch on a chevron made the icon the touch target, so the side was
measured against the icon's box and most taps read as left. The ⋯ sheet
now leaves out only the keys the current row shows, so agent tabs get Tab
and shell tabs get Shift+Tab and Enter back.

* fix(mobile): keep the last changed files clear of a growing commit box

The file list's bottom inset was a fixed 196 pt, so a commit message several lines long hid the last rows behind the commit bar. The inset now follows the bar's measured height.

* test(mobile): give the file list test its bottom inset
2026-10-30 04:51:47 +00:00
Brennan Benson a05cb89f1e Restore OMP thinking choices for non-running models (#36158)
* fix(acp): restore thinking choices for non-running OMP models

* test: cover OMP catalog persistence and menu scaling

* test: keep OMP scaling measurements in assertions

* test: load ACP fixtures before consumer tests

* test: preserve catalog source types in persistence cases
2026-10-29 21:25:58 -07:00
Brennan Benson bf3e7ed405 Show a card in the coordinator's chat when it starts a worker (#35263)
* Snapshot agent message relations and verify task display prefixes

* Show native chat agent messages in navigable cards

* Keep agent message cards derived from canonical input and sidebar state

* test: correct agent card contracts and cover raw queue editing

* test: repair agent card runtime and operation contracts

* fix: preserve queued image previews and typed test measurements

* fix: use checked worker fixture and owned sender button typography

* fix: complete agent card fixtures and native presentation

* test: preserve queued edit exports and current authorship

* test: use namespace type imports in queued edit fixture

* Show newly started workers in native chats

* Preserve sender progress and consolidate card contracts

* Simplify sender and notice contract instrumentation

* Remove duplicate sender and notice measurement mirrors

* Use a template literal for the dispatch boundary fixture

* Correct sender and notice verification phase accounting

* Consolidate agent message tests around user contracts

* Restore folded agent message preview on focus exit

* Consolidate agent message regression coverage

* Consolidate agent message fixture data

* Fix display text test lint diagnostics

* Use conversation view type for mail test records

* Reuse active copy control in card workflow test

* Use fixed timestamp in worker start context fixture

* Count fixture array reads without reflective access

* Use a typed store in runtime state fixture

* Fix worker card fixture types and CLI transport project includes
2026-10-29 20:28:54 -07:00
Kelvin Amoaba dc99281085 feat(source-control): resolve merge conflicts and complete merges from the phone (#36160)
* feat(source-control): resolve conflicts with one host operation shared by desktop and mobile

* feat(mobile): resolve merge conflicts and complete merges from Source Control

* test(mobile): pin Complete merge refusals and the older-desktop message

* fix(source-control): only resolve paths Git still reports as conflicted

* fix(source-control): refuse to keep a missing file and serialize conflict resolution per worktree

* fix(source-control): resolve only the exact conflicted path

* fix(source-control): match conflicted paths in Git's separator form on Windows and WSL

* fix(source-control): accept only the resolutions the live conflict offers

* fix(source-control): refuse to keep a both-modified file that is gone from disk

* feat(mobile): translate the merge conflict actions

* test(runtime): keep the mobile allowlist test under its line cap

* fix(mobile): let VoiceOver reach conflict action buttons
2026-10-30 03:18:48 +00:00
Kelvin Amoaba 1ed54cf4b5 fix(mobile): restore alerts without native push (#36125)
* fix(mobile): restore alerts without native push

* test(mobile): refresh notification reply matrix
2026-10-30 03:03:19 +00:00
OrcaWinandOrcaWin 6be126d65f test: remove low-value copy, layout, and equivalence checks (#36192)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 19:35:42 -07:00
OrcaWinandOrcaWin 2c4eb87240 fix(mobile): retain editor styling when switching color schemes (#35171)
* fix(mobile): retain editor styling when switching color schemes

* test(mobile): fit theme-switch harness hooks under the file line cap

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 19:28:48 -07:00
OrcaWinandOrcaWin 8a5c96349b fix(mobile): align task checkboxes with their first text line (#35157)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 19:19:51 -07:00
OrcaWinandOrcaWin 5d5073be6c fix(mobile): preserve blocks and images when formatting inline code (#35110)
* fix(mobile): preserve blocks and images when formatting inline code

* test(mobile): drop collapsed-selection inline code case

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 19:13:25 -07:00
OrcaWinandOrcaWin 3eda769de3 fix(mobile): preserve empty tasks through save and reload (#35085)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 19:02:59 -07:00
Brennan Benson b578e3012e fix(pi): the thinking menu before the first message matches the chat's (#34592)
* fix(pi): the thinking menu before the first message matches the chat's

Pi's pre-session catalog now asks Pi for its models over RPC and builds each
menu with the same projection a running chat uses, falling back to the text
listing only when Pi cannot answer over RPC.

* fix(pi): preserve remembered off effort on precise model lists

* test(pi): focus effort regression and stop fallback contracts

* test(pi): allow metadata reads between ordered option writes

* fix(pi): derive supported effort without replacing accepted intent

* test: cover host effort projection and refreshed frozen queues

* test: consolidate session option imports

* test: normalize absent catalog fixture records

* test: isolate host fixture types from client projects

* Preserve legacy effort capture for other agents
2026-10-29 18:59:25 -07:00
OrcaWinandOrcaWin 649cced481 fix(mobile): name task checkboxes from their current task text (#35081)
Task checkboxes take their own text (excluding the checkbox label, nested lists and code blocks) as an aria-label, refreshed on every change, with 'Task' as the fallback for an empty item.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 18:56:04 -07:00
OrcaWinandOrcaWin ec62243ded fix(mobile): keep table/list line breaks, item paragraphs and list code blocks through rich Markdown saves (#35259)
* fix(mobile): keep table-cell and list-item line breaks on their own source line

Table cells and list items save line breaks as <br /> (and sibling P/DIV
blocks inside an item as breaks), and reopen attribute-free <br> tokens
as breaks, so Shift+Enter or Enter no longer splits a row or ends a list.
Typed '<br>' text gets only its '<' entity-escaped, raw text newlines
become spaces, and browser caret placeholder breaks are dropped (a cell
that holds only a placeholder saves empty; a cleared item keeps a <br />
so its marker still parses).

* fix(mobile): keep fenced code blocks inside Markdown list items

Indented fences under a list item (README steps such as
'1. Install:' followed by an indented bash fence) now read as a code
block inside the item and save back under the item's continuation
indent. Only items whose continuation holds a fence change; headings,
quotes, rules and tables after the fence end the item and read as
before. Top-level and list code blocks share one PRE writer, blank
separator lines are not indented, and a fence needs no blank line
beside it so tight items stay tight.

* fix(mobile): keep caret code blocks out of the paragraph they follow

Code block with a collapsed caret after text in its block ran native
insertHTML, which merged the PRE into that paragraph as prose. Prepend
a <br> only when content precedes the caret, so block-start, empty-line
and empty-document insertions stay as they were.

* fix(mobile): keep authored runs of trailing table-cell breaks

* fix(mobile): use template literal for list code-fence probe

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 18:31:17 -07:00
OrcaWinandOrcaWin e988b5dd77 fix(mobile): preserve code, quotes and code blocks through rich Markdown edits (#35056)
* fix(mobile): preserve literal code through rich Markdown edits

* fix(mobile): preserve inline code containing backticks

* Preserve adjacent inline-code text when saving mobile Markdown

* Preserve quote paragraphs and blocks in mobile Markdown

* fix(mobile): preserve selected text when creating code blocks

* test(mobile): choose native history shortcut from browser host

* Preserve paragraph-owned mobile code blocks when saving

* Preserve code selected inside mobile headings after saving

* fix(mobile): keep code serialization space-normalized and trim review tests

- Inline code and code blocks keep turning browser-created NBSPs into spaces;
  only the reader-side entity fix is needed for literal code.
- Inline code line breaks save as spaces so table rows and headings stay intact.
- Code blocks keep trimming trailing newlines left by placeholder <br>s.
- Heading- and paragraph-owned code blocks join adjacent inline code runs.
- Empty nested quotes reopen as a plain empty paragraph.
- Trim synthetic and behavior-locking tests.

* fix(mobile): keep quoted text literal when block reading would rewrite it

Quoted list continuations and lazy lines were restructured on save because the list reader drops them; reopen quote blocks only when they save the source or the same bytes as the literal paragraph.

* test(mobile): use template literal for saved code-block markdown

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 17:38:16 -07:00
Neil 5121f25a5a perf(mobile): batch iOS push-dismissal ledger writes per page (STA-7366) (#36145)
Catch-up pages called the native ledger once per dismissal, each call
re-reading, encoding and writing the full 24h UserDefaults ledger. A new
rememberAll bridge merges a whole page in one locked read/encode/write with
identical semantics (max seq per identity, refreshed 24h expiry).
2026-10-29 17:36:12 -07:00
OrcaWinandOrcaWin 6236fdd4d7 test: remove low-value copy and CI fixture checks (#36159)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 17:20:50 -07:00
Brennan BensonandVyacheslav Scherbinin 00de405c5c fix: group Antigravity models and refresh effort choices (#34518)
* fix(acp): update Antigravity model and effort metadata

* fix: confirm ACP model families and idle option metadata

* Preserve provider-owned model and effort selection

* test: repair model option host and consumer fixtures

* Use the provider child type for optional delivery ownership

* test: match model option fixtures to their protocol contracts

* fix: isolate resting options from adapter type dependencies

* Preserve Antigravity option fixture types

* Match option fixture control response contract

---------

Co-authored-by: Vyacheslav Scherbinin <gentslava@mail.ru>
2026-10-29 16:21:22 -07:00
OrcaWinandOrcaWin 85522e89b8 test: remove low-value theme and copy suites (#36140)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 16:13:19 -07:00
Kelvin Amoaba 2e5711fcaa fix(mobile): use paired ports in firewall help (#36130)
* fix(mobile): use paired ports in firewall help

* fix(mobile): use a namespace type in diagnostics test
2026-10-29 22:55:38 +00:00