Skip to content

fix(mobile): start an explicitly chosen agent even when it is hidden in Settings - #27773

Closed
brennanb2025 wants to merge 5 commits into
mainfrom
brennanb2025/mobile-hidden-agents-explicit
Closed

brennanb2025 wants to merge 5 commits into
mainfrom
brennanb2025/mobile-hidden-agents-explicit

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 7 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​258 $\color{#cf222e}{\Huge{\mathbf{−}}}$​7 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​251
Prod 22 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​987 $\color{#cf222e}{\Huge{\mathbf{−}}}$​585 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​402

ELI5

On the phone, choosing an agent you've hidden in Settings now starts it, the same as on the desktop since #27766. Hiding an agent only controls whether it shows up in menus. As Brennan put it: "the disabled button is just for showing it in the UI or not".

#27766 removed the "agent is disabled" refusals from the host and the desktop window. It left the phone app alone because the phone's own checks are pinned by its recorded-RPC test fixtures. This PR removes those phone-side checks and re-records the fixtures they changed.

What Changed

Every row assumes the agent is hidden in Settings on the computer.

Phone surface Before After
Task page, "Create workspace" from an issue or PR, with a chosen agent Error "Selected agent is disabled. Choose an enabled agent before creating.", the picker jumped back to the automatic pick, nothing created The workspace is created and the chosen agent starts
New-workspace sheet, with a chosen agent Same error and picker reset, nothing created The workspace is created and the chosen agent starts
Either create screen, when you picked an agent and it was then hidden on the computer while the screen was open Mostly the same error at Create; if the screen re-read settings first, your choice was silently replaced by the automatic pick Your choice stays and starts
Either create screen, when you never touched the picker and the agent it shows was hidden on the computer after the screen loaded The same error at Create, then the picker moved to another agent Create re-picks from the computer's current settings and starts that agent instead. There is no message, so the agent that starts differs from the one the screen showed (rare: it needs the phone's copy of Settings to be out of date)
AI buttons on a workspace ("Fix checks with AI", "Resolve conflicts with AI", commit recovery, review notes) whose saved agent is hidden Error "The saved agent for this action is not available on this workspace host." The saved agent starts

Still the same: the phone's agent pickers list only visible agents (a choice you already made stays listed so it shows as selected), and the automatic pick (default agent, then the first detected agent) still skips hidden agents. Both create screens re-run that automatic pick from the settings they read at Create, so a phone whose copy of Settings is older than the computer's still can't start a hidden agent you didn't choose. An AI button whose saved agent isn't installed on that host still shows "The saved agent for this action is not available on this workspace host." rather than quietly using a different agent.

Because the pickers never list a hidden agent, the create screens reach this path less often: an agent chosen before it was hidden, or a selection made when the screen opened. The AI button with a hidden saved agent is the everyday case.

Wording: the desktop Settings switch now reads Shown/Hidden (#27766), so the phone stops calling agents "enabled". No phone string called an agent "disabled". These changed:

Where Before After
New-tab menu, when no agent can be offered (two menus) "No Enabled Agents" "No Agents to Show" (the desktop's "No agents to show", in the phone's title case)
AI buttons, when no saved agent is set and none can be picked "No enabled AI agent was detected on this workspace host." "No AI agent on this workspace host is both installed and shown in Settings. Install one there, or show one in Settings on your computer."

Older computers (mixed versions): a phone with this change, paired with a computer that doesn't have #27766 yet, gets that computer's refusal. It never fails silently or shows a raw code:

  • Task page create: shows the computer's sentence ("Selected agent is disabled. Choose an enabled agent before creating.") in the drawer's error line. That create uses worktree.create, which answers with the sentence.
  • AI buttons: show the computer's sentence ("Agent claude is disabled. Choose an enabled agent.") under the button. One new test pins this, using the code an older computer really sends (runtime_error).
  • New-workspace sheet: on a computer that offers the newer launch route, the refusal comes back only as the code agent_session_operation_unknown, and for a terminal agent that computer created nothing. The sheet has just read that computer's Settings at Create, so it recognises this case when all of these hold: you picked the agent, those Settings hide it, the reply is that code, and it answers the first send rather than a resend. It then shows "Orca on your computer won't start Claude while it's hidden in Settings there. Show Claude in Settings on your computer, or pick another agent." Every other reply on that route is shown exactly as on main.
    • When the line can be wrong: every failure on this route reaches the phone as the same code, for example git refusing the worktree, or a chat that fails to start after the workspace exists. On a computer that has feat(agent-launch): hiding an agent only hides it from pickers #27766, such a failure for a hidden agent you picked shows this line instead of the code. It is rare, since it needs a hidden agent you picked plus a failed create. In the chat case a workspace may already exist, so picking another agent and tapping Create again makes a second one.

An older phone talking to a newer computer still refuses on its own until the phone updates. No request or reply shapes change.

Mechanism

  • Task page: the create drawer passes its agent only when you picked it (workspaceAgentOverridden). use-mobile-tasks-workspace-create-actions.tsx sends a passed agent as is and otherwise re-runs the automatic pick from the settings it reads at create. The refusal and its selection reset are removed.
  • New-workspace sheet: use-new-workspace-create-submit.ts now takes agentOverridden from the agent selection. It sends your pick as is and otherwise re-runs the automatic pick from the settings it reads at create. The refusal and its selection reset are removed. The sheet's agent list keeps a hidden current choice, as the task picker does.
  • use-new-workspace-create-submit.ts also maps the one refusal above to the sentence naming the agent (hiddenAgentRefusedMessage). The shared create retry (worktree-create-retry.ts) now marks a failure that answered a resend (replayed: true), so a resend is never relabelled. That is its only change; what it shows is unchanged.
  • new-worktree-agent-selection.ts and workspace-agent-selection.ts: the selection logic that clears a choice you made now drops it only when that agent isn't detected on the host, not when it is hidden. The task-page picker keeps your current choice in its list so it can show it as selected.
  • mobile-source-control-launch-agent.ts: a saved agent starts if this host has it, hidden or not. With no saved agent, the shared automatic pick (pickSourceControlLaunchAgent) runs as before and still skips hidden agents. The phone resolves the saved agent itself rather than through that shared helper. That way this PR behaves correctly whether it merges before or after feat(agent-launch): hiding an agent only hides it from pickers #27766, which changes the same helper.
  • Deleted isWorkspaceAgentEnabled, which nothing uses now, and the two copies of the phone's refusal string.

Recorded-RPC fixtures (goldens): re-recorded with the harness's own pnpm --dir mobile rpc:record over the whole set. 9 of 793 files changed, none added or removed, all in the two families built around this refusal. The recording adapters choose Claude while the host's settings hide Claude:

  • settings-task-workspace-{fulfilled,refused,transport-error} and matrix-settings.task-workspace-settings.get-1: these used to end on the phone's refusal. They now reach the repo's setup prompt, which is the step the adapter's own comment says this family exists to cover.
  • matrix-settings.task-workspace-create-settings.get-1: in the variants where the settings read fails, the phone used to fall back to its seeded settings (Claude hidden) and refuse. It now sends worktree.create with Claude.
  • settings-workspace-submit-{fulfilled,refused,transport-error} and matrix-settings.workspace-submit-settings.get-1: these used to end on the refusal plus a reset of the selection to Codex. They now record worktree.create going out with startupAgent: "claude". The scenarios script no reply to that create, so the submit is still pending at the last step and teardown records a cleanup step for the closed connection. I didn't add a scripted create reply: it would derive a new reply-variant fixture and new parity verdicts for a create path other families already cover.
  • The new-workspace recording adapter marks Claude as the user's own pick (agentOverridden: true), so these recordings pin the explicit-choice rule. The automatic re-pick is pinned by unit tests.
  • The page parity closures (C1, C5) keep their pinned verdicts for these families.

Why

The phone is a client of the same host rules. After #27766 the host starts a hidden agent when asked. The phone refusing first would leave the phone the only place where hiding still locks an agent out. Removing the checks, instead of adding a "launch anyway" path, keeps one meaning for hiding everywhere: menus and automatic picks skip the agent, and an explicit choice starts it.

Linked Issue

Follows #27766 (desktop and host). No separate issue.

Visual Proof

Live phone QA on 4447ca5 (iOS simulator, paired to a hidden desktop test copy running #27766's final head; real Claude/Codex; settings changed only in the desktop Settings UI).

New-tab menu when no agent can be offered:

Phone new-tab menu: No Agents to Show

AI button when no saved agent is set and none can be picked:

Phone commit-failure Fix with no agent available

Claude picked on the sheet, then hidden on the computer: Create still starts Claude, and the "won't start Claude while it's hidden" line correctly does not show (that line is only for a computer running an Orca from before #27766):

Phone after Create: Claude starts in the new workspace

Testing

  • pnpm --dir mobile rpc:record (whole set) then rpc:diff: exactly the 9 goldens above moved. Re-recording the committed tree reproduces them byte for byte. Re-recording after each review round moved nothing further.
  • Mobile vitest, named files (26 files, 1865 tests pass): the recording replays (pilot-recordings, family-recordings), pilot-mutants, family-mutants, rpc-recording-through-bridge, derived-goldens, adapter-seam, the C1/C5 page-closure and divergence-classes tests, plus the unit tests for every changed module and the create route (use-new-workspace-create-submit, use-mobile-tasks-workspace-create-actions, worktree-create-launch-operation, agent-launch-mobile-replay, mobile-agent-launch-architecture, worktree-create-retry, blank-workspace-create, source-workspace-create, pr-ai-triage-launch, new-worktree-agent-selection, workspace-agent-selection, NewWorktreeModal, use-new-workspace-runtime-context, use-mobile-session-terminal-create-agent-launch, use-mobile-tasks-provider-view-projection, host-workspace-list-action-error).
  • Mobile typecheck (tsc --noEmit) and the mobile test-typecheck ratchet (scripts/check-tests-typecheck-ratchet.mjs, which CI's mobile job runs): pass.
  • orca-ci-checks --no-typecheck: 21 of 23 pass, and the changed-code quality gate is among them. The two failures are not from this diff. typecheck:ci fails locally in its bun runner (Script not found "check"), as feat(agent-launch): hiding an agent only hides it from pickers #27766 also hit. audit:code-quality:native reports import cycles in mobile files this PR doesn't touch (transport/host-client-hooks.ts, transport/client-context.tsx, terminal/document/*). This PR only removes imports, so it can't add a cycle.
  • No desktop or host code changed, so the root typechecks don't cover anything here.

Tests changed:

  • new-worktree-agent-selection.test.ts and workspace-agent-selection.test.ts: each screen's selection logic keeps a user pick that is hidden in Settings.

  • use-new-workspace-create-submit.test.ts (new): the computer has hidden the sheet's default agent since the sheet loaded. An untouched automatic pick is re-picked to another agent, and the same agent picked by the user starts. A third case: an older computer refuses that user-picked hidden agent with only agent_session_operation_unknown, and the sheet shows the sentence naming Claude. Two negative cases (an automatic pick, and a user pick that is shown in Settings) show the code exactly as on main.

  • worktree-create-launch-operation.test.ts, agent-launch-mobile-replay.test.ts: the two cases whose failure answers a resend now also expect replayed: true. Nothing else about them changed.

  • use-mobile-tasks-workspace-create-actions.test.ts (new): the same two cases for the task-page create. The re-pick case pins create's fallback when no agent is passed; it also passes without this PR. The drawer's one-line change, passing its agent only when you picked it, is checked by typecheck and reading; the drawer can't render under the test runner without React Native.

  • pr-ai-triage-launch.test.ts: new test. An AI button whose saved agent is hidden sends that agent to the host, and an older host's refusal comes back to the user in the host's words. It fails on the old code, which refused on the phone before sending anything.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Review

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • SSH and folder workspaces: the phone sends the same requests as before to whichever host owns the workspace. Detection of agents on that host still decides whether a saved agent can start.
  • Remote compatibility: no request or reply shapes change. Mixed versions are covered above.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason (after shots from live phone QA above)
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…in Settings

Follows #27766: hiding an agent only hides it from pickers and the automatic
pick. The phone no longer refuses a hidden agent on the task-page workspace
create, the new-workspace sheet, or a source-control AI button's saved agent,
and a chosen agent is no longer cleared when it becomes hidden. An older host
that still refuses hidden agents shows its own message.

Re-recorded the settings.task-workspace and settings.workspace-submit RPC
goldens with rpc:record.
…irmed create

Only an agent the user picked may start while hidden: both create screens now
re-run the automatic pick from the settings read at create time unless the user
chose the agent. The new-workspace sheet lists a hidden current choice like the
task picker does.

A launch-route create the host can't settle (agent_session_operation_unknown or
_expired, which an older host also sends when it refuses a hidden agent) now
reads "Couldn't confirm the workspace was created. Check your workspaces before
trying again." instead of the raw code.
Reverts the generic "Couldn't confirm the workspace was created" mapping in the
create retry, so resend, expiry and cutover replies behave as on main. Instead,
the new-workspace sheet recognises the one case it can explain: a user-picked
agent that the Settings just read hide, refused with
agent_session_operation_unknown by a computer from before hidden agents could
start. That computer created nothing, so the sheet names the agent and the
next step.
… offer

Matches the desktop Settings switch, now Shown/Hidden: the new-tab menu's empty
row and the AI button's no-agent line name hidden agents and the next step.
…the desktop's empty-menu wording

The create retry marks a failure that answered a resend (replayed: true), and
the new-workspace sheet only names a hidden agent when the refusal answered the
first send. The empty new-tab menu now reads "No Agents to Show".
@brennanb2025

brennanb2025 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Status: ready for review (head 4447ca5)

This is the phone half of #27766 (hiding an agent only hides it from pickers). It does not depend on #27766 being merged first; against an older computer it keeps today's behaviour plus one plain-words line (below).

Review. Three rounds with fresh reviewers each round, every finding fixed or listed:

  • Round 1: an automatic pick could start a hidden agent on both phone create screens (the task drawer always sent its pick as the user's choice); fixed. A new phone talking to an older computer showed the raw code agent_session_operation_unknown; handled in round 2.
  • Round 2: a general "couldn't confirm the workspace was created" mapping changed what every failed create says; reverted. Replaced by one line on the new-workspace sheet only, shown when the computer is an older Orca that refuses a hidden agent the user picked: "Orca on your computer won't start Claude while it's hidden in Settings there. Show Claude in Settings on your computer, or pick another agent."
  • Round 3: that line no longer shows for a failed reply to a resent request; the body states exactly when it can still be wrong (a computer that already has feat(agent-launch): hiding an agent only hides it from pickers #27766 sends the same code for other create failures, so a hidden pick plus an unrelated failure can show it); tests added for an automatic pick and a shown agent (plain message as on main). Phone wording now matches the desktop: "No Agents to Show"; no phone string calls an agent "disabled".

Readiness. CI green on 4447ca5 (6 pass, 0 fail, including the mobile verify job with the test-typecheck ratchet). Merges cleanly with current main 93e0b80, and main has changed none of this PR's files since its base, so the CI result stands. No file over the line limit (largest touched mobile file 344 of 379), no line-limit disables, type assertions carry SAFETY comments.

Live QA (iOS simulator through orca emulator, paired to a hidden desktop test copy on #27766's final head, real Claude/Codex, settings changed only in the desktop Settings UI):

Row What was checked Result
P2 Claude picked on the new-workspace sheet, then hidden on the computer: Create starts Claude, and the hidden line does not show PASS
P3 Commit-failure "Fix" with the saved agent Claude hidden: "Agent started in main", Claude starts PASS
P4 Default agent Claude shown when the sheet opened, then hidden: Create starts Codex (automatic picks skip hidden agents) PASS
P1 Task page create with a hidden agent chosen BLOCKED: the task page needs a hosted issue or PR, and the isolated test copy has no remote or login

New phone strings were checked on screen: "No Agents to Show" and "No AI agent on this workspace host is both installed and shown in Settings. Install one there, or show one in Settings on your computer."

Not verified. P1 (above). The sheet's "hidden" line against a computer running an Orca from before #27766 was covered by a unit test, not live. Side note seen in QA: hiding the default agent also resets the default to Auto (desktop behaviour, unchanged here).

@brennanb2025
brennanb2025 marked this pull request as ready for review October 12, 2026 10:45
@coderabbitai

coderabbitai Bot commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fbb3ce9e-4e1f-4ec8-8485-0a5329a5b56c

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3ce44 and 4447ca5.


📒 Files selected for processing (29)
  • mobile/rpc-foundation/goldens/matrix-settings.task-workspace-create-settings.get-1.json
  • mobile/rpc-foundation/goldens/matrix-settings.task-workspace-settings.get-1.json
  • mobile/rpc-foundation/goldens/matrix-settings.workspace-submit-settings.get-1.json
  • mobile/rpc-foundation/goldens/settings-task-workspace-fulfilled.json
  • mobile/rpc-foundation/goldens/settings-task-workspace-refused.json
  • mobile/rpc-foundation/goldens/settings-task-workspace-transport-error.json
  • mobile/rpc-foundation/goldens/settings-workspace-submit-fulfilled.json
  • mobile/rpc-foundation/goldens/settings-workspace-submit-refused.json
  • mobile/rpc-foundation/goldens/settings-workspace-submit-transport-error.json
  • mobile/src/components/NewWorktreeModal.tsx
  • mobile/src/components/new-worktree-agent-selection.test.ts
  • mobile/src/components/new-worktree-agent-selection.ts
  • mobile/src/components/use-new-workspace-agent-selection.ts
  • mobile/src/components/use-new-workspace-create-submit.test.ts
  • mobile/src/components/use-new-workspace-create-submit.ts
  • mobile/src/session/mobile-source-control-launch-agent.ts
  • mobile/src/session/pr-ai-triage-launch.test.ts
  • mobile/src/session/use-mobile-session-panel-route-actions.tsx
  • mobile/src/tasks/agent-launch-mobile-replay.test.ts
  • mobile/src/tasks/mobile-tasks-dependencies.ts
  • mobile/src/tasks/mobile-tasks-workspace-create-drawer.tsx
  • mobile/src/tasks/use-mobile-tasks-workspace-create-actions.test.ts
  • mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx
  • mobile/src/tasks/use-mobile-tasks-workspace-create-projection.tsx
  • mobile/src/tasks/workspace-agent-selection.test.ts
  • mobile/src/tasks/workspace-agent-selection.ts
  • mobile/src/tasks/worktree-create-launch-operation.test.ts
  • mobile/src/tasks/worktree-create-retry.ts
  • mobile/src/test-support/rpc-recording/adapters/workspace-settings-mounts.ts

💤 Files with no reviewable changes (1)
  • mobile/src/tasks/mobile-tasks-dependencies.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.



📝 Walkthrough

Walkthrough

Mobile agent selection now retains detected user choices that are hidden in Settings. Workspace creation uses the latest runtime settings for automatic selection and tracks whether failed create responses came from a resend. Source-control launches accept a saved agent when the mobile host detects it, even if Settings hides it. RPC recordings and tests cover the updated selection and creation paths.


Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 4447c

The reviewed agent-selection and workspace-creation changes have no identified issue requiring a fix before merge. Normal checks remain appropriate.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 16.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 19 files. (9 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title is concise, specific, and accurately summarizes the primary mobile behavior change: explicitly chosen hidden agents can start.
Description check Passed The description is comprehensive and covers the user impact, implementation, rationale, compatibility, visual proof, testing, and checklist requirements. It references related PR #27766 instead of lin…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 16.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 19 files. (9 skipped: 9 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Closing: disabled agents should be refused at launch, because Orca stops maintaining their status hooks (Brennan, 10-12). Main's refusals stay.

@brennanb2025
brennanb2025 deleted the brennanb2025/mobile-hidden-agents-explicit branch October 12, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant