mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 17:17:38 +00:00
884575a797ebfd54d4c76cbd2efbe0bedbf0a404
1166
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4fd7398013 | test(native-chat): run ZCode SQLite fixtures on the production runtime | ||
|
|
a90e5d9de6 |
ci(e2e): run the layout oracle on PRs that change layout writers (#27103)
* ci(e2e): run the layout oracle on PRs that change layout writers Co-Authored-By: Claude <noreply@anthropic.com> * ci(e2e): narrow the layout oracle triggers to the modules that write layout Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
33a1ddfc26 | ci(zcode): register native credential tests in the Windows lane | ||
|
|
8ba353a1a7 | [CI] Refresh unit timing weights and reduce repeated test setup (#27315) | ||
|
|
ddcbb78013 |
chore(lint): bypassing owner routing fails lint (#27313)
* chore(lint): delete the focus-routing helpers; bypassing owner routing fails lint The last six renderer sites (Settings visibility defaults, preflight readiness, Linear key dialog copy) mirror the default scope host and now say so through defaultScopeHost. getActiveRuntimeTarget and settingsForRuntimeOwner are deleted with their re-exports, the unused settings-fabrication helpers go with them, and the owner-routing baseline is empty, so any new use fails lint. The provider dispatch rationale is rewritten in neutral, shorter terms. * test(preflight): keep the existing cast's rationale on the edited line --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
26ee9bbfab |
[CI] Reduce repeated test setup and unnecessary packaging (#27308)
* [CI] Reduce repeated test setup and remove source text checks * [CI] Consolidate transcript tests and preserve fixture-only CI routing * [CI] Retarget reliability gate to consolidated transcript suite |
||
|
|
0a73d1e093 |
[CI] Reduce repeated test setup and real CLI waits (#27297)
Combine related chat, worker-release, and filesystem tests while retaining their contracts. Replace fixed Codex terminal waits with observed readiness and hook completion. Keep runtime database contracts under Node. Local measurements and all CI lifecycle costs are documented in PR #27297. |
||
|
|
81867c8ea0 |
refactor(sources): row-less sources and host-less surfaces name their host (#27290)
* refactor(sources): row-less sources and host-less surfaces name their host Linear and Jira clients take a RowLessSource: a task-source context, an explicit host, or defaultScopeSource(settings) when no Tasks source is chosen, so raw settings no longer compile. defaultScopeHost joins defaultCreationHost as the second sanctioned reader of the default-host setting (both behind one private read, both ratchet seeds), and the status-bar account switchers, settings navigation and the settings host picker's initial default use it. Skill discovery routes by the owner id its install terminal resolves, and the workspace-board Linear sync by the workspace owner. * fix(lint): count the default scope source and assign-then-return readers defaultScopeSource is a sanctioned read of the default host, so its call sites count. A function that assigns a reader's result to a local and returns that local is a reader too, which keeps the skill-discovery hook counted. --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
75dfd75460 |
refactor(runtime): owner transports, the creation default and a focus-read ratchet (#27275)
* refactor(runtime): owner transports, the creation default and a focus-read ratchet Adds runtimeTargetForOwnerEnvironment, runtimeTargetForOwnerHostId and runtimeTargetForWorkspaceOwner so routed call sites can get a transport from the resource's owner, and defaultCreationHost as the one sanctioned reader of the Active Server setting for creation flows with no source row. The owner-routing ratchet gains a second per-file counter for reads of the setting (member reads, the focus-routing helpers and defaultCreationHost), so swapping a helper for a direct read can no longer lower a count. Baseline rows may carry a trailing note that survives --prune. * chore(lint): pin defaultCreationHost's own read in the focus-read baseline * fix(lint): the focus-read ratchet counts shared focus helpers and destructuring reads * fix(lint): discover functions that read the default host instead of hand-listing them A hand list let a look-alike such as getAutomationListTarget replace getActiveRuntimeTarget and lower both ratchets. Every exported top-level function whose body reads the setting or calls a seed helper now counts as a reader, and nested destructuring reads count too. * fix(lint): readers are found through imports and returned values Readers are keyed by defining file and resolved through imports and re-exports, so a same-named function elsewhere is not mistaken for one, and a function that returns a reader's result (a wrapper of a wrapper) is found too. Components are not readers, and a declaration ends at the next top-level statement. * fix(lint): a reader called through a namespace or dynamic import still counts * fix(lint): renamed, parenthesized and .then() dynamic imports bind readers too --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
83db5b5ec1 |
[CI] Reduce test teardown waits and duplicate CI setup (#27253)
* [CI] Reduce test teardown waits and duplicate CI setup * [CI] Map browser ownership to the combined test check |
||
|
|
3a8f8e1790 |
fix(review): PR reads and actions follow the ownership table (#27248)
* fix(review): PR reads and actions follow the repo owner, not a host-less task source A GitHub task source without a runtime host used to spread activeRuntimeEnvironmentId: null over the repo owner's settings, so assignee, reviewer, label, status and merge cells for a runtime-owned repo ran on this desktop. Every PR read and action site now routes through getGitHubRepoRoutingSettings (renamed from the merge-only helper), and the store's source-scoped routing defers to the repo owner the same way. Focus is never a fallback. Fixes #7623 * fix(review): a host-less source never inherits an ambiguous repo owner Duplicate repo ids across hosts made the host-less source fallback pick a server owner by focus (UI) or by first row (store), so a local item could read or write on a paired server. The owner is now inherited only from the single row with that id; ambiguity stays on the source's own host. * test: drop stale repo-owner mocks from GitHub repository scripts --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
4dfc74e5e6 |
[CI] Reduce repeated test imports and unrelated runner allocations (#27222)
* [CI] Reduce repeated test imports and unrelated runner allocations * [CI] Exercise macOS packaged CLI invocation receipts * [CI] Unmount workspace hook fixtures before environment teardown * [CI] Wait for replacement Bash readiness before the child command |
||
|
|
e0376015a4 |
refactor(runtime): route adapter, split fences, ownership table, combined ratchet (#27218)
* refactor(runtime): route adapter, split fences, ownership table, combined ratchet Adds callHostRoute, which calls a host-owned method on the host a HostRoute names and reports a reply whose host identity moved mid-call as unverifiable instead of applying it. Host fences are split: an identity fence (pairing, runtime connection generation, the route's own SSH target) for mutations, and the catalog data fence built on top of it for snapshot reads, so unrelated catalog or SSH-state churn no longer moves a mutation's fence. HOST_OPERATION_OWNERSHIP classifies every runtime RPC namespace. A new ratchet counts getActiveRuntimeTarget( + legacyRouteFromSettings( + settingsForRuntimeOwner( together per renderer file (227). One exemplar, the folder workspace review-note write, moves onto the adapter. * fix(runtime): fence the folder note write on its server; refuse aliased ratchet helpers The folder catalog row lives on the paired server, so its write is fenced on that server's identity, not on the SSH target the folder names. The ratchet now counts spaced calls and value uses, and refuses an aliased import or re-export that would hide calls from the count. * test(ci): pin the owner-routing ratchet step to the static phase --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
31b2b17d9b |
refactor(wsl): move the WSL guest bundle sources out of src/relay (#27174)
* refactor(wsl): move the WSL guest bundle sources out of src/relay The WSL hook relay and WSL browser network relay are built from src/relay but are not part of the SSH relay. Move them, and the 46 relay modules the hook relay bundles, to src/wsl-guest so the SSH relay can be deleted on its own. Pure renames; the built bundles are byte-identical. Adds a boundary test so nothing outside src/relay imports it except relay tests. * fix(ci): exempt renamed files' existing lint debt in the changed-lines gate * test(relay): keep the cast suppression on the wrapped line * test(relay): only parse files that mention relay in the import boundary check --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
3c71318d5b |
[CI] Overlap independent process waits and remove two static tests (#27198)
* [CI] Overlap independent process waits and remove two static tests * [CI] Use the declared conditional Vitest chain |
||
|
|
dab3f6efeb |
fix(native-chat): preserve running subagent rows in long chats (#26798)
* fix(codex): keep running subagent groups in long chats * fix(codex): remember superseded settled child turns * fix(native-chat): retain running Claude subagent groups |
||
|
|
b63d39ebe5 |
Keep repository detection off the main registration thread (#26760)
* Keep repository detection off the main IPC thread Share repository discovery decisions across synchronous compatibility callers and the existing asynchronous Git runner. Await discovery in project registration, nested imports, and folder upgrades, and recheck folder ownership after discovery completes. * Make repository detection fixtures work on native Windows * Await asynchronous Git checks in folder upgrade fixtures * Prevent duplicate project registration after async discovery * Check authoritative registration identity before renderer convergence * Narrow repository responsiveness to detection and registration * Keep one local project identity after concurrent registration * Run registration SSH coverage in the existing Docker lane * test(git): cover classifier failure stages and literal path identity * test(git): use the current process host package * test(repos): use current process host in registration fixture |
||
|
|
f4c4eaeece |
fix(i18n): correct Korean Finder menu label (#26866)
Use the approved Korean Finder wording and preserve it during locale regeneration. Co-authored-by: YEONGUK LEE <contact@abruption.dev> |
||
|
|
915c4b74a2 |
Update Claude usage without rereading the whole conversation (#26967)
* Verify pinned transcript reads and stream Codex usage aggregation * Resume Claude usage scans with compact token checkpoints * Harden transcript snapshots and reject incomplete discovery * Keep Codex race fixtures inside their temporary data home * Verify pinned transcript rotation with portable file moves * test: keep Claude usage mock registration in test suites * Compress saved Claude usage without dropping history * Keep Claude cache writes bound to their original request * Register Claude contracts without conflicting with chat contracts * Assert unchanged Claude sources skip the actual cache writer |
||
|
|
71733ccc04 |
Speed up process-host import enforcement in CI (#27124)
Reduce import-scanner work by omitting unused AST parents and the duplicate traversal. Run the mandatory process-host import check alongside static work and explicitly join it before CI can succeed. Update both workflow phase/enforcement contracts and migrate the newer benchmark to the public subprocess package API. Keep the original package build path, manifests, runtime, test selection, and shard count. Independent native review is clean; validation and timing evidence are in the PR. |
||
|
|
8452fc3315 |
Keep tool results with the right command and reveal all results on mobile (#26968)
* Pair native chat tool results in linear time with provider identity * Preserve orphan tool output and independent disclosure identity * Keep mobile tool detail attached to its command after row changes * Keep named mobile results open across copied history refreshes |
||
|
|
7c22f6f045 |
[CI] Consolidate tests, retire static scans, and update evidence (#27109)
* [CI] Consolidate renderer test modules and retire static scans * [CI] Keep consolidated test within the existing line limit * [CI] Refresh evidence for the preserved turn-duration gate |
||
|
|
3563270132 | ci(release): read the watcher child from the supervisor's slot in the fault harness (#27120) | ||
|
|
03408d8570 | ci: skip build:packages on release tags that predate it (#27110) | ||
|
|
440cde0f74 | Reduce memory used to count Codex usage and avoid partial totals (#26966) | ||
|
|
c9b7244bb9 |
fix(native-chat): lazy WSL tier for Claude, Grok and omp lookup by id (#27082)
Only Codex had a WSL fallback when a transcript is looked up by session id, so Claude running inside WSL with no hook path was searched only on the Windows profile and chat showed "Transcript unavailable". Every id lookup now searches this host's roots first and, only on a miss, each running distro's roots for the same agent, through the shared per-root WSL scan. One layout table names how each agent files a session (claude, codex, grok, omp) for both host and WSL lookups. Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> |
||
|
|
c8b8997762 |
feat(native-chat): offer Codex Ultrafast as a speed choice (#26962)
* feat(native-chat): offer Codex Ultrafast as a speed choice Codex lists Ultrafast as a third service tier for eligible models and accounts (GPT-6.1 Sol). Codex chats saved Fast as on/off, which cannot hold a third tier. The Codex speed is now a Standard/Fast/Ultrafast choice built from the tiers the model lists; the tier id is still resolved from the catalog at each send. Older clients keep their Fast toggle: the host still reports Fast on/off and accepts it as a speed. * refactor(native-chat): save the Codex tier id instead of a speed name The chat now keeps the tier id Codex lists (serviceTier: default, priority, ultrafast) and sends it as-is on turn/start; Codex drops a tier the model no longer lists with its own warning. This removes the saved per-model tier map, the send-time lookup and the reconcile code. The unused fastModeTierByModel catalog field is deleted. Older clients still get Fast on/off, derived from the model's tier named Fast. Also drops the pnpm-lock.yaml churn the first commit picked up. * test(pi): drop the removed fastModeTierByModel catalog field * fix(native-chat): review round 1 for Codex service tiers - Accept an older client's fastMode write through the Codex adapter; it was refused before reaching the tier alias. - Bump the saved model catalog schema so catalogs from before serviceTiers re-list instead of offering a Fast toggle with no tier. - Keep only the reported tier on the record, not the Fast it implies. - Drop a reported tier, not only a picked one, when the next model does not list it. - Localize Standard inside the speed choice only. - Return the options answer directly instead of a one-field wrapper. * fix(native-chat): review round 2 for Codex service tiers Keep a tier Codex reports for the thread (it accepts unlisted ones such as flex); read the legacy Fast tier beside an empty serviceTiers list. * fix(native-chat): review round 3 for Codex service tiers A reported tier the old model listed and the new one does not resets to Standard on a model switch, and the reported tier itself stays pickable. * fix(native-chat): keep a re-picked reported Codex tier The thread's reported tier is never reset by the unlisted-tier drop, so a re-picked Flex survives the next read, a model switch, and the turn. * refactor(native-chat): one rule for which Codex tier a model offers Standard, a tier the model lists, or the thread's reported tier that no model lists. The setter and the unlisted-tier reset share it, replacing the separate reported-tier and model-switch guards. * test(native-chat): drop the removed fastModeTierByModel field from main's new catalog test |
||
|
|
1912c90141 |
Extract subprocess handling into @orca/process-host (#26963)
Extract subprocess execution and process contracts into @orca/process-host with explicit public entry points, independent checks, and one Node 18 compatible CommonJS runtime. Migrate application consumers and integrate package builds, dependency selection, import enforcement, and runtime resource staging. Preserve daemon startup ownership and profile isolation, and qualify development rebuild recovery and concurrent output publication. Remove unnecessary aliases, test forwarding exports, and a duplicate output scan. Validation: full typechecks, changed-code quality, package and artifact checks, native Windows builds/types plus 306 runtime tests, and independent native reviews. Matched full E2E controls on original main and unchanged reviewed head both pass all 17 applicable tests (nine skips). Earlier intermittent E2E failures are documented in the PR; no assertions were weakened. The final combined-tree audit preserves both branches with no import-boundary violations. |
||
|
|
5ef576c913 | [CI] Reduce fixture work and consolidate related test scopes (#27063) | ||
|
|
b44a5796c1 |
fix(native-chat): settle a reply cut off by a server restart (#26460)
* fix: preserve streamed turn duration after host restart * test: run restart duration regression in Node * fix: preserve provider receipt time in journal updates * test: verify provider receipt in Claude ownership assertion * fix(native-chat): time interrupted turns from real provider output, not flushes Shared-timeline checkpoints stamped the coalescer flush or retry time as the provider's latest proof of life, so a turn whose provider died before a delayed flush settled with an inflated duration after a host restart. Carry each delta's receipt time through the coalescer and timeline lane. * fix(native-chat): derive interrupted-turn duration from saved output A reply cut off by a server restart could show "Worked for 0s" because recovery ended the turn at the last heartbeat or the reply's first timestamp. End it at the latest time this owner's output was saved to chat history instead, derived in the existing journal fold from the row save time. Drops the per-frame receipt plumbing through every provider and buffer. * fix(chat): exclude host recovery revisions from provider activity Mark journal-open and connection-cleanup revisions with the existing recovery annotation so an interrupted turn does not include host downtime. Preserve buffered provider output and advance restart fixtures to the restart clock. * fix(native-chat): interrupt turns a replaced server left running When the managed server died mid-reply and a new one started on the same host, the cut-off turn settled `unverifiable` with no end whenever the old provider's identity could not be proven gone, and nothing ever revised it: the chat showed no turn status and the sidebar said "unconfirmed". The new server opens the chat records holding the host's instance lock, so every runtime that wrote them before is gone, and every provider it held lost its pipes with it. Record that at load (the fences those runtimes granted, the loaded owner's last renewal, how its runtime ended) and let the stale settle end those runtimes' running or unverifiable turns as interrupted at the owner's last saved output or renewal, with the existing Orca-stop row. Lease adjudication and the live / unverifiable / exited owner verdicts are unchanged. * fix(native-chat): require the record store for any journal open that settles Only an acquisition's open may skip it; a reader open without the store would leave a replaced server's turns unverifiable. * fix(native-chat): say a remote host's Orca restarted, not that it was closed A reply cut off when a remote host's Orca server stopped read "Orca on <host> was closed while this response was in progress." Nobody closed anything there: the server stopped and Orca started it again before the row could show. For a chat on a remote environment, cause quit now reads "Orca on <host> restarted while this response was in progress." The desktop's own quit keeps "was closed". Renderer-only; no wire change. * fix(native-chat): say a remote host's Orca stopped, true for a shared desktop too * test(native-chat): register Grok without compaction in the recovery-output rig Main's #26502 made Grok declare compaction; the rest-test rig adapter has no compact, so the registry refused it before any recovery case ran. * chore(native-chat): say a replaced runtime also revises an unverifiable turn |
||
|
|
280ef3c6f3 |
fix(native-chat): accept sends through their own receipt (#26672)
* feat(native-chat): add a chat-owned command receipt store Adds the agent_session_command_receipts table and an insert-if-absent receipt write that runs inside a command's own journal transaction. A receipt records the command's identity, canonical hash, status and a pointer to the row holding its result; it dies with its chat record. Nothing uses it yet: the existing operation ledger stays authoritative. * fix(native-chat): key command receipts like today's ledger ids Rows are keyed by caller and operation id; a send looks across callers and other methods look up only their caller's row, matching the existing ledger. Bad rows and newer table shapes read as unreadable instead of throwing. * fix(native-chat): order receipt lookups by insertion and key by operation id Global lookups now take rows in insertion order, so a read and an insert agree on which receipt answers an id regardless of the host clock. The primary key leads with the operation id, so its own index serves both lookups. * fix(native-chat): accept sends through their own receipt Send (direct, queued, steer) and /compact no longer commit a separate ledger reservation before the message is saved. Their command receipt is inserted-if-absent in the same transaction as the submission or queued draft; a repeated id replays from it, a changed request conflicts. Operation ids are checked for syntax only, so age, clock skew, pruning and the reservation's own storage can no longer refuse a send. The ledger success row they already co-committed stays as a temporary insert-if-absent write so families not yet switched keep seeing these ids; it is never read on this path. * fix(native-chat): answer a send's receipt one way, share /compact's id space with Send, wake delivery once - After its commit, a send whose publication fails answers through the same receipt replay a retry takes, so one id gets one answer; the in-memory copy and journal reload are gone. - /compact ids are global like Send's: a retry under a new connection replays instead of needing a second acknowledgment write. - The receipt route calls its runner directly; the runner wakes delivery when a new message row commits. - The compatibility ledger row expires from host time; each temporary site is labelled. - Receipt read errors and post-commit failures are logged. * test(native-chat): expect receipt answers where tests assumed the send ledger Restart-continuation tests now model the case Send cannot vouch for (saved but not loaded into memory) and keep it unconfirmed; a later throw after the message is in the chat answers continued, as a resend would. Drop /compact's unreachable legacy replay branch and fix stale comments. * test: run the queued tests that open the journal database in the Node runtime project |
||
|
|
0f7c06aedb |
fix(native-chat): identify a paired device by its device id, never its credential (#26777)
A paired device's socket passes its bearer credential as clientId, and native chat used it as the caller key it stores in ledger rows, receipts, chat records and prompt answers (shown to other clients). Name a paired device by the device id its socket proved instead. |
||
|
|
7012f8455c |
[CI] Advance debounce clocks and simplify test fixtures (#26996)
* [CI] Advance test debounce clocks and remove workflow text checks * test: use a representative PowerShell command fixture |
||
|
|
8defd660c7 |
A new Pi chat names the model it will run on its first frame (#26821)
* refactor(native-chat): one rule for what a no-pick session says of its configured default ACP's rule (only a new session that restored no model pick and was sent none runs its config's default; an effort it picked says nothing) moves beside the catalog entry types so other agents' adapters report through the same step. An empty listing (a signed-out agent) now says nothing instead of "no listed model", so it can never retire a saved default. * feat(native-chat): check Pi's project config before naming its default model Pi reads `.pi/settings.json` in the chat's folder and loads project extensions from `.pi/extensions` (and the `extensions`/`packages` lists). A settings file that sets defaultProvider, defaultModel, defaultThinkingLevel, modelThinkingLevels or enabledModels, loads extension code, or can't be parsed counts as the project picking the model; extension code may register providers or set the model itself. Key names come from Pi 1.0.4's own settings manager and docs, read without running Pi. * feat(native-chat): a new Pi chat names the model and thinking level Pi starts on Pi's model listing marks no model as the one it runs, so a new Pi chat with no saved pick showed "Model" and then changed to the model its session reported. A new Pi session (not one resumed or forked from a saved conversation) that restored no model pick and was sent none now reports the model and, unless it picked one, the thinking level it started on, through the same host step as Grok, OpenCode and OMP. The host saves them as the account's default behind the project-config check, so the next new Pi chat names them on its first frame. A signed-out Pi, which lists no model, saves nothing. * fix(native-chat): a newer, coarser effort menu keeps the effort a chat ran The saved list takes each model's effort menu from the newer listing. Pi's `--list-models` menu stops at high, while a chat's own menu adds xhigh or max for models whose thinking map allows them. After a background re-list, a learned xhigh was no longer in the menu, so the first frame dropped it. When the configured effort is only in the other listing's menu, that menu is kept. * fix(native-chat): Pi teaches only the model and thinking level it started on A Pi chat re-derived its configured default from Pi's current state on every options read, so a model an extension switched to mid-chat (extensions can call setModel) was saved as the account default, and the next new chat named the wrong model. The choice is now computed once, after start-up restores the chat's saved picks, and every later read reports that snapshot. A pick made in the chat no longer matters to it. Tests cover an extension switch, a pick made in the chat, a forked chat, and a learned xhigh surviving a newer re-list. |
||
|
|
573ff0bca3 |
Save a new chat's first message during create (#26332)
* fix(native-chat): the host owns the send queue; the window keeps no saved outbox The desktop kept each structured chat's unsent messages in localStorage and sent them in order, so one message whose fate was unknown froze every later send, Retry dropped it silently, failed sends could not be discarded, and an offline chat could send hours later. The host already records every message and owns the queue; the window now only sends. - One in-memory sender for composer, launch prompts and messages sent from outside the chat. One send in flight per chat; a transport failure resends the same id for up to 30 s; a refusal that proves nothing was recorded puts the text back in the composer with the reason; a send that went out and was never answered shows an in-doubt line with Send again and holds nothing up. - The host's "unknown" rows get the same in-doubt line and Send again, from the journal, in every window. - A message an older build left in localStorage is never sent: the host's conversation outline decides what goes back to the composer, and the copy is deleted once that is saved. * fix(native-chat): send through the structured chat RPC wrapper, with its timeouts The sender called the runtime RPC directly, skipping the per-method timeouts every other structured chat call gets. Only a remote host's request skips the compatibility check the sender already ran. * fix(native-chat): an unconfirmed send goes back to the composer, with no new row line The common pattern draws nothing extra on a message whose delivery is in doubt once its turn is over, and puts a failed send's text back in the composer with the reason. So a send nobody answered in time, or one a host answers in a way that proves nothing, goes back to the composer worded as unconfirmed, and a host "unknown" row shows nothing extra. Removes the in-doubt phase, Send again, and its strings. A host's made-up row for an id its journal lost now reads as unconfirmed, not as recorded, so that message comes back instead of vanishing. * test(native-chat): pin that nothing resends a send given back as unconfirmed * fix(native-chat): sends survive a tab close, never resend after a Stop, and keep remote images - A normal tab close lets sends on their way settle; what the host never took goes back to the conversation's draft. Only a cancelled launch or a worktree purge drops them. - After any Stop, a send already on its way is never sent again under its id: a doubtful answer, or a resend that was due, hands its text back worded as unconfirmed. - A returned image keeps the SSH connection it lives on; the connection never goes to the host. - An older build's saved message the host recorded and then rejected is left to the host's own row, never handed back. * fix(native-chat): a Stop or a tab close never resends a send already out, and a kept card is the card's A Stop that landed while a same-id resend was being readied (its timer fired, its request not out yet) let that resend go out after the Stop. The sender now tracks whether a request is awaiting its answer: a Stop hands back every send between attempts as unconfirmed, lets one whose request is out settle from its answer, and never issues a request after it. A normal tab close withdraws the same way instead of doing nothing, so nothing more goes out and nothing is dropped. A send the host rejected but kept as a card (keptAsQueuedMessageId) is the card's, from its reply or the journal, and never goes back to the composer. Adds the freeze tests: a send whose fate is unknown holds later sends no longer than its deadline, and one the host can neither confirm nor deny releases the next at once. * fix(native-chat): read a resend's turned-away call or reused id as unproven Ports the send-answer proof contract. A call the host turned away before running it (method_not_found, invalid_argument, unauthorized) proves only that this request wrote nothing, so it reads as never sent on a first attempt only; on a resend an earlier attempt may have landed, and it goes again under the same id. A resent id the host says was already used for other content (messageIdReused) proves nothing either, like an expired or conflicting id. Pins the rest of the contract: any row the host returns is its own, a thrown error is no answer whatever its code, and an older build's refused, held or outlived-Stop copy is handed back once and never sent. * refactor(native-chat): type the structured composer's send with its attachment type Keeps NativeChatStructuredSession.tsx within the file length limit. * refactor(native-chat): drop the kept-card guards the sender never needed A kept send's row is a rejection that was never a Stop's, so the sender already reads it as recorded, from its reply or the journal. The test that pins it stays; the two extra checks only covered a kept row that is also a withdrawal, which the host never writes. * test(native-chat): route launch tests' sends through the client wrapper the sender calls The sender sends through callStructuredAgentSession, but these launch tests replaced that module with a factory that answered nothing (and still named a probe that no longer exists), so every launch prompt resent until its 30 s deadline and the tests timed out. Each factory now hands sends to the runtime RPC mock the tests already answer, and expectations of a local send no longer ask for the remote-only compatibility option. * fix(native-chat): hand a message back without importing the composer's attachment hook The worktree purge reaches the launch prompt, which hands text back, and the attachment hook's imports reach the store. A test that builds the real store behind a mocked one then waited on itself and hung. Handing back now writes images to the draft store directly, as the hook's helper did, and a test pins that each returned image keeps its SSH connection. * fix(native-chat): one send per chat, with no line of sends behind it A chat with a send out took further messages into an in-memory line and sent them one by one. A message typed behind one in doubt then hit its own 30 s deadline and came back as not sent without ever going out. Now, as the common pattern does, a chat takes one send at a time: while it is out, Send is disabled and Enter leaves the text in the box. The sender refuses a second send instead of lining it up, so the 30 s deadline always runs from the send itself. A Stop or a tab close stops the one send: settled from its answer if its request is out, handed back as unconfirmed between attempts, or silently if it never went out. Notes sent from outside the chat while its send is out stay with their sender (not ready); a launch prompt that meets the person's own first message waits in the composer instead of being lost. * fix(native-chat): give a Stop-withdrawn note back to its chat once its notes were cleared Notes sent from outside a chat clear once their message is recorded. A message the host recorded as pending and a Stop then withdrew came back only to its sender, which had already let go of it, so the text was lost. The chat's draft now takes it, as an earlier build's outbox did. * test(native-chat): type the composer-actions probe without a cast * chore(native-chat): drop outbox wording left in comments and an empty locale group * fix(native-chat): pace failed checks, keep the host's reason, and hold the chat for its launch prompt - A send whose checks failed before its request went out (an unreachable or incompatible host, an unreadable history) was tried again at once, about a thousand times a second for 30 s. Attempts are now paced by the attempts made, whether or not their request went out. - A host that refuses every resend by throwing (native chat turned off, a journal that won't open) gave back only "couldn't confirm". The host's reason now comes first, still without claiming not sent. - A launch's prompt now holds the chat's one send from the click, drawn as sending, so a message typed while the chat starts can't overtake it; it goes out once the chat exists, and a cancelled launch frees it. - Notes whose send nobody could confirm say so instead of "did not accept", and notes launched into a new chat let go of their text once that chat's composer holds it. - An open chat keeps drawing a recorded send until its row arrives, so a reply that beats the history no longer makes the message flicker out. * fix(native-chat): hold a chat's sends until it has started, and send a failed chat's message with its restart A message sent to a chat still starting went out at once to a host that had no record of the chat yet, read for a fence it could not get, and came back as not sent. A message sent to a chat whose start failed restarted it but no longer went with the restart. While a chat starts, Send stays off and Enter leaves the text in the box, as with a send already out. A text message sent to a chat whose start failed restarts it and goes as the restart's first message, through the same staged-prompt path a launch prompt takes: it holds the chat's one send slot, drawn as sending, until the chat exists, and comes back to the composer if the restart fails again. Notes wait while a chat starts and ride a failed chat's restart, keeping their text until it is sent. * chore(native-chat): test the queue request, rejection words and card hand-offs; drop an unused clear - Pin which sends ask the host to queue, the moved rejection wording, and that a queue send whose card was handed off and then refused or withdrawn, or whose replay names a withdrawn card, is never handed back. - The send-at-most-once gate now says what the desktop promises after a reload: it never sends the id again, and hands the text back. - The legacy read names when it goes, and drops the notice clear nothing called. * fix(native-chat): keep a sent launch prompt's entry, and give back at once what can't go out - Cleaning up a launch prompt released its send slot even after the prompt had gone out, which deleted the entry the sender keeps once the host records it. A launch prompt recorded as pending and then withdrawn by a Stop was lost from both the chat and the box, and an open chat dropped the new chat's first message before its row arrived. The slot now gives back only a reservation that was never sent. - A send stopped before its request went out by something trying again won't clear (this client and the server can't talk, or the host refused the history read) kept Send off for 30 s and then said Orca couldn't reach the agent. It now comes back at once with its own cause: not sent, since nothing went out, or unconfirmed if an earlier attempt did. Transport errors keep the paced retries. * fix(native-chat): notes keep their own text through a new agent's launch Notes sent to a New agent whose start failed came back to the notes and also sat in the new chat's composer, so sending both delivered the text twice. The notes keep their text until it goes out (they hold it from the click), so the launch now says so and no composer gets a copy, on a failed start or a refused prompt alike. The tests that asserted the copy in the composer pinned the old double ownership and now assert the notes are its only owner. Notes that rode a failed chat's restart and ended unconfirmed now say Orca couldn't confirm them, as notes sent directly do, instead of that the agent did not accept them. * chore(native-chat): the send-once gate says what the desktop keeps across a reload The desktop keeps a send's id in memory only: a send still unsettled at a reload or crash is not resent and not handed back. The coverage notes no longer credit the renderer tests with durable identity across a remount. * fix(native-chat): say once why notes sent to a new agent did not go Since notes keep their own text through a new agent's launch, a prompt the host refused, nobody could confirm, or that found the chat's send taken came back to the notes with nothing said anywhere: the chat shows no notice for text its caller keeps. The notes menu now reports it once, with the toast a send to an existing chat already uses: not accepted, couldn't confirm, or not ready. A start that failed still says so in the new chat instead. * fix(native-chat): retry a history refusal the host says clears, and name it at the deadline A send stopped before its request went out came back at once for any refusal of the history read, including ones the host names as clearing (its journal briefly unavailable, a chat detached while the host quits), so the automatic retry was lost. Only a version mismatch and refusals that won't clear come back at once now; the rest go again on the paced schedule, and if the deadline still finds nothing sent, the words are the host's refusal rather than Orca couldn't reach the agent. * feat(native-chat): a send makes one request, and nothing ever sends it again The desktop resent a message under its own id for up to 30 s when the answer was lost. A send now makes exactly one request, as the common pattern's clients do: - An answer that is lost, dropped or proves nothing hands the text back at once with "couldn't confirm… check the chat". - A failure before the request goes out (the environment check, the history read for the fence, a refused connection) means nothing went out: the text comes back at once with its own reason, or as not sent. - The 30 s cap stays on the one request, so a host that never answers can't hold Send. Nothing ever resends, so nothing can go out after a Stop: a Stop only takes back a send still in its pre-send checks. The resend state goes with it (tries, generation, awaiting, stopped, the resend timer, the send-answers-proof probe, and the first-attempt/resend split in the evidence), and the send-once gate says the desktop never resends. * fix(native-chat): notes keep the chat's line, and a send held behind a rewind says it was not sent - Only a send whose text belongs to the chat's composer clears the chat's line. Notes sent from outside the chat no longer wipe a "couldn't confirm... Check the chat" line that explains text already back in the box. - A send the host turns away behind a rewind it could not confirm went back as "not sent" but said "couldn't confirm what happened. Check the chat". It now gives the rewind's reason and says the message was not sent. - Reliability gate names the single-request test and records a fresh evidence run; the sender test drops its leftover resend mocks and a duplicate Stop test. * fix(native-chat): a send ends even when putting its text back fails If writing the returned text into the chat's draft threw, the send never settled: it stayed "sending", the chat refused every later send until a reload. The send now always ends after a hand-back, the failure is logged, and the chat's line adds "Couldn't save your message." * fix(native-chat): a message typed during /clear stays in the box and follows the chat A /clear moves the chat to a new conversation, and its host refuses any send while it runs. A message sent then went out, came back refused into the old conversation's draft with its line, and vanished when the chat moved on: the box and the line now belong to the new conversation. - A /clear holds the chat's one send slot while it runs: Enter does nothing, Send shows busy and the text stays in the box, as for a send that is out. Notes sent from outside get "busy". - Once it moves the chat, the old conversation keeps taking no send until the view leaves it, and what is left of its draft moves into the new conversation's draft, after anything there: when the composer's /clear settles, and again when the view moves. * fix(native-chat): no "Send message?" or queue clear while the chat's send is out While a send is out (or a /clear runs) the chat takes no message, yet Enter over a held queue still opened "Send message?", and Clear queue deleted every card before its message was refused. Enter now does nothing there and the text stays; Clear queue re-checks and deletes nothing if a send went out after the question opened. * refactor(native-chat): take the /clear draft carry out of this change Moving the old conversation's draft into the one a /clear replaces it with fixes a bug main has too (text left in the box during a /clear stays with the old conversation), so it goes in its own change. Kept here: a /clear holds the chat's send slot while it runs, and the conversation it moved away from takes no send until the view leaves it. * fix(native-chat): a /clear's hold on sends always ends - A view that unmounted while a /clear that moves the chat was out left the old conversation holding its sends until a reload: the late reply kept the hold for a view that was gone. The reply now releases it. - The local call for a conversation command has no deadline of its own, so a /clear that never answers kept Send off for good. The hold now also ends at the command's deadline (195 s, the one the remote call already uses), whichever comes first. * test(native-chat): opening a chat an older build left stuck; hand back its copy in send order Pins, through the real chat hook, sends, legacy recovery and draft store, what opening such a chat does: the queued messages behind a message the host recorded in doubt come back to the composer once, in order, with the "not sent" or "couldn't confirm" wording; the chat is free to send under its read's fence; nothing happens while the chat has no fence here. The legacy reader now hands entries back in the order they were sent (queuedAt), as the older build's reader did, instead of array order. * fix(native-chat): a send this window turned away for a re-paired server comes back as not sent A managed server's update rotates its pairing, and this window's main process then answers the next call itself, before forwarding anything, with runtime_environment_changed. The send read that thrown answer as proving nothing, so the person was told Orca couldn't confirm a message that never left. It is now handed back as not sent, with the reason. Every other thrown answer still reads as unconfirmed once the request may have gone out. * Save a new chat's first message during create * Align opening-message types with the user-message wire * Keep chat publication and cleanup outside store initialization * Complete the create refusal fixture ledger * test(native-chat): prove a created first message waits for the agent's start and is handed over once * refactor(native-chat): keep the host and session hook under the line limit after the main sync * test(native-chat): a chat created with its first message and no pick still teaches its agent's default After the main sync, a created chat's agent starts from the delivery loop rather than the create call. Grok (through the real ACP adapter and model catalog) and Claude (through the real adapter) each still report the model their own config resolved to once the chat reads its options. |
||
|
|
8b2a5e45f1 |
Re-land Claude per-account folders (#24434, #26405) with the upgrade and proxy fixes (#26801)
* Revert "Revert Claude per-account folders (#24434, #26405) before release (#26638)"
This reverts commit
|
||
|
|
9021133929 |
Add the inert workspace layout model, Loader and Serializer (#26748)
* feat(layout): add the inert workspace layout model, Loader and Serializer One model of a workspace's tab layout (all tab kinds, groups, split trees, pane bindings, titles/colors/pin, sleeping records) in src/shared/workspace-layout, with a Loader from today's stored session partition and a Serializer back to it. The structural rules check and the pure pane/group tree helpers move into the same folder so the module can run them; their callers import the new paths. Nothing in the app calls the new module yet. * fix(layout): avoid toSorted in shared code and drop an unused helper The mobile bundle includes src/shared and Hermes lacks Array#toSorted. * fix(layout): one stored home per layout fact; Loader reports every rule it applies The row's terminal id, preview flag, worktree id and execution host are now derived on save instead of kept a second time. Groups never stay empty. The Loader reports row/tab-bar disagreements, re-minted ids, worktree id and host disagreements, keeps a row stored in two workspaces where the tab bar names it, and gives a pane id repeated in a second tab a new unbound pane. The rules check runs on what the Serializer writes. Fixtures become test fixtures, and a test lists every model field with the one fact it holds. * fix(layout): derive each tab's host from its owner and keep one preview fact per editor tab An editor tab names its file's owner (an SSH target or paired runtime), every other tab its partition. Where the stored tab and file preview flags disagree the tab loads permanent, so a draft can never be replaced. A row terminal that differs from the one derived from its focused pane is now reported. * fix(layout): one binding kind, one title, one host rule; records follow a reassigned pane A legacy row with no pane layout now loads as a one-pane tab bound to its terminal (reusing the leaf its records name), so the null-panes branches and legacyPtyId are gone. A pane given a new id because two tabs shared it takes its sleeping and incarnation records, scrollback and focus with it. A terminal's live title is one fact (the tab-bar label wins on load). Every tab-bar entry names its execution host by one rule. The fact-location test is now keyed by on-disk field and checked by mutating every source. * fix(layout): one change report by construction; records without copies The Loader now picks values by fixed precedence only and reports one field-by-field diff of the stored session against what the next save writes, over the disk-field tables (now in workspace-layout-disk-fields.ts, with session fields derived from SESSION_FIELD_OWNERS). Sleeping and closed-tab records live in their workspace without the pane key, tab and worktree id their key and workspace already give; the Serializer fills them. Tab-bar entries are written in the one tab order. * fix(layout): name the change report's key-list parameter's type * refactor(layout): key pane data by leaf, check the model itself, one legacy record - Each pane's data (terminal, incarnation, title, sleeping agent) is one leaf record keyed by leaf id, and scrollback beside it is keyed the same way. Pane keys are derived only when saving. The Loader gives a repeated leaf id a new id before attaching records, so rekeyPaneRecords is gone; records naming no pane are carried as stored. - The rules check runs on the model directly (ungrouped tab, empty group, group tree that disagrees with the groups, pane data without a pane); the disk-format rules stay separate. - The row-ownership marker and topology revision move into one legacy record outside WorkspaceLayout, updated by updateLegacyPersistence after each apply. - Fixtures include a terminal tab whose tab-bar id and terminal id differ. * fix(layout): join the group ids the tree-mismatch detail names * fix(layout): leave the stored revision map as is when no repo advances |
||
|
|
6013d093e2 |
fix(mobile): one host sidebar on iPad, with the page owning the host area (#26761)
* feat(mobile): let the page own the wide host area, one sidebar only
On wide layouts a detail route's page session ran app/h/_layout.tsx inside
the detail pane, judged itself wide, and drew a second host sidebar beside
the native one.
- The page draws the host sidebar only when init carries the new optional
`ownsHostArea` fact, never from its own width.
- The page manifest's `/h/[hostId]` route declares `canOwnHostArea`.
- On wide layouts the native host route mounts one host-area page session.
A declaring bundle serves it with every served route's grants, so hops
stay in the page, and the native layout drops its sidebar. Without the
declaration, or without a bundle, the session answers native-route and
every wide detail route stays native.
- The owner is recorded per host so the layout and switches agree and a
relaunch does not flash.
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): decide the wide host area per session, without a stored owner
Round 1 kept a per-host owner record that the native layout trusted. When
the record said the page owned the area, a detail route opened natively
(deep link, notification, handoff, narrow-to-wide with a detail pushed)
showed no sidebar at all.
- Drop the record. A wide session decides from the manifest it already
read: it is served only when the host route declares canOwnHostArea,
and it rebuilds when the layout class changes.
- The native layout hides its sidebar only on the host route, while that
host's page session is serving, as the shell screen reports through a
layout context. Detail routes keep the native sidebar, and a page there
draws none, so there is exactly one.
- Phones read and render nothing new.
- The host-area page can read and write every workspace-scoped key of its
host (chat tabs, live-input handles), as a per-workspace session does.
Claude-Session: lane-ipad-page-owns-host
* test(mobile): type the layout-class doubles rather than assert them
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): keep detail pages through a layout flip, guard capped keys
- A wide/narrow flip rebuilds a session only on the host route or under a
bundle without canOwnHostArea, where the answer changes. A detail page
under a declaring bundle keeps its document, scroll and draft.
- In the host-area page, a workspace key the 32-entry init cap leaves out
is named in storageOversize, so the page cannot replace the device's
chat-tab list from a default. The init frame bounds that list to the
page's schema; the host still refuses every key in the full list.
- A leaving host-area session clears only its own report.
Claude-Session: lane-ipad-page-owns-host
* refactor(mobile): host-area ownership from the reducer, storage read on demand
- The serving report is a focus-scoped boolean, so a host pushed over
another no longer leaves the first one's area unclaimed after the pop.
- The reducer takes `layout-changed {wide}`: it keeps the session when the
route view is unchanged and restarts it otherwise; `routeViewOf` returns
`ownsHostArea`.
- One web override, `usePageOwnsHostArea`; the native rule is inline in the
host layout.
- A host-area page reads a host workspace key from the shell on demand
(`native.storage.read`, granted to that session only) instead of init
enumerating the store.
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): host-area page reads back its own workspace-key writes
A page read right after a page write of the same key is answered from the
page's own value, not from a shell that may not have the notify yet. A
refused read crosses as an error, never as an unset key.
Claude-Session: lane-ipad-page-owns-host
* refactor(mobile): read-your-writes from the shell's mirror, final review fixes
- The shell answers a workspace-key read from the mirror, which every
shell-side write updates synchronously (removals held as known-absent),
and reads the store only on a miss. The page shim's written-keys set
goes.
- `onLayoutChanged` compares the route view field by field; the session
is created with its layout and the layout effect fires on `wide` alone.
- The device verb dispatcher's type excludes the storage read.
- The sidebar matrix mounts the real shell screen to decide the report.
Claude-Session: lane-ipad-page-owns-host
* feat(mobile): host-area page takes the whole screen from the download on
The native sidebar steps aside once the manifest says the page owns the
host area: fetching, activating, ready and the failure screens after them
are full screen, as on a phone. It stays while the host is being checked.
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): host-area workspace-key read survives a write during it
On a mirror miss the read went through the mirror's hydrate, which drops
its answer when any mirrored write lands meanwhile, so a stored key read
as unset right after a relaunch. A miss now reads the store directly, and
a store failure rejects rather than reading as unset.
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): a wide detail session hands the host route to the shell
A session opened on its own under a page that can own the host area
kept a hop to the host route in-page (a missing worktree's notice, or
leaving the session), drawing a second host list beside the native
sidebar. Its pairs now leave the host route out, so the hop goes to the
shell, which opens the area-owning session. Phones keep the hop in-page.
Claude-Session: lane-ipad-page-owns-host
* test(mobile): a phone mount's layout dispatch leaves the session alone
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): leaving a wide detail session returns to the host area
The leave-session chevron and the missing-worktree bounce hand the host
route to the shell on a wide layout, which pushed it: a second host-area
session over the session, with Back reopening the session. On a wide
layout the shell now dismisses to this host's route instead, taking the
href's params, or replaces the session when nothing is below it. Phones
still push.
Claude-Session: lane-ipad-page-owns-host
* fix(mobile): a narrow-wide flip restarts a detail session's page
The route view comparison now counts the paired routes, so a detail
session under a page that can own the host area restarts on a flip
instead of keeping the narrow pairs, whose host-route pair let the page
draw a second host list beside the native sidebar.
Claude-Session: lane-ipad-page-owns-host
|
||
|
|
1f8dce85d4 |
refactor(runtime-rpc-terminal-io): clean up Phase 3-3.8 code (#26895)
* refactor(runtime-rpc-terminal-io): clean up Phase 3-3.8 code - One admission prologue and one unary invocation shared by both RPC dispatchers - Delete rpc schema re-export shims; import from the shared params catalog - Delete the unregistered duplicate markdown tab method module - Collapse multiplex installer stage types; add isMultiplexStreamAttached - One source-identity guard in the ACK recovery snapshot - Single stream teardown in the renderer multiplexer - De-duplicate RPC method declarations; derive dispatch options from RpcContext - Share viewport-frame decoding and one head-trim loop for pending queues - Single sendTerminal call in sendTerminalStreamInput * test: point cross-version and scope checks at the moved browser tab-create schema; run transport parity test under Node --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> |
||
|
|
51e7181850 |
Keep remote terminal path links on their own host (#26696)
* Keep terminal workspace root links on their execution host * Resolve terminal root-link source host from the owner, not a missing connection id A direct SSH pane whose worktree id also exists on the desktop has no connectionId (ambiguous owner), which was read as local and offered the desktop workspace. Resolve the source via the owner-route resolver and skip the root shortcut when the source host is unknown. * Resolve terminal file links against the source owner's host A same-id SSH workspace left connectionId unset, so a rejected root link, the default-app row and Shift-click fell through to this machine's files. The terminal file context now names the resolved direct SSH host and refuses file access when no owner can be determined. * Keep an ambiguous terminal link owner unresolved instead of local The connection lookup ignores detected worktree rows, so a registered local row could override an owner the full resolver found ambiguous (registered local, detected SSH) and send link stat/open to this machine. Only a missing route may now defer to the connection lookup. * Re-resolve a held chat link's owner before rechecking it Native chat rechecks held link targets when a turn ends. A target resolved while its owner was local kept that context after a same-id worktree was detected on an SSH host, so the recheck still asked this machine. Each existence ask now re-resolves the workspace owner and refuses when it is unresolved or names a different host. --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
7b91405547 |
Let in-page links switch sections inside a chat visual (#26729)
* Let in-page links switch sections inside a chat visual * Make in-page links work in chat visuals on mobile and in WebKit The first fix (an about:srcdoc base in the visual) only reached desktop Chromium. On mobile, the page hosting the visual carried a policy with base-uri 'none', and a srcdoc visual inherits its host's policy before its own, so the base was refused and an in-page link still took the visual off its page and showed it as failed. The mobile web shell sends the same rule as a header. Separately, WebKit (iOS, and the web client in Safari) fires the frame's load event for an in-page link inside a sandboxed frame, and both hosts treated any second load as the visual navigating away and retired it. - The mobile host page and the mobile web shell header now allow only an about: base, so the shell's own base applies; the visual's own policy still refuses any base it declares. - Instead of retiring a visual on its second load, the host now asks the visual's shell after every load. A later load must be answered by the same run of the shell within the plugin panel watchdog's 5 s deadline; no answer, or an answer from a new run (a reload), still retires it. - Tests: unit tests for the policy, the answer reader and the frame's keep/retire rules, and a Chromium + WebKit test of both mobile surfaces that runs in the mobile web app CI job. * Keep any answered later load, and say plainly what the check is for The previous commit tagged each run of a visual's wrapper with a random id so a reload would still retire it. The visual shares a window with its wrapper, so it could read or set that id itself, and a reload only reruns the same Orca-written document, which is not an escape. Drop it: after any load past the first, the host asks once, and any answer on this visual's channel within the wait keeps it; silence retires it. - Comments now say the check is a tripwire for a frame gone blank or to another page; the frame guard (desktop), the host page's policy plus the app's load filter (mobile) and the sandbox are the boundaries. - Visuals get their own 5 s wait instead of borrowing the plugin panel watchdog's, because a 1 s wait retired a busy visual in WebKit. - Tests: a reload is now kept; going blank, or dropping the base and following a link, still retires. The CI routing for the shared wrapper is now pinned in the path-classification test. * Load the visual links check's mobile modules only where they can build The unit shards run every config/scripts test with only the root dependencies installed. This check imported a mobile/ module at load, and transforming it reads mobile/tsconfig.json, which extends a package those shards do not have. The transform error could not be sent back to the test worker under Bun, so the whole shard stopped with "DataCloneError: The object can not be cloned". Import the visual shell and the mobile host page inside the dependency gate, as the session-dictation check already does, so the shards skip the file without loading them. The mobile web app job, which installs mobile dependencies, still runs it in full. |
||
|
|
05ab94bd65 |
Move shared file watches when the selected remote host changes (#26632)
* Invalidate shared file watch targets when the selected host changes * Watch the selected host's own workspace root when hosts share a workspace id * Watch each open editor on its own execution host instead of the selected host --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
941c8d88c7 | Reset explorer tree lifetime when its execution host changes (#26627) | ||
|
|
93a6b1abff | Keep managed file drags out of desktop browser paths (#26698) | ||
|
|
6c20143807 | Preserve the selected host in explorer watcher ownership (#26616) | ||
|
|
9be39b6eb7 |
Restore remote explorer updates after server recovery (#26612)
* Restore remote explorer updates through the recovered app watcher * Keep the remote Explorer watched when it is shown as a fallback tab --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
4845ae8716 |
Restore editor file watching when remote host contact returns (#26606)
Co-authored-by: OrcaWin <alpha-eng@stably.ai> |
||
|
|
3bcb312043 |
Keep managed servers unverifiable until they answer (#26637)
* Require a server reply before treating a live managed process as serving * Log the unanswered live managed server like the other unverifiable verdicts --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: OrcaWin <alpha-eng@stably.ai> |
||
|
|
c12c211804 |
Preserve retained desktop browser pages during SSH conversion (#26572)
* Preserve desktop browser page placement when SSH workspaces convert * Place the browser-service-status page on the managed host explicitly Converted SSH workspaces now keep retained desktop pages local, so the spec opens its remote-placed page on the managed environment instead of relying on the retained page moving there. * test(e2e): refocus the managed browser page before retrying its Reconnect The managed host can seed a terminal for the converted workspace and the client mirrors it with focus, hiding the browser notice mid-test. --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: OrcaWin <alpha-eng@stably.ai> |
||
|
|
7b1242ba94 |
[CI] Reduce repeated test work and use pinned Bun for localization extraction (#26806)
* [CI] Reduce repeated test setup and retire source inventories * [CI] Give consolidated floating panel suites distinct titles |