Skip to content

fix: use client defaults for new SSH chats - #26496

Closed
brennanb2025 wants to merge 23 commits into
brennanb2025/sta-8261-permission-pickerfrom
brennanb2025/ssh-chat-defaults-sent-by-client
Closed

brennanb2025 wants to merge 23 commits into
brennanb2025/sta-8261-permission-pickerfrom
brennanb2025/ssh-chat-defaults-sent-by-client

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #26116; retarget to main after it merges.

ELI5

Starting an SSH chat used the remote server's saved permissions, model, and reasoning effort instead of the desktop's choices. Someone who selected “Ask for approval” on the desktop could therefore get a new remote chat with Full access. New chats now carry the client's choices, and the composer shows the same choices that creation sends.

What Changed

  • Resolve the desktop's saved chat defaults once, use them in the composer, and send them explicitly with chat creation. Picks made while creation is pending are folded into that request; replay after a lost response or reload keeps the original choices.
  • The execution host honours explicit options without filling missing model choices from its own preferences. Clients that send no options retain the host's existing defaults.
  • Negotiate support before sending the new optional create field. With an older server, the desktop continues to show that server's reported starting choices and omits the unsupported field. Released desktop and phone readers accept the additive support-response field; real released-code tests verify this, so the response field needs no client gate.
  • Phone creation and workspace-plus-chat launch requests carry the phone's existing paired-host preferences. The agent launch path now preserves permission mode alongside model, effort, and Fast choices.
  • Remember desktop model, effort, and Fast picks in the desktop's settings, including picks made in SSH chats. The existing host/provider confirmation still owns permission fallback before the first turn; provider-incompatible choices use the stricter supported mode.

Why

Defaults belong to the client starting the chat, while the execution host owns running it. Sending the same resolved choices that the composer uses follows the common pattern and avoids a second, independently resolved set of defaults on the remote server. Copying settings to every server would leave choices tied to server state and introduce synchronization work.

Differences from the common mechanism:

  • Intended: keep Orca's existing global Chat preferences and empty-chat creation when a tab opens. Later composer picks use the existing option writes before Send, so the first turn still receives the chosen values without changing the tab lifecycle.
  • Intended: older clients keep host-owned seeding, and newer clients use the old host's reported choices when it cannot accept explicit options. This preserves mixed-version compatibility and keeps the picker honest.
  • Intended: the phone retains its existing paired-host preferences rather than gaining a device-local settings store. The choices it resolves are carried explicitly on the supported execution-runtime pairing path.
  • Temporary: a phone paired to a desktop still cannot create a chat on that desktop's SSH workspace because execution-host forwarding is missing. Follow-up: phone chats on a desktop's SSH workspaces (U17).

Linked Issue

Internal SSH structured-chat audit, U31. Dependency: #26116.

Visual Proof

Pending coordinator-owned hidden-window Electron validation and screenshots. No rendered UI validation or live SSH run was performed in this lane; this PR remains a draft for that review and QA.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated

On macOS: 224 targeted desktop, host, shared, and compatibility tests pass across 19 explicit files, and 100 mobile tests pass across four explicit files. Seven new regression assertions fail against the unchanged #26116 base. Six additional Fast-setting regressions fail before the encoded-option parsing fix and pass afterward.

Coverage includes conflicting desktop and SSH-host defaults, older hosts, old clients, an untouched model preference, composer picks before creation, exact replay after settings changes/reload, client-owned picker persistence, phone creation and workspace-plus-chat creation, lost phone launch replies, saved Fast on and off, and provider permission support. Unknown permission values fall back to Ask rather than silently becoming a host default.

Compatibility tests feed the new host response through released desktop result readers and phone response parsers for every pinned release in the existing cross-version suite, plus the newest release (currently v1.4.222). Each available released phone creator also proceeds to creation while omitting the new request options. These response readers are open; older host request schemas are strict, so the request field remains negotiated. The release fixture includes the phone sources and preserves each client's own imports.

Queued node, web, CLI, and mobile typechecks pass on the final implementation. Final pre-push checks: 21 of 22 static checks pass with those typechecks already completed. The sole local failure is the native code-quality audit, which reproduces five existing import-cycle warnings in mobile transport hooks and terminal document modules whose import graph matches origin/main.

