Skip to content

sync: upstream df95be4090 into swaplabs/main - #62

Merged
kiwidream merged 360 commits into
swaplabs/mainfrom
sync/upstream-20261027
Oct 27, 2026
Merged

kiwidream merged 360 commits into
swaplabs/mainfrom
sync/upstream-20261027

Conversation

@kiwidream

@kiwidream kiwidream commented Oct 27, 2026 •

Copy link
Copy Markdown
Files Added Deleted Net
Test 1258 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​39776 $\color{#cf222e}{\Huge{\mathbf{−}}}$​20769 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​19007
Prod 1742 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​61788 $\color{#cf222e}{\Huge{\mathbf{−}}}$​32836 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​28952

ELI5

Upstream Orca moved forward 359 commits since yesterday's sync (#58). This PR merges them into swaplabs/main. 21 files conflicted with fork changes. Two fork features overlapped with new upstream work, and the operator decided both (#61):

A few more things broke without a conflict and are fixed here. This PR replaces #60 (head main), which could not merge.

What Changed

Upstream range 33ddab70b7..df95be4090, 359 commits (compare). One signed merge commit, e610bed8d5 (Merge upstream main (df95be4090) into swaplabs/main), on sync/upstream-20261027, cut at the integration head 4997ffc041.

Operator decisions (#61)

#3, unreachable-host project removal → upstream stablyai#34079. Upstream now removes a paired-server project while its server is unreachable: it removes it locally and replays the owed repo.rm once the server reconnects, so the project does not come back. #3's "forget on this computer" flow left the project registered on the host and let it return. The two cannot both run, so #3 is dropped whole:

  • its 11 files take upstream's version, including the conflicted repo-removal.ts, repo-state.ts, settings-project-list.ts and use-settings-store-model.ts;
  • its fork-only files are deleted: project-removal-outcome.ts and its test, project-removal-owner.ts (a past sync's max-lines move), and ssh-host-remove-workspaces.test.ts;
  • en.json loses its six strings (RemoveFolderDialog's four, and the settingsProjectList block).

#30, host resume of a re-created pane → one launcher, upstream stablyai#34054's. Upstream's hookRowPaneResumeRecord resumes a pane with no saved record from its own local hook rows, which is the case #30's no-record fallback covered, and it ran first. Instead of keeping two launchers, #30's launcher (host-pane-agent-resume.ts, its unit test, and most of host-pane-agent-resume-start.ts) is removed. The fork's rules run on upstream's path:

Rule Where
Resume only the session selectTerminalLossResume names for the pane. Any other row, such as one the user ended, gets a plain shell and stays resumable by hand admitHostPaneAgentResume, called from resolvePaneOwnedResumeStartup (agent-session-resume-ownership.ts, 5 lines)
Relaunch with the settings-default flags (#40 stays open) admitHostPaneAgentResume sets the record's launchConfig
Declare no restore intent, so the host paces the resume but never defers it or holds it behind an unclean-death pause (#41) restoreSpawnIntent, used by restored-pane-materialize.ts
A failed resume spawn opens a plain shell and keeps the identity openShellAfterRefusedHostResume, in materializePendingMobileSessionTerminal's catch
Concurrent activations of one pane share one re-creation trackHostPaneRecreation, unchanged

Fork source for this path goes from 296 to 145 lines, plus 26 changed lines in two upstream files (22 before), and a 126-line unit test goes. What changes for users, all from upstream's path:

  • an agent tab whose hook rows upstream finds nothing to resume in (rows from another worktree, a relayed SSH host's or a structured host's), or whose resume upstream's own checks veto (such as two conversations in the pane's rows), now launches its agent fresh, as upstream chose. fix(resume): a paired host resumes each pane's agent after its terminal is lost #30 opened a plain shell whenever the pane had any hook row. A session the fork's rules refuse, such as one the user ended, still gets a plain shell;
  • the resume now carries upstream's saved-resume admission (resumeOrigin: 'saved', so a conversation an open native chat holds is not resumed in a terminal), its resume claims, and its resume folder (launchCwd). These were open items on Resume: follow-ups for #6 and #30 after the 2026-10-22 sync #41.

host-pane-agent-resume-activation.test.ts passes unchanged, apart from one new assertion that the resume declares no intent. docs/reference/swaplabs-agent-resume.md describes the new arrangement.

Conflicts, by fork PR (orca-fork-ops conflicts)

Fork PR File Upstream change Resolution
#8, #15, #16, #20, #24, #48 (fork builds); #26 (sync review rule) .gitignore, AGENTS.md, docs/reference/swaplabs-fork-builds.md, docs/reference/swaplabs-agent-resume.md stablyai#34008 deletes docs/reference/; stablyai#34322 moves AGENTS.md's references to docs/agents-md-refs/. Rename detection proposed moving the fork docs there too the fork docs stay at docs/reference/swaplabs-*.md, per fork policy. .gitignore keeps upstream's agents-md-refs lines and adds the fork's docs/reference/ ones. AGENTS.md takes upstream's new test-antipatterns link and keeps the fork's section unchanged
#6, #7, #9, #10, #13, #14, #17, #31 src/renderer/src/i18n/locales/en.json, en-runtime-required.json new keys upstream's catalogs plus the fork's: 33 keys and 1 changed value in en.json, and the fork's terminalPane block in en-runtime-required.json. verify:localization-runtime-catalog passes
#6 (auto-resume) src/main/ai-vault/runtime-session-scanner.ts adds pairingRevision the fork's ...result spread, on upstream's pairingRevision
#25 (daemon drain) src/main/daemon/daemon-pty-runtime-state.ts adds readRunningWslDistros both options
#1, #5 (resume handles, host routing) src/renderer/src/lib/workspace-session-host-persistence.ts, workspace-session-host-split.ts stablyai#33972 sends emptied fields (emptyContainerHostIds) upstream's field beside the fork's sleepingRecordOrigins. #1's KNOWN LIMITATION note is unchanged; narrowing it is item 3 of #61
#3 5 files see above upstream's
#10, #16, #27 (update sources) src/main/updater-prerelease-feed.ts, src/main/updater/updater-release-feed.ts stablyai#34076 pins the stable fallback to the tag /releases/latest names (fetchLatestStableReleaseTag) ported to the fork's release sources: the page and tag pattern come from the source's repo (getLatestReleasePageUrl, getReleaseTagPathPattern), readiness from probeReleaseManifest, and the HEAD probe is requestGitHubReleaseHead in the fork's readiness module, split as upstream split it. A lookup a newer check overtook returns the fork's 'superseded'
#10, #14, #16 src/main/updater/updater-status.ts stablyai#11567 sends through sendToMainWindow upstream's guarded send, then the fork's pinned auto-download
#10, #16, #27 src/main/updater-test-harness.ts, updater.check-failure.test.ts, updater.nudge-campaign.test.ts, updater.startup-scheduling.test.ts imports and harness members both sides' imports; the harness as below

Breaks the conflict list did not show

Fork PR File Upstream change Fix
#16 (mac self-update) src/main/updater/update-engine.ts stablyai#34276 listens for electron-updater's login event the fork's UpdateEngineEvents gain login
#10, #14, #16 the fork's updater tests stablyai#11567's sendToMainWindow calls isDestroyed() the tests use upstream's updaterMainWindow fake; createUpdaterMainWindowFake delegates to it
#10, #16, #27 src/main/updater-prerelease-feed.ts (328 counted lines, max 300) stablyai#34076 the fork's manifest verdict moves unchanged to the fork-owned updater-release-tag-manifest.ts, re-exported. Now 283
#10, #27 src/main/updater/updater-release-feed.ts (302) stablyai#34076 the fork's skipped-check diagnostic moves to the fork-owned updater-release-sources.ts. Now 295
#10, #16 src/main/updater-test-harness.ts (305) stablyai#34076, stablyai#11567 the fork's mocks come through createSourceFeedMocks(appMock).extend(...) in the fork-owned updater-release-source-feed.test-fixture.ts. Now exactly 300
#25 (daemon drain) src/main/daemon/daemon-entry.ts (301) upstream grew the file the file now equals upstream's: startDaemon in daemon-main.ts reads #25's argv hand-over, beside upstream's spawnAdmission

Fork delta check: each of the 352 files the fork changes, before or after, was compared against upstream on both sides of the merge. 306 keep exactly the same fork lines. The other 46 are the changes listed here:

Some notable upstream changes in the range

Why

Daily upstream sync.

Linked Issue

N/A: daily upstream sync. Decisions: #61. Follow-ups: #40, #41, #42, and #61 (item 3).

Visual Proof

N/A. The one user-visible fork change is #3's removal dialog, which is now upstream's.

Testing

All checks ran on the merge result in the sync worktree, before the commit:

  • Install: pnpm install --frozen-lockfile.
  • Typecheck: pnpm tc passes. Before the fixes it failed on updater-setup.ts ('login'), which shows the gate is live.
  • Lint: pnpm lint, all 35 steps pass. It failed first on four max-lines overflows and one anti-slop finding, all fixed above.
  • Changed-code gate: check:code-quality:changed with ORCA_SYNC_PR_DIFF_BASE=df95be4090: 0 findings across 313 fork files.
  • Tests: every fork unit test file (109) plus src/main/runtime, src/main/agent-hooks, src/main/updater*, src/main/daemon, src/main/ai-vault, src/renderer/src/store/{repos,slices}, src/renderer/src/components/{settings,sidebar}, src/renderer/src/web, src/renderer/src/lib/workspace-session-host*, src/renderer/src/i18n and the localization scripts: 3,255 files, 32,165 tests passed, 251 skipped, 47 failed in 10 files, all upstream files. None is the merge's:
    • 33 tests in 3 files (runtime-interrupted-local-worktree-removal, repo-worktree-admin-fingerprint, orca-runtime) fail because this host's signing wrapper refuses their fixture commits. With fixture signing off (commit.gpgsign=false, tag.gpgsign=false) all 3 files pass (1,523 tests).
    • 5 tests in 3 updater files fail because this host exports ORCA_SERVER_UPDATE_HELP_URL, so LOCAL: let a managed server link its update instructions #17 adds a helpUrl. With the variable unset all 3 pass.
    • 9 tests in 4 files (7 bash-wrapper tests on bash 5.3.9, and 2 zsh live-shell tests with no /bin/zsh) fail the same way on pristine upstream df95be4090 on this host.
    • 5 upstream store test files pass but report 10 unhandled EnvironmentTeardownErrors; pristine upstream df95be4090 reports the same 10.
  • Resume, specifically: host-pane-agent-resume-activation.test.ts (6), host-pane-agent-resume-upstream-first.test.ts (3) and upstream's restored-pane-hook-store-resume.test.ts (10) pass. The new no-intent assertion fails when the intent is declared. The fork's e2e spec paired-host-agent-resume-after-terminal-loss.spec.ts was not run.
  • Pre-commit hook: oxfmt --check reports all 4,545 staged files lint-staged formats as formatted. oxlint, its JS-plugin and React Doctor configs, and ast-grep scan --min-severity warning pass over the 4,423 staged code files. The hook then ran normally, and the tree before the commit (90dbf664e1) equals HEAD^{tree} after it.
  • Signature: e610bed8d5 is G from the sync key BF1DD75F888E96080C2453E2D9E158C5D6874235.

AI Disclosure

Prepared by the "Orca upstream sync" automation (Claude Code, Claude Opus 5.5), with the operator's decisions on #61.

Agent skill upstream boundary

  • Not applicable: this PR merges upstream's history; it adds no agent skill.

Notes

orca-fork-ops status for swaplabs/main (4997ffc041) against upstream df95be4090, before this merge:

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

nwparker and others added 30 commits October 26, 2026 11:47
…ocused terminal (stablyai#34037)

Closing the Agent Dashboard drawer or workspace board with Escape still
forwarded the key to a focused xterm, because xterm ignores
defaultPrevented. Stop propagation only when the target is the xterm
helper textarea so other fields keep their own Escape handling.
…tablyai#34035)

sanitizeWorkspaceStatusLabel cut labels with slice(0, 32), which could keep
only the high surrogate of an emoji straddling the limit and render U+FFFD.
Use the existing surrogate-safe sliceAtCodeUnitLimit helper instead.
…; machines list the sources they accept (stablyai#33862)

A connector conversation now names its source (slack, discord or linear), and a posted reply reports a neutral messageId. Each machine's hello lists the sources it accepts, and the cloud only routes a Slack conversation to machines that list Slack. Machine events from other sources are filtered out where they arrive, and a reply for a non-Slack conversation is refused, so a Discord or Linear conversation can never post into a Slack thread with the same id. The unused turn-bound cancel fields are removed (they return with Stop). Inert: no shipped desktop uses the contract, and Slack is off unless configured.
…ses (stablyai#33961)

A host whose move to its Orca server was refused over saved state (an
enabled SSH automation and its runs, stale workspace details, unsupported
saved tabs) stayed in error on every Connect. Move anyway, which connects
it and leaves those items on this computer, was only in the card's
overflow menu, so the host looked stuck. The card now offers Move anyway
next to its refusal, as it already does for Recover server.

Refs stablyai#29083.
…blyai#33852)

With the experimentalConnectors setting on and the desktop signed in to Orca, the desktop keeps one long-poll request open to the Orca Cloud connector and hands each delivery to the existing connector code that starts or talks to an agent. Each delivery is confirmed twice (received, then its result), and the agent's turn and prompt events are reported back. The desktop authenticates with a 5-minute connector token from the Orca sign-in service, follows the relay's start/stop lifecycle, and stops on sign-out. Its hello lists Slack as the one source it accepts. Off by default with no settings UI.
…yai#33990)

* fix(ssh): say why SSH failed when Connect never reaches the host

When the SSH session itself could not open (key rejected, port refused,
host not answering, host key not trusted), Connect on a host Orca had not
set up yet said "Orca couldn't start its server on this host" and offered
a plain SSH terminal that could not work either. Errors from opening the
SSH session are now marked where they are dialed, and a setup that fails
on one ends the connect with SSH's own reason. A held move keeps its
status. The connect-failure toast also drops Electron's IPC prefix.

* fix(ssh): lead an SSH connect failure with what to do about it

stablyai#33928 shows SSH's own reason when Connect never reaches the host. Raw
reasons like "connect ECONNREFUSED 10.0.0.1:22" or "Timed out while
waiting for SSH authentication" still leave users guessing. A failure
from opening the SSH session is now published with a next step for the
kinds users can act on (host key mismatch, rejected sign-in, refused
port, unknown host name, no route, timeout), and SSH's words follow in
parentheses. The connect-failure toast reads the same published text.
…in zh/ja/ko/fr (stablyai#33561)

Replace mistranslated subagent summaries ("kicked off" rendered as "fired"/
"kicked out", untranslated "Ran") and add missing measure words to the zh
tool-run clauses. Leading tool-run clauses are now joined with a translated
runListSeparator so CJK locales use 、 instead of an English comma.

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
…yai#16413)

The Team, Lead, Members and Labels popovers in the Linear new-project
dialog are portaled outside the dialog, so its scroll-lock cancelled
native wheel input over their inner max-h-64 lists. Opt their
PopoverContent into the shared wheel shim via wheelScroll, and move the
p-1 padding onto the children so the layout is unchanged.

Fixes stablyai#16412

Co-authored-by: Neil <neil@stably.ai>
…ai#33889)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…(E9 C) (stablyai#33840)

* fix(forge): skip PR refreshes for a WSL host that is off, and say so

E9 connect policy, part 3. PR status for a workspace on a WSL host is fetched through
the host, and a poll never boots it. While the host isn't ready, the visible-row
refresh skips it (the row keeps its last badge and the existing "host disconnected"
mark), a direct PR refresh keeps the last answer and records a 'host-off' skip, and
the Checks panel says the host is off and to reconnect it. The cached-field half of the
refresh candidate moves to its own helper to keep the lookup file in bounds.

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

* test(forge): a WSL host that goes off keeps its last PR badge and records host-off

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

* fix(forge): only a stopped or closed WSL host is "off"; mark row badges as last known (E9 review)

Review of stablyai#33840:
- Connecting, reconnecting and unverifiable hosts were treated as off. Only a
  confirmed-stopped (or parked) host, or one closed with WSL hosts turned off, is off
  now; anything else lets the call proceed or fail as usual. A status change re-runs
  the visible refresh, so rows refresh as soon as the host turns ready.
- Row badges now carry the stale mark too: the card's review status gets the hover
  card's last-known treatment and "Last known status" in its label, and the hover
  card's reference rows are stale and not fetched while the host is off.

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

* test(forge): build the host-off PR refresh test on the shared GitHub slice harness

Drops the copied store and seed casts.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
… session (stablyai#34048)

OMP's ACP session advertises commands it handles itself (e.g. /fast), but
native chat claimed them as host-only TUI commands and refused them as
unavailable. Commands the running session reports in its slash menu are now
left unclaimed so they send through, on desktop and mobile. Mobile reads the
session command list once in the native-chat lane and shares it between the
send path and the composer menu.
… down (E9 A) (stablyai#33838)

* fix(wsl-host): boot only the focused WSL host, and keep a stopped one down

E9 connect policy, part 1. A stopped distro now boots only for an explicit user action
or when its host becomes focused:
- Visible work is the active workspace plus workspaces focused earlier in this window
  that still have tabs. Saved tabs alone no longer count, so a launch with two hosts
  boots only the focused one.
- After a confirmed stop (wsl --shutdown, WSL update) the host is parked. Liveness no
  longer reboots it even when it is visible, and polls get "<distro> was stopped"
  instead of a boot. Re-focusing the host, Connect, or the distro running again lifts it.
- Liveness recovery always needs a confirmed-running distro, so a distro that stops
  mid-recovery is never booted again.

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

* test(wsl-host): launch boots one of two hosts; polls never boot; lost contact never parks

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

* fix(wsl-host): only a focus entry or a user action boots a WSL host (E9 review)

Review of stablyai#33838:
- Re-focus never lifted a park: a host focused earlier stayed in the visible set, and
  the renderer skips unchanged reports. The renderer now sends a separate focus entry
  (focusHost) each time the user switches to a workspace on a WSL host, including the
  launch restore; only that, or Connect, lifts a park and may boot.
- Runtime calls could boot: ensureForRuntimeCall connected any visible, unparked host.
  It now reads the host's reachability first: a confirmed-stopped distro parks at once,
  an unreadable running list refuses, and only a distro confirmed running is
  reconnected (for visible work). Visible work itself never connects anything.
- Turning WSL hosts on no longer boots every visible host, and focus isn't recorded
  while they're off; the window re-reports its focused host instead.
- Each window's visible work is kept apart and unioned, so one window can't drop
  another's.
- wakeForAutomation/isConnected move to the automation PR, which uses them.

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

* fix(wsl-host): a poll waits for liveness's verdict right after an exit (E9 re-review)

Right after `wsl --shutdown` WSL can still list the stopping distro as running (the
supervisor waits and re-reads for exactly this). A poll's cold probe then read
'unreachable', reconnected, superseded the pending distro-stopped verdict and booted
the distro again. The supervisor now reports when it is settling (a verdict in
progress, or a watch/holder exit within the last few seconds), and a runtime call
refuses instead of reconnecting then; the verdict parks the host as before.

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

* test(wsl-host): a new supervised entry starts with no recorded exit

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Radu Toader <radu.m.toader@gmail.com>
…st's move (stablyai#34041)

* fix(ssh): show Move anyway on a host card whose move saved state refuses

A host whose move to its Orca server was refused over saved state (an
enabled SSH automation and its runs, stale workspace details, unsupported
saved tabs) stayed in error on every Connect. Move anyway, which connects
it and leaves those items on this computer, was only in the card's
overflow menu, so the host looked stuck. The card now offers Move anyway
next to its refusal, as it already does for Recover server.

Refs stablyai#29083.

* fix(ssh): make Move anyway the next step when saved items refuse a host's move

When a host's move to its Orca server is refused only over saved items
that Move anyway can leave on this computer (stablyai#29083's enabled
automation and its runs, for example), every surface now leads with it:
- the host card says which items can't move and that Move anyway
  connects the host and keeps them here, with Move anyway as its
  primary button;
- the refusal toast says the same and offers Move anyway, opening SSH
  Hosts where the move is confirmed;
- the terminal pane's Move anyway is primary too;
- the host picker and connect toast read the same line.

Refs stablyai#29083.
…tablyai#17714)

The packaged agent-browser binary resolves its version-matched skills from the
nearest skills/ directory above it (Resources/). Only the binary shipped, so
`agent-browser skills get core` answered "Skill not found" and `skills list`
"No skills found". Ship node_modules/agent-browser/skills/agent-browser and
skill-data beside it on mac, linux and win, and cover it with a test that stages
the host's extraResources slice and runs the real binary.

Refs stablyai#17705

Co-authored-by: zerone0x <zerone0x@users.noreply.github.com>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
…i#29321)

Several zh.json strings used a translation with the wrong meaning for the
UI context (e.g. git base ref, dividers, host, browser profile, search
keywords). Align them with the intended sense and consistent terminology.

Co-authored-by: Neil <neil@stably.ai>
…ai#31546)

* fix(native-chat): render math and center standalone equations

* fix(native-chat): parse math without rewriting message source

* fix(native-chat): accept element roots for math selections

* fix(native-chat): preserve math boundaries and selected source

* fix(native-chat): derive math fence closure from accepted parser events

* fix(native-chat): reuse exhausted math searches per tokenizer

* fix(native-chat): load math typesetting after parsed formulas

* Use declaration references for chat math augmentations

* Declare chat math metadata and register equation label

* Preserve i18n exports in selection quote test mock

* test: expect cached legacy failure display reuse

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
…yai#31985)

* fix(opencode): allow picked models across CLI updates

* test(opencode): prune obsolete timeout ratchet allowance

* fix(opencode): use resolved agents and refuse unsafe workers upfront

* fix(i18n): include OpenCode refusal messages in runtime catalog
…32045)

* fix(ports): bound macOS scans by the lifetime of each operation

* refactor(ports): keep Darwin metadata acquisition together

* fix(ports): preserve valid Darwin observations and source host routing

* fix(ports): retain scan admission outside aged temporary cleanup

* perf(ports): skip unused listener acquisition for ownership actions

* test(ports): make child fixture streams portable across runtimes

* fix(ports): share source host derivation across scan rows

* test(ports): initialize scan projection without a type assertion

* fix(ports): restore existing browser open routing

* fix(ports): preserve scanner compatibility on degraded hosts

* test(ports): explain real process lifetime timing
…eybinding (stablyai#31679)

* fix(native-chat): make the chat view toggle a remappable keybinding

The terminal and Chat UI toggle was hardcoded to Mod+Shift+J, so users
could not rebind or disable it, Settings did not list it, and it
overrode user bindings on that chord. Declare it as
terminal.toggleNativeChat in the keybinding registry, match it through
the user's keybindings, and render its menu labels from the registry.

* fix(keybindings): align native chat toggle admission and execution

* fix(keybindings): preserve runtime input and defer closed menu hints

* test(keybindings): use typed alias read instrumentation

* Fix keybinding dependency direction and physical modifier inputs

* Preserve typed input facts in floating shortcut arbitration

* Clarify native chat shortcut precedence on Windows and Linux

* Simplify native chat shortcut resolution and nominal labels

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* fix(worktree): track explicit remote branch

* test(worktree): cover remote branch path retry

* fix(worktree): resolve cached remote branches canonically

* fix(git): retain commit validation in bounded ref probes

* fix(worktree): preserve selected remote identity during creation

* test(worktree): count cached resolver Git work during path retries

* Fix branch intent state in composer source fixture

* Make Git and daemon regression fixtures portable

* Use the selected base for existing branch creation

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
…#32919)

* Fix automatic branch naming for workspace labels in every language

* Use creature branch seeds for typed workspace labels

* Keep first-work generator mocks in creator test suites

* Type the created worktree test mock from its production signature

* Assert created worktree results before exercising first work

* Match the missing-folder update contract in first-work fixtures
…actions (stablyai#31931)

* fix(native-chat): validate saved next-fence floors before use

* WIP: separate saved conversation observations from runtime proof

* Consolidate duplicate imports for WIP compiler checkpoint

* Preserve saved conversation observations with strict runtime authority

* Consolidate session admission and catalog imports

* fix: align conversation observation contracts and fixtures

* test: update conversation observation and writer fixtures

* test: use checked host fixtures for structured workers

* fix(native-chat): bound conversation projection work per request

* test(native-chat): consolidate scale fixture imports

* test(native-chat): use checked scale fixture types

* test(native-chat): bound unreadable inventory traversal

* Test native CLI admission and durable reference reads

* test: bound cold conversation name subscription work

* test: distinguish native receipt probes from terminal identity

* test: retain exact mutation refusal recovery identity

* fix: explain agent conversation preparation refusals

* test: adapt remaining conversation readers and document CLI timeout

* fix: register preparation refusal English message

* test: align conversation fixtures with checked read APIs

* test(native-chat): use checked conversation in Codex fixture
nwparker and others added 20 commits October 27, 2026 01:40
It raced the relay's kill against the stub cats setting their TERM trap, and picked the cat to
keep blocked by start order. It now hangs up only once both traps are in place, and tells the
socket reader from the stdin reader by whether its stdin is the relay's socket (fd 3).
)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…ablyai#24327)

On repos whose base branch requires a merge queue and that disable
auto-merge, gh pr merge --auto always calls enablePullRequestAutoMerge,
which GitHub rejects. Call the enqueuePullRequest mutation directly in
that case and report enqueue failures as merge-queue errors.

Fixes stablyai#19638

Co-authored-by: Neil <neil@stably.ai>
* refactor: group shared native chat composer input

* refactor: consolidate concrete composer imports
…#34113)

* Import cookies without clearing existing sessions

* fix(browser): keep new cookie imports merge-only

* fix(browser): admit native cookie preparation through session lock

* fix(browser): retire superseded shipped cookie imports

* test(browser): make cookie expiry fixtures deterministic

* test(browser): restore cookie clear mock type import

* fix(browser): show skipped cookies in import result toast

* test(browser): expect native cookie imports to preserve existing coordinates

* fix(browser): report only successfully imported native cookie domains
…tory stack frames (stablyai#34335)

Vitest's reporter checks existsSync(file) and then reads the file to find a
source map. When an error stack names a directory, readFileSync throws EISDIR
as an unhandled error, so the shard fails with every test passing. Read only
regular files.

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

Pin commit.gpgsign=false and tag.gpgsign=false in the throwaway repos
built by the release script tests so a global signing config cannot turn
lightweight fixture tags into annotated tags that abort with
"fatal: no tag message?".
…ai#34337)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…anup (stablyai#25478)

The queued-message test rig deleted its temp state directory while the
shared journal SQLite handle was still open, so teardown failed with
EBUSY on Windows. Close the rig root's journal database after the host
drains, then remove the directory.
…ication (stablyai#34327)

Both arch jobs overlapped ~2.5 min of setup with qualification, then polled
for the template for 400-560 s on the most expensive runner we use.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…d base (stablyai#33782)

check:changed --base=<ref> resolved a merge base for the gates it drives
directly, but the flaky-test ratchet subprocess re-derived its scope from
origin/main. On a checkout whose origin is a stale fork that pulled in
unrelated files and could fail the run. check:changed now forwards its
merge base via ORCA_CODE_QUALITY_BASE (the env the other changed-code
gates already honor), and the ratchet uses it before falling back to
origin/main.

Fixes stablyai#33763

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Bell, test, task-complete, tool-preview, permission-probe and startup
registration notifications now read their sentences from the i18n
catalogs instead of English literals. The notification translator
accepts interpolation values; the English default fills them so
headless hosts produce unchanged English copy. The startup permission
prompt waits for main-process i18n before it is shown.

Fixes stablyai#27068

Co-authored-by: outof-place <contact@outofplace.space>
…022 runner (stablyai#34350)

The free windows-11-arm and macos-15-intel lanes already set the matrix's wall
time; the paid 8-vCPU Blacksmith Windows lane finished minutes earlier for ~$48/day.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Only the automations and client-hosted-browser steps had an id-keyed
entry in the localized step copy map, so every other contextual tour
(workspace board, agent sessions, browser, tasks, floating workspace,
workspace creation) rendered English titles, bodies, and action labels
next to localized Back/Next/Done controls.

Give every tour step a required stable id and move the copy lookup into
contextual-tour-step-copy.ts. The map `satisfies` a record over all step
ids, so a new step without localized copy is a type error. Primary and
secondary action labels (Split terminal, Got it, Browser settings) are
localized through the same entry. Existing automations and
client-hosted-browser keys are unchanged so shipped translations keep
resolving.

Add the new strings to en and translate them for ko, es, ja, zh, fr,
and pt.

Co-authored-by: Neil <neil@stably.ai>
* test(wsl): hand the reap test's fake cat its real stdin

The fake cat backgrounded the real cat with `&`, which a non-interactive sh starts on
/dev/null (dash even under `<&0`). The socket reader therefore ended at once, before orcad
hung up, and the relay killed its partner, sometimes before that cat's TERM trap was set:
on Linux under load the trap count stayed at 1 even after stablyai#34329 (3 of 6 rounds of 50
failed). The fake cat now passes stdin on fd 5, as the relay itself does, so the socket
reader ends only when orcad hangs up and the stdin reader blocks until killed.

* test(wsl): mark the fake cat armed only once its child is known; tighten the comment
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Upstream range 33ddab7..df95be4, 359 commits. 21 conflicted
paths, 24 hunks: 19 both modified, and 2 fork docs that rename
detection carried into upstream's new docs directory. The operator
decided two fork features (orca#61).

Operator decisions:
- Unreachable-host project removal (fork #3) takes upstream stablyai#34079: a
  local removal plus an owed repo.rm replay once the server
  reconnects. #3 is dropped whole. Its 11 files take upstream's
  version (the conflicted repo-removal.ts, repo-state.ts and two
  settings imports included); project-removal-outcome.ts and its test,
  project-removal-owner.ts and ssh-host-remove-workspaces.test.ts are
  deleted; en.json loses #3's six strings.
- Host resume of a re-created pane (fork #30) now runs through
  upstream stablyai#34054's hook-row resume, the only launcher.
  host-pane-agent-resume.ts and its unit test are deleted.
  host-pane-agent-resume-start.ts keeps the fork's rules on upstream's
  path: only the session selectTerminalLossResume names (otherwise a
  plain shell), the settings-default flags (#40), no declared restore
  intent, a plain shell when the resume spawn fails, and one
  re-creation per pane for concurrent activations. Upstream's own
  vetoes now launch the tab's agent fresh, as upstream does, and the
  resume takes upstream's saved-resume admission, claims and folder.

Conflicts:
- Docs (#8 #15 #16 #20 #24 #48, #26): upstream deleted docs/reference
  (stablyai#34008) and moved its AGENTS.md references to docs/agents-md-refs
  (stablyai#34322). The fork's docs stay at docs/reference/swaplabs-*.md, per
  fork policy; .gitignore keeps upstream's agents-md-refs lines and
  adds the fork's docs/reference ones. AGENTS.md takes upstream's new
  test-antipatterns link and keeps the fork's section.
- Locale catalogs (#6 #7 #9 #10 #13 #14 #17 #31): upstream's catalogs
  plus the fork's keys. en.json carries 33 fork keys and 1 changed
  value; en-runtime-required.json the fork's terminalPane block.
- runtime-session-scanner.ts (#6): the fork's ...result spread on
  upstream's pairingRevision.
- daemon-pty-runtime-state.ts (#25): upstream's readRunningWslDistros
  and the fork's draining option.
- workspace-session-host-persistence.ts and -split.ts (#1 #5):
  upstream stablyai#33972's emptyContainerHostIds beside the fork's
  sleepingRecordOrigins.
- Updater (#10 #14 #16 #27):
  - updater-prerelease-feed.ts ports upstream stablyai#34076's pinned stable
    fallback (fetchLatestStableReleaseTag) to the fork's release
    sources: the /releases/latest page and tag pattern come from the
    source (getLatestReleasePageUrl, getReleaseTagPathPattern), and the
    HEAD probe is requestGitHubReleaseHead in the fork's readiness
    module, split as upstream split it;
  - updater-release-feed.ts pins that tag, and a lookup a newer check
    overtook returns the fork's 'superseded';
  - updater-status.ts keeps the fork's pinned auto-download after
    upstream's guarded send;
  - the updater tests keep both sides' imports.

Breaks the conflict list did not show:
- Upstream stablyai#34276 listens for electron-updater's 'login' event; the
  fork's UpdateEngine events gain it.
- Upstream stablyai#11567's sendToMainWindow checks isDestroyed(); the fork's
  updater tests use upstream's updaterMainWindow fake.
- Four files went over max-lines because of fork lines; the fork's
  lines move to fork-owned modules:
  - updater-prerelease-feed.ts: the manifest verdict moves to
    updater-release-tag-manifest.ts and is re-exported;
  - updater-release-feed.ts: the skipped-check diagnostic moves to
    updater-release-sources.ts;
  - updater-test-harness.ts: the fork's mocks come through
    createSourceFeedMocks(appMock).extend(...);
  - daemon-entry.ts now equals upstream: #25's argv hand-over is read
    inside startDaemon, beside upstream's spawnAdmission.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T14:35:26.863251Z e610bed PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kiwidream

Copy link
Copy Markdown
Author

Checks after the merge: 95 pass, 2 fail, 2 pending (ssh on managed orcad (Docker 2/2) and hosts (arm64, windows-11-arm, inbox)). No check had failed when the PR merged.

Both failures are in e2e / changed e2e specs, on upstream specs the fork does not change:

Not run anywhere: the fork's resume e2e spec, paired-host-agent-resume-after-terminal-loss.spec.ts. changed e2e specs runs only specs the PR changes.

The fork build 40522380777 published swaplabs-v1.4.214+202610271435 for macOS arm64 and x64 and Linux x64 and arm64. Release notes: Release notes.

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.