Commit Graph
16002 Commits
Author SHA1 Message Date
Jinjing 70e8ef7f3b fix(i18n): translate recent desktop and mobile copy (#36489) 2026-10-30 16:16:54 -07:00
Victor HerreraandNeil 711772b740 fix(azure-devops): negotiate API version down for older Azure DevOps Server (#36424)
Self-hosted Azure DevOps Server instances capped below REST 7.x reject
every api-version=7.1 call with VssVersionOutOfRangeException, so PR
detection, checks, review state and PR creation silently failed.

Step down a fixed 7.1 -> 6.1 -> 5.1 ladder (plus the existing -preview
retry) on version rejections, cache the negotiated version per origin,
and bound retries. PR creation shares the same negotiation.

Fixes #36423

Co-authored-by: Neil <neil@stably.ai>
2026-10-30 16:16:31 -07:00
David CabreraandNeil e78cbfba9b fix(rate-limits): map Cursor pools for team-limited accounts (#36394)
Team-limited (enterprise) Cursor accounts report the member's included
allowance as `individualUsage.overall` instead of an enabled `plan` pool,
so the monthly meter showed nothing. Fall back to `overall` when `plan` is
absent or disabled. Team-wide `teamUsage.onDemand` stays unmapped because
it is not this member's allowance.

Co-authored-by: Neil <neil@stably.ai>
2026-10-30 16:16:23 -07:00
QiuzandNeil 12df63b4ee fix(agents): bundle the CodeBuddy icon instead of the Google favicon fallback (#36265)
CodeBuddy was the only catalog agent with neither an iconUrl nor a bundled
favicon, so AgentIcon fell through to Google's favicon service, which returns
a generic globe for codebuddy.ai. Map it to the already-shipped
src/shared/agent-icons/codebuddy.png (also used by mobile).

Fixes #36259

Co-authored-by: Neil <neil@stably.ai>
2026-10-30 16:16:15 -07:00
Neil 0826abd48e plugins: add Try it samples for the new official syntax plugins (#36486) 2026-10-30 16:10:09 -07:00
Brennan Benson c8903ea467 Fail readiness promptly when the terminal exits (#36457)
* fix(terminal): settle idle waits after a recorded exit

* test(terminal): keep CLI wait integration in runtime boundary

* fix(terminal): preserve idle waits across uncertain disconnects

* fix(terminal): observe process lifetime during composer readiness

* test(terminal): bound pending composer exit work

* test: wait for SSH idle admission without wall clock

* test: use checked federation runtime replies
2026-10-30 16:05:33 -07:00
Kelvin Amoaba a545b8926c fix(ai-vault): clear the Session History search when you switch workspace (#36472)
* fix(ai-vault): clear the Session History search when its workspace changes

The query was panel state with no tie to the workspace or project it
searched, so the sidebar panel kept filtering the next workspace with it
and showed no matches. Clear it when the Workspace or Project scope's
subject changes; All and user-picked scope changes keep it.

* refactor(ai-vault): pick the query subject with a scope lookup
2026-10-30 23:05:16 +00:00
Brennan Benson dfa617cc67 Show each chat’s account in Session History details (#35392)
* Show recorded session accounts in History details

* Fix session account lint failures and extract presentation

* Isolate session account cards from unrelated settings updates

* Keep session account labels tied to available current roster evidence

* Add English session account labels

* Share recorded session account observation and isolate optional stream evidence

* Verify healthy account and usage consumers during optional registry loss

* Bound session account comparisons and acquisitions

* Use nonmutating reversal in account peer tests

* Type the account subscription replay fixture without assertions

* Repair account directory types and integration fixture imports

* Give account details fixture a portable return type

* fix: release account streams on transport abort

* test: name desktop account stream IPC event type

* chore: temporarily expose e2e compiler diagnostics

* test: type account stream unsubscribe as callable
2026-10-30 15:52:32 -07:00
Brennan Benson d879474a03 docs(orchestration): explain recovery after repeated worker startup failures (#36335)
* docs(orchestration): explain user-directed task recovery

* docs(orchestration): correct recovery placement and terminal cleanup
2026-10-30 15:51:30 -07:00
Kelvin AmoabaandZheNing Hu add1778e4a fix(terminal): link a URL wrapped inside a table cell on every row (#36482)
* fix(terminal): link a URL wrapped inside a table cell

A markdown table rendered by an agent TUI wraps a long URL onto extra rows
of its own cell, leaving the sibling cells blank. Two gates in the
hard-wrapped HTTP builder rejected that layout, so the link stayed cut at
the first row and opened a truncated URL:

- a changed prefix under a second left frame was always read as an
  adjacent table cell, and
- only the padding up to the URL's own right frame is cell-local, so a
  populated sibling cell to the right killed the row.

Treat a blank gutter between the frames as the same cell continuing, and
only require the URL's own cell padding to be blank. A blank-gutter
continuation is also enough evidence to join a two-row URL, which the
previous three-row minimum ruled out.

* fix(terminal): join a two-row URL in the first table column

A URL that starts in the left table column continues through the
unchanged-prefix branch, so no blank sibling cell marks its continuation
row and the row-count guard dropped the second row.

Count the blank cells right of the URL as continuation evidence for that
layout too, and keep single-column tables on the three-row minimum so a
complete URL that happens to end at the cell border is not glued onto the
next table row.

* fix(terminal): join a table-cell URL only when its row's other cells are blank

A wrapped table cell leaves every other cell on its continuation rows blank,
so that one rule now decides a two-row join in any column. This replaces the
adjacent-cell gutter count and the first-column 0.95 border threshold. Checking
only the adjacent cell glued a next table row like `│ 2 │     │ notes │` onto
the URL above it.

* fix(terminal): end a table-cell URL at a row whose right-hand cells are filled

Below the URL's first row, a filled cell to its right starts a new table row. Text beside an overlay with no table frame is not a sibling cell either.

* fix(terminal): end a table-cell URL where the cells left of it change

Every continuation row of a wrapped cell shows the same cells to its left, so a row that fills them again (a repeated label) starts a new table row.

* fix(terminal): apply table-cell rules only to rows that keep the table frame

An overlay's gutter can show a frame beside its first row only; those rows vary by design and keep the overlay join.

* fix(terminal): count cells right of a URL as a table only when they close with a frame

A split pane or screen text beside an overlay ends without a closing frame and is not a sibling cell.

---------

Co-authored-by: ZheNing Hu <adlternative@gmail.com>
2026-10-30 22:47:25 +00:00
Neil c8e3809812 fix(status-bar): toggle Plugins settings closed on a second click (#36479)
The Plugins status bar button always navigated to Settings > Plugins, so a
second click left the page open. Route the click through a new 'toggle'
settings navigation intent: Settings, which owns the active pane, closes
itself (via the unsaved-changes guard) when that pane is already showing and
otherwise navigates as before. The Mod+Shift+X shortcut stays open-only.

Fixes #36415
2026-10-30 15:45:05 -07:00
Kelvin Amoaba 77f76af037 fix(native-chat): stop a finished turn announcing "responding" (STA-10926) (#36474) 2026-10-30 22:34:51 +00:00
Brennan Benson 12edee3ac6 Choose default models and effort for agents (#36210)
* Add host-owned model and effort defaults to agent settings

* Unify terminal defaults and raw argument precedence

* Keep agent model defaults typed through creation

* Preserve quick-create prompt through preparation

* fix: complete execution-host preference boundary and CI contracts

* Preserve raw options until a replacement is emitted

* Complete launch choice ownership and consumer contracts

* Align launch contracts with compiler boundaries and consolidate proof

* Name exported fixture mocks and verify ordered chip removal

* Preserve typed choices across compound legacy publication edits

* Preserve non-emitted composed launch choices through legacy edits

* Preserve rollback omissions and settle agent launches before success

* Carry terminal draft ownership through launch completion

* Keep inline draft delivery independent of terminal projection

* test: consolidate launch ownership contracts

* test: check web launch fixture array types

* test: align launch fixtures and conformity records

* test: import the shell-ready marker from its declaring module

* test: give caller routing the web host tab's completion contract
2026-10-30 15:17:52 -07:00
Neil d42130b433 fix(plugins): stop painting a disabled plugin's terminal theme (#36471)
* fix(plugins): stop painting a disabled plugin's terminal theme

* fix(plugins): tell the clicking window when a plugin is disabled or removed

* test: merge duplicate import
2026-10-30 15:14:25 -07:00
Brennan BensonandNeil d307d114a0 A dropped screenshot is written once, straight into the chat's attachment store (#31779)
* fix(native-chat): a dropped screenshot is written once, straight into the chat's store

A screenshot dragged from its macOS thumbnail into a local chat was read into
memory, or spilled to a private copy in the OS temp folder for a batch over
50 MiB, then moved into the chat's attachment store; when the temp folder and
the store were on different disks that move was a second full copy.

The page now reads the dropped File's bytes, the way the common pattern does,
and the store writes them once into a hidden part file in its own folder and
renames it into place. Main still decides which dropped paths are such files
and leaves them unread; a file over the store's 50 MiB limit keeps its checked
private copy, and a store that is unavailable, refused or failing gets the
received bytes as a private copy instead. The in-memory tier, the spill and
the cross-disk import are gone.

Tracked in STA-11413.

* test(native-chat): type the dropped-bytes mock instead of asserting

* fix(native-chat): own dropped files through completion and drain

* fix: keep failed drop cleanup outside payload drain

* fix: include drop integration dependencies in web typecheck

* test: run main file and plugin integration contracts in Node

* fix(i18n): preserve runtime entries after removing untracked settings (#31852)

* fix(native-chat): write dropped screenshots straight into the chat store

A local chat's drag-temp files stay open after their checks and are
streamed once into a pending file in the chat's attachment folder, then
renamed into place. This removes the in-memory tier, the temp-folder
spill and the cross-disk copy that made large cross-disk drops slower.
A file over the attachment limit, or a drop with no store, keeps the
private temp copy made from the same open handle. A file rewritten after
the drop is refused as changed.

* fix(native-chat): keep checked drop source open for fallback

* test(native-chat): make dropped source rewrite deterministic

* Use bounded reads for small checked drop files

* Register approved checked drop copier line exception

* Keep checked drop source copying in a focused module

* Finish buffered drop writes after proven bytes persist

* Capture budgeted drop bytes before waiting for the chat store

* Assert the capture test store getter resolves successfully

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-30 15:09:11 -07:00
Kelvin Amoaba 17cace4f22 fix(mobile): lead workspace-list agent rows with the conversation name (#36464)
* fix(mobile): lead workspace-list agent rows with the conversation name

* fix(mobile): name a same-tab child once its parent row is gone

* refactor(runtime): share the structured chat tab id parser

* test(runtime): build the row-name summary without a cast

* perf(runtime): read each worktree's session once per worktree.ps pass
2026-10-30 22:07:24 +00:00
Neil 8c777ea465 plugins: tell once when an automatic update waits for your review (#36462)
* plugins: tell once when an automatic update waits for review

When the auto-updater holds back an update because it asks for more access
or moved repository, show one toast per plugin version (grouped when several
wait). Review opens the existing per-plugin update review or the Updates list;
it never installs or approves. Told versions persist across restarts, kill-listed
plugins are skipped, and the copy is protected from language packs.

* test(plugins): wait on the update pass instead of sleeping in the review toast e2e
2026-10-30 15:01:54 -07:00
OrcaWinandOrcaWin e6a8959f4b test(windows): give the credential fixture's cold Python start 30s (#36465)
* test(windows): give the credential fixture's cold Python start 30s

* test(windows): explain the credential test's timeout

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 14:59:48 -07:00
Neil 34f508fb11 fix(plugins): let an enabled plugin syntax beat Orca's guessed language (#36468)
A plugin syntax only applied to files Orca showed as plain text, so plugins
could not color MATLAB .m (Objective-C), OCaml .ml/.mli (F#), Julia .jl,
JSP .jsp/.jspf (HTML stopgap), or Haskell .hs and Erlang .erl/.hrl, which
Orca maps to ids it never registers a grammar for.

Now an enabled plugin syntax wins for any file name or extension it
declares, except files Orca opens as TypeScript, JavaScript, JSON, CSS,
SCSS, Less, HTML or Markdown (their language drives completions,
diagnostics or Markdown features). JSP stays overridable. Ties between
plugins go to the lower syntax id instead of load order. The editor and
both diff views share the hook, so they agree.
2026-10-30 14:57:23 -07:00
Neil e8d9a58b05 plugins: show a catalog entry's own publisher, not the catalog owner (#36466) 2026-10-30 14:51:01 -07:00
Neil 6dfddc1a20 fix(sidebar): stop clipping the child workspaces chip in classic cards (#36460)
* fix(sidebar): restore horizontal padding on the child workspaces chip

* fix(sidebar): stop clipping the child workspaces chip in classic cards
2026-10-30 14:48:51 -07:00
BingZ 3207b8a346 fix(persistence): keep profile backup temp names within eCryptfs's 143-byte limit (#33984)
The profile-state backup temporary name embedded the full 64-char SHA-256
owner scope, producing 191-195 byte names that fail with ENAMETOOLONG on
eCryptfs homes (namemax=143). Use an 8-char base64url prefix (48 bits) of the
digest instead; orphan cleanup still reclaims files written with the legacy
full-hex scope.

Fixes #33936
2026-10-30 14:47:46 -07:00
OrcaWinandOrcaWin 24bf181d56 test: remove 17 low-value suites from audit batch 848 (#36461)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 14:35:29 -07:00
Kelvin Amoaba 99cb2cbbf3 fix(source-control): say when the review lookup failed instead of "not ready" (#36458)
A ready branch whose MR/PR lookup failed was told it wasn't ready, hiding the real problem.

Refs #35632
2026-10-30 21:25:00 +00:00
Jinwoo Hong d9652f2b19 Let a coordinator give follow-up work to a finished chat worker (#36445)
Orchestration-created chat workers are now classified as chats by their Orca session ID, so worker-start --terminal reuses a finished chat worker the same way it reuses a terminal worker. Dispatch admission and the coordinator census share one new-work rule (kept open, release in progress, held by a finished Dispatch, actively assigned pane), and the structured session binding is keyed by the worker's root session.
2026-10-30 17:20:14 -04:00
Kelvin Amoaba 43f42a8cc6 fix(native-chat): stop a cancelled image leaving an extra space in a hidden chat's message (#36448)
* fix(native-chat): drop a cancelled image's space from a hidden chat's draft

* test(native-chat): name the hidden image cancel test for what it checks

* refactor(native-chat): read the previous node instead of a flag when dropping a chip's space

* test(native-chat): expect a handed-back edit to drop the kept chip's space
2026-10-30 21:17:47 +00:00
Kelvin Amoaba 0c1275222c fix(editor): reopen Markdown Find on Mod+F right after closing it (#36456)
Close focused the editor through Tiptap's focus command, which waits a frame. The Find input unmounts first, so a fast Mod+F hit the body and the editor-scoped shortcut ignored it; hidden Linux E2E windows never ran that frame at all. Focus the ProseMirror view synchronously before Find unmounts.
2026-10-30 21:15:38 +00:00
Kelvin Amoaba 162ea19851 fix(browser): stop paired desktops serving mirrored browser tabs back to their host (#36447)
When two desktops pair both ways, B mirrored A's browser tab and republished
it in its session inventory under A's workspace and page ids. A applied B's
copy onto its own workspace, so A's local page became B-hosted and showed a
dead Remote browser pane (selector_not_found from B).

Browser rows whose page runs on a paired server now carry
hostRuntimeEnvironmentId, as editor rows do since #33752, so B serves them to
its phone but not to other runtimes.

Fixes #36386
2026-10-30 21:14:06 +00:00
Neil 99fdbcf2d9 refactor(jira): colocate row interaction tests (#36362) 2026-10-30 14:06:46 -07:00
OrcaWinandOrcaWin 07142b50a2 test: remove 29 low-value suites from audit batch 847 (#36446)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 14:04:36 -07:00
Brennan Benson d0bdbfb314 fix(updater): keep status current after reopening the window (#34104)
* fix(updater): stop sending update status to a closed window

* test(updater): cover retained status and queued failure delivery

* test(updater): prune duplicate notification and dialog cases

* test(window): type runtime reload lifecycle mocks

* test(window): infer API-typed runtime fixture

* Resolve updater notifications and dialogs through the current main window
2026-10-30 14:03:03 -07:00
Brennan Benson 528757a980 fix(agent-status): settle killed Claude background helpers (#35930)
* fix(agent-status): settle killed Claude helpers from host transcripts

* fix(agent-status): reconcile interrupted and recovered helper generations

* fix(agent-status): retain admitted helper observation across startup

* test(agent-status): exercise first admitted child fanout failure

* test(agent-status): consolidate helper lifecycle contracts

* test(agent-status): document recovery timing and fix scheduler clock

* test(agent-status): type recovery owner inspections

* test(agent-status): consolidate listener state imports

* test(agent-status): use declared recovery owner members

* test(agent-status): correct typed consumer and recovery contracts

* fix(agent-status): await complete helper transcript frames

* Preserve complete Claude helper transcript evidence

* Retain transcript checkpoints until semantic acknowledgement

* Fix transcript test setup and record narrowing
2026-10-30 13:51:56 -07:00
OrcaWinandOrcaWin 44de854ded test: remove 25 low-value suites (audit 846) (#36434)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 13:40:57 -07:00
Neil af9ca88c22 fix(plugins): show icon-theme SVGs that omit xmlns (#36436)
The official Minimal Icons files start with a bare <svg>, so the XML parser
put them outside the SVG namespace and the sanitizer dropped every icon;
the theme was selected but the Explorer kept the built-in icons.
2026-10-30 13:37:12 -07:00
Brennan Benson 619d473f87 fix(cli): choose OpenCode 2 for managed account login (#36292)
* fix(cli): choose a supported OpenCode login for managed accounts

* fix(cli): own OpenCode login probes and preserve existing installs

* test(cli): explain account-add subprocess timeout budgets

* Bound captured account login probes by process lifetime

* Conform account probe tests and process type imports to guards

* fix(cli): preserve Windows account login preparation guidance

* test(cli): accept platform-specific install prefixes
2026-10-30 13:37:02 -07:00
Brennan Benson 2078ebb959 Keep tab right-click menus open through the opening release (#36308)
* Keep tab context menus open after their opening gesture

* Use actual context menu ownership for tab actions

* Retire pending tab activation when context menus open

* Make tab menu class strings statically inspectable

* Own stationary tab menu animation in context primitives

* Conform tab menu caller fixture to existing types
2026-10-30 13:36:38 -07:00
Kelvin Amoaba f22a7d43b5 refactor(source-control): move the changed-file tree builder to src/shared (#36433)
Mobile can only import from src/shared, and its PR files view needs the
same compact tree desktop builds. Move source-control-tree.ts and the
relative-path normalizer it depends on, so both apps run one implementation.
2026-10-30 20:25:25 +00:00
Brennan Benson f06399f5fc Keep refreshed Linear Tasks rows current (#34591)
* Keep Linear refresh results authoritative in Tasks

* Preserve scoped Linear edits through read settlement

* Complete Linear consumer entry and source teardown

* Fix scoped Linear read lifecycle and external refresh

* Complete Linear terminal reads and causal refresh dispatch

* Cover cached Linear read reconciliation under pending writes

* Fix cold Linear lookup invalidation

* Make Linear regression fixtures deterministic

* Align Linear test fixture naming with lint policy

* Consolidate Linear test imports

* Keep Linear saved publications coherent through React replay

* Preserve confirmed Linear accounts through unavailable checks

* fix(linear): retire recovered credential errors on acknowledgement

* fix(linear): keep runtime cache reset on account acknowledgement

* Fix Linear CI fixtures after final main integration

* Correct Linear mobile fixtures and scoped lint annotations

* Keep the mobile fixture assertion annotation on its expression

* Fix Linear static contracts and integration test boundaries

* Complete audited Linear static gates and preserve no-op selection

* Separate Linear selection decisions from observations and preserve create completion

* Name exported Linear fixture mock types with public annotations

* Preserve exact submitted drafts through create settlement

* Read draft retention mode from its committed snapshot

* Publish the current closing draft after queued form replay

* Type Linear create attempts from their form owner

* fix: supply complete task creation test fixtures

* fix: complete checked Linear creation metadata fixtures

* test: complete Linear dialog fixture composition

* test: use host-qualified workspace keys for board sync fixture
2026-10-30 12:51:35 -07:00
OrcaWinandOrcaWin 9bccd67955 test: remove 46 low-value suites (audit 845) (#36407)
* test: remove 46 low-value suites (audit 845)

* test: remove orphaned workflow and runtime test references

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 12:46:07 -07:00
Brennan Benson eca40bc3bf fix(github): honor the saved project account for PR requests (#35023)
* fix(github): resolve project accounts at the request boundary

* fix(github): retain account identity through request settlement

* fix: isolate GitHub leaf caches by held execution identity

* fix: use canonical options type for merged review membership
2026-10-30 12:39:59 -07:00
Brennan Benson bd82832a53 fix(native-chat): keep model picker choices stable during discovery (#36113)
* fix(native-chat): keep model picker choices stable during discovery

* Preserve unknown model inventory across session option reads

* Preserve explicit picker choices and discard refused opens

* Exercise recorded empty ACP inventory through host and picker

* test(chat): align mobile picker contracts with descriptive inventory

* perf(chat): skip effort fallback scans when already resolved

* test(native-chat): align synthetic model consumer expectations

* test: preserve accepted launch seed payload contracts
2026-10-30 12:35:02 -07:00
Brennan Benson eb3379ff99 Fix macOS daemon PTY kqueue descriptor leak (#16870)
* fix(daemon): release node-pty kqueue descriptors

* test: remove redundant wait from kqueue regression
2026-10-30 11:42:31 -07:00
Brennan Benson b83e76f01e Keep Hermes and Antigravity helper IDs out of terminal recovery (#36349)
* fix(copilot): keep helper IDs out of pane recovery

* test(copilot): use recorded root hook shape and fixed clocks

* test(copilot): fail on rejected hooks before ingesting them

* fix(hermes): bind terminal recovery only from root hooks

* fix(antigravity): derive terminal recovery from conversation origin

* Preserve hook event typing and verify bounded transcript reads

* fix: retain accepted hook session binding through reentry

* test: use controlled time for hook binding fixtures

* fix: preserve hook binding type and test boundaries
2026-10-30 11:36:49 -07:00
Brennan Benson cc69f3dda2 Keep unsent hand-off messages after restarting Orca (#34933)
* fix: keep unsent hand-off drafts through restart

* test: prune obsolete structured draft clock baseline

* test: give shared launch mocks a portable public type

* fix(chat): preserve published drafts and initial caret

* Preserve published drafts across launch cancellation and fallback

* Keep unsent conversation drafts through launch cancellation

* Consolidate draft retention test imports

* Preserve native draft caret ownership across adoption and close

* Document intentional elapsed-time regression waits

* Document measured proxy property forwarding

* Set workspace identity in draft retirement fixture

* test: complete structured launch guard store fixture

* test: expect ordinary draft retention after launch cancellation

* test: use real tab owners for structured launch fixtures

* test: construct complete launch scenario settings

* Update provisional selection lifetime regression

* Narrow initialized launch fixture settings reads
2026-10-30 11:28:40 -07:00
Jinwoo Hong a1f7f97671 Orchestration v3: coordinators end their turn and Orca wakes them (#36137)
* fix(orchestration): keep a terminal's mail from being consumed by another terminal, and let settled structured workers take further tasks

A plain orchestration check consumed the named terminal's mail whatever terminal ran it, so a
coordinator checking a worker's handle took the worker's message. A consuming check from a
terminal whose own live pane is a different terminal's is now refused; --peek and --all still read
it without consuming.

worker-start --terminal and dispatch --inject routed a structured worker (structworker_ handle) as
a terminal and failed with terminal_unsupported_for_agent_session. Any agent-session party now
takes its task as a send into its session, while a structured worker keeps the pane and process
authority its first Dispatch had.

* fix(orchestration): fence check by live terminal incl. acks; defer injecting structured workers

Review fixes for the mail fence and structured worker reuse:
- The check fence compares the caller's and the mailbox's live terminal process instead of
  recorded panes, so exited terminals keep the old behaviour and two processes sharing a
  recorded pane are told apart. It also covers --ack in every read mode. The caller lookup is
  shared with the lifecycle caller fence.
- dispatch --inject to a structured worker stays refused as before: an injected Dispatch takes
  no custody, so releasing the first Dispatch could close a session working on the second.
  worker-start --terminal reuse transfers custody and stays supported.
- worker-start decides pane-less chat authority from the resolved party and passes the session
  down, so delivery and next commands no longer re-derive it from the address spelling.
- Receipts name an agent session, not a chat.

* fix(orchestration): an exited caller's env pane names no caller

The caller lookup fell back to the env pane key whenever the env handle was not live, so an
exited terminal's pane resolved to whatever terminal now occupies it, and a tmux worker's own
check was refused. The pane fallback now applies only when the env handle is not proven exited.

* fix(terminal): keep surviving terminals streaming to main after a restart

Main now attaches every live local daemon session it adopts at startup,
not only ones a window pane or remote view is showing, and re-attaches
after a daemon endpoint drop. The attach snapshot seeds main's screen,
tail and title, and an attached-but-silent agent gets an output clock so
readiness can see it has gone quiet. Waits on a survivor main could not
attach fail at once instead of timing out.

* fix(terminal): restore only pane-less streams after endpoint loss; one attach state

- Endpoint loss re-attaches in main only sessions no renderer view reports; a pane restores its own.
- The attach hide skips views mid-attach and leaves a pane's own hidden claim alone on failure.
- One per-session stream state (attaching, attached, lost) replaces three sets and is forgotten on exit.
- Waits retry the attach before failing, including after a failed re-attach.
- The output clock starts wherever a reattach result is seeded, so pane reattaches get it too.

* refactor(terminal): attach survivors at inventory adoption only; waits on unattached survivors fail at once; one ptyId output clock

* test(e2e): scope the restart attach spec's terminal listing to the unopened workspace

* fix(terminal): narrow survivor attach: waits behave as on main, one quiet clock per generation, keep main's hidden mark on failed attach

* Teach the orchestration guide when to hand off and to end the turn after dispatch

* Rewrap a messaging reference line

* Keep the original placement default and skill trigger; keep the accuracy fixes

* Point DAG retries at --retry-of and drop the last blocking-wait instruction

* Check the served orchestration guide by its new worker heading

* Apply council review: best-effort wake, full completion rule, restored safety rules, fixed scope and settled wording

* Say when the orchestration skill applies, and prefer own subagents otherwise

* Name the polling, steering, checkout, and worker fan-out habits to avoid

* fix(orchestration): wake a coordinator whose turn ended while its program still reports working

Claude Code keeps its OSC 7501 report on working while an agent-teams
teammate is alive, even after the lead's own turn ends. The mailbox gate,
idle edges and tui-idle all read that report, so worker mail was stored and
never typed. A hook turn end newer than the program's working report now
counts as rest; hook rows re-classify the PTY so the existing idle edge
delivers. Agent Teams panes now join their claude hook rows.

* fix(orchestration): compare the lead's own turn end, not the row's receipt

A child's hook restamps the row's receivedAt while the lead's turn is still
the old one, which could mark rest under a newer program working report.
Use the lead's turn-end stamp on this runtime's clock, after the latest input.

* feat(orchestration): a consuming check marks the batch it returns as handled

* Say why watch scripts and open waits block the wake

* feat(orchestration): release settled workers automatically after a grace period

* fix(orchestration): use checked row reads for delivery cursors

* fix(orchestration): trust a live own-process turn end instead of comparing clocks

Drop programActivitySince and the turn-end clock mapping: replays and SSH
host clocks made the comparison unreliable. A Claude lead counts as at rest
under a program working report when its hook turn end is a live transition
from this pane's host and launch, past the existing input and respawn floors.

* test(orchestration): drop cast in ack no-op check

* test(orchestration): seed legacy outstanding batch for held chat nudges

* test(orchestration): built CLI check hands its batch over

* test(orchestration): annotate unchanged casts and stub the keep item in tab menu tests

* fix(orchestration): let real input, explicit release and host releases converge with automatic release

- Record worker takeover at the owning runtime when it accepts UI input, before the bytes reach the PTY.
- Run remote attachment releases through the same per-resource single-flight as local ones.
- Apply the confirmed-release home projection when host observation reports a host-side release, and carry the host deadline in fleet snapshots.
- Prove restart recovery with a file-backed database reopened by a fresh runtime.

* test(orchestration): classify the keep RPC's worker fields instead of counting methods

* fix(orchestration): checked delivery reads and observer and recovery help

* refactor(orchestration): end a check when it hands over a batch; wake rides the wait result

* fix(orchestration): refuse an automatic close after real input, join remote releases, converge the home

- An automatic close checks the terminal's last driving-input time right before closing and keeps a worker someone typed into after worker_done; typing itself does no orchestration database work.
- Remote releases share the per-resource single-flight with local release, so a home worker-release joins the host timer's close.
- Host fleet snapshots and federationShow report released and the pending deadline; the home applies the existing release projection inside its observation fence.
- Real restart tests: a file-backed database reopened by a fresh runtime releases a missed deadline once and finishes interrupted requests.

* fix(orchestration): receipt a shared wake batch on arrival and report the applied Run ack

* fix(orchestration): deliver the wake to a working coordinator; agents queue mid-turn input

The wake was typed only into a live idle pane, so a Claude lead whose program
status stayed working (teammate alive) never got it. Agents queue or steer text
typed mid-turn, so a pane takes mail when live idle or working; dialogs,
permission prompts, exited agents, unsettled panes and cold-parked Enter still
hold it. Drops the held-batch Enter deferral and the per-turn-end hook logic.

* fix(orchestration): record each remote release request before joining, publish archives only through the conditional commit

- Each remote release caller records its own request before joining a close under way, and the close decides on the current row, so an explicit release that overlaps the host timer clears the automatic deadline.
- Remote capture publishes its archive through commitWorkerTerminalArchiveForRelease, so a retain during capture leaves no stale archive for worker-read.
- Remote worker-show projects the fenced host deadline and its next action.
- The input guard lives in its own module instead of the scheduler.

* feat(orchestration): start a worker in one step; worker-start creates the coordinator's Run when none is bound

worker-start --spec now creates and binds a Run for a root coordinator with
no bound Run, through the same path run-create uses, and names the Run it
created or joined in every receipt. Workers on a Dispatch keep starting
helpers in their own Run and never get a new one. A new CLI against an older
runtime runs run-create and retries; old CLIs need no change.

* fix(orchestration): drop the older-runtime fallback; check the spec before a Run is created

The CLI fallback matched a refusal text the client decorates, could not
prove the caller was a root coordinator on an older runtime, and recovered
an inner run-create under the worker-start command. Older runtimes keep
their refusal and the guide says to run-create first there. The prompt
budget check now runs before worker-start can create a Run.

* Route report-back requests to coordinators, complete the steer command, and label the wake loop branches

* Say workers are done only when worker_done confirms, wait for helpers to settle, and let bare-shell workers exit

* Route report-back requests away from handoff and steer supervised workers through their mailbox

* docs(orchestration): teach auto-handled check, retry-request and inbox recovery in the guides

* Describe the mid-turn wake in the messaging reference

* docs(orchestration): say terminal workers are released 2 minutes after worker_done

- The guide's Completion section, the reuse recipe and the recovery reference now describe the automatic release and its autoReleaseAt deadline: reuse or worker-retain before it; explicit worker-release still works and is required for chat workers and workers without a deadline.
- The worker preamble says the terminal stays available until Orca releases it, about 2 minutes after worker_done unless retained.
- Regenerated the bundled guides.

* feat(orchestration): receipts say when to end the turn

* feat(orchestration): tell the coordinator when a worker stops without worker_done

* test+docs: worker stop reports

* fix(orchestration): judge the empty-check stop with execution-host verdicts

* test: drop casts from worker stop tests

* Say that report-back requests still mean end the turn

* Say that report-back requests still mean end the turn

* fix(orchestration): stop reports wait for children, keep their Dispatch, and relay intact

* fix(orchestration): a stop belongs to the Dispatch active when it was seen; restored stamps announce nothing

* fix(orchestration): never say to stop while a remote worker runs

* Shrink the orchestration guide to the end-state workflow

* fix(orchestration): stop reports quote the agent's last words, or the screen for errors and prompts

* fix(orchestration): withhold the stop while chat failure mail is off

* test: a clean finish quotes the agent's last words

* fix(orchestration): stop asking workers for heartbeats

Workers are no longer told to send periodic heartbeats. A heartbeat that
still arrives from an older worker or peer only records last_heartbeat_at:
it is stored already handled, so it never lands in a coordinator inbox and
never wakes a coordinator or a check --wait. Removes the stale-heartbeat
warning and the heartbeat interval plumbing that only fed the preamble.

* fix(settings): remove the worker heartbeat controls

The Worker heartbeats switch and Heartbeat interval field only changed the
worker preamble text, which no longer mentions heartbeats. Saved values are
dropped on load as retired settings.

* fix(orchestration): wake a coordinator that reports program status but never sets a title

Program status only re-classified a pane that had a title, so a titleless
agent (agy) never got a live status and the wake gate refused it.

* fix(orchestration): a new Run no longer cuts a coordinator off from its earlier Run

* test(orchestration): drop heartbeat-batch cases the handled heartbeat row removed

* fix(orchestration): redact capabilities from a stop report's quoted output

* fix(orchestration): never wake a mailbox for a heartbeat

One rule at the runtime notification entry replaces per-call-site read
checks, so mutation replay and federated control-mail import stay silent
for heartbeats too.

* Shrink the orchestration references and worker preamble to the end-state workflow

* Name the older-Orca bind refusal as worker-start prints it

* Owner-fence test: a refused foreign ack changes nothing, whatever the worker's own check already handled

* Integration: drop the duplicate consumingCheck after merging #34043 and #35293

* Integration: await the worker-start next receipt before naming its Run

* Apply review round 1: drain to zero, release without auto-release, retry after stop, Run before a DAG

* Apply review round 2: start ready DAG Tasks, block when no failure wake, replay sends by request ID

* Apply review round 3: one receipt-based wait rule for starts and wakes

* fix(orchestration): a worker stopped without reporting needs action, and stop keeps its output

worker-list projected a stop-reported attempt as live, in_progress, no action. It now
projects finished_unverified with a worker-read recovery until mail reaches the worker.
worker-stop closed the terminal before anything archived it, so release reported the
archive unavailable; stop now archives the output first.

* Revert "Owner-fence test: a refused foreign ack changes nothing, whatever the worker's own check already handled"

This reverts commit 336ff91737.

* Revert "Merge #34043 (terminal mail guard, chat worker reuse) into integration"

This reverts commit 9c01b1a06e, reversing
changes made to d4b0c6c5f7.

* Revert "Merge #33720 (restart: attach surviving terminals) into integration"

This reverts commit d4b0c6c5f7, reversing
changes made to 53f9735bfe.

* Integration: restore #35293's check-methods after removing #34043

* fix(orchestration): bound the pre-stop archive and keep it through retain

* fix(orchestration): a failed pre-stop archive never blocks the stop

* fix(orchestration): answering a question says to end the turn while the worker runs

* fix(orchestration): a settled worker whose terminal moved owes nothing

* Cut the orchestration guide to what Orca does not already enforce or explain

* Drop the terminal-send recovery the CLI already prints

* Restore a short never-do block: no polling, no terminal steering, no hand-made checkouts

* Trigger on named-agent review requests, define failure in specs, show the reuse commands

* Restore six guide rules from the cut review and drop the preamble heartbeat block

* Integration: drop the removed heartbeat interval from preamble tests

* Drop the outside-Orca wait and run-use lines; Orca's errors teach both

* Release finished chat workers like terminal workers unless the user touched them

A finished chat worker now closes ~2 min after its accepted worker_done, like a
terminal worker. Clients report a touch when a chat is on screen at rest (opened
idle, or its turn ends on screen); the owning host keeps a finished worker's
chat on that report, until its automatic release commits the archive and closes
in the same tick. Chat workers arm only while every connected client advertises
the touch capability; old clients keep today's manual release.

* Decide an automatic chat close in the session lane, recheck clients there, re-touch after reconnect

The automatic close now asks the database in the chat's session lane right before
Stop: a touch until then keeps the chat, and a client that cannot report touches
(joined during the grace or after a restart) sends it back to manual release.
Touch reports wait for a read chat, so a reconnect re-reads and reports again.

* Keep explicit chat releases eager and re-touch a desktop chat after lost contact

* Resolve a chat touch by durable worker identity, so a closing chat's hidden tab stays touchable

* Keep the mobile touch report free of route and app-state hooks: shown counts as seen

* List workerChatTouch's identity fields and the close's optional admission in their census tests

* Release a settled remote worker from the home when its host predates automatic release

* Replace Keep Worker Open with an auto-close setting, and tell agents when an older server needs a Run

The coordinator's runtime decides whether finished workers close: it gates local arming, the
settlement ack's autoRelease opt-in to a remote host, and the home deadline for older hosts.
worker-start and run-create name an older server's one-Run-per-coordinator behaviour instead
of failing or rebinding silently.

* Escalate a parent's prompt or error even while its helper is open

* Report a chat touch when a worker chat is opened while working, and on each turn edge

* Record worker takeover when the host admits a person's chat send, so mobile sends keep the worker

* End a reported worker stop when the worker resumes, not only when Dispatch mail arrives

* Recheck a chat mail notice at admission so mail a check consumed starts no turn

* Type the resumed-turn stop test's pane move directly

* Keep the stop decision in an empty check, report muted chat failures as stops, and bind a new Run only once a start passes preflight

A start or reply receipt now sends the caller to drain its mail with check instead of ending its turn, so a mid-batch answer cannot skip a later report and a replayed receipt carries no stale stop. With chat error mail off, a failed chat request still reports a plain stop through the existing stop report path. worker-start creates and binds its Run just before the Task and Dispatch, so a start refused in preflight leaves no Run behind. worker-release help no longer says chats never auto-release.

* Reuse a Run a parallel first start bound, refuse dependencies before creating a Run, and relay a paired-server worker exit home as a stop report

* Read a reported worker stop against live agent status instead of recording resume observations

A stop report is mail the coordinator reads once. Whether a worker shows as
finished now comes from its live status: a fresh working agent status (local
pane, chat session, or the execution host's fleet snapshot) outranks the
report, so nothing needs clearing on resume.

* Drop agent steps Orca already covers: start receipts say Orca wakes you, a check asks for another only when a capped batch leaves mail, workers get no mail-check or ack lines, and chat errors always report with the exact error

* Keep the home's remote auto-release deadline until the host answers, and let a retain win at the send

Claiming a due deadline postpones it instead of moving it to a releasing state, so a restart or
a failed attempt runs it again; the release send rechecks the deadline with no await before it.
A host that cannot be asked at settlement still gets the deadline, and a host upgraded since
settlement is released by the home, since it never armed its own.

* Close a finished worker automatically only if the user never opened it

Seeing a worker's terminal or chat now writes the user's Keep record (owned,
retained) on its host, at any point before its close is admitted, so a worker
seen while it worked is never armed and a pending automatic close is cancelled;
the coordinator can still release, stop or re-engage it. Desktop reports from
the on-screen attention scan for every on-screen terminal pane and chat once a
present user is on that workspace; mobile reports the tab a session opens on
and each tab switch. The weaker chat-only touch hooks are removed. A chat send
admitted after the automatic close committed its archive now keeps the chat.

* Show only live facts for a worker that reported a stop

A stop report is escalation mail that wakes the coordinator once. worker-list
and worker-show no longer project it as finished_unverified with a recovery
action, so the live-working override that cleared that label goes too.

* Report a paired-server worker's process exit home even while its ask or check --wait is still registered

* Report a seen worker until its host records the keep, including chats shown before custody and mobile auto-selections

The touch reply now says pending while a structured worker's custody row is
not yet recorded; desktop and mobile keep a subject unreported after a
failed or pending reply and retry on the next scan, snapshot or reconnect.
Mobile reports whichever terminal or chat is displayed, tapped or selected
by a snapshot, instead of only the first per workspace.

* Record a person's chat send or command takeover inside the session lane

Takeover moves from the RPC wrappers into the host's in-lane acceptance
of userSend sends, /compact and /clear, so a close queued behind an
accepted send cannot admit before the keep, including during /compact's
handover wait. Host orchestration sends never set userSend.

* Say which stop reports a deliberate wait suppresses

* Align merged tests with the shorter preamble and the fixed start hint

* Retry an unrecorded mobile worker touch when the phone reconnects

* Drop the removed worker check line from the CLI boundary test

* fix(orchestration): wake a coordinator that survived an app restart

After a restart, main typed the mail wake only into an agent whose status it
had seen live since starting, so a coordinator whose turn had already ended
never woke. At reattach, take the agent's own last hook report, which the hook
server restores from disk and from its offline spool, as that observation while
an agent still holds the surviving process.

* fix(orchestration): restore the lead's own turn, hold a restored draft, fence respawns

Read the lead agent's turn from the restored report so background work does
not hide an ended turn, keep the wake out of a composer that still holds text
typed before the restart, and drop a restore that a respawn has overtaken.

* fix(orchestration): restore a reattached status only from a current screen without a draft

The whole-screen accessor hides a model the provider still owns after attach, so a
draft there read as none. Read the screen the way wait gates do, provider image
included, and decline the restoration when it is unavailable.

* fix(orchestration): restore a reattached status without reading the screen

After a restart main has no record of typing, so the existing draft hold cannot
apply; a screen read here could miss a draft and, when slow, strand the
coordinator for good. A draft left before the restart now meets the same rule
as an abandoned one.

* fix(orchestration): let a slow foreground probe still restore a reattached status

A probe answering after the interactive two-second bound was dropped for good,
stranding the coordinator. Restoration has no caller waiting, so it takes the
real answer; the existing fences still guard application.

* test(orchestration): mark the slow foreground probe as fake-clock driven

* Report a terminal worker whose agent died while its shell lives

A killed agent sends no stop hook and its shell keeps the PTY open, so its
Dispatch stayed open and the coordinator was never woken. The shell's
command-finished already retires the PTY's launched-agent authority; the
panes it retires now go to the worker stop reporter as an 'exited' stop
(same mail and wake as a PTY exit, once per Dispatch, none once settled).

* refactor(orchestration): key mail, waits and settle checks by terminal

Reapplies #34056 on the integrated orchestration work: mail delivery, the
settle recheck and terminal waits are keyed by ptyId instead of the window
pane, deleting the pane-keyed leaf lane and the headless-only PTY lane.

Keeps #34706's delivery rule (a terminal taking input, idle or mid-turn,
gets the wake; dialogs, permission prompts and unsent drafts hold it; the
cold-park fence still defers a parked Enter) and #35274's multi-Run
coordinator mailboxes.

* fix(orchestration): keep best-effort delivery's catch; stage the remount e2e

deliverForHandle keeps the integration branch's catch: ownership resolution
still reads SQLite, and a notification queued before teardown must not throw.

The remount e2e now asserts each stage on its own (mid-turn mail before the
workspace opens, the wait across the remount, mail after it), since #34706
types mail mid-turn and the old single mail check could pass before the
remount happened.

* refactor(orchestration): settle a new terminal wait from its first reading

A wait now keeps the PTY record it resolved, and nothing runs between the
first evaluation and the waiter's registration, so the second evaluation
re-read the same evidence. Starts the poll from the first verdict instead.

Deletes the leaf wait-result builders the leaf lane left without callers,
and adds a unit test that a tui-idle wait survives its pane remounting
(the e2e cannot order the wait's registration before the remount).

* Report a dead worker agent only once its shell is proven alone

A command-finished marker alone does not prove the launched agent exited: a
nested interactive shell in a live worker emits the same marker. The exit
report now waits for the execution host's shell-alone proof and is fenced to
the Dispatch and launch seen at the marker, so a relaunch in the pane is not
reported by an older completion. It no longer hangs on launch-authority
retirement, so a nested completion that retires metadata does not stop a later
real death from being reported. The agent-exited fact feeds the same path for
shells without OSC 133.

The shell-alone report and a paired-server worker's PTY exit share one exit
entry point and key, so the Run home gets one report per process.

* fix(orchestration): resolve a terminal's mailbox across every pane that shows it

Two panes can show one PTY; ownership read only the first listed pane, so a
Run bound to the other was never woken. The mailbox terminal now carries
every pane alias and ownership, discovery and the delayed-Enter recheck
consult them all.

* Report a killed worker agent from its launch's exit receipt

The launch command now ends with a per-shell marker the shell prints once
the agent returns, however it ended. The execution host scans it before
thinning (main and daemon), checks it against the PTY's current launch and
incarnation, and reports through reportWorkerExit. A nested shell has no
receipt and a relaunch names a new one, so the shell-alone inference is gone.
A later local PTY exit reuses the same exit message id, so it settles the
Dispatch without a second report.

* Revert "Revert "Merge #33720 (restart: attach surviving terminals) into integration""

Reapplies survivor attach (72b3b79fd3, fe906ea2a2, f46777ba18) so the
#33720 merge that follows carries it; integration reverted it in 2f945fa715.
The output clock now feeds v3's terminal-keyed wait path; the leaf lane it
also fed is gone in v3.

* test(orchestration): give exit-path DB stubs the remote-attachment lookup

The paired-server exit relay now asks the Orchestration DB for an active remote
attachment on every local pty exit; partial stubs without it threw.

* Report a worker killed after a restart from its Dispatch's launch commitment

The exit receipt ID is now derived from the launch-token hash a Dispatch
persists, so a PTY reattached after restart (no launch token in memory)
accepts its receipt when the pane's active Dispatch committed that launch
in the same shell process.

* test(orchestration): stub main's session-dispatch presentation read in the stale-leaf DB

Main's projection scope now reads listSessionDispatchesForPresentation on every
projection; v3's hand-rolled stub predates it.

* test(orchestration): drop the stale-leaf stub key integration's merge now supplies

* test(orchestration): align main's new tests with integration's mid-turn mail, admitted close and nameless worktrees

Main's titleless-turn test assumed mail waits for Stop; v3 types it into a working agent.
Main dropped the --name requirement, so that preflight case now fails on the missing repo.
The evict close now forwards the session lane's admitClose.

* perf(orchestration): read the next federated release deadline through its partial index

The armed-state filter alone cannot use the non-null partial index, so every rearm walked retained federation history.

* perf(terminal): keep unviewed restart survivors to the daemon's live window

Main now attaches every surviving terminal at startup; each mirror took the full
5,000-row depth with no viewer. A survivor nobody views keeps the 1,000 rows the
daemon itself holds, and grows to full depth from those rows once a view subscribes.

* chore(orchestration): clear check:changed findings on the main merge

Format a listing statement, prune the flaky-pattern baseline, and justify or remove the
test casts the changed-code gate flags.

* Revert the unviewed-survivor mirror cap: it can lose desktop history after a restart

A capped survivor mirror is still served as complete history to desktop recovery, and a desktop pane
added after inventory never lifts the cap. Restart memory for unviewed survivors moves to a follow-up
that defers the screen model instead of truncating it.

This reverts commit 4ea934ca7f.

* Key main's new null-agent idle-wait test by terminal, as integration's waits are

* fix(orchestration): type mid-turn mail only into a recognized agent

An unrecognized terminal's working verdict may be a running program reading stdin,
so null-agent panes keep waiting for quiet before the pointer is typed.

* Remove killed-worker exit receipts from orchestration v3

The launch-bound receipt added a visible printf to every agent launch line. Owner decision: ship v3
without killed-worker detection (behaves as main does today) and revisit it later, e.g. by watching the
agent's hook-reported process.

This reverts merge b9a30b6e74.

* Stop re-arming a delivery recheck once the quiet window has passed

A refusal that outlives the quiet window (an unrecognized terminal still reading as working) is not
time-bound, so a 50 ms recheck spun forever. The next output, title or mail edge rechecks it.

* Keep retrying deliverable mail past the quiet window; gate mid-turn delivery on terminal agent identity

A refusal outliving the quiet window can wait on a hook final-frame deadline or a late foreground
recognition, neither of which emits a delivery edge, so poll slowly while that terminal still has
deliverable mail and stop once none is pending. Mid-turn delivery now asks whether the terminal agent
is recognized at all, not whether it has readiness rules, so a recognized reusable agent keeps it.

* Keep structured-agent-session.ts within the 300-line cap

* fix(orchestration): arm delivery rechecks only for actionable delivery work

The recheck predicate now counts persisted pointer reservations awaiting
recovery as well as selectable new mail, and gates every recheck (quiet
window, post-quiet, and holds) on it, using the canonical output clock.

* Check the served orchestration guide by a heading the v3 guide keeps

* test(e2e): launch the mail-pane fake under its agent CLI's name

v3 types mid-turn mail only into a recognized terminal agent, and a title alone no longer
recognizes one, so the fake runs as `node …/codex` (or cursor-agent) like an npm shim.
The hold-while-working case now models the unrecognized program that contract still holds for.

* test(e2e): align idle mail delivery spec with v3 auto-ack, mid-turn Enter and multi-Run coordinators

A consuming check now marks its batch handled (8fbb395a32), so the live
waiter's mail is pulled once returned and the held-batch case is seeded
as an older Orca leaves it. Agents queue mid-turn input (e0cb9a68d2), so
the held reminder's Enter is no longer withheld. A coordinator keeps its
earlier Run (#35274), so Run A direct mail is pointed with --run A.

* Wake a Run's coordinator through its pane when the Run's stored terminal handle belongs to the pane's previous PTY

* Make check --ack acknowledge only, so it never takes new mail

A check carrying --ack acknowledged that Delivery and then took (and,
since checks now acknowledge what they show, consumed) the next batch.
A caller that discarded the output lost that mail. --ack now returns
after acknowledging; newer mail stays unread, so the wake path still
fires and the next plain check shows it. The receipt says --ack is not
needed. Removes the ack-then-take receipts this made dead.

* Print every message body and payload in a plain orchestration check, since current hosts acknowledge the batch on read

* Keep acknowledge-then-take for check --ack --wait, and reject --ack on direct mail

A waiting caller reads what the wait takes, so --ack --wait acknowledges
and then waits for and takes the next batch, as before; --ack alone
stays acknowledge-only. Direct mail has no Delivery, so --ack there now
fails as a foreign delivery instead of consuming the mail.

* Keep a user-kept worker terminal kept when a new Dispatch reuses it, since its on-screen pane reports only once

* Tell a coordinator to check a remote worker itself when its host cannot report turn stops

* Find a Run's pane terminal for mail without re-issuing its handle mid-reload

* Keep the original ack-then-take path for check --ack --wait

Composing an ack with a second check lost the acknowledged consumer
generation and persisted subcall receipts. --ack --wait now runs the
original single-generation path unchanged; only --ack without --wait
returns after acknowledging, and direct mail still rejects --ack.

* Settle the e2e agent idle before newer mail so the mid-turn pointer cannot race the idle title

* Record a user's view of a worker terminal as user_seen so only it, not a coordinator's retain, survives reuse by a new Dispatch

* Let a worker ask, end its turn, and be woken with the answer

* Drop casts from the ask tests and the pending-question query

* Tell agents to run a plain check after acknowledging a held Delivery

--ack without --wait no longer takes newer mail, so the held-delivery
pointer now names the follow-up check for the new messages.

* Deliver Run and Dispatch mail to the pane's current PTY, issuing its handle only when none exists

* Wait for a PTY's exported handle before mail, and wake it when that handle is adopted

* Keep a cancelled ask from taking its answer, scope the asked-question stop mute to the asking turn, and end a waiting ask when its Dispatch settles

* Order the asked-question stop mute by message sequence, not same-second timestamps

* Wake a PTY's deferred mail whenever it gets a handle, by any path

* Make the headless Dispatch adoption test hold in both layout modes

* Mock the finished-worker strip states with neutral pane and chat notice fixtures

* Mock the temporary-worker strip with the owner's copy and the Allow auto-close tab menu item

* Mock chat workers with a goal-style composer strip instead of the composer notice

* Keep a worker open only by Keep open; hold its countdown while its agent works again

* Remove viewing and typing as implicit keeps on desktop and mobile

* Update the routing specs to acknowledge a held Delivery, then take with a plain check

* Show the temporary-worker strip with Keep open and its countdown, and Allow Auto-Close in tab menus

* Share the worker auto-close poll and key its read to the subject

* Re-read kept workers often so Allow Auto-Close shows its countdown promptly

* Hold auto-close through every turn, refuse stopping kept workers before anything changes, and read worker state only for known workers

* Keep a claimed close final, check the agent before claiming, refuse remote stops without a Keep open answer, and keep re-reading known workers

* Classify workerChatTouch caller fields and drop a test-only cast
2026-10-30 14:20:02 -04:00
Brennan Benson 527e7082b6 Reduce whole-app hitches when many chats are running (#35624)
* Move chat journal checkpoints off the host thread

* Apply checkpoint lifecycle style and teardown test checks

* Wake journal checkpoints for cleanup writes and retire fixture owners

* Use fixed time in attachment checkpoint fixture

* Derive checkpoint timer handles and check unref capability

* Preserve journal test close completion and event typing

* test: await journal close before fixture reuse and cleanup

* test: await registered journal fixture cleanup

* test: integrate goal sweep fixture with journal ownership

* Simplify journal checkpoint worker lifecycle
2026-10-30 11:13:21 -07:00
Brennan Benson 3129ede025 Keep Copilot helper IDs out of terminal recovery (#36324)
* fix(copilot): keep helper IDs out of pane recovery

* test(copilot): use recorded root hook shape and fixed clocks

* test(copilot): fail on rejected hooks before ingesting them
2026-10-30 11:07:14 -07:00
Brennan Benson a68230334e Let automations run in Chat (#34332)
* Let automations run in Chat or Terminal through the shared agent launcher

* Preserve automation targets and complete owned terminal lifecycles

* Keep stale prompt projection available when recomputing

* Count repeated desktop lifecycle resource cleanup

* Preserve automation targets and observe committed chat work

* Scope automation observation and reconciliation work to each operation

* Restore automation server composition and process import boundaries

* fix(automations): preserve busy chat reuse and runtime boundaries

* Correct shutdown test acquisition and exported measurement types

* Correct automation fixture contracts and duplicate imports

* Keep Chat automations separate from Terminal execution

* Preserve Chat automation intent while support loads

* Resolve automation Chat validation diagnostics

* Remove unused automation style directives

* Make automation surface classes statically inspectable

* Move automation surface styling into a toggle group variant

* Correct automation launch test receipt and output fixtures

* Account for pane and prompt journal reads in delivery test

* Preserve admitted automation surface across save effects

* Separate automation page test actions from their lifecycle owner

* Complete automation route test fixture input

* Reopen saved automation chats through the existing record owner

* test: isolate session action fixtures and complete tab groups
2026-10-30 10:49:18 -07:00
Brennan Benson 3881fbcda9 Keep pending questions through agent notices and undelivered replies (#36306)
* Keep pending blocking questions through non-answer rows

* Use a canonical delivered human row in blocking question tests

* Remove redundant live-status question test
2026-10-30 10:46:10 -07:00
ValeandBrennan Benson b2b8b0be93 fix(plugins): clarify selected themes and confirm other-mode picks (#35926)
* plugins: show which theme chip is selected and switch modes for an other-mode pick

A selected chip used the muted secondary style and an unselected one the
filled primary style, so the theme in use looked like the inactive one.
Selected chips are now filled with a check and the others outlined.

Choosing a theme for the other mode only filled that mode's slot, so
nothing changed on screen and the click looked broken. Like installing a
one-mode theme, it now switches the app to that mode and offers Switch
back. The snapshot and toast are shared with applyPluginThemesNow.

Terminal chips were all listed under 'Use now', even a light terminal
theme shown in dark mode. They now sit under the mode they apply to.

Fixes #35922

* fix(plugins): switch back only the settings a theme chip changed

Switch back after an other-mode chip pick restored every theme setting,
so an icon or terminal pick made while the toast was still up was undone
too. It now restores only the keys that pick wrote, plus the mode. The
install flow keeps the full snapshot since it writes most of those keys.

* fix(plugins): list a terminal theme shown in the current mode under Use now

Installing a plugin whose only terminal theme is for the other mode puts
it in the slot that is showing. Grouping terminal chips by their own mode
then showed it selected under 'Use for light', and a click switched the
whole app to light. Treat a theme in the showing slot as that mode's for
the group, the check and the update together.

* fix(plugins): treat the terminal slot light mode displays as Use now

With Match dark mode on, light mode shows the dark terminal slot, but the
chip only checked the light slot. The dark theme on screen was listed
under 'Use for dark' and a click switched the app to dark. Check the slot
that is actually displayed.

* fix(plugins): replace theme chip type assertions

* fix(plugins): preserve appearance when assigning theme chips

* test(plugins): exercise disabled palette across plugin pages

* Prepare plugin terminal palettes only when selected

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-30 10:20:03 -07:00