Commit Graph
16234 Commits
Author SHA1 Message Date
Neil aadd6fb27b perf(test): cache local Vitest dependencies and add changed targeting (#33305) 2026-10-24 17:32:02 -07:00
Neil 9c5d789a42 refactor: group cookie import orchestration and cleanup (#33314) 2026-10-24 17:25:22 -07:00
NeilandNico Hu bdae681fbd fix: deliver follow-ups to running Codex goals on the choices the goal inherits (#33300)
Codex native chat: follow-ups to a running goal turn are steered into it (turn/steer) instead of waiting, when the follow-up's model/effort match what the turn actually runs (newest handed-over submission, incl. ones rejected after their turn opened). Still waits while an earlier send is pending. Fixes #33056. Supersedes #33057.

Co-authored-by: Nico Hu <296744606+niconicohu@users.noreply.github.com>
2026-10-24 17:23:23 -07:00
NeilandClaude 4995568049 fix(runtime): a workspace sleep no longer fails when another workspace sleeps at the same time (#33283)
* fix(runtime): a workspace sleep no longer fails when another workspace sleeps at the same time

Sleeping two or more workspaces at once failed every one but the last with
terminal_liveness_unavailable, so their terminals kept running. Each sleep asks the terminal
host which PTYs are live; when a newer listing starts while one is in flight, the older answer
is discarded as stale and retried once. Two sleeps leapfrog each other: each retry starts a
listing that makes the other's stale, and the second retry gives up.

A targeted read that a newer listing overtook now waits for that listing and uses its answer,
which is at least as fresh as the read itself, instead of starting another listing. Lifecycle
changes (a PTY spawning or exiting mid-listing) keep the single retry they had.

The listing step moves into its own layer to keep the refresh within the file-size limit.

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

* fix(runtime): an overtaken PTY listing joins only a newer one that asked the same question

A targeted read that a newer listing overtook adopts that listing's answer. That newer listing
could have asked without foreground-process evidence, or waited less for slow hosts, so the read
could get rows without the evidence it asked for, or fewer hosts than it would have waited for.
It now joins only a newer listing with the same evidence option and a deadline at least as
late as its own; otherwise it keeps its single re-list.

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

* fix(runtime): a PTY read with no deadline stops after one listing budget, however many it joins

Each listing an overtaken read joined got a fresh 3 s when its caller set no deadline, so
pollers starting listings faster than a slow SSH census finished could keep such a read waiting
without end; before joining it gave up after two listings. The read now fixes one deadline up
front (the caller's, or one listing budget from now) and every listing it joins shares it.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 17:18:41 -07:00
mmarabel 95ec9e1784 fix(agent-status): mark a Pi answer unread before the compaction after it ends (#33272)
Pi: a finished answer followed by Pi's own threshold compaction is announced (done/unread) when the compaction starts instead of waiting for it to end. Skipped when follow-ups are queued; the settle post still ends the row. Refs #33267 (idle-compaction case unchanged).
2026-10-24 17:18:05 -07:00
Neilandu-ichi a8d0bd0afd fix(codex): ask before running MCP tools that require approval (#33310)
Codex native chat shows the existing approval card for MCP tool-call approvals (form-mode elicitations with no fields) instead of auto-declining them; Deny sends Codex's user-cancel reply so the turn continues. Other elicitations and turn-less requests are still declined. Fixes #25045. Supersedes #25988, #25046.

Co-authored-by: u-ichi <82369+u-ichi@users.noreply.github.com>
2026-10-24 17:16:09 -07:00
Neilanddorian-kwon c75c059e48 fix(runtime): keep a fresh agent's chat identity under an older shell title (#33306)
A hook-reported agent under an older shell title (e.g. zsh before Codex paints its title) keeps its agent status and session id, so mobile can open a fresh Codex chat; PTY titles now record when they were observed. Fixes #32030. Supersedes #32046.

Co-authored-by: dorian-kwon <61652817+dorian-kwon@users.noreply.github.com>
2026-10-24 17:15:46 -07:00
Manan c4c41aca61 fix(pi): paint the rest title at session_start so branded Pi forks reach launch readiness (#28317)
Pi's titlebar extension paints the idle title at session_start (plain Pi only, not OMP) so Pi-based harnesses that brand their own title pass worker-start agent_readiness. Fixes #28273.
2026-10-24 17:10:44 -07:00
Neiland 5a60ac7405 fix(hermes): attribute shared-gateway events to each session's own pane (#33288)
Hermes 0.22's shared gateway: the status plugin reads pane identity from each session's own client env (scrub-safe aliases via terminal.client_env_passthrough) instead of the gateway's os.environ, so every pane reports its own status. Unsafe-to-edit configs fall back to main's plugin-only edit; SSH panes now get the scrub-safe aliases. Fixes #32709. Supersedes #33240, #33222.

Co-authored-by:  <+@users.noreply.github.com>
Co-authored-by:  <+@users.noreply.github.com>
2026-10-24 17:07:35 -07:00
OrcaWinandOrcaWin ca3b0fdb02 test: remove redundant cases and strengthen state-transition assertions (#33309)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 17:05:58 -07:00
NeilandClaude 44f97fa958 fix(agent-status): keep a running Codex turn on paired and mobile views while /side is shown (#33308)
* fix(agent-status): keep a running Codex turn on paired and mobile views while /side is shown

Codex's terminal title follows the thread it displays, so opening /side idles the title while the main turn runs. The paired/mobile session projection read that idle title, newer than the main turn's last hook, as the turn ending and published a title-only done row with no prompt. A Codex row whose hooks report the main turn running now owns the title interval; the turn's end still arrives by hook or rollout.

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

* fix(agent-status): keep a Codex main turn waiting on approval through /side on paired views

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

* fix(agent-status): leave restored Codex rows to the existing title rules

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

* fix(agent-status): stop a running Codex turn at a PTY process replacement

A replacement process on the same PTY id invalidates its predecessor's title-interval evidence; record when that happened so a predecessor's running Codex hook cannot outlive it.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 17:01:30 -07:00
Neil ba43f8539c fix(runtime): a cold-restored terminal keeps its agent session without showing the old Done (STA-12043) (#33302)
* fix(runtime): a pane's new process does not wear its previous run's Done (STA-12043)

* fix(runtime): keep the superseded turn's segment and date process start at spawn request

* fix(runtime): take the identity row's segment from the turn clients were shown
2026-10-24 17:00:48 -07:00
Sunhy 759e536e5f Preserve concurrent edits during remote Hermes reinstall (#20631)
Hermes remote install only rewrites config.yaml when its content changed, so a stale snapshot can no longer overwrite a concurrent edit (matches local install).
2026-10-24 17:00:33 -07:00
Hoang Le QuocandNeil c580d7f2d3 fix(terminal): stop "104;255" leaking onto agent prompts after a tab switch (#31411)
A CSI scan now stops at ESC/CAN/SUB (as xterm's parser does), so a hidden-startup carry ending mid-CSI no longer swallows the next OSC's introducer and leaks `104;255` onto the prompt. Fixes #31410.

Co-authored-by: Neil <neil@stably.ai>
2026-10-24 16:59:59 -07:00
Neilandggbdpq d170b5a806 fix(opencode): accept OpenCode release ranges for launch-time model selection (#33307)
OpenCode model selection accepts per-major floors (1.x >= 1.18.30, 2.x >= 2.0.14; prereleases and 3.x refused) instead of exact version allowlists, so current releases launch with a picked model again. Fixes #26611. Supersedes #26683, #31985.

Co-authored-by: ggbdpq <67929842+ggbdpq@users.noreply.github.com>
2026-10-24 16:59:04 -07:00
NeilandDamHV 2a4f8e65d8 fix(agent-hooks): stop Claude agent-hook runs from minting phantom subagent rows (#33298)
Claude tool events from agent-hook runs (`hook-agent-<uuid>` ids, which never send SubagentStop) no longer mint phantom "Working - Agent" subagent rows. Fixes #27775. Supersedes #27776, #15326.

Co-authored-by: DamHV <251416543+DamHV@users.noreply.github.com>
2026-10-24 16:55:06 -07:00
Neil a02a635764 fix(agent-hooks): stop the first-work name generator from retrying without limit (#33299)
First-work branch/workspace-name generation backs off after a failed attempt (30s, 2m, then every 30m) instead of re-running on every working event, bounding cost to ~2 sessions/hour/workspace and recovering after a limit resets. Fixes #9705.
2026-10-24 16:41:50 -07:00
OrcaWinandOrcaWin 45bc63a187 test: strengthen persistence, session and failure-result assertions (#33303)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 16:40:41 -07:00
Neil d778369541 refactor: group runtime session ownership (#33301) 2026-10-24 16:40:25 -07:00
866ea1b579 fix(kimi): read usage from the scoped OAuth slot Kimi Code 2.x records in config.toml (#33290)
Kimi usage resolves the credentials slot and usage URL exactly like Kimi Code (resolveKimiCodeRuntimeAuth / resolveKimiCodeOAuthKey), so scoped-environment logins (e.g. api.kimi.ai) stop showing "session expired". Fixes #24176. Supersedes #24200, #30494.

Co-authored-by: Paramon <7700920+Paramon@users.noreply.github.com>
Co-authored-by: Bensonluo <18586615+Bensonluo@users.noreply.github.com>
2026-10-24 16:31:49 -07:00
NeilandBen Grynhaus e18752acea fix(terminal): answer a background pane's startup queries while its paired view is paused (#33273)
* fix(terminal): answer a background pane's startup queries while its paired view is paused

A paired desktop pauses the output of a terminal it is not showing. The host
drops that output, but it still counted the paused view as the one answering
terminal queries, so main's query responder stayed silent too. A fish started
in such a pane (for example by `orca terminal create`) sent DA1, got no
answer, and stalled 10 s before warning.

A multiplex stream now registers with its pause state, and main answers the
queries of output a paused view drops, exactly as it does for output the
hidden-pane gate drops. A view that receives the output still answers it, so
each query is answered once.

Fixes #32944

Co-authored-by: Ben Grynhaus <ben.grynhaus@wiz.io>

* fix(terminal): answer queries in output a pausing remote view discards unsent

A chunk ingested while the view was still receiving yields its queries to
that view. If the view then pauses, the host drops the chunk from the
output batcher, or clears it from the ack backlog, before the view ever
parses it. Nothing answered those queries.

The pause now carves the query bytes out of what it discards, with the
same extraction the hidden-pane gate uses, and hands them to main's
existing responder. The responder answers only while no other view is
receiving that terminal's output.

Refs #32944

Co-authored-by: Ben Grynhaus <ben.grynhaus@wiz.io>

* revert: answer queries in output a pausing remote view discards unsent

This reverts commit 3fc500fe09. Answering those queries later through
main's emulator injects bytes into its live parser. That can cancel a
partial escape sequence, it answers cursor and mode queries against
state that has since moved on, and it can answer twice when two views
pause one after the other. An exact fix has to capture the replies when
the bytes are first parsed and track delivery per view, so it is left as
a follow-up.

Also renames a test helper to say what it reads.

---------

Co-authored-by: Ben Grynhaus <ben.grynhaus@wiz.io>
2026-10-24 16:14:02 -07:00
OrcaWinandOrcaWin 2479c5e20f test: consolidate redundant checks and verify behavioral boundaries (#33292)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 16:09:45 -07:00
Pr1p 04e07a6643 fix(opencode): prevent stale credential status after save (#33081)
OpenCode Go credential status: a late initial read can no longer overwrite a save/clear result, and pending/failed reads show Checking…/Status unavailable instead of Not saved. Fixes #33068.

Co-authored-by: Pr1p <48266347+Pr1p@users.noreply.github.com>
2026-10-24 16:08:47 -07:00
Neilandoutof-place c788a071d4 fix(terminal): fold Codex's inner thread-name spinner frame so session tabs stop republishing per tick (#33291)
Fold a standalone copy of the leading spinner frame in agent titles (Codex 0.155–0.163 `⠙ renaming... ⠙ | x`) so the title tracker stops republishing session tabs every 100ms. Fixes #27598. Supersedes #27599.

Co-authored-by: outof-place <69466055+outof-place@users.noreply.github.com>
2026-10-24 16:08:28 -07:00
Neilandzhangxaochen 70d9c97b98 fix(rate-limits): find agy for Antigravity usage in the env agent launches use (#33289)
Antigravity usage probe uses the same host shell env agent launches use, so agy is found under Git Bash on Windows. Fixes #31459, #28036. Supersedes #32032, #31809.

Co-authored-by: zhangxaochen <3416667+zhangxaochen@users.noreply.github.com>
2026-10-24 16:08:07 -07:00
NeilandDavid De Smet 2aae4577da fix(claude): restore scrubbed pane identity in the managed Claude hook (#33286)
Claude's hook script refills ORCA_PANE_KEY / ORCA_AGENT_LAUNCH_TOKEN from the scrub-safe aliases when CLAUDE_CODE_SUBPROCESS_ENV_SCRUB strips them, so scrubbed Claude panes report status and resume again. Fixes #31832. Supersedes #31834.

Co-authored-by: David De Smet <2607383+daviddesmet@users.noreply.github.com>
2026-10-24 15:54:59 -07:00
Neil 9c8ce8d818 refactor: group repository execution settings (#33261) 2026-10-24 15:46:51 -07:00
NeilandBingZ c344f3f0ab fix(source-control): drop Kimi flags Kimi Code rejects (--quiet, --thinking) (#33285)
Kimi Code (the current `kimi`) rejects --quiet/--thinking/--no-thinking; send only --prompt [--model]. Fixes #14771. Supersedes #14790.

Co-authored-by: BingZ <11211020+bbingz@users.noreply.github.com>
2026-10-24 15:44:18 -07:00
Neil 08ec2b3aac fix(orcad): a liveness probe must not mistake its own shell for orcad (#33158)
* fix(orcad): a liveness probe must not mistake its own shell for orcad

After a host or distro restart the recorded orcad PID is free, and the probe's own
'sh -c' (whose argv carries the slot paths) can be given it. The argv identity
check matched and kill -0 succeeded, so the probe answered LIVE: a wake skipped
the start and the next probe found nothing. The probe now treats its own PID, or
any shell process, as a reused PID.

* fix(orcad): only the probe's own shells count as reused, never another shell

Review: an older launcher (before exec) recorded a shell that waits on a live
orcad, and the setsid launch path holds an sh between the PID write and exec;
calling every shell reused turned those into DEAD, which permits GC and relaunch.
Only the probe's own shell and the shell wrapping it are now excluded.

* test(orcad): drop an unused parameter

* test(orcad): reap the waiting shell's node child after the liveness test

* test(orcad): keep the wrapping shell alive so the parent-PID case is exercised on dash
2026-10-24 15:33:52 -07:00
OrcaWinandOrcaWin c1a33b7372 test: assert persisted state and observable terminal and mobile behavior (#33282)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 15:30:18 -07:00
NeilandClaude 05165e759d fix(agent-status): keep Codex status on the main task through /side chats after a restart (#33275)
* fix(agent-status): keep Codex /side threads from taking over the pane after a restart

The /side guard keyed on transient caches (the parsed rollout and the
listener's own row), so after an Orca or relay restart a side thread's
hooks claimed the pane and its Stop showed the pane finished while the
main turn was still running. Decide by the stored row's thread instead,
on the execution host and again when a relayed hook arrives.

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

* fix(agent-status): recognise Codex side threads on the execution host only

Record ephemeral forks from their own SessionStart and fall back to the stored row's thread, so the host keeps dropping /side hooks across restarts without a desktop rule that cannot tell a fork from a new conversation.

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

* fix(agent-status): keep a running Codex turn when a relay restarts mid side chat

A relay that restarts during a /side chat has lost the fork's SessionStart, so the desktop keeps a running main turn against the rest of that thread's relayed hooks. Any relayed SessionStart still passes, so a new conversation can replace the row.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 15:13:35 -07:00
OrcaWinandOrcaWin 6b469405ec test: expose masked persistence and send-handler regressions (#33276)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 15:10:18 -07:00
Neil bfbe9637e9 Run generated worktree cleanup during automatic dev maintenance (#33277) 2026-10-24 15:09:18 -07:00
Neil 8c95a9bb5d fix(daemon): refuse input to a live terminal whose PTY stopped taking it instead of reporting delivery (#33269)
* fix(daemon): report input to a live terminal whose PTY stopped taking it instead of claiming delivery

* fix(daemon): treat master-retiring errors as closed input on every platform; keep same-incarnation close across spawn reply

* fix(daemon): track closed input per incarnation so a replacement's early report survives its spawn reply
2026-10-24 15:06:40 -07:00
NeilandSahilZ0810 0c27fd5f91 fix(ssh): move a managed tunnel off an unbindable saved local port (#33271)
* fix(ssh): move a managed tunnel off an unbindable saved local port

When the saved local port of a managed SSH server's tunnel can no longer
be bound (EADDRINUSE from another listener, or EACCES from a Windows
excluded port range), pick a free port, save it with the pairing and the
deployment link together, and build the tunnel again. The pairing, server
identity, remote port and projects are unchanged.

A move interrupted between its sidecar and store writes reads the moved
port from the stored endpoint, so the deployment link is never dropped.

Fixes #33182

Co-authored-by: SahilZ0810 <sahil@zamp.ai>

* test(e2e): drop squatter connections so teardown never waits on them

* fix(ssh): move the tunnel port before pairing repair and retire old transports

Move outside buildWithPairingRepair so a refusal on the moved port is
repaired against the revision the move saved, and retire transports and
status owners still dialing the old port, as a repair does.

* fix(ssh): refresh maintenance pairings on the current tunnel port

Update, rollback and restart reread the deployment's local port when they
save the new pairing, since the census before them may have moved it.

* fix(ssh): let concurrent tunnel builds follow a port another caller moved

---------

Co-authored-by: SahilZ0810 <sahil@zamp.ai>
2026-10-24 15:03:39 -07:00
Neil 2679464ead fix: let capable paired hosts plan composer terminal agent launches (#32192)
A workspace created from the composer on a paired host launched its terminal
agent with the desktop's command, arguments and environment. Hosts that
negotiate agent.launch.v2 now get startupAgent (and startupPrompt) and build
the launch through their own planner and settings. Older hosts, failed probes,
hosts that predate the agent's name, linked-item drafts and VM recipes keep the
desktop-built command. When the host planned the launch, the window never runs
the desktop plan or its own agent recovery, and says it couldn't confirm the
agent started if the host reported no agent terminal.
2026-10-24 15:01:29 -07:00
Neil 293bfe795d fix(browser): closing a host page retires a window-saved tab whose ids differ (STA-11998) (#33266) 2026-10-24 14:55:44 -07:00
Neil c197b9f3f1 fix(new-workspace): search and offer Linear on the same host in Create worktree (#33270)
* fix(new-workspace): read Linear status on the host the search runs on

Create worktree searched Linear on the selected repo's host but offered the
Linear tab from the focused host's status. With Linear connected only on the
desktop and a project on a paired server, the tab appeared and every search
silently came back empty. The repo-derived Linear source now reads its own
host's status, as explicit sources already did, so the tab and the selected
workspace follow the host that will answer.

* fix(new-workspace): keep Linear status per host while it re-reads, and treat loading as unknown

The host status read is keyed by host, not project scope, and a same-host
re-read (repo switch, workspace change, reconnect) keeps the last status
instead of reading as disconnected, so the Linear tab and the chosen mode no
longer reset. While the first read is pending, a chosen Linear tab stays
selected and a pasted Linear URL keeps blocking Enter. The credential-error
test now stubs the repo host's status read it depends on.
2026-10-24 14:49:24 -07:00
81a6cea193 fix(cli): say a headless terminal create found no workspace, not that the window is missing (#33264)
* fix(cli): say a headless terminal create found no workspace, not that the window is missing (#33044)

On a windowless `orca serve` host, `orca terminal create` from a folder
outside any workspace failed with "No renderer window available". The
create falls through to the window-only path because no workspace was
resolved, so name that and point at --worktree instead. Behavior is
unchanged; only the error message for this already-failing create.

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

* fix(runtime): pass the no-workspace message to the window lookup instead of relabeling every error

A catch-all would rename any other window-lookup failure as a missing workspace.

---------

Co-authored-by: tnfhrnsss <tnfhrns@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 14:46:49 -07:00
Neil e2b0e9a19e fix(runtime): a host status publication keeps the probed capability readable (STA-11921) (#33263)
* fix(runtime): a status publication that answers a pending probe leaves the capability readable (STA-11921)

* fix(runtime): keep negative-capability re-probe across a published replacement; split the test

* refactor(runtime): one compatibility-entry factory keeps the cache under max-lines
2026-10-24 14:45:31 -07:00
OrcaWinandOrcaWin 621a09def5 test: repair masked assertions and remove eight low-value checks (#33268)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 14:43:09 -07:00
Neil 2c500bffbe perf(orcad): start managed servers with a smaller V8 young generation (#31494)
* perf(orcad): start managed servers with a smaller V8 young generation

* test(orcad): tighten the launch byte ceiling to its measured size
2026-10-24 14:38:14 -07:00
NeilandClaude ad991175da fix(runtime): a split agent tab's shell panes restart as shells, not fresh agents (#32418)
Starting a saved pane with no live terminal (a paired client opening it, or a restore)
fell back to the tab's launchAgent for every pane with no recorded session, so a shell
split beside an agent pane came back as a fresh agent. The host's tab projection now
publishes the tab-wide launchAgent only on a sole pane, as the window already does, so
the pane start and every reader of that projection see the same per-pane evidence.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 14:35:02 -07:00
Neil 333be496a4 fix(ssh): Reconnect & Delete only deletes the workspace you selected (STA-11912) (#33253)
* fix(ssh): Reconnect & Delete stays pinned to the workspace the user selected (STA-11912)

* fix(ssh): say the workspace list changed and clear the shared delete state on a send-time refusal
2026-10-24 14:33:56 -07:00
NeilandBearMett 917899bf8d fix(runtime): stop paired desktops republishing mirrored editor tabs (#33259)
* fix(runtime): stop paired desktops republishing mirrored editor tabs

When two desktops pair both ways, B mirrored A's editor tabs and then
published them in its own session inventory as if B had opened them. A
then applied B's copy, which took over A's own tab.

isMobilePublishableOpenFile now skips rows marked
mirroredFromRuntimeSession, the marker is part of the open-files sync
projection so a flip republishes, and the marker is saved with the
session and restored so a relaunched client does not republish its
restored mirrors before the host's first snapshot.

Based on #25877 by BearMett.

Co-authored-by: BearMett <agomdole@gmail.com>

* fix(runtime): keep restored mirrors through unpublished frames and out of headless publication

A restored mirror now carries its marker, so an unpublished host frame
must not cull it (and its recovered draft). The windowless publication
skips persisted mirrored rows for the same reason the window does.

Co-authored-by: BearMett <agomdole@gmail.com>

---------

Co-authored-by: BearMett <agomdole@gmail.com>
2026-10-24 14:28:33 -07:00
Neilandethereal49 976fa11e81 fix(github): send a paired server its own repo id when an SSH row shares the path (#33257)
* fix(github): route runtime repo paths by execution host

When a repo path is registered on both SSH and a paired runtime, path-only lookup could send the SSH-side repo ID to the runtime. Prefer the row owned by the target runtime, then retain the original first-path fallback.

AI-Assisted: OpenAI Codex

Signed-off-by: ethereal49 <hongyeluo49@gmail.com>

* fix(github): resolve the runtime repo on the target host by the caller's repo id

getRuntimeRepoTarget now takes the caller's repo identity and resolves the
row through the repo lookup index, preferring the row on the target runtime
with that id, then the row on that runtime for the path. This keeps the
refresh sweep's repo reads linear (a per-call list scan broke that ratchet).
Legacy rows with no host stamp still fall back to id-or-path lookup.

Removes the test that pinned the off-host fallback; it asserted sending
another host's repo id to the server.

---------

Signed-off-by: ethereal49 <hongyeluo49@gmail.com>
Co-authored-by: ethereal49 <hongyeluo49@gmail.com>
2026-10-24 14:13:50 -07:00
NeilandClaude 7a0c7af69d fix(ssh): sign an SSH conversion's manifest as the host parses it (#32369)
The conversion hashed the exported objects, but the manifest parser keeps only the fields it knows.
A runtime-only field in the live session (gone after the next load) made the conversion's own
journal and the host refuse the digest until the app restarted. Sign the parsed form of the JSON.
Manifests without such a field sign exactly as before.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 14:10:08 -07:00
OrcaWinandOrcaWin 5be204618a test: strengthen rejection and callback coverage, remove redundant checks (#33256)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 14:09:35 -07:00
OrcaWinandOrcaWin c90d0f93c0 test: exercise real mobile controller and repair weak assertions (#33248)
* test: exercise mobile controller and strengthen audit assertions

* test: use array syntax required by React Doctor

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 13:54:31 -07:00
Neil 5ee74f4f83 refactor: group browser cookie source modules (#33250) 2026-10-24 13:51:37 -07:00