mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 17:17:38 +00:00
d3fc80292be694f454717e18f82fdc19dbe353de
1153
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7244bf3e6f |
Reclaim idle worktree space automatically on dev startup (#28864)
* Run safe worktree cleanup on dev and add interactive pnpm reclaim * Rename storage cleanup command to reclaim-space * Keep real stream constructors in transcript dependency tests * Detach cleanup output and align historical cache previews |
||
|
|
13a75d3939 |
[CI] Reduce redundant test work and import existing helpers directly (#28365)
* [CI] Reduce redundant test work and import existing helpers directly * [CI] Preserve provider guards and pin the mobile browser test core * [CI] Fix CI test setup and verify retained contracts * [CI] Compare native media chunks without boxed byte arrays * [CI] Detect shifted native media reads with position-sensitive bytes |
||
|
|
4559c250b3 |
fix(windows): restrict secure files in-process instead of spawning icacls (#28135)
* fix(windows): restrict secure files in-process instead of spawning icacls Every secure write on Windows spawned icacls.exe five times on the calling thread (the Electron main thread for most stores): verify, /reset, /inheritance:r /grant:r, verify, verify. Process creation under endpoint security costs ~0.6 s each, so each write froze the UI for seconds (#26027). The /reset + /inheritance:r pair is also what behavioural EDR scores as ransomware tradecraft (#25583). Add native/windows-security (@orca/windows-security): a small N-API addon over advapi32 that reads and writes DACLs in-process. It exposes the token user SID, a DACL read as SDDL, a DACL write (sync and on the thread pool), a create-with-DACL file write, and an additive grant. Policy and verification stay in TypeScript. - writeSecureFile creates each temp file already carrying the protected user/SYSTEM/Administrators DACL (CreateFileW + SECURITY_ATTRIBUTES), reads it back once, and renames it. No ACL is modified on the write path and no process starts. Before: 5-7 spawns, 94-138 ms per write. After: 0 spawns, ~0.5 ms. - A secure directory is verified once per process. It is rewritten only when verification fails, on the thread pool, because the write walks every descendant (~2 s on a 29k-entry userData). - The verifier follows OpenSSH's rule: only the user, SYSTEM and Administrators may be granted anything, and the path must be protected (or, for a file, inherit from a secure parent). DACLs written by the icacls-era hardening pass unchanged, so there is no migration. - If the addon cannot load, the write still happens and reports unrestricted, logged once. There is no icacls or PowerShell fallback. - grantDirAcl, the startup userData grant, and the install-dir probe and package repair use the same addon, so whoami.exe and icacls.exe are no longer spawned anywhere at runtime. - orcad's Windows slots ship the addon beside their bundles (built per arch, PE-machine checked). Its data-root privacy check fails closed, so without the addon a Windows orcad would not start. Fixes #26027 Fixes #25583 * refactor(secure-file): harden existing Windows files through the sync lane The read path called restrictWindowsPathSync directly and recorded success itself; the existing sync lane already does both. One call site fewer. * refactor(windows-security): one load, one rule, no fallthrough (review #28135) - The descriptor parser is anchored, so a conditional ACE (its body holds parentheses) or anything else it cannot read fails closed instead of verifying the ACEs before it. - findSecureDaclViolation is one flat rule: protected, allow rules only for the user, SYSTEM and Administrators (OpenSSH's ACE rule), and full control for the user. The inherits-from-a-secure-parent exception is gone: it accepted exactly what loosening the parent reaches. - The addon and the user SID load once, behind one wrapper that adds the extended-length prefix to every path and runs async DACL writes to one path in order, so a startup grant cannot land after a re-lock and restore the broader DACL. - With the addon loaded, a failed born-restricted create throws with the matching Node error code instead of falling back to a plain write. - A grant leaves a NULL DACL untouched instead of turning 'everyone' into 'only this SID'. WriteFile runs once and fails on a short write. - The artifact create-intent store writes through writeSecureFile and drops its own temp writer, directory LRU and synchronous directory re-lock. - Test seams the global fake makes redundant are gone. * fix(packaging): fail a Windows build whose workspace addon binary is missing or foreign-arch The @orca/windows-* workspace links exist on every host, so their presence proved nothing: a missing or wrong-architecture .node only surfaced at runtime, as unrestricted secure files or an orcad that refuses to start. beforePack now reads each addon's PE machine against the target arch. * refactor(windows-security): prune what the native ACL left dead (review #28135) - Sync-spawn ratchet: hardenSecurePath and the sync-flag exemption it alone used are gone, and the advice and baseline header no longer say secure writers run icacls. - The install-dir probe reads ACEs through parseSddlDacl, so an ACE it cannot parse fails the whole reading closed instead of being skipped; AC is a resolved alias there now. - The packaging check reads the addon binary through node_modules, the copy that ships. - No winCode-to-errno table: nothing reads .code off a failed secure write. - The load memo is not mutated; secure-path keeps its own log-once flag. - grantInstallDirPackageAcl is a plain function, and secure-file restricts a Windows directory and a POSIX path directly instead of through one two-platform helper. * fix(windows-security): resolve LA in real-ACL tests; tear a file whose close fails - The GitHub Windows runner is the built-in Administrator (RID 500), whose SID reads back as LA. Production already resolves it through localDomainSidOf; the win32 test helpers parsed without it. One shared readDaclOf resolves aliases for every real-ACL suite, and the verifier's unit test covers an LA-aliased directory and LA as a stranger. - createFileWithDacl treats a failed CloseHandle like a failed write (lost data on a network volume) and deletes the torn file. - Drop a duplicate test reset and a typo. * fix(windows-security): load only from inside the app; read DACLs as structure (review #28135) - Loader: orcad's staged binary first, then the workspace package only if its real path is inside the app (process.resourcesPath, or this checkout). A bare specifier otherwise walks every parent up to C:\node_modules, which any local user may create, and orcad holds credentials. - The addon reads a DACL as { protected, aces: [{ type, flags, mask, sid }] } via GetAce, with a SID only for plain allow/deny ACEs and null for a NULL DACL. findSecureDaclViolation and the install-dir probe check that structure, so conditional, callback and object ACEs fail closed. The SDDL parser, its alias table, LA/localDomainSid resolution and getDaclSddl are gone; SDDL is only the write format. - Install-dir tree pass: files flagless as before, but a directory only when its own DACL is protected (inheritably). Re-granting inheriting directories re-propagated each subtree (3.2 s for 1,093 directories). The root is no longer granted, or counted, twice. The two passes are plain functions behind a { root, tree } seam. - One namespacing (path.win32.toNamespacedPath) at the addon boundary, also the per-path ordering key; the comment states the real sync-grant invariant. - restrictWindowsDirectory(dir): Promise<boolean> replaces the callback lane; the reporter is guarded once, so the 'settle' stage is gone. - Sync-spawn ratchet: the secure writers no longer spawn or block, so they leave the gate (109 -> 61 uses). - Errors name the Win32 call and code only; a failed GetSecurityDescriptorControl fails the write instead of defaulting to unprotected. * test(secure-file): assert the durable POSIX write's outcome, not the old chmod order writeSecureFile now chmods the temp file to 0o600 before fsyncing it, so the fsync also covers the mode change and the file is owner-writable when opened. Assert what matters under umask 0o200: the write succeeds, the temp file is fsynced read-only, and the published file is exactly 0o600. * fix(windows-security): namespace paths with the host's toNamespacedPath path.win32.toNamespacedPath rewrote POSIX temp paths (/tmp/x -> \tmp\x) in the Linux runs of the Windows-logic unit tests, so the fake addon wrote to the wrong place. The addon only runs on Windows, where the host function is the win32 one; elsewhere it is the identity. The long-path assertion runs on Windows only. * test(windows-security): assert the install-dir long-path prefix on Windows only The prefix comes from the host's toNamespacedPath, which is the identity off Windows; the Linux run of this suite expected the win32 escape. * fix(windows-user-data-acl): grant the root even when its children cannot be listed (review #28135) A readdir failure on userData aborted the whole grant, so the root grant that could repair a DACL refusing the listing was never attempted. The listing failure is now recorded, the root is still granted, and the marker stays withheld so the next launch retries. * test(windows-security): wait for relock propagation, accept Entra ID SIDs (review #28135) - The large-relock test waited only for the parent to turn protected, which happens before propagation reaches the children, then read a child. It now waits on the parent and both ends of the child range. - The token-user test rejected S-1-12-1 (Entra ID) accounts, failing the suite on Entra-joined dev machines. --------- Co-authored-by: Orca Worker <orca-worker@localhost> |
||
|
|
c8996d76a5 |
Speed up daemon smoke checks and keep compiler slots busy (#28106)
* Remove repeated daemon smoke builds and idle compiler slots * Test compiler scheduling through its process interface * Keep preview component below the existing line limit with a type-only split |
||
|
|
125007b680 |
chore: upgrade terminal dependencies to matching payload betas (#27935)
* chore: upgrade terminal dependencies to the matching payload betas * test: harden xterm payload contract, align mobile pins, fix serialize-at-ref across version bumps - Cover foreign-payload replacement and the shared blank-cell reset in the installed image payload contract (both mutants previously survived). - Bump mobile's xterm, webgl and unicode11 pins to the root's betas. - Resolve the ref's own serialize version and patch so the differential fuzz baseline builds across a version bump. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
fa4ef2b961 |
ci: stop new main-process code from freezing Orca with synchronous launches (#27756)
* ci: ratchet synchronous child-process launches in main and shared code
The Electron main process freezes every window while a synchronous child
process runs, and on Windows each launch is slow because antivirus scans
it. Nothing stopped new synchronous launches from landing in main-process
code, and the spawn observer behind ORCA_MAIN_THREAD_DIAGNOSTICS only saw
async spawns, so the worst blocks were invisible to it.
Ratchet: check:main-sync-spawn-ratchet parses production src/main and
src/shared files (test-only paths excluded) and fails when a file not in
config/main-sync-spawn-baseline.txt reaches execFileSync, spawnSync or
execSync from child_process, runProcessSync from @orca/process-host, or
one of the synchronous secure-file writers (they run icacls on Windows).
Named, aliased, namespace, default, require() and import() forms count.
A baseline entry whose file no longer launches synchronously fails as
stale, so the list can only shrink. It runs in lint and in the PR
static-analysis job next to the process-host import check.
Observer: runProcessSync now reports to the spawn observer, timing the
whole call (that is how long the thread was stuck) and reporting from a
finally so failing, throwing and timed-out children are counted too.
Runtime behavior is unchanged except that the diagnostics observer now
sees synchronous launches; with no observer registered the sync path
pays one extra branch.
* ci: count sync launches per file and gate the repo's sync wrappers
The sync-spawn ratchet only tracked which files launched synchronously, so a
file already on the list (wsl.ts, win32-utils.ts, git-exec-file.ts) could add
more launches unnoticed, and new callers of the repo's own synchronous
wrappers passed CI.
The baseline now stores a per-file count of uses, in the same format as the
focus-read ratchet: a rise or a new file fails, a lower or zero count fails
until `pnpm check:main-sync-spawn-ratchet --prune` lowers it, and --prune
never raises an entry. Every value reference to a gated function counts
(call, hand-off, alias and its uses, re-export); imports alone count nothing.
Gated wrappers: gitExecFileSync (and the git/runner re-export),
restrictWindowsPathSync, hardenSecurePath when called with sync: true,
grantDirAcl, getWslHome, listWslDistros, wslUncDirectoryExists,
isWslAvailable (and the wsl.ts re-export), isPwshAvailable. Their 18
current caller files join the baseline.
Failure messages now give advice per family: the async process-host API for
child-process launches, the async twin for wrappers, and for the secure
writers a note that no async secure writer exists yet, so the sync one stays
and must never become a plain write (that drops the Windows ACL hardening).
Also refresh two stale blockMs descriptions and drop a no-op line from the
spawn-observer "stays silent" test.
* ci: count hardenSecurePath unless visibly async, and tighten ratchet tests
hardenSecurePath was counted only when `{ sync: true }` was written inline,
so moving the options into a variable or a spread dropped the count and the
check then asked for a prune. It now counts every use except a call with no
options or a spread-free object literal whose `sync` is absent or false.
Also: resolve backslash paths in the importing file as well as the
specifier; still visit heritage and instantiation expressions
(`extends mixin(fn)`, `fn<T>`); state the reference-only counting limit;
and point the secure-writer advice at raising this file's baseline count.
Tests cover the hardenSecurePath shapes, the alias chains that need the
fixpoint loop, and a prune that must not raise a grown row.
* test(ci): pin the main sync-spawn ratchet background step
* fix: count secure hardening calls with spread arguments
|
||
|
|
7c13365f03 |
refactor(build): relay survivors named for what they are (#27962)
Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
8cc779e576 |
Editor: Nim and Typst on the shared TextMate layer, so a long line can't freeze the window (#26987)
* feat(editor): run Nim and Typst on the shared TextMate layer with per-line limits The editor's Nim and Typst highlighting moves from vscode-textmate onto the Shiki core + Oniguruma layer chat uses, with the same per-line length cap and time limit. A skipped line leaves the rest of the file plain instead of freezing the window. Chat code block labels now name catalogue languages (vue -> Vue, ts -> TypeScript). * test(native-chat): expect the catalogue label for a ```ts fence |
||
|
|
9ad45591af |
refactor(layout): keep compatibility code in named folders behind one entry (#27556)
* refactor(layout): keep compatibility code in named folders behind one entry Moves the old-client translators into src/shared/workspace-layout/old-client/ and the remote layout snapshot recorder and persistence into src/main/remote-layout-snapshot/, each behind an index.ts. A new check-compat-boundary-imports script, run by pnpm lint and the PR workflow, fails when code outside a compatibility folder imports past its index or when a file other than the folder's named importer imports it. Moves only; no behaviour change. * test: drop whole-repo scan from boundary check unit tests; CI step runs it * fix(lint): list only existing compatibility folders; resolve renderer aliases in renderer files |
||
|
|
f9794d8efc |
refactor(remote): one paired E2EE handshake core for desktop, CLI, web and mobile clients (#27523)
* refactor(remote): one paired E2EE handshake core for desktop, CLI, web and mobile clients Every paired client now builds its hello, checks the host's ready, seals its auth frame and opens host frames through src/shared/paired-e2ee-client-handshake. Platforms inject their own NaCl/base64 primitives. The v2 client session and its pure-JS key schedule (@noble/hashes 1.8.0, the version mobile pins) move to src/shared, and the per-host v2 latch policy is shared with an injected store. No wire change: frames match the captured legacy and v2 fixtures byte for byte, and a cross-version test drives the core against the released host and the released client against this host. The auth step is now async so a device-key signer can slot in later. * fix(remote): keep @noble/hashes out of the CLI's unbundled runtime The packaged CLI loads src/shared output from disk, so a bare @noble/hashes import failed the packaged-runtime check. The v2 key schedule is now a primitive: Node clients use the node:crypto schedule (moved to src/shared so the CLI can reach it), while the browser and phone keep the pure-JS one. * fix(mobile): re-check the v2 latch before sending a legacy auth frame The auth step is async, so another socket can latch the host to v2 while a legacy auth frame is being sealed. Refuse it at send time, as before. --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
e969881be5 |
chore(ratchet): layout-writer ratchets for main and renderer (#27431)
* chore(ratchet): layout-writer ratchets for main and renderer Two per-file ratchets that may only go down: main-process callers of the Store's layout setters plus direct edits of saved session partitions, and renderer writes of the window's layout and per-view selection fields (including computed-key and spread writes, counted where the key or object is built). The frozen-mirror writers are exempt. Wired next to the focus-read ratchet in lint and the PR workflow. * chore(ratchet): count only membership writes of editor and browser entries A .map over the existing openFiles or browser tab list keeps its entries and order, so it is a content update (draft, git status, URL) and is no longer counted by the renderer layout-writer ratchet. * chore(ratchet): ignore variable keys and pass-through shorthands A variable key such as exitCodes[ptyId] names no field, so only string keys count. A shorthand key counts only in an object handed to set, setState or a Store writer; elsewhere it passes a value on. * chore(ratchet): prune renderer baseline after main moved |
||
|
|
34d7884a52 |
chore(ratchet): one focus-read ratchet (#27426)
Fold the empty owner-routing baseline into the focus-read ratchet. The three deleted focus-routing helpers stay banned as a forbidden-name list. Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
c69f9d2f62 |
Add manual cleanup for worktree Electron storage (#27414)
* Add manual worktree storage cleanup command * Validate cleanup exclusions and preserve failure diagnostics |
||
|
|
ac156c0302 |
perf(ci): overlap Bun typechecking and skip redundant alias scans (#27382)
* perf(ci): skip unnecessary alias scans and compare preflight compilers * perf(ci): overlap measured Bun typechecking with static checks * perf(ci): use measured Bun lint runtime and strengthen compiler parity checks |
||
|
|
2b4b60a87e |
refactor(relay): delete the SSH relay server, its build assets and tests (#27215)
* wip: delete the SSH relay server and its build, assets and tests * wip: drop main/relay plugin conformance; WSL reader lookup test * fix: drop the emptied relay bench; prune baselines * test: keep the native halves of tests that also covered the relay * chore(ci): drop shard timings for the deleted relay server tests * fix: keep the directory listing budget that darwin terminal names now import --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
ff27338299 |
refactor(ssh): connect fails for hosts orcad can't serve; remove the relay client path (#27214)
* wip: connect fails for hosts the managed server can't serve; remove relay session, deploy and relay UI * wip: delete relay-only client modules left unreachable, prune their tests and gates * wip: format * wip: exhaustive unserved message * wip: drop relay attestation test for the deleted ownership proof * fix: prune stale baselines; type the test transport stub * fix(ssh): census proves leftover relay leases; name the remedy for older terminals; translate every connect-failure surface * test(ssh): leftover leases defer to the host census * test(e2e): remove relay-path SSH e2e specs and their CI lanes * test(e2e): drop the auto-convert case that built its relay era through a live relay * test(e2e): mark relay-era browser and catalog journeys fixme until they seed a profile * test(e2e): seed relay-era browser and catalog journeys from a saved profile The three journeys built their old-version state through a connect without an orcad template, which now refuses the host. They now start from a seeded relay-era profile, so the first connect converts the host as an upgrading user's would. * chore(ci): drop shard timings for the deleted relay tests * test(e2e): carry a relay-era login cookie across the browser conversion; own every launch * test(ci): drop the deleted SSH layout oracle from its route * test(e2e): open the retained browser after conversion, retrying a pre-connect card * test(e2e): bind the relay-era browser partition before seeding its cookie A relay-era build always recorded the partition binding before a page stored data in it. Seeding the cookie into an unbound partition made the binding store refuse it (browser_route_partition_binding_store_invalid), so the retained tab showed the generic routing card and Retry could never clear it. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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. |
||
|
|
2cb2bef67e |
feat(native-chat): highlight code blocks and shell commands (#26343)
* feat(native-chat): highlight code blocks and shell commands Uses Shiki rather than the highlight.js already in the preview: it can resume mid-block while a reply streams. * fix(native-chat): leave the tool row command unhighlighted * refactor(native-chat): highlight code through a shared TextMate interface Chat code now goes through one renderer highlighting interface built on Shiki core and the Oniguruma WASM the editor already loads for Nim and Typst, with VS Code Light+/Dark+. Lines that are too long or too slow leave the rest of the block plain, failed grammar loads retry from a mounted block, every block shares one time slice, finished-block caching counts retained text, each theme keeps its own formatting, Vue template expressions are colored, and tool-row commands take the grammar of the shell they ran in. * chore(deps): drop pnpm self-install entries from the lockfile Keeps the lockfile change to Shiki alone; the earlier commit picked up the @pnpm/exe entries pnpm 12 writes when it runs in a fresh checkout. * test(native-chat): give cold grammar loads time in highlighting tests The first colored block in a test file loads its grammar and the regex engine, which took over a second on a busy CI runner. --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> |
||
|
|
3c075883ed |
feat(native-chat): make native chat replies flow in and the transcript glide when following (#26238)
* feat(native-chat): pace and fade streamed reply text Snapshots land a clause at a time, 50-700 ms apart. Drawing behind them at an eased speed is what makes a reply read as flowing. * feat(native-chat): glide the transcript when following and jumping to latest The offset is still pinned at once; only what the pin moved is eased, so nothing races the virtualizer or a reply that keeps growing. * chore: list remend with the other bundled renderer packages dependencies is for packages the main process loads at runtime. * Bound streamed reply reveal and preserve chat interactions * Smooth overlapping chunks without postponing reveal deadlines * Fix first-reply following and pin settled layout changes * Pin concurrent media layout changes without a follow glide * Keep native chat layout stable when replies complete * Model delayed browser scroll events in navigation tests --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> |
||
|
|
c0273b1ff7 | test(e2e): move the Source Control reveal golden into its own spec so older release tags skip it (#26005) | ||
|
|
37ff3873a0 | Run combined localization catalog verification on Bun (#25999) | ||
|
|
d8c871a1f0 |
Speed up unit tests with cross-runtime duration scheduling (#25967)
* Schedule unit tests across runtimes by measured duration * Keep new SQLite fixture suites on Node after updating main * Inject scheduling timings instead of mocking the module * Keep agent-session database lifecycle contracts on Node |
||
|
|
72b84118e0 |
test(e2e): terminal layout parity check against main (#25681)
* test(e2e): add terminal layout parity check for topology refactor PRs Runs fixed terminal-layout journeys in the real app on two builds, captures the renderer topology and the saved workspace session, normalizes volatile values and fails on any difference not declared for a named bug. Co-Authored-By: Claude <noreply@anthropic.com> * test(e2e): record quit exit status and report paths main does not reproduce Co-Authored-By: Claude <noreply@anthropic.com> * test(e2e): invoke pnpm correctly under corepack and silence the typeless-module warning Co-Authored-By: Claude <noreply@anthropic.com> * test(e2e): accept pnpm's forwarded -- in the layout parity runner Co-Authored-By: Claude <noreply@anthropic.com> * test(e2e): close parity panes through the user's chord and treat absent maps as empty Driving PaneManager.closePane directly left main to learn of the close from the PTY exit, which raced quit; the keyboard path commits the close in main first. Co-Authored-By: Claude <noreply@anthropic.com> * test(e2e): build parity checkouts before running, forward -g, and add a drag-out scenario Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
83cf7cf5e2 |
perf(ci): compile release JavaScript once for all packaging hosts (#25828)
* perf(ci): share release JavaScript across packaging hosts * fix(ci): verify the projected web entry in release archives * fix(ci): use the Windows system archive tool for release bundles * test(ci): retain stylesheet evidence in release build comparisons * test(ci): verify release parity across native color rounding * test(ci): normalize manifest asset references without changing import order * test(ci): compare portable outputs across Windows text and color formatting * test(ci): preserve module identity across dependent asset hashes * fix(ci): keep SVG build inputs identical across release hosts * fix(ci): stabilize compiler inputs and projected web bindings * fix(ci): retain vendor minification in projected web output * test(ci): normalize platform-specific pnpm manifest source paths * fix(packaging): exclude shared build staging from application files * test: align thinking-state fixtures with the current source shape * test(mobile): reuse message fixtures within the line limit |
||
|
|
3ec38b8c6d |
Run Vitest on Bun with Node runtime contracts (#25840)
* Run Vitest on Bun while preserving Node runtime contracts * Preserve runtime timing provenance and keep the Bun pin in config * Scope builtin compatibility mocks to test-only lint exceptions * Give capture retention fixtures distinct filesystem timestamps * Await the copy button success state in the React fixture * Bound Node test worker shutdown and tighten migration fixtures |
||
|
|
020cebeff6 |
Add standalone Agent Client Protocol client layer (#24990)
* Add standalone ACP protocol client and session runtime * Protect ACP transport teardown from late stream errors * Retire incoming ACP request ids before publishing responses * Narrow ACP configuration requests and transport message types * Remove redundant ACP request handler return unions * Keep ACP waits caller-owned and preserve protocol extensions * Preserve open ACP decisions through prompt completion * Generate open ACP enums and check the generated schema offline A newer or vendor enum value (tool kind, tool status, option kind, stop reason) no longer fails the whole message: generated enums accept the known literals plus any other string, typed so callers can still narrow on the known ones. The generated header now records the pinned input digests, the generator digest and a body hash, so `verify:acp-protocol` catches a stale or hand-edited file without network access; it runs in lint and the PR workflow. * Land the ACP runtime contract the agent adapters use - Deliver notifications other than session/update through onExtensionNotification, in arrival order with session updates. - Accept _meta on prompt, setMode, setModel, setConfigOption and cancel. - cancel() always sends session/cancel once the session runs, since the agent can be in a turn it began itself; only a successful send is shared, so a failed write is retried. - Cancel aborts each open agent request's signal and lets its handler send its own answer; -32800 only when the handler rejects. - Permission requests validate only the session, tool call id and options; unreadable fields are dropped with a diagnostic, and any answer Orca cannot send is `cancelled` instead of a JSON-RPC error. Agent-started turns may ask; whether to show it is the caller's decision. - AcpAgentError marks the agent's own errors; AcpInvalidResponseError keeps the raw answer and validation issues for answers Orca could not read. - Lines over the size limit are classified by prefix (shared with the Codex reader): the owed request fails, an oversized agent request is answered with an error, and an unattributable response closes the connection. * Answer every agent request after an ACP cancel A cancel that lands before a permission handler starts now still runs the permission path, so the agent gets the `cancelled` outcome rather than a request-cancelled error. A handler that ignores the abort no longer leaves the agent waiting: once the abort has run through, any request still unanswered gets request-cancelled. Handlers that answer on abort keep their own reply. Also renames a lint-rejected helper parameter, replaces a Reflect.apply in a test, and stops the permission diagnostic from firing with an empty list. * Let each ACP request handler own its answer after a cancel Removes the next-event-loop-turn fallback that answered request-cancelled for any handler still silent after a cancel. It raced answers that were still being saved (an approval mid-journal-write reached the agent as an error) and made the outcome depend on event-loop timing. The handler that owns an agent request now always sends its answer, or throws for request-cancelled; a request it never answers ends when the connection closes. A permission whose handler had not started still answers `cancelled`. * Register the ACP schema verify step in the PR preflight phase test * feat(acp): a steer's cancel asks once and never ends the agent The runtime had one cancel: send session/cancel, wait at most 10 s for Orca's prompt to settle, then close the connection, which ends the agent. A steer used it too, so a slow agent lost its process just because the person added a message. requestSteerCancel() now sends session/cancel once per prompt, cancels the agent's open requests and answers later permissions cancelled, and never bounds or closes: the prompt's own reply ends it and the steer's prompt follows. cancel() stays the Stop: bounded, then close. A Stop after a steer still bounds and closes. Both cancel paths move into acp-prompt-cancel.ts over one cancel channel. * fix(acp): a repeated steer shares the cancel in flight; say what the caller owns Per review: a second steer before the first write lands returns that write instead of resolving early. The steer's JSDoc says the wait for the prompt's reply is unbounded and that a prompt that fails instead must not take the steer until the caller rebuilds the session; the Stop's says a prompt that settles in time leaves the agent for the Stop's owner to end. The steer test now gives the runtime a handler that would allow: the open permission's signal aborts and the late one never reaches it. * test(ratchet): require src/main/acp now that this PR lands it |
||
|
|
a47e0f5657 |
fix(feedback): optimize oversized screenshots without losing detail (#23664)
* fix(feedback): shrink oversized screenshots instead of refusing them Fixes #22776 * fix(feedback): release each shrink canvas and skip the PNG ladder for a JPEG Two defects in the attach-time shrink ladder: - Every step allocated a fresh full-size canvas and left it for the garbage collector, so a 32-megapixel source could keep six of them alive at once. Past the renderer's canvas memory budget Chromium hands back a blank canvas, which would upload as a blank screenshot with nothing to notice it. Each step's canvas is now released once toBlob has answered. - A JPEG source ran two full-size PNG encodes first. A PNG of decoded JPEG noise is many times larger than the source it has to undercut, so those steps could only ever burn time and a large buffer before the first JPEG attempt. A lossy source now starts at the JPEG steps. * fix(feedback): keep the image read queue usable after a settle callback throws The queue tail is what the next batch awaits. A throw in either settle callback left it rejected, so every later attach short-circuited into "Could not read the attached images" without reading anything — and the rejection went unhandled. * feat(feedback): say when an attachment is still being prepared Shrinking a full-screen capture takes long enough that the gap between picking the file and its thumbnail appearing reads as a dropped attachment: the only other signal was the Send button quietly staying disabled. The attachment hint now reads "Preparing attachments…" while a batch is in flight. * fix(feedback): report an undecodable oversized image as invalid, not too large * fix(feedback): detect an animated PNG by walking its chunks, not a 64 KB text scan * docs(feedback): stop claiming toBlob encodes off the renderer thread * refactor(feedback): seed the image read queue ref directly * test(feedback): cover the real decode, downscale and release path of the shrink * perf(feedback): skip image batches still queued when the dialog unmounts * fix(feedback): show the preparing hint only once a read outlasts a short delay * test(feedback): pin the animated-PNG walk on corrupt lengths and a refused image's budget * fix(feedback): blame the shared budget, not the file size, when a shrinkable image has no room * fix(feedback): cap each shrunk screenshot at half the attachment budget A shrink kept the largest step that fit everything left, so the first full-screen screenshot took a 3.8 MB PNG, the second fell to a barely readable JPEG and the third was refused. Re-encodes now target at most 2 MB; an image that already fits is still attached untouched. The "larger than 4.0 MB" refusal now applies whenever the capped target an empty budget would give was the one that refused it. * test(feedback): pin the half-budget shrink cap independently of its constant * fix(feedback): reserve a shrinking screenshot's capped size, not its file size, for the paste gate A 6 MB screenshot still shrinking reserved 6 MB, more than the whole budget, so a second paste during the shrink fell through to the textarea even though it attached. Each pending file now reserves what the reader can commit under the same fit and shrink-target rules. Also corrects the minimum shrink target comment to the measured smallest step. * docs(feedback): correct the canvas-release and shrink-queue test comments; mock toast.info in the dialog test * Revert "refactor(feedback): seed the image read queue ref directly" This reverts commit e2272b825eb2d26286aee3a99ca28f3ea984508e. * fix(feedback): keep preparing hint compatible with current main * fix(feedback): preserve mixed paste text and seed read queue on attach * fix(feedback): preserve screenshot detail and pending paste text Optimize oversized attachments only as full-resolution lossless PNG; refuse them with existing warnings when that cannot fit. Bound each pending batch independently so earlier optimization slack, rejected files, or removed drafts cannot under-reserve bytes and swallow co-pasted text. Regression tests demonstrate the old mixed-batch text loss. * test(journal): retain provider handle import across main integration * test(startup): account for encoded Windows prompt lines * test(compatibility): retain the released journal parser dependency --------- Co-authored-by: Neil <neil@stably.ai> Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com> |
||
|
|
b32462f246 |
Replace patched JSON parser with stream-json (#25202)
* Replace patched JSON parser with stream-json * Isolate dependencies for historical server compatibility builds |
||
|
+34 |
c2dba12072 |
Add host-owned OpenCode and Devin managed account profiles (#24636)
* Add host-owned OpenCode and Devin account profiles * Manage OpenCode and Devin profiles in account Settings * Expose registered account roots to host transcript readers * Clarify managed profile provider flags * Retain isolated Electron home in browser sidecars * Restore inherited account environment and preserve cleanup retries * Check relay environment values before merging * Consolidate managed account type imports * fix(accounts): use existing localized provider names Align the new Japanese account copy with the existing catalog repair policy. * Keep managed account baselines private to the execution host * Align account enrollment help with accepted providers and flags * Show the active System account in managed profile lists * Document the validated Linux managed account scope * Fix managed account removal, credential audits, and runtime bundling * Quarantine removed accounts and audit captured credential snapshots * Continue Antigravity IDE and 2.0 history in new CLI conversations (#24692) * feat(antigravity): bridge IDE history into new CLI conversations * fix(antigravity): preserve fresh-launch model and environment for IDE references * fix(antigravity): forward IDE history opt-in through desktop IPC * fix(antigravity): rebuild remote IDE reference startup on its host * fix(antigravity): register IDE continuation action labels * fix(antigravity): confine IDE references and bound metadata reads * fix(antigravity): localize IDE continuation badges * Preserve scanner service cache assertions and refresh Antigravity opening metadata * Preserve Antigravity opening joins and target folder runtime authority * fix(opencode): retry timed-out SSH plugin updates (#24666) Preserve bounded retry behavior and the current-main status-envelope fields. Original-PR: #24124 Reviewed-source: |
||
|
|
1aa0860f7e |
Keep large Markdown previews responsive (#24880)
* Keep large Markdown previews responsive * Fix large preview review navigation and Find budgets * Initialize preview scroll caches once and check viewport visibility * Restore large previews after loaded rows are measured * Refresh loaded Markdown rows after viewport changes * Keep Markdown revisions visible and reuse bounded search text |
||
|
|
76b1a90ff6 |
chore(deps): update reviewed dependencies across Orca (#24561)
* chore(deps): update reviewed desktop dependencies and tooling * chore(deps): update compatible mobile packages and Fastlane * chore(deps): update cloud transports and enforce release age * chore(deps): patch documentation dependencies and record review * chore: remove dependency review reports * test(linear): smoke-load resolved SDK through CommonJS loader * fix(deps): keep native rebuilds from reinstalling addon dependencies * fix(native): invoke installed node-gyp directly for Node rebuilds * test(cloud): exclude observer probes from row-lock timing budget * test(mobile): preserve the CSS writer receiver in viewport spy * test(native): remove obsolete batch-shim fixture exception * Stream native rebuild output through the process wrapper |
||
|
|
6593d7d194 |
feat(orcad): run orcad on the pinned Node instead of Bun (#24110)
* ci(daemon): gate PRs on daemon protocol crossing from the newest release Lands daemon-protocol-facts.mjs from the Windows update diagnostic branch with a stricter parser, and adds check-daemon-protocol-crossing.mjs (rule R1): the working tree must attach the newest release tag's daemon. Rollback crossing is reported only. Runs in the cross-version-wire job, which already has full tags; tag selection moves to config/scripts/stable-release-tags.mjs so both use one rule. * feat(persistence): run profile backups in the worker whenever its entry is bundled * refactor(orcad): make profile and native preflight runtime-neutral The profile preflight parser now takes the expected runtime identity from the caller (shipped callers pass the pinned Bun identity), and the native preflight is renamed to orcad-runtime-native-preflight with neutral wording. * feat(runtime): pin the Node 24.21.0 server runtime with an offline CI check Add src/shared/node-runtime-pin.ts (NODE_RUNTIME_PIN, SERVER_TARGETS, NODE_RUNTIME_ASSETS for all 8 server targets plus the headers tarball), generated by config/scripts/update-node-runtime-pin.mjs from the nodejs.org and unofficial-builds SHASUMS. check-node-runtime-pin.mjs verifies, with no network, that the pin tracks the locked Electron, matches engines.node's major, and covers exactly SERVER_TARGETS; it runs in the static analysis job. ORCAD_BUN_TARGETS consumers now read SERVER_TARGETS so there is one target list; orcad's Bun runtime and build output are unchanged. * test(persistence): skip plain-Node backup selection tests in the Bun profile suite * fix(runtime): reject a pinned archive that belongs to another target * ci(daemon): fail PRs that swap a runtime launcher and bump the daemon protocol D7.1 R3: hosting orcad or the daemon on another runtime is not a protocol change, so one PR must not do both. The launcher file list lives in the check script; the allow-runtime-launcher-protocol-bump label overrides it. * feat(orcad): select pinned-Node slots by a .runtime-node marker D7.1 R5: a Node slot names its shared runtimes/node-<sha256>/node through .runtime-node instead of .build-target, so Bun-era clients read it as a legacy slot rather than exiting 78 on a missing bun-runtime. Nothing builds the marker yet. * fix(runtime): load the Node pin without the typeless-module warning check-node-runtime-pin.mjs now requires the pin and takes nodeDistArchiveName from its own module, so it no longer loads the update script's build graph. * fix(orcad): resolve Node slots to the design's runtimes/node-<sha>/bin/node layout * feat(orcad): 8-slot node-pty prebuilds against the pinned Node headers at N-API 8 - build-orcad-prebuilds.mjs adds win32-x64/arm64 (conpty.node, the vendored conpty.dll/OpenConsole.exe, upstream's N-API conpty_console_list.node), compiles in a scratch copy against the hash-verified pinned headers (node.lib pinned per Windows arch) with NAPI_VERSION=8, rejects post-8 node_api_* imports, and writes a schema 2 manifest with per-file sha256, N-API level and the glibc need. - --require-slots [slots] verifies files against hashes; --smoke loads the slot under the pinned Node and spawns a PTY; --print-slot names the host slot. - The slot installer gates on N-API, libc, arch, glibc and file hashes instead of the exact NODE_MODULE_VERSION, and installs nested files (conpty/). - bun-profile-tests.yml builds, verifies and smokes each runner's slot. * fix(orcad): scope node-pty's glibc .symver pins to glibc on musl prebuild slots musl's unversioned libc cannot satisfy openpty@GLIBC_* references at link time, so the Alpine slot compile would fail. Pin the staged pty.cc guard to __GLIBC__ and assert both musl transforms against the installed patch. * feat(orcad): run orcad on the pinned Node instead of Bun A packaged orcad slot now references the pinned Node 24.21.0 by its executableSha256 (`.runtime-node`, `.server-target`) instead of carrying bun-runtime, and ships node-pty from the slot's prebuild, only its own ripgrep, and no Windows Bun PTY gate. The runtime lives beside the slots at runtimes/node-<sha>/bin/node (node.exe on Windows, upstream name). - build:orcad (build-orcad-node.mjs) builds the host slot's prebuild when missing and places the pinned runtime; the template is schema 3 with per-target files. - handoffToBundledOrcad() resolves the slot's runtime reference and checks process.versions.node against the pin; a host Node >= 18 still hands off. Startup preflight keys on running as that runtime; callers expect 'node'. - orcad and its daemon use node-pty (ConPTY + windows-pty-job on Windows); the Bun PTY sources, gate entry and canUseBunPty branches are removed. - SSH deploy uploads the official archive once per pin, extracts and hash-checks it on the host, and self-tests it before publishing. Bun slots stay launchable for rollback; Node slots never use host Node. - The runtime materializer is generic over pinned assets; the Bun wrapper remains only for the OpenCode vault reader (design Phase 2). - Cross-runtime test: a profile DB written by Bun 1.4.2 (WAL left by SIGKILL) opens and backs up under the pinned Node, and the reverse. No daemon PROTOCOL_VERSION change (design D7.1 R3). * docs(ci): name the headless lanes after the pinned Node, drop Bun shard timings Design D10: ci-demand-rollout.md and ci-runner-efficiency.md follow the bun-profile-tests.yml -> node-server-tests.yml rename; shard timings drop the deleted Bun PTY tests and follow the renamed ones. * chore(ci): count the runtime archive download as a runtime launcher path * fix(orcad): pin the macOS C++ standard for node-pty prebuilds The official Node headers' config.gypi sets clang: 0, so common.gypi skips its gnu++20 xcode_settings and Apple clang 15 (macos-14 runners) compiles node-addon-api as C++98. * fix(orcad): resolve the preflight's slot through realpath, as the handoff does A symlinked orcad.js handed off to its real slot's pinned Node, but the startup and profile preflights read the symlink's directory, found no runtime marker there, and silently skipped the readiness check. * refactor(ssh): drop materializeCachedNodeRuntime, which nothing calls Deploys upload the verified official archive (design D5); no client path needs an extracted Node executable cached by digest. * test(orcad): gate the Bun-to-Node upgrade and Node-to-Bun rollback with live terminals Design D7.1 R1/R3/R4 and D7.2. The last Bun orcad and this checkout's Node slot are installed side by side under ~/.orca-remote, launched and stopped with the client's own deploy commands, and share one data root. Each direction proves the incoming orcad adopts the outgoing runtime's daemon (same PID, same shell, output continues), opens its profile database and backs it up with its own shipped worker, and that GC keeps the slot the live daemon was forked from. The node-server Linux lanes provide Bun 1.4.2 and build that Bun orcad from main, and run with --cross-runtime. --artifact and --cross-runtime now make their tests fail on a missing input instead of skipping. * ci(node-server): pin node:24.21.0-alpine by its multi-arch index digest * test(ssh): name the runtime archive fixture after its role * test(node-server): load node-pty from the packaged slot in artifact runs The node-server lane installs dependencies without building node-pty, and Linux has no upstream prebuild, so the real-PTY failed-I/O teardown test (picked up by the pty-subprocess selector) could not load pty.node. In --artifact runs, alias node-pty to out/orcad's shipped slot so the test exercises the addon orcad actually runs under the pinned Node. * fix(orcad): let the Windows profile preflight exit after its PTY probe On Windows, node-pty keeps the conout worker thread and pseudoconsole alive until kill(), even after the shell exits. The PTY health probe never killed a cleanly exited probe, so the packaged preflight printed its readiness line and then hung until the build's 30s timeout, reported with an empty stderr. - The probe kills its PTY on Windows after exit and uses the bundled ConPTY the daemon spawns with. - The preflight exits once stdout is flushed; its owner reads to EOF. - Preflight failures now report code, signal, timeout, stdout and stderr. * test(node-server): load the slot's node-pty in the real-PTY test, not by alias A vite alias redirected only ESM imports of node-pty; windows-pty-job and local-pty-utils resolve it through require, so Windows loaded two conpty.node copies and the Git Bash job-membership proof read an empty job. The failed-I/O teardown test now loads node-pty through a fixture that picks the packaged slot in artifact lanes. The pty-subprocess selector was a prefix that also pulled in its POSIX-host sibling unit tests, which pr.yml runs and which were never qualified on Windows. Select the directory plus the two sibling files that belong here. --------- Co-authored-by: m4air <m4air@m4airs-Air.localdomain> |
||
|
|
d2dfc79764 |
ci(daemon): runtime-launcher protocol ratchet and Node slot marker (#24108)
* ci(daemon): gate PRs on daemon protocol crossing from the newest release Lands daemon-protocol-facts.mjs from the Windows update diagnostic branch with a stricter parser, and adds check-daemon-protocol-crossing.mjs (rule R1): the working tree must attach the newest release tag's daemon. Rollback crossing is reported only. Runs in the cross-version-wire job, which already has full tags; tag selection moves to config/scripts/stable-release-tags.mjs so both use one rule. * feat(persistence): run profile backups in the worker whenever its entry is bundled * refactor(orcad): make profile and native preflight runtime-neutral The profile preflight parser now takes the expected runtime identity from the caller (shipped callers pass the pinned Bun identity), and the native preflight is renamed to orcad-runtime-native-preflight with neutral wording. * feat(runtime): pin the Node 24.21.0 server runtime with an offline CI check Add src/shared/node-runtime-pin.ts (NODE_RUNTIME_PIN, SERVER_TARGETS, NODE_RUNTIME_ASSETS for all 8 server targets plus the headers tarball), generated by config/scripts/update-node-runtime-pin.mjs from the nodejs.org and unofficial-builds SHASUMS. check-node-runtime-pin.mjs verifies, with no network, that the pin tracks the locked Electron, matches engines.node's major, and covers exactly SERVER_TARGETS; it runs in the static analysis job. ORCAD_BUN_TARGETS consumers now read SERVER_TARGETS so there is one target list; orcad's Bun runtime and build output are unchanged. * test(persistence): skip plain-Node backup selection tests in the Bun profile suite * fix(runtime): reject a pinned archive that belongs to another target * ci(daemon): fail PRs that swap a runtime launcher and bump the daemon protocol D7.1 R3: hosting orcad or the daemon on another runtime is not a protocol change, so one PR must not do both. The launcher file list lives in the check script; the allow-runtime-launcher-protocol-bump label overrides it. * feat(orcad): select pinned-Node slots by a .runtime-node marker D7.1 R5: a Node slot names its shared runtimes/node-<sha256>/node through .runtime-node instead of .build-target, so Bun-era clients read it as a legacy slot rather than exiting 78 on a missing bun-runtime. Nothing builds the marker yet. * fix(runtime): load the Node pin without the typeless-module warning check-node-runtime-pin.mjs now requires the pin and takes nodeDistArchiveName from its own module, so it no longer loads the update script's build graph. * fix(orcad): resolve Node slots to the design's runtimes/node-<sha>/bin/node layout --------- Co-authored-by: m4air <m4air@m4airs-Air.localdomain> |
||
|
|
2a83c9536f |
ci(daemon): gate PRs on daemon protocol crossing from the newest release (#24089)
Lands daemon-protocol-facts.mjs from the Windows update diagnostic branch with a stricter parser, and adds check-daemon-protocol-crossing.mjs (rule R1): the working tree must attach the newest release tag's daemon. Rollback crossing is reported only. Runs in the cross-version-wire job, which already has full tags; tag selection moves to config/scripts/stable-release-tags.mjs so both use one rule. Co-authored-by: m4air <m4air@m4airs-Air.localdomain> |
||
|
|
3135fbbf49 |
feat(runtime): pin the Node 24.21.0 server runtime with an offline CI check (#24087)
* feat(runtime): pin the Node 24.21.0 server runtime with an offline CI check Add src/shared/node-runtime-pin.ts (NODE_RUNTIME_PIN, SERVER_TARGETS, NODE_RUNTIME_ASSETS for all 8 server targets plus the headers tarball), generated by config/scripts/update-node-runtime-pin.mjs from the nodejs.org and unofficial-builds SHASUMS. check-node-runtime-pin.mjs verifies, with no network, that the pin tracks the locked Electron, matches engines.node's major, and covers exactly SERVER_TARGETS; it runs in the static analysis job. ORCAD_BUN_TARGETS consumers now read SERVER_TARGETS so there is one target list; orcad's Bun runtime and build output are unchanged. * fix(runtime): reject a pinned archive that belongs to another target --------- Co-authored-by: m4air <m4air@m4airs-Air.localdomain> |
||
|
|
2ab179ccf7 |
fix(emulator): take serve-sim 0.1.47 so the iOS simulator works on Xcode 27 (#24228)
* fix(emulator): take serve-sim 0.1.47 so the iOS simulator works on Xcode 27 serve-sim 0.1.40's helper binary hard-linked SimulatorKit at its pre-Xcode 27 path, so every iOS emulator start failed with a dyld error on Xcode 27. 0.1.47 replaces that binary with a napi addon that finds SimulatorKit in either location, and runs the stream helper as a node process. Match the new helper process (serve-sim.js ... --exit-on-simulator-shutdown) while still matching legacy serve-sim-bin helpers left by an older Orca, and mark the package's new standalone helpers executable. * refactor(emulator): drop redundant serve-sim chmod; the package already ships helpers executable serve-sim publishes its helpers as 755 and pnpm, fs.cpSync and electron-builder all preserve the mode, so the executables list and every chmod over it are dead. * fix(emulator): give the materialized serve-sim runtime its node dependencies serve-sim 0.1.47's entry imports `ws`. Packaged macOS builds run serve-sim from a copy under userData, and that copy had no node_modules, so every iOS emulator attach failed with ERR_MODULE_NOT_FOUND. Dev builds were unaffected because they run serve-sim straight from pnpm's node_modules. Lay the copy out as <version>/node_modules/serve-sim and link each dependency the package declares to the bundle's installed sibling, so transitive deps keep resolving from the bundle. A runtime in the old flat layout, or one whose links dangle because the app moved, is rebuilt instead of reused. |
||
|
|
0f52bb8be5 |
perf(ci): use four ARM test workers and remove repeated compilation (#23685)
* ci: benchmark per-job Node compile caching on full unit shards * ci: measure unit shards with three and four workers * ci: benchmark localization extraction CLI patch * perf(build): reuse identical relay bundles across platforms * ci: compare Vitest 4 and 5 on complete ARM shards * perf(ci): upgrade localization extraction to skip irrelevant syntax walks * perf(ci): use all four ARM cores and remove benchmark workflows * ci: preserve failures while capturing unit source revision * fix(ci): preserve commented and escaped localization calls * ci: remove corrected localization benchmark harness |
||
|
|
e8d8f2f0b3 |
fix(deps): take Electron 43.7.5 so detached webviews stop blanking browser tabs (#23586)
Electron 43.7.0 threw 'Invalid guestInstanceId' from <webview>'s disconnectedCallback for a loaded guest (electron/electron#53989), so a webview React removed and re-inserted kept a dead guest id: the tab went blank, reload did nothing, and the destroyed listener never fired. 43.7.4 (electron/electron#54097) returns early when the guest is gone. Raises the runtime floor test to 43.7.4 so a downgrade cannot re-ship it. Fixes STA-8757 |
||
|
|
3dd7d29455 |
Revert "perf(ci): shard the anti-slop audit across processes instead of one JS runtime (#23543)" (#23575)
This reverts commit
|
||
|
|
8494b2422d |
perf(ci): take i18next-cli 1.74.1 so extraction stops re-scanning every key to find its leaves (#23550)
1.65.0 decided "is this key a leaf" by scanning all extracted keys per key, so the check cost ~13,200 squared startsWith calls. 1.74.1 replaced that with a prefix Set. Extraction drops from 22.1-23.3s to 16.9-17.4s locally, and the gate from ~23s to 17.8s. It also extracts 17 keys 1.65.0 missed, all of which are already committed in en.json, so they move out of the orphan list rather than needing new translations: extracted 13,191 -> 13,208 and orphans 1,567 -> 1,550. No key is lost and no existing value changes, so no catalog is regenerated here. |
||
|
|
fae0ae7a46 |
perf(ci): shard the anti-slop audit across processes instead of one JS runtime (#23543)
config/oxlint-anti-slop.json turns every native oxlint category off and runs its rules through jsPlugins, so oxlint's threaded Rust engine does no work and the pass is one JS runtime per process. Measured, it does not scale with --threads: 11.68s at 4 threads against 12.38s at 16. Parallelism has to come from more processes, so the audit now splits its file set across them. Locally, 11.72s single pass against 3.83s at 4 shards (3.1x) and 2.91s at 8. Sharding is sound because every anti-slop rule is a single-file analysis; the only mutable module state is a WeakMap keyed on each file's own Program node. Verified by running both shapes with all 18 rules enabled: 392,398 findings from one pass and from the shard union, identical as sorted multisets. |
||
|
|
27b823f934 |
ci: compile the E2E CLI once for all consumers (#23384)
* ci: share compiled CLI output across E2E consumers * ci: preserve CLI setup and old-ref fallback for shared artifacts * docs: record shared E2E CLI benchmark evidence * docs: include final CLI reuse timing range --------- Co-authored-by: m4air <m4air@m4airs-Air.localdomain> |
||
|
|
d8e2a694f6 |
ci: overlap package preparation and security scans; share localization parsing (#23364)
Co-authored-by: m4air <m4air@m4airs-Air.localdomain> |
||
|
|
7468e9cccb | release: v1.4.214 | ||
|
|
6fc3cdcad6 |
Bundle Bun for headless Orca and profile persistence (#22635)
Bundle a pinned, verified Bun runtime for headless Orca so existing Node launch commands can hand off before opening a profile. Keep desktop execution on Electron. Add the Bun SQLite adapter and terminal backend, bounded shutdown, process inspection and cross-platform artifact qualification. Keep future managed SSH deployment separate from current production launch paths. |
||
|
|
fa018fe520 |
chore(deps): refresh maintained dependencies (#22964)
* chore(deps): refresh maintained dependencies * fix(deps): defer upgrades that violate runtime and test contracts * test: align catalog response assertion and updated formatter |
||
|
|
7ea01279cd |
feat(search): bundle ripgrep for local, WSL, and SSH search (#22396)
* feat(search): bundle ripgrep for local, WSL, and SSH search Ship @vscode/ripgrep-universal's prebuilt rg for all six relay platforms in every desktop artifact. Local and WSL searches spawn the bundled binary and drop the git ls-files / git grep fallbacks; SSH deploys upload the remote's binary once per ripgrep version and the relay prefers it over PATH rg. * fix(search): address bundled ripgrep review findings - Key the SSH ripgrep cache on the binary's content hash; a package bump is the only update step - glibc verifier: read arch tokens below the slice root and accept static ELFs (arm64 release blocker) - Ship ripgrep/PCRE2/musl license notices; bundle rg with orcad - Packaged builds never spawn a bare rg; report fd pressure as transient - SSH: install rg before sweep/GC, size-validate installs, back off instead of disabling on launch failure - Scope Dependabot to @vscode/ripgrep-universal; revert unrelated lockfile churn * chore(search): drop bundled-ripgrep reference doc; assert full packaging layout parity * refactor(search): one entry point for spawning the bundled ripgrep Local Quick Open, Quick Open path search, the Explorer name filter, and runtime text search each repeated the same three steps: resolve the bundled command, spread in the WSL distro, spread in the WSL shell expression. Fold that into spawnBundledRipgrep so one place owns the rule that a bare 'rg' must never reach spawn, and simplify the resolver's command/packaged checks. Restore the AGENTS.md ripgrep rule dropped alongside its reference doc in |
||
|
|
da1c322b00 |
feat(mobile): one build-time switch picks native or OTA, default native (OTA phase E1) (#22193)
* feat(mobile): one build-time constant decides native or OTA, default native EXPO_PUBLIC_MOBILE_SHELL is read in exactly one place, mobileShellBuildKind in preferences.ts. Expo's babel preset inlines a literal process.env member expression at build time, so a release bundle carries the answer as a constant and anything but the exact string 'ota' — unset, empty, a typo — is native. Every default build is therefore the native app, unchanged. mobileWebShellFlagCanBeOn now answers __DEV__ or an OTA build, so the ability to mount the page comes from the build and never from storage: a native binary installed over an OTA one, same bundle id and same data container, still refuses a stored 'true' without reading the key. An unset key reads on only in an OTA build; a development build keeps its opt-in, and a stored 'false' wins everywhere so the Troubleshoot toggle can switch an OTA build back to native. That toggle now mounts wherever the flag can be on, which is the only way back to the native screens in an OTA build, and its label names the build kind rather than saying "(dev)". The bundle probe row beside it stays development-only: it fetches. The flag census gains two rules — one module reads the switch, in the member form Expo inlines and not the bracket form, and one named function answers the build kind — and the build-kind fence now lists the Troubleshoot route that asks it. Docblocks that said a store build can never mount the shell now say it mounts only when built for OTA. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * ci(mobile): one workflow input picks the shell, and no input means native Both release workflows gain a `shell` workflow_dispatch choice, options native and ota, default native, and hand it to the step that bundles the JavaScript as EXPO_PUBLIC_MOBILE_SHELL. That is the Gradle assembleRelease step on Android and the fastlane build_and_upload step on iOS; nothing else in either file sets it. A tag push and a schedule carry no inputs at all, so `inputs.shell || 'native'` yields native for them — the first OTA release is a dispatch with one field changed, and every other run is the app we ship today. Each build step prints the value it is about to build with, read back from the same variable rather than from a second copy of the expression, so a run's log cannot claim a shell the build did not use. The new contract test evaluates that expression rather than matching its text: absent, empty and 'native' all resolve to native, 'ota' to ota, and any expression shape it cannot evaluate is a failure rather than a pass. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * build: the desktop packages the real page, and the placeholder is retired build:mobile-web now runs the app builder and app verifier, and both take their output root from MOBILE_WEB_BUNDLE_DIR in the packaging guard rather than each carrying a constant of their own — one definition of where the bundle lives, so a drift cannot leave electron-builder's beforePack looking at an empty directory while the builder reports a tree it wrote elsewhere. build:mobile-web:app is gone; it was the same two commands. src/mobile-web/ and its two scripts go with it. What the app builder shared with them is split into three modules named for what they hold rather than for the bundle that used to own them: mobile-web-bundle-manifest.mjs (content types, the canonical asset serialization, buildId, hashed assets, the protocol window and the manifest write), script-entry-detection.mjs (isDirectInvocation, whose two failure modes are Windows paths and symlinked entries), and mobile-web-source-line-endings.mjs (the CRLF guard, now with a required directory rather than a default pointing at the deleted tree). The two suites that only needed *a* valid tree on disk — the beforePack guard and the packaged-bundle guard — build one from mobile-web-bundle-fixture-tree instead of bundling the whole mobile graph. It goes through the same manifest writer the page does, so a manifest shape change still reaches them. Also retired: the placeholder's tsconfig project and its typecheck lane, its knip entry, its electron-builder exclusion and .gitattributes pins, and the app-bundle test that asserted the shims stayed out of a builder that no longer exists. pr.yml's page job builds the same bundle the package job ships. Inert for native phones: they never fetch it. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * style(config): one import of node:fs/promises in the entry-detection suite The changed-code quality gate's focused plugins read the two as a duplicate import; the readFile line was left over from the split. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs: the comments that still describe the retired placeholder bundle The web entry said it was built by `build:mobile-web:app` into out/mobile-web-app and shipped by nothing. That script, that directory and that fact are all gone: it is built by `build:mobile-web` into the packaged bundle dir, and a phone mounts it only when the binary was built with EXPO_PUBLIC_MOBILE_SHELL=ota. Two Windows cache keys explained themselves by naming src/mobile-web and "the two bundle builders"; config/** now covers the builder, the verifier and the manifest writer, and the spike's key no longer waits on a Phase C flip that has happened. The keys themselves are unchanged. Three scratch directories in the app-bundle suites and one in the verifier still spelled the retired output root. Renamed to mobile-web, which is what the build writes; they are temp subdirectory names and nothing reads them. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb |
||
|
|
eb92222e7f |
feat: support Antigravity as supervised worker (#21705)
* feat: add supervised Antigravity worker support * fix: address Antigravity worker review findings * fix: stabilize Antigravity readiness detection * fix: allow Antigravity resume footer after readiness * fix(antigravity): make agy reach worker_done as a supervised worker Three defects each blocked `orchestration worker-start --agent antigravity --worktree new-child` at the agent_readiness stage. 1. Readiness never fired. The composer check required the trimmed line to be exactly one character, but agy 1.2.7 launches in accept-edits mode and paints it into the caret row (`> Accept-edits mode: ...`). Widened narrowly to a bare `>` or `> <name> mode:`; matching any `> <text>` would make every menu dialog read as ready, since they all prefix their highlighted row the same way. 2. No trust artifact for agy. Added markAntigravityWorkspaceTrusted, writing ~/.gemini/antigravity-cli/settings.json under `trustedWorkspaces` — verified empirically against agy 1.2.7, and distinct from the Gemini CLI's trustedFolders.json, which agy does not consult. Trust is exact-path and not inherited by subdirectories, so each child worktree needs its own entry. 3. The orchestration path skipped the preset. Orca has two trust dispatch chains: the renderer's preflightAgentTrust and the main-process markLocalWorktreeTrusted. worker-start only takes the second, which matched cursor/copilot/codex and fell through for antigravity, so the trust write never happened while renderer-side tests passed. Verified live end to end: the dispatch settles `succeeded` with worker_done carrying the right task and dispatch ids, and the worktree is appended to agy's settings with sibling keys untouched. Known gap: remote-agent-trust-presets.ts has no antigravity branch. The SSH artifact path is unverified, so agy over SSH still stalls at agent_readiness. Recorded in a comment there rather than guessed at. * fix(antigravity): wire trust preset through preload safely * fix: preserve Antigravity readiness across transcript tails --------- Co-authored-by: Neil <neil@stably.ai> Co-authored-by: LielinaH <lielinah@gmail.com> |