Commit Graph
10 Commits
Author SHA1 Message Date
+1 891f7e6880 fix(source-control): fit local argv prompts to Windows and Linux limits (#34123)
* fix(source-control): fit argv agent prompts to the local command line by truncating the diff

Antigravity and the other promptDelivery: 'argv' agents pass the whole
commit or PR prompt on the command line. The prompt builders capped the
diff at 200,000 characters, but runLocalSourceControlPlan refuses argv
over 30,000 UTF-16 units on Windows (and any argument over 120 KiB on
Linux), so a large branch diff failed before the agent started.

For local targets, when the planned argv would exceed that limit, pick
the largest diff budget whose prompt fits (binary search, so Windows
units and Linux bytes are both measured on the real plan) and rebuild
the prompt with it. This covers the default action template path as
well as plain prompts. WSL targets are left to the existing guard
because the WSL launcher re-wraps the command. The pre-spawn guard
stays as the backstop when the non-diff sections alone are too large.

Fixes #34109

* Unify Source Control action permissions and card layout (#30449)

* 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

* 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.

* 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.

* 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.

* 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.

* fix: keep saved action and restart launch recipes consistent

* 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

* fix: retain saved action controls during agent detection

* fix(i18n): retire obsolete Portuguese action labels

* test: align folder launch fallback mock with outcome export

* fix: carry resolved connector launch intent and mode together

* 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

* Keep Source Control action controls within their Settings columns

* Use primitive variants for compact action settings controls

* 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

* feat(wsl-host): start a WSL host's distro when one of its automations comes due (E9 B) (#33839)

* feat(wsl-host): start a WSL host's distro when one of its automations comes due

E9 connect policy, part 2. A WSL host's automations run inside its distro, so a
distro that is off (a reboot, an idle release) missed them. While a host is connected
the desktop now reads its enabled automations' next run (on connect and every 15 min)
and keeps the soonest one per host in userData. When that time comes with the host off,
it boots the distro once, and orcad's startup catch-up fires the run within its missed-
run grace. A run due while the computer was off fires once Orca starts. Nothing wakes
past the grace window, and a connected host is left to its own scheduler.

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

* test(wsl-host): a due automation boots a parked host once, never with WSL hosts off

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

* fix(wsl-host): keep the following run, and forget changed automations (E9 review)

Review of #33839:
- A run handled while connected dropped the host's next due time. The wake now keeps
  each host's enabled schedules and computes the following run locally whatever
  happens to this one (wake failed, past grace, handled by the host), and re-reads the
  real one from a connected host.
- A deleted, disabled or rescheduled automation kept waking the distro at its old
  time. A successful automation.create/update/delete from this desktop now re-reads the
  host's automations, as do the 15-minute re-read and every connect. Nothing boots a
  distro to check: on wake, a distro already running is just reconnected.
- wakeForAutomation/isConnected live here now (moved out of #33838); isConnected reads
  the host's reachability, never booting.

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

* refactor(wsl-host): say isConnected answers for this process; keep the service in bounds

isConnected reports whether the host answers through this process; false is not
"stopped" (a fresh process has no bridge yet, and the wake just connects). The
service's quiet record read moves beside the other record helpers so the file stays
within its line limit after the E9 additions.

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

* refactor(wsl-host): give the connector contract its own file; one wake path for focus and automations

After rebasing onto #34063, #34093 and #33110 the WSL host service was over its line
limit. The connector contract (what the service drives) moves to
wsl-host-connector-contract.ts, re-exported from the service, and the focus entry and
the automation wake share one private wake step: lift the park, then reconnect unless
the host answers, read with #33110's focusReachability so neither pays a WSL round trip
when this process has no bridge yet. An automation wake no longer reconnects a host
that already answers.

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

* test(wsl-host): an automation wake with no bridge skips the reachability probe

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

---------

Co-authored-by: Claude <noreply@anthropic.com>

* test(connector): freeze the shipped connector schema behind an upgrade test (#34115)

Freezes the connector's shipped table definitions: later schema changes must be additive statements. Adds a baseline fixture and an upgrade test (baseline, then current schema, compared with a fresh database on SQLite and Postgres), plus the statement-shape check relay already uses. No runtime change.

* test: remove 30 low-value cases and seven suites (#34120)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* test(terminal): a pinned parked tab's process exit asks first, then closes as a pty-exit (#34121)

Co-authored-by: Claude <noreply@anthropic.com>

* fix(ssh): move enabled SSH automations to the host's Orca server (#34044)

* fix(ssh): move enabled SSH automations to the host's Orca server

Connecting an SSH host moves its saved state to the host's managed Orca
server. An enabled SSH automation refused that move on every Connect
("automations (1), automation runs (4)"), leaving the host unconnectable;
Move anyway connected it but stranded the automation on the desktop, where
it no longer ran.

An enabled automation whose runs have all finished now moves with its run
history. The manifest still carries it disabled, which every server version
accepts; once the move commits the desktop disables its retained copy and
turns the server's copy back on through automation.update, re-sending its
start time so the next run is the next future occurrence. A server that
can't is noted in Settings; an unreachable one is retried on the next
Connect. While a move fences the host, the desktop scheduler, Run now and
the launch re-check write nothing for its automations, so a tick can no
longer break the fenced export; releasing the fence resumes them. A run
still in flight keeps blocking and the refusal now says to wait for it.

Fixes #29083

* test(ssh): mock the server automation enabler in the delta-move handler test

* test(e2e): keep the Move anyway specs refusing now that enabled automations move

The inline Move anyway spec seeded an enabled automation to force a
refusal, which this branch now moves instead. It seeds one pinned to an
earlier registration of the host, which still stays behind. The relay
bridge spec's Move anyway lookup also matched the refusal toast's
button since #34041; it now takes the pane's own.

* fix(connector): one turn id from the host's stamp everywhere (#33909)

The host's turn-start timestamp is the only turn id the connector uses: snapshots, turn ends and replies all carry it, and the desktop's separate turn cache is gone, so they can no longer disagree. The unused turn-bound cancel was removed (Stop is parked). The hook server reads the main agent state through the same shared accessor.

* feat(orchestration): add a Settings switch to turn worker heartbeats off (#34070)

* feat(orchestration): add a Settings switch to turn worker heartbeats off

Dispatched workers are told to send a heartbeat every 5 minutes. A new
"Worker heartbeats" switch under Settings > Agent Orchestration (on by
default) lets users turn that off: newly dispatched workers are no longer
told to send heartbeats, and the stale-heartbeat check is skipped.

The interval the brief states and the stale check both derive from one
resolver over the live setting, read from the runtime's own store like
the other orchestration settings.

* Test heartbeat preferences across settings and worker dispatch

* Keep focused heartbeat preference contracts

* Explain partial runtime fixture assertion

* Correct CLI integration fixture contracts

* fix(wsl-host): a cold wake that loses orcad recovers by itself instead of leaving a dead pane (#33147)

* fix(wsl-host): a cold wake that loses orcad recovers by itself; stopped-distro refusals stay final

* fix(wsl-host): identity and pairing refusals stay final; no second wake after a stop; settling is retryable

* fix(files): open host files outside workspaces for any client with terminal access (#33958)

* fix(files): open host files outside workspaces for any client with terminal access

Paired clients that can open terminals on a host can already read and write
anything its user can, so the per-terminal provenance gate on files outside
workspaces protected nothing. The host now grants any existing file outside
its workspaces; older hosts get a clear update message instead of a refusal.

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

* fix(files): refuse SSH, device and WSL-home paths instead of misreporting them

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

* perf(files): size grant digests to the file and skip status checks for local fallbacks

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

* fix(files): read procfs files whose stat reports size 0

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

---------

Co-authored-by: Claude <noreply@anthropic.com>

* fix(mobile): resume history sessions with desktop's resume and host rules (#33943)

* fix(terminal): keep ConPTY's viewport top through a width change (#34061)

* fix(terminal): keep ConPTY's viewport top through a width change, checked against a captured transcript

A captured ConPTY 1.23 resize (wsl.exe) shows it keeps the line at the top
of its viewport through every resize and repaints only that viewport. xterm
keeps the cursor's rows instead: a wider grid that rejoins wrapped rows pulls
rows out of scrollback (ConPTY's repaint then overwrites them), and a
narrower one that rewraps pushes rows into it (the repaint then repeats
them). The windowsPty row rule covered neither. ConPTY-backed emulators now
put the top line back on its row after a resize.

* fix(terminal): ConPTY resize correction respects unfinished escapes and history replay

- Skip the widen correction while the parser is inside an escape sequence,
  so a resize landing mid-SGR/OSC no longer aborts the app's sequence.
- Skip it when an app set a scroll region.
- Replay daemon history (cold restore from log, durable rebuild) with the
  live emulator's ConPTY model, so replayed and live screens agree.
- Keep the saved cursor with its text when rows come back on narrowing,
  and never drop a background-coloured blank row.

* fix(terminal): replay a saved log with the resize model of the daemon that wrote it

- A daemon now stamps resizeModel into each session's meta; the history reader uses the ConPTY
  replay model only for a stamped session and keeps xterm's for one an older daemon recorded.
- Fix the DECSC adjustment: xterm keeps savedY absolute, so popping a blank row already keeps
  DECRC on its text; the old +1 sent it to the top row.
- Tests: narrow-direction replay, older-daemon replay, DECSTBM skip, DECSC/DECRC after narrowing,
  a background-coloured blank row kept.

* fix(terminal): take the history resize model from the daemon hosting the session

Main writes history and rebuilds durable checkpoints, but a daemon outlives an app update, so
main's own code is not what the live emulator ran. The daemon now reports its resize model in
hello (older daemons omit it, meaning xterm's); main stamps it into meta on open, restamps it
when a checkpoint starts a fresh log, and rebuilds durable history with it. The client's token
read moved to its own module to keep client.ts under the line limit.

Also clamps a saved cursor (DECSC) on a popped row to the new bottom row, as xterm's reflow does.

* fix(terminal): a disconnect leaves the history resize stamp alone

The client keeps the last daemon's reported model through a disconnect (the next hello replaces
it); undefined, before any daemon has answered, now means unknown and skips the restamp instead
of reading as an older daemon. Tests: a disconnect mid-commit keeps the stamp, and a Sleep-cache
wake onto a newer daemon restamps with its first checkpoint (#34060).

* fix(terminal): read the rebuild's resize model through the history manager

The durable rebuild called client.getDaemonResizeModel() in the checkpoint path, which tests that
fake the client with only request() could not answer, so the rebuild fell back to the live
snapshot. The history manager already holds the hosting model's provider; the rebuild reads it
there, keeping the checkpoint path's client use to request().

* refactor(connector): the desktop takes Discord and Linear conversations as well as Slack (#33927)

The desktop's connector accepts conversations from Slack, Discord and Linear and lists all three sources in its hello; per-source details (the Sent from line) come from one table. Nothing changes until those adapters are configured; behind the experimentalConnectors setting.

* fix(settings): show cookie import as available before skill setup (#34097)

* Linux cookie import says when secret-tool is missing instead of blaming the keyring (#34099)

* fix(browser): report why Linux cookie keys cannot be read

* test: cover cookie warning forwarding across import hosts

* test: place wire fixture cast rationale at assertion start

* fix: declare Linux cookie import warning translations

* test: extract WSL host connector fixture to restore lint (#34132)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* Size tabs to titles and preserve floating panel drag space (#34025)

* Size tabs to titles and preserve floating panel drag space

* Stabilize agent tab layout during activity changes

* Balance tab widths across titles and tab types

* Reserve terminal tab icon space before agent detection

* Run floating header drag E2E in the isolated headful project

* Prevent native text selection on the floating panel drag handle

* Cap expanded tab width at 24rem

* Let tabs expand to fit titles in available space

* test: remove 81 low-value cases and 12 suites (#34130)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(agents): launch Claude Agent Teams as plain orca on Orca servers (#34116)

* fix(agents): launch Claude Agent Teams as plain orca on Orca servers

A paired Orca server has no SSH connection id, so client launches treated it
as a local Linux desktop and typed `orca-ide claude-teams`. Headless servers
only put `orca` on PATH. Client launches now read the resolved execution host
(SSH or server, except WSL workspaces), and launches built on a headless Linux
server use the launcher that server publishes.

Fixes #33920. Reported by @williamhrs. Client-side approach from #33987 by
@coolwindX; #33975 by @Shubham-Padkonde showed the host-built launch gap.

* fix(orcad): keep orca-ide working for older clients on Linux servers

Older clients type the desktop orca-ide claude-teams into server terminals.
Write an identical orca-ide launcher beside orca. Idea and test from #33975
by @Shubham-Padkonde.

* fix(ssh): Stop and remove keeps an SSH host's managed server removed across reload and restart (#34107)

* fix(ssh): Stop and remove keeps the managed server removed across reload and restart (#34003)

* fix(ssh): recheck the removal hold after a queued Stop settles

* fix(ssh): a new managed-server claim lifts the Stop and remove hold

* fix(web): a TUI copy the browser refuses offers a Copy button (#34135)

Browser clipboards need a recent user gesture, and an OSC 52 copy from a
TUI arrives after a host round trip that can outlive it. The web client
now shows a replaceable toast whose Copy click writes the refused text.
Desktop keeps its existing failure toast.

Refs #33937

* fix(editor): let desktop edit host files outside workspaces (#34119)

* fix(files): open host files outside workspaces for any client with terminal access

Paired clients that can open terminals on a host can already read and write
anything its user can, so the per-terminal provenance gate on files outside
workspaces protected nothing. The host now grants any existing file outside
its workspaces; older hosts get a clear update message instead of a refusal.

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

* fix(files): refuse SSH, device and WSL-home paths instead of misreporting them

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

* perf(files): size grant digests to the file and skip status checks for local fallbacks

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

* fix(files): read procfs files whose stat reports size 0

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

* fix(editor): let desktop edit host files outside workspaces

Paired clients with terminal access can already write any file on the host, and
phones can now save these files, so desktop grant tabs open editable too. Saves go
through the host grant, renewing it when it lapsed and keeping the disk-change check;
a grant tab never falls back to writing this computer's same path.

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

* fix(editor): renew lapsed host grants for reads, banners and restored tabs

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

* fix(editor): ask older hosts for an update instead of reporting a lapsed grant as deleted

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

* fix(editor): keep grant tabs read-only on hosts that cannot renew grants

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

* fix(editor): check a discarded save right before the grant write is sent

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

* fix(editor): pin grant saves to one pairing and grant restored tabs before saving

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

* fix(editor): open grant tabs read-only when the host cannot be asked, and restore read-only grants as read-only

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

* fix(editor): pin a restored tab's grant request to the save's pairing

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

* fix(editor): treat only a proven not-found as a missing granted file

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

* fix(editor): keep restored drafts by refusing read-only grant saves instead of locking the tab

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

* fix(editor): read a restored grant on the pairing that issued it and keep read-only grants off the tab

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

* fix(editor): let every reader of a restored host-file tab ask its host for a grant

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

* fix(editor): add no await before ordinary reads and saves pin their pairing

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

* fix(editor): explain unrecreatable deleted host files and hide rename for grant tabs

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

* fix(editor): move the grant capability probe out of the store-importing module to break an import cycle

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

* fix(editor): renew grants without cross-workspace retargeting and settle saves whose reply was lost

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

* fix(editor): read back a lost write reply through a fresh grant after a disconnect

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

* fix(editor): trust only an unanswered write with byte-exact readback as saved

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

* fix(editor): read back only sent writes that lost their connection, including desktop timeout envelopes

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

---------

Co-authored-by: Claude <noreply@anthropic.com>

* fix(runtime-environments): keep session partitions of saved servers the listing hides (#34134)

The registry watcher now reconciles orphaned runtime sessions on every
write, so the reconcile must only drop hosts the file proves are gone. It
read the filtered listing, which omits newer-format records and servers
hidden by an unreadable sidecar or WSL overlay, and checked file presence
before reading, so a file vanishing in between read as an empty registry.
Build the known set from every raw record id, fail closed on a missing
file or an id-less record, and keep the catalog broadcast running if the
reconcile throws. Follow-up to #34101.

* fix(session-tabs): keep the server's per-device tab pick on the tab the desktop shows (#34082)

* fix(session-tabs): keep the server's per-device tab pick on the tab the desktop shows

The server hands its remembered pick back whenever the desktop has no tab groups of its own for a workspace. A desktop that kept its groups never reported what it showed, so that pick went stale and such an open landed on the wrong tab.

* fix(session-tabs): report only a ready visible pane, and retry after an error answer

Name the pane the desktop shows and require it ready, so a report never starts a pending sibling's terminal. A failure envelope no longer marks the pick as reported.

* fix(session-tabs): report a desktop's pane once per change and connection

Two windows sharing one device id could steer the pick back and forth. Report again only when this desktop's own pane changes, scope the record to the pairing and connection, and resolve the visible tab with the existing helper.

* fix(session-tabs): report only the on-screen workspace, compare panes, and remember agreement

Reports stay with the workspace on screen, whose pane attaches anyway, so a report never starts a terminal elsewhere. The pick is compared pane for pane, and an agreeing frame records the pane so a later change of this desktop's pane reports again.

* fix(session-tabs): settle before reporting, report on opening a workspace, and only to its owner

A click records its activation after an async hop, so a report now waits until the pane settles and compares against the latest frame. Opening a workspace reports from its latest frame. A workspace id two servers share is reported only to its owner. The e2e now drives the real flow: a stale pick, then a desktop restart.

* fix(session-tabs): keep one outstanding pick check per workspace, fenced to its connection

A busy workspace's frames no longer postpone the check. A frame from a replaced pairing or connection is dropped, and a frame without the per-device projection clears the cached one.

* fix(session-tabs): bound the pick report caches and clear them on mirror teardown

One record per workspace, with the connection in the value. Environment teardown drops reports, frames and timers. The tests use checked types, and the e2e notes why it waits and why it needs more time.

* fix(session-tabs): check again when the user moved on before a report finished

The host does not order activations, so a report that completes after the user picked another pane may have landed last. Clear its record and recheck from the latest frame.

* fix(session-tabs): type the visible pane's leaf as optional

* fix(session-tabs): send a browser or chat pick again when a late report landed after it

A terminal report that completes after the user picked a browser or chat tab may have had the last word. Re-send that pick the way a click does.

* fix(session-tabs): recheck a late report against the host's answer, and fence it to teardown

The activate answer is the host's per-device frame after the report, so a late landing is checked against it instead of a cached frame. A report answered after mirror teardown or a new connection does nothing.

* test(session-tabs): drop the in-connection suppression check from the restart e2e

Whether the desktop repairs a stale pick within the connection depends on which frames settle first; the guarded outcome is the pick after a restart.

* fix(session-tabs): reconcile the user's newer pick after any report outcome, timeouts included

A report whose answer timed out may still have landed after the user's newer pick. Settle every outcome the same way: retry on failure, then reconcile with what the desktop shows.

* fix(source-control): stream large Antigravity generation prompts over stdin (#34148)

* fix(rate-limits): show agy's own error when Antigravity usage can't be read (#34106)

When agy refuses a usage read with its own error envelope (for example the location eligibility rejection), Orca now shows agy's text, redacted and bounded to one line, instead of the generic "did not report a quota" message. Existing failure precedence and the last good quota bars are unchanged.

Fixes #33426

* fix(antigravity): save an agy account whose credential has no id_token (#33580)

agy 1.4.7 stores no id_token, so Save current account stayed disabled and the account could not be saved. Save now asks Google's userinfo endpoint which account owns the current access token (only on the Save click), then saves it, or updates the saved account with the same Google subject. The credential is re-read after the lookup, and nothing is saved if it changed.

Fixes #33323

* Refine lint performance and safe process execution (#34147)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(agent-status): keep an Antigravity run working while its helper agents finish (#34128)

When an Antigravity parent ends its turn to wait for invoke_subagent helpers, agy reports the parent's Stop as fullyIdle=false, but its own terminal status says done at each turn end. After two minutes of hook silence Orca let that terminal done replace the hook row, so automations completed while helpers were still working. The parent's busy Stop now marks the row as held open for helpers, and a program's non-boundary done can no longer settle a row held open for child work. Late helper hooks after a completed turn are rejected before they touch parent state.

Verified with real agy 1.4.7: helpers slower than two minutes ended runs early on main (3/3) and complete with all helper output and the final report on this change.

Fixes #33973

* fix(mobile): match history sessions and scope paths with desktop's rules (#33955)

* test: load real modules before timed waits, and ratchet in-test vi.importActual (#34151)

* test: load real modules before timed waits, and ratchet in-test vi.importActual

Two tests paid a cold real-module load inside their timed wait:
- the empty-remote wake test's 1s vi.waitFor raced the post-create refresh's
  lazy session-tabs import; it now loads those modules in beforeAll;
- the runtime label-only create tests called vi.importActual inside each test
  (19-23s of the 30s budget on the first case); it now runs in beforeAll.

test-no-in-test-import-actual flags vi.importActual outside vi.mock/doMock/
hoisted factories, beforeAll and module scope; the 50 existing findings are
grandfathered in the flaky-test ratchet baseline.

* test: flag vi.importActual in a doMock factory registered inside a test

* test: flag vi.importActual in any vi.doMock factory; its load runs on the next import

* test: remove 47 low-value cases and 13 suites (#34136)

* test: remove 37 low-value cases and 3 suites

* test: delete ten more renderer wiring and copy suites

* test: drop deleted suite from its contract entry point

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* Compact worktree project and host pickers with stacked details (#34098)

* Compact worktree project and host pickers with stacked details

* Align worktree picker markers and action gutters

* Extract WSL connector fixture to satisfy file length limit

* Restart CI after resolving upstream fixture conflict

* refactor: group remote runtime client modules (#34133)

* Revert benchmark-only startup loading study (#33912) (#34162)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* test: remove 294 low-value cases and 12 suites (#34156)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(connector): the Discord gateway sends queued posts, so its replies don't wait for the API to wake (#34131)

The always-on Discord gateway worker now runs the same background sweeps as the API (queued posts, held starts, cleanup), so Discord replies go out at once instead of waiting for the scaled-to-zero API to wake. Posts are claimed with leases, so running the sweeps in both services never sends one twice.

* refactor(mobile): share agent child-row text and favicon domains with desktop (#33962)

* refactor(mobile): share child-row detail text and agent favicon domains with desktop

* refactor: share the agent tool preview line with child rows

* refactor: translate the child-row Ended label only when shown

* fix(mobile): show chat images stored on the host as thumbnails (#33731)

* fix(mobile): show chat images stored on the host as thumbnails

Fixes #33554

* fix(mobile): read stored chat images two at a time

A burst of megabyte replies over a slow link overflows the host's outbound queue and drops the phone's socket.

* refactor(mobile): tidy stored chat image read

* fix(mobile): skip stored image reads for rows that already left

Also ignore a result read through a different host client.

* feat(connector): each Slack app verified with its own signing secret at its own URL (#34125)

Groundwork for per-company Slack apps. Each Slack app gets its own row with encrypted secrets, and Slack posts to /slack/apps/<app id>/..., where the address only selects which secret to check; a request acts only in a workspace where that app is installed. Rate limits are per address and per app, so one workspace can't hold up another's posts. Schema changes are additive. The existing staging app keeps working on the old route until a documented cutover. Inert for users.

* test: remove 368 low-value cases and 4 suites (#34157)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>

* fix(source-control): account for Windows quoting when fitting argv prompts

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Co-authored-by: OrcaWin <alpha-eng@stably.ai>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Manan <100475418+thefrikidude@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
2026-10-26 18:37:51 -07:00
OrcaWinandOrcaWin 7d6603aa17 [comment audit] Complete repository-wide comment cleanup (#33249)
* [comment audit] Align legacy failure-read counts with cached display

* [comment audit] Condense shared provider lifecycle and browser recovery comments [skip ci]

* [comment audit] Condense shared generation, path and preview comments [skip ci]

* [comment audit] Condense host, file and Git contract rationale [skip ci]

* [comment audit] Tighten Git lifecycle and provider contract comments [skip ci]

* [comment audit] Clarify shared host authority and launch isolation [skip ci]

* [comment audit] simplify local access mobile and native chat contracts [skip ci]

* [comment audit] simplify native chat presentation and state contracts [skip ci]

* [comment audit] simplify native runtime and provider contracts [skip ci]

* [comment audit] simplify migration and orchestration contracts [skip ci]

* [comment audit] simplify plugin trust and process capture rationale [skip ci]

* [comment audit] simplify terminal delivery and remote compatibility rationale [skip ci]

* [comment audit] clarify remote recovery and launch wire rationale [skip ci]

* [comment audit] shorten shared RPC compatibility and runtime evidence comments [skip ci]

* [comment audit] simplify secure storage shell startup and sidebar rationale [skip ci]

* [comment audit] clarify sidebar, skill and SSH invariants [skip ci]

* [comment audit] condense structured chat delivery and timing rationale [skip ci]

* [comment audit] condense terminal replay and telemetry invariants [skip ci]

* [comment audit] clarify launch permission and terminal delivery rationale [skip ci]

* [comment audit] clarify workspace ownership and layout contracts [skip ci]

* [comment audit] wait for fitted and painted SSH terminal links

* [comment audit] clarify layout persistence and session ownership [skip ci]

* [comment audit] clarify host routing and workspace lifecycle contracts [skip ci]

* [comment audit] clarify startup persistence and app lifetime comments [skip ci]

* [comment audit] clarify recovery and activity boundaries [skip ci]

* [comment audit] condense activity and artifact invariants [skip ci]

* [comment audit] condense automation authority contracts [skip ci]

* [comment audit] simplify automation scheduling and history contracts [skip ci]

* [comment audit] clarify browser chrome and annotation lifecycles [skip ci]

* [comment audit] clarify browser routing and retained guest ownership [skip ci]

* [comment audit] clarify browser recovery and document ownership comments [skip ci]

* [comment audit] restore hosted runners required by native IME fixtures

* [comment audit] shorten preview, palette and dashboard invariants [skip ci]

* [comment audit] clarify terminal preview, dashboard and retention comments [skip ci]

* [comment audit] clarify diff-note recovery and editor lifecycle comments [skip ci]

* [comment audit] shorten rich-text and combined-diff ownership comments [skip ci]

* [comment audit] shorten autosave, draft recovery and model ownership comments [skip ci]

* [comment audit] shorten save-queue, notebook and Markdown constraints [skip ci]

* [comment audit] shorten Monaco, PDF and rich Markdown safeguards [skip ci]

* [comment audit] clarify rich Markdown source and selection safeguards [skip ci]

* [comment audit] clarify editor loading and emulator stream lifetimes [skip ci]

* [comment audit] trim emulator and feature tour narration [skip ci]

* [comment audit] clarify floating workspace and GitHub cache ownership [skip ci]

* [comment audit] trim provider controls and Linear filter explanations [skip ci]

* [comment audit] clarify pairing and chat resume lifetimes [skip ci]

* [comment audit] clarify chat delivery and transcript lifetimes [skip ci]

* [comment audit] clarify session options and host-owned status [skip ci]

* [comment audit] clarify draft durability and live-status precedence [skip ci]

* [comment audit] Trim chat send and model ownership explanations [skip ci]

* [comment audit] Shorten transcript ownership and send recovery comments [skip ci]

* [comment audit] Simplify native chat composer and transcript hook comments [skip ci]

* [comment audit] Shorten native chat scroll and structured session explanations [skip ci]

* [comment audit] Trim workspace picker and onboarding commentary [skip ci]

* [comment audit] Simplify pet rendering, review cache and quick open comments [skip ci]

* [comment audit] Trim sidebar and session history explanations [skip ci]

* [comment audit] Condense session resume and review checks comments [skip ci]

* [comment audit] Shorten checks state and file explorer refresh comments [skip ci]

* [comment audit] Trim plugin bridge and source-control action rationale [skip ci]

* [comment audit] Trim source-control listing and review rationale [skip ci]

* [comment audit] Shorten sidebar lifecycle and explorer safeguards [skip ci]

* [comment audit] Condense Settings account and appearance rationale [skip ci]

* [comment audit] Trim pairing and repository Settings explanations [skip ci]

* [comment audit] Condense Settings search SSH and terminal safeguards [skip ci]

* [comment audit] Shorten Settings voice and provider ownership comments [skip ci]

* [comment audit] Condense Settings draft persistence and host-state rationale [skip ci]

* [comment audit] Trim Settings hooks and sidebar setup rationale [skip ci]

* [comment audit] Condense sidebar deletion and board-filter safeguards [skip ci]

* [comment audit] Condense worktree cards, host ownership and Markdown contracts [skip ci]

* [comment audit] Condense sidebar drag, folder and filtering contracts [skip ci]

* [comment audit] Condense sidebar parity, sleep and host ownership contracts [skip ci]

* [comment audit] Prune focus-read baseline after comment cleanup

* [comment audit] Clarify sidebar visibility, board drops and agent evidence [skip ci]

* [comment audit] Tighten sidebar listing, drag and reveal contracts [skip ci]

* [comment audit] Clarify viewport geometry and skill update safeguards [skip ci]

* [comment audit] Tighten skill inventory, usage and host status comments [skip ci]

* [comment audit] Clarify usage ownership and resource kill safeguards [skip ci]

* [comment audit] Tighten tab selection, rename and search contracts [skip ci]

* [comment audit] Tighten tab-strip geometry and drag ownership comments [skip ci]

* [comment audit] Tighten Tasks recovery, pagination and mutation comments [skip ci]

* [comment audit] Tighten provider loading and terminal recovery comments [skip ci]

* [comment audit] Tighten completion, cadence and PTY ownership comments [skip ci]

* [comment audit] Clarify terminal restore and parked-pane boundaries [skip ci]

* [comment audit] Tighten PTY startup and replay explanations [skip ci]

* [comment audit] Clarify PTY identity and delivery ownership [skip ci]

* [comment audit] Shorten remote reconnect and input replay rationale [skip ci]

* [comment audit] Condense terminal parking clipboard and file link comments [skip ci]

* [comment audit] Clarify IME ownership and trim trace history [skip ci]

* [comment audit] Shorten pane recovery and parked watcher explanations [skip ci]

* [comment audit] Condense snapshot replay and visibility recovery rationale [skip ci]

* [comment audit] Shorten terminal parking and keyboard ownership rationale [skip ci]

* [comment audit] Trim renderer lifecycle and menu rationale [skip ci]

* [comment audit] Condense workspace cleanup ownership and settlement notes [skip ci]

* [comment audit] Clarify renderer hook evidence and source ownership [skip ci]

* [comment audit] Tighten IPC ownership and reconnect explanations [skip ci]

* [comment audit] Trim renderer focus, paste and attention comments [skip ci]

* [comment audit] Shorten scroll, locale and agent lifecycle comments [skip ci]

* [comment audit] Trim agent launch, resume and ownership commentary [skip ci]

* [comment audit] Shorten account, browser and editor comments [skip ci]

* [comment audit] Clarify host-mirror waits, previews and input ownership [skip ci]

* [comment audit] Condense launch recovery and editor tokenization comments [skip ci]

* [comment audit] Condense workspace selection and terminal pane rationale [skip ci]

* [comment audit] Condense terminal fitting and rendering recovery comments [skip ci]

* [comment audit] Condense terminal input and host routing explanations [skip ci]

* [comment audit] Condense ownership and sleeping-session recovery rationale [skip ci]

* [comment audit] Condense structured launch and terminal link explanations [skip ci]

* [comment audit] Condense terminal ownership and workspace file routing rationale [skip ci]

* [comment audit] Condense session persistence and workspace activation rationale [skip ci]

* [comment audit] Condense workspace routing and browser ownership rationale [skip ci]

* [comment audit] Condense mirror recovery and layout authority rationale [skip ci]

* [comment audit] Condense runtime transport and file safety rationale [skip ci]

* [comment audit] Condense runtime graph and structured session rationale [skip ci]

* [comment audit] Condense browser creation and remote tab recovery rationale [skip ci]

* [comment audit] Condense snapshot authority and publisher recovery rationale [skip ci]

* [comment audit] Condense frame, startup and provider cache rationale [skip ci]

* [comment audit] Condense host twin and agent lifecycle rationale [skip ci]

* [comment audit] Condense browser authority and editor cleanup rationale [skip ci]

* [comment audit] Condense editor buffer identity and review cache rationale [skip ci]

* [comment audit] Condense provider lifetime and repository ownership rationale [skip ci]

* [comment audit] Condense reconnect, hydration and terminal retirement rationale [skip ci]

* [comment audit] Condense recovery, reconciliation and persistence rationale [skip ci]

* [comment audit] Condense cleanup ownership and listing admission rationale [skip ci]

* [comment audit] Condense teardown ordering and terminal ownership rationale [skip ci]

* [comment audit] Condense recovery ledger and web host-boundary rationale [skip ci]

* [comment audit] Condense web reconnect and credential lifecycle rationale [skip ci]

* [comment audit] Condense cloud rollout and assignment safety rationale [skip ci]

* [comment audit] Condense relay session and database recovery rationale [skip ci]

* [comment audit] Condense relay placement and protocol compatibility rationale [skip ci]

* [comment audit] Condense build and packaging constraints [skip ci]

* [comment audit] Condense CI gates and validation isolation rationale [skip ci]

* [comment audit] Condense catalog identity and browser validation rationale [skip ci]

* [comment audit] Condense mobile browser and frame-budget rationale [skip ci]

* [comment audit] Shorten mobile route and browser test explanations [skip ci]

* [comment audit] Condense editor and session seam test rationale [skip ci]

* [comment audit] Trim session and terminal closure history [skip ci]

* [comment audit] Shorten terminal browser and census explanations [skip ci]

* [comment audit] Preserve root-only E2E diagnostic baseline

* [comment audit] Condense mobile seam and HTML preview test rationale [skip ci]

* [comment audit] Condense preview instrumentation and render harness rationale [skip ci]

* [comment audit] Condense bundle contracts and native-build constraints [skip ci]

* [comment audit] Shorten native packaging and CI routing rationale [skip ci]

* [comment audit] Condense release tooling and benchmark constraints [skip ci]

* [comment audit] Condense packaging and platform gate rationale [skip ci]

* [comment audit] Shorten mobile route and history rationale [skip ci]

* [comment audit] Condense mobile browser and component rationale [skip ci]

* [comment audit] Shorten drawer and workspace-form rationale [skip ci]

* [comment audit] Trim mobile review and editor-document explanations [skip ci]

* [comment audit] Condense editor lifecycle and Markdown explanations [skip ci]

* [comment audit] Trim mobile file, diagnostics and dictation commentary [skip ci]

* [comment audit] Simplify mobile host-list and workspace-view explanations [skip ci]

* [comment audit] Clarify mobile shell lifetime and bridge delivery constraints [skip ci]

* [comment audit] Condense bridge stream, native request and audio rationale [skip ci]

* [comment audit] Reduce bridge schema and page-client commentary [skip ci]

* [comment audit] Tighten mobile page bridge contracts [skip ci]

* [comment audit] Clarify mobile cache and session constraints [skip ci]

* [comment audit] Condense mobile route and lifecycle rationale [skip ci]

* [comment audit] Tighten mobile shell hook timing rationale [skip ci]

* [comment audit] Clarify route handoff and notification compatibility [skip ci]

* [comment audit] Clarify push registration and dictation cleanup constraints [skip ci]

* [comment audit] Condense keyboard geometry and native media ownership rationale [skip ci]

* [comment audit] Tighten mobile chat scroll and composer concurrency rationale [skip ci]

* [comment audit] Condense mobile reply compatibility and upload ownership rationale [skip ci]

* [comment audit] Condense optimistic echo and scroll ownership rationale [skip ci]

* [comment audit] Tighten stream replay and queued session ownership rationale [skip ci]

* [comment audit] Condense mobile composer and reply-schema constraints [skip ci]

* [comment audit] Clarify mobile transcript recovery and session ownership [skip ci]

* [comment audit] Clarify mobile queue and source-control compatibility [skip ci]

* [comment audit] Condense storage and task launch constraints [skip ci]

* [comment audit] Clarify task schemas and terminal document ownership [skip ci]

* [comment audit] Tighten terminal input and viewport rationale [skip ci]

* [comment audit] Shorten terminal and RPC recorder contracts [skip ci]

* [comment audit] Condense recorder engine and connection contracts [skip ci]

* [comment audit] Shorten host credential and relay recovery comments [skip ci]

* [comment audit] Tighten pairing recovery and bundle transport rationale [skip ci]

* [comment audit] Clarify RPC delivery and workspace catalog boundaries [skip ci]

* [comment audit] Condense catalog and relay entry contracts [skip ci]

* [comment audit] Shorten shutdown and SSH relay delivery contracts [skip ci]

* [comment audit] Condense WSL relay and E2E regression rationale [skip ci]

* [comment audit] Shorten cross-version harness and renderer fixture explanations [skip ci]

* [comment audit] Condense paired-host and E2E lifecycle rationale [skip ci]

* [comment audit] Shorten layout oracle and regression explanations [skip ci]

* [comment audit] Condense paired recovery and ownership regression contracts [skip ci]

* [comment audit] Shorten restart, sidebar and SSH lifecycle contracts [skip ci]

* [comment audit] Condense terminal rendering and IME regression rationale [skip ci]

* [comment audit] Shorten terminal recovery and benchmark contracts [skip ci]

* [comment audit] Condense tooling and Windows lifecycle proof rationale [skip ci]

* [comment audit] Condense workflow routing and release rationale [skip ci]

* [comment audit] Condense mobile security and installer contracts [skip ci]

* [comment audit] Shorten native rationale and stylesheet workarounds [skip ci]

* [comment audit] Shorten Windows visibility probe rationale [skip ci]

* [comment audit] Condense embedded release and signing rationale [skip ci]

* [comment audit] Retain current main test behavior in final reconciliation [skip ci]

* [comment audit] Complete final comment review across current source inventory

* [comment audit] Handle consolidated audit reports before final CI

* [comment audit] Preserve credential storage census detail [skip ci]

* [comment audit] Scale broad changed E2E selections with verified timing shards

* [comment audit] Align E2E assertions with browser close and settled session metadata

* [comment audit] Match existing E2Es to current resource and windowing contracts

* [comment audit] Observe the shared server outage notice in reconnect coverage

* [comment audit] Make existing renderer probes measure settled tab and PTY work

* [comment audit] Align palette E2E selector with task search

* [comment audit] Refresh remaining palette search selectors

* [comment audit] Keep selector correction within selected audit specs

* [comment audit] Await emoji fixture settings inside renderer evaluation

* [comment audit] Cancel fixture fit retries between terminal tests

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 04:05:46 -07:00
Neil 77f23b013f refactor(shared): drop the shared/types barrel and import from the real modules (#14447)
#14397 split `shared/types.ts` into 46 per-domain modules but kept the path as
a re-export barrel so the import sites did not have to change. This removes
the barrel: every consumer now imports from the module that actually declares
the type, and `src/shared/types.ts` is deleted.

Barrels hide where a type lives, make every consumer look like it depends on
the whole domain, and let an unrelated edit invalidate a module that ~2,000
files transitively import.

2,323 import declarations across 2,321 files. Rewritten mechanically: each
specifier was resolved to an absolute path via the TypeScript AST and
recomputed, rather than string-substituted, so alias forms (`@/../../shared/
types`) and per-specifier `type` modifiers survive.

Four cases the mechanical pass had to handle, each found by a gate rather than
by reading the diff:

- Modules inside `src/shared` import the barrel as `./types`, not
  `shared/types`. A pre-filter on the latter string skipped 176 of them and
  left imports dangling at a deleted file, which surfaced as confusing
  `Property 'x' is optional in type 'Repo' but required in Pick<Repo, ...>`
  errors rather than "module not found".
- The barrel RENAMED one type on the way through
  (`WorkspaceSource as WorkspaceCreateTelemetrySource`), so the original name
  in the owning module has to be re-aliased at each consumer.
- Three test files put `;(globalThis as ...)` on the line after the import.
  TypeScript parses that `;` as the import statement's terminator, so
  replacing through `statement.getEnd()` deletes it and breaks ASI. The
  rewrite now stops at the module specifier.
- A file that already imported directly from a module got a SECOND import
  from it, because the barrel re-exported those same names — which trips
  `import/no-duplicates` under `--deny-warnings`. A post-pass merges
  declarations sharing a specifier and type-only-ness; the `import type` plus
  `import` pair from one module is left alone, since that form is allowed.

Splitting one barrel import into several genuinely adds lines, which pushed
`terminal-layout-pty-ownership.ts` to 301 counted lines: its 107-character
import must wrap, and neither local type collapses onto one line (101 and 116
characters). Rather than contort a type declaration to fit a line budget,
`collectLeafIds` and `pruneLeaves` move to `terminal-pane-layout-tree.ts` —
they are pure structural operations on the layout tree and independent of PTY
ownership. `visible-worktrees.ts` similarly loses its own mini-barrel
re-export of `isDefaultBranchWorkspace`, with the four real consumers
repointed at the declaring module. No `max-lines` bypass added.

Verified: cold `tsc --noEmit` green on node, cli, and web (buildinfo deleted
first — these projects are `composite: true` and reuse stale caches); the full
`pnpm lint` green, not just bare oxlint — the narrower local check is what let
the duplicate imports reach CI; max-lines ratchet OK at 344.
2026-08-13 22:48:24 -07:00
NeilandOrca 73c5009b82 chore(dead-code): drop ~2k lines of unreachable exports and orphan modules (#12077)
* chore(dead-code): drop 2k lines of unreachable exports and orphan modules

Ran knip across every build entry (main, preload, renderer, popout, web,
cli, relay, workers, forked sidecars, config scripts) and removed what no
entry graph can reach.

- 11 orphan modules nothing imported, plus one test that only covered them
- 159 unused exports/types, with their now-dead helpers, imports and tests

Each candidate was verified against dynamic references before deletion.
42 knip hits were false positives and are kept: shared modules consumed by
the mobile/ workspace, the src/shared/plugins/** public API, vendored
shadcn primitives, and relay wire-protocol constants held for compatibility.

Adds knip.json + `pnpm audit:dead-code` so this stays measurable.

Verified: pnpm typecheck, pnpm lint, and 2081 tests across the 73 affected
test files all pass.

* chore(dead-code): move knip config under config/

Root-level additions are blocked by the root directory guard.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-02 00:33:57 -07:00
JinjingandOrca ca70be8318 Add {linkedIssue} template variable for commit and PR generation (#10640)
* feat(source-control-ai): add {linkedIssue} recipe variable for commit and PR prompts

Custom commit-message and pull-request recipes can now reference the GitHub
issue linked to the workspace, so a template like "Fixes #{linkedIssue}" lands
the closing trailer without the user retyping the number.

- register `linkedIssue` on the commitMessage and pullRequest actions only,
  with the VARIABLE_INFO entry the chip hover card requires
- substitute unconditionally via `formatLinkedIssueTemplateValue` (empty string
  when nothing resolves) so the token never survives into a prompt; enrich the
  draft context conditionally via `withLinkedIssueDraftContext` so unlinked
  workspaces keep their existing context shape
- attach at the 7 call boundaries (runtime commit x2, runtime PR shared, IPC
  commit x2, IPC PR x2); the pure git gather stays pure
- validate the renderer-supplied worktreeId against the request path and repoId
  before any meta read, comparing SSH paths as raw strings so a Windows host
  cannot rewrite a remote POSIX path
- built-in prompts are unchanged; no GitLab dual-read and no default trailer

* fix(source-control-ai): resolve {linkedIssue} adversarial review findings

Addresses 13 of the 14 findings from the {linkedIssue} code review
(6 minor, 8 nit, 0 critical, 0 major); Issue 5 (GitLab provider naming)
is deferred to design Open Question 3 as product expansion.

Behavior:
- Dialog previews the workspace's real linked issue instead of the
  synthetic 123, in both the chip hover card and the plan preview, so an
  unlinked workspace previews the `Fixes #` it will actually generate.
  Settings dry-runs stay fully synthetic.
- Reject non-positive, fractional and unsafe-integer issue numbers at the
  IPC resolver via a shared isLinkedIssueNumber predicate, so corrupt meta
  never reaches a draft context (previously -7 rendered `Fixes #-7` and
  1e21 rendered `Fixes #1e+21`).
- Fail closed on an empty-string repoId instead of skipping the cross-check.

Structure:
- Split the variable registry into source-control-ai-action-variables.ts
  and re-export it, restoring max-lines headroom with no consumer churn
  and no lint disable.
- Constrain withLinkedIssueDraftContext to contexts declaring linkedIssue.
- Move the misplaced shared imports into their import group.

Docs and tests:
- Document that the IPC id/path validator guards relay/CLI/future callers,
  not the renderer (whose path is id-derived), and rename the three tests
  that read as proof of a protection that cannot fire.
- Add PR-side coverage that was missing: three git:generatePullRequestFields
  handler tests, a built-in PR prompt no-leak guard, and the runtime PR
  unlinked case.
- Replace the coincidental '42' assertion with a fixture-unique sentinel.
- Type the runtime worktree fixture with satisfies, which surfaced and
  fixed pre-existing drift in its git sub-object.
- Add an e2e case covering the preload -> main -> meta -> template chain.

Co-authored-by: Orca <help@stably.ai>

* fix(source-control-ai): resolve {linkedIssue} adversarial re-review findings

Addresses all 8 findings from the {linkedIssue} code re-review
(2 minor, 6 nit, 0 critical, 0 major); none deferred.

Behavior:
- Revert the variableOverrides parameter on planSourceControlTextGeneration.
  Its result is a Save/Generate gate, not a preview, and the recipe it
  validates is saved repo- or globally scoped -- so rendering it against the
  active workspace disabled both buttons with "Command input is empty." for a
  {linkedIssue}-only template on any unlinked workspace, blocking a global
  settings write. Validation is synthetic again; chip previews are unchanged.
- Make the chip hover card additive instead of either/or. A supplied preview
  now appends a "This workspace" sample below the description and Example
  rather than replacing them, so the GitLab-empty and dangling `Fixes #`
  warning survives on the two dialogs where recipes are actually authored.
  basePrompt keeps its preview-only shape, where the preview is the content.

Structure:
- Drop the registry re-export from source-control-ai-actions.ts and move the
  last two consumers onto source-control-ai-action-variables, so one import
  path per symbol keeps a grep of the registry's consumers complete.
- Split the registry/helper suites into source-control-ai-action-variables.test.ts
  so each test file mirrors its module.

Tests:
- Cover the Save/Generate gate at the canRunGeneration level for a bare
  {linkedIssue} recipe on linked and unlinked workspaces, with a negative
  control proving the buttons can still be disabled.
- Cover the chip hover card directly; the dialog tests mock it away.
- Guard the PR mismatched-id test with toHaveLength(1) so it cannot pass
  vacuously on an unrelated early return.
- Add an unlinked-workspace e2e case (saw-issue:empty), which is what
  distinguishes a real resolver from one that always returns a number.
  Spec now runs green: 3 passed.
- Rename the dialog test that claimed a synthetic-fallback assertion it did
  not make, and route its renders through one shared helper.

Docs are worktree-local (.gitignore:84 ignores docs/**): the design doc's
plan-preview and chip-surface claims, the manual QA rows, and both reviews'
statements about pre-existing PR-handler tests are corrected there.

* fix(source-control-ai): make the {linkedIssue} e2e guard and dialog test falsifiable

The e2e unlinked case extracted the echoed issue with `ORCA_E2E_ISSUE=(\d*)`,
which matches zero digits in front of an unexpanded `{linkedIssue}` and reported
it as `empty` — so the case that exists to catch a literal token surviving into
a prompt passed on exactly that regression. Capture the whole line instead: a
literal now arrives as `saw-issue:{linkedIssue}` and fails, verified by dropping
the substitution key for unlinked contexts and watching the case go red.

Also drop the inert `not.toContain('Command input is empty.')` assertion — that
copy is click-driven `generationError` state and this suite renders statically,
so it could never fail; the claim it reached for is carried by the plan test.
Rename two plan tests off the "plan preview" framing the design now rejects.

Local review artifacts (design doc, implementation notes, final review) were
swept to match the tree in the same pass; they are gitignored here.

* Resolve {linkedIssue} from live metadata, not cache

Resolved worktrees are cached for a second, causing commit and PR
generation to use stale linked-issue state. Hosts now implement
getWorktreeLinkedIssue to provide fresh issue metadata by worktree id,
with proper fallback for unlinked workspaces. Updates both commit
message and PR field generation paths; includes integration and e2e
coverage.

* Keep cached linkedIssue when metadata is unavailable

Return undefined from getWorktreeLinkedIssue when live metadata cannot be read
(store not ready), distinguishing it from null (unlinked). The caller now falls
back to the cached worktree value instead of treating unavailable as unlinked.

Also extract the linked-issue echo generator as a shared e2e test helper.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-25 19:31:44 -07:00
Jinwoo Hong 972078f2c4 Fix paste ownership, input bounds, and IPC validation
Supersedes #5745, #5746, and #5747.
2026-06-19 17:14:55 -07:00
Jinjing 256e0ef81a Handle buffer overflows gracefully and truncate diffs fairly (#5083)
- Gracefully fall back to file-name summaries when staged diffs exceed
  node/ssh execution maxBuffer limits, preventing generation failures.
- Split oversized diffs by file and allocate budget via water-filling,
  ensuring single huge files do not starve smaller human changes.
- Clip truncated diff sections on line boundaries to avoid half-lines.
2026-06-09 23:56:36 -07:00
Brennan BensonandOrca e4ac0df51d Clean up auto branch rename settings (#3378)
Co-authored-by: Orca <help@stably.ai>
2026-05-30 12:44:04 -07:00
Jinjing e9bf07643e Enable AI commit messages by default (#2060)
* test commit

* fix: address review findings
2026-05-15 21:33:59 -07:00
b030257c3b feat(source-control): AI commit message generation (#1487)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: brennanb2025 <brennankbenson@gmail.com>
2026-05-15 02:18:46 -07:00