Load the Hermes plural-rules polyfill from the phone app entry instead of
mobile-i18n, and transform mobile-i18n and its catalog loader without the
Expo tsconfig in root vitest.
* feat(wsl): re-key the profile of UNC Windows-drive projects converting to drive paths (D1c-4b)
* fix(wsl): keep the conversion's field table out of the main layout-writer census
* fix(wsl): merge the drive-keyed rows startup wrote for a UNC drive project instead of refusing
WSL Git lists a UNC /mnt/c project's folders under their drive paths, so startup discovery writes a
bare C:\-keyed worktree row (and its identity alias) beside the saved UNC one. The re-key then
landed both on one key and every conversion was refused as wsl_drive_unc_key_collision.
Before the re-key, a drive-keyed row holding only discovery bookkeeping is dropped with its alias
and identity row, so the saved row (instance id, name, links) takes the key. Any other two keys
that meet merge when one is empty or both match; only differing user data refuses, and the error
names the key.
* fix(wsl): treat a chosen workspace status as user data, so the conversion never drops it as a discovery row
Discovery writes only the default status. A drive-keyed row with any other status now counts
as the user's, so the conversion refuses with the key instead of dropping it.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): read /mnt/<letter> with the same case rule as the UNC path folding
Only a lowercase /mnt is drvfs, with the drive letter in either case, as
foldWslUncPathCaseInsensitiveParts already says; /MNT is an ordinary Linux folder.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): a refused duplicate spelling no longer blocks the drive folder's one converted project as an overlap
* test(wsl): a project nested under a refused duplicate's folder still converts
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Code blocks get a header with the language and copy button, syntax
colours from the file reader's highlighter, a line-number column and
horizontal scrolling. Short tables fill the message width, cells get more
room, quotes sit on a panel, bullets are dots, and Mermaid diagrams use
the app's borders and type.
Co-authored-by: Nico Hu <haoyu.hu@lexmount.com>
* feat(mobile): show chat images that live on the paired desktop
* fix(mobile): read every image type desktop chat shows
* refactor(runtime): share the bounded preview read and chat-image type check
* test: keep the chat-image tests typed and off importActual
A load that drops an unreadable row quarantines the file at the first
save. The save then re-read the now-missing file, took the empty list
as an admin deleting it, and dropped every valid device. The writer now
records its own quarantine and writes the save as is until a write
lands; a file someone else deleted still revokes everything.
* fix(wsl): Settings CLI status, startup CLI repair, interop health and link checks never boot a stopped distro (E9)
- cli:getWslInstallStatus: opening Settings takes a settled running read and shows a refreshable
"not running" status instead of starting the distro; the refresh button passes wakeWslDistro.
- Startup CLI repair re-reads each listed distro (settled) right before its repair spawns and
defers it otherwise, so a distro stopping mid fan-out is not restarted.
- Interop health: stop-triggered checks no longer trust the stop event's list; every check takes a
settled read, and again before the root repair.
- shell:pathsExist (chat link and terminal hover existence) refuses a stopped distro's UNC path
instead of statting it; callers already retry an unverifiable answer.
* docs(wsl): note the missing-kernel availability probe as the known E9 exception
* fix(wsl): shell:pathsExist refuses only the stopped distro's path, not the whole batch
One UNC path in a stopped distro no longer fails the host paths checked with it; the renderer
treats that path alone as unverifiable and retries it.
* feat(wsl-host): a paired phone reaches the desktop's WSL host and never starts its distro (E6)
Behind ORCA_INTERNAL_WSL_HOSTS and the Experimental switch. The desktop relay
lists its WSL hosts to phones. Every relayed call (resolve, call, watchChanges,
status.get) passes a never-start check, and a WSL host serves a phone only
while it already runs.
- WslHostPhoneGate holds the phone's view. The call check reuses E9's
focusReachability, so with no bridge in this process it refuses without a
running-list read. A host shows as "stopped" only on a confirmed stop
(liveness's distro-stopped, or a running list read by the check); anything
else gets a neutral "isn't available" message. Hosts are hidden from phones
while the Experimental switch is off or a Remove is pending.
- The relay host list sends optional `stoppedOnDesktop` only for a confirmed
stop. The phone badges those rows "Start on computer"; older peers ignore
the field.
- The paired-server rows producer carries WSL hosts like any server, so the
main-computed sidebar feed a phone reads has their rows.
- The paired-phone e2e drives a WSL host project end to end and asserts a
stopped distro is never started.
* fix(wsl-host): keep the phone's no-start check off non-WSL servers, and a stale stop off a ready host
- status.get runs the no-start check only for a WSL host, through a
check-only helper. SSH-managed and paired servers reach the status owner
exactly as on main: no reconnect, no redeploy, and the manual-disconnect,
coalescing and repair handling stay in place. The preparation option is
stripped before the probe.
- WslHostPhoneGate drops a 'stopped' read when a ready status arrived while it
ran (a per-host ready generation), and clears a recorded stop when a check
finds the host answering.
- A phone asking about a host that is switched off or being removed gets copy
that says so, not "open one of its projects".
* test(wsl-host): the real no-start helper leaves SSH-managed and paired servers untouched
* fix(wsl-host): tie a phone's confirmed WSL stop to that host's status, and label a host not connected
- A stop a phone's check confirmed is stored with that host's own status
object and holds only while that status is current. Another host's change no
longer clears it. Any status of its own (ready, a disable's closed, a failed
Remove's closed) does. A read never records a stop over a ready status, so a
read shared with one begun before ready can't. Removed hosts drop their
entry. The generation map and status listener are gone.
- The relay sends optional `unavailableOnDesktop` for a WSL host this desktop
isn't connected to and doesn't know is stopped. New phones badge it "Open on
computer"; older ones still show Connecting.
- The relay list reads the WSL host records once per poll (reachAll).
* refactor(wsl-host): one records read per phone check; note the gate's status identity compare
* test(wsl-host): read the phone's host flags as booleans in the paired-phone e2e
toMatchObject({ stoppedOnDesktop: undefined }) requires the key to be
present, and the desktop omits an unset flag, so the ready poll could never
match. The poll now compares relay plus both flags read as booleans.
* test(wsl-host): expect the neutral refusal once main's fake drops a stopped distro's bridge as closed
Main's fake connector (#34573) now publishes 'closed' when a stopped distro's
bridge drops, not liveness's 'distro-stopped'. So the phone's check reads the
stop under a ready status and doesn't claim it. The phone gets the neutral
copy and unavailableOnDesktop; the confirmed-stop copy stays unit-tested.
* test(wsl-host): the paired-phone e2e expects the confirmed stop again, and checks nothing booted the distro
Main's fake now publishes 'distro-stopped' when it drops a stopped distro's
bridge (#34624), as liveness does, so the phone gets "isn't running" and
stoppedOnDesktop. The spec also checks distros.json still reads 'stopped' at
the end: the fake boots a distro by rewriting it.
* test(wsl-host): the startup reconcile suite stubs the phone gate built beside the service
The reconcile still runs before the connector exists; the suite only lacked the new
setWslHostPhoneGate export on its service-instance mock.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(wsl): anchor the guest kill's stop read after the guest ran; re-check before each heal batch
A 'stopped' answer skips the guest kill as proof the group ended, so it must come from a probe
started after the guest reported its group. The Codex index heal re-checks the distro right before
each batch spawns its guest codex, closing the window during the inter-batch delay.
* fix(wsl): the Codex heal also stops on an explicit may-have-stopped note
A hook-relay or watcher exit notes the distro may have stopped before any running list sees it;
shouldStop now hears those notes too, not only the running-list diff.
* feat(wsl): fetch and cache a remote WSL hosts policy for the kill switch
Adds the client half of a remote switch that can turn WSL hosts off: a
small versioned policy file, downloaded from a fixed release-asset URL per
channel, validated, bounded, and cached in userData with a monotonic
revision. Nothing reads it yet; wiring into the gate follows.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(wsl): expose the cached WSL hosts policy as allow, block or missing
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Moves ~600 strings in the shared components (modals, drawers, host cards, dictation,
accounts), the pull request sidebar and diff review to the translation API, with all
ten translations.
- Invalid account snapshots are detected by error type, not by matching English text
- Credit expiry wording uses separate keys for one and several credits instead of
plural rules, which would pick the wrong sentence in Japanese or Russian
- The PR chip memo recomputes on a language change
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(wsl): keep background git and GitHub reads from booting a stopped distro
Git history, diff and status-follower reads, GitHub issue/work-item/check
polls, chat link existence checks, the composer's create-base prefetch,
the worktree-root fan-out and the Settings/Automations orca.yaml previews
now refuse or skip a stopped WSL distro instead of starting it (E9).
* fix(wsl): explicit opens may start a stopped distro; more polls gated (E9)
Folds the parallel G1-G6 work into this branch and splits background
reads from user acts:
- An explicit open runs as a user act for its distro and may boot it:
showing a diff tab or its Retry, showing Commits or its Refresh,
opening the checks panel or entering its tab, checks Refresh, a check
action, and linking or creating a PR. Main takes a wakeWslDistro flag
on git:diff, git:branchDiff, git:commitDiff, git:history and
gh:prChecks and runs those reads under runAsWslUserAct.
- Polls, timers, refreshes after Git actions, prefetches and fan-outs
stay background and are refused while the distro is stopped.
- Also gated: the hosted-review card poll for every provider, the GitLab
checks-panel poll (background flag), and the composer's open-time
orca.yaml check (Create re-checks in the foreground).
- Pollers keep the data they already show on a refusal: the issue on a
card, the checks list, an open diff and loaded submodule children, and
stop logging it.
* docs(wsl): note that a hosted-review poll's stopped-distro refusal is still logged (E9)
* fix(wsl): Settings re-asks orca.yaml once a stopped distro runs; drop link-check gating (E9)
- Link existence checks (shell:pathsExist / pathExists) are no longer
gated here: answering "missing" cached chat and terminal links as
absent and toasted "File not found" on markdown link clicks. The
pathsExist refusal lives in its own PR, which throws instead.
- Settings no longer sits on "checking" forever: a repo whose distro
refused the background check is re-asked on window focus, on
visibility, and after 10 s, until it answers. An unverifiable distro is
now marked (wsl-distro-unverifiable) and treated as unread too, instead
of being stored as "no orca.yaml".
- The sidebar issue poll and the Tasks list and count refuse with "Open a
terminal in it to start it", since their Retry is itself a background
read; the checks panel keeps "Retry", whose Refresh is a user act.
* fix(wsl): Tasks Refresh, interactive review refresh and manual PR lookups may start a stopped distro (E9)
- Tasks: a Refresh, Retry or search, or Tasks opened on a single repo,
passes wakeWslDistro through gh:listWorkItems and gh:countWorkItems
(IPC only; the RPC twins and web routes drop it). A multi-repo open
stays background. Their refusal says "Retry" again; only the sidebar
issue poll says "Open a terminal".
- hostedReview:forBranch wakes for an interactive request (the checks
panel's manual Refresh), so GitLab, Bitbucket, Azure DevOps and Gitea
reviews with nothing cached can load.
- gh:prForBranch, the renderer's fallback when refreshPRNow is missing,
is gated like the other card polls; a manual lookup wakes, matching
refreshPRNow's manual-only rule. The fallback call moves into its own
module, built from the refresh candidate.
* fix(wsl): only an explicit Refresh starts a stopped distro for review status (E9)
hostedReview:forBranch woke on admissionTier 'interactive', but the
visible-review scheduler sends 'interactive' for the selected card on a
timer, so that poll restarted a stopped distro every interval. The wake
is now an explicit wakeWslDistro flag (desktop IPC only). The card
refresh helper sets it, since every caller follows a user act (the
checks panel's manual Refresh, or a review created, linked or edited),
and the manual Refresh also wakes its pre-refresh git status.
admissionTier is back to priority only.
* fix(wsl): an explicit review Refresh never joins a refused poll (E9)
fetchHostedReviewForBranch let a forced card Refresh join an in-flight
forced scheduler poll, since the join only compared force. On a stopped
WSL distro that poll is refused, so the click got the refusal. The
in-flight entry now records the wake, and a waking request joins only a
waking flight; a poll may still join an explicit Refresh.
Each terminal read in the restart measurement opened a fresh connection,
which on WSL spawns a new wsl.exe bridge, so first-output time counted
bridge spawns the app never pays. Hold one shared control connection per
restart, as the app does.
The bridge fish launch's -C now also defines a fish_prompt hook that
sends the same percent-encoded OSC 7 as bash and zsh, only inside WSL,
after the user's config.fish.
The host answers a worktree delete as soon as it accepts it and lets Git
delete the checkout in the background. Clients that show a "removing"
marker ask it to wait for Git, but the CLI could not, so it printed
`removed: true` before anything was deleted, and a delete Git then refused
(for example a checkout with submodules) failed only in the host's log.
Scripts saw success, and every retry repeated the same silent failure.
`worktree.rm` takes an optional `waitForBackgroundRemoval` flag, and the CLI
sets it, so the command exits with Git's real result or error. It waits as
long as the desktop and web clients do and, if it stops waiting first, says
the delete may still be running and how to check. A reply sent on
acceptance now says `removed: false` alongside `removing: true`, so callers
that still get the early answer are not told the checkout is gone. Older
hosts ignore the flag, and the CLI then says the delete is still running.
Fixes#35135
Git refuses `git worktree remove` without --force for any checkout with
submodules, even when nothing is dirty. Orca's dirty check passed such a
clean checkout, so the delete was accepted, its terminals were stopped, and
Git's refusal arrived later in the background, where the CLI and
automation never saw it.
The dirty check now applies Git's own test (submodule repositories under
the worktree's admin directory, or a gitlink checked out with its .git),
which the native Windows path already used, and refuses a clean checkout
that fails it with a message that keeps Git's wording, so every app
version still offers Force Delete with the submodule warning. The same
test now decides when a dirty refusal names submodules. Force is not
applied automatically: it would also delete submodule commits, branches
and stashes that were never pushed.
Refs #35135
The rc was released right after Enter, so on Linux CI the keys' trip to the host
sometimes outlasted the rc's 50 ms poll and they landed after the prompt. Wait for
the tty's echo of the typed line first, which appears only if the bytes reached
the PTY while the rc still waited, and restore the check that they came before
the first prompt.
The mock built completed_at when the projection called it, after the
projection captured now. With 1 ms or more between the two, the
"stale" row was within the freshness window and the test failed under
load.
Moves ~600 strings in the root screens, settings, pairing, onboarding, accounts,
agent history, diagnostics, connection status, home and host workspace lists to the
translation API, with all ten translations.
- Connection verdicts carry an explicit `dialing` flag instead of matching the
"…" ending of an English label
- Update-failure copy and connection-path accessibility labels are built from data,
not by editing translated text
- Workspace status names stay the host's labels, as on desktop; transport errors
stay English
- The stale-key check keeps a plural family while any of its forms is referenced
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(orcad): harden the startup qualification marker (execPath, node-pty load failure)
- The key includes process.execPath, so a slot re-pointed at another Node build re-qualifies.
- A node-pty load failure in orcad (degraded local PTY routing) discards the slot's marker, so
the next launch re-probes node-pty and reports the cause; reported through a small listener so
the shared provider stays free of orcad imports.
- Tests: a schema-1 marker never matches; a Windows slot is never qualified by a matching marker.
* fix(orcad): discard the startup marker only after an in-flight record lands
A node-pty failure right after readiness could unlink the marker before the confirm's write
renamed it into place, recreating it. The discard now waits for the last marker write first.
* fix(wsl): background preflight and agent detection never boot a stopped WSL distro (E9)
Integration checks (git/gh/glab --version and auth status) and agent detection ran inside the
focused workspace's WSL distro on every mount, poll and status-bar render, and wsl.exe starts a
stopped distro. They now take a settled running read first and refuse (WSL_DISTRO_STOPPED or
WSL_DISTRO_UNVERIFIABLE) when it is not running. Window focus/visibility, retry buttons, agent
refresh buttons, a runtime choice in Settings and first-run onboarding pass wakeWslDistro, which
runs the check as a user act on that distro only. Running distros behave exactly as before.
* fix(wsl): a focus wakes only a focused WSL workspace's distro; end-to-end preflight gate test
A focus with a native workspace active sends no wake. Ports the real running-list preflight case
from #35395 and adds user-act scoping cases.
* test(wsl): model the running gate in the preflight RPC suite and cover a stopped distro
Windows CI runs the real gate, so the WSL detection case must state that the distro runs.
* fix(wsl): an agent refresh click never joins a background refresh it would be refused with
Store the wake flag with each in-flight refresh, as preflight.ts does, so a status-bar or Agents
refresh click during a mount refresh reaches main as a user act. Note why the RPC project branch
stays ungated.
* fix(wsl): a refused background check waits for the distro, and an agent picker wakes it
A preflight or agent detection refused for a stopped WSL distro was final: once the distro came
up, nothing re-ran it, so the tab-bar + menu offered no WSL agents (real-WSL golden). Now a refusal
is deferred until the distro is next confirmed running (deferUntilWslDistroRunning), and main tells
renderers to re-ask. Opening an agent-launch picker (tab-bar +, composer, continuation dialog,
source-control action dialog) whose list was refused retries it as a wake, never joining a
background probe.
* fix(wsl): an open agent picker wakes a refused list once, and never retries real failures
The picker wake fired whenever the list read 'failed', so a woken probe that failed again
(pending -> failed) re-fired it: an endless wsl.exe loop while the picker stayed open, and repeated
probes for native failures too. It now fires at most once per open per target, and only when the
last probe was an E9 refusal (distro not running/unverifiable), matched by the gate's message.
* fix(wsl): forget agent-inventory refusals when the inventory or its project contexts are cleared
* feat(wsl): offer Git for Windows in a Windows-drive WSL project's settings
Project settings show a Git row for a WSL-runtime project on a Windows drive (WSL
hosts on). "Use Git for Windows" checks the project, shows any blocker in plain words,
optionally sets core.autocrlf in the repo, and saves the returned runtime through the
normal project update. Once converted the row says where Git and terminals run.
Switching the distro keeps Git for Windows instead of silently dropping it.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): offer the Git choice only for a Git repo, not a folder
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(wsl): scope and path map for converting UNC Windows-drive projects (D1c-4a)
The mover refuses a project kept as a distro's UNC path into a Windows drive
(\\wsl.localhost\<d>\mnt\c\x). D1c converts it in place to C:\x. This adds the pure
part: which local repos and folder workspaces qualify (every stored path on the drive;
not remote; not already a C:\ project here), the UNC → drive path map, and the
worktree id each converted worktree gets (same repo id, drive path). Reuses the mover's
list of a repo's stored paths. Nothing calls it yet.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): say Windows denied access when adding a WSL path it refuses, not that it isn't a repo
* fix(wsl): name a refused WSL path only with WSL hosts on
The new message replaced "Not a valid git repository", which the renderer
matches to offer adding the folder as a non-git project. With the WSL hosts
gate closed the add fails with the usual text again.
(cherry picked from commit a5a70dad7743f679fd764c3e17a3e27b71c9f28b)
* fix(wsl): convert one UNC spelling per drive folder, and only folders the distro mounts from that Windows drive
- Two UNC spellings of one drive path (\\wsl$ vs \\wsl.localhost, \mnt\C vs \mnt\c) would
both convert into two projects. Each accepted conversion now claims its drive path, so the
next spelling is refused as a duplicate. Folder workspaces get the same duplicate check.
- Any /mnt/<letter> read as a Windows drive. The scope now takes the distro's Windows-drive
mounts (drvfs/9p from its mountinfo, parsed as the WSL-host drive guard does) and converts a
path only when its mount is that same whole drive. A folder workspace has one path, so that
check is its mixed-location check too.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): match the distro's drive mount point case-sensitively, so a real /mnt/C directory never converts onto C:
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
upsertDelegatedMobileDevices returned every planned entry, including a child whose row was
removed on disk and so dropped by the merged save; the parent would pass that dead token to the
phone. It now returns only entries still in the written registry.
* perf: cache folder workspace connection inference
* fix: preserve folder resolver fallback for partial catalogs
* test(renderer): trim folder connection cache test to one direct warm-read check
Drop the zustand store wrapper and duplicate 1,000-repo case, and use a neutral fixture path.
* test(renderer): drop folder connection read-count test
The invalidation and tri-state test guards observable behavior; the getter
read counter only pinned the cache implementation.
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(github): preserve concurrent changes on thread rollback
* test(github): assert reaction publication before rollback
* fix: restore thread resolution on newly posted replies
* test(github): trim thread rollback tests to behavior guards
Drop duplicate false/throw variants, the cleared-cache and paired-source
cases, and the helper case already covered by the remaining lib tests.
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
- Deduplicate candidates per command: 'tool' and 'tool.CMD' may resolve to
the same on-disk file and both must still be found.
- Probe known candidate names directly when readdir is denied (EACCES/EPERM):
an execute-only directory cannot be listed, but stat on known names works,
which is what the per-candidate lookup did.
- Skip the install-dir fallback's PATH re-scan: the batch already proved the
missed commands absent on the PATH it searched, and that PATH is a superset
of the fallback's (merged persisted PATH on Windows, the same filtered PATH
on a WSL host), so the fallback scans install directories only.
findCommandsOnLocalPath() replaces one isCommandOnPath() call per agent
command: it reads each absolute PATH directory once with readdir and matches
command names and PATHEXT permutations in memory, then verifies only the
hits through isExecutableFile. Symlink, directory, permission,
case-insensitivity and absolute-only PATH semantics match the per-candidate
lookup. On the machine in the issue this replaces about 24,000 stat() calls
per detection run with about 38 directory reads.
Fixes#34636
* fix(editor): restore diagram scroll after async rendering
* fix(editor): retain pending diagram scroll while hidden
* fix(editor): key Mermaid restore on rendered source and cancel it on user scroll
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(editor): preserve folds and horizontal scroll across tabs
* refactor(editor): keep reading state cache with its lifecycle
* test(editor): give stale-cache model its URI
* refactor(editor): keep editor view state cache beside diff view state
Move editorViewStateCache into scroll-cache.ts, clear it in the shared model
lifetime fixture, drop the e2e evidence spec and the duplicate LRU test.
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* Read sidebar PR and stack metadata in one GraphQL query
* Preserve direct PR error recovery without duplicate GraphQL reads
* Keep combined sidebar queries out of merge preflight
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* feat(wsl): offer Git for Windows in a Windows-drive WSL project's settings
Project settings show a Git row for a WSL-runtime project on a Windows drive (WSL
hosts on). "Use Git for Windows" checks the project, shows any blocker in plain words,
optionally sets core.autocrlf in the repo, and saves the returned runtime through the
normal project update. Once converted the row says where Git and terminals run.
Switching the distro keeps Git for Windows instead of silently dropping it.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): offer the Git choice only for a Git repo, not a folder
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Subscribe to onDidChangeModelContent directly instead of the
@monaco-editor/react onChange prop, which calls editor.getValue() before
Orca's ownership and programmatic-sync checks run. Programmatic echoes
(external reloads, shared-record commits, read-only live tail) no longer
materialize the full model text only to discard it.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>