Commit Graph
13195 Commits
Author SHA1 Message Date
Jinjing 69cf557a69 fix(sidebar): keep project headers from overlapping the pinned host (#26775)
The host header lays out as a 32px card in 4px top padding (36px), but
estimateRenderRowSize sized the row at 32px. The group tier's 36px pin
offset then fired 4px early, so a project header could pin while its
in-flow copy was still on screen — two headers at one coordinate.

Size the host row 36px so it matches the pinned slot, and resolve each
sticky handoff from the row's real start offset instead of only the
lagging range start, so a header pins exactly when it reaches the slot.
2026-10-09 00:09:06 -07:00
NeilandNaveen Chatlapalli cc2ad7b188 fix: dispatch Muse Windows hooks directly on safe profile paths (#26755)
Run Muse Windows hooks through the existing direct launcher on safe profile paths and refresh managed installations. Keep the PowerShell compatibility fallback for paths requiring special quoting. Verified on Windows; CI passed.

Adapted the direct-launcher change from community PR #26734.

Co-authored-by: Naveen Chatlapalli <naveen.aifanatic@gmail.com>
2026-10-09 00:05:58 -07:00
Neilandfanzzzd cf8cc09e25 [CI] Enable the existing Windows hang watchdog and preserve restart evidence (#26763)
Enable the independent hang watchdog on Windows and preserve the previous run's marker until the startup trace sink is ready. Retain local consent, heartbeat timing, worker cleanup and bounded marker validation. Operation tracking is deferred.

Adapt the startup-order regression coverage from community PR #26468.

Co-authored-by: fanzzzd <fanzzzd@outlook.com>
2026-10-08 23:58:04 -07:00
Neilandm4air f01bd93748 Keep managed workspace paths out of desktop editor launches (#26668)
* Guard desktop open actions with the target workspace owner

* Wait for the folder catalog only in the folder menu exercise

* Resolve the row owner only while its Open in menu is open

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 23:49:11 -07:00
Brennan Benson ded0144525 fix(native-chat): settle a dead agent's leftover work in one write that always fits (#26664)
* fix(native-chat): settle a dead agent's leftover work in one write that always fits

A dead generation's cleanup was several separately committed writes, and a
single leftover item larger than one batch row was rejected on every try, so
the chat stayed stuck. Plan every row first and commit them in one
transaction: bounded batch rows, an oversize item as an ordinary row with its
full body, and the settlement's own send verdicts. Readers see it only after
the commit. Settlement rows are rebuilt only from schema-known fields, address
saved items by their stored key, never invent an end time, and new writes
require safe revisions, so cleanup never builds a row it cannot save.

* fix(native-chat): settle Codex exits in one write and keep turn fields a newer build saved

- Codex's own exit cleanup hands the whole settlement to the journal's one-transaction planner instead of committing chunk by chunk.
- One shared planner rejects an item named twice, on both the direct and resolved paths.
- Rewriting a turn keeps fields this build does not know, as the journal schema promises; the legacy carrier's kind still cannot override it.
- Drop the write-only revision admission and the planner skip that worked around it: insert admission is the reader's again, and a saved revision that cannot advance is skipped by the reducer while the rest settles, as before.
- Remove two dead-generation journal members settlement no longer calls.

* fix(native-chat): advance repeated items across a settlement's rows and keep nested turn fields

Repeated Codex question ids in one write fold in order again instead of failing the write,
and a saved turn's context usage keeps fields a newer build stored inside it.

* test(native-chat): run the new Codex journal SQLite tests in the Node runtime project
2026-10-08 23:47:49 -07:00
github-actions[bot] db53143032 Update README downloads badge 2026-10-09 06:47:37 +00:00
Neil 46460d49c7 feat(runtime): require Node 24 for servers and remote hosts (#26171)
* feat(runtime): default to bundled Node 24 and require modern hosts

* Update SSH deployment expectations for Node 24 guidance

* Expect Node 24 in Windows runtime installation guidance
2026-10-08 23:35:11 -07:00
Brennan Benson d7e985caa7 Start worktree.create's agent through the launch executor (#26709)
* Start worktree.create's agent through the launch executor

The host's worktree.create handler now starts a requested agent (startupAgent,
or a linked startupDraft) through executeAgentLaunch instead of calling the
create directly. Nothing on the wire changes: the request, the reply and
agentTerminalHandle are the same, the agent is still the workspace's startup
terminal whatever the chat default says, and the create still delivers the
text itself (folded into the command at any length, a follow-up for agents
that read it after start, and the draft pasted unsent).

Adds three host-internal executor inputs: terminalOnly, the legacy-host prompt
policy, and a shared entry (createWorktreeWithStartupAgent) that host
producers can call in place of createManagedWorktree.

* Keep a linked-draft create recording only the agent it actually started

Problem: after worktree.create moved onto the launch executor, a create from
a linked issue (phone "create from issue", or a raw worktree.create with
startupDraft) could differ from before in two narrow cases. When the draft's
agent came from the settings default or from detection and its launch command
could not be built (for example unbalanced quotes in the saved agent
arguments), the workspace was recorded as created with that agent even though
it never started, and a background create opened no terminal at all instead
of its plain shell. When no agent was found, detection ran twice (an extra SSH
round trip on remote repos).

User-facing change: none intended; both cases now behave exactly as before
the executor move.

Mechanism:
- The entry hands the draft's chosen agent to the create as a main-internal
  startupDraftAgent, which steers only the draft; createdWithAgent stays what
  the caller sent. A draft that resolves no agent is created without the
  draft, so the create does not detect again.
- AgentLaunchExecution is a discriminated union: every normal launch must
  bring its surface factory, and a legacy-host launch must be terminal-only,
  bring a workspace factory, and cannot bring surfaces. The runtime guards
  the types replace are gone; the target kind is checked before any create.
- Legacy-host receipts follow the delivery module's rule: a blank prompt is
  no prompt, a submit folded into the launch command is handed-to-terminal,
  a post-start send the create does not await is unconfirmed (host-internal),
  a draft is not-delivered.
- The no-agent error lives with the legacy-host policy and is caught only by
  the shared entry.
- Tests: a real-runtime parity test (stored agent, terminal spawns,
  detection count vs the create alone, including the unbuildable plan),
  exact-argument checks over every non-agent startup field, compile-time
  checks for the union, and direct tests of the draft agent resolver.

* Say which creates still bypass the shared agent entry

Two comments stated that headless automations and federation already go
through createWorktreeWithStartupAgent; both still call
createManagedWorktree directly. Reword them as the plan. Comment-only.
2026-10-08 23:27:32 -07:00
Brennan Benson fc5eb16034 Send a headless automation's prompt to agents that read it after they start (#26703) 2026-10-08 23:26:51 -07:00
Brennan Benson 55d348d671 feat(native-chat): show an agent message's sender by its current title, clickable on the queued card too (#26357)
* feat(native-chat): name an agent's message by its current title, and open it from the queued card

The sender line on another agent's message and on its queued card now shows the
name Orca shows for that agent right now (its sidebar agent row or chat tab
name), falling back to the name recorded when it was sent. The queued card's
names open the sender, as the transcript row's already do.

* fix(orchestration): name a CLI agent sender by its tab's own name, not just its agent

A terminal agent's recorded sender name used only a manual tab rename, else the
agent type, so mail from CLI agents read as "Codex" or "Claude". The host now
names every sender the way Orca shows it: a chat by its rename or saved name, a
terminal agent by its sidebar agent row's name (rename, quick command, generated
or meaningful live title; a split pane only by its own title). The task title and
generic agent label are fallbacks. The renderer shows the live own name, else the
recorded one.

* fix(orchestration): preserve known sender names in message snapshots

* Preserve sender names across chat clears and terminal reuse

* fix: keep sender links on the recipient host across older runtimes

* test: type sender naming fixtures with their declared identities

* Fix sender ownership publication after clearing a chat

* Drop /clear sender lineage now that /clear keeps the same conversation

Main's #26579 keeps a native chat in the same session across /clear, so a
message's sender id still names the live chat. Remove the host's
orchestration-root projection, the optional status field, and the renderer's
lineage lookup and feed capability probe that only served it.
2026-10-08 23:25:08 -07:00
Brennan Benson d273d85606 fix(native-chat): underline a file path only once its workspace confirms it exists (#26675)
* fix(native-chat): underline a file path only once its workspace confirms it exists

Chat underlined any path-shaped text, so an example path an agent made up
(`src/app.ts`) looked clickable and a click said "File not found". The
terminal already checks a path on its host before underlining it; chat now
goes through that same code: the terminal's path finder, one shared
resolve-and-check step (terminal-file-link-target.ts), and the same
longest-match rule. The terminal's hover and click fallback use the shared
step too.

Fixes STA-9683

* fix(native-chat): recheck every shown file link when a turn ends or the host returns

Chat only forgot "missing" answers at turn end, so a file deleted or renamed
during a turn kept its underline, and a path the host could not answer
stayed plain until the message remounted.

Each answer now records the recheck generation it was asked in. A turn end,
or a reconnect / re-pair of the host answering for the workspace, starts a
new generation and re-asks only the paths shown by mounted messages; old
answers keep showing until the host replies, and only messages whose answer
changed re-render. A reply to an older question cannot overwrite a newer
answer. A host that cannot answer keeps the previous answer and is retried
three times with backoff, ending when no message shows the path or at the
next recheck. While an SSH workspace's connection is unresolved, paths are
treated as unknown instead of being checked on this machine, and the chat
starts over once the connection resolves.

* fix(native-chat): keep main's file-path shape rules and check existence on top

Chat detection goes back to main's rules: a candidate needs a folder plus a
rooted prefix, a line suffix or an extension, and prose spans are split into
tokens as before. Bare names and folders are not underlined, and ordinary
prose no longer sends word prefixes to the host. Existence is required on top,
so the underlined set only shrinks compared with main.

A rooted spaced span ("/Users/me/repo/src/x.ts to use src/app.ts") now also
offers its tokens, so both real paths link; a real spaced rooted path still
wins as the longest one that exists.

Tests: bare names and folders stay plain even when they exist, slash tokens
and versions stay plain when everything exists, `My Notes.md:7` is rejected by
shape, explicit links and fenced code never reach the existence check, plus
the rooted-then-relative and longest-span cases.

* fix(native-chat): catch up file links answered before subscribe; tighter recheck triggers

- A message renders (and asks) before it subscribes; an answer landing in
  between was never shown. Each message records the answer its render used,
  and on subscribe it re-renders if the answer differs and re-asks outdated
  paths. A failure for a path no message shows yet no longer arms a retry.
- A rooted path ending a sentence ("/Users/me/r/a.ts.") inside a longer span
  now links, with the punctuation kept outside the link. Unrooted spans are
  unchanged, matching main.
- The checker takes the workspace's SSH connection id and decides
  "connection not known yet" from it, so the provider memo needs no lint
  suppression.
- SSH reconnects recheck only when the connection reaches connected or gets
  a new generation, not on every intermediate status.

* fix(native-chat): never check a network share outside the workspace without a click

Chat checks every path in a finished reply on its own. On Windows, a local
check of a path like \\server\share\a.ts or //server/share/notes.md opens an
SMB connection to that server and sends the user's credentials, and agent
text can be steered by prompt injection. Such a path is now never asked
about and stays plain text, unless it is inside the workspace or is a known
workspace root. WSL paths (\\wsl$, \\wsl.localhost) and checks made by an SSH
or remote runtime host are unaffected. Terminal hover and click behaviour is
unchanged.

* chore: restore main's copy of structured-agent-session-queued-mutations.ts

The merge commit's format hook dropped one blank line in this unrelated file.
Committed without the hook so the file matches main byte for byte.

* refactor(native-chat): own the file-link checker in NativeChatView, not each chat view

The provider now sits where NativeChatView picks the chat view, and derives
the file-link context from the tab id. The two chat views keep only a
one-line turn-end hook, since only they know whether a turn is running.
Same lifetime as before: inside the session-keyed owner for structured
chats, and per resolution for terminal-backed ones. No behaviour change;
it keeps NativeChatResolvedView under its line limit after main's find-in-chat.

* fix(native-chat): refuse network shares on SSH hosts too; allow only the workspace's WSL distro

- The "no network share outside the workspace" rule now applies to SSH
  targets as well: a Windows SSH host's relay would otherwise stat
  //server/share/... and open SMB with no click. Remote runtime paths stay
  exempt, since they are always inside the worktree.
- WSL paths are allowed only for the workspace's own distro (from the pane
  runtime or the worktree path, via the same helper the path mapping uses),
  after `..` is normalized, so `//wsl.localhost/../x` or another distro is
  refused.
- Drop the \\?\UNC\ chat test case: the real detector never produces it.

* refactor(terminal): keep file-link host path helpers out of the open flow

terminal-file-link-target imported its pure path helpers from
terminal-file-open-routing, which also opens files and so loads worktree
activation, launch and the agent catalog. Since NativeChatView now hosts the
chat file-link checker, that chain reached tests that render NativeChatView
with a minimal i18n mock (native-chat-view-file-drop.test.tsx failed in CI).

getTerminalFileContext, mapTerminalFilePath, terminalLinkWslDistro and
terminalPathWslDistro move unchanged to terminal-file-path-mapping.ts;
terminal-file-open-routing imports and re-exports them, so its callers and
their mocks are unchanged.
2026-10-08 23:24:25 -07:00
Brennan Benson 4f126bc01a Show "Pi isn't signed in" in native chat before the first send (#26743)
* Show 'Pi isn't signed in' before the first send

A Pi chat whose agent started with no model to use now says so in the
existing availability notice, and the next send replaces that agent so
a sign-in made since takes effect.

* Re-read the sign-in notice when the chat's agent stops; ignore an exited Pi

A Pi's start verdict ends with that Pi: the notice now re-reads when the
host starts or stops the chat's agent, and a Pi whose process already
exited reports nothing.

* Keep one sign-in line after a refused send; re-read on every agent start or stop

The notice steps aside while the newest send was refused for the same
reason, and the chat re-reads its verdict whenever its agent starts or
stops, dropping an answer read before.

* Step the notice aside only while the refused send's own line is on screen

Uses the host's send order and the chat's rendered delivery lines, so a
deleted returned card or a trimmed row brings the sign-in notice back.

* Keep the sign-in notice when the refused message is no longer loaded
2026-10-08 23:24:00 -07:00
Neil f9d0aa2f67 Refresh open Markdown links when workspace files change (#26599)
* Refresh open Markdown document links after file changes

* Use the stable Markdown refresh callback in the watcher effect
2026-10-08 23:23:14 -07:00
Brennan Benson 6235f9a641 fix(acp): show the agent's own reason when a prompt fails (#26666)
Agents often answer a failed session/prompt with a generic JSON-RPC message ("Internal error") and keep the real reason in error.data. Only OMP and Grok had hooks that read it, so OpenCode and future ACP agents showed the bare message.

The prompt error detail now reads, for every ACP agent: the agent's hook, else string data, else data.details, else the message. Other structured data is metadata and is ignored. OMP's details hook and Grok's string-data branch are now covered by that rule and removed.
2026-10-08 23:22:55 -07:00
Brennan Benson 496a1712f2 fix(acp): keep OMP replies that follow its reasoning (#26658) 2026-10-08 23:22:27 -07:00
Neil d2d2d39cca Refresh rich Markdown links when document metadata changes (#26595)
* Refresh rich Markdown links when document metadata changes

* Type Markdown link storage for metadata refresh tests
2026-10-08 23:02:59 -07:00
Neilandm4air b79862dcc7 Describe unverifiable managed servers without claiming they stopped (#26663)
Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 23:01:35 -07:00
Neil 5264a7d65f Retire canceled managed startup checks before reconnecting (#26645) 2026-10-08 22:48:41 -07:00
Neil 45a969f83f Wait for retained editor ownership before listing Markdown documents (#26590) 2026-10-08 22:45:11 -07:00
Jinjing f3c0390d67 Fix Compact usage notice focus and older-host compatibility (#26747)
* Preserve usage-menu focus and polish the Compact notice

* Restart usage notice delay when selected notice changes
2026-10-08 22:38:31 -07:00
Neilandm4air 4e232f96c7 Preserve execution host identity throughout folder sidebar rows (#26634)
Folder rows used the bare folder ID for active state, DOM IDs, virtual keys
and activation, so same-ID folders on two hosts collided. Use the existing
host-qualified worktree identity, matching git worktree rows.

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 22:34:43 -07:00
Neilandm4air 6a15cd8972 Preserve editor file identity during SSH host conversion (#26593)
* Preserve editor file identity during SSH host conversion

* Keep a dirty in-session editor tab on its file record during SSH conversion

A file opened over the relay in the current session carries route provenance,
so the no-host-evidence check repointed its tab to a fresh clean record and
hid the unsaved draft. Keep any retained record with no runtime owner instead.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 22:18:51 -07:00
Neilandm4air b71e5382f6 Explain why stopping the selected Active Server is refused (#26584)
Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 21:47:10 -07:00
Neilandm4air 118de208a5 Keep open Remote Settings subscribed to the saved-server catalog (#26581)
Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 21:47:01 -07:00
Neil b9a7830036 Keep new browser tabs on SSH routing after managed conversion (#26570)
* Keep local browser routing on the deployment SSH host after conversion

* Seed published SSH connection state in browser lifecycle fixture
2026-10-08 21:30:46 -07:00
Neilandm4air 8167ddaa7f Distinguish remote browser failures from server connection failures (#26573)
* Distinguish remote browser service failures from server outages

* Use the shared browser_unavailable code in the stream failure classifier

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 21:07:48 -07:00
Brennan Benson 8d3c922176 refactor(tabs): reuse persistAgentLaunchTabOrder for copied tab-order logic (#26704)
Sleeping-session resume, AI vault resume and the plain quick-command
terminal each carried a line-for-line copy of persistAgentLaunchTabOrder.
Call the helper instead. No behavior change.
2026-10-08 21:04:21 -07:00
Brennan Benson 13c9f1fcc8 fix(floating-workspace): keep file links in their owning panel (#26655) 2026-10-08 21:03:03 -07:00
Brennan Benson 56cdd678fc fix(native-chat): read a queued message in full (#26004)
* fix(native-chat): read a queued card's whole text, and keep Edit from hiding it behind a prompt

A queued card showed one clipped line, so a long message (often another
agent's, never typed by the reader) could not be read before Steer or
Delete. A clipped card now opens in place to its whole text; the phone's
two-line card opens on tap.

Edit moved the card's text into the composer and deleted the card even
while a question or approval card stood in the composer's slot, so the
text vanished from the page. Edit now waits, saying why, until the
prompt is answered; the pane and the queue read one check for whether a
prompt holds the composer's slot.

* fix(native-chat): keep the full-text hover title on a folded queued card

* fix(native-chat): phone card opens only when it clips; test the composer-slot check

The phone card measured nothing and made every card a button; it now lays
the text out unseen at its width and offers Show more only past two lines.
The Edit reason is no longer dimmed twice, and the shared composer-slot
check and the desktop toggle's keyboard reach have their own tests.

* fix(mobile): the unseen measuring copy of a queued card takes no touches

* fix(native-chat): open a queued card's full text below its row, at the card's width

In a narrow chat the opened text sat beside the card's actions and wrapped
a few characters per line. It now opens under the row, indented to the
text, the way the transcript's awaiting-input row opens its question.

* fix(native-chat): the queued card's toggle names the opened text only while it exists

* refactor(native-chat): the queue reads pending prompts itself, keeping the session hook under its line cap

* refactor(native-chat): keep this PR to reading a queued message in full; Edit moves to in-place editing

* test(native-chat): queue list rig passes the pending-prompt flag main's controller takes
2026-10-08 20:54:59 -07:00
Neil 1cda323b6a Report browser placement support from the installed provider (#26559)
* Report browser placement capabilities from the installed provider

* Run managed browser capability checks in the template-building CI lane
2026-10-08 20:51:50 -07:00
Neilandm4air bdf0d66d7c Provide Orca CLI on managed Linux and macOS servers (#26539)
* fix(orcad): provide execution host CLI in Unix managed terminals

* fix(orcad): keep the server starting when the CLI launcher cannot be written

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-08 20:50:37 -07:00
Jinjing 04d2ccbfad Default status-bar usage to Compact and explain the change once (#26726)
* Default status bar usage to Compact

* Explain Compact usage to affected existing users once
2026-10-08 20:32:47 -07:00
Neil da6d632a91 [CI] Revert library patches introduced by test optimization (#26727) 2026-10-08 20:29:42 -07:00
Neil 978c32bfe6 fix(remote): group migrated folders under their execution host (#26535) 2026-10-08 20:22:01 -07:00
Brennan Benson ebb192e3e5 Native chat: Cmd/Ctrl+F finds in the chat (#26517)
* Native chat: Cmd/Ctrl+F opens find in window

Mod+F inside a focused native chat opens a find bar at the chat's top-right
corner. The bar is a separate sandboxed view stacked over the main window, so
its own input is never a match; main runs the window's find-in-page and relays
the match count back. Enter/Shift+Enter step, Escape closes and clears.

Also stops the terminal search bar from opening over a chat that covers a
terminal pane.

* Native chat: Cmd/Ctrl+F finds inside the chat transcript

Replaces the window-level find panel with a find bar inside the chat.
The panel searched the whole window, pasted into the composer, outlived
its chat, and let Escape interrupt the agent.

- Searches only the transcript text the reader can see and paints matches
  with CSS highlights, reusing the markdown preview's search, now shared
  as lib/dom-text-search-highlights.ts.
- Re-searches as the transcript streams or scrolls, keeping the current
  match; a step leaves "follow latest" like a reader scroll.
- Escape closes the bar first and returns focus; paste and editing keys
  stay in the bar's input.
- Terminal guard yields any chat.find chord inside a chat cover; a PDF
  no longer takes Mod+F from another surface.

* Native chat find: round-2 fixes

- Escape: the chat root's React capture handler closes the bar before the
  composer's own capture handler can interrupt the turn.
- One visibility rule for picking and revealing a match: typing no longer
  scrolls to a match that is already on screen, and the bar's real rect,
  not a full-width band, decides what it covers.
- Reveal scrolls nested scroll boxes (code lines, tool output, thinking);
  text cut off by a box that cannot scroll is not counted.
- PDF find opens from its own tab and the file explorer again, but not
  from another group, a chat, or a text field.
- Prompt cards no longer take focus from the find input; clicks on the
  bar keep typing in it; buttons keep their own Enter.
- A match whose row scrolled away restarts from the first visible match.
- Streamed text growth re-searches every 120 ms instead of every frame,
  and searches reuse their Range objects.
- Hover-only row chrome is marked and skipped instead of read by opacity.
- Chat find stays off in the web client, where the browser's find keeps
  Mod+F.
- The text matcher moves to lib/text-match-ranges.ts with neutral names.

* Native chat find: round-3 fixes

- Text that held a match re-searches before the next paint: React
  rewrites a growing text node whole, collapsing its ranges, so the
  streaming paragraph's highlights no longer blink. Other text growth
  keeps the 120 ms re-search.
- A disclosure's height animation ending re-searches, so an output
  opened while find is open is counted.
- A prompt card that arrived while the find bar held focus gets it when
  find closes.
- A reveal that cannot scroll no longer stops following the latest.
- PDF find follows the panel's chord owner (its tab is the active tab
  of the focused group, the rule the browser pane uses), so it no longer
  takes Mod+F from a chat, terminal or browser in another split, and it
  opens again after clicking its own editor header.

* Native chat find: PDF find answers only its own window surface

The floating workspace panel keeps its own focused group, so a PDF that
owns its panel's chords no longer takes Mod+F from a chat in the other
surface (main window vs floating panel), matching how the browser pane
scopes a floating workspace's chords.
2026-10-08 19:51:44 -07:00
Brennan Benson 820277c207 Show pre-upgrade Experimental Chat UI users a one-time native chat upgrade tip (#26710)
* feat(native-chat): one-time upgrade tip for pre-upgrade Experimental Chat UI users

Show the new native chat upgrade tip through the normal startup feature-tip
flow, only to profiles whose saved Experimental Chat UI setting was on before
this release. Main records that audience once, from the profile as saved by the
previous build, and never re-derives it from the live setting, so later
opt-ins, new installs and the future graduation stay excluded.

* fix(native-chat): keep the upgrade tip readable and dismissed

Focus Got it without scrolling and tighten the ja/es/fr copy so the title is
visible on open. Show the tip exactly like other startup tips (no resume-dialog
wait), keep the illustration's upward menu unclipped, and merge seen tip ids
on save so a stale client cannot bring a dismissed tip back.

* fix(native-chat): say "between chat and CLI" in French and pin the audience basis in tests
2026-10-08 19:30:43 -07:00
Brennan Benson d191386809 Offer Resume in New CLI / Native Chat from the tab right-click menu (#26705)
* Offer Resume in New CLI / Native Chat from the tab menu

Right-clicking a native chat tab now offers "Resume in New CLI", and
right-clicking a terminal tab running Claude or Codex offers "Resume in
New Native Chat": the same items, gating and handlers the Session History
row menu uses.

The tab finds its Session History row through the existing mappings (the
chat tab's session id against the row's structuredSession, and a terminal
tab's agent-reported provider session, the mapping tab titles use, against
the row's agent and session id), read from the Session History list scoped
to the tab's workspace and host. Both surfaces now share one gate,
resolveAiVaultSessionSurfaceSwitchTargets, one menu-item component, and
call handleResumeInNewCli / handleResumeInNewChat from
useAiVaultSessionLaunchActions.

* Share the Session History list request with the tab menu's chat/CLI move

The tab menu looked its history row up with its own list request, so it
never shared the panel's cached list (and evicted it), forced a full
rescan on every miss outside the panel's rescan budget, and inserted the
item above Pin/Close seconds after the menu opened.

- One list request (scope paths, depth, host, Antigravity flag) and one
  renderer-cache read/write, used by the panel and the tab lookup; the
  tab builds the panel's own request for its workspace.
- A warm menu answers from the panel's cached list at first paint with no
  IPC; a cold one sends the panel's non-forced request and keeps its
  result in the panel's cache.
- A forced rescan on a miss now takes the panel's shared forced-rescan
  budget; no other force.
- No lookup on hosts where neither move can ever be offered (non-local).
- The item moves to the end of the menu, so a late insert shifts nothing.
- The panel and the tab compose the row's resume inputs through one
  function; parity is pinned by unmocked tests.

* Revalidate the tab menu's chat/CLI move and allow it for remote-server chats

- The cached first paint is always replaced by the fresh list answer, so a
  conversation a chat has since taken no longer offers Resume in New
  Native Chat from a stale cached row.
- Native chat tabs in a remote Orca server workspace look their row up on
  that server (it projects chat ownership), so Resume in New CLI shows
  there as it does on the row. CLI tabs stay local-only; SSH stays skipped.
- A menu that closed between the two list calls no longer starts the
  forced rescan or spends the shared budget; forced rescans stay local.

* Keep the tab menu's history lookup from writing the panel's result cache

A tab lookup wrote its list into the Session History panel's renderer
cache, so a panel opened afterwards could paint that pre-launch list
without asking the host and show a chat-adopted row under its old title.
The tab now only reads that cache for its first paint; the host's cached
list is already shared through the identical request.

* Offer the tab menu's chat/CLI move only from a fresh history answer

The panel's renderer cache never carries current chat ownership (the host
projects it per reply), so painting the menu item from it first flashed
"Resume in New Native Chat" on a terminal tab whose conversation a chat
had taken, and missed the move on that chat's own tab. The item now
appears only once the fresh (non-forced) list answer lands.

* Put the tab menu's chat/CLI move above Pin Tab and hide Switch to chat view
2026-10-08 19:18:08 -07:00
Brennan Benson 37833ce9a0 feat(native-chat): add a chat-owned command receipt store (#26653)
* feat(native-chat): add a chat-owned command receipt store

Adds the agent_session_command_receipts table and an insert-if-absent
receipt write that runs inside a command's own journal transaction. A
receipt records the command's identity, canonical hash, status and a
pointer to the row holding its result; it dies with its chat record.
Nothing uses it yet: the existing operation ledger stays authoritative.

* fix(native-chat): key command receipts like today's ledger ids

Rows are keyed by caller and operation id; a send looks across callers and
other methods look up only their caller's row, matching the existing ledger.
Bad rows and newer table shapes read as unreadable instead of throwing.

* fix(native-chat): order receipt lookups by insertion and key by operation id

Global lookups now take rows in insertion order, so a read and an insert
agree on which receipt answers an id regardless of the host clock. The
primary key leads with the operation id, so its own index serves both
lookups.
2026-10-08 18:47:17 -07:00
Jinwoo Hong 7f0e067256 test(e2e): layout oracle scenarios with window, headless serve and SSH (#26674)
* test(terminal): check the runtime's workspace layout against structural rules

A pure rules check over the runtime's session partitions: a terminal in two
panes, a pane in two tabs, a tab outside exactly one group, tab rows and tab
bar disagreeing, two tab orders, and ids changing for the same pane, tab or
group across an update. Wired into the seeded layout model test after every
step, plus late-spawn cases (one known on main, kept as an expected failure).

* test(e2e): layout oracle scenarios with window, headless serve and SSH

Drives layout journeys through window gestures, CLI and paired-client runtime
commands, and after every step checks the runtime's layout against the
structural rules, the window's DOM, the paired-client and CLI views, the
expected end layout, restarts (relaunch, cold daemon, in-app daemon restart)
and per-pane terminal markers. Findings main still has are listed with their
cause; anything else fails. Includes headless orcad/Electron serve scenarios
for the serve issues and a Docker SSH scenario.

* test(terminal): check layout rules on every write and race client commands with the window

The layout model now checks the structural rules on every in-memory
workspace-session write, not only at each step's end, naming the writer
of any breach. Three documented two-writer transients (main mints a tab
row before the window writes its tab bar) are allow-listed by rule, op
and writer; they must still heal by the step's end.

New model ops race a stale window save against a paired client's tab
close, a host-created split, and main's PTY-exit retirement. A new file
runs main's updateMobileSessionPaneLayout (old phone pane trees) against
the real Store; the case with no topology revision is an it.fails: main
drops a live pane and its binding there.

* test(e2e): oracle expected outcomes, transient sampling, remount counts, more scenarios, latency

Every step checks the expected panes, which panes went away and that the rest
kept their terminals; a 100 ms sampler runs the rules between steps; xterm
creations are counted per pane and an unexpected recreation fails. Adds host
navigation, window reload (graph republication), quit right after a change
(quit-time save), an old client's stale pane tree, and a latency measurement
(command to drawn update, idle and under an output flood; no pass/fail).

* docs(e2e): describe the oracle's added checks and latency measurement

* test(e2e): #12723 SSH folder scenario, CI lane for the SSH oracle spec, short socket dir

Adds an SSH folder-workspace (no repo) scenario that checks the layout lives in
one partition across relaunch; registers the SSH oracle spec in the Docker SSH
lane's selection lists; headless hosts put long-TMPDIR profiles under ~/.orca-lo
instead of /tmp.

* ci(e2e): run the headless layout oracle in the job that builds orcad; Linux relaunch findings

The headless oracle spec needs out/orcad, which only the orca serve mode-switch
job builds, so it runs there (and fails rather than skips in CI if orcad is
missing). Records what the first Linux CI run found on main: after a relaunch
main can hold tab rows with no tab bar past the settle wait, and Electron serve
on Linux also lists a renamed terminal's title as null after a restart.

* test(e2e): join partition lists in the SSH folder scenario's log lines

* test(e2e): retry the latency spec's reads through a brief terminal-ownership gap

Linux CI saw terminal.list answer terminal_surface_ownership_unavailable while
the window re-published its terminals; reads retry for up to 10 s, commands do not.
2026-10-08 21:18:21 -04:00
Jinwoo Hong d010c83943 test(terminal): check the runtime's workspace layout against structural rules (#26673)
* test(terminal): check the runtime's workspace layout against structural rules

A pure rules check over the runtime's session partitions: a terminal in two
panes, a pane in two tabs, a tab outside exactly one group, tab rows and tab
bar disagreeing, two tab orders, and ids changing for the same pane, tab or
group across an update. Wired into the seeded layout model test after every
step, plus late-spawn cases (one known on main, kept as an expected failure).

* test(terminal): check layout rules on every write and race client commands with the window

The layout model now checks the structural rules on every in-memory
workspace-session write, not only at each step's end, naming the writer
of any breach. Three documented two-writer transients (main mints a tab
row before the window writes its tab bar) are allow-listed by rule, op
and writer; they must still heal by the step's end.

New model ops race a stale window save against a paired client's tab
close, a host-created split, and main's PTY-exit retirement. A new file
runs main's updateMobileSessionPaneLayout (old phone pane trees) against
the real Store; the case with no topology revision is an it.fails: main
drops a live pane and its binding there.
2026-10-08 21:17:19 -04:00
Jinjing 4ad8690df2 Resolve native chat workspaces from catalog snapshots (#26428)
* Use catalog snapshots for native chat workspace reads

* Resolve native chat workspace directories from the catalog snapshot

- Stop falling through to folder-path parsing once the catalog is loaded. The fallthrough let a folder workspace on another host resolve to a local path.
- Look up model discovery settings by the worktree's runtime owner instead of the agent tab's, so a session's model list matches the worktree it runs in.

* commit

* Use worktree owner settings for native chat model discovery

* Resolve native chat files from catalog snapshots
2026-10-08 17:59:04 -07:00
Neil 0e8e4e78fb Reduce repeated test work and skip unrelated server matrices (#26711)
* Reduce repeated imports in SourceControl and socket tests

* Retire test-only scans and skip unrelated server test matrices
2026-10-08 17:54:40 -07:00
Jinwoo Hong ad7af63b20 fix(relay): throttle the connection-reservations autovacuum so a run stops evicting the shared database cache (#26370) 2026-10-08 20:35:55 -04:00
Jinwoo Hong dec18a8cc9 fix(runtime): settle DSH tui-idle on its hook-store done (#26481)
DSH's managed hook posts to the hook server and never emits OSC 9999, so the
dsh-only first-party done lane never fired and tui-idle waits ran to timeout.
Give DSH turn-end hook authority through an agent-state-rules file, mark its
SessionStart as a session boundary, and drop the dead dsh special case.
2026-10-08 20:11:38 -04:00
Neil 59b9bdeb90 Reduce repeated test work and fix Windows cleanup and IME confirmation (#26608)
* ci: share test transforms and remove six redundant checks

* test: remove obsolete project copies and two build string checks

* test: use the injected clock for exact launch readiness budgets

* fix: retain IME confirmation and retire disconnected Windows PTYs

* ci: include relay installer in existing Windows boundaries

* perf: import the canonical SSH manager for filesystem operations

* test: remove 42 source-spelling checks

* test: advance deadlines after real entry and await actual PTY exit

* Preserve native Windows exit acknowledgments and skip daemon-only smoke triggers
2026-10-08 16:08:49 -07:00
Brennan Benson bb44f74d00 Keep native chat /clear in the same conversation (#26579)
* Keep clear in the same chat and reset its provider context

* Derive clear pauses only from journal membership and cover older rewind clients

* Point queued command rewind test at the structured hook

* Group queue consume errors and rewind replay assertions
2026-10-08 16:00:29 -07:00
Kelvin AmoabaandBrennan Benson 3c075883ed feat(native-chat): make native chat replies flow in and the transcript glide when following (#26238)
* feat(native-chat): pace and fade streamed reply text

Snapshots land a clause at a time, 50-700 ms apart. Drawing behind them
at an eased speed is what makes a reply read as flowing.

* feat(native-chat): glide the transcript when following and jumping to latest

The offset is still pinned at once; only what the pin moved is eased, so
nothing races the virtualizer or a reply that keeps growing.

* chore: list remend with the other bundled renderer packages

dependencies is for packages the main process loads at runtime.

* Bound streamed reply reveal and preserve chat interactions

* Smooth overlapping chunks without postponing reveal deadlines

* Fix first-reply following and pin settled layout changes

* Pin concurrent media layout changes without a follow glide

* Keep native chat layout stable when replies complete

* Model delayed browser scroll events in navigation tests

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-08 15:38:49 -07:00
OrcaWinandOrcaWin 4d1a3dd6ac Detect installed GitHub CLI behind hung launchers (#25183)
* Recover installed forge CLIs after launcher timeouts

* Preserve healthy CLI timeouts and add native platform checks

* Resolve Windows tree termination outside PATH

* Use native absolute paths in the relative PATH fixture

* Expect the absolute System32 taskkill in tree-kill tests

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-08 15:37:25 -07:00
Yuang Peng 81fd59dab3 fix: keep workspace search filter button on one line (#26580) 2026-10-08 15:09:15 -07:00
Brennan Benson 58a58f4e4e Show OMP sign-in guidance when OMP reports no model selected (#26649)
* Recognize native chat sign-in failures across structured agents

* Fix authentication failures and chat sign-in guidance

* Preserve sign-in diagnostics and command retry context

* fix(native-chat): keep visible sign-in guidance and localize startup rows

* fix(native-chat): separate auth diagnostics from retry guidance

* test(native-chat): align startup guidance expectations

* fix(native-chat): treat OMP's signed-out 'No model selected' as not signed in

* fix(native-chat): start a new agent for the send after it reports not signed in

* fix(native-chat): scope the signed-out check by fence and read without a snapshot

* fix(native-chat): keep a signed-out agent while it owes work, and read only its own rows

* fix(native-chat): keep a signed-out agent that may owe a wake-up turn, and skip the check during a Stop
2026-10-08 14:54:30 -07:00