Prepare requested immutable historical snapshots before timed extraction and direct reads, using the existing acquisition/process helpers and local-only consumers. Move four suites' historical module setup into per-pin hooks without changing pins, compatibility assertions, workers, extraction/assertion deadlines or publication ownership.
Independent reviews and the binding design settlement passed. The cold comparison and normal uninstrumented final-head CI each passed49files197tests; normal Checkout62s/job276s. All temporary probes removed; brennan-ready READY.
Tracked in STA-13683. Outer-hook failure attribution limitation tracked in STA-13703. No application, saved-data or wire behavior change.
* refactor(mobile): keep phone list facts beside the desktop's worktree row
The phone wrote its own list facts (lineage depth, host labels, list keys
and so on) onto the worktree.ps row object it got from the desktop, so a
desktop field with one of those names would be read as the phone's own.
List items are now { row, view }: the row is the desktop's, typed from the
shared RuntimeWorktreePsSummary contract, and view holds what the phone
works out. Host labels are a lookup beside the rows instead of fields on
them. A type test fails if the desktop row gains a view field's name or a
type the phone row would not accept, and a contract test feeds rows from
the desktop's own worktree.ps builder through the phone list.
* fix(mobile): type desktop replies from shared contracts and reject unchecked rows (#37923)
* wip: contract guards
* fix(mobile): type desktop replies from the shared contracts and ban unchecked z.custom
Session tabs, the createSupport reply and native-chat frames were typed by
hand on the phone, so a desktop change could leave the phone compiling
against a stale shape. They are now Pick/Partial of shared types; the
createSupport reply and native-chat transcript frames gain shared types the
desktop uses too, which also gives the phone the 'chat-program' reason it
was missing. Type tests fail when a desktop tab gains a phone-only name or
a field type the phone would not accept.
Catalog rows were admitted with z.custom<Worktree>() and no check. They now
need a string worktreeId, and an ast-grep rule rejects a z.custom with no
check anywhere in mobile/src.
* test(mobile): the desktop contract check also catches a null the phone would not accept
* fix(terminal): a local file link opens in the workspace it was clicked in
Clicking a terminal link to a file inside another local workspace switched to
that workspace: the editor loader moved the absolute-path tab to the workspace
containing the path (#11369), and link routing jumped to a sibling tab already
showing the file (#16544). This computer reads absolute paths directly, so
local tabs now stay where they were opened, editable. SSH and server hosts,
which read only workspace-relative paths, keep moving to the owner.
Refs #32158, #25838
* fix: merge duplicate editor store import
Keep the GitHub Tasks source picker, rows, totals, searches and issue creation tied to the selected project, host and source. Ignore outdated replies and wait for source preference saves before creating an issue. Preserve support for older paired servers.
Tracked in #8726. Tracked in STA-1815.
* fix(chat): show device names on answer receipts
* fix(chat): resolve receipt names across local and remote hosts
* test(chat): type receipt boundary test dependencies
* fix(chat): keep receipt labels within history frame budgets
* test(chat): return complete compatibility attach replies
* Read Linear drawer details in one issue query
* Keep readable Linear details after optional field errors
* Select only Linear fields needed by each issue reader
* Explain the typed Linear partial response boundary
* Typecheck Linear integration in the mixed-process project
* Update Linear integration fixtures for raw issue reads
* Agent message cards keep their sender's agent icon when the agent can't be found
A card names its sender by a snapshot written with the message, but drew the
icon only from a live lookup, so a sender the lookup missed (a worker on
another host, a terminal after restart, a closed agent) showed "?". Every
writer (worker start, mail, task, federated start) now saves the sender's
agent kind beside its name, and the card draws it when no live row names
the agent. Live rows stay the source of icon and status whenever they match.
* Preserve known worker agents on federated cards and mail
* Resolve agent message senders through shared host identity
* Retain acquired worker launch identity for later sender snapshots
* Prune repeated worker sender contract checks
* Combine worker command contract projection imports
* Keep sender identity bounded and scoped per worktree
- A worktree removal frame drops only its own scope; a host stays
publishing once any frame carried the field.
- Identity history rebuilds follow writes to the facts it reads
(connection-local triggers), not heartbeats, read marks or receipts;
new mail is read incrementally.
- One principal per paired peer replaces every federated route ever made.
- Unchanged worktrees keep their scope object; a refresh republishes only
worktrees whose scope changed. Chat records key on the store's state
generation instead of serialising every record.
- The publication rides client frames only, and phone frames drop it.
- A failed history read keeps the last good publication and is not
marked indexed; malformed rows are skipped; opening the database for
display never throws.
- A located chat keeps its tab's agent icon for cards saved without one.
* Save each agent card's sender identity and open the pane it names
Orca now records who sent each agent message and created each task when it accepts them, and the chat card resolves that saved identity against what each host says runs now. The avatar dot, label and click all read that one answer: a located terminal opens through the sidebar's own activation path, a closed chat reopens through its lineage, and a sender no host can prove shows its saved icon and says it is no longer available instead of opening whichever agent now holds the old pane.
Publication now has the host's pairing key from the RPC server, so it no longer fails on every build.
* Resolve agent card senders by the terminal handle every card saves
A card's sender is now the terminal its saved handle names, the worker lineage its Dispatch continued into, or its chat session. That survives a normal restart, works with hooks off, from a plain shell and for replies, and needs no newly saved sender data, so the hook-conversation records, their table and the saved identity key are gone.
The avatar, link and click read one answer. A terminal that now runs a different kind of agent than the card saved, or a sender two places claim, shows the saved icon as a plain name. A terminal that exited or was respawned keeps the host's own lookup on click without a status dot, behind one switch.
Chat senders rebuild only when a chat appears, moves, clears or closes, and each live pane's worker reads go through the existing partial indexes.
* Send sender identity once per revision and judge every host by one rule
The host's sender publication now carries an in-memory epoch and content revision that move only when what clients read changes. A window's graph sync sends the revision it applied and gets "unchanged" instead of the rows; each session-tab stream sends a worktree's scope once per revision. The window keeps the whole-host publication as its baseline and a newer worktree scope over it, by revision, so a delayed reply never undoes a newer scope and repeated deliveries cost nothing.
An older paired host's cards now go through the same resolution as everyone else's: a terminal that runs a known different agent shows the saved icon as a plain name, and what the host's lookup returns is judged by the same row. Pi and OMP, and Claude and its teams wrapper, count as one agent. Failure text names the agent and says what to do.
WSL chats are published, closed chat history no longer counts as open before the tab table exists, and paired principals are read again only after a pairing changes.
* CI: keep the sender delivery contract test out of the web project and fix its types
The cross-process delivery test moves to tests/e2e, where tests that span main and renderer live, so the web typecheck no longer pulls main files in. It now drives the stream encoder main uses. The worker lineage walk takes a reader type without a this binding, the stream delta composes with the proof delta's own frame type, alias buckets accept terminal and chat tab arrays, and the publication test builds fully typed fixtures.
* CI: share the dispatch-address link rule and align the merged view test with saved-kind icons
The base's worker command contract test reads the shared rule that a
dispatch: address is never a link; the card's link check now calls that
shared rule instead of repeating it. The base's sender view test expected a
different agent's live row to replace the saved icon; this branch shows the
saved kind without that row's status, so the test asserts that.
* Use the sender snapshot resolver in main's new receiving-account tests
* Read a saved "unknown" agent kind as no kind for the card's icon and its replaced check
A hooks-off agent whose last status came from a terminal report without an app id saves the kind
"unknown". That kind proved nothing, yet it vetoed the live agent in its own terminal: the card
showed "?" with no dot as a plain name, and a raced click said another agent was running there.
One shared read now treats it as no saved kind for the veto and the icon, on every path.
* Apply a frame's sender scopes when the window receives it, ordered by each scope's own revision
A stream counts a sender scope as sent once a frame carries it, but the window applied it only
inside the tab apply, behind the tab version, resume census, receipt recovery and frames-draw
checks. A frame those checks dropped could hold the only copy, so a paired host's cards stayed
on stale rows (no dot while the sidebar showed the agent) until that worktree's senders changed
again. Each receipt path now folds the frame's sender scopes in right after its connection,
pairing and runtime checks; the tab apply keeps only a worktree's removal.
A scope now also yields to that scope's own newer delivery, not only to a newer whole-host
baseline, so a delayed list reply can't put back older rows. Every publishing host stamps a
revision, so the content-comparison path for unrevisioned publications is gone.
* Read chat senders from open chats and their /clear predecessors, not every saved chat
Each chat tab opened or closed, chat created or moved, or /clear committed rebuilt the chat
senders by listing every saved chat (42 ms at 10,000 on the main thread) only to keep the open
ones. The record store now keeps an in-memory reverse of the saved /clear pointer, built at
load and updated for the rows each commit writes; nothing new is saved. The sender read starts
from the open chats and follows that index to their predecessors, so its work no longer grows
with closed history.
* Walk live terminals once per session-tab inventory or broadcast, not once per worktree
A one-shot inventory or a broadcast built every worktree's frame through its own sender
refresh, and each refresh walks every live terminal: 20,000 visits for 1,000 terminals over 20
worktrees. Both passes now build their frames from one refresh. The publisher counts its leaf
and terminal visits, and a test drives the real inventory and broadcast methods at 100 and
1,000 terminals.
* Re-read a tab bucket's sender aliases only when a host it read changes
The window's sender aliases were recomputed for every open tab whenever any workspace-owner input
changed, such as switching workspaces or writing a setting, though a bucket reads those inputs
only through one host per worktree. Each bucket now keeps the host values it read and, when
owner inputs move, checks just those before reusing its aliases. The delivery contract test
counts alias work through workspace switches, settings writes and a title-only change.
* CI: restore the single-frame builder declaration and compare sender content without its revision
R4 swapped the inventory's abstract single-frame declaration for the batch one, but the
headless browser-tab emit and the runtime-owned terminal create still build one worktree's
frame through it; both keep the per-frame sender scope. The publisher's content comparison now
takes publications without their revision stamp, which R4 made required.
* CI: give the sender no-op test's heartbeat a fixed timestamp instead of the wall clock
The heartbeat only has to be a write that changes no sender identity, so a fixed time keeps the
assertion and satisfies the flaky-test gate.
* CI: assert one terminal walk per orchestration RPC and no identity reads in the sender refresh test
R4 added leaf and terminal visit counts to the publisher's work counters, and each orchestration
RPC's refresh walks the live terminals once, so the whole-counter comparison failed. The test now
compares history, chat and lineage reads, unchanged, and asserts exactly one walk per RPC.
* CI: reach the sender pass methods through a typed view of their prototypes
The test read the runtime's protected inventory and broadcast methods with Reflect.get and an
object-typed owner. It now names the three methods it drives in narrow types over their real
prototypes and calls them on the same stand-in; the assertions are unchanged.
* CI: list every sender target kind in the link switch and merge the duplicate sender-type import
The link check's switch now names the ambiguous and replaced kinds, which return false as the
default did; the publisher imports its sender types from one statement.
* Skip a paired host's floating-terminal sender scope at receipt, as the tab apply does
Applying sender data on receipt took a paired host's floating-terminal scope that the window
never mirrors, so its sender drew as a link whose click activated a pane this window lacks and
did nothing. The receipt now uses the tab apply's own floating rule for paired hosts: that sender
opens by asking its host, as before. This machine's own floating terminal still publishes.
* Read /clear predecessors through the record store's existing successor index
The sender's chat read reached each open chat's /clear predecessors through an in-memory reverse
index the record store built at load and kept per commit. The store already has an indexed query
for that link, which its lineage read uses; the sender now shares that query and checks each
candidate on its conversation, so branching, unreadable and cyclic predecessors resolve as
before, and the second index and its commit bookkeeping are gone.
* Keep live workers' sender history between builds and re-read only what a write reaches
Any write to a Dispatch, worker terminal or remote attachment re-read the history of every live
terminal (three queries and the lineage reads per pane) on the main process: about 20 ms at 100
live workers and 150 ms at 1,000, for a write none of them read. The connection's triggers now
also record the panes and Dispatch ids a write's old and new rows name. The history keeps each
live pane's reads and each Dispatch's verdict with every key it read, lookups that found nothing
included, so a write re-reads only the panes and lineages it reaches. Federated Dispatches move
their own counter, so worker writes no longer re-read paired principals. A commit from another
connection, which no trigger sees, still rebuilds everything.
* CI: build each sender trigger from a typed event list so its SQL parts are plain strings
* CI: give startup runtime fakes the sender peer-key setter and drop new test type assertions for typed fixtures
* Ask the host to reveal a located sender this window holds no tab for, as the lookup did before
* Keep no worker history read inside an open transaction, and forget workers and keys no live pane reaches
* Test that sender names render only when what they show changes
* CI: pass the sender target's dispatch id explicitly and write a real sidebar body in the delivery test
* Read terminals' existing handles for sender rows instead of issuing them
The sender publication walked every live terminal through the runtime's handle-issuing functions,
so each display build could mint, adopt or rebind terminal handles. During a renderer reload or a
split close that changed which handle a terminal held and what retirement frames published. Sender
rows now read only the handles terminals already hold; a terminal with no issued handle has no row,
and no card can name it.
* Open a located sender's own pane through its host when this window has no tab for it
When a card's sender was found in a pane this window had not loaded yet, the click asked the host
about the card's saved terminal instead. For a worker reopened by a follow-up, that opened its first
terminal, or said the pane was gone, while the card showed the reopened worker running. The click
now opens that same pane: by the handle its status row holds on that host, else by asking the host
for that pane in the host's own coordinates. It checks the card again after the host answers, and a
closed pane says the agent is no longer running. The saved-address lookup stays only for senders no
host has located.
* Read a terminal's start-time handle for its sender row while no window graph exists
When the window graph went away, the host cleared its handle records but kept each terminal's
start-time handle, which its agent's mail cards save as the sender. The read-only handle lookup
required a record, so the running terminal lost its sender row and its cards showed no dot until a
window came back. It now returns the handle issuing would reuse, record or not, and still changes
nothing.
* CI: type the open helper's target as any runtime target so the paired-host case typechecks
* Lease the sidebar rows a sender name's link check reads, as its avatar does
A sender name drawn without an avatar (queued mail, a card's later senders) checked for a different
agent through a source nothing leased, so every store write rebuilt that worktree's sidebar rows.
The name's link now holds the same lease the avatar does, and a card with no saved agent kind
skips the row read entirely.
* Index a build's terminal handle records once instead of scanning them per terminal
The read-only handle lookup fell back to a scan of every handle record for each leafless terminal
holding no handle, on every sender build. A build now gets one reader that indexes the records on
its first miss and answers each terminal from that index, with the same handles issuing reuses.
* Lease a replaced card's sidebar rows from where its sender runs before the kind check
A card whose terminal now runs a different agent resolved no location, so it leased no row
source and rebuilt its worktree's rows on every store write. Both the avatar and the link now
lease from the candidate location the kind check reads; their answers are unchanged.
* Show a paired host's worker status dot on its card when this window mirrors the whole tab
A paired host names a pane <tab>:<leaf>; this window mirrors that tab whole as web-terminal-<tab>
with the leaf ids kept, and its status rows use that key. The alias projection mapped only
per-pane mirrors, so the card located the host's key and found no row to draw a dot from. The
terminal bucket now also maps a whole-tab mirror's host tab, and a host pane takes this window's
name from either form; two names for one pane still locate neither.
* Publish a chat sender change even when the terminal read in the same refresh fails
The chat rows and their key were stored before the terminal read; when that read threw, nothing
was published, and the next build saw both keys as handled, so the chat change waited for an
unrelated identity change. The refresh now publishes whatever changed beside the last good
terminal rows, and the read's error still reaches the build's warning.
* Bound sender projection work to current consumers and lineage facts
* Update runtime call assertions for sender demand options
* Preserve mobile sender navigation availability
* Open large pasted text and attached text in structured chats
* Read pending pasted text before its host route resolves
* Pass structured attachment eligibility from the owning chat
* Preserve composer and Markdown state when inspecting text attachments
* fix: preserve attachment identity and cancel deferred reads
* test: consolidate phone attachment rendering contracts
* Scope attachment previews to visible chats and share route indexes
* test: consolidate duplicate attachment preview coverage
* perf: share remaining workspace catalog derivations
* feat(chat): open text attachments from structured goal objectives
* fix(chat): reuse preview owner and bind app hooks
* refactor(chat): trim duplicate tests and unused capability initialization
* test(chat): share routing scope mount fixture
* Fix routing performance attribution and folder row imports
* Share attachment capability through its domain module
* Align attachment fixtures and warm routing contracts with current gates
* Preserve relay connection timeout default for ordinary requests
* Share image classification ownership and repair integration fixtures
* Repair real attachment integration fixture boundaries
* Expose e2e compiler diagnostics and prune stale read allowance
* Type the recall fixture row ref as a div
* Keep text attachment capability in its existing capability owner
* Keep image MIME bindings in the media type owner
* Own private bridge response completion at the request boundary
* Complete bridge fixture return and retention types
* Localize native chat text attachment preview controls
* Complete attachment preview localization at presentation boundaries
* Preserve legacy preview locale identity and complete localization controls
* Fix typed mobile host witness lookup
* Commit attachment page edits and reset mobile page scroll
* test(chat): remove duplicate preview localization coverage
* fix(mobile): apply page input font and footer safe area
* fix(chat): commit edited page before admitted navigation
* fix(chat): retain field readiness on pending commit
* fix: preserve attachment field focus until control activation
* fix: restore attachment preview styles and canonical close
* Bind mobile input font role to the central theme
* Type font source fixture cases as tuples
* Attribute inherited owner filter work and qualify folder fixtures
* Keep owner filter fixture input types source-derived
* test: retain attachment capability assertion import
* test: focus attachment coverage on important regressions
* Replace text attachment paging with bounded scrolling and trim tests
* Preserve literal phone attachment whitespace and trim unused test meter
* Keep scroll view refs and measurements out of render
* Keep preview collection independent of native clipboard initialization
* Give the phone scroll fixture coherent measured DOM geometry
* Commit attachment scroll extent before restoring its anchor
* Preserve text viewport geometry across bounded reads
* Unify bounded text scrolling around the viewport
* Preserve the live text anchor across viewport resizing
* Measure committed text viewport bounds from the host
* Preserve live attachment position across native client extent changes
* Use the actual first source block in the resize regression fixture
* Reuse subscription handle type
* Keep attachment effects keyed to their existing triggers
* Keep attachment rows within the committed track
* Allow the full attachment renderer contract to settle
* Open text attachment previews in a large modal
* Preserve attachment modal header layout with primitive-owned styles
* feat(browser): guard page commands with an expected URL
* fix(browser): refuse an empty --expect-url and check it on dialogs and the forwarding desktop
* fix(browser): recheck the expected URL right before keys go out
* refactor(browser): drop duplicate session type, dialog alias and per-capability sidecar fields
* chore(browser): satisfy the changed-code gates for the expected URL guard
* Preserve open overlays when focusing the chat composer
* Fix chat composer focus after launch menus close
* Fix chat composer focus handoff after overlays close
* Fix composer focus after custom overlays close
* Prevent chat composer from stealing overlay focus
Scope recovery overlays to their own pane and let menus dismiss before
returning focus to the composer. This keeps the quick launcher open
when delayed chat actions complete.
* Fix composer focus across nested overlays
Track focus ownership through portaled overlays so the launch prompt can
regain focus while its model list is open. Close the context menu before
inserting a quote so the caret lands after it.
* Fix overlay focus CI regressions
* Complete overlay focus ownership for inline and retained surfaces
* Declare public overlay focus hook return type
* Keep review note changes on their captured workspace owner
* Keep review note actions on the copy whose notes are shown
Review notes now read their owner and their notes together, so an action
always changes the copy the user is looking at:
- A paired SSH copy saves through its server even when its row does not
name the server, instead of saving on this computer.
- The Markdown preview shows and edits the selected copy's notes, not the
first copy listed with the same workspace id.
- While the selected copy is not listed yet, no other copy's notes are
shown; a note started then saves to that copy once it lists.
- A listing that stamps the same copy's host no longer looks like a new
copy: a pending Send stays held and unsaved note edits are kept.
- Clear all / Clear file confirmations stay on the copy they opened on
when the selected host changes.
- A copy removed since the user acted reports the existing save or clear
failure once instead of failing silently.
- Mounted note views skip ownership work on store updates that cannot
change it, and do not re-render for another copy's changes.
* Keep review notes on the exact workspace copy each surface shows
Notes, their owner and every note action now come from one copy identity.
Previews and editors of a server's copy read and save that copy, paired
SSH copies keep working through their server, an SSH draft never lands on
a local row, and controls stay disabled instead of claiming "All notes
sent" while a copy's notes are unknown. Open Clear confirmations share the
cached read, so unrelated store writes do no row work.
* Resolve review-note copies through the shared workspace ownership rules
Every listed row now gets its copy from the same rules the app routes
writes with, including server provenance from detected listings and the
SSH place behind a paired server for older rows without host stamps.
Previews, editors and diffs read notes from their own tab's provenance
instead of the selected copy, folders honor their source's host, and a
note composer's shortcut captures the copy its surface shows when it
opens.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Keep folder review notes on the folder copy their source names
A folder's notes now come from the same source rules as worktree notes,
so a file from this app never shows or saves to a server's folder with
the same id. Queued folder saves and rollbacks check the captured folder
copy the same way reads do, and resolving copies no longer rescans the
project list for every row.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Read review-note copies through the shared id indexes
Folder and worktree note views now read only their own workspace's
catalog entries from the shared indexes, and readers of one folder
share its qualification, so listing updates cost work proportional to
what is shown rather than catalog size times readers. Also fixes the
type errors and the end-to-end note seeds, which now pass the owner of
the worktree they seed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Share review-note copy resolution across rows and readers
Rows of one workspace on the same host now share a single ownership
answer per catalog snapshot, so duplicate listings of an SSH worktree
no longer make every note view rescan its peers. Folders that are not
listed return one shared answer instead of leaving cache entries behind.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Name the catalog snapshots review-note ownership results are shared under
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Save renamed-file drafts under the new path and encode restored SSH targets
A diff note draft opened before its file was renamed in place now saves
under the file's current path, still on the copy it was opened on. A
restored SSH file whose target id needs encoding now shows and saves its
own copy's notes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Update the diff note path ref after render instead of during it
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Add standalone chat right-click session actions
* Update fork draft fixtures for source focus callbacks
* Read chat menu data only while the menu is open
Quick Commands and the provider Copy Session ID now read their data from
components that mount only inside the open chat menu, so closed menus in
retained chats do no work on repo, project or agent-status writes. The
add-command editor reuses the terminal's editor dialog and outlives the menu.
Chat menus also stop showing the Insert hint, since they run every quick
command in a new tab the way the tab bar's Quick Commands menu does.
* fix(native-chat): let createSupport ask whether another terminal runs a resumed conversation
A resume's createSupport can now carry resumeFrom (behind
agent-session.structured.resume-writer-admission.v1, since older hosts'
strict params reject it). The host runs the same writer check create runs,
leaving out the panes the client will close first (matched by key or by
the PTY they resolve to; a shared tmux/OpenCode server is never left out),
and probes the candidates together so a bounded client wait is not spent
on one probe after another. The host's English refusal says "another chat"
only when it names one. The resume params move to their own module to keep
the params file under its line limit.
Tracked in STA-13440.
* fix(native-chat): refuse a resume before anything closes or opens when another terminal runs it
Continue in Chat UI asks the host before closing the terminal, naming the
panes the close takes; when another terminal runs the conversation it says
so in one toast and leaves the terminal open with no chat. Session History's
Resume in New Chat (and any other resume launch) asks through the launch
admission and, on that refusal, opens no placeholder tab: its caller's one
toast is the only notice. A local admission that times out still never
leads to a close. Older hosts without the capability keep today's flow.
The launch admission's toasts move to their own module to keep that file
under its line limit.
Tracked in STA-13440.
* fix(native-chat): say why a resumed chat failed when a terminal holds it or its history is missing
A failed start refused because a terminal's agent still runs the
conversation (no chat named as holder) now reads the existing "already
running this conversation in another terminal" words instead of a bare
"Chat could not be started.". A transcript the host could not find yet gets
the same history words an unreadable one already had. This covers the
create-time backstop: a terminal started between the pre-check and create,
or an older host without the pre-check.
Tracked in STA-13440.
* fix(native-chat): keep exporting ResumeSource from the session params module
* fix(native-chat): keep a terminal open when its host's resume check could not be confirmed
A failed capability read was taken as an older host, so the resume question
was left out, the host admitted, and the terminal closed before create refused
the conversation another terminal runs. An unread capability now leaves the
resume unanswered; a host that reports an older capability list keeps its path.
* fix(native-chat): say "another terminal" only where the refusal's owner is still known
The write failure drops the refusal's owner, so a chat-owned conflict on a
send, mutation or phone notice read as a terminal. Only the failed start,
which keeps the raw refusal, now records that no chat was named; everywhere
else keeps the generic wording.
* perf(native-chat): resolve panes in the writer check only when some are left out
Every create, resume and acquire check resolved each matching row's pane to
its PTY, even with no panes to leave out, and each unresolved key scanned
every terminal. With nothing to leave out no pane is resolved now; with some,
one identity read context serves every key.
* test(native-chat): pin createSupport's resume refusal to create's, and History's one notice
Runs the real createSupport handler on a runtime whose status store proves
another terminal live: leaving out the source pane admits, otherwise it refuses
with create's code and details. The Session History replacement keeps its chat
and toasts once when the host refuses before anything opens.
* fix(native-chat): translate the "another terminal runs this conversation" toast
It is now the only notice when Continue in Chat is refused before the terminal
closes, and only English carried it, so every other language showed English.
* fix(native-chat): withhold an unread resume capability only where a terminal closes next
Reading an unknown capability as unreachable refused Session History and
/resume launches on a paired host that main admits and create completes. The
host question now asks the plain question on an unread capability and says so
on its answer; only Continue in Chat, which closes the terminal next, treats
that answer as not admitted, from the same read that chose the request.
* test(native-chat): count the writer check's terminal reads with a typed map
The perf contract counted iteration through a proxy, which the type-aware lint
rejects. It now counts record reads on a Map subclass; a scan of every
terminal per row still shows up as rows times terminals.
* test(native-chat): read the writer-check fixtures without type assertions
The changed-code gate rejects casts. The perf contract builds real terminal
records through the identity fixture, and the createSupport parity test reads
create's refusal through the shared refusal parser.
* fix(native-chat): declare the refusal holder that failed-start cause words read
The failed chat's notice passes its launch failure, with the holder its
refusal named, through the cause parts to the words that tell a chat from a
terminal. Those functions now declare that field instead of carrying it
undeclared, which the typecheck rejected for a literal in the test.
* perf(native-chat): probe a conversation's writers a few at a time and stop at a holder
The writer check started a process probe for every matching row at once and
kept them all running after the first live holder refused. It now picks the
rows in one synchronous pass, probes at most eight at a time through the
shared bounded pool, and starts no probe once a holder refused.
* test(native-chat): pin the writer check's single terminal look on the real runtime
The scale contract built its own resolver, so a host that made an identity
read per pane, or passed none, still passed. It now runs the runtime's own
writer check over recorded terminals and counts read contexts and per-key
terminal scans: one context and no scans with panes to leave out, none
without.
* test: remove 25 low-value checks and six complete suites
* Remove deleted startup benchmark from plugin CI routes
* Remove CI route for deleted pet layout smoke suite
* test: repair retained E2E labels and collision lifetimes
* test: remove synthetic activation collision scaffolding
* fix: activate folders opened on the selected runtime
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
wsl-host-paired-phone asserted the pre-#36771 'isn't running' copy; it now
asserts the stable remote_runtime_unavailable code and '<distro> is stopped'.
wsl-move-dialog's gate-closed case seeds a saved host, which since #34683 puts
the app in serve-only: the WSL hosts section still lists the host. Assert
instead that Add is hidden and the host row's menu has no move entry.
Co-authored-by: Claude <noreply@anthropic.com>