* perf(mobile): switch back to a terminal without rebuilding it
* fix(mobile): keep resume positions across terminal handle swaps
* fix(mobile): snapshot a cleared, reloaded or errored terminal instead of resuming it
* fix(mobile): cancel only resumable streams on a dropped connection and forget positions on a text-size change
* test(mobile): give the startup recording its catch-up read
* test(mobile): give terminal webview harnesses the resume state
* fix(runtime): end resume for a stream that saw its coverage reset while live
* feat(mobile): offer to restore unsaved file and markdown edits
* fix(mobile): keep offered edits through other discards and clear saved Markdown drafts
* fix(mobile): offer a copy of edits to a now read-only document and key drafts by host
* refactor(mobile): one guard for the draft save effect
* fix(mobile): clear an offer once its edits are saved by hand
* feat(mobile): keep automation drafts across kills
* fix(mobile): drop a created automation's draft on affirm and restore saved fields under typed ones
* fix(mobile): stop saving an automation draft after it is dropped
* fix(mobile): reopen the automation editor with in-memory edits while the store can't be read
* refactor(mobile): one rule for which automation draft fields changed
* perf(runtime): push worktree row changes; host list poll becomes a 10 s backstop
* fix(runtime): announce title-only agent status changes and gate the rows capability with the switch
* fix(mobile): keep event reads a floor apart while a read is out; announce a retired title clear
* test(runtime): assert the rows notice without counting events
* feat(mobile): keep screen data on the phone between launches
* feat(mobile): keep the repo list snapshot id across launches
* fix(mobile): don't read a key again that the boot read just found empty
* fix(mobile): late-restored strips, revocation fence and reads never built on stored data
* test(mobile): give the session startup recording the late strip watch
* fix(mobile): remember Workspace options, keep the revocation fence until reauth, store no terminal output
* test(mobile): give the view settings recording its remember hook
* docs(mobile): say what a restored key means to a fetch
* style(mobile): format host-query after rebase onto Q11
* refactor(main): organize runtime implementation owners
* test: retire wall-clock CLI title recovery case
* refactor: route new folder mutation to runtime store owner
* test: import folder mutation store contract from its owner
* perf(mobile): open the PR tab with its last state and refresh only what a write changed
* fix(mobile): allow the phone's comment re-read and settle review findings
* fix(mobile): keep PR reads current across path switches and overlapping writes
* refactor(mobile): share PR query keys and simplify PR write rollbacks
* chore(mobile): list every PR action and comment write kind explicitly
* fix(mobile): read the push-time PR reread through an effect event
* fix(mobile): report a comment write interrupted by a path switch as unconfirmed
* fix(mobile): settle a comment write whose reply was lost from the re-read comments
* style(mobile): format host-query after rebase onto Q12
* perf(mobile): show the last task list per filter while it refreshes
* perf(mobile): read Tasks repos six at a time
* fix(mobile): hold Tasks paging while kept rows re-read
* test(mobile): pin Tasks paging held during a query switch
* perf(mobile): read Tasks repos four at a time, the desktop's gh limit
* test(mobile): give the Linear connect recording the revalidating input
* perf(mobile): open Tasks on its kept hydration and lists through host query families
* fix(mobile): keep the desktop's newer Tasks state and only cancel screen-read queries
* fix(mobile): type the Jira refresh harness and Tasks list read for CI
* feat(runtime): confirm a structured chat send by clientMessageId past the first journal page
* fix(mobile): ask the send's own chat before handing it back
* fix(mobile): read send-recorded support when the deadline fires and settle rows that land mid-lookup
* fix(mobile): re-subscribe Home and the follow-up preference after the client event stream ends
* fix(mobile): try a refused client event wire once per connected edge
* refactor(mobile): mark replayed client event readies in the shared stream
* test(e2e): give the phone feed socket client a state listener
* fix(mobile): re-probe an empty "+" agent list and derive the sheet state
* refactor(mobile): mark the agent refresh sent from the transport's beforeSend
* perf(mobile): tick only agent rows on the host list and keep repo looks across polls
* fix(mobile): refresh the shared clock when a list comes back within one interval
A clock stopped less than one interval ago kept its old time and started a new full interval, so a quickly reopened host list could show agent ages up to about a minute old.
* fix(mobile): share bundle read slots per connection and keep a waiting page update across relaunch
* fix(mobile): keep a page's update check across its document start
* fix(mobile): wait out a same-build update fetch and keep shared read slots from stalling
* fix(mobile): trust a waiting stage only when every asset is on disk at full size
* fix(mobile): count late window replies as connection activity
* fix(mobile): keep the launch sweep going when one host's stage is unreadable
* refactor(agent-session): split subscribe params and read failure text into their own modules
Both host files sit at the 300-line budget, so the append negotiation that
follows needs room. Pure moves: SubscribeParams keeps its exact schema (now
z.object + sessionId instead of OptionsParams.extend, which is equivalent) and
is re-exported from the params module; stream failure text moves beside the
other read-refusal classification.
* perf(agent-session): stream running tool output heads as appends
A running tool call re-sends its whole output head (up to 16KB) on every
revision, and keeps re-sending the saturated head after it stops growing.
Streams that also ask for toolOutputAppend (host advertises
agent-session.tool-output-append.v1) now get only the head's new text under the
same shared sender/reader rules and self-healing refusal as reply appends.
- The live read negotiates the exact subscribe capabilities object instead of
a boolean; mobile asks for tool output appends when advertised.
- Hosts with only text-append.v1 drop the unknown key, so clients ask only
when the new capability is advertised and both ends track the same bases.
- Text-only streams keep the 8-base limit already-shipped readers evict at.
- A host that refuses the capabilities param (an older build after a
downgrade) makes the next open go without appends instead of failing forever.
* perf(native-chat): ask remote hosts for streamed text appends on desktop
Desktop chats on a paired or SSH-managed orcad received every streamed reply
checkpoint whole: about 9x the reply's bytes at the Claude/Codex checkpoint
cadence, and O(N^2) for ACP/JSONL providers that rewrite each 60ms window.
The desktop read now asks environment hosts for reply and tool-output appends
when they advertise them, reusing the shared reader that rebuilds whole items
before the reducer. Local IPC reads are unchanged and still subscribe in the
same turn. The support read runs once per chat run, overlapping hydration.
* refactor(remote-runtime): share compressed frame inflate across client platforms
Move the length checks and decode of paired E2EE compressed frames into
the shared module behind a small gzip/UTF-8 codec, so the desktop can
read them with node zlib while mobile keeps its native/fflate path.
* perf(remote-runtime): read compressed frames from paired hosts on desktop and CLI
Desktop and CLI sockets to orcad/orca serve now advertise
transport.compressed-frames.v1, so a v2 host gzips large text replies and
terminal output before sealing them, as it already does for phones.
- Every Node client transport (one-shot requests, request connection,
shared control, subscriptions) opens frames through one sealed-frame
reader that inflates compressed frames on v2 channels, synchronously so
frame order and v2 counters stay in arrival order.
- A compressed binary frame may claim up to the 8 MB binary outbound cap
(terminal frames can exceed the 4 MB JSON cap), for phones too.
- ORCA_DISABLE_MOBILE_COMPRESSED_FRAMES=1 now also stops a desktop or CLI
from asking for compressed frames.
- Relayed phones and the browser client are unchanged.
* refactor(remote-runtime): simplify the mobile inflate codec and clarify capability comment
* fix(remote-runtime): name why a sealed frame could not be read
Text-only sockets report an authentic binary payload as an unexpected
binary frame again, and tell a decrypt failure apart from a corrupt
compressed frame, instead of calling every failure undecryptable.
Shows CI result lines in the chat that opened or pushed to a pull request. They're hidden in the terminal overlay and on the phone until the phone app gets the setting.
* perf(mobile): show the workspace list from memory and refresh it on desktop changes
* fix(mobile): import the host list queries type without an import() annotation
* fix(mobile): keep host labels on a not-connected read and update the phone feed e2e helper
* fix(mobile): keep the event router listening when its stream ends while opening
* fix(mobile): reuse the shared read-view base and remount for the cache-return recording
* fix(runtime): keep a terminal's last output on exit and stop charging dropped screencast frames
* fix(browser): clear an oversize frame held for credit instead of retrying it
* fix(mobile): keep held model lists through late preloads and running chats
* fix(mobile): let progress answers fill empty lists and decide recording per read
* fix(mobile): record a pre-send listing on rejoin and leave unheld retirements alone
* test(desktop): use a valid listed catalog in the preload race test
* test(mobile): type the catalog cache test's renderer
* fix(mobile): stop false Wi-Fi arrivals and update the relay gate text
* refactor(mobile): read the network fresh for every caller
* perf(mobile): share a network read within one nudge fan-out
* fix(tasks): confirm a lost Tasks comment by author on GitLab and GitHub REST reads
Only GitHub GraphQL's viewerDidAuthor marked the viewer's comments, so on GitLab,
the GitHub REST fallbacks (including issues with more than 100 comments) and the
gh view fallbacks the phone kept an unconfirmed draft even after the comment
posted. Those reads now match the login of the account that made them, and an
explicit PR refresh reads comments uncached.
* fix(mobile): settle an unconfirmed comment only on one posted after the send
A refresh of an issue with more than 100 comments reads comments the first
load never showed, so an older identical comment by the same account looked
new and could clear the draft.
* refactor(gitlab): share the glab viewer read and skip it on Checks polling
* test(mobile): pin the clock in the unconfirmed comment test
* fix(mobile): retry a failed Changes compare and drop preserveReadyOnFailure
A compare that failed, or one cleared by a worktree switch, kept its status
read marked as compared, so returning to Changes inside the 3 s fresh window
skipped it. Forget the read when its compare doesn't land and when the route
identity changes. Branch compare already always kept a ready result on
failure, so the loadStatus option and nextBranchCompareState flag were dead.
* fix(mobile): keep a superseded compare from clearing the retry marker
* refactor(mobile): forget a failed compare's read inside the attempt
* fix(mobile): clear the compare marker in an effect, not during render
* perf(files): page large folders on the phone instead of reading them whole
* fix(files): page from hasMore, refresh closed folders, retry a superseded Show more
* fix(files): rerun a refresh that paging displaced, and keep an old host's whole folder from duplicating rows
* test(mobile): re-record the Files matrix goldens for paged reads
* test(files): type the paging fake host's params without widening
* fix(files): filter folder reads that land after the folder closes
* feat(mobile): add host mutations with draft, block and queue modes, starting with rename
* fix(mobile): settle a lost rename through the reconnected client and keep server rows routed
* fix(mobile): offer Retry on the offline banner once the host is unreachable
* fix(mobile): let the offline banner's Retry redial from the page
* fix(mobile): date the offline banner from the drop, not the connect
* fix(mobile): keep the terminal rename sheet's state updates pure
* test(mobile): mount rename and close-action tests inside a query client
* refactor(mobile): share one draft rename sheet between workspace and terminal rename, and retry a confirm after a path switch
* fix(mobile): keep another target's unsaved rename and show the offline reason over an old refusal
* fix(mobile): keep a newer rename draft when an older save lands late
* feat(mobile): queue chat sends while the desktop is offline
* test(mobile): cover the offline chat send queue
* fix(mobile): drop a closed chat tab's queued messages
* fix(mobile): keep offline queue order and hold drains behind terminal prompts
* fix(mobile): drain a structured chat's queue only once its session loads
* test(mobile): stub reanimated in the prompt controller render mocks
* feat(mobile): bring a queued chat message back paused after Orca closes
* fix(mobile): update the queue's send ref after render and type the queued bridge test
* fix(mobile): keep the queued send intent type free of page storage imports
* test(mobile): pass a send's chips through its intent in the kill test
* fix(mobile): hand a queued host command with a lost reply back to its queue
* fix(mobile): chat page follow-ups
- clear the touch state when the chat hides, so a held reply lands on return
- keep the chat pinch scale per chat
- record waiting display-math openers in the math plugin instead of a line regex
- share the details markup test and the orphan row id predicate
* fix(mobile): record math openers whose scan reaches the end, skip no-op pinch commits
* fix(mobile): fall back to a whole parse only for details section tags
* refactor(mobile): drop a repeated comment
* perf(mobile): open Jump back in and notifications inside the host document
* fix(mobile): gate open targets on page 3, keep notification suppression, fold double taps
* fix(mobile): report the shown session from host documents and only open this host's sessions
* test(mobile): ignore the page's location report in the agent-history notify check
* fix(mobile): let a Back before the paint gate settle the host stack
* refactor(mobile): build the route-param clear frame beside its name
* perf(mobile): let the model pill take picks before the chat attaches
* fix(mobile): lock the picker while a held pick is sent and keep the mode toggle for attach
* fix(mobile): report a held pick's refusal only for its own chat
* feat(mobile): keep chat drafts and unsent text in the device store
* test(mobile): give the send tests a real draft destination
* fix(mobile): confirm reopened sends past the loaded window and save the journal id with the clear
* fix(mobile): let an open chat claim a released send, and warn on a reopened command
* refactor(mobile): share the pausable unconfirmed-send deadline between chat holds
* fix(mobile): hold every lost structured send and replace a re-held deadline; use the shared store value codec
* fix(mobile): save chip-only drafts, save only a send's own chips, and keep hold time across outages
* fix(mobile): hash a draft key the device store would refuse as too long
* fix(mobile): drop a sent message's chips in the write that settles it
* fix(mobile): return a structured host command whose reply was lost to the box
* perf(mobile): route the last status.get callers through the shared status read
* refactor(mobile): drop the unused one-shot Codex reset capability read
* fix(mobile): open the chat transcript when the text-append check fails, and key connections on one epoch
* perf(mobile): open a session without the startup terminal polls
* test(mobile): re-record session startup goldens
* perf(mobile): cache the session strip from host snapshots and drop phone-closed tabs
* fix(mobile): keep a shown terminal over the offline and loading body states
* test(mobile): re-record the last-strip reopen golden
* refactor(mobile): drop a startup guard that can no longer fire
* fix(mobile): drop a pending-terminal activation reply from an earlier route
* test(mobile): type the pending terminal tab fixture
* test(mobile): import the last-tabs module type without an import() annotation
* perf(mobile): reopen agent history from memory
* fix(mobile): reread history after association changes without restarting reads, and share the connection's status with query reads
* fix(mobile): reread history after an association change only when the query can read, including after a failed scan
* refactor(mobile): name every history screen state
* fix(mobile): keep history's connected-edge watcher by not gating its query on the connection
* perf(mobile): prefetch the next and previous file in Review
* perf(mobile): open Review on the tapped file without reading the first file
* fix(mobile): show failed Review diff reads and re-read refused deleted files
A re-keyed worktree diff that fails now shows its error instead of the
older lines. A deleted-file stand-in from a refused read is re-read on the
next visit and by Retry. Without git status, the branch section no longer
waits on an unused compare.
* fix(mobile): remount silently after background WebView losses
* fix(mobile): hold a reclaimed remount until the app is in front
* fix(mobile): give a reclaimed renderer one free remount per painted document
* fix(mobile): report a dead Android renderer again with its original loss facts
* refactor(mobile): build the page update-failure record in one place
* fix(mobile): declare desktop-bound native verbs in the verb table and let the device store skip the verdict hold
* refactor(mobile): name the update-failure record builder after the effect it returns
* test(mobile): check the device store read before the verdict actually succeeds
* test(mobile): leave the store-verb hold test to its own PR
* fix(mobile): stop a session opened on a pane from faulting the page
* test(mobile): check the opened pane leaves the session URL
* fix(mobile): type the session's own navigation for the pane erase
* feat(mobile): persist TanStack queries through the device store
* fix(mobile): refuse query storage keys the store verb would reject
* fix(mobile): skip re-encoding oversized query records and guard long keys on remove
* fix(mobile): keep the query storage flush chain alive when a write throws
* refactor(mobile): share one store value codec and hash query store keys
* refactor(mobile): check stored query records with a type guard
* fix(mobile): replay a page's streams only after its connection verdict
A reconnect or a cutover after a drop re-sent every stream the page held
before the page's verdict for the new connection, bypassing the bridge's
hold. The client now asks the stream's owner before re-sending; the bridge
holds the re-send until the verdict opens. An unsent stream's cancel no
longer sends an unsubscribe.
* test(mobile): expect the replay hold on a page stream's subscribe options
* refactor(mobile): one subscribe options type and one pass-through rule for the verdict hold
Count a key changed twice in one write once, keep the per-bucket estimate an upper bound, and redo a seed pass that missed files at the next foreground instead of trusting it as exact.
The page store refuses a bad key or an over-cap value before posting anything, keeps its calls in call order and inside the bridge's in-flight cap, and checks deferred slots. The shell reads only the keys that surely fit the reply budget, so no value is decrypted twice.
* Prepare queue rows to preserve accepted delivery intent
* Keep waiting native chat input in one ordered queue
* Keep a typed view of admitted queue records
* Keep the removed queue caption in the runtime catalog
* Remove the unused queue barrier caption
* Keep queue writes local and preserve accepted send provenance
* Read the sender from the queued admission request
* Keep continuation fixture clock within its operation window
* Remove deleted queue-barrier test from ratchet baseline
* Keep ratchet baseline change scoped to the deleted test
* Filter historical acceptance reads before loading payloads
* Instrument cached acceptance cursor once per fixture
* Restore original personal provenance after legacy card cleanup
* Complete legacy sender fixture metadata
* Narrow admitted history record types
* Reconstruct accepted personal proof after restoring original admissions
* Use the fixed clock for historical queue fixtures
* Consolidate queue source and type imports
* Preserve admission refusals and failed startup ownership
* Keep manual queue holds independent of later turn endings
* Remove obsolete mobile queue barrier expectations
* Keep journal format initialization independent of its decoder
* Assert returned-row recovery for released send clients
* Preserve Stop assertion across handoff-only publication