* Revert "Keep same-machine folders with matching Git remotes in separate projects (#32272)"
This reverts commit 29a5f89b8a.
On a machine with several clones of one repo, #32272 moved the oldest clone
into the shared cross-host project. Shared Windows QA machines have several
orca clones, so everyone's sidebar "orca" project suddenly gained that
machine's main checkout and its worktrees. Revert until the intended
grouping is decided.
Conflicts resolved against later main: Settings files moved into
settings/repository (imports adjusted), and two test files later deleted on
main stay deleted.
* Use checked types in restored test fixtures
* Combine restored fixture type imports
* fix(native-chat): list OMP skills in the / menu as /skill:<name>
* test(native-chat): OMP now carries the Pi-shaped skill profile
* Publish native OMP skills with compatible command catalogs
* Index native skill descriptions once per picker build
* Combine catalog test composer imports
* Correct native catalog test types and project inputs
* Run cross-platform picker scaling contract with mobile tests
* fix: discover native commands before the first chat message
* test: isolate native command discovery from mobile typechecking
* fix: release command discovery ownership after managed root exit
* refactor: reuse the ACP child owner during shutdown drain
* test(acp): load filesystem implementation before test execution
* test: drive discovery close completion explicitly
* test: await discovery admission cleanup between demand waves
* test: control discovery close ordering in demand waves
---------
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* fix(gitlab): keep paging merge requests when GitLab omits the totals
When total headers are absent, a full response advertises another page to probe and a short response ends pagination. Keep the existing header precedence and unknown total count.
Tracked in #33800
* test(gitlab): cover MR pagination exhaustion and header precedence
* test(gitlab): verify unknown-total metadata across list consumers
* test(gitlab): cover remaining screen consumers of list metadata
* test: use checked GitLab RPC runtime fixtures
---------
Co-authored-by: Hotragn <103170876+Hotragn@users.noreply.github.com>
* fix(mobile): leave Agent Session History when resuming a session from it
Resuming always pushed the session screen, so Back from it landed on the
history screen again (A -> B -> A). History now learns it was opened from a
session (origin=session, as Source Control does): resuming into that same
workspace pops back to it, anything else replaces the history screen.
The history screen is a page in the shell, and the page could only ask the
shell to push. The navigate notify gains an optional replace flag; a page with
no in-page history asks the shell to replace its screen, and one with history
below pops its own entry and has the shell push. Older shells strip the flag
and push as before.
Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>
* fix(mobile): show the resumed terminal on the session that opened Agent Session History
Going back to the session screen below kept its old tab: the session pins its
own pick over the host's caller-scoped snapshot. History now hands the resumed
terminal to that session through the registry Source Control already uses for
opened diffs, renamed to session-screen-handlers since it carries both.
* refactor(mobile): positional replace flag on notifyNavigate, share the owned-session test fixture
* fix(mobile): keep MobileWebShellScreen under its line cap
---------
Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>
* feat(mobile): light and dark themes with desktop's palettes
Settings → Appearance offers System, Light and Dark. The shell passes the
resolved scheme to over-the-air pages in its init frame.
Fixes#22184
* fix(mobile): draw your chat messages in desktop's user bubble
Desktop uses a faint surface with a hairline border in both themes; the inverted fill went black in light.
* test(mobile): re-measure the page script sweep after the shared theme hooks
Every route now imports the theme hooks while the entry does not, so they emit one shared script (96 for the tree). Re-swept every route prefix; the worst route step is now 15.
* test(mobile): read themed stylesheets in the text-input font-size census
The census only unwrapped StyleSheet.create({...}); inputs styled through themedStyleSheet(() => ({...})) came back unread.
Mobile kept its own copy of the language tables and looked file names up
on plain objects, so constructor, toString or __proto__ returned an
Object member and lowlight threw. Mobile now uses desktop's shared
detector, which only reads own keys; .make moves into the shared table
so mobile keeps its Makefile highlighting.
Mermaid draws every flowchart label in the theme's text colour, so a
`style` or `classDef` fill can hide it: light text on a pale node in dark
mode, dark text on a deep one in light mode. After rendering, labels that
fall below 4.5:1 on their node's fill switch to whichever theme colour
reads better, on desktop previews, chat and the phone.
Co-authored-by: Nico Hu <haoyu.hu@lexmount.com>
* feat(mobile): copy button on shell command rows in chat
* test(mobile): stub the copy button where chat tests count tool row presses
* fix(chat): decode the login-shell script the way the shell does
Codex joins argv by switching quote styles, so stripping only the outer
quotes left \" escapes and quote splices in about a fifth of real
commands. Argv arrays are now shell-quoted when joined.
* fix(chat): keep the shell-path match to the outer command; reuse the label's full command
Argv arrays go back to a plain join: no argv-shaped shell calls exist in
real transcripts, and quoting them broke PowerShell and cmd.exe argv.
* test(mobile): leave quote decoding to the shared unwrap test
* refactor(chat): slice double-quoted runs and name the row's command fields plainly
* style(mobile): format copy button mocks in chat row tests
* refactor(mobile): share the queued-card projection with desktop
Image-only queued drafts showed a blank card on the phone.
* fix(mobile): honor the host's Queue follow-ups setting
With it off, a mid-turn send from the phone still queued while desktop sent it into the running turn.
* fix(mobile): keep a queued-card edit when the card leaves the queue
The phone closed the editor and dropped the typing; it now goes to the chat box as on desktop.
* fix(mobile): hold /clear and /compact for background work and sends
The phone fired the command where desktop holds it, showed start failures twice, and left the agent unnamed in failures.
* fix(mobile): hand a queued edit back to the chat it came from
* fix(mobile): scope a command's send hold to its own chat
* fix(mobile): read a published null queue as empty
* refactor(mobile): share the returned queued-card caption rule
* test(mobile): drop queued-card tests the shared rules already own
* refactor(native-chat): share the needs-attention rule and drop leftover wrappers
* fix(mobile): type the structured sends mock, drop the moved queued-cards path and ship queued edit copy at boot
* fix(native-chat): drop the queued card's unused image-label import after the rebase
* fix(mobile): order the phone's queue reorder preview by position, as the shared cards sort
* test(mobile): keep the queued-messages test within its line budget
* fix(mobile): settle terminal chat working state and turn timing with desktop's rules
Move desktop's live-status merge, Stop suppression, hook-state resolver and
terminal turn timing to src/shared/native-chat. Mobile reads the transcript
lifecycle the host already sends, so a provider turn end settles Working the
same way desktop does. Terminal chats now get the turn bar, timer and folding,
and the streaming preview uses the shared deriveNativeChatStreamingText.
* fix(mobile): send desktop's terminal Stop keys, a second Escape only for OpenCode
Desktop sends one Escape on Stop. It adds a paced second Escape only for
OpenCode, which confirms an interrupt that way. Claude Code and Codex read
Esc-Esc at an idle prompt as rewind. The rule moves to
native-chat-agent-support, and the phone now paces the second Escape at
desktop's answer step instead of 80ms.
* fix(mobile): word Orca-stop and usage-limit notices like desktop
Move desktop's Orca-stop sentences to src/shared with an English table that
desktop translates. The phone names the Orca host it pairs with, and when
that host is unnamed it says "the remote server". Usage-limit rows rebuild
desktop's sentence from the failure fact. The usageLimitLineText fallback,
which only the phone used, is deleted.
* test(mobile): pass the overlay's host name in the prompt controller harness
* test(mobile): re-record Stop goldens at desktop's step, split status-notice tests, pin the turn clock and ship notice copy at boot
* fix(mobile): offer structured Stop while a send is out and read queue-sends-next as working
Move desktop's structured Stop rule, its Stop-joining helpers and the
queue-sends-next rule to src/shared. Both sides now use them. The phone
counts its in-flight sends, so a conversation-stop host offers Stop before
the turn opens. Between queued turns the phone reads as working, and
commands that can't wait in line hold like they do on desktop. Untargeted
Stops are no longer joined on legacy hosts.
* fix(mobile): offer terminal Stop again when its Escape went nowhere
Stop hides Working on the phone like it does on desktop. The phone's Escape
can fail outright, though, while desktop writes to a local PTY. When no Escape
could have landed, the phone now drops that suppression. The streaming preview
also treats a pending echo as the transcript's tail, as desktop does, so an
earlier reply can't hide a new preview.
* fix(mobile): hold structured Stop while a send it covers is in flight
On desktop, Stop's held and Stopping state depends on whether the chat can
stop, and that includes a send still in flight. The phone now does the same.
Once Stop is pressed before the turn opens, the button holds and repeated
presses send no more untargeted cancels.
* fix(mobile): end the terminal Stop hold when a new message is sent
Desktop clears Stop's working suppression on an optimistic send, so a new turn
that keeps the same hook epoch (Claude with working subagents) still offers
Stop. The phone now does the same when a new pending echo appears.
* refactor(mobile): trim chat turn wiring after the desktop rule move
Drop the controller's unread nativeChatAgentWorking field. Re-render only when
a chat starts or stops having a send out. Keep the structured turn indicator
stable across stream frames. Type the Stop test table instead of casting.
* refactor(mobile): track structured sends in flight once for Stop and command holds
* test(mobile): re-record Stop goldens now that Stop settles with its Escape delivery
* fix(mobile): escape terminal image paths like desktop drops
* fix(mobile): keep launch-draft prefill over older user turns
* fix(mobile): rank @ file matches with desktop's fuzzy Quick Open search
* fix(mobile): use desktop's composer triggers for mid-prompt / and $ picks
Picked @ files are now quoted when the path has spaces.
* fix(mobile): send picked skill paths on structured chats
* fix(mobile): list the host's disk-scanned skills in the / and $ menus
The phone names the workspace and the host resolves its folder, refusing SSH
workspaces as desktop does; hosts without skills.discover-workspace.v1 list none.
* fix(mobile): forget a picked skill once its token is deleted
* fix(mobile): drop a picked skill as soon as its token is deleted, and retry failed skill scans
* fix(mobile): treat a picked leading skill as chat and stop failed skill scans from refiring
* test(mobile): drop the menu ranking case the shared picker tests own
* refactor(mobile): keep skill picks on the draft record and reuse shared send rules
A rejected send now keeps its picks and leading-skill origin on both send paths.
* fix(mobile): replace a re-picked skill's file and restore picks with a rejected send
* fix(mobile): read the chat agent for the skill catalog from the active resolution
* style(native-chat): format the composer autocomplete files
* fix(native-chat): import the picker's apply and send-classify rules from the shared composer module
* refactor(mobile): import the composer's draft-store hooks once
* style(mobile): format the notice row's style import
* fix(mobile): resolve terminal chat agents in desktop's order
Mobile now uses the shared detected-then-launch precedence and transcript-readability check; the phone's remembered agent only fills in after them.
* fix(mobile): hide Codex foreground commands from the background-task strip
* refactor(native-chat): share diff-card gutter, basename and task count
* fix(mobile): show clipped tool output sizes in KB/MB like desktop
* refactor(native-chat): share the tool-run header rules with mobile
* fix(native-chat): share tool-line detail rules; skip unsafe-only search hits
* fix(mobile): copy message text with desktop's rule
Copy now leaves out roster and background-task fallback twins and wordless provider frames.
* refactor(native-chat): memoize shared tool-line view and output sizes; share result preview
* fix(native-chat): read a lone result's preview from its narrowed body
* chore(i18n): ship chat tool and stop copy in the runtime English catalog
* refactor(native-chat): move the pending-send echo rule to shared
Mobile reuses it instead of its own matcher.
* fix(mobile): match chat echoes after their send boundary, sink unmatched ones
Uses desktop's rule: rows before the send no longer retire an echo, a send that
never lands no longer lets later glued sends retire, and an unmatched echo sits
below later turns.
* fix(mobile): keep glued photo captions and folded boundaries in echo matching
* fix(mobile): give image preview echoes the send time the occurrence rule reads
* fix(mobile): match echoes on image-normalized rows and cap open sends at eight
Same input and bound as desktop; each open send rescans the transcript.
* test(mobile): drop a pending-order case the tail test already covers
* refactor(mobile): read the send boundary once and skip echo normalization when idle
* test(native-chat): type the occurrence case's pending send
* test(mobile): drop the pending-echo wall-clock entry from the flaky-test baseline
* refactor(native-chat): share session option labels with mobile
Mobile's options pill now shortens effort levels (Med, XHigh, Min) and names
choices and options the way desktop does, from one English table that desktop
translates.
* refactor(native-chat): run mobile terminal chat options on the desktop surface
The terminal-chat option surface, its appliers, the option cache and the
dispatch types move to src/shared, and the phone builds its pickers from them.
Grok and every other agent with a catalog now get model and effort pickers on
the phone, picks are saved as the host's launch defaults, the OMP live switch
gate and discovery mapping come from one copy, and authoritative discovery
retires persisted models it no longer lists. The option stamp moves to shared.
* refactor(mobile): merge the session option type imports
* fix(mobile): keep terminal chat option picks on their own chat
The phone keeps one option surface per chat, so a pick that lands after leaving
and returning shows there, and a picker command only switches the chat it came
from. Discovered models merge with the seed catalog as on desktop, so Grok keeps
its effort picker. A Claude model switch the phone cannot confirm is never
saved as a launch default.
* fix(mobile): start terminal chat options over when a tab changes agent
A tab that runs another agent drops its kept option surfaces, report markers
and cached record, so a fresh session shows its own model. A pick that lands
after the phone moved to another chat is not saved as a launch default.
* fix(mobile): fence retired terminal chat option surfaces
A write that lands after its tab started another agent no longer publishes the
old agent's record, and a changed OMP switch capability rebuilds the chat's
surface from the cache instead of reviving an older one.
* refactor(native-chat): simplify the shared session option wiring
Desktop translation pieces use literal English defaults so the localization gate can read them, the selected-choice lookup is shared once, and the phone keeps one option surface per tab with the agent change detected from the cached record.
* refactor(mobile): return no option surface for an agent without a catalog
* test(native-chat): expect the shared Effort label in the startup picker test
* test(native-chat): keep only the label cases main still checks after the rebase
* refactor(native-chat): import the session option snapshot rules once in the PTY option surface
* refactor(native-chat): share structured option pick bookkeeping with mobile
Desktop and the phone now track picks per option through one shared book: a
repeat of an option on its way waits, other options go together, a lost reply
is not a pick done, and a stale reply only commits its own option. The phone
also re-reads options each turn and after the provider starts, and shows picks
at once while the host is still starting the provider.
* refactor(native-chat): share the option pick blocking rule
* fix(native-chat): read in-flight option picks from the shared book for launch send options
* fix(native-chat): keep the structured options hook within its line budget and pass the phone turn in the e2e harness
* fix(mobile): build the Source Control action sheet from desktop's menu rows
Adds Force Push and desktop's order, enable rules and hints.
* fix(mobile): rebase from desktop's effective base and keep the Force Push warning in the action sheet
* fix(mobile): keep the rebase row's base when the branch compare fails
* fix(mobile): keep upstream compares working when the default base lookup fails
* fix(mobile): keep the rebase target apart from the branch compare so failed or unsupported compares keep it
* fix(mobile): leave force pushes to desktop when the linked review has its own push target
* refactor(mobile): rebase onto the shown base and share the force-push block with the primary action
* perf(mobile): stop redrawing the chat per keystroke and scanning every row per scroll frame
Typing re-rendered the whole session screen because the draft text was
subscribed in the drafts hook at the route; the composer now subscribes by
draft key. The page list's reading place indexed every drawn row with a
page-wide querySelectorAll on each scroll event; it now binary-searches the
row box's children. The list also observes its viewport so composer resizes
keep a parked reader's place without a list commit.
* test(mobile): keep the keystroke redraw test in the draft-store suite under the line cap
* fix(native-chat): keep Claude approval choices across model changes without freezing delivery
A Claude chat saved as "Approve for me" could reopen asking for every approval,
because Orca read the folder's saved model list as launch policy, and a model
change could keep running in a weaker approval mode Claude opened with. The
first fix for this was reverted after it froze the app: restored history left
a turn reading as running, a send was refused against it, and delivery retried
the same send with nothing changed.
- The saved approval choice goes to Claude as-is; the menu offers every mode.
- Orca records the mode Claude actually opened in. A send that picks a new
model reopens Claude first when that mode differs from the one requested,
only when the chat owes no work; Orca mail notices never reopen it.
- A message sent while a Claude turn is running joins that turn on its current
choices; new choices apply at the next new turn. Nothing is refused.
- History catch-up closes every turn it opens, in the thread it opened in.
- At startup, a turn reading as running under the new agent that the agent is
not running is ended as interrupted.
- Delivery goes round again only after a step shows what it changed (a commit,
a different child, a start it joined ending, or a wake); otherwise it waits
for the next change instead of repeating the same step.
Tracked in STA-10953.
* fix(native-chat): preserve execution evidence at dispatch
* Fix delivery iteration ownership and progress contracts
* Correct journal fixture types in delivery regressions
* Separate Claude input choices from error correlation
* feat: drag to reorder queued messages on desktop and phone
* fix: use the queue grip button padding from its primitive
* fix: preserve the queue grip touch width with hit slop
* test: carry queue animation mocks into the chat view harness
* test: complete the shared chat view harness registrations
* test: carry the queue move cross-version wire contract
* Scope queue move feedback to the issuing chat and preserve phone touch width
* Keep queue reorder presentation stable during measurement and pending moves
* Keep measured row handoff tokens constant size
* Avoid rebuilding queue arrival IDs on unchanged renders
* Fix mobile queue regression test fixture boundaries
* Share the queued message leading slot with its reorder grip
* Fix queue regression fixture quality findings
* Check queue icons within the leading slot
* Allow every unsettled queued message to reorder
* Supply stable scope in queued row test mock
The pending-terminal budget was skipped whenever another session-tabs
recovery need was active, so it never ran out and the terminal never
reached "Terminal is taking longer than expected" with Retry.
Refs #32231
Co-authored-by: zhangxaochen <zhangxaochen@163.com>
* fix(mobile): open wrapped terminal urls and paths with desktop's link detection
Desktop's terminal URL and file-link detectors move to src/shared and the phone's
WebView document calls them, replacing its single-row copies. File taps carry every
reading of the tapped text so the phone opens the longest one the host finds, as
desktop does.
* fix(mobile): keep the unc host of osc 8 file links for the host to resolve
* fix(mobile): resolve terminal file-tap readings a few at a time
A tap inside a run of path rows yields hundreds of hard-wrap guesses; firing them all at once overflowed the page bridge's pending-request cap and the real path was never checked.
* refactor(terminal): share the osc 8 link classifier and trim file-tap plumbing
Desktop and the phone now read OSC 8 targets through one shared classifier. Terminal file taps carry only their candidate list, deduped by path, and desktop checks OSC overlap only for candidates it can resolve.
* refactor(terminal): keep shared link files under the line cap
The xterm buffer subset gets its own module, and the text-only OSC resolver goes now that the router uses findExactTerminalFileLink.
* fix(mobile): compare branches and show diffs with desktop's base-ref and whitespace settings
Base-ref resolution moves to src/shared and the host publishes the compare-against-upstream
and show-whitespace settings, so the phone's branch compare and diffs match desktop.
* fix(mobile): use the upstream compare policy on the review screen and rebuild diffs when whitespace changes
* fix(mobile): reread Source Control settings on Refresh and restart diffs loading under the old whitespace setting
* test(mobile): cover diffs dropped when desktop's whitespace setting arrives
* refactor(mobile): share one Source Control settings read per host across screens
* fix(runtime): clear Claude's question wait when a phone keystroke answers it
Claude sends no hook after AskUserQuestion is answered; desktop infers it, phone answers left the pane waiting.
* fix(mobile): answer multi-question cards like desktop, with Skip and back-stepping
Mobile required every answer and locked grouped structured questions once tapped; the card rules and structured mapping now live in shared code.
* fix(mobile): announce ask card options as checkboxes or radios
* fix(mobile): answer a grouped question only on the prompt it was picked on
* test(runtime): drop the multi-question case the shared answer rule already covers
* refactor(native-chat): share the typed-answer rules and fold the host answer check into terminal.send
* fix(mobile): send terminal paste, keys and query replies like desktop
* fix(mobile): encode Shift+Enter for the pane's negotiated keyboard modes
The phone's xterm now tracks Kitty flags and modifyOtherKeys with desktop's tracker, seeded from the host snapshot.
* fix(mobile): keep keyboard modes across terminal snapshots
* fix(mobile): adopt snapshot keyboard modes with desktop's rule
* refactor(terminal): share snapshot keyboard-mode adoption and mode mirroring
* fix(mobile): compare terminal modes field by field instead of a dynamic read
* refactor(mobile): share terminal display-mode adoption between snapshot and resize
* fix(mobile): accept only known terminal display modes from the host
* fix(mobile): follow desktop terminal display rules
- ZWJ emoji width: activate the shared Orca unicode provider instead of plain Unicode 11.
- Contrast floor: share desktop's resolver and background parser; translucent
backgrounds composite over the published light/dark surface.
- Word selection: use xterm's default word separators via a shared rule.
- Takeover reports: share the 30 s gate and single retry between desktop and mobile.
- Use the shared viewport minimums and default scrollback rows.
* refactor(mobile): trim duplicate tests and reuse shared terminal types
* fix(mobile): resolve terminal tab agent icons with the desktop rule
Moves the tab-strip identity resolver to src/shared and deletes the drifted copy in use-tab-agent.ts, so the desktop tab strip, open-tab search and the phone all run one rule.
* fix(mobile): rank host cursor identity as the tab's process signal
* fix(mobile): rank cached host cursor identity only for unowned terminal tabs
* fix(terminal): keep sleeping tab identity through hibernation shell evidence
The kill that hibernates a pane can report the shell foreground while the wake record is kept on purpose; the tab strip never retired sleeping identity on exit evidence, so the shared resolver keeps that behavior.
* test(terminal): drop tab agent tests that replay the shared resolver
* refactor(terminal): share the observed agent signal rule between tab strip and snapshots
* fix(mobile): send terminal paste, keys and query replies like desktop
* fix(mobile): encode Shift+Enter for the pane's negotiated keyboard modes
The phone's xterm now tracks Kitty flags and modifyOtherKeys with desktop's tracker, seeded from the host snapshot.
* fix(mobile): keep keyboard modes across terminal snapshots
* fix(mobile): adopt snapshot keyboard modes with desktop's rule
* refactor(terminal): share snapshot keyboard-mode adoption and mode mirroring
* fix(mobile): compare terminal modes field by field instead of a dynamic read
* refactor(mobile): share terminal display-mode adoption between snapshot and resize
* fix(mobile): accept only known terminal display modes from the host
* fix(mobile): follow desktop terminal display rules
- ZWJ emoji width: activate the shared Orca unicode provider instead of plain Unicode 11.
- Contrast floor: share desktop's resolver and background parser; translucent
backgrounds composite over the published light/dark surface.
- Word selection: use xterm's default word separators via a shared rule.
- Takeover reports: share the 30 s gate and single retry between desktop and mobile.
- Use the shared viewport minimums and default scrollback rows.
* refactor(mobile): trim duplicate tests and reuse shared terminal types
* fix(mobile): send terminal paste, keys and query replies like desktop
* fix(mobile): encode Shift+Enter for the pane's negotiated keyboard modes
The phone's xterm now tracks Kitty flags and modifyOtherKeys with desktop's tracker, seeded from the host snapshot.
* fix(mobile): keep keyboard modes across terminal snapshots
* fix(mobile): adopt snapshot keyboard modes with desktop's rule
* refactor(terminal): share snapshot keyboard-mode adoption and mode mirroring
* fix(mobile): compare terminal modes field by field instead of a dynamic read
* refactor(mobile): share terminal display-mode adoption between snapshot and resize
* fix(mobile): accept only known terminal display modes from the host
* fix(mobile): use desktop's sort, colour, count and agent-row rules in the workspace list
Recent ignores terminal output, repo colours fall back to desktop's neutral,
Home counts skip archived rows, folder workspaces trail each lane, and a stale
agent row on a live terminal reads "No update in …" like desktop.
* fix(mobile): keep Delete disabled on a primary checkout, as desktop does
* fix(mobile): keep the task text on a silent agent row
* fix(mobile): show a silent agent row's time since its last update
* test(mobile): drop agent-row tests that replay the shared verdict
* refactor(mobile): check host PTY liveness once and keep the delete guard on the row flag
* test(mobile): re-record the home catalog goldens for the list's active count
* fix(mobile): list Source Control changes with desktop's sections, sort and row rules
Conflicts get their own section in the user's group order, submodule rows lose stage and
discard like desktop, paths sort with the shared collator, and review notes go out as desktop formats them.
* fix(mobile): read the group order the host now publishes and keep submodule rows read-only
The host's paired settings projection now carries sourceControlGroupOrder, the
normalized status projection keeps submodule metadata, and conflict rows reuse the
shared conflict-kind labels.
* refactor(mobile): share Source Control grouping and row rules with desktop
Desktop and mobile group rows through one shared helper, mobile's unstage button
follows desktop's rule, and the group order resets when the host changes.
* fix(mobile): ask before running orca.yaml default-tab commands from the phone
The host's repo.hooks reply now carries desktop's setup config, so the phone
gates the Run/Skip choice and the trust prompt on defaultTabs commands too.
* fix(setup): keep the local script in run-both setup config without orca.yaml commands
* test(setup): drop the shared duplicate-host trust test desktop already covers
* refactor(setup): derive host setup trust from the shared setup config
* fix(mobile): count every host's repo rows before honouring repo-wide setup trust
* fix(mobile): show desktop's PR lanes and failed/interrupted status dots on the phone
The host builds worktree.ps linkedPR with the desktop's PR-lane cache reader
and sends the desktop sidebar dot as an optional sidebarStatus field.
* fix(mobile): keep uncached PR badges and let finished turns show through working titles
* fix(mobile): suppress agent panes' permission and parent titles in the host status dot
* test(runtime): expect sidebarStatus on the compact ps summary
* test(runtime): keep only host-specific sidebar status cases
* refactor(mobile): keep host title suppression and the uncached PR lane in one place each
* test(wire): pass the terminal title evidence map to new host builds
* fix(runtime): read each workspace's PR through its own host's repo
* fix(mobile): ask before running orca.yaml default-tab commands from the phone
The host's repo.hooks reply now carries desktop's setup config, so the phone
gates the Run/Skip choice and the trust prompt on defaultTabs commands too.
* fix(setup): keep the local script in run-both setup config without orca.yaml commands
* test(setup): drop the shared duplicate-host trust test desktop already covers
* refactor(setup): derive host setup trust from the shared setup config
* fix(mobile): count every host's repo rows before honouring repo-wide setup trust
* fix(mobile): read chat prompt cards with desktop's shared parser
Mobile guessed permission and question cards from assistant prose; the
guess could outrank the real approval and send the wrong key.
* fix(mobile): keep an ask answer valid across the status-to-transcript handoff
* chore(i18n): ship approval card copy in the runtime English catalog
Its fallbacks now come from the shared copy table, which i18next cannot rebuild from the call site.
* test(native-chat): own approval parsing cases in the shared test
* refactor(native-chat): build each prompt dismiss key once
* fix(mobile): prepare Create PR and the commit action like desktop
Create PR now fast-forwards a behind-only branch before committing, picks its push step
from desktop's shared rule, and the commit-area button reads the branch's review state.
* fix(mobile): keep Create PR commit failures intact and skip fork push-target gating
Restaging after a failed commit is best effort and checks the branch first, and reviews
with their own push target are not gated until mobile reads targeted upstream status.
* fix(mobile): enter Create PR on desktop's intent rule and leave fork push targets ungated
* refactor(mobile): share the linked-review push decision and enter Create PR on desktop's intent rule
Desktop and mobile compose the review push target through one shared function, the
Create button admits branches Create PR can prepare, and older hosts without a lookup
outcome still fail closed on mobile.
* fix(mobile): use desktop's check order, labels and fix-checks prompt in the PR panel
Check, step, reviewer and comment rules move to src/shared; the phone's fix-checks agent
now gets failing log tails, the worktree path and the action's saved agent arguments.
* test(shared): pass only the fields comment mutability reads
* refactor(mobile): gate fix-checks on desktop's broken-check set and drop the prompt re-export
Fix and Rerun show for the same checks the prompt and the host use, desktop imports
the fix-checks prompt from src/shared directly, and job steps split through the shared summary.
* fix(mobile): prepare Create PR and the commit action like desktop
Create PR now fast-forwards a behind-only branch before committing, picks its push step
from desktop's shared rule, and the commit-area button reads the branch's review state.
* fix(mobile): keep Create PR commit failures intact and skip fork push-target gating
Restaging after a failed commit is best effort and checks the branch first, and reviews
with their own push target are not gated until mobile reads targeted upstream status.
* fix(mobile): enter Create PR on desktop's intent rule and leave fork push targets ungated
* refactor(mobile): share the linked-review push decision and enter Create PR on desktop's intent rule
Desktop and mobile compose the review push target through one shared function, the
Create button admits branches Create PR can prepare, and older hosts without a lookup
outcome still fail closed on mobile.
* Source control actions start chats and terminals on their saved model
A "start an agent" action's model lived only in free-text CLI arguments, which a native chat
never reads, so AI Fix opened a chat on the default model. Each action now saves a structured
model and effort that both routes apply: chat create options, or the agent's own flags in a
terminal (winning over the same flag in CLI arguments). Desktop, dialog, fix-checks and mobile
launches carry it; Settings rows get Model/Effort selects and the CLI arguments field says it is
terminal-only.
Tracked in STA-11102.
* Name the model in the repository override note
* Type the dialog's model hand-off; keep Agent in English in Japanese copy
* fix: preserve action chat model choices through launch
* Preserve action selection ownership across chat launches
* Keep terminal host contract fixtures aligned with preflight
* fix: wait for action Settings agent inventory
* fix: consolidate direct agent routing imports
* fix: use standard action option labels
* fix: align action launch contracts with shared types
* fix: sync action option localization metadata
* test: provide action Settings inventory in mounted fixtures
* Keep action options row height stable while loading
* Let each Source Control action choose its chat permission mode
An action's saved chat choice may now carry a permission mode, with or without a model;
"Same as new chats" saves nothing. A model is replaced only when the action names one,
so a permission-only choice keeps the chat's remembered model and options.
* fix(native-chat): leave older hosts their own permission mode and keep action options readable
- An action's saved permission mode is sent only to hosts that advertise
agentSession.create.options-mode.v1. Older hosts get no mode, in create
options or a later setOption, so the chat starts on that host's new-chat
default, as a phone launch to such a host already does. Hosts from
1.4.225 to 1.4.227 refused a mode their tables lacked (OpenCode, Grok,
OMP), leaving the action unable to start.
- Settings action rows give Model and Permissions full rows in the options
column so saved values are readable; the loading placeholder reserves the
same rows.
- Remove two unused locale keys; fix two stale comments.
- Tests: the older-host create carries no permission mode; a permission
mode picked alone keeps the remembered model on an acquired create.
* fix(settings): reserve one options row while loading an action with nothing saved
Terminal and permissions-only rows no longer shrink when loading ends; a chat
agent with a model list may grow by its Model row once known.
* fix(native-chat): keep the create options mode a checked literal type
* fix(settings): share verified action option fields
* fix(settings): keep action selectors on standard typography
* feat(agents): Create worktree and continuation pickers offer chat or CLI per agent, like the "+" menu
The Create worktree, Create folder and session-continuation agent pickers now
list the same rows as the tab bar "+" menu: chat agents first, each with a
terminal button that picks the agent's CLI instead, then the agents that only
run in a terminal, labelled "(CLI)". A terminal pick shows as "Claude (CLI)"
and starts the agent in a terminal even when chats are the default.
A continuation into a subfolder shows chat as unavailable there.
* fix(agents): picker rows keep the combobox item spacing instead of restyling CommandItem
* chore: drop accidental lockfile churn
* fix(agents): type the surface picker's props and the composer's agent rows
* fix(agents): submit the picker selection captured by each form
* test(agents): include repository identity in continuation fixture
* Keep the launch files under their length limits after the main merge
The structured route imports its result types where they are defined, and the two older-host
action-launch tests share one setup helper.
* feat(source-control): Source Control AI actions pick chat or CLI with the unified agent picker, and saved actions remember it
The shared Source Control AI action dialog (commit/push failure fix, checks
fix, resolve conflicts, resolve comments, PR-page fix checks) now lists the
same rows as the tab-bar "+" menu: chat rows with a hover terminal button,
and "(CLI)" rows. The pick carries chat-or-terminal into the launch.
- One inventory: the dialog's own detection is gone; agent list, default
selection, status copy, Start gating and auto-start all read the same
host observation the "+" menu reads (the worktree's host, or the repo's
host for the PR page's not-yet-created workspace).
- The captured launch choice threads through runSourceControlAgentActionStart
into launchAgentInNewTab, and on the PR page through the fix dialog into
both launchWorkItemDirect planning sites.
- Saved recipes gain optional `surface: 'chat' | 'terminal'`, bound to the
recipe agent like launchPreferences: normalized, inherited, copied on
Customize, dropped on agent change, compared for receipts and matches.
A pick saves a surface only where the agent had a chat row.
- Default paths (split-button primary, fix checks with and without a
workspace, saved auto-start) request a terminal only for a saved
terminal; a saved chat follows the settings route so it can still fall
back to a terminal.
- Settings rows are unchanged here; the dialog layout keeps following the
settings route.
* Import Source Control action ids and the agent setter once in the recipe test
* One action settings section for chat and terminal launches
A Source Control action's Model, model options and Permissions now apply whether it opens a
chat or a terminal; terminals receive them as the agent's own flags, and a repository's own
CLI arguments keep the flags it sets. Extra CLI arguments stay terminal-only.
* Make saved source control starts explicit and preserve recipe intent
* fix(source-control-ai): one terminal projection for saved action choices
Ask in a terminal now states its permission instead of leaving it to the
user's own config: Claude and Grok pass --permission-mode default, Codex
passes -a on-request -s read-only -c approvals_reviewer="user" (the
interactive CLI has no untrusted policy, so a read-only sandbox is what
asks before edits). Agents whose CLI has no flag for a mode show the
existing "Applies to chats only" hint.
The strict launch-preferences projection now requires the launch agent at
every caller, composes model ids through the resolver's own step, carries
a mode only where the agent's terminal has a flag for it, and the local
string wire keeps booleans as 'true'/'false', so Cursor Thinking/Fast reach
the terminal and an OpenCode permission-only choice is not refused.
The argument parser knows flag arity, so removing a boolean permission
flag keeps other options' values, following positionals and '--'.
Pre-admission and executor share one terminal admission check on the
options the terminal will receive. Customize with Save launches the recipe
as it will resolve once saved; legacy partial repository overrides are
edited as the complete recipe they resolve to. Empty Extra CLI arguments
start collapsed.
* fix(source-control-ai): an edited repository action saves complete
Every Settings edit of a repository action (agent, model, permission,
prompt or arguments) now starts from the complete recipe the action
resolves to, whether its stored override is owned or a legacy partial.
The resolved agent selection is kept (never an agent only detected to run
a default), an explicit null args clear stays null, and empty args stay
empty instead of being dropped. Clearing the last preference therefore
means the action agent's own defaults rather than re-inheriting Global.
The action text draft is lossless: unset or cleared prompt and args stay
so until the user types, and the inputs show them as empty, so saving a
prompt no longer writes empty args that suppress the agent's default
flags. Untouched sibling actions are not rewritten by the edit.
* Keep source control correction and completion independent of launch eligibility
* fix(settings): style the Extra CLI arguments toggle through Button's own variant and size
CI's changed-code quality check refuses restyle classes on Button and
CollapsibleContent. Use the ghost variant at size xs with a margin, and
put the content spacing on a plain inner wrapper.
* Verify saved action launches and lossless repository reloads
* Update review refresh consumer after React commit
* Preserve independent source control actions and phone option precedence
* Repair launch contract test fixtures
* Save source control action choices before starting the agent
* Report source control recipe write failures without holding agent launch
* fix: keep saved action and restart launch recipes consistent
* Report pull request action save failures and correct recipe boundary types
* fix: describe inherited arguments and chat-only permissions accurately
* test: check repository action settings fixture type
* test: map saved action options into terminal compiler inputs
* Strip Unicode format characters from check log excerpts
* test: remove redundant source control action runner cases
* fix: retain saved action controls during agent detection
* fix(i18n): retire obsolete Portuguese action labels
* test: align folder launch fallback mock with outcome export
* test: complete source control recovery controller fixture
* Keep action argument visibility aligned with selected launch route
* fix: carry resolved connector launch intent and mode together
* fix: share host agent preferences across source control actions
* fix: keep preference refresh tied to observation inputs
* Fix optional agent preference contracts and typed fixtures
* Require preference keys while preserving undefined values
* test: pin shared action launch branches to recorded agent output
* test: preserve saved source control choices through detection and migration
* test: align launch fixtures with integrated result contract
* test: retain recipe and restart contracts after main integration
* Unify Source Control action permission settings
* Keep native Ask copy with its owning change
* Preserve action drafts and old-host permission intent
* Consume rejected Source Control action saves
* Follow the moved Settings persistence fixture
* Keep permission integration contracts in the cross-version test project
* Include the action permission inheritance label in English catalogs
* Align launch contracts with shared permission recipes
* Preserve settings snapshot for Source Control recovery
* Align saved action persistence fixture with shared agent picker
* Keep Source Control action controls within their Settings columns
* Use primitive variants for compact action settings controls
* Avoid returning from the launch test store setter
* Show action arguments only for terminal defaults and widen recipe rows
* Apply terminal-only action arguments visibility to repository overrides
* Align action permission control with model controls
* Use shared settings label for action permissions
* Hide action model controls until argument migration ships
* Show action arguments for explicit CLI picks
* Preserve Unicode joiners in check log excerpts
* fix(mobile): gate PR merge and linking on desktop's shared rules
Merge state moves to src/shared so the phone stops offering Merge on drafts,
conflicts and blocked PRs, and stops letting branch PRs override explicit links.
* fix(mobile): keep stack merges and stale-link recovery in the PR panel
Mobile now applies desktop's stack override and drops a linked PR the branch has moved
past, and only offers Ready for review when a relaying desktop also forwards it.
* fix(mobile): persist stale PR link clears and add a merge recheck
The phone now writes desktop's link clear instead of rereading the stale link, and a
blocked Merge can be rechecked since nothing on mobile polls PR state.
* fix(mobile): guard stale PR link clears like desktop
Re-reads the worktree before clearing so a link chosen after the lookup survives, and
localizes the merge-state strings the lift exposed to the coverage gate.
* test(mobile): drop identity test for worktree link params
* refactor(mobile): share one stack-merge decision and trim PR panel wiring
* fix(mobile): default worktree bare/archived flags for the stale-link guard
* fix(mobile): label the PR merge button from its default merge method
* fix(chat): preserve transcript source order across history windows
* test(chat): use template literal for mobile transcript fixture
* test(chat): place composed transcript contracts across project boundaries
* test(chat): move reader-to-phone contract across project boundaries
* test(chat): reuse transcript input setup and caller contracts
* test(chat): align mobile recordings with source-order capability
* test(chat): scope phone transforms and await history snapshot