mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 18:07:45 +00:00
de3da487fa6bbfde6f9e4b53fba7672fada5322c
120
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6a68dac421 |
fix(terminal): bound WebGL atlas pages and release removed page textures (#39715)
Cap merged atlas pages at FORCED_MAX_TEXTURE_SIZE instead of the device MAX_TEXTURE_SIZE (16384 on Apple Silicon), stop the link render layer from acquiring the shared atlas with a mismatched 2048 texture size, and reset GL texture slots of removed atlas pages to the 1x1 placeholder. Mirrors xtermjs/xterm.js#6187, #6156 and #6306 in the addon-webgl source patch and regenerates the runtime patch and lock hash. Co-authored-by: FlamingoPg <1106310035@qq.com> |
||
|
|
0b22e904e3 |
perf(terminal): avoid reparsing xterm inline color styles (#39482)
Set RGB and contrast-adjusted colors through CSS properties instead of serializing and reparsing the complete inline style. Regenerate the pinned xterm runtime patches and lock hash without changing terminal scheduling or recovery. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
e97b290cb8 |
test: remove 835 low-value tests (#39558)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
a59d47b1eb |
fix(terminal): let default-matching cell backgrounds follow background opacity (#39372)
Explicit SGR backgrounds equal to the translucent default background, and style-only cells (dim, italic, extended underline) in WebGL, painted an opaque fill over the theme wallpaper. Treat them as the default background in both the WebGL and DOM renderers; the buffer keeps the original color. Closes #37671 |
||
|
|
9bd6272fdf |
refactor(tooling): organize build, CI, and test owners (#38130)
* refactor(tooling): organize test runtime and maintenance owners * test(tooling): preserve relocated runtime fixture dependency edges * refactor(tooling): preserve xterm routing owner checks * ci(tooling): include routing owner in sparse checkout * test(tooling): preserve copied workflow dependency closures * fix(tooling): normalize hashed JSON assets in release parity * fix(tooling): distinguish asset aliases from literal references * fix(tooling): frame normalized asset reference payloads * fix(tooling): normalize decoded JSON asset references * refactor(tooling): organize build, CI and release owners * fix(tooling): align moved generator and workflow path contracts * fix(tooling): update generated plugin bundle owner banners * test(tooling): create relocated mobile verifier fixture directories * test(tooling): copy headless detector dependency closure * test(tooling): align native batch policy fixtures with owner path * fix(tooling): link moved reliability command to historical evidence * fix(tooling): preserve nested sandbox owners and canonical guide source * fix(tooling): target release version owners in checkout fixture |
||
|
|
74df8bf42e |
test: remove 997 low-value test declarations (#38058)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
e98c6a439a |
test: remove 2816 low-value test declarations (#38030)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
9c7fe9793e |
fix(deps): backport minimatch, glob, and deepmerge security fixes (#37981)
Backport upstream matching and abort fixes plus safe deepmerge property handling across the independent workspaces. Includes installed-package regression tests and audit-tool fixture repair. Agent-reviewed at 83ca381d519e6247d7c1b3f0a52ce2907a9f9a19; CI aggregate passed. Version-based scanner alerts remain open pending documented disposition or compatible upstream releases. |
||
|
|
f3c65cd556 |
fix(deps): update Electron to 43.8.6 and resolve open security advisories (#37916)
- Electron 43.8.4 -> 43.8.6: upstream Chromium/V8/ANGLE/PDFium/Skia/WebRTC security backports. Drops the now-unneeded minimumReleaseAge exclusion. - @hono/node-server 2.1.0 -> 2.1.5 (GHSA-rmxm-3fg6-px4f), lockfile only. - mobile node-forge 1.4.0 -> 1.4.2: fixes 10 advisories (5 high) and the previously patched GHSA-86w9-cpqp-85rv, so the local patch and its audit exception are removed. The regression test still passes on 1.4.2. |
||
|
|
b69963356d |
chore(terminal): bump xterm to 6.1.0-beta.336 and regenerate patches (#37266)
Port the xterm, webgl, search, serialize and image source patches to upstream 08829c7. Where upstream fixed the same bug (#6204 mouse NaN guard, #6226 warm-up cancel on dispose, #6235/#6237 serialize width clamp) take upstream and keep only Orca's remaining delta (domContainer warm-up gate, clipped wide-cell blanking). Bump mobile's webgl subset patch alongside. Drop serialize fuzz seed normal:5, which now round-trips. |
||
|
|
07b437c9e9 |
fix(terminal): detect foreground from the physical PTY owner (#36342)
* fix(terminal): observe foreground at the physical PTY owner
* fix(terminal): keep existing inventory, inspection and display semantics around master-group foreground
Review round 1 fixes for the physical-owner foreground observation:
- Stop and liveness verification keep complete-inventory proof: the router's
scoped listProcesses({ptyIds}) is owner resolution again (absent = []).
Only the launch guard's old-owner fallback asks for an established
target's owner via an internal targetOwnerOnly option.
- Degraded daemon mode routes foreground observations and target reads to
the established owner, so an unreachable unrelated daemon cannot refuse a
known terminal there either.
- Display and name refreshes read the master's foreground group but take
member rows from the shared single-flight process-table snapshot; no
per-terminal ps per refresh. Recognized agent names skip the confirm scan
again, and builds without the native accessor keep the existing reader.
- Ordinary inspections keep their first-match routing; strict owner and
incarnation checks apply only to foreground decisions. The unused
foregroundOnly preload/IPC/RPC surface is removed.
- Local inventory forwards only the target scope, never caller deadlines.
- An interpreter running an agent script counts as that agent, as before;
a blank argv row no longer voids a terminal capture outside the
foreground group.
- Bump the packaged compatibility contract to daemon protocol 55 and move
the node-pty accessor above the process getter's doc comment.
* fix(terminal): keep the node-pty patch hunk well-formed and drop redundant foreground tests
Remove two stray context lines from the src/unixTerminal.ts hunk so its body
matches its header (strict patch parsers reject the mismatch), and update the
lockfile patch hash. Prune foreground tests whose rows repeat branches the
parity table already covers.
* fix(terminal): index the shared snapshot by TTY once and keep observation age nonnegative
Display refreshes filtered the whole shared process table per pane, so
work grew with panes times processes. Group each snapshot by normalized
TTY once, memoized by array identity, and look each pane up directly;
the scaling contract now counts row TTY reads at N and 10N panes.
Both foreground observation producers clamp capturedAgeMs at zero, so a
wall-clock step back during the read no longer yields an envelope the
validator rejects and the launch guard refuses.
* test: move foreground-observation compat tests into the protocol compatibility suite
Main removed daemon-pty-adapter-steady-state-compat.test.ts; the merge restored it with only this branch's block. Reuse the suite's existing inspection adapter helper so no new type assertion is added.
|
||
|
|
9eb930173e |
Keep rich Markdown in place when focus returns from Find (#36781)
* Preserve rich Markdown viewport through bare focus returns * Retire viewport ownership on editor remount * Complete no-op navigation and body Tab coverage * Keep patch metadata keys separate from dependency snapshots * Retire the viewport before root detach callbacks * Give the engine writer fixture its native selection * Keep native focus navigation current in Markdown * fix: leave smooth Markdown scrolling to native focus cancellation * Cover focus wrapper removal and routed Markdown writers * Type the viewport scroll spy and mark the focus-recovery wait as deliberate * Scope Markdown viewport wheel and touch guards to the editor scroller |
||
|
|
14d29b8d24 |
feat(themes): background images for app themes (#36589)
An app theme may declare one validated raster image (png/jpeg/webp, <=2 MB, >=640x360, inside the plugin) served through orca-plugin-image, painted as one static body layer under translucent terminals. Older Orca ignores the field; a bad image drops only the image. |
||
|
|
82ac952ad7 |
feat(editor): one typography resolver for every Monaco surface + opt-in weight, line height, ligatures, size and macOS smoothing (#36577)
* feat(editor): route editor typography through one resolver and add opt-in weight, line height, ligatures, size and macOS smoothing Monaco sites built font options ad hoc and never received fontWeight, fontLigatures or lineHeight; the editor size was tied to the terminal. editor-typography.ts now feeds every Monaco and DOM code surface. New optional settings default to today's rendering. A macOS-only Font Smoothing setting rebuilds WebGL terminal renderers so the change reaches their shared glyph atlases. * fix: satisfy changed-code quality gates * fix(terminal): cancel WebGL atlas warm-up on dispose so rebuilt renderers stop leaking canvases The warm-up queue kept drawing into a disposed atlas, which re-appended its scratch canvas to the terminal element. Every WebGL renderer rebuild (GPU toggle, context-loss retry, font smoothing toggle) leaked one canvas per pane. * feat(editor): read pixel and zero line heights like code editors and let markdown code follow an explicit editor font |
||
|
|
0cb87957e0 |
fix(terminal): stop terminal text turning bold after a restart (STA-4042) (#36463)
xterm's WebGL atlas warm-up pre-rasterized default-color ASCII without a DOM container. When it ran before the first glyph was drawn (a blank restored pane), the glyph canvas was still detached, so Chromium ignored the page's -webkit-font-smoothing: antialiased and baked heavier glyphs into the cache until something cleared the atlas (e.g. an image paste). Warm up through the terminal element and skip it while that element is not connected; skipped glyphs are drawn on demand. |
||
|
|
eb3379ff99 |
Fix macOS daemon PTY kqueue descriptor leak (#16870)
* fix(daemon): release node-pty kqueue descriptors * test: remove redundant wait from kqueue regression |
||
|
|
756d623955 |
perf(terminal): bound the in-process macOS process table's blocking calls and ps fallbacks (#31783) (#36282)
* fix(terminal): bound the in-process macOS process table's blocking calls and ps fallbacks (#31783) Follow-up to #35987 from its post-merge reviews. - cwd and executable path: node-pty's readProcessCwd/readProcessPath now run PROC_PIDVNODEPATHINFO and proc_pidpath on a libuv worker (the synchronous exports are gone, so an older pty.node falls back to ps/lsof). JS caps them at two outstanding lookups and 250ms; a wedged mount or a full cap answers from lsof -b, which never stats, so a dead NFS/SMB/FUSE mount cannot freeze the daemon's event loop or take the whole pool. - Unreadable argv prints "(comm)", as ps does, instead of a proc_pidpath lookup under Orca's credentials on the table worker. - The table exports each row's euid. Argv recovery runs setuid ps only for another user's processes, never for our own mid-exec or exiting ones (or SIDL/exiting rows), which ps cannot read either: a pane looping short commands forked ps on ~15% of full reads, now none. - Recovery is coalesced per process across concurrent readers and a failed recovery waits 5s before costing another ps. The cache keys on comm and start time. - Full-table and shell-foreground captures, which feed strict evidence with the capture's age, take only argv ps read after their request; display readers keep the 30s cache. - While the reader is down (stalled-pool breaker open, or a rejecting addon, which now backs off 1s..30s), runPsInProcess runs /bin/ps itself through one shared budget: identical invocations share a run, a burst of 4 forks then one a second, and a run spawned before a request never answers it. Descendant teardown and foreground-group signalling keep their own full-timeout ps (callerRunsPs). 13 pollers at 750ms: 1,040 ps/min before, 63 after. No daemon protocol bump: the wire format is unchanged, and each daemon loads JS and pty.node from the same runtime copy. * fix(terminal): make the libproc reader survive worker teardown, fail closed and share one fair fork budget (#31783) Review follow-ups to the previous commit. - Native: every libproc AsyncWorker derives from OrcaPromiseWorker, which skips JS completion once an env cleanup hook marks the env closing and swallows a Napi::Error thrown mid-teardown. Terminating a worker_thread with cwd or table reads in flight aborted the process; 200 terminates each now survive. - (comm) in a terminal's foreground group (argv neither reader recovered, e.g. a root `su`) judges 'unknown', never 'agent', so the launch line is not typed into it. - Fresh argv only for getFreshSnapshot captures; the 500ms TTL readers keep the 30s cache. Argv recovery runs through its own fork budget (2, then one per 2s). Root `su` pane, 13 pollers at 750ms: TTL 79 -> 2 ps/min, fresh 158 -> 31. - The fork budget serves invocations in FIFO turns, grouping each one's waiters onto one run. 13 streams: served 80,42,1,1,2,0x8 -> 10-12 each. - Forced subprocess captures (a held naming pass) go through the fallback budget: 5 readers, 400 direct ps/min -> 63, 395 of 400 captures served. - A failed recovery is retried 5s after ps gave up, not after it started. - Tests pin Orca's euid instead of reading the runner's and assuming root is 0. - process-cwd keeps one lsof per pid until it exits, so a dead mount no longer leaks one per poll; shell readiness reads the exe path through runProcess, which gives up on an lsof that ignores SIGTERM. - A #35987 pty.node (table reader, no async path reads) keeps the in-process table; cwd/path use lsof, with a one-time warning. - captureProcessTable moves to process-table-ps-capture.ts. * fix(terminal): make withheld argv unverifiable and reuse recovered argv for at most 2s (#31783) Round-2 review follow-ups. - Worker teardown: drop OrcaPromiseWorker and its env flag (Node drains the pool before cleanup hooks, so it never fired). node-pty's mac pty target now builds with NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS, which covers both the call-in and completion paths. The smoke test now calls the reads from a timer while terminating: the previous build aborted 2 of 3 runs, this one survives 3/3 x 100. pty.cc is back to the first follow-up's exact content. - A foreground process whose argv ps withheld (`(comm)`: another user's, exiting, or a recovery the budget skipped) makes the batch resolver, and so host-stamped evidence, `argv_unreadable`/unverifiable rather than live with no agent; agent-foreground resolution reports it unavailable. - judgeTerminalForeground fails closed only for an unreadable shell (`(bash)` from a root `su`), not our own exiting `(git)`. - Recovered argv is reused for at most 2s per identity (pid, start, comm) for every reader (the next commit ages evidence by it), and fresh reads no longer queue behind the recovery budget. Root `su` pane, 13 fresh pollers: p50 2,989ms -> 53ms, 31 -> 26 ps/min (TTL reader 1 -> 26). - The fork budgets serve interactive and fresh readers before display polls (cheap and TTL snapshot captures), FIFO within each. 20 display streams plus a 3s launch-paste read every 5s: 0/12 -> 12/12 served, polls 4-7 each. - On a selected terminal, the foreground group's argv is recovered even with no process of ours left (`exec su`); the root login is not. - Budgeted captures keep the 32 MiB output ceiling. * fix(terminal): age strict evidence by its oldest recovered argv (#31783) Round-3 review follow-ups. - Recovered argv carried no read time, so a capture reusing it (cached, or a recovery still in flight) stamped its own capture time over argv up to 2s older, and the remote write guard could take a same-comm re-exec for the agent. Rows now carry when ps read their recovered argv; runPsInProcess reports the oldest through onArgvReadAt, and the snapshot reader stamps capturedAtMs at that input, so capturedAgeMs is the age of the oldest input and consumers' own freshness checks (the write guard's 500ms) decide. A recovery begun more than 2s before a reader asked no longer answers it, and an older recovery finishing late cannot replace a newer one. - resolveSpawnFileForegroundFromRows reports a withheld `(node)` foreground unavailable. - One budget queue entry per invocation: an interactive request promotes a queued poll's, a poll joins an interactive one. - parseShellForegroundRows gets its JSDoc back. * fix(terminal): keep a cached name from authorizing a refused write; integer, under-2s argv ages (#31783) Round-4 review follow-ups. - When the relay's evidence declines a write (stale, unverifiable, another agent), its foreground name may still prove the shell but no longer proves the agent: that name can be the tracker's 1s display cache, e.g. `claude` cached just before Claude exited to a root shell under su. Relays that send no evidence keep the name as before. - Snapshot ages round up to whole milliseconds; the wire rejects fractions from the monotonic-to-wall conversion. - Recovered argv is reused for at most 1.5s, so reuse plus the 500ms snapshot cache stays under the 2s freshness gate; reuse ages from when that ps spawned, not from the wait for its fork token, and only an answer is remembered (a timed-out or withheld run proves nothing). Fork budget unchanged. Root su pane, 13 pollers: 30 ps/min; fresh p50 51ms; strict evidence age p50 752ms, max 1,508ms. * fix(terminal): keep the relay's agent name behind structurally unverifiable evidence (#31783) The previous commit refused the name fallback whenever the relay sent any evidence, so `unverifiable` evidence for structural reasons also blocked writes: npm Codex (node codex.js spawning native codex) and Gemini (relaunching itself) put two agent rows in the foreground group (ambiguous_foreground_group), and remote tmux reads multiplexer_boundary. On SSH POSIX hosts that dropped launch prompts and failed worker briefs, conversation send/cancel and automations with agent_not_in_foreground. The name now cannot authorize only when the evidence saw the group (`live`: stale, or no agent in it, as in the cached-`claude`-over-root-shell repro) or withheld a foreground argv (`argv_unreadable`, possibly a root `su` shell). Other unverifiable reasons keep the name fallback, as before this branch. * fix(terminal): let a relay name complete only fresh agent-positive evidence (#31783) The SSH name fallback still let a stale or cached name authorize a write under any unverifiable reason but argv_unreadable: ps EAGAIN (process_table_unreadable) after the tracker cached `claude` over a root bash, anchor_missing, tty_boundary (`sudo -i` with use_pty, a root shell on a new pty), or a 1.5s-old ambiguous capture. - The name now completes evidence only when it is fresh (within the guard's 500ms bound), its reason is one that saw an agent row (ambiguous_foreground_group, multiplexer_boundary, candidate_start_time_missing), and the name is the launched agent. Every other reason, including ones this build does not know, reads unknown. Relays that send no evidence keep the name, for mixed versions. - The relay's evidence names one agent that holds two rows of the group (npm Codex: node codex.js spawning native codex; Gemini relaunching itself), so a new relay proves them live even when its name is `node`. Two different agents stay ambiguous. No wire change. * fix(terminal): judge a relay name by the host's capture age; keep old relays' npm Codex (#31783) - Name completion compared the capture's start with the read's start, so a slow response made old evidence look fresh: a capture 1,500ms old arriving after 1,100ms passed. It now uses the host-reported capturedAgeMs against the 500ms bound, which latency cannot shrink. Live evidence keeps its capture-start rule. - Relays before same-agent dedupe report npm Codex (node wrapper plus native binary) as ambiguous_foreground_group and name it `node`. For that reason only, `node` now completes the evidence when the launched agent is npm-installed per the node entrypoint tables; other agents and reasons stay fail-closed. * fix(terminal): bound relay-name completion by twice the snapshot TTL (#31783) The 500ms bound refused ~9.5% of tmux name completions on a host with 13 pollers (cached snapshot up to one 500ms TTL old plus ~30ms capture, max 528ms), and a refusal drops the launch prompt or throws with no retry. The bound is now 2 x PROCESS_TABLE_SNAPSHOT_MAX_STALENESS_MS (1s), still on the host-reported age: 0 of 767 reads exceed it, the delayed 1,500ms repro still refuses, and the cached-name hazard (the tracker's ~1s display cache) is no wider. * fix(terminal): complete relay evidence with a name read now, not the display cache (#31783) With the 1s bound, a capture at 0-528ms, `codex` cached at 100ms, Codex exiting at 101ms and the guard at 999ms still let the cached name authorize a write over the bash that replaced it. - Name completion (structural reasons, host age within 2x the snapshot TTL) now asks confirmForegroundProcess, which reads the foreground now (a fresh scan, or node-pty's raw process name) rather than the tracker's 1s display cache; a null answer reads unknown. No new wire surface: the local daemon answers confirmForegroundProcess, paired runtimes evaluate guards locally, and the production controller returns null (read as unknown, failing safe) when a provider lacks it. Controllers without the method, and relays sending no evidence, keep the cached name as the legacy path. - Live evidence also accepts a host-reported age within 2x the TTL, so a real agent behind a 500-528ms cached snapshot on a fast link is no longer refused; a capture begun after the read was asked still counts, and 5,000ms-old evidence still refuses. * fix(terminal): confirm live evidence older than one snapshot TTL with a fresh read (#31783) Accepting live evidence up to 2x the TTL reopened the window the previous commit closed for name completion: a capture at 0-528ms, the agent exiting at ~529ms, and at 999ms `live claude` still read as agent over a bash. Live evidence begun no more than one TTL before the read was asked (so any host age within one TTL, however long ps took) still answers alone. Between that and 2x the TTL, confirmForegroundProcess reads the foreground now: the launched agent proves it, a shell reads shell, anything else unknown. Controllers without that read fall through and refuse, as before. Reachability: the remote (host.remote) write-guard path has no production caller since the SSH provider's removal (#27499); the registry dispatches only local providers and paired runtimes evaluate guards locally. This is defence in depth for any future remote provider. |
||
|
|
fd976a47be |
Keep zoomed PDF detail text sharp (#36173)
* Keep zoomed PDF detail text at device resolution * Test PDF detail update dimension-read bounds * Account for browser layout units in PDF geometry test |
||
|
|
5951dbbf92 |
fix(editor): task-list parsing fixes (ordered parents, wrapped markup, tight continuations, bare markers) (#35187)
* fix(editor): preserve sibling tasks beneath ordered list items * fix(editor): preserve wrapped inline markup in task items * fix(editor): keep nested task continuations valid and editable * fix(editor): keep literal task markers out of mixed checklists * fix(editor): apply review fixes to task-list parsing stack - Trim synthetic test matrices to the behavioral cases - Regenerate pnpm-lock (drops a stale github-slugger importer entry) - Assert the plain bullet's node type under an ordered parent * fix(editor): keep one-column-deeper ordered tasks as sibling checkboxes Dedent an ordered item's task block by the first task's column instead of keeping its leading whitespace. A task one column deeper stays a sibling checkbox, and text at or within the first task's column stays nested as before. Strip leftover paragraph indent from task children. --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
525719789f |
perf(terminal): read the macOS process table in process instead of forking setuid ps (#35987)
* perf(terminal): read the macOS process table in process instead of forking setuid ps (#31783) /bin/ps is setuid root, so every exec costs an uncached syspolicyd assessment and an EDR inspection. The terminal host forked ~7-10 ps/lsof per second with 4 agent panes, and each stale daemon multiplied that. node-pty's patched pty.node now exports processTable (sysctl KERN_PROC_ALL/KERN_PROCARGS2 on a worker thread), processCwd (PROC_PIDVNODEPATHINFO) and processPath (proc_pidpath). runPsInProcess renders the same ps column text for the invocations Orca issues, so the existing parsers and callers are unchanged; anything it cannot reproduce, non-macOS hosts, and builds without the exports keep running ps/lsof. Measured with 4 anchored panes polled every 750 ms for 60 s: ~440 ps/lsof children before, 0 after. * fix(daemon): roll the in-process macOS process table into a fresh v54 daemon (#31783) * fix(terminal): bound, escape and complete the in-process macOS process table like ps (#31783) Review follow-ups for the libproc reader: - Timeouts: every caller passes its ps timeout; a read stalled behind a saturated libuv pool resolves timed out (code null, timedOut) at that budget, exactly as the killed ps would. Identical native reads share one worker, each caller racing its own deadline; past 8 distinct reads in flight callers run ps. execFile-shaped callers reject like a failed child. - tty naming shares one slot with captureDarwinProcessTable's guard, so a draining naming pass sends both paths to ps instead of naming again. - Commands: the addon renders argv with adv_cmds' getproclline and strnvis (VIS_TAB|VIS_NL|VIS_NOSLASH) under the caller's LC_CTYPE via a thread-scoped uselocale, so newlines print as \012 instead of splitting tokens; zombies print <defunct>. - Other users' processes: unreadable argv is marked commandIncomplete. Only -p selections and processes on a terminal under the user's own readable process there (sudo in a pane) get a targeted `ps -p ... -o pid=,command=`, cached by (locale, pid, start time); root daemons and a pane's root login never spawn ps. - -t selects with KERN_PROC_TTY after ps's addelem_tty path resolution, so per-terminal reads skip argv for every other process (~0.3 ms vs 4 ms ps). - -p deduplicates; rows sort by terminal then pid as pscomp(); stat adds ps's < N X V L modifiers. The export is renamed readProcessTable so an older pty.node falls back to ps rather than misreading the new query. * test(terminal): diff the real libproc addon against /bin/ps on macOS (#31783) Spawns a pty holder whose argv carries a newline, tab, invalid UTF-8 and é, then compares Orca's ps invocations column by column: pid/ppid/pgid/tpgid/ lstart/tdev/tty exactly, commands for the user's own processes, and stat modulo running/idle (thread state needs setuid ps). Rows are compared only when two in-process reads around the ps run agree, so churn cannot flake it. * fix(terminal): never serve a native process table read begun before the request (#31783) A timed-out read stayed shareable, so a later descendant capture could join an earlier poll's abandoned worker and take its rows as fresh; a descendant that exited meanwhile could have its reused pid SIGTERMed. The addon now reports when its worker actually began reading (startedAtMs), and runPsInProcess refuses a shared read that began before its own request and reads again, so every consumer that signals from rows (descendant teardown, foreground-group signalling, identity probes) only sees rows scanned after its stamp. Regression: pty-descendant-termination-libproc. Also from review: - argv recovered with setuid ps is keyed by pid, start time to the microsecond, comm and executable path (exec changes the latter two) with a 10 min TTL and 512-entry bound. - Recovery covers a sudo use_pty tree: the unreadable chain must start on the terminal of the user's own readable process, so the root shell and agent on sudo's own pty qualify while root daemons, GUI helpers and a pane's root login (own pty, under a terminal-less or tty-inheriting host) do not. - Concurrent tty= readers wait out the single naming pass, and readers past the 8-read cap queue behind one, within their deadlines, instead of bursting /bin/ps at startup restore (24 panes polled at once: 0 ps). - darwin-terminal-naming-slot.ts is now darwin-terminal-naming-single-flight.ts. * test(terminal): require /bin/ps row order in the libproc parity test (#31783) Parsers that take the first matching row depend on ps's terminal-then-pid order, so compare the order of the rows both captures share, not just their contents. * test(terminal): pin libproc read start times instead of reading the wall clock (#31783) * fix(terminal): match native process table reads to requests by sequence, not wall clock (#31783) Freshness compared the worker's gettimeofday with Date.now(), so a clock step back let an abandoned read's rows through (wrong-pid SIGTERM) and a step forward could reject fresh reads until the deadline. Each read now takes a JS-side sequence number when created and is submitted a microtask later; a caller joins only a read not yet submitted or created after it registered, so callers in one turn share a worker and nothing submitted before a request serves it. The addon drops startedAtMs again. Deadlines, timeouts and the argv cache use performance.now(). Callers past the 8-read cap wait on one slot notifier and each joined read has one settle notifier; both unsubscribe on timeout, so a stalled pool retains no per-caller reactions. If the pool is still at the cap when an overflow caller's deadline passes, the reader is marked stalled for 30s and callers run ps, as before this branch. Recovered argv is trusted for 30s: exec can keep pid, start time, comm and executable (node -> node with another script) and no cheap field shows it, so a sudo pane costs one targeted ps per process per 30s. * fix(terminal): keep ps fallbacks off a stuck terminal naming pass (#31783) - captureDarwinProcessTable's canonical fallback, taken while the naming slot is busy, now runs /bin/ps directly instead of re-entering the in-process reader and waiting on that same slot (a held lstat timed out every strict capture without one subprocess fallback). - In-process tty= readers wait out a short pass (startup restore) but hand a pass older than 500ms to ps, which names terminals out of process. - The naming single flight keeps one settle notifier per pass; waiters sit in a Set and drop off on timeout, so timed-out callers leave no reactions on a stuck pass (was one per call). The notifier moves to deadline-settle-notifier.ts, shared with the native read scheduler. - Once the native read breaker has tripped, a caller finding the cap still held after the cool-down returns to ps at once instead of waiting out its timeout. - Descendant teardown and foreground-group signalling give the native read half their budget and fall back to a fresh ps on a native timeout, so a partly stalled pool cannot cost a kill. * fix(terminal): give signalling ps fallbacks their full baseline timeout (#31783) Splitting the budget in half shrank ps's window behind a stalled native read: a 750ms ps lost descendant SIGTERMs and an 80ms foreground ps lost group SIGWINCH. Descendant teardown and foreground-group signalling now try the native reader for min(150ms, timeout/4) (inProcessSliceMs), then give ps the whole original timeout; readProcessTableBeforeDeadline extends the production reader's outer deadline by that slice, so ps succeeds exactly when it did on main. The stale-read regression test now also asserts the fresh rows' real descendant is signalled. * fix(terminal): carry the in-process deadline allowance through every descendant reader (#31783) readProcessTableBeforeDeadline granted the native slice only when the reader was readProcessTable by identity, so the daemon shutdown sweep's sharing wrapper kept a bare 250ms deadline: a stalled native read plus a 200ms ps missed it on every retry and descendants survived shutdown. ProcessTableReader now declares deadlineAllowanceMs; the fresh reader sets it (0 without the addon or with a stalled pool, so Linux and ps-only hosts keep their exact deadlines), createProcessTableSnapshotReader and the shutdown wrapper inherit it, and injected readers default to none. The fresh reader moves to pty-descendant-fresh-table.ts. The real-ps parity test gets a 30s per-case timeout, since whole-table /bin/ps runs slow under suite load. * chore(terminal): move the descendant reader's child_process baseline entry with it (#31783) * test(terminal): pin the libproc test locale so lstart doesn't follow the runner's LANG (#31783) |
||
|
|
f12e12f212 | fix(test): report a failing test whose stack names a Bun builtin frame (#35384) | ||
|
|
a891e3612c |
chore: remove remaining Vitest patch (#34878)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
7cdfebdc1b |
Revert iteration checks and custom Vitest selection (#34834)
* revert: remove iteration checks and custom Vitest selection * chore: use upstream affected-test selection --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
0866cb1b08 |
fix: bound local iteration checks and show live progress (#34700)
* fix: bound local iteration checks and show live progress * fix: harden check lifecycles and cached test evidence * fix: preserve process instrumentation and fixture lifecycles * fix: give fixture unref spy a portable function type --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
917ef9c737 | feat(browser): install Chrome extensions from the Web Store into Orca's browser (#30940) | ||
|
|
176852ad5a |
fix(terminal): highlight the active IME conversion range (#27903)
Japanese IMEs convert one clause at a time, but the terminal's preedit overlay painted the whole composition uniformly, so the clause the candidate window targets was invisible. Read the IME's selection from xterm's textarea on the insertCompositionText input event (Chromium only updates it there) and paint that range of the preedit in the theme's selection colors. Cell-grid advance corrections are unchanged and nothing reaches the PTY; a collapsed caret or a range outside the preedit highlights nothing. Fixes #27873 Co-authored-by: Neil <neil@stably.ai> |
||
|
|
becf899273 |
fix(test): stop Vitest failing green unit shards with EISDIR on directory stack frames (#34335)
Vitest's reporter checks existsSync(file) and then reads the file to find a source map. When an error stack names a directory, readFileSync throws EISDIR as an unhandled error, so the shard fails with every test passing. Read only regular files. Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
47567c6ac7 |
fix(terminal): refuse non-finite mouse coordinates so scroll never sends NaN to the PTY (#23330)
xterm's touch inertia gesture events carry no clientX/clientY, so with a TUI requesting wheel reports a flick sent `ESC[<65;NaN;NaNM` to the PTY (#20983). NaN slipped past `col < 0 || col >= cols`; the patched range check in MouseService._triggerMouseEvent is negated so it fails closed. Regenerate the beta.304 bundle and lock hash. Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com> |
||
|
|
fcf5e7b418 |
fix(native): pin node-pty cfset*speed with legacy baud codes for glibc 2.42+ (#33803)
* fix(native): pin node-pty cfset*speed with legacy baud codes for glibc 2.42+ glibc 2.42 versioned cfsetispeed/cfsetospeed (GLIBC_2.42) to take literal rates and redefined B38400 as 38400U, so node-pty built on 2.42+ fails the Ubuntu 20.04 floor gate. Pin both to the compat version alongside the existing openpty/forkpty/pthread_sigmask pins, and pass the legacy CBAUD code (__B38400 on 2.42+ headers, B38400 otherwise): the compat setters reject literal rates with EINVAL, which left every PTY at speed 0. Fixes #19420. Supersedes #19421. Co-authored-by: MK <mkjung.github@gmail.com> * fix(native): fail the build if pinned cfset*speed would get a non-legacy baud code A 2.42+ header set without __B38400 would otherwise silently pass 38400U to the compat setters and open every terminal at B0. --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Co-authored-by: MK <mkjung.github@gmail.com> |
||
|
|
e4bbbe045f |
perf(test): faster local test loop and cold-worktree changed runs (#33421)
- test:changed exits before starting Vitest when Git reports no changed files. - Unrecorded tests beyond 100 in scope use Vitest's static import graph instead of all running, so a fresh worktree's first changed run no longer runs the whole suite (patched RecordedModulesResolver; CI does not record, unchanged). - Bun's slow config load was the SQLite import scan statting every unit test; filtered runs now classify only the tests their filters can select, and the scan walks directories instead of fs.globSync. - Silence the native config loader notice on every run. - Zod's test bundle is content-addressed and reused, so a killed run leaks nothing; leaked per-run directories older than 6h are swept. - build:packages skips compiling when package inputs, compiler, and dist are unchanged; test scripts no longer nest pnpm invocations. |
||
|
|
f3104c80bf |
fix(daemon): a Windows terminal's output-relay write error no longer kills the PTY daemon (#33391)
* fix(daemon): contain ConPTY output-relay write errors to the one terminal instead of killing the daemon * fix(daemon): end a Windows terminal whose output relay dies before connecting * fix(daemon): kill a Windows terminal whose output relay fails before its first output |
||
|
|
ec5cfbad37 | fix(deps): patch vulnerable Zod collections in mobile and docs (#32941) | ||
|
|
4c6cfda0ac | fix(editor): keep paragraphs starting with "Dr.", "A." or "iv." out of ordered lists (#32694) | ||
|
|
a8dff64cb8 | chore: remove unused shadcn generator dependency (#31737) | ||
|
|
5f50b95c9c |
fix: remediate dependency security advisories across workspaces (#31681)
* fix: remediate dependency security advisories across workspaces * test: verify security patches without ad hoc dependency installs |
||
|
|
df0c44571b |
fix(build): shared native packages get one immutable build instead of in-place rebuilds (#30226)
* refactor(build): extract the lock-free shared tree publish from the Electron dist cache Native builds in package dirs shared across worktrees need the same stage, validate, rename-into-place publish; one implementation keeps the never-replace-a-good-entry and quarantine-restore rules in one place. * fix(build): never rebuild a native addon in a package dir other worktrees load Under pnpm's global virtual store node_modules/node-pty is one store slot shared by every worktree, so an in-place node-gyp or @electron/rebuild run in one worktree replaced the pty.node another was running. A shared package dir now gets an immutable per-ABI build/orca-napi-<platform>-<arch> compiled in a scratch copy, load-checked in a fresh process, and published atomically; a usable entry is reused, never rebuilt. The patched node-pty and windows-process-tree loaders try that dir before build/Release, and packaging renames it to build/Release so packaged layouts are unchanged. Private (non-GVS, CI) installs keep the existing in-place path. * fix(build): find shared native packages through the project's own node_modules link require.resolve with paths fell back to another install under Bun, so a test fixture's private node-pty was judged shared. * ci: run native checks when the shared native build modules change * fix(build): pin the shared native slot and keep sibling publishes intact Resolve the package's physical dir once so a concurrent relink cannot publish one slot's build into another, verify the quarantined tree is the one judged unusable before replacing it, and keep in-flight staging/quarantine trees out of the packaged resource copy. * fix(build): never move a sibling's fresh native entry, and refuse off-platform builds Re-check the entry's identity right before quarantining it, and fail instead of publishing a host-OS binary under another platform's entry name. |
||
|
|
357aa41cb4 | fix(terminal): keep Vim scrolling inside shrunken panes (#29960) | ||
|
|
90849ed0c6 |
Enable Claude plugin images and bounded terminal file transport (#28200)
* fix: render Kitty Unicode placeholder images with bounded ownership * Enable managed Claude plugin images and bounded host file transport * Preserve isolated Claude evidence and paired restart diagnostics * Resolve Windows workspace aliases before WSL image reads * Handle split remote terminal identities and improve WSL file-read diagnostics * Reuse native drive paths for WSL image files and preserve guest temporary roots * Apply native Windows path restrictions to mapped drive image sources * Preserve WSL participation evidence across image checks * Keep WSL drive directory containment case-sensitive after canonicalization * Negotiate managed Claude image support with the launching renderer * Make image repaint checks independent of display profile and shell output * Capture repaint diagnostics only after the pixel assertion fails * Allow floating terminal image reads from host temporary folders * Keep image stack independent of unrelated CI runner and mobile lint settings * Reuse worktree argument builder for terminal viewer context Remove duplicated mapping and keep the RPC method table within its existing line limit. |
||
|
|
26278b32ce |
Render Kitty images at Unicode placeholder cells (#26031)
* fix: render Kitty Unicode placeholder images with bounded ownership * Make image repaint checks independent of display profile and shell output * Capture repaint diagnostics only after the pixel assertion fails |
||
|
|
6607c54984 |
perf(ci): cut redundant tests and reuse expensive setup (#28669)
* perf(ci): reduce test overhead and reuse expensive build work * test(ci): keep worker startup outside failure-case deadlines * test: isolate push fixture advisory locks * test(ci): preserve fixed drain retry allowance * Align CI contracts with current triggers and guide content * Stabilize consolidated reveal scenarios and retain behavioral CI contracts * Fix upstream lint blockers while retaining behavior and assertions * Classify global Jira preferences in the WSL migration inventory * Align Jira test fixtures with startup and build safety checks * Include package-test routing dependency in CI checkouts and fixtures * Keep native stream classes intact in transcript dependency tests |
||
|
|
58d0de6bb6 |
fix(terminal): keep the text of an IME key pressed before a commit finalizes (#28441)
* fix(terminal): keep the text of an IME key pressed before a commit finalizes A Process (229) keydown that lands after compositionend but before xterm's deferred finalizer runs took the composing early return and never recorded that it owed its own commit. When the finalizer ran first, the key's insertText found no pending transaction and no owed commit, so xterm dropped it: `你` then `,` reached the PTY as `你`. Record the debt for such a keydown when the ended session's commit is already in the textarea, and clear it when the pending transaction settles the text itself. Sessions still waiting for their post-composition echo keep their old path, so the echo cannot be sent twice. Fixes the intermittent terminal-linux-direct-ime-commit e2e failure. * fix(terminal): keep a commit when Escape or a keypress follows compositionend A plain Escape after compositionend cancelled the accepted commit, dropping both the text and the Escape; it now settles the commit and then sends Escape. The Escape that itself ends a session (still composing, reported after compositionend) still cancels. A keypress for the Process key that owes a commit now clears that debt, so a later input cannot send the key's text a second time. |
||
|
|
83d096b5f5 |
perf(lint): avoid unnecessary anti-slop scope construction (#28470)
* perf(lint): construct anti-slop scopes only for relevant expressions * fix(ci): resolve extensionless mobile census entries as files |
||
|
|
7e0d6dc2f6 | fix(diff): stop closed diff editors from leaking through Monaco's gutter menu (STA-3565) (#27793) | ||
|
|
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> |
||
|
|
d327cc9418 |
feat(daemon): opt-in OS ceiling on terminal processes, reported per host (#27769)
* feat(daemon): opt-in OS ceiling on terminal processes, reported on or off per host * fix(daemon): verify the ceiling is enforced, reap its slice with the daemon, and keep terminals starting when systemd-run is unusable * fix(daemon): stop the ceiling slice before the daemon scope, and report a dropped slice as lost * test(daemon): expect the pid record's processCeiling field --------- Co-authored-by: m4air <m4air@Mac.localdomain> |
||
|
|
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 |
||
|
|
da6d632a91 | [CI] Revert library patches introduced by test optimization (#26727) | ||
|
|
59b9bdeb90 |
Reduce repeated test work and fix Windows cleanup and IME confirmation (#26608)
* ci: share test transforms and remove six redundant checks * test: remove obsolete project copies and two build string checks * test: use the injected clock for exact launch readiness budgets * fix: retain IME confirmation and retire disconnected Windows PTYs * ci: include relay installer in existing Windows boundaries * perf: import the canonical SSH manager for filesystem operations * test: remove 42 source-spelling checks * test: advance deadlines after real entry and await actual PTY exit * Preserve native Windows exit acknowledgments and skip daemon-only smoke triggers |
||
|
|
e3639ef8d6 |
Phase 3.5: fix the top SSH/remote issues at the root cause (#26483)
* fix(remote-runtime): stop arm64 Linux servers dropping clients every heartbeat (empty WebSocket write EFAULT) (#26200) * fix(remote-runtime): never write an empty WebSocket payload on its own (arm64 Electron EFAULT) Patch ws@8.22.0 Sender.sendFrame so a frame with an empty payload is written as its header alone. Under Electron on arm64 kernels with 39-bit virtual addresses, socket.write() of a zero-length buffer fails with EFAULT and kills the connection, so every empty heartbeat ping, auto-pong and close dropped the remote runtime with 1006. Wire bytes are unchanged. * test(remote-runtime): run the ws empty-payload guard on real Node Bun resolves 'ws' to its built-in client, so under the Bun test project the guard exercised Bun's implementation instead of the patched package. --------- Co-authored-by: m4air <m4air@Mac.localdomain> * fix(orcad): ship the session scanner child so agent session history lists on orcad hosts (#26309) orcad built every forked child except session-scanner-service-entry.js, so aiVault.listSessions always failed on an orcad host. The resolver also skipped the adjacent entry whenever isPackaged was true, so shipping the file alone would not have been enough. - build every ORCAD_CHILD_ENTRY_POINTS entry from one loop and add the scanner - add it to ORCAD_ARTIFACTS so a deploy missing it fails integrity checks - share one forked-child path resolver (asar layout vs flat app root) between the watcher and the scanner - smoke-fork the built scanner during build-orcad under both runtimes Fixes #24105 Co-authored-by: m4air <m4air@Mac.localdomain> * fix(remote-runtime): one owner for a remote pane's binding and recovery (#26308) A remote pane no longer latches in connecting on terminal_not_found, holds keystrokes typed during same-terminal recovery instead of dropping them, reports transport-owned retries so the pane is not remounted mid-retry, and no longer infers absence from an inventory that predates the leaf. Co-authored-by: m4air <m4air@Mac.localdomain> * ci(e2e): move apt off the Azure mirror on runner images that use a mirror list (#26335) Ubuntu 24.04 runner images resolve apt sources through /etc/apt/apt-mirrors.txt, so rewriting only the source lists left package downloads on azure.archive.ubuntu.com, which intermittently fails ('Ign:' on every package). Rewrite the mirror list too, and retry the install once with --fix-missing. Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(terminal): remote snapshot replay keeps scrollback it cannot replace (#26319) Desktop subscribers of a remote terminal received screen-only snapshots, and every pushed snapshot replay cleared the pane's scrollback with ESC[3J. A reconnect, a remount, or a recovery after a dropped frame therefore wiped history the host never resent. - Host: desktop subscribe snapshots use the same scrollback-row ladder as mobile, and SnapshotStart now carries an optional scrollbackRows field. - Client: a pushed snapshot clears scrollback only when the host says it carries history; screen-only images (scrollbackRows 0, or older hosts that omit the field) repaint the screen and keep the pane's history. Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(daemon): clean launch env, validate client frames, fit the socket path (#26306) * fix(daemon): clean launch env, validate client frames, fit the socket path - Drop Chromium's DBUS_SESSION_BUS_ADDRESS=disabled: marker from the daemon, its systemd-run scope launch and every PTY env (#25580, #21119). - Use the durable user-manager scope only when that manager outlives the caller: lingering on, or the caller already runs inside it (#24201). - Shape-check hello and request frames, and catch request rejections, so a malformed frame closes one connection instead of the daemon (#17841). - Move the daemon socket to a short per-uid private dir when the data root would overflow sun_path (#17840). * fix(daemon): validate a relocated socket dir before any connect, not just before bind --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(ssh): keep crediting a PTY after its recovery delivery is canceled (#26341) A canceled recovery delivery released its source spans while the renderer and model could still settle them; the stale projection then threw on every later ACK, so the next delivery was never credited and the relay paused the PTY for good. Settling or transferring a span of a closed delivery is now a no-op. Co-authored-by: m4air <m4air@Mac.localdomain> * fix(rpc): deny-by-default caller permissions and a scoped SSH bridge credential (#26337) * fix(rpc): deny-by-default caller permissions and a scoped SSH bridge credential Every RPC method now declares a required permission, and RpcDispatcher checks it against the caller's scope on every transport (owner, mobile, paired runtime, SSH bridge). The SSH relay bridge no longer spawns the client CLI with owner authority: each invocation gets a short-lived credential bound to its SSH target, revoked when the child exits. Without the new per-host opt-in, that credential reaches only its own host's terminals; with it, workspace methods but never desktop control, accounts, settings writes, skill install/share, pairing or host admin. Paired runtime clients need a pairing-time grant (orca serve --grant-desktop-control) for computer.* actions. Fixes #23835 Fixes #25259 Refs #18269 * fix(rpc): let a bridged SSH worker report to its own coordinator; allowlist paired-runtime permissions Without the per-host opt-in, orchestration send/ask/reply/check/inbox now pass when the caller is a terminal on the bridged host, binding pane key, payload Dispatch, run and recipient to that caller's own orchestration (recipient off-host only as the creator of its active Dispatch). Paired runtime clients get an explicit standard permission set; pairing-admin and desktop-control are grant-only. * fix(rpc): resolve a bridged SSH caller's own Run and Dispatch mailboxes before admission Mail routing stores a worker's follow-ups under dispatch:<id> and worker questions under run:<id>, so comparing the original recipient to the caller's terminal handle refused an SSH worker replying to its coordinator, an SSH coordinator answering its own Run's question, and explicit sends to the caller's own run:/dispatch: address. The bridge now resolves the exact mailboxes the caller's live pane and process read (as check does) and admits replies and recipients against those. * refactor(rpc): parse SSH bridge selectors with a typed schema instead of Reflect.get --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(projects): remove a project only on the host the user picked (#26340) * fix(projects): remove a project only on the host the user picked removeProject now requires a hostId and matches that host's row exactly. The bare-id fallbacks (unique candidate, focused host) could resolve to another host's live project and delete it. Orphaned SSH purge and group deletion now pass each row's own host. Fixes #13071 * fix(projects): group delete removes only the group's member rows Same-id rows on other hosts outside the group were removed because membership was rebuilt from bare ids after the cascade cleared it. Capture (id, host) member pairs before deletion and remove only those. * fix(projects): never let a stale catalog widen a project removal to every host The renderer chose id-only `repos:remove` when its own catalog showed no same-id row on another host. A stale catalog (another window, a paired client, or a pending refresh) hid that row, and main then deleted every host's registration and saved workspace metadata. - The local catalog route now always calls `repos:removeForHost` with the owner row's host, for local, direct SSH, git and folder projects. - `Store.removeProject` refuses an id that rows on more than one host share, so no id-only caller can delete another host's row. - Setup rollbacks remove the just-created row by its host. --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(serve): load SSH targets on a headless serve; a user Quit only closes serve-hosted windows (#26348) * fix(serve): load SSH targets on a headless serve; a user Quit only closes serve-hosted windows - launchServeMode registers the SSH handler layer before RPC binds, so a windowless 'orca serve' lists and connects the profile's SSH targets (#25886, #8489). - Under serve, the app-menu Quit/Exit, tray Quit and renderer-recovery Quit close the desktop windows instead of quitting the process (#15537). Signals, supervisor stops, relaunches and update installs still quit normally; on macOS a signal reaches before-quit the same way Cmd-Q does, so the guard lives on the user commands, not in before-quit. * fix(serve): SSH profiles serve on Electron; native macOS quits and frozen windows no longer trap or stop serve - orca serve: a profile with saved SSH targets stays on the Electron host by default, since orcad has no SSH stack yet (#25886, #8489). ORCA_SERVE_RUNTIME=orcad still forces orcad. - macOS serve: Dock > Quit, app-switcher Cmd-Q and other native terminates only close the desktop windows (#15537). Signals, supervisor stops, relaunches, update installs and logout/shutdown still quit. - The serve signal listeners now reclaim SIGINT/SIGTERM/SIGHUP from Electron's native handler. Any signal that had a Node listener before app ready was left with Electron's handler, so these listeners never ran. - A serve user Quit closing a frozen renderer's window arms the same 10s ack deadline as a desktop quit, and skips minimize-to-tray. * fix(serve): stay on Electron when the profile's SSH targets cannot be read yet A valid older-schema profile is rejected by the read-only probe, and the selector took that as "no SSH", so a default serve before the first migration started orcad with an empty SSH registry. Fail closed instead. * refactor(window): type user-Quit close marks as a named window slice, not object * test(serve): pass the desktop-control grant default in the headless SSH launch fixture * test(serve): run the serve-selection SQLite fixtures in the Node runtime project --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(terminal): keep the main-process terminal tail linear under TUI redraw floods (#26316) * fix(terminal): keep the main-process terminal tail linear under TUI redraw floods Full-width in-place row rewrites rebuilt the row string per character (O(width^2)), a long chunk past the line cap spliced the row array once per newline (O(lines x cap)), and multi-frame chunks summed every cursor-up so they fell back to the whole-tail path. Rows now hold mutable cells joined once, capped rows are dropped in batches, and the redraw window uses the net cursor reach. Fixes #11315 * fix(terminal): do not rebuild a redraw row the cursor only revisits Rows stayed cell arrays once touched and re-joined on every newline, so a cursor revisiting one wide row thousands of times cost O(width) per newline. Runs now splice into the row string, a row switches to cells only after 32 edits between snapshots, and cells are joined once and dropped. * fix(terminal): keep one cached row per chunk so unchanged redraw revisits cost O(1) A row now keeps its cells, right-trimmed snapshot and content end across newlines and only invalidates them on a real content change; identical writes leave it clean. Adds a work-accounting matrix over restore, the append path and live onPtyData, plus a per-character row oracle fuzz. * fix(terminal): return redraw rows to flat strings with cached snapshots Cells made every changed snapshot a full-width join, which was far slower than the old flat-string splice. Rows are flat strings again, written one run at a time; each keeps a cached right-trimmed snapshot and content end that only a real change invalidates, so identical rewrites and cursor-only revisits stay O(1). A wall-time test now times every review probe against a vendored copy of the old row model on restore, append and onPtyData. * test(terminal): read runtime leaf and PTY tail through typed members --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(ssh): relay fallback runs Orca's pinned Node by default, never a host npm install (#26303) * fix(ssh): relay fallback runs the pinned Node ladder by default, never a host npm install A host whose connect falls back to the relay route now gets the A/B/C ladder (Orca's uploaded Node and prebuilt addons) unless it opts into Host Node. A refused rung C steps to rung D with an actionable reason instead of compiling native deps on the host. * fix(ssh): mark the opt-in Host Node relay runtime as unsupported on the SSH host card The relay fallback now defaults to Orca's pinned Node ladder; the host-npm path is reachable only by an explicit per-host Runtime or ORCA_SSH_REMOTE_RUNTIME override. When a relay actually launches on it, main publishes hostNodeRuntime on the connection state (optional, admitted field-by-field for paired clients) and the SSH host card shows an unsupported-configuration warning. * fix(ssh): keep the relay runtime ladder honest about what it cannot verify - NixOS's stub loader refusing Orca's generic Linux Node (exit 127, 'Could not start dynamically linked executable') is classified wrong_libc, so the ladder steps on to the host Node instead of failing the connect at rung A. - In plain SSH mode the shell provider answers absent only for shells it saw exit; a PTY id it never minted (one an earlier relay may still run) is unverifiable, never exited. - The rung D message offers Host Node only when the host's own Node refused the prebuilt addons, and calls it an unsupported configuration; a download, unresolved-host or Windows refusal gets no Host Node advice. * fix(ssh): keep the host-Node relay where the ladder can't judge the host A client without Orca's runtime artifacts (a dev, e2e or source build with no orcad template, or an offline client) refused rungs A and C with artifacts_unavailable, and the connect settled on rung D. That reason describes the client, so it now lands on the host-Node relay it had before the ladder, marked unsupported, and persists no host decision. A proved noexec still lands on D. Windows hosts have no rung B or C yet, so any rung A refusal there keeps the host-Node relay too. The rung D message is worded from the host OS: Windows gets no noexec-mount wording and is offered Host Node. * fix(ssh): a host-Node fallback with no Node settles rung D, and mutable refusals expire The host-Node relay the ladder chooses in place of D (a client artifact gap, or a Windows rung A refusal) hard-failed the connect when the host had no Node: the resolver threw a plain Error, which plain SSH mode does not admit. The fallback now proves host Node with a strict probe first; an answered "no Node" settles D with a classified, host-OS worded reason, and an unanswered probe stays a retryable failure. A gap no longer rewrites D to host Node once rung C proved host_node_missing. Mutable pinned-runtime refusals (missing_lib, security_software, and noexec on Windows) are no longer persisted and replay from memory for ten minutes only, so a repaired host gets rung A back. The in-memory refusal cache moves to ssh-relay-pinned-refusal-cache.ts. * fix(ssh): no host does worse than the pre-ladder host-Node default Restructure the relay runtime ladder around one invariant: A, B and C are tried first, and any refusal past them falls back to exactly the pre-ladder default, the host-Node relay marked unsupported. That covers an unidentified libc, a client artifact gap, Windows, mutable refusals and a C N-API floor the npm build would not have hit. Rung D is reached only when that fallback proves the host has no usable Node, or a proved noexec home would defeat it too. Strict host-Node resolution now treats only a command that ran and exited as an answer, so a refused channel (MaxSessions), session limit or timeout stays a retryable failure instead of a 'no Node' verdict. The launch reuses the Node the fallback probe found. Mutable refusals (missing_lib, security_software, Windows noexec) persist again with their proof time and replay for 24 hours, so a host that still blocks Orca's runtime is not re-uploaded to on every connect, while a repaired one gets rung A back. A table-driven test asserts the invariant per host class. * fix(ssh): every answered rung failure reaches the host-Node default, and D only past it Two shortcuts skipped the pre-ladder default. An answered but unclassified install failure (tar ENOSPC, an extract or hash marker, an unverified Windows promote, a self-test that failed outside every refusal class) aborted the connect on every attempt; it now steps down as a non-persisted install_failed. Only unanswered failures (abort, timeout, channel-open, session limit, an unconfirmed termination, SFTP connection loss, ssh exit 255) stay retryable, and nothing steps down once a relay launch was issued. A proved noexec no longer jumps to D: exec denial can be per binary (AppArmor allowing /usr/bin/node), so it skips B and C, which load from the same tree, and reaches the host-Node fallback. D now follows only that fallback answering with a failure, so its outcome is a superset of the default's by construction. The never-worse test is now the cross-product of every A, B, C and host-Node answer on Linux and Windows, plus named review cases. * fix(ssh): system-ssh upload failures and a broken cached runtime step down before launch System-ssh directory upload and system sftp threw plain Errors that dropped the host's exit status, so a remote tar ENOSPC or a Windows sftp permission refusal aborted the connect instead of stepping down. The remote side now throws SystemSshCommandExitError (ssh exit 255, signals and lost-connection diagnostics stay retryable), and a local tar failure is still blamed on the client rather than the remote tar that saw its truncated stream. The warm runtime check only tested that the verified executable existed, so a cached runtime that the host's exec policy or a removed library had since broken was launched and hung on every reconnect. The same command now also runs it and reports a refusal the way promotion does, so it steps down before any launch, with no extra round trip. * fix(ssh): keep the remote answer when local tar only failed writing to it When the host's tar exits early (ENOSPC, a refusal), BSD tar on macOS exits 1 with 'Write error' and no signal, so the upload rethrew the local error and dropped the typed remote exit, aborting the connect. The remote answer now wins whenever local tar finished, was signalled, failed after ssh closed, or reported a write or pipe error; a local tar that failed on its own input first is still the client's fault. * test(ssh): hostile-host cells allow read-only version probes, never installs; probe each Node once The noexec-home cell failed on 'npm --version': under the never-worse ladder a proved noexec reaches the strict host-Node fallback, whose probe asks npm its version before settling D. The cells now judge install and compile calls (npm install/ci, node-gyp, cc, make) and allow '<tool> --version' / '-v'. The probe ran twice because the login shell named the Node the path probe had already rejected. Candidate checks are now memoized per resolution, for the host-Node fallback and rung C alike. --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * chore(i18n): regenerate the runtime-required English catalog after the main merge * fix(serve): serve on the profile the CLI selected, and refuse any other before the instance lock (#26424) Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(remote-runtime): open terminal tabs reattach after a managed server update re-pairs the host (#26433) * fix(remote-runtime): a remote pane rebinds after a server update re-pairs its host A pane captured the host's pairing revision once, when it mounted. A forced managed-server update re-pairs the host under the same environment id, so every later request from that pane was refused as stale, and the refusal counted as fatal: the pane stopped retrying and Reconnect replayed the same stale revision. Each request now carries the current revision, a pairing refusal re-reads the catalog before the retry, and the pane treats it like lost contact. * fix(remote-runtime): close a stream left on the old pairing and ignore a 0x0 grid hold A stream that reopened before main re-paired stayed open while sendFrame refused its stale revision, so typed keys vanished. A revision change now closes it as recoverable so the pane rebinds on the new pairing. A just-restarted server also published a 0x0 hold that shrank the visible pane to one cell; holds with no grid are ignored. * fix(remote-runtime): a pane follows only its own machine's re-pair A re-pair under the same environment id to a different host key published its revision before the catalog retired the old tabs, and the pane recovered at the new revision, so its next call was authenticated as the replacement peer. The catalog now classifies each re-pair before publishing revisions: a replaced or removed machine's terminal streams end for good first, and a pane only advances its pairing along a proven same-host rotation (same registration and host key). An unresolved identity holds the pane until it is proven. --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * refactor(rpc-permissions): Phase 3.5 elegance pass (#26471) * refactor(rpc-permissions): drop never-read incarnation and invocation id from bridge credentials * refactor(rpc-permissions): define runtime device grants once and reuse bridge scope fixtures * refactor(rpc-permissions): decide terminal host membership in one predicate and share the opt-in hint * refactor(rpc-permissions): parse bridge selectors once per call * refactor(rpc-permissions): admit and bind unopted bridge methods from one table --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * refactor(remote-pane-binding): Phase 3.5 elegance pass (#26470) * refactor(remote-pane-binding): keep the pane's pairing revision in one slot * refactor(remote-pane-binding): share one hold decision across the input entry points * refactor(remote-pane-binding): define the persisted-handle adopt once in attachPane * refactor(remote-pane-binding): build the pushed-snapshot meta once * refactor(remote-pane-binding): drop the test-only peerReplacedEnvironmentIds wrapper * test(remote-pane-binding): share the input and subscribe frame readers via stream fixtures --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * refactor(relay-ladder): Phase 3.5 elegance pass (#26474) * refactor(relay-ladder): put the host-Node fallback in the ladder before D The Auto ladder now lists legacy as the rung before D, so the step function is one rule plus the next rung. Deletes nextRelayRuntimeStep, the hostOs step context and the mutable hostNodeFallback flag (now a constructor-time laddered field). Windows still ends at legacy: B and C refuse there before any host I/O. * refactor(relay-ladder): one rung-D reason and message over reachable states D is reached only from the host-Node fallback, so its refusal is host_node_missing or install_failed. Merges the reason and message functions, drops three message branches that could not run, and folds noexecRemembered/noexecProved into one noexec field. * test(relay-ladder): one never-worse cross-product with a remembered axis Drops the named cases (each matches a cross-product outcome), the transport case that only checked the model against itself, and the third case the rank check already implies. Adds rung B's noexec answer and per-rung remembered flags for A and B, the only rungs that replay a cached refusal. * refactor(ssh): one answered-miss rethrow for the node resolution probes Four catch blocks repeated the same session-limit, abort and strict checks. They now call rethrowUnlessAnsweredMiss and keep their own fallthrough. Also drops a stale 'Caches nothing' comment. * refactor(ssh): share the host-answered system-ssh exit rule; flatten the upload throw cascade isHostAnsweredSystemSshExit owns the 255/null transport rule for both the upload pipeline and isAnsweredHostFailure. settleUploadPipeline drops a branch that could not run: a failed tar is judged once, then ssh, then pipe. --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * refactor(serve-daemon-misc): Phase 3.5 elegance pass (#26478) * refactor(ssh-pty): build obligation transitions behind one closed-delivery guard * refactor(build-orcad): table-drive the shipped worker smokes * refactor(daemon): pass scope probe seams as one deps object and share cgroup line parsing * refactor(repos): route every project removal through removeProjectForHost * refactor(build-orcad): type the worker smoke table for the type-aware gate --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> Co-authored-by: m4air <m4air@Mac.localdomain> * refactor(terminal-tail): Phase 3.5 elegance pass (#26465) * refactor(terminal-tail): share mulberry32 and compare whole results in redraw equivalence tests * refactor(terminal-tail): keep one splice ceiling at the onPtyData entry point --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> * fix(terminal): bound the backing a redraw row can pin across chained erases (#26547) Each erase that keeps at least half the row skipped the copy, so a chain of them left nested slices pinning the original wide row. Rows now track an upper bound on the string they slice and copy once the cumulative shrink passes half. Co-authored-by: m4air <m4air@Mac.localdomain> --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
b32462f246 |
Replace patched JSON parser with stream-json (#25202)
* Replace patched JSON parser with stream-json * Isolate dependencies for historical server compatibility builds |