Skip to content

chore: sync main into phase3 (sync 5) - #26147

Merged
OrcaWin merged 10 commits into
OrcaWin/node-rt-phase3from
OrcaWin/node-rt-phase3-sync5
Oct 7, 2026
Merged

OrcaWin merged 10 commits into
OrcaWin/node-rt-phase3from
OrcaWin/node-rt-phase3-sync5

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 28 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1204 $\color{#cf222e}{\Huge{\mathbf{−}}}$​204 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1000
Prod 38 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​838 $\color{#cf222e}{\Huge{\mathbf{−}}}$​456 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​382

Summary

Merges current main (47f4d3f, 8 commits) into OrcaWin/node-rt-phase3, then phase3's new tip b71dbe4 (#26087), so #24863 is mergeable again. Real merge commits; both sides are kept, and main-owned files stay identical to main.

Conflicts and resolutions

  • config/scripts/run-node-server-tests.mjs: both sides fixed the same problem, where vitest 5 ignores a CLI --exclude for inline projects, so Electron probes ran in the headless node-server containers and failed for lack of a display. Phase 3 resolved the selectors with an extra vitest list process; main (fix(ci): actually exclude Electron probes from the headless node-server lanes #26093) globs the unit include list and filters it. Took main's version, which is now identical to main. Locally the node-server lane still selects the same 96 files (1060 tests pass under the pinned Node).

Other main changes checked against Phase 3

Verification

  • pnpm install --frozen-lockfile and full pnpm tc: pass
  • oxlint on every file the merge changed, check:code-quality:changed against both phase3 and origin/main: 0 findings
  • check:max-lines-ratchet, check:runtime-electron-ratchet, check:ts-nocheck-ratchet, check:reliability-gates: pass
  • Touched suites pass: runtime worktree create, agent-launch RPC, worktree RPC, orca-runtime, renderer agent-launch and source-control actions, automations (2445 tests), and the orcad/SSH lock suites after merging fix(ssh): reclaim this desktop's own exited lock on Windows hosts too #26087 (960 tests)
  • pnpm test:node-server: 95 files passed, 1 skipped

nwparker and others added 10 commits October 7, 2026 00:09
Pin generated skill JSON and Vitest snapshots to LF so Windows autocrlf checkouts pass byte-for-byte verification. Cover the checkout behavior with a real Git regression test.

Co-authored-by: Shuhei Konno <shuhei.konno@gmail.com>
…er lanes (#26093)

vitest 5 does not apply a CLI --exclude to inline projects, so the glibc floor
container ran profile-state-writer-stall.electron.test.ts and failed with
'spawn xvfb-run ENOENT'. Resolve the selectors to files and filter them before
vitest sees them.
* perf(tests): cache Vitest module transforms between runs

* test(native-chat): align resume fixture with mention menu props
The 320px cap made long code a scroll-within-a-scroll.
…t is (#26025)

* fix(agent-launch): a paired device's launch leaves the desktop window where it is

A launch from the phone (or any paired client) revealed the workspace on the
host desktop: the early tab's viewer rule said `reveal-owner` for callers whose
navigation is their own, and with no early tab the spawn surfaced the owner by
default. One predicate, `agentLaunchMovesHostWindow`, now decides both: paired
callers get `none` for the shown tab and `surfaceOwner: false` at spawn. The
device still selects the tab for itself; the CLI and the desktop are unchanged.

* fix(agent-launch): a paired device's new-workspace launch leaves the desktop window where it is

An agent.launch that creates its workspace never asked agentLaunchMovesHostWindow:
the create payload's activate/runHooks passed straight through, so a paired
caller that set either would switch the desktop to the new workspace and reveal
the startup terminal there. No shipped client sends them through agent.launch
yet, so nothing changes today; it closes the gap before a phone's work-item
creates move here.

For a caller whose launch does not move the host window, the create now runs
unactivated, which provisions setup and default tabs in the background. runHooks
keeps its setup half as setupDecision 'run'. CLI and desktop creates are
unchanged. Also makes the CLI "still reveals" test assert that a terminal was
actually created, so it cannot pass with none.

* docs(agent-launch): a paired client's create no longer activates the host to run setup

The caller-selection header said a launch that creates its workspace relies on
worktree.create's host activation to run setup. Since the previous commit that
holds only for in-process callers: a paired client's create never activates the
host window, and its setup and default tabs are provisioned in the background.
Comment only.
…the local branch and say so (#26009)

* fix(worktrees): create from the usable local base when there is no tracking ref, and say so, on the host's create

The host's create (agent.launch, worktree.create, the phone and the CLI) asked for a remote base like
origin/main with no tracking ref yet fetched it, and threw offline, even when the local branch existed;
it also never reported a base it fell back to. Like the desktop create, it now uses the local branch
without fetching and returns baseFallback, which the desktop window already turns into a notice.

* fix(worktrees): fetch the remote base first and fall back to the local branch only when the fetch fails

The host's create skipped the fetch whenever a local branch matched a
remote base with no tracking ref, so online phone/CLI/agent.launch creates
silently built on a possibly stale local branch, every time. Fetch first,
as main does; only when that fetch fails use the local branch the remote
names and report it with baseFallback. With no local branch the existing
error is unchanged.

Decide the base before naming so branch reuse and conflict checks, the add
and the persisted baseRef all see the base actually used, and return
baseFallback as its own field of the create result instead of riding on the
git add result.

* fix(worktrees): report the fallback for a local ref of the requested name, as the desktop create does

The tracking ref is still missing there; only the fetch is skipped, as before.

* test(worktrees): pin that the host create names only after the base fetch settles

Also pins the existing not-found-after-fetching error, now owned by the base decision.

* fix(worktrees): fall back to the local base only for creates a person asked for; keep the exact-name ref silent

Scheduled automations, orchestration workers and federation keep main's
"Check your network" error offline: nobody is watching to be told the
workspace was built on a possibly stale local branch. The fallback is a
host-side create option (allowLocalBaseFallback, default off, not on the
wire) that the worktree.create RPC and agent.launch set unless the request
carries automation provenance.

A local ref of the exact requested name goes back to silent, as on main's
host: reporting it showed "may not include the latest remote changes"
online for plain local branches.

* test(worktrees): pin the local-base opt-in at agent.launch and its absence for an automation's worktree.create
#26111)

* perf(tests): cache Vitest module transforms between runs

* test(native-chat): align resume fixture with mention menu props

* perf(tests): reuse the SQLite store fixture in automation suites
…agent.launch (#25624)

* feat(agent-launch): host-assigned caller identity and a launch record written when the surface exists

Step 1 of the agent-launch unification, on main.

- The dispatcher stamps every request's caller from what its connection proved (runtime socket:
  the local CLI; the desktop's IPC: the desktop; a paired socket: its device). Params never set it.
- The launch record is written twice: once when the tab exists (what creation settled: on the
  launch command, a draft, or a submit still `unconfirmed`), and again once the prompt's fate is
  known. A restart in between finds the running agent instead of answering "unknown".
- A replay re-derives its terminal handle from the pane key in the running host, and shows
  `unconfirmed` only to callers that advertise agent.launch.prompt-unconfirmed.v1.
- The record store opens in its own slot, without building the chat host; the chat host is built
  on that same store.

Rebuilt from this PR's own commits (b9adf88, 0d7d9b5, c83f44d, 39d15d5) onto
main, without #24080/#24081. Conflicts: the delivery doc table (main's "line fits" row plus the
`unconfirmed` row), and main's journal-database open in install(), which now goes through the
record-store slot.

* feat(agent-launch): show an agent's tab at once, where the caller asked for it

An agent.launch now shows its terminal tab before admission and spawn, in
the requested placement (group and/or anchor tab), and the pane attaches to
the agent as soon as it runs. A pane whose agent can't start, or whose start
can't be confirmed, says so instead of becoming a plain shell, and keeps
saying so across restarts. A user's close of the tab or its pane during the
launch stops it and answers agent_launch_tab_closed. Whose view moves is
unchanged from main for every caller.

Rebuilt on main (with #24934) from the previous branch head 8f62858.

* feat(agent-launch): the desktop AI buttons start their agent through agent.launch

Part 3 of 3 of the agent-launch unification, on main. The AI buttons (Fix
checks, the source-control actions, commit/push recovery, Explain commit,
notes and annotation sends, session continuation) started their agent from
the window. They now ask the host's agent.launch to start it, with no
prompt, into the tab the window makes at the click, under one operation id
per click; the window's pane waits for the host's agent instead of spawning
a shell. The window then pastes the prompt with main's own paste, moved out
verbatim and started only once the host's agent holds the tab, so delivery
and follow-ups are exactly main's. A typed new-tab prompt and launches while
chat is the default keep main's path. The source-control dialog drops its
launch-command preview, which the host builds now.

* style(runtime): one-line the tab-order map so the headless browser-tabs runtime stays under its line limit

The merge of main (#25724's emitMobileSessionTabsSnapshot metadata) plus this branch's close mark put
the file one line over max-lines. Formatting only.

* fix(agent-launch): watch an AI button's agent for readiness from its first output

The window started watching for the agent's ready signal only after the host
answered agent.launch, so an agent that had already turned on bracketed paste
by then was never seen ready and its prompt waited out the readiness budget.

Readiness is now watched from the moment the tab's terminal exists, as main
watches it; the paste is written, and the chat copy seeded, only once the host
says its agent started in that tab.
…3-sync5

# Conflicts:
#	config/scripts/run-node-server-tests.mjs
@OrcaWin
OrcaWin requested a review from brennanb2025 as a code owner October 7, 2026 08:29
@OrcaWin
OrcaWin merged commit e547664 into OrcaWin/node-rt-phase3 Oct 7, 2026
39 checks passed
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.

5 participants