Commit Graph
1312 Commits
Author SHA1 Message Date
Brennan Benson d0bfbd22ac Keep host-removed rows out of desktop and phone chats (#34996)
* Keep removed chat rows out of coalesced updates

* test: bound destructive history burst work

* test: verify removed history through transcript projection

* test: count retained row reads with typed getters
2026-10-28 13:50:25 -07:00
Neil 7b3fb541f4 Built-in syntax highlighting for .env files (#34542)
* feat(editor): built-in syntax highlighting for .env files

.env, .env.* and *.env files now open as a dedicated dotenv language with
comment, key, export, value, quoted-string and ${VAR} colouring instead of
INI. .envrc opens as shell, since it is sourced as a shell script.

* fix(mobile): map dotenv to the ini grammar for mobile highlighting

* fix(editor): keep quotes after the first dotenv value character literal
2026-10-28 13:40:03 -07:00
Kelvin Amoaba 6c54b4fac5 fix(mobile): show the chat mic busy while a stopped dictation transcribes (#35320)
Fixes #35313
2026-10-28 20:38:01 +00:00
OrcaWinandOrcaWin 33800f8c8b fix(mobile): stop bundle work after caller cancellation (#34793)
* fix(mobile): stop bundle work after caller cancellation

* test(mobile): use a type import for the fflate mock

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:37:53 -07:00
OrcaWinandOrcaWin 9fecb29aa9 fix(mobile): batch notification catch-up ledger writes (#34785)
* fix(mobile): batch notification catch-up ledger writes

* test(mobile): use a fixed expiry in catch-up storage test

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 13:37:47 -07:00
Kelvin Amoaba 88662806c0 fix(mobile): explain dictation setup before asking for the microphone (#35248)
A mic tap opened capture, and with it the OS permission prompt, before
anything asked the host whether it could transcribe; the setup sheet only
appeared after the host refused dictation.start. The session screen now
gates the start on the setup read it already does, opens the setup sheet
when setup is missing, and hands the next tap back to the host and re-reads
when the sheet closes. A host that never had a model selected now offers
the mic. The sheet's switch uses MobileSwitch.

Fixes #35203
2026-10-28 20:14:39 +00:00
Kelvin Amoaba 1f45c87c50 fix(dictation): say dictation is in use elsewhere instead of dictation_already_active on desktop (#35269)
Move the host dictation error map from mobile to src/shared so the desktop start toast and the phone read the same sentences.
2026-10-28 20:10:43 +00:00
OrcaWinandOrcaWin 7d29cd0839 fix(mobile): recover host profile reads without discarding cached bundles (#34806)
* fix(mobile): retry unavailable host profiles without discarding cache

* fix(mobile): cancel startup work on terminal shell failures via flow advance

Merging main pushed use-mobile-web-shell-session.ts over max-lines; move
the host-profile cancellation into the reducer so the flow-change cancel
path from #34780 handles it.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:48:17 -07:00
OrcaWinandOrcaWin e0420b3b58 fix(mobile): skip queued generation stages after cancellation (#34809)
* fix(mobile): skip queued generation stages after cancellation

* test(mobile): fold canceled queued-stage case into download suite

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:48:11 -07:00
OrcaWinandOrcaWin d4b6e928ac fix(mobile): index reusable bundle assets once per generation (#34789)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 12:48:05 -07:00
92a754a088 fix(mobile): suspend hidden and background terminal gestures (#31468)
* fix(mobile): suspend gestures in hidden and background terminals

Adapt the retained-pane interaction lifecycle from community PR #30324.
Restore policy across readiness/recovery and keep output/query replies flowing.
Release cancelled gesture frames, discard touches interrupted by suspension,
and restore the resting pinch transform on every gesture cancellation.

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Neil <nwparker@users.noreply.github.com>

* test(mobile): stub route focus where the web mount renders terminal panes

* test(mobile): send production-shaped file taps and the clipboard prop in activity tests

* fix(mobile): keep inactive and interrupted terminal moves away from xterm

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
Co-authored-by: Neil <nwparker@users.noreply.github.com>
2026-10-28 18:53:58 +00:00
6caa44eefb fix(mobile): keep the terminal reading position when resize snapshots overlap (#31350)
* fix(mobile): keep the reading position when resize snapshots overlap

A snapshot that overtook a hidden replay took its scroll anchor from the
hidden terminal, which sits at the bottom, so the reader jumped down. The
newer replay now keeps the anchor the overtaken one would have restored,
unless live output, a clear or an alternate screen made the hidden buffer
the source. A superseded replay also hands the live terminal back before
theme painting reads it.

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: ogarciarevett <ogarciarevett@gmail.com>

* fix(mobile): keep the overtaken anchor when live output arrives during a replay

* test(mobile): use T[] for the replay harness completions

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Co-authored-by: ogarciarevett <ogarciarevett@gmail.com>
2026-10-28 18:38:00 +00:00
Neil 80bbbaff7f refactor: give native chat readability one concrete owner (#35231) 2026-10-28 11:28:03 -07:00
Brennan Benson 28d6883756 fix(mobile): grey the queue's other controls while Clear all or Resume is on its way (#29219)
* feat(native-chat): one queue header that becomes the pause row; no composer Resume or send dialog

The queued cards now sit under one header row on desktop and phone: "Queued"
and the count normally, and "Paused" with the count, Clear all and Resume
while the host holds the queue after a Stop. A chevron folds only the cards;
the choice is local to the view and resets when the queue empties.

The composer's Send no longer turns into a second Resume, and a message sent
into a paused queue no longer asks "Send message?": it sends, its accepted
turn lifts the pause, and the cards follow it. Clear all deletes every card
through the existing per-card delete. No wire or host change.

* test(mobile): find the background-tasks strip's toggle inside the strip, not the queue header's

* Make queued Clear all atomic across clients

* Show queued message failures in collapsed headers

* Use per-card delete for paused queue Clear all

* Join repeated paused queue Clear actions

* fix(mobile): grey the queue's other controls while Clear all or Resume is on its way

On the phone, Resume and each card's Steer and Delete stayed tappable while
Clear all was still deleting the cards, so Resume could start sending cards
Clear was deleting, and a card's Steer could race its own delete. Clear all
and Resume now share one in-flight key, so each greys during the other, and
Clear all holds every card it deletes, leaving out a card whose own action
is already running. Same mechanism as the desktop fix.

* fix(mobile): wait for pending cards before clearing the queue

* style(mobile): format queue control contract test

* fix(mobile): Clear all and Resume share the queue's pending key, as on desktop

Clear all holds every card it deletes and greys Resume until it settles, and
waits for any card's own action instead of starting over it.

* test(mobile): bound queued message conflict work
2026-10-28 11:08:46 -07:00
844c7f6d96 fix(mobile): preserve Korean 10-Key live-input syllables (#31388)
* fix(mobile): preserve Korean 10-Key live-input syllables

Hold unsent conjoining jamo until committed so grapheme-deleting editors do not erase preceding syllables. Based on community PR #24821; verified real current iOS shell keyboard taps and actual Claude PTY replay.

Co-authored-by: Hojin <hojinkim971597@gmail.com>

* test(mobile): cover held Korean jamo editing boundaries

* test(mobile): keep held-jamo commit tests that add coverage

Boundary cases (Tab, accessory Enter, external send, tab switch, disconnect) already run through the existing held-text tests; the jamo hold reaches them the same way.

---------

Co-authored-by: Hojin <hojinkim971597@gmail.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-28 18:07:21 +00:00
NeilandKelvin Amoaba e0b5a42852 fix(mobile): handle invalid pairing links and start fresh for each invite (#31705)
* fix(mobile): validate pairing routes and isolate invite lifetimes

Repeated code parameters crash parsing, and replacing an invite retains old attempts and callbacks. Validate route input and key confirmation state by invite; allow confirmation content to scroll on short screens.

* fix(mobile): retire pairing immediately when Back is pressed

* fix(mobile): keep the pair confirmation layout unchanged

The ScrollView wrapped ConnectionLog's own vertical scroller without nested
scrolling on Android and was not needed for the invite-lifetime fix. The
repeated-code case is covered by the route-state test.

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-28 17:57:24 +00:00
Kelvin Amoaba 49e53bd345 fix(mobile): greet a just-started terminal Claude with "Start a chat" (#35219)
Claude reports its session at startup but writes no transcript until the
first prompt, so the host answers pending and the phone said "Can't find
this conversation yet". A session the running agent reported live is new;
only remembered sessions keep the not-found copy.
2026-10-28 17:41:03 +00:00
Jinjing 117bbc48e6 Extract mobile native chat prompt controller (#34244) 2026-10-28 10:36:44 -07:00
Kelvin Amoaba 7951f8fe51 fix(mobile): keep dictated words through calls, busy taps and failed inserts, and say why dictation failed (#35216)
* fix(mobile): keep dictated words through interruptions, busy taps and failed inserts

A call, Siri or mic dropout now finishes the dictation instead of
discarding it, a tap while transcribing no longer cancels, a transcript
its target refuses is copied to the clipboard with a toast, and host
dictation error codes show as plain sentences.

* test(mobile): share one session dictation harness for refusals and kept transcripts

* refactor(mobile): share the lost-session dictation sentence and keep speechless helpers private

* fix(mobile): keep a dictated terminal transcript when the live send throws
2026-10-28 17:34:33 +00:00
Neil 49695f37b1 refactor: group native chat subagent transcript rules (#35200) 2026-10-28 10:24:47 -07:00
Kelvin Amoaba 247035b026 fix(mobile): give phone audio back when dictation stops, and fail clearly when iOS can't record (#35214)
* fix(mobile): release the dictation audio session on stop and fail clearly without iOS voice processing

Stopping dictation only muted the native input, so the iOS voiceChat session
and Android audio focus stayed held until the screen unmounted and other apps'
audio stayed ducked. End now tears the engine down; the next open rebuilds it.
iOS tearDown stops I/O before deactivating and notifies other apps.

The iOS engine returned from setup before installing the mic tap when voice
processing could not be enabled, so recording reported success and captured
nothing. Setup now throws, so initialize fails and the phone shows the
microphone error.

* test(mobile): expect dictation stop to tear the audio engine down

* test(mobile): drop the duplicate release-throw case from native capture tests
2026-10-28 17:15:30 +00:00
Neil 74937b50aa refactor: group native chat transcript retention (#34761) 2026-10-28 09:22:44 -07:00
Brennan Benson fa5284aca2 feat: edit queued messages inline with the full chat composer (#31180)
* fix(native-chat): a refused queued message still blocks the queue when its card write fails

Every reader of a queued card goes through one derived view of the journal's dispatch facts,
so a card whose message was refused reads as returned even when its card-table update and heal
both failed. One decision and one writer store the derived state for every action.

* refactor(native-chat): keep each queued message in the chat's journal, not a second table

A queued message lived in its own SQL table, and a hook that may be skipped copied
each refusal from the journal into it. When that write failed, a refused card
vanished: the cards behind it sent, and its Send and Delete did nothing.

Each queued message is now a `queue` row in the chat's journal beside the
submission that hands it off and the dispatch row that answers it. The reducer
folds the card from those rows, so a refusal returns the card and holds the
cards behind it with nothing written, and replay reads the same. Every action
writes its own rows in one transaction. Cards an earlier build stored are read
through the same classification until they move: each action moves its own
card, and a bulk import runs once per open. A new epoch restates every card
still owed an answer in the transaction that deletes the old rows.

The settlement hook and its savepoint, the open-time heal, the drain's heal and
the derived-card view are gone. The published card list is unchanged.

* test(native-chat): adapt the queue tests to cards kept in the journal

Cards are written through the journal, so tests queue them with their body
alone and hand them off under their real fingerprint. Tests of the removed
settlement hook, heal and SQL store are deleted; the text-update spec now
covers the edit decision alone, and a test of an earlier build's stored holds
seeds the legacy table and reads the imported cards. Rolling over an epoch now
keeps a card whose hand-off was never handed over, so that test checks the
retried id never sends rather than that nothing sends.

* test(native-chat): a refused card holds the queue through rewind, a new epoch and a restart

One whole-flow test through the host: the refusal writes no card row, a rewind
that retires the refused hand-off and a rolled-over epoch keep the card
returned, a restart and Resume send nothing behind it, its own Send refused
again still holds the queue, and its Delete releases the next card in order.

* test(native-chat): an earlier build's queued cards move into the journal once, each read the same

One mixed-import test through the host. The first open's import fails and
moves nothing, yet every card reads as it will; Delete and Send each move only
their own card. The next open moves the rest in one transaction, writing a
refusal only where its hand-off is gone, nothing for answered cards, and leaving
an unreadable row on disk. A later command turn spends a moved command card, a
third open writes nothing, an old Delete replays from its receipt, and a chat
with only answered legacy rows clears them in a delete-only transaction.

* test(native-chat): adapt typechecked tests to cards kept in the journal

The row-kind table lists a queue row, the clear and legacy-import tests
match the current signatures, and the downgrade test keeps only the
leftover-send case: a queued card is now a newer-version journal row an
older build keeps read-only, and users don't downgrade.

* refactor(native-chat): drop the journal row writer's unused transaction hook

No caller passes one since the queue's savepoint bookkeeping left.

* test(native-chat): downgrade probes write rows at the version older builds read

The highest version this build reads is now 4, the queue row's. A newer
build's row in these probes is written at version 3 so the older build
meets its kind, not a newer version, and the Stop-event probe hands the
older build the rows as stored, since a read raises each row's version.

* test(native-chat): unit tests follow the queue row's version 4

The legacy-import test opens real SQLite, so it runs in the Node runtime
project. The newest version this build reads is now 4, and a read raises a
row's version to it, so the turn-lifecycle test no longer pins the
in-memory version (the written one stays pinned by journalRowSchemaVersion).

* fix(native-chat): one batch echoing two refused queued messages spends both

The per-row delivery check returned only the first waiting card an echo
proved delivered, so when one settlement carried echoes for two cards the
second stayed waiting and was sent again. It now returns every card the
row proves delivered, and the fold withdraws each; replay folds the same.

* fix(native-chat): a rewind moves an earlier build's cards into the journal first

While the open's import had failed, an earlier build's card that read as
refused through its hand-off lost that reading when an in-place rewind
retired the hand-off: it disappeared and the card behind it sent. The
rewind now adopts every legacy card ahead of its tombstones and deletes
their rows in its own transaction, as an epoch replacement already does,
so the fold latches each card's reading before its hand-off is gone.

* fix(native-chat): keep an earlier build's card whose hand-off is still unconfirmed

The import dropped a legacy card handed off as a send whose delivery was
unknown, though the fold keeps such a card linked and a later refusal
returns it. The import now keeps every card whose hand-off a later row can
still answer, through the same check the reducer folds dispatch rows by.

* fix(native-chat): one delivery echo withdraws at most one queued card

One provider echo proves one delivery, yet it withdrew every waiting card
with the same text whose hand-off was refused, so a second identical card
was lost. The fold now pairs each echo with one card: on its own row the
earliest-positioned match no other echo of that row took, and for a card
that waits again the earliest applied echo no card has taken. Paired echoes
live in the fold's state, so live and replay pair the same; readers of
cards not yet imported work on a copy.

* fix(native-chat): a queued message handed to the agent is sent again only on proof it never got it

Pressing Stop after Orca handed a queued or steered message to the agent,
before the agent confirmed it, put the card back in the queue, and Resume
or the next send sent it again. A check matching the agent's echo of the
text was the only guard against a double send, and it kept trading a
resend for a lost card. Whether the card waited again was decided by the
rejection's category, not by proof the agent never got the message.

A refused hand-off now waits again only where Orca proves the agent never
received it: the host still held it, or whoever settled it recorded that.
A failure still returns the card and holds the cards behind it. Anything
else may have reached the agent, so the card is spent and its message
reads as sent, derived on every fold from the stored rejection: with the
turn it was answered into, as that turn's unconfirmed message where it was
handed over; withdrawn before any turn opened, as a person's own send a
Stop took back. The reopen mark ignores a recovered doubt, and the restart
reconciler no longer judges a queued hand-off unsent from what history
lacks. The echo text matching and its pairing are deleted.

A close or quit while the agent starts settles sends with the unrun hold.
The host hands nothing to a child before its start answers
(structured-agent-session-delivery-loop.ts: a handover needs phase
ready), so such a send went to an earlier child and may have run: it now
reads as sent instead of waiting again.

* fix(native-chat): Claude's report that it removed a queued message unrun lets the card wait again

Claude says when it removed a send without running it: the interrupt
receipt's cancelled list, or a command_lifecycle cancelled, discarded or
refused frame for a command that never started. Every one settles through
rejectClaudeDispatchWaiters, which now marks the settlement unrun. For a
queued card's hand-off the host records that as proof the agent never got
it, so the card waits again under the queue's pause. A direct send keeps
the plain refusal: there the proof would owe it as stopped history.

* fix(native-chat): an earlier build's card stopped after hand-over follows the same rule on upgrade

Earlier builds put a card back to waiting after any refusal without a
verdict and cleared its link, so a card the agent may already have would
be sent again after the upgrade. The card's own hand-offs in the journal
decide now: unchanged and last sent as one that may have reached the
agent, it is spent on that hand-off and its message reads as sent; edited
or sent again since, it is held for its own Send under a host-only marker
that publishes as a plain hold; with no hand-off in doubt, including one
that never left Orca, it waits as before. The import writes a card spent
on a hand-off in doubt, so its message shows.

* fix(native-chat): read a queued row's hand-off before the lookup that uses it

The lookup's callback lost the narrowing of the row's change, which the
mobile test typecheck rejects.

* test(native-chat): a card steered into a turn a Stop ends stays sent in the Stop tests

Three tests pinned the old rule, that a card handed into a running turn
comes back to waiting when a Stop ends it. Under the new rule nothing
proves the agent never got it, so the card is spent: with the turn named,
its message reads as that turn's unconfirmed one; without, as a send the
Stop took back. Neither is ever sent again.

* fix(native-chat): a queued message stopped before Orca handed it to the agent waits again

A Stop that aborts a hand-off after its row is written but before the agent call now records
the withdrawal as never reaching the agent, for queued hand-offs only, so plan D's rule returns
the card to waiting under the Stop's pause instead of spending it. Direct sends keep the plain
withdrawal (the flag would owe them as stopped history). The agent's own refusal while aborted
is kept rather than overwritten, and an abort thrown during the call stays in doubt.

* fix(native-chat): a queued message stopped while the agent prepares it waits again

The abort signal reaches only an adapter's preparation (its options, the previous turn opening),
never its write, so the signal's own reason thrown back is the adapter saying nothing was
written. The handover now reads that, for queued hand-offs only, as never reaching the agent,
so the card waits again under the Stop's pause. Claude no longer wraps that abort as an option
refusal, which had returned a stopped card as a refused one blocking the queue. A real refusal
keeps its cause and its barrier; any other throw stays in doubt and is never resent.

* test(native-chat): the usage-limit Continue backlog case writes its card through the journal queue

Main's #30396 wrote its backlog card with the stored fingerprint and host-instance stamp the
journal queue derives instead; the card the Continue must yield to is the same waiting card.

* test(claude): the real-CLI queued Stop expects the unrun mark Claude's cancelled-unrun receipt carries

* feat(mobile): edit a queued message's images on the phone: remove or attach

* fix(mobile): gate queued image edits on the host reader verdict

* test(mobile): declare the upload fixture chat mode

* fix(native-chat): retain spent legacy messages when import fails

* fix(mobile): reveal the full queued image editor on open

* fix(mobile): invalidate queued editor geometry without a render ref write

* refactor(chat): prepare composer drafts and measured queue dragging

* feat(native-chat): add conditional queue removal and authoritative reordering

* feat(native-chat): move queued edits into the normal composer on desktop and phone

* fix(native-chat): own complete phone drafts before authoring

* fix: preserve submitted composer drafts across storage replacement

* fix composer validation and mobile CI diagnostics

* fix mobile composer test contracts and diagnostic output

* Capture mobile test compiler diagnostics in CI

* Fix queued message contract typing and English strings

* test: complete queued extraction transport fixtures

* refactor: separate composer skill binding from send mutations

* fix(mobile): grant draft storage within route limits

* fix(native-chat): settle each draft save on its own and publish complete composer drafts

Phone: a queued Edit copy no longer consumes the save that later typing
owns. Each ordinary save and the exact copy settle only their own result;
an explicit save waits for its own pending write, and a failed or retired
write never schedules another or revives the copy.

Desktop: a pasted-text leaf no longer shifts which selected file binds
where, and a hand-back held during an IME composition reaches the store
only merged with the visible editor document, including writes the editor
admits without an update and the composition settle.

* fix(native-chat): import the draft type once in the draft cache

* test(mobile): type the held-write state without an assertion

* test(native-chat): assert the handed-back file on Send without reading a typed transport as a mock

* test(mobile): pass main's agent-confirmed flag to the submitted-files harness

* fix: reveal queued reorder grip on touch screens

* fix: save reopened phone drafts and batch reorder measurements

* test: use an explicit React module type

* Preserve queued message sortable identities on unchanged renders

* Prevent stale queued drag completion after unmount

* fix(mobile): hand off navigation across session workspaces

* test(mobile): use resolved session identity in dictation fixture

* feat: edit queued messages inline with the chat composer

* fix: normalize queued edit skill ownership

* fix: retire phone skill selections with the sent draft

* fix: consolidate queued edit module imports

* fix: separate edit save action and stabilize image callbacks

* fix: complete phone inline composer integration

* fix: retain same-name queued skill selections

* fix: complete desktop queued composer integration

* test: use typed phone composer host lookups

* fix: include queued edit localization keys

* Preserve inline edit input across save and attachment completion

* Preserve complete queued edits across delayed saves

* Preserve queued edit input across delayed completion

* Complete queued edit lease loss and pending cancellation

* Use recognized queued edit test fixtures

* Consolidate queued edit imports and type host test spy

* Print mobile test compiler diagnostics on ratchet failure

* Correct queued edit integration fixture types

* fix: keep queued edit placeholder independent of readiness

* Fix queued edit compiler fixture boundaries

* Align upload completion test with ordinary insertion

* Combine mobile composer draft imports

* Load queued edit host fixture during test collection

* Size inline phone queue editor to available space

* Use typed scroll components in phone presentation contract

* Save typed text in a queued edit as written

The inline editor is the chat composer, so it keeps the composer's own identity model and no longer refuses Save for text that looks like a command. Command rows picked from the menu are still refused, Enter still means Save, and Edit never sends or runs anything.

Regression tests cover Undo after deleting an accepted command or skill pill, a scanned skill named like a command, two saved files behind one token, and typed command text saving literally. Also fixes two merge leftovers in tests: a missing import and a fixture that stored the whole menu row as a skill.

* Keep ordinary sends on the main composer contract

* Fix mobile composer imports and fixture loading

* Consolidate queued edit imports and duplicate regression

* Restore ordinary send catalog short circuit and repair test boundaries

* Preserve returned rich drafts through send acceptance

* Remove obsolete queued editor strings from new locales
2026-10-28 02:09:49 -07:00
Jorge AlbarracínandNeil d155cfba05 feat(editor): syntax highlighting for Glimmer .gjs/.gts files (#13236)
Register glimmer-js and glimmer-ts Monaco languages that embed
JavaScript/TypeScript as the background script and tokenize each
<template> block as a Handlebars island. Embed entry is bounded by the
shared line budget so long lines cannot blow the Monarch recursion
limit. Mobile maps the new ids to javascript/typescript highlighting.

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-28 01:10:23 -07:00
Jinwoo Hong cb43b47359 fix(terminal): let file existence pick spaced path readings so prose cannot hide a path (#34281)
* fix(terminal): let file existence pick spaced path readings so prose cannot hide a path

* refactor(terminal): let the host's file check decide spaced paths and replay phone taps that name no file

Spaced readings no longer guess where a path ends: a rooted path offers one
reading per following word (up to ten), and a relative path grows only to its
first filename so dense path lists stay cheap. A phone tap whose readings name
no file replays the ordinary tap instead of reporting a failed open, and
checks up to 16 readings at once.

* fix(terminal): drop a phone tap's replay after a newer tap, and accept digit-led extensions

* fix(terminal): drop a phone tap's replay after typing, URL taps or selection, and accept Unicode extensions

* refactor(mobile): decide terminal file taps from the text under the finger instead of replaying withheld taps

A tap is a file tap only when it lands on a path itself; prose beside a path
stays an ordinary tap at once. This removes the withheld-tap fallback and its
stale-tap counters.

* refactor(terminal): return spaced path guesses apart from written paths so only a host check can act on a guess

Hover and chat check every reading as before. A click opens a guess only after the host finds its file, and never past an external share. A phone tap is a file tap only when a written path is under the finger, so a markdown destination with spaces counts. OSC 8 targets are parsed as written. Phone file checks return to 8 at a time.

* fix(terminal): leave a click on prose beside a path to the terminal unless a written path or a confirmed guess covers it

* fix(terminal): fall back to the shortest checked written path when a click's file checks fail

* docs(terminal): say relative paths grow only to their first filename
2026-10-28 03:02:19 -04:00
OrcaWinandOrcaWin 9d33005090 perf(mobile): defer unopened terminal document allocation (#34743)
* perf(mobile): defer terminal documents until first selection

* test(mobile): address review findings on pane-gating test

* test(mobile): use T[] array type in terminal document mount test

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:58:24 -07:00
OrcaWinandOrcaWin f0e97a6b2d fix(mobile): stop repository requests for obsolete task searches (#34740)
* fix(mobile): stop obsolete task repository requests

* fix(mobile): release task-list spinners when a load is abandoned

* fix(mobile): release spinners only for in-flight abandoned task loads

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:58:16 -07:00
OrcaWinandOrcaWin 6d5db9a397 fix(mobile): cancel superseded shell download flows (#34780)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:40:40 -07:00
OrcaWinandOrcaWin 8916bf36aa fix(mobile): release queued inbound frames after transport teardown (#34777)
* fix(mobile): release queued inbound frames when transports close

* test(mobile): run relay inbound retention regressions in every runner

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:40:36 -07:00
OrcaWinandOrcaWin 72ff417691 fix(mobile): discard refused picker cache copies (#34772)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:18:40 -07:00
OrcaWinandOrcaWin 4270c886d8 fix(mobile): release native picks after page teardown (#34760)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:18:36 -07:00
OrcaWinandOrcaWin 1ac9be7605 fix(mobile): let native screens handle Android Back after handoff (#34766)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:18:31 -07:00
OrcaWinandOrcaWin 9c094e16d2 fix(mobile): share microphone ownership across page sessions (#34762)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:18:27 -07:00
Wooseong KimandNeil 55f9525c49 feat(editor): highlight CUDA C and C++ files (#21384)
Register a `cuda-cpp` Monaco language (VS Code's id) that reuses Monaco's
C++ grammar with CUDA qualifiers, built-ins, and vector types as keywords.
Map `.cu`/`.cuh` to it, and alias it to lowlight's cpp grammar on mobile.

Fixes #21267

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-27 23:15:01 -07:00
OrcaWinandOrcaWin eac5699bcd perf(mobile): pause active turn clocks while backgrounded (#34746)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:06:36 -07:00
OrcaWinandOrcaWin 6fcbce32b9 fix(mobile): release cancelled relay stream captures immediately (#34745)
* fix(mobile): release cancelled relay subscription callbacks

* test(mobile): run relay cancellation GC regression tests by default and in CI

Expose GC via v8 flags so the collection cases no longer skip under the default pool or Bun, run the file on Node in mobile CI, and drop cases that already passed on main.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:06:33 -07:00
OrcaWinandOrcaWin d5dcc2cdf7 perf(mobile): keep terminal backlog draining linear (#34741)
* perf(mobile): drain terminal backlog without repeated array shifts

* test(mobile): cover backlog reuse after mid-drain dispose

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:06:29 -07:00
OrcaWinandOrcaWin 00666138a7 fix(mobile): show pairing progress and errors without camera access (#34739)
* fix(mobile): show pasted pairing feedback without camera access

* test(mobile): drop unreachable revoke and mock-only listener tests

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:06:25 -07:00
Brennan Benson 8d908764dc Revert "Keep same-machine folders with matching Git remotes in separate projects (#32272)" (#34662)
* Revert "Keep same-machine folders with matching Git remotes in separate projects (#32272)"

This reverts commit 29a5f89b8a.

On a machine with several clones of one repo, #32272 moved the oldest clone
into the shared cross-host project. Shared Windows QA machines have several
orca clones, so everyone's sidebar "orca" project suddenly gained that
machine's main checkout and its worktrees. Revert until the intended
grouping is decided.

Conflicts resolved against later main: Settings files moved into
settings/repository (imports adjusted), and two test files later deleted on
main stay deleted.

* Use checked types in restored test fixtures

* Combine restored fixture type imports
2026-10-27 20:38:35 -07:00
Neil 6bb0c14a98 refactor: group native chat text presentation (#34647) 2026-10-27 19:48:24 -07:00
Neil 4d3451601a refactor: group native chat live presentation (#34638) 2026-10-27 17:56:38 -07:00
Neil ea532813b1 refactor: group native chat turn presentation (#34629) 2026-10-27 17:33:03 -07:00
Pandu dwi PutraandBrennan Benson ec49e9fac0 fix(native-chat): list OMP skills in the / menu as /skill:<name> (#31999)
* fix(native-chat): list OMP skills in the / menu as /skill:<name>

* test(native-chat): OMP now carries the Pi-shaped skill profile

* Publish native OMP skills with compatible command catalogs

* Index native skill descriptions once per picker build

* Combine catalog test composer imports

* Correct native catalog test types and project inputs

* Run cross-platform picker scaling contract with mobile tests

* fix: discover native commands before the first chat message

* test: isolate native command discovery from mobile typechecking

* fix: release command discovery ownership after managed root exit

* refactor: reuse the ACP child owner during shutdown drain

* test(acp): load filesystem implementation before test execution

* test: drive discovery close completion explicitly

* test: await discovery admission cleanup between demand waves

* test: control discovery close ordering in demand waves

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-27 17:14:20 -07:00
Neil f3adb8f85a refactor: group native chat work-run boundaries (#34528) 2026-10-27 15:18:29 -07:00
Kelvin Amoaba 941f4ece37 feat(mobile): support the iPhone Duo folded and unfolded, with controls in its side status bar (#34484) 2026-10-27 22:16:33 +00:00
Brennan BensonandWooseong Kim 287a34c0e5 fix(github-project): show linked PRs and sub-issue progress (#34185)
* fix(github-project): render linked PR and sub-issue progress values

* fix(github-project): probe schema support for project column values

* fix(github-project): preserve independently supported project fields

* Preserve nullable project values and unsupported fetch concurrency

* Exercise project relation payloads through unchanged consumers

* Combine project coordination test cache imports

* Use checked project payload types in consumer tests

* Place project provider column contract in cross-layer tests

---------

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
2026-10-27 13:48:54 -07:00
Brennan BensonandHotragn 8f3d8c8583 fix(gitlab): preserve MR pagination when totals are missing (#34171)
* fix(gitlab): keep paging merge requests when GitLab omits the totals

When total headers are absent, a full response advertises another page to probe and a short response ends pagination. Keep the existing header precedence and unknown total count.

Tracked in #33800

* test(gitlab): cover MR pagination exhaustion and header precedence

* test(gitlab): verify unknown-total metadata across list consumers

* test(gitlab): cover remaining screen consumers of list metadata

* test: use checked GitLab RPC runtime fixtures

---------

Co-authored-by: Hotragn <103170876+Hotragn@users.noreply.github.com>
2026-10-27 13:46:07 -07:00
Neil 55dffb479a refactor: group shared native-chat empty-state copy (#34503) 2026-10-27 11:55:40 -07:00
Neil 8414076859 refactor(shared): group native chat notice presentation (#34481) 2026-10-27 11:23:49 -07:00
Kelvin Amoabaandzhangxaochen 2a9d874e67 fix(mobile): leave Agent Session History when you resume a session from it (#34485)
* fix(mobile): leave Agent Session History when resuming a session from it

Resuming always pushed the session screen, so Back from it landed on the
history screen again (A -> B -> A). History now learns it was opened from a
session (origin=session, as Source Control does): resuming into that same
workspace pops back to it, anything else replaces the history screen.

The history screen is a page in the shell, and the page could only ask the
shell to push. The navigate notify gains an optional replace flag; a page with
no in-page history asks the shell to replace its screen, and one with history
below pops its own entry and has the shell push. Older shells strip the flag
and push as before.

Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>

* fix(mobile): show the resumed terminal on the session that opened Agent Session History

Going back to the session screen below kept its old tab: the session pins its
own pick over the host's caller-scoped snapshot. History now hands the resumed
terminal to that session through the registry Source Control already uses for
opened diffs, renamed to session-screen-handlers since it carries both.

* refactor(mobile): positional replace flag on notifyNavigate, share the owned-session test fixture

* fix(mobile): keep MobileWebShellScreen under its line cap

---------

Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>
2026-10-27 17:58:49 +00:00