Final-head CI is complete. Static analysis/typecheck, mobile checks, cross-version compatibility, relay integration, Linux/Windows packaging, nine desktop unit shards, and unit-selection evidence pass. Earlier failures in this lane's optional-argument and support-response assertions are corrected and now pass. The remaining failure is an existing timer-yield test in desktop shard 5: terminal-history-gc.test.ts observed five timer ticks where it requires more than five. Its test, implementation, and dependencies are unchanged from origin/main, and the prior-head shard passed. The aggregate verify check fails because of that shard; no new failure from this change remains. Conditional jobs were skipped and are not counted as passes. Real SSH/WSL and rendered picker behavior await coordinator QA.

Review

Draft: coordinator review and UI QA are pending.

Agent skill upstream boundary

  • Not applicable: this change copies no upstream skill-installer implementation.

Notes

Author X handle: @BrennanKB5. Execution ownership and transcript authority stay on the host; this change carries starting preferences across the existing request paths.

Checklist

  • This PR is focused on new-chat defaults
  • I explained the problem, user-facing change, mechanism, and alternatives
  • Before/after screenshots or videos attached
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH, folder-workspace, and mixed-version impact considered
  • Full CI complete; every failure classified

Add an independent global default for new Claude and Codex chats, seed it
once from current terminal permissions, and retain per-chat desktop and
mobile permission controls without changing terminal launch behavior.

Apply inherited Claude middle modes before the first message with a safe
Ask fallback, and persist supported Codex modes after thread opening.
…on mode

A chat's saved permission mode is now one of the chat's own modes; plan is
not one of them, so the launch check uses Accept edits.
…tion controller

The controller now takes the structured chat's own field names, so the
phone chat controller no longer copies seven fields one by one and stays
under the line limit once main's newer lines are merged.
Claude's model listing includes supportsAutoMode only when it is true, so the
picker's "not false" check offered auto on every model. Match the start path.
Also give the chat settings test the tooltip provider the app root supplies.
…-chat-permissions

# Conflicts:
#	src/renderer/src/components/native-chat/NativeChatComposer.tsx
…-chat-permissions

# Conflicts:
#	src/main/claude/claude-structured-launch-resolution.test.ts
#	src/main/codex/codex-structured-launch-resolution.ts
…-chat-permissions

# Conflicts:
#	src/main/claude/claude-structured-launch-resolution.ts
#	src/main/runtime/structured-agent-session-runtime.ts
…-chat-permissions

# Conflicts:
#	src/renderer/src/i18n/locales/es.json
#	src/renderer/src/i18n/locales/fr.json
#	src/renderer/src/i18n/locales/ja.json
#	src/renderer/src/i18n/locales/ko.json
#	src/renderer/src/i18n/locales/zh.json
A post-pick refresh that answered after a newer publication-driven read
could put the permission button back on Ask while the host held Full
access. Both reads now share one generation, as on mobile.
Accept edits only appears for Claude, where it still asks before commands;
Full access keeps saying it has no sandbox or approval checks.
Claude's modes follow its own rules: Ask skips what settings allow, Accept
edits also approves file commands, and Full access keeps Claude's rules and
sandbox. Codex Full access has no sandbox, so it keeps that warning.
…-chat-permissions

# Conflicts:
#	src/main/claude/claude-structured-launch-resolution.ts
#	src/main/runtime/structured-agent-session-runtime.ts
#	src/main/runtime/structured-claude-runtime-adapter.ts
…-chat-permissions

# Conflicts:
#	src/renderer/src/i18n/locales/en.json
@brennanb2025
brennanb2025 force-pushed the brennanb2025/sta-8261-permission-picker branch from 7e29652 to f467d20 Compare October 12, 2026 08:39
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Closing. New-chat defaults (permission mode, model, effort) stay owned by each host, which is how main works today: the composer shows the host's starting choices and the create sends exactly those, and model or effort picks made in a host's chats are remembered on that host. This PR moved ownership to the client starting the chat, which contradicts that design, and most of its remaining machinery has since landed another way (each send and create now carry the model and effort). The one gap left, editing a remote host's chat permission default from the desktop, can follow the existing per-host Quick Commands settings if we want it.

@brennanb2025
brennanb2025 deleted the brennanb2025/ssh-chat-defaults-sent-by-client branch October 14, 2026 17:37
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