* feat(native-chat): copy chat selections when Copy on Select is on
The terminal's Copy on Select setting now also copies text selected in a
native chat transcript, at the point the Add to chat offer already treats
a selection as finished. It writes the same text right-click Copy does,
skips the composer and other fields, and leaves the setting key as is.
* fix(i18n): translate the Copy on Select description and search keywords
Settings and Settings search showed English to es, fr, ja, ko and zh users
after the description moved to new keys. Extend the old terminal-only
translations to cover chat, and translate the new highlight and chat search
keywords.
* fix(native-chat): send typing after a click to the chat's composer
The default Claude/Codex chat never wired the root typing redirect, so a
click in the transcript, on a toggle or link, on the chat's own tab, or on
blank app chrome left typed keys with nowhere to go. The chat-view-over-TUI
had the redirect but treated every button and link as a key owner.
Both views now share one hook that runs the reveal focus, focuses the chat
on blank clicks, routes keys typed inside the chat (but not in overlays it
portals out), and, while it is the only chat visible in the focused group,
routes keys typed with focus on the page body. Buttons and links pass
letters but keep Space and Enter. Re-activating an already visible chat tab
re-runs the composer claim, as a terminal tab refocuses xterm.
* fix(native-chat): refocus the composer when its active tab is activated again
Re-activating an already visible chat tab re-ran the ordinary reveal
claim, which stops as soon as focus is anywhere inside the pane. With the
transcript or a code-block Copy button focused, the tab shortcut left focus
there and Space kept scrolling or pressing the button. The activation now
moves focus to the composer from inside the pane too, unless a text field
such as the find input holds it; an ordinary reveal still keeps the user's
focus.
* feat(wsl-mover): shell history moves with the project to the WSL host (D1b-6c-1)
* fix(wsl-mover): moved WSL history lands under the host's login shell (D1b-6c-1)
* fix(wsl-mover): history follows the shell a pane would actually run, fallback included (D1b-6c-1)
* fix(wsl-mover): history installs follow the real pane shell, wait for live shells, and mark what they installed (D1b-6c-1)
* fix(wsl-mover): history installs wait until live shells can be checked (D1b-6c-1)
* fix(agent-launch): find a repo's project the way the window does
The host now also takes a project named after the repo as that repo's project, as the window
does, so both pick the same project row and runtime even when a repo was moved out of the
project named after it.
* refactor(agent-launch): share one repo-to-project match with the window
The host's agent-launch lookup and the window's launch preflight now call one projectMatchesRepo
instead of each writing the match out. No behaviour change on either side.
The drag preview's set-and-restore of the active tab per group now goes
through previewDragActiveTab, restoreDragActivationSnapshot and
restoreSourceGroupActiveTabAfterDrop instead of setState from a component.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Worktree removal, purge, rename, activation wake and SSH target cleanup now
build their tab/group/pane layout changes with named transitions in
tabs/worktree-layout-lifecycle.ts, folded into the same single store update.
Project removal drops its layout writes: purgeWorktreeTerminalState, run just
before in the same call, already cleared every one of them.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(terminal): park and quit capture keeps the stored pane layout
The capture that runs on quit, sleep and park rebuilt the whole pane tree
from the DOM. The tab's stored layout already follows every pane change, so
the capture now writes only what it alone knows onto that layout: the
scrollback buffers, the pruned scrollback refs, and the live PTY bindings
with the focus repair that goes with them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(terminal): keep a stored leaf's scrollback and binding while its pane is unmounted
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- ko Worktree Jump Palette: render "actions" as 동작 so it is distinct from
the tasks entry (작업) in the same list.
- zh DevTools cookie instruction: clarify the filter phrase to
`任意包含 remains 的请求`, keeping the literal `remains` request name.
Scan 2026-10-14: fill target-locale coverage for PRs merged since the
2026-10-13 scan (#28486). Adds the missing keys (es 98, fr/ja/ko/zh 125
each), updates the two changed WorktreeJumpPalette strings, and fixes
pre-existing mistranslations: the ZCode missing-TUI notice (English in
all five locales), fr settings search keywords (procuration/indigene),
zh workspace-cleanup browse MT, 6 zh keys that still used Latin "Agent",
and the zh AccountsPane credential-help cluster (leftover English and a
mangled __Host-console_session token).
Leaves the 11 pinned provider-credit-balance keys plus the 3 pinned Chat
UI keys as English fallback by design. Records the scan in
config/update-translation.txt.
* fix(ssh): the SSH password dialog no longer closes itself and comes back
A host that drops an unanswered login no longer replaces the open prompt
with a new one, a background dial no longer replaces a connection whose
reconnect is asking the user, one Cancel closes every open prompt for that
host, and a paired client's automatic connect stays automatic.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): a typed password its reconnect has yet to use is not replaced by a background dial
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
* Avoid unused module imports and trim cosmetic test coverage
* Capture hidden popup frames and attach CDP before guest creation
* Overlap relay test projects within the existing worker budget
* Consolidate native preparation and add an opt-in transform cache comparison
* Release inherited debugger sockets during final E2E teardown
* Refresh unit scheduling weights from all five qualified ARM shards
* Avoid retaining unasserted RPC call history in the delivery model
* Use the supported unconditional background wait syntax
* Overlap unconditional output upload with native preparation
* Verify relay integration stays enabled for ordinary unit callers
* fix(terminal): bring each pane back after a terminal service restart when it is shown
After Settings -> "Restart terminal service", every pane that was open kept its
dead process: typing did nothing and agents never resumed until Orca relaunched.
A restart-replaced exit now arms the pane: the visible pane spawns its
replacement at once, any other pane when it is next shown, through the same
fresh spawn and cold-restore agent resume the hibernation wake uses, so old
output stays above the new prompt. The exit keeps the agent status the resume
reads, and clears the dead binding so the replacement binds as a first spawn.
Local spawns wait for an in-flight restart so they reach the new daemon.
Claude-Session: p2-headless
* fix(terminal): resume from the live recovery record; skip a pane another flow rebound
A restart exit is a process death to main's agent-status store, which clears the
pane's row before the window sees the exit, so keeping the window's copy changed
nothing. The resume reads the live recovery record every agent turn already
writes, as a relaunch after a crash does. The replacement also stands down when
the pane's stored binding already names another process.
Claude-Session: p2-headless
* fix(terminal): send every restart exit down one path
A finished-turn agent pane took the hibernation wake, which gives up when its
record changes before the pane is shown. Every restart exit now arms the
replacement directly.
Claude-Session: p2-headless
Ten create sites now mint the new tab's id (or browser page id), pass it to
the create action, and key every follow-up (select, focus, tab order, group
focus, remote page handle) off that id instead of the returned record.
Creates stay synchronous, so the follow-ups still run immediately.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A workspace with no groups got a random root group id from the window. It
now gets the name-based id the shared loader already mints for that
workspace's group, so main can derive the same id without the window.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(wsl-mover): a moved pane reopens in its last folder on the WSL host (D1b-6b)
* fix(wsl-mover): consume a restore hint only when its pane spawns, scope it to its worktree, retry failed installs (D1b-6b)
* feat(orcad-migration): a capability-gated blob channel beside scrollback, for the WSL mover's new data (D1b-6a)
* fix(orcad-migration): the commit names its blob set, prune clears leaked blobs, reserved names refused (D1b-6a)
* perf(ci): reduce test overhead and reuse expensive build work
* test(ci): keep worker startup outside failure-case deadlines
* test: isolate push fixture advisory locks
* test(ci): preserve fixed drain retry allowance
* Align CI contracts with current triggers and guide content
* Stabilize consolidated reveal scenarios and retain behavioral CI contracts
* Fix upstream lint blockers while retaining behavior and assertions
* Classify global Jira preferences in the WSL migration inventory
* Align Jira test fixtures with startup and build safety checks
* Include package-test routing dependency in CI checkouts and fixtures
* Keep native stream classes intact in transcript dependency tests
* fix(terminal): keep a hibernating pane's resume record through its stop
The agent dies before its shell, so the shell's command-finished mark read
as the agent exiting and deleted the record the hibernation had just written.
* fix(automations): sleep a finished run's terminal instead of closing it
Closing it left the run's own workspace empty, so opening it later showed a
blank chat or shell instead of the run's conversation.
Fixes#28645
* feat(chat): Resume in New CLI for OpenCode and OMP chats
OpenCode's and OMP's CLIs have no copy flag, but their chat protocol copies a
conversation (ACP session/fork). For a fork of one of their chats, the chat's
host now has a short-lived agent, launched exactly as the chat's own, copy the
conversation; the terminal then opens the copy with a plain resume. The chat
keeps its own conversation, so the CLI is never a second writer on it.
The copy travels on the existing aiVault.prepareSessionResume fork request as
an optional forkedSessionId; a host that predates it answers without one, and
the client asks for an Orca update instead of resuming the original.
* fix(chat): open an OpenCode 2.x chat's CLI copy with opencode, not opencode2
The copy kept the row's agent, so Resume in New CLI ran `opencode2 --standalone --session <copy>`,
which OpenCode 2.x doesn't install. The chat's host now answers the copy with the agent whose CLI
opens it: the chat's own.
* fix(chat): type the copied conversation's agent as a history agent
* fix: preserve independent chat copies through CLI launch
* test: keep only the tests that pin user-visible behavior
* fix(chat): validate OpenCode copies on their execution host
* test(chat): expect copied OMP forks after main integration
* Run safe worktree cleanup on dev and add interactive pnpm reclaim
* Rename storage cleanup command to reclaim-space
* Keep real stream constructors in transcript dependency tests
* Detach cleanup output and align historical cache previews
* fix(terminal): reject a requested tab id that is already taken
createTab silently minted a fresh id when the caller's requested id was
already in use. The caller's PTY routes agent status by the id it asked
for, so the new tab never received its agent status and the status went
to the other tab instead. Now the create throws and changes nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(agent-launch): drop the unreachable tab id mismatch guard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Skip reindexing unchanged transcripts on cold session list reads
A cold session-list read re-parsed every self-contained transcript and rewrote its search rows, even when nothing had changed. That wasted work and churned the index on every list.
- When a transcript's stat (mtime, size, inode, device) matches a complete index entry, the list read now skips the rewrite. Agents with sidecar metadata, unknown sizes, or partial or stale entries still reread.
- Test fixtures that replay a "changed" transcript now pass a new mtime so they still exercise the replace path.
- New tests cover unchanged skips, changed size/mtime/file identity, sidecar refresh, due/failed repair, and append.
- Dependent-transcript and Codex title tests check that cold rereads keep search and title data current.
* Make the self-contained transcript check exhaustive over every agent
- Replace the hand-maintained `Set` of self-contained agents with a
`Record<AiVaultAgent, boolean>`, so adding an agent type fails typecheck
until someone decides whether its transcript is self-contained.
- Classification is unchanged: the agents that were in the set are `true`,
and the rest are `false` with a short note on the sidecar or metadata
source they depend on.
- Make the replace-generation tests derive the second mtime from the first
candidate instead of a hard-coded timestamp, so they stay valid if the
default fixture mtime changes.
* Guard file-stat reuse with a self-contained transcript test
Indexing skips reparsing unchanged transcripts for agents marked self-contained. That is only safe if their parsers read nothing but the transcript itself, and nothing enforced it. A parser that started reading a sidecar or dependency file could serve stale index entries.
- Export SELF_CONTAINED_TRANSCRIPT_AGENTS so the test checks the real list
- Add a test that parses each self-contained agent's fixture, both direct and cached, and fails if any file other than the transcript is read
- Register the test in the SQLite runtime-file include list
* Require stored file identity before skipping a transcript rewrite
- Rows with a NULL dev or ino were treated as covered, so a file replaced with the same size and mtime could be skipped and never reindexed.
- Such rows now count as uncovered, so the rewrite runs and records the identity.
- The identity is read through the shared `fileIdentity` helper instead of the raw file fields.
* Add regression test for session rows indexed without file identity
A session row indexed before file identity (dev/ino) was recorded was never reread once the stat began supplying one, so it could keep stale search content. This test covers that case: the first read with identity replaces the row, and a second read with the same identity leaves it alone.
* test(session): compare what the window shows before and after the shared session loader
Boots the window's real startup hydration on each saved-profile fixture as
stored and as the shared loader rewrites it (load then save), and compares
tabs, groups, active tabs, pane trees, terminal bindings, editor and browser
tabs. Today's eight differences are listed with the loader rule behind each;
the list may only shrink, so any new difference fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(session): let the parity test own its store so the harness reads no host focus
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(session): restore the parity boot's UUID spy even when the boot throws
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Restarting the terminal service ends each session with a synthetic -1 exit. Main
read those as ordinary deaths and retired every terminal surface from the saved
layout, while the window kept drawing them. Phones and the CLI lost the tabs, and
the next launch restored a split as a single pane.
The restart now labels those exits as replaced, and main records them in its
existing intentional-stop register, the one terminal restarts already use. The
runtime keeps the surface and the window receives the same replaced label.
Claude-Session: p2-headless
Seven call sites created a terminal tab and then queued its startup command
in a second store write. Pass the command through createTab's existing
pendingStartup option instead, so the tab and its command land in one write.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The dialog title and cancel button said 掃除 (household cleaning), while its own description and confirm button already say クリーンアップ. Use クリーンアップ throughout.
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
The Japanese option read 掃除済み ("housekeeping done"), while the migration notice that points to the same setting already calls it クリーン. Use クリーン in the option and its settings-search keyword.
Also restore the literal CLI command in the reset hint, which translation had re-capitalised in ja, zh, and fr so it could not be copied and run.
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* feat(wsl-mover): background writers back off a project a WSL move is taking (D1b-5c-3)
* fix(wsl-mover): re-check before renames, quiet owned automations, stable folder ids (D1b-5c-3)
* test(wsl-mover): seed journals one phase at a time and advance existing moves (D1b-5c-3)
* fix(wsl-mover): a branch rename that already ran settles even when the move skips the folder (D1b-5c-3)
The layout stream (layout.subscribe, still unused) re-loaded every session
partition and ran the load's save-and-diff report after each write. A save
now names the partition it wrote, the stream re-loads only that partition
without the report, and the renderer layout client no longer re-subscribes
on a timer. Adds a latency spec variant with a subscriber attached.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(tabs): delete unused copy-tab and merge-group store actions
copyUnifiedTabToGroup and mergeGroupIntoSibling had no callers outside
the store and its tests. Tests that used the copy action as a setup step
now create the duplicate tab directly, the same call the action made.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(tabs): follow the split-ratio file rename in the layout-writer baseline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
OpenCode in a \\wsl$ repo runs in WSL whatever the project's setting, and Orca can't verify a
model there yet, so picking one is refused, as it already is for a project set to WSL, instead
of being checked on Windows.
* fix(files): never write through a dangling symlink
A path that doesn't exist yet was authorized by walking up to the nearest
existing folder. A dangling symlink fails realpath with ENOENT, so the walk
stepped over it and approved the link's own path; the write then followed
the link and created its target outside the allowed folders. The walk now
continues from the link's target, and returns that real destination.
* refactor(native-chat): rename the chat visuals folder to the chat scratch folder
The per-chat folder agents write into is the chat's scratch space, not only
a visuals folder. Its root becomes <state>/chat-scratch/<hash> (the hash is
unchanged) and the agent variable becomes ORCA_CHAT_SCRATCH_DIR. The old
ORCA_CHAT_VISUALS_DIR is never set and is still stripped from what every
agent child inherits, Pi included. The visuals skill names the new variable
and says the folder is temporary.
* test(native-chat): keep the delivery test to the rename
The launch parity snapshot already pins that every agent drops the
pre-rename variable.
* fix(files): refuse any dangling symlink in the missing-path walk
Following a dangling link by hand resolved relative targets against the
lexical parent, not the link's real folder: through a folder link the walk
could loop forever or authorize the wrong file. Refuse instead: realpath
can't say where a dangling link leads, but a write would follow it.
* feat(runtime-files): the host serves a chat's scratch folder as a file root
File commands accept `path:<this host's chat-scratch root>/<32 hex>` and
resolve it only when it names this host's own folder, at the file-commands
seam so the selector never reaches chat placement. They authorize against
the project roots plus the chat-scratch root, refuse files.open/openDiff
for the folder, and agentSession.readVisual's ok results carry the file's
absolute path so a client can build the selector.
* test(runtime-files): name the readVisual helper's parameter type
* test(files): drop the loop case that duplicated the dangling-link refusal
* test(runtime-files): run the readVisual RPC test, which opens a real SQLite store, under Node
* test(runtime-files): put the same-suffix folder inside the authorized root so only the selector refuses it
* refactor(native-chat): open a chat visual like any file
"Open in new tab" on an inline chat visual now opens the visual's file the
way any HTML file of the chat's workspace opens: a file:// browser tab for a
local chat (its overflow menu gains "Open source file"), the document
preview for a paired-host chat (with its existing source action and Share).
Edits save on the chat's host through the exact path: selector the host
serves, and a matching editor save re-reads the inline copy freshly. The
read-only chat-visual tab is removed.
* feat(native-chat): share a chat visual from the chat
The inline visual's toolbar gains Share beside Open. It publishes under the
file's own key on the chat's host, the key the opened preview and editor use,
so every surface updates one link. The published text comes from a fresh read
begun after the click; a failed read publishes nothing and says the visual
couldn't be read. The toolbar stays shown while Share's popover is open.
* fix(native-chat): a visual read without a path is a malformed reply
A visual's path is always on the current host's readVisual answer, so the
inline Open needs no branch for a missing one. Also prune the deleted
chat-visual tab action from the layout-writer baseline.
* test(native-chat): give visual read replies their path without longer lines
* fix(native-chat): address a scratch file by its folder only outside every workspace
A workspace that contains the host's state folder keeps its own address, so
explorer drops, folder creation and renames inside it stay on one root.
Document preview Share reads a runtime grant's own selector and root
directly instead of passing the selector off as a workspace id.
* fix(native-chat): show a chat visual's Share whenever it shows
Every read now carries the visual's path, so Share no longer waits on one; its
key comes from the path the click's fresh read returns.
* test(runtime-files): wait for the stores to close before removing the state folder
* feat(wsl-mover): pause a moving project's terminals through Sleep and prove they exited (D1b-5d)
* fix(wsl-mover): gate again under the fence, swap journal phases atomically, keep sessions frozen through commit (D1b-5d)
* test(wsl-mover): the fence e2e walks the journal one phase at a time, as a move writes it (D1b-5d)
* Rank browser history above fuzzy file matches in the omnibox
Scattered-character fuzzy file matches are weak evidence, so a remembered
page should appear above them. Exact and literal file matches and typed
URLs still rank above history. Adds a test for typing a host like
linear.app, which should rank the page above unrelated fuzzy files.
* Anchor omnibox history on the typed URL instead of demoting fuzzy files
The real bug: after visiting https://linear.app/, typing `linear.app`
made Enter open an unrelated file. The history row removes the typed-URL
row it duplicates, but was then placed below every file match, so the
page lost the top slot the URL row had.
History now sits with the typed URL row (in its slot when it replaced
it). Queries with no typed URL keep the old rule: below every file match.
This replaces the previous commit's rule of ranking history above
"fuzzy" files. That label covers every non-exact match for queries with
a slash, a dot suffix or a space, so a code-host page whose title holds
the file path took Enter away from local rows for path queries (or left
nothing selected when pasted). It also left `localhost` broken when a
file name contained it.
* feat(telemetry): count agent start failures from the host too
The host spawn path (CLI, phone, orchestration workers, headless automations,
worktree startup) now records agent_error when starting an agent fails, as the
window path already did. Removes C5a's TEMPORARY recordsAgentError input; the
host already threads each launch's telemetry, so failures get real kinds.
* fix(telemetry): count a claimed start that several requests joined once
Concurrent resumes of one agent session join one claimed start. When it
fails, every joined request ran the host catch and recorded agent_error, so
one failed start counted once per request. Only the request that ran the
start records it now; the others still clean up.
* fix(telemetry): only skip agent_error for a request that joined another start
The host marked a request as joined before calling ensure, so a claim that
refused the request on its own (conflict, capacity, unreachable owner) recorded
no agent_error. ensure now reports the join itself, right before awaiting the
other request's start.
* chore: re-run CI after main's localization fix (#28810)
* feat(chat): Resume in New Native Chat for Pi terminal conversations
A Pi conversation started in the terminal now offers "Resume in New Native Chat" in its Session
History row menu and its tab's right-click menu, like the other chat agents: a new Pi chat takes
it over, showing its history and continuing it.
Pi joins the shared adoption path. Its import finds the session file Session History lists under
the row id, and reads it with OMP's decoder, since OMP kept Pi's session format. A Pi chat's handle
names its session file, so the import says so and create mints the adopted handle from the found
file; the committed-create replay compares through the registration's row id, and the adopted
link id is kept to the link-id alphabet. A Pi chat forks a conversation recorded in another folder
instead of resuming it, so the workspace rule covers Pi too.
* fix(pi): preserve adopted session identity and active history
* Fix saved Pi adoption history and summary content
* test: keep only the tests that pin user-visible behavior
* feat(wsl-mover): refuse edits to a project a WSL move is taking, and drop its background bookkeeping quietly (D1b-5c-2)
* fix(wsl-mover): hide only local rows of a moved project; the host's own row keeps its id (D1b-5c-2)
* fix(wsl-mover): refuse a user's unread toggle, fence branch deletes, host setups and issue commands; settings unfreeze once the host owns a repo (D1b-5c-2)
* test(wsl-mover): the fence e2e refuses edits to moving projects and drops their bookkeeping quietly (D1b-5c-2)
* refactor(wsl-mover): name the update type the fence inspects (D1b-5c-2)
* test(wsl-mover): run the fence tests that open a real store in the Node runtime (D1b-5c-2)
* fix(wsl-mover): a host setup's own repo stays frozen once the host owns it; e2e pins the quiet drop (D1b-5c-2)
The automation removal deleted the screens but kept their strings in every
locale catalog. With no call site left, the boot-bundle catalog check counts
them as required and fails on main.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(files): never write through a dangling symlink
A path that doesn't exist yet was authorized by walking up to the nearest
existing folder. A dangling symlink fails realpath with ENOENT, so the walk
stepped over it and approved the link's own path; the write then followed
the link and created its target outside the allowed folders. The walk now
continues from the link's target, and returns that real destination.
* refactor(native-chat): rename the chat visuals folder to the chat scratch folder
The per-chat folder agents write into is the chat's scratch space, not only
a visuals folder. Its root becomes <state>/chat-scratch/<hash> (the hash is
unchanged) and the agent variable becomes ORCA_CHAT_SCRATCH_DIR. The old
ORCA_CHAT_VISUALS_DIR is never set and is still stripped from what every
agent child inherits, Pi included. The visuals skill names the new variable
and says the folder is temporary.
* test(native-chat): keep the delivery test to the rename
The launch parity snapshot already pins that every agent drops the
pre-rename variable.
* fix(files): refuse any dangling symlink in the missing-path walk
Following a dangling link by hand resolved relative targets against the
lexical parent, not the link's real folder: through a folder link the walk
could loop forever or authorize the wrong file. Refuse instead: realpath
can't say where a dangling link leads, but a write would follow it.
* feat(runtime-files): the host serves a chat's scratch folder as a file root
File commands accept `path:<this host's chat-scratch root>/<32 hex>` and
resolve it only when it names this host's own folder, at the file-commands
seam so the selector never reaches chat placement. They authorize against
the project roots plus the chat-scratch root, refuse files.open/openDiff
for the folder, and agentSession.readVisual's ok results carry the file's
absolute path so a client can build the selector.
* test(runtime-files): name the readVisual helper's parameter type
* test(files): drop the loop case that duplicated the dangling-link refusal
* test(runtime-files): run the readVisual RPC test, which opens a real SQLite store, under Node
* test(runtime-files): put the same-suffix folder inside the authorized root so only the selector refuses it
* refactor(native-chat): open a chat visual like any file
"Open in new tab" on an inline chat visual now opens the visual's file the
way any HTML file of the chat's workspace opens: a file:// browser tab for a
local chat (its overflow menu gains "Open source file"), the document
preview for a paired-host chat (with its existing source action and Share).
Edits save on the chat's host through the exact path: selector the host
serves, and a matching editor save re-reads the inline copy freshly. The
read-only chat-visual tab is removed.
* fix(native-chat): a visual read without a path is a malformed reply
A visual's path is always on the current host's readVisual answer, so the
inline Open needs no branch for a missing one. Also prune the deleted
chat-visual tab action from the layout-writer baseline.
* test(native-chat): give visual read replies their path without longer lines
* fix(native-chat): address a scratch file by its folder only outside every workspace
A workspace that contains the host's state folder keeps its own address, so
explorer drops, folder creation and renames inside it stay on one root.
Document preview Share reads a runtime grant's own selector and root
directly instead of passing the selector off as a workspace id.
* test(runtime-files): wait for the stores to close before removing the state folder
* feat(native-chat): record which agent run wrote each journal item
Each journal item row, subagent roster entry and background-task entry now
records ownerFence: the lease fence of the agent run whose output produced it.
Optional, persisted, no row version bump and no migration. The journal's
itemFence() returns it, so the turn-verdict rules and per-run provider activity
read the producing run rather than the writer's fence.
* test(native-chat): fewer provenance tests: fold reopen and unstated-owner checks into the main case
Drops the epoch-replacement case (Part 2 rewind test reads the same values through the same rebuild) and the corrupt-value case (no version writes one).
* test(native-chat): an unstamped roster entry from an older build reads as its row provenance
Moved here from Part 4 so it sits beside stampJournalEntryProvenance.
* test(native-chat): build the older-build roster row inline, after main removed its body helper
Main #27947 writes one row per subagent and deleted journal-subagent-group-body; a roster row from an older build is still what this case reads.
* refactor(native-chat): provenance is per item only; drop per-entry stamping
Main's #27947 writes one saved row per subagent, and each background task already has its own row,
so an item's own ownerFence names the run of every entry a producer still writes. Per-entry stamps
inside a row mattered only for the shared roster rows saved before #27947, and no run writes into
those any more, so the row's own provenance settles them correctly. Removes the entry stamping,
the optional ownerFence on roster entries and background tasks, and their tests.
* fix(native-chat): an item's provenance is set when it is created; revisions keep it
A newer run's provider can revise an item an older run created: Pi's start and an ACP
session/load both report context usage onto the newest saved turn. Restamping that turn with
the newer run let the newer run's exit settle the older run's unverifiable turn as interrupted.
Only creation states an owner now, as main's itemFences rule did.
* test(native-chat): keep the provenance test below the production lines it covers
A refusal names a \\wsl$ working directory first, since no runtime setting can move it out of
WSL, and names Settings > Project Runtime when the runtime comes from the global default.
* Bound and sanitize CI failure excerpts with linear ANSI stripping
* Fix excerpt regression checks and reduce bounded marker overhead
* Require signal proof for benchmark timeouts and load consumer fixtures portably
* Validate benchmark timeout framing and run required cases with a pinned CI baseline
* Strip dense generic ANSI escapes with bounded forward scanning
* Use the standard UTF8 encoder for byte-cap test oracles
* Gate CI log performance suites behind a dedicated job
The wall-clock performance suites run about 1k child workloads up to 63 MiB, so they were sharing runners with unit tests and could fail on noise. They now run only in their own `check_log_performance` job, opted in with `ORCA_CHECK_LOG_PERF=1`.
- Remove the pinned-baseline checkout and `ORCA_CHECK_LOG_BASELINE_DIR`. The baseline comparison is now a manual step that reads the pinned ref from local Git history.
- Run the current-implementation checks with `compareBaseline: false`, which skips baseline builds and audits.
* Inline check-log fixture and drop dedicated perf CI job
- Replace the captured failure-log JSON with a synthetic log built by `createCheckLogFixture()`, so no scraped job output or provenance metadata is kept in the repo.
- Remove the `check_log_performance` CI job. The log performance suites now run only when `ORCA_CHECK_LOG_PERF=1` is set, as a manual benchmark.
- Update the benchmark scripts and tests to use the new fixture helper and drop the `fixturePath` parameter.
* fix(terminal): judge an agent's --shell against the runtime it runs in
`orca terminal create --shell` for an agent is now judged only against the runtime that agent
runs in, not also against the project's saved runtime. So --shell wsl.exe for an agent in a
\\wsl$ repo (saved as Windows host, or with no setting) runs instead of being refused.
* chore(ci): re-run checks against current main
* chore(ci): re-run checks against current main
* chore(ci): re-run checks against current main
* chore(ci): re-run checks against current main
* chore(ci): re-run checks against current main