Commit Graph
128 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin e173296f14 test: remove Linux screenshot refusal-only classes (#42405)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-14 06:27:40 -08:00
Brennan Benson 88a266e003 Make SQLite the source of truth for native chats (#39256)
* Retire projection adapter tests and use real SQL journal fixtures

* Persist bounded history detail and conversation outline projections

* Select rewind cuts by provider indexes and delete uniform rows as a set

* Cache bounded conversation outlines after reader projection

* Remove retired journal fold and message adapters

* Add the 4a main-vs-candidate native chat comparison harness

One entry (native-chat-4a-comparison.ts) seeds the 55k-history/310-chat
profile once through the seed arm, clones it per arm at a fixed path,
launches each built checkout in the background with an isolated home,
and drives the same stub provider events through the host RPC surface
both builds serve. Envelopes come from each arm's own source bundle.
Rows cover send/queue, 1/8/16 MiB streams with a competing send,
maintenance windows, open/reopen, history/detail, outline/fork,
rewind, record operations, R3 retained-history admission and, reported
separately, first-launch conversion (optional 20 GiB source). Output is
one JSON and one markdown table keyed by both head SHAs.

* Fail the 4a harness launch fast on a non-e2e build and stop the app it launched

* Shim tsx's __name in 4a harness pages and install the probe inside the guarded launch

* Read the native chat working flag from the 4a harness's visible root itself

* Retry transient main-process evaluates in the 4a harness host-work probe

* Use the history page's itemId in the 4a harness and name what a visible-state wait timed out on

* Activate 4a harness chat tabs through their tab group and seed enough smoke filler chats for the unopened-chat row

* WIP: migrate native chat tests to SQL journal readers

* Treat refusals carried inside a successful 4a harness RPC result as refusals

* Give the 4a stub's user echo the uuid its transcript row records

* Remove retired journal writer test machinery

* Chain the 4a stub's resumed transcript to the last message, past a fork copy's title row

* Fork the 4a harness's large chat through its latest response, not its latest prompt

* Port persisted chat tests to SQL fixtures (red WIP)

* Add the 4a main-vs-candidate native chat comparison harness

One entry (native-chat-4a-comparison.ts) seeds the 55k-history/310-chat
profile once through the seed arm, clones it per arm at a fixed path,
launches each built checkout in the background with an isolated home,
and drives the same stub provider events through the host RPC surface
both builds serve. Envelopes come from each arm's own source bundle.
Rows cover send/queue, 1/8/16 MiB streams with a competing send,
maintenance windows, open/reopen, history/detail, outline/fork,
rewind, record operations, R3 retained-history admission and, reported
separately, first-launch conversion (optional 20 GiB source). Output is
one JSON and one markdown table keyed by both head SHAs.

* Fail the 4a harness launch fast on a non-e2e build and stop the app it launched

* Shim tsx's __name in 4a harness pages and install the probe inside the guarded launch

* Read the native chat working flag from the 4a harness's visible root itself

* Retry transient main-process evaluates in the 4a harness host-work probe

* Use the history page's itemId in the 4a harness and name what a visible-state wait timed out on

* Activate 4a harness chat tabs through their tab group and seed enough smoke filler chats for the unopened-chat row

* Treat refusals carried inside a successful 4a harness RPC result as refusals

* Give the 4a stub's user echo the uuid its transcript row records

* Chain the 4a stub's resumed transcript to the last message, past a fork copy's title row

* Fork the 4a harness's large chat through its latest response, not its latest prompt

* Port ACP tests to SQL journal named reads

* Port Claude tests to SQL journal named reads

* Port Codex tests to SQL journals and drop the legacy row rollback test

* Port failure and persisted-read fixtures to the active chat database

* Remove obsolete internal-work counting from chat inventory tests

* test(native-chat): repair SQL epoch fixtures and sender closure case

* fix(native-chat): own async option preparation and port SQL runtime fixtures

* test(native-chat): encode the full founding identity

* fix(native-chat): recover saved live work on SQL open

* fix(native-chat): select retained image sources before history paging

* fix(native-chat): preserve catch-up authority and scoped journal teardown

* Cover the 4a conversion, history-shape and maintenance-debt cases through outside observation

Conversion: seed a medium chat (310 chats on the full profile) and refuse a
cached seed from another recipe. Observe the candidate's existing
epoch-installed ready boundary with a read-only poll of journal_chat_state.
An idle seed copy yields launch to every chat ready and the per-size
ready-mark intervals; the families copy verifies an unconverted first open and
waits for every chat ready before any steady-state family.

History/detail: the stub emits ordinary Claude subagent frames (interleaved
and sparse-root corpora) and a shapes turn (huge completed tool originals, one
above the detail reply cap, an oversized ordinary message). Each named shape is
verified through the real history/detail route before its samples count; diff
items stay explicit missing evidence because the Claude adapter writes none.

Maintenance: write and rewind large completed rows on a disposable seeded chat
under a held outside reader, then measure other-chat sends during the hold,
after release and while freed pages are reclaimed, from read-only page/WAL
state. Retired-epoch pruning is skipped unless such rows are observed.

* fix(native-chat): preserve stopped result disclosure and async fixture ownership

* Resolve lost-session warning identity at the journal writer

* Cover the 4a conversion, history-shape and maintenance-debt cases through outside observation

Conversion: seed a medium chat (310 chats on the full profile) and refuse a
cached seed from another recipe. Observe the candidate's existing
epoch-installed ready boundary with a read-only poll of journal_chat_state.
An idle seed copy yields launch to every chat ready and the per-size
ready-mark intervals; the families copy verifies an unconverted first open and
waits for every chat ready before any steady-state family.

History/detail: the stub emits ordinary Claude subagent frames (interleaved
and sparse-root corpora) and a shapes turn (huge completed tool originals, one
above the detail reply cap, an oversized ordinary message). Each named shape is
verified through the real history/detail route before its samples count; diff
items stay explicit missing evidence because the Claude adapter writes none.

Maintenance: write and rewind large completed rows on a disposable seeded chat
under a held outside reader, then measure other-chat sends during the hold,
after release and while freed pages are reclaimed, from read-only page/WAL
state. Retired-epoch pruning is skipped unless such rows are observed.

* Remove the retired ACP warning-reader fixture field

* Validate warning writer authority before duplicate selection

* Wake queued delivery when pending requests change

* Validate authority before all resolved item selection

* Use current chat test fixtures and name the handover journal owner

* Keep warning authority validation on the semantic selection branch

* test: lose unsaved ACP creations before a successful resume

* refactor: tighten SQL journal types and publication reads

* test: use SQL chat writers and async journal observations

* Replace casts and empty type imports in the 4a harness scripts with annotations and guards

Renderer times and tab ids from waitForFunction handles go through typeof
guards, the visibility probe is a declared Window global, the runtime call
keeps its own typed response, and cached manifests, Electron paths, profiles
and families are narrowed by guards. The empty `import type {}` blocks name
AppStore and use it. Three casts remain, each with a line-specific SAFETY:
the generic RPC result and Node's performance inside main-process callbacks.

* refactor: type handover owners and finite recovery snapshots

* Name the 4a arm's bundled envelope builders by their tracked source files

The protocol bundle imported from './src/shared/agent-session/...', a folder
the path-literal ratchet reads as an unresolved import. Each module is now a
tracked-file constant joined onto the arm's own checkout, the same form
runtime-file-watcher-resource-probe.mjs uses; the bundle and its exports are
unchanged.

* Replace casts and empty type imports in the 4a harness scripts with annotations and guards

Renderer times and tab ids from waitForFunction handles go through typeof
guards, the visibility probe is a declared Window global, the runtime call
keeps its own typed response, and cached manifests, Electron paths, profiles
and families are narrowed by guards. The empty `import type {}` blocks name
AppStore and use it. Three casts remain, each with a line-specific SAFETY:
the generic RPC result and Node's performance inside main-process callbacks.

* Name the 4a arm's bundled envelope builders by their tracked source files

The protocol bundle imported from './src/shared/agent-session/...', a folder
the path-literal ratchet reads as an unresolved import. Each module is now a
tracked-file constant joined onto the arm's own checkout, the same form
runtime-file-watcher-resource-probe.mjs uses; the bundle and its exports are
unchanged.

* Port cross-version wire tests to SQL journal reads

Hosts take the shared domain database, reads go through named async
journal reads and catch-up history pages, and released-build fixtures
type the release's own synchronous journal API.

* Align cross-version downgrade tests with one-way conversion

A downgraded build sees the chat and records as converted and its
later writes are not carried forward. Drop tests whose subject was
this build's legacy row and outcome writes; seed newer legacy rows
before the first conversion.

* Port cross-version wire tests to SQL journal reads

Hosts take the shared domain database, reads go through named async
journal reads and catch-up history pages, and released-build fixtures
type the release's own synchronous journal API.

* Align cross-version downgrade tests with one-way conversion

A downgraded build sees the chat and records as converted and its
later writes are not carried forward. Drop tests whose subject was
this build's legacy row and outcome writes; seed newer legacy rows
before the first conversion.

* test: open runtime fixtures with SQL journal workers

* test: combine runtime fixture imports

* test: prune resolved compatibility timeout finding

* test: use bundled SQL workers for runtime admission fixtures

* test: await SQL reader delivery and complete real rewind cuts

* test: include the medium chat in comparison profile metadata

* test: cover snapshot holds after replacement rollback and read failure

* test: keep clear history assertions on saved and rendered results

* Inject the deletion scenarios' record removal at the SQL record store's reads

The SQL record store has no transact or record-deletion command, so the
authoritative-deletion cases make the store's public record reads answer as
for a missing record and restore them before teardown. Assertions unchanged.

* Align cross-version fixtures with async SQL publication

Wait for frames that follow committed reads, await the async
completion feed, route the outline and item calls to their current
host methods, and expect the restart unreconciled latch on loaded
records.

* test: delete automation records with their command receipts

* Seed completed diff originals through the baseline writer and measure them

The 4a stub speaks Claude stream-json, whose adapter writes no diff items, so
completed diff originals were a skipped row. The seed now appends known
diffs once into its last filler chat through the seed arm's own original
journal writer, after that arm stops and before the seed is renamed or
copied, so every arm starts from the same rows and item IDs. Both arms verify
kind, original length, a short page head and the exact patch from detail
before timing the tail page and the detail read, and the conversion sweep
reports the diff chat apart from the small chats.

* Pin each 4a arm to a full SHA and prove its build came from it

Each --arm now names name=<checkout>@<full sha>. The harness refuses an arm whose HEAD
differs, whose product sources are dirty, whose renderer build-commit stamp is not that
HEAD, or whose sources changed after the build, and records that provenance in every
result. A cached seed from another seed-arm commit is refused, and report-only refuses to
mix results from different pins, seeds or recipes. Tables name full SHAs and disclose that
writer BEGIN-to-COMMIT spans are not observed.

* Establish restart recovery debt in the record writer

* Add active-chat resident memory comparison to 4a harness

* Commit complete provider dispatches and preserve Stop sources

* Coalesce pending publications across provider dispatches

* Capture CI watch actions at SQL writer publication

* Restore Claude task linkage in SQL acquisition facts

* Lift restarted queue holds through SQL admission

* Forward brief clear through Claude close

* Isolate SQL test worker lifetimes and prove fork durability

* Preserve saved queue order and recover restart custody on SQL open

* Keep saved queue contracts explicit and type fixtures accurately

* Run startup chat workspace conversion through its SQL owner

* Make journal command classifications exhaustive and remove unchecked casts

* Temporarily reverse quality cleanup to isolate translation regression

* Restore verified behavior-neutral journal quality cleanup

* Initialize real saved snapshot routes in Claude translation tests

* Repair native chat campaign readiness and contention measurements

* Measure fork contention under isolated retired history pressure

* Verify contention still targets a live stream at dispatch

* Run chat maintenance within the record-store lifetime

* Bound chat activity reads to work transitions

* test: adopt saved snapshots in direct Claude sinks

* Cover maintenance activity during registered starts

* test: initialize saved facts for Claude permission and resume fixtures

* test: await durable Claude resume and chain publications

* Complete provider dispatch identities in maintenance fixtures

* Preserve journal body admission and text close finality

* Scope optional permission backfill failure to its record change

* test: seed SQL reader fixtures through their owning contract

* test: assert saved Codex outcomes through SQL readers

* test: seed replay-budget withdrawals through command turns

* fix: refuse chat access on newer journal schemas

* test: migrate Claude echo wait; fails on known product finding

The retained Working assertion still fails after awaiting initial publication and accepted echo. The product finding is handed to the author.

* test: await SQL transcript and command publications

* test: migrate public rewind cursors and teardown warning scopes

* test: await child-work and status re-entry publications

* test: bind operation fixtures to SQL current-work reads

* test: establish recovery fixtures through owner restart reconciliation

* Keep child work owned across null status publications

* test: await subscriber and late-proof SQL observations

* test: resolve the profile transfer fixture from the repository root

* test: assert restart recovery capsules instead of internal call counts

* test: migrate Claude echo wait; fails on known product finding

The retained Working assertion still fails after awaiting initial publication and accepted echo. The product finding is handed to the author.

* test: await runtime session publications and final writer acknowledgement

* test: migrate coordinator mail SQL APIs; known product failures remain

* test: persist fork sources and use SQL RPC fixture contracts

* test: observe conversation publications in worker abandonment

* test: admit downgrade fixture owners through the SQL store

* test: await ordered attention prompt relay observations

* Keep status observer failures outside provider ingress

* Order provider facts before late delivery receipts

* test: submit replay fixture turns through the general writer command

* test: await durable worker delivery and lifecycle outcomes

* test: follow current provider ownership in coordinator mail

* fix(chat): settle mail custody from writer outcomes

* fix(perf): format retired fixture row count explicitly

* fix(chat): admit automatic worker close from current work

* Require live tool contention witness at send dispatch

* Await attention fixture updates and prune the fixed echo wait baseline

* Preserve the Pi startup exit verdict after recording process identity

* Check restored image deletion through the transcript view

* Adapt history pressure fixture and probes to current item storage

* Repair CI import paths and asynchronous lint findings

* Keep journal storage and projections acyclic

* Preserve proven startup facts across acquisition settlement

* Wait for the owning chat boundary in recovery and delivery tests

* Observe admitted delivery work in native chat fixtures

* Make native chat comparison measurements fail closed

* Isolate SQL worker fixtures across test files

* fix(sqlite): avoid retaining large bindings in cached statements

* perf(native-chat): reuse the captured queue publication

* test(orchestration): await refused mail settlement before recovery

* fix(orchestration): reconcile owned mail before consuming checks

* fix(orchestration): preserve each mail check response

* test(orchestration): diagnose surviving timers through public SQL reads

* perf(native-chat): place item metadata before large forms

* test(native-chat): require the octet-length column flag

* fix(native-chat): version persisted item presentations

* fix(native-chat): bound queued-image history admission

* test(orchestration): update shared mail source support

* fix(native-chat): preserve Stop transitions and admitted forms

* perf(native-chat): select the existing latest-turn index

* perf(native-chat): reuse history admission facts

* perf(native-chat): reuse shortened history wire forms

* perf(native-chat): batch bounded fork metadata reads

* fix(native-chat): synchronize CI fixtures and type mailbox receipts

* perf(native-chat): bound fork scratch presentation work

* test(native-chat): await subscriber catch-up completion

* fix(native-chat): retire readers after fork setup failure

* perf(native-chat): batch bounded fork metadata and output reads

* Reuse validated journal publication inputs on demand

* fix(chat): cancel reader requests on requested shutdown

* perf(native-chat): reuse narrow SQLite work reads

Read canonical current work and queue eligibility in one snapshot, and reuse validated work through the existing journal observation entry. Preserve full status publication, live authority validation, optional queue failures and final writer claims.

Frozen700 matches the reviewed 27-file source manifest and measured tree 6423b1cfbb. Cold and changed-head reads meet the one-point budget; unchanged publication frames improve.

Disclose report698 strict-rule misses accepted by the coordinator as noise: the approximately 4us warm in-memory hit has paired p50 ratio 1.047; one writer-ack cell (empty / 2 subscribers / changed) is +5.5% at p50, 0.259 to 0.274 ms, while completion is approximately twice as fast.

* test(native-chat): synchronize Stop with interrupt entry

The request note is written before the separate dispatch read and native cancel call, so observing the note cannot prove cancelTurn has started. Await the mock interrupt entry, then inspect the request note while its response stays unanswered.

Remove eventual polling and verify the single status note before and after the response without asserting its wording. No production ordering change, sleep, retry or timeout increase.

* fix(native-chat): refresh invalid full work projections

Use the existing SQL authority and context validation before preserving a
full projection, so refreshed narrow work can be reused after row-free
invalidation. Preserve a valid full projection arriving during a narrow
read and extend the existing owner scenario for both transitions.

Correct the description in b98a2544bf: the report698 strict misses are
small measured overhead, not proven noise. Empty warm currentWork p50 is
3.542 to 3.709 us (+0.167 us, 60/80 pairs slower, ratio 1.04715, 95% CI
1.02291-1.07259). Empty/2-subscriber/changed writer ack p50 rises 5.5%,
0.259459 to 0.273833 ms, with its CI excluding parity, on an unchanged
writer path; completion falls 1.546834 to 0.657125 ms. The coordinator
accepts these marginal costs; the strict FAILs remain disclosed.

Frozen714 patch 6a4ded1ee72e8c0134a9a2121fb39bde618213e3f740b4888fd13c8900274620.
Owning 53 tests pass on both configured entries; static gates pass. Private
point attribution verifies repeated narrow reuse and all 92 serving/frame
outputs match. Focused714 against pre-P7 base still measures a small warm
currentWork median overhead; report716 preserves raw samples and CIs.

* fix(native-chat): retain full work projections with saved Stop

Reuse the existing work-answer validity lookup when a narrow read returns.
A full status projection includes the saved Stop, while narrow work leaves
that overlay unrequested. Comparing only the authority work actually read
preserves a valid arriving full projection and retires stale authority or
context without a second cache or comparator.

Extend the held-read owner scenario with a real saved Stop. Private point
attribution shows unchanged full demand going from one reader point to
zero, with full and work outputs equal; invalidation reuse remains one
read followed by three cache hits. Owning 53 tests pass on both entries and
static gates pass. Frozen721 is parent plus two W3 files only; paused SQL
diagnostics work is excluded. Historical P7 benchmark costs remain small
measured overhead as corrected in 12d479e640 and report716.

* refactor(native-chat): remove obsolete work-state read plumbing

Remove the test-only combined work/queue wrapper and its queue callback after the work-state RPC removal. Delete unused projection and queue-list wrappers, keep internal functions private, and point the hydration overlap assertion at surviving current-work and queue owners.

Retain the narrow SQL work path, work-only projection entry and invalidation/Stop reuse guards: subscriber frames, history/current requests and background-task publication still demand them. Combined work and queue eligibility plus resolved-work reuse remain in production.

Validation: 7 owning files, 26 cases on direct Node and configured Bun entry; full configured Node typecheck and static gates pass. Focused parent-versus-change micro preserves exact output equality and point shape across 36 live queue/frame cells and 80 pairs; no paired interval excludes parity. Removed RPC work-state measurements are historical only.

Prior P7 strict misses remain disclosed small measured overhead: warm current-work median 3.542 to 3.709 us (+0.167 us, ratio 1.047; 60/80 pairs slower), and empty / 2 subscribers / changed writer acknowledgment 0.259459 to 0.273833 ms (+5.5%, CI excludes 1) on an unchanged writer path; completion 1.546834 to 0.657125 ms. Neither cost is established as noise.

* test(native-chat): preserve released chat queue publication coverage

Use the surviving queue publication owner after rewind and reopen,
preserving visible card persistence checks across both providers and all
three release cohorts without a production wrapper used only by tests.

Validation: all 49 cross-version and owning files pass on Node and the
configured Bun entry (148 passed, 1 skipped each); the e2e typecheck
ratchet has zero test errors and the owning static gates pass.

* Register native chat SQL workers with the main-blocking ratchet

The journal SQL writer and reader entries run on worker threads. Their
dependencies are grandfathered in the SQLite baseline as worker-only, the
same way existing worker dependencies are; none run SQL on Electron main.
Prune baseline rows the branch no longer needs.

* test(orchestration): hold native admission in mail reconciliation busy chats

The file-local busyChat answered turn/start, so main's automatic mail
steering (#41476) handed each queued mail card to the accepted turn about
80 ms after send. Cases that wait for a visible card then timed out (or
found it gone), and teardown logged the closed SQL reader. Reuse the
custody fixture's busyChat and settleTurn, which keep admission
unanswered until the scenario settles the turn.

Bun: 4/7 failed before; 35/35 passed across 5 runs after. Node: passes
with the custody file (18/18).

* test(agent-session): wait for the at-rest opening snapshot on the open stream

Subscribers queue the opening snapshot behind an asynchronous SQL work
read, so agentSession.subscribe can reply before the snapshot frame; the
queued-image wire contract depends on that ordering. The at-rest case
read frames only up to the reply and lost the race under CI load.

With a 50 ms opening delay injected locally: old assertion 3/3 failed
(expected undefined), new assertion 3/3 passed.

* Correct subscribe comment: the opening snapshot follows the reply

* test(agent-session): assert no agent start after the at-rest opening snapshot

* test(agent-session): wait for the status summary's own publication in the child-records switch

The session-list summary publishes after an async journal projection read that
neither flushStreamedEvents nor the strip's batch covers, so asserting it right
after either raced the SQL worker.

* fix(explorer): resync a recovered remote watch only after the host watcher is installed

The contact-regained resync fired when the files.watch subscription was accepted, before the
restarted host reported its watcher ready, so a file created in that gap was neither in the
re-read listing nor reported by the watcher. The managed-orcad explorer recovery spec now waits
for that resync before writing its probe file.

* fix(explorer): re-read a recovered remote explorer once when its host watcher fails to install

* test(explorer): the recovered watch resyncs after its ready signal

* test(agent-session): await the queued-operation results instead of polling a settled flag

The operation-order cases polled a settled flag and the compact spy with
vi.waitFor's 1 s default. Under SQL worker contention the goal or rewind
answers after more than a second, so the poll gave up while the operation
was still on its way (CI: "expected false to be true", then "closed by
quit" from the unhandled result). Await the result itself and a promise the
compact stub resolves.

With a 30 ms SQL reply delay injected locally plus CPU load, 3 repeats: the
old file failed "releases a startup goal" (expected false to be true) and
"answers a goal" (compact called 0 times); the awaited version passed all.

* fix(agent-session): reserve queued sends before a waiting operation's own place

DeliveryOrder.reconcile became async when the first-queued read moved to the
SQL readers, but the ready-operation path still called it without awaiting
and reserved the operation's place right after. The operation then took its
place before the queued send it was meant to follow, so a goal, rewind or
other operation requested while the agent starts could run ahead of a
message sent earlier; a failed read also became an unhandled rejection.
Await it, restoring main's order (reconcile, then reserve).

Found by typescript/no-floating-promises over src/main/native-chat.

* test(agent-session): let delivery park before the attention case's idle sweep

The single idle-sweep tick keeps a chat whose delivery loop is still
running, and the loop parks only after SQL reads that follow the second
send's completion event. When the tick ran first it touched the session
instead of retiring it, and the 1 s hasSession poll failed. Wait for the
loop to park (wake resolves when it does), as goal-steering does.

With an 8 ms SQL reply delay injected locally plus CPU load: old 2/5
failed (expected true to be false), new 5/5 passed.

* test(agent-session): await the fake Codex child's requests in compact-exit

Restarting after a mid-command exit runs the exit settlement, a fresh
acquire and the queued send's handover through the SQL workers before
turn/start, which outran vi.waitFor's 1 s poll under load. The shared fake
Codex now resolves nextRequest(method) when a child receives that request;
compact-exit awaits it instead of polling the calls list.

Seen once in a contended local sweep (8 ms SQL reply delay plus CPU load):
"expected [] to have a length of 1" at the turn/start poll. The new
version passed 5/5 under the same delay.

* fix(agent-session): keep a settled send's frame over an older work restatement

Subscriber delivery reads current work before the history page, then lets
that work restate unanswered sends over the page's rows. When a send's
settlement committed between the two reads, the page carried it accepted
but the earlier work restated it pending, so the frame at the new cursor
published the stale state. Later caught-up frames restate only still
unanswered sends, so the client never learned of the acceptance: the
Claude echo case kept a "pending" bubble although the journal held it
accepted. A restatement only describes sends its read saw unanswered, so
an accepted or rejected page row is newer and now wins.

structured-agent-session-claude-echo-working (failed once in CI, never
reproduced) with an 8 ms SQL reply delay injected locally plus CPU load:
before, most repeats stayed pending for 15 s while the stored row was
accepted at the subscriber's own cursor; after, 7/7 passed in ~100 ms.

* fix(native-chat): record the original journal copy identity

* chore(native-chat): grandfather the writer worker's one-shot source receipt

The receipt is captured once inside domain initialization, which runs only in
the SQL writer worker, so its synchronous stat and SQLite write never run on
Electron main or the orcad loop.

* test(native-chat): await current-request reads instead of polling for one second

The child-request case waited 1 s for the SQL reader's current-request
answer and failed on a loaded CI shard. Wake on each real state change
from the subscription and the request reader instead.

* fix(native-chat): re-answer current work when a catch-up page passes its cursor

A subscriber catch-up answered current work at one journal cursor, then read
the history page in a later reader transaction. The restated copy of a send
still pending at the work cursor replaced the page's accepted row, so the
renderer kept showing the send as sending.

Re-answer work when the page cursor has passed the work answer, refresh the
fan-out's shared work answer once the journal adopts a newer commit, and keep
the page's own rows when the page holds a commit not yet adopted.

* fix(native-chat): read subscriber page rows and current work in one reader snapshot

The catch-up overlaid a work answer from one journal cursor on a history page
read at another. Re-answering work afterwards still left a page that ran ahead
of the adopted cursor without its work, so a send shown as unknown could
revert to pending under an unchanged work fingerprint.

The history read now answers current work in its own transaction. The main
thread validates that answer against live owners and handover with the
existing currentness check, and reads the frame again until it has adopted
the frame's cursor. A cached answer is reused only when the page head is that
same cursor. The fan-out's queue now follows the work answer it was read
with.

* fix(native-chat): capture each subscriber frame at one held command-lane position

A subscriber frame paired rows, current work and the queue from different
positions, and waiting for the main thread to adopt a newer head re-read the
page until it did.

Each frame now captures its page and work (one reader transaction) and its
queue inside a single readInOrder on the chat's command lane, then releases
the lane before emitting. The queue reaches the frame through the explicit
queuePublication option, so emission never reads a newer one. A capture
whose live authority changed mid-read is discarded without advancing the
subscriber; the change's own publication delivers its replacement. Inactive
subscribers, closed journals and replaced session handles abandon the frame.
The resume path no longer decorates stop notes with work read before catch-up;
they restate the work of the frame the subscriber caught up to.

* fix(native-chat): validate whole captured frames and capture every work overlay

The queue gate inside a frame capture re-read work until it matched live
authority, holding the command lane, and the capture stopped validating
before its queue read. Stop-note pages, history replies, attach hydration
and queued-image decoration still paired rows and work from different
positions.

The queue gate now reads once at the frame's own authority, and outside a
capture once at the live one; a moved authority abandons the frame for the
change's own redelivery. The capture re-validates authority, handle and
cursor after its queue read. Stop-note pages are read on the lane only
while the journal is still at the delivered frame, otherwise the resume
catches up first. History replies and attach hydration use the same held
capture, and image decoration that finds the journal past its frame is
abandoned in favour of the newer commit's delivery. With every overlay
coherent, a settled page row can no longer meet an older restatement, so
the settled-send guard is removed.

* fix(native-chat): owe restatements after an emitted replacement and refuse exhausted captures as unavailable history

* test(native-chat): follow captured history frames in cross-version and queued-image wire tests

* Remove the converted legacy chat journal after its grace period (#42024)

* fix(native-chat): retire certified legacy journals after the grace period

* perf(native-chat): pace source proof through existing maintenance

* test(native-chat): exercise retirement with the native source lock

* fix(native-chat): account for queued card epochs during source proof

* fix(native-chat): settle retained journals and cancel stalled source leases

* fix(native-chat): keep the prepared retirement state narrowed

* fix(native-chat): apply retirement backoff before writer admission

* fix(native-chat): retry restored legacy retirement eligibility

* fix(native-chat): retain pending legacy eligibility helpers

* chore(native-chat): grandfather the writer worker's one-shot source receipt

The receipt is captured once inside domain initialization, which runs only in
the SQL writer worker, so its synchronous stat and SQLite write never run on
Electron main or the orcad loop.

* fix(native-chat): make retirement filesystem checks asynchronous

The four maintenance SQLite uses run only in the SQL writer worker and the 28 proof-page SQLite uses run only in the SQL reader worker; main-side proof coordination dispatches worker requests.

* fix(native-chat): build lock helper at the server glibc floor

Build Linux server helpers with the existing pinned glibc 2.28 slot images when the host is newer. Keep native floor and musl builds, and select the separate desktop toolchain explicitly. This prevents fast Ubuntu prebuilds from linking GLIBC_2.33/2.34 into a 2.28 payload.

Bound the helper PR workflow to 20 minutes and cover compiler selection without compiling native code locally.

* fix(native-chat): honor read-only retirement ownership

Do not acquire a writable retirement lifecycle for a newer-schema database, so shutdown never sends its read-only writer a retirement-credit command. Keep the existing preservation and empty-diagnostics regression unchanged.

Select the native exclusion test with the dedicated workflow flag instead of generic CI, and merge duplicate database imports in the retirement test.

* fix(native-chat): remove source proof table assertion

Annotate the content table inventory as readonly strings so membership checks accept schema table names without a type assertion.

* fix(native-chat): bound legacy retirement proof work

Persist source-intrinsic refusals for the exact copy, source and destination descriptor. Resume completed proof work after transient failures, and let the existing conversion owner finish pending imports.

Use covering-index key pages for history membership and exit terminal retirement states before writer admission. Preserve originals and prepared unlink manifests.

* fix(native-chat): recover legacy proof without repeating source work

Use the fixed profile-copy columns for source certification and keep damaged destination inventory retryable. Advance the shared refusal policy so earlier false inventory results are re-proved.

Complete verified empty heads after transient conversion failure, and carry proven original-source diagnoses through SQL errors without changing their ordinary identity. Persist only source-intrinsic refusals.

Validate in-place schema recovery, bounded empty completion, and malformed/newer histories at 128/1280 rows with zero retirement proof, conversion, restore or helper work across subsequent owners. Focused tests, tc:node, scoped checks and all 27 ratchets pass.

* test(native-chat): trace cursor resume frames on failure

Capture synthetic subscriber frame payloads and emission stacks when the existing restart assertion fails in CI. Keep the two-frame expectation and production behavior unchanged.

* test(native-chat): allow held-cursor roster frames on resume

A restarted host can publish an empty task and command roster before catch-up when its initial coherent capture is superseded. Validate that optional metadata frame, preserve the two history/work frames and no-replay checks, and await the work restatement instead of polling packet counts.

Remove temporary per-frame stack tracing now that CI identified the publisher. Production wire behavior is unchanged.

* test(native-chat): assert empty resume batches independently

Use literal empty arrays in the resume contract so a defect in the host's batch constructor cannot also change the expected value. Keep the optional held-cursor roster prefix and the two required catch-up/work frames.

* test(native-chat): expect the current conversation fence on resume

The roster publisher reads the conversation fence after restart and send, which can advance beyond the earlier runtime lease fence. Derive the expected fence from that current record and preserve every other resume assertion.

* test(native-chat): hold the domain database lock while a revoked history step is dispatched

* test(native-chat): accept held-cursor state frames before a resumed catch-up and fold them in a released client

* Start the chat journal writer earlier and defer maintenance until serving (#42045)

* Boot the chat journal writer during startup waits

Start the existing record-store slot after login env and before the daemon
wait in orcad, and right after runtime construction on Electron, through one
shared location builder that probes for saved chats once. Startup restoration
consumes that same attempt, so a refused journal is not reopened before RPC.
orcad's push-service start moves to its own module to keep the entry small.

* Start journal maintenance after startup restoration

The CPU profile showed the background sweep's reader spawn and writer
work competing with pre-RPC startup for the disk and CPU. A startup
open now holds maintenance until its restoration settles; other openers
start it on open as before. Reads still convert saved chats on demand.

* Move the headless-serve browser check to its own module

Behavior-neutral; keeps main-process-runtime-launch.ts within the line limit.

* Collect saved chat ids once and start journal maintenance after serving

orcad passes the ids it collected for the early open into runtime
construction instead of collecting them again. Background journal
maintenance now waits for the host's serving milestone (orcad readiness
published, Electron serve ready, desktop RPC start) rather than
restoration settling, so a stalled renderer cannot hold it. The desktop
early open starts after the first-window services fence. The refusal
test now observes that the journal is opened once.

* Keep the deferred desktop chat open inside shutdown, and start CI-line watches after serving

A first-window fence that settles after quit or a failed startup has
committed no longer opens the chat journal past its teardown; the
Electron startup-failure path now commits host shutdown as orcad's does.
Host installation re-arms CI-line watches only after a teardown stopped
them, so the first run starts at each host's serving milestone (orcad
after readiness, Electron after startup settles) instead of during
restoration.

* Admit CI-line watches at each host's serving milestone and let installs retry them

The first watch start no longer depends on renderer load: orcad admits it
after readiness, Electron serve after the serve-ready line, desktop once
the window and RPC start settle. Before admission, chat installation
leaves watches to that milestone; after it, installation's idempotent
start covers a failed first start as well as a teardown. Starts are
skipped once host shutdown has committed.

* Fence desktop watch admission, make warmup retry-only, and release failed watch starts

Desktop admits CI-line watches after the bounded first-window fence, so
automatic journal work never precedes it. The startup warmup timer only
retries a failed start; admission stays with each host's serving
milestone. A watch service whose start rejects after registering its
outcome observer and job hooks is stopped before a retry replaces it.

* Retry a failed CI-line watch start on the journal's maintenance pass

After admission, a saved-chat host whose first watch start failed had no
automatic retry. The journal's existing periodic maintenance pass now
calls the idempotent start when watches are admitted but neither running
nor starting; it does nothing after committed shutdown or while a service
runs. No new timer or loop, and nothing moves before readiness.

* Wire PR-watch recovery into every record-store opener

The chat host's install could open the once-slot first, without the
maintenance-tick hook, leaving a failed first watch start with no automatic
retry. The hook is now a required location field, set through one shared
builder by every production opener.

* Keep runtime identity state within the file-length limit

The saved-chat startup open's import now uses one namespace line, so the
file stays at the 300-line cap after the early-open field and method.

* Load the real chat host once before the PR-watch tests

The host-install-first regression loaded the real chat host module inside
the test, which CI's in-test vi.importActual gate refuses. It now loads in
beforeAll; the test body and its assertions are unchanged.

* Mark the desktop serving test's runtime stand-in as a reasoned cast

CI's changed-code gate requires the lint suppression form for a test cast;
the stand-in and its SAFETY reason are unchanged.

* Share journal database open options so the file stays within its line limit

* test(chat): restore released-client resume projection coverage

* test(chat): type the released-client fold accumulator

* test: fail the first opening subscription data frame

* test: update benchmark module paths after main sync

* test: resolve benchmark modules within each checkout

* test(native-chat): inject late receipts without a history read
2026-11-14 05:51:16 -08:00
OrcaWinandOrcaWin 856c91bba2 test: remove low-value native, extension, and editor suites (#42333)
* test: remove native policy and wrapper test suites

* test: remove low-value extension and editor fixture suites

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-14 01:01:36 -08:00
OrcaWinandOrcaWin 120e55a818 test: remove low-value removal and lifecycle examples (#42329)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-14 00:18:39 -08:00
OrcaWinandOrcaWin a92db9d4d0 test: remove low-value native, cache, and trust examples (#42321)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-13 23:55:09 -08:00
Jinwoo Hong aaa61af50a fix(computer): report a locked screen instead of missing Accessibility (#42277)
* fix(computer): report a locked screen instead of missing Accessibility

Behind the lock screen (display sleep, screen saver or a manual lock) macOS reports Accessibility as untrusted. Orca read that as a missing permission, and its recovery hint led agents to open System Settings. Check the session lock first and return screen_locked; permission setup refuses while locked.

* fix(computer): recheck the lock under the provider lock and at setup launch

* fix(computer): read the lock fresh for setup and keep locked status reads out of the cache

* refactor(computer): drop the extra lock read at setup; the status and setup helper already check it
2026-11-14 02:43:37 -05:00
OrcaWinandOrcaWin d06458173d test: remove low-value relay, workspace and UI suites (#42288)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-13 20:59:03 -08:00
OrcaWinandOrcaWin 8ee811174f test: remove mock-only suites and native text-entry harness (#42283)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-13 20:45:01 -08:00
Kelvin Amoaba 4d005cf8b8 fix(computer): read wait --enabled state from the host, not label text (#42260) 2026-11-14 03:18:36 +00:00
Kelvin Amoaba a406364654 fix(computer): click, set and scroll Windows buttons, text boxes, combo boxes and lists without bringing the window forward (#42237)
* fix(computer): press, set and scroll Windows native controls without activating the window

Measured on Windows CI: UI Automation's Invoke, Toggle, ValuePattern and
ScrollPattern focus a background WinForms control first, which activates its
window. Native controls now go through their own messages instead, each
owner-checked: BM_CLICK for buttons, check boxes and radio buttons, select-all
plus EM_REPLACESEL for set-value on edits, CB_SETCURSEL with CBN_SELCHANGE for
combo boxes (exact-text match, read back after the app's handler runs) and
LB_SETTOPINDEX for list box pages.

* fix(computer): refuse read-only Windows documents before typing keys, document the caret fallback

* fix(computer): keep Windows native routes to measured controls and refuse partial writes

BM_CLICK only for WinForms buttons, multi-column lists stay on ScrollPattern, a
list already at its end reports success, edits refuse text past their limit,
the combo's owner is checked right before the selection, a cleared selection
reads as a mismatch and a disabled control is element_not_enabled.

* fix(computer): hold Windows edit limits without a readback, require a complete combo search

* fix(computer): read a long Windows edit's length from the field for its limit check

* test(computer): share the Windows fixture action helpers
2026-11-14 02:45:10 +00:00
Kelvin Amoaba f49eb51f95 feat(computer): launch-app starts desktop apps without taking the foreground (#42197)
* feat(computer): add launch-app to start apps without taking the foreground

* fix(computer): leave running apps alone and keep the launch env clean

* fix(computer): recheck aliases, keep focused launches visible, refine launch hints

* chore(computer): document the launch result casts

* test(computer): check launch-app reports where the app ended up on Windows CI

* docs(computer): point app_not_found at launch-app

* test(computer): format the merged Windows background e2e

* fix(computer): match launch paths to the running file and word background launch as an attempt
2026-11-14 02:11:33 +00:00
Kelvin Amoaba e2fb873c0a fix(computer): type into Windows text boxes without bringing the window forward (#42165)
* fix(computer): type into Windows text fields without raising the window

Adds type-text --element-index on Windows through EM_REPLACESEL for user32,
RichEdit and WinForms edits (owner-checked, read back with WM_GETTEXT), or a
ValuePattern write merged with the TextPattern selection. Keyboard verbs on a
background window now refuse with background_unavailable before sending
anything and point at type-text --element-index. Foreground typing uses one
SendInput KEYEVENTF_UNICODE batch instead of WM_CHAR posted to the top-level
window, and get-app-state shows multiline edit text again.

* fix(computer): refuse typing into Windows list items, keep the caret on a confirmed prefix
2026-11-14 01:28:30 +00:00
Kelvin Amoaba 62b22aeab0 fix(computer-use): read minimized, hidden and other-Space macOS windows without --restore-window (#42182)
* fix(computer-use): observe minimized, hidden and other-Space windows on macOS without a restore

macOS only enumerated on-screen windows and dropped minimized AX windows,
so an app whose window was minimized, hidden or on another Space (any
full-screen app) could not be observed, and agents fell back to
--restore-window, which activated every window of the app and switched
the user's Space.

Enumerate every window, keep the off-screen ones accessibility can still
read (other-Space windows by remote token, closed windows dropped by
their Space membership), and report their real minimized and off-screen
state. Background pointer and key input on such a window refuses before
sending anything. --restore-window now raises only the target window,
once per request, and delivery is measured from whether the target
became frontmost.

* fix(computer-use): pin the restored window and prefer visible windows by default

* fix(computer-use): keep window-index cache keys and stale-element checks across a restore

* fix(computer-use): restore only this app's resolved window and refuse a closed target before raising

* docs(computer-use): say macOS reads minimized, hidden and other-Space windows
2026-11-14 00:58:33 +00:00
Kelvin Amoaba cc1e3740da feat(computer-use): scroll and select list rows in background Linux windows, and aim GTK 4 clicks (#42201)
* feat(computer-use): scroll and select rows in background Linux windows, and aim GTK 4 pointer input

Scroll moves the nearest scroll bar's value by whole viewports, handing
the scroll outward at a view's end, or pages a web document with
Component.ScrollTo, before falling back to the pointer. A click on a
list row with no action selects it through the list's Selection when
the index is proven to name that row. GTK 4 rectangles come from
WINDOW extents plus the X11 client origin, since its SCREEN extents
read [0, 0, w, h].

* fix(computer-use): keep Linux background scroll and select honest under partial and slow results

Wait for ScrollTo to move before planning the next page, report pages
already scrolled instead of falling back, let refused scroll bars fall
through, clear a multi-select list before a plain-click select, accept
only an InvalidArgs refusal as index proof, bound child walks, and
read GTK 4 origins lazily.

* fix(computer-use): scroll the innermost Linux view that overflows, and bound the scroll search

ScrollTo now runs on each ancestor that overflows its own box, innermost
first, so an inner scroller moves before the page; coordinate scrolls
start from the deepest node under the point. Cap the scroll bar search
to small containers, report a document at its end as a no-op, keep
looking past an unusable spanning child, and look up GTK 4 window names
once per operation.
2026-11-14 00:31:34 +00:00
Kelvin Amoaba 513aef5e7d fix(computer): ask the user before retrying with --restore-window (#42181)
* fix(computer): ask the user before retrying with --restore-window

Error hints, recovery steps, the skill guide and the CLI follow-up command
told agents to retry with --restore-window on their own, which raises the
target app and takes the user's screen. They now say to ask the user first,
stop recommending a restore just to observe, and fix stale per-platform
background claims.

* docs(computer): name the Linux keyboard gate and the Wayland limit
2026-11-13 23:50:03 +00:00
Kelvin Amoaba 1f56231043 fix(computer-use): keep Linux actions in the background and refuse ones that need the foreground (#42157)
* fix(computer-use): keep Linux actions in the background unless the user allows a raise

Pointer fallbacks, scroll and drag no longer raise the target window and
warp the pointer without --restore-window; they refuse with
background_unavailable before sending anything. With the flag, the
target point is validated before the raise, a window on another
workspace is refused instead of switching the user's view, and the
pointer is put back afterwards.

Also refuse background clicks that open menus, keyboard-grabbing popups
or dialogs (ported from agent-desktop's foreground classifier), refuse
synthetic input on Wayland where it never lands, press Return through a
GTK entry's activate action, re-check focus and held modifiers while
typing, and report action.delivery from what happened.

* fix(computer-use): check the workspace before every Linux raise and release held buttons

Run the other-workspace check before GrabFocus too, raise before a
user-approved menu or dialog opener, validate a pointer target before
asking for the flag, count newly active app windows as foreground,
release synthetic buttons when input is interrupted, and stop typing
without an exception exit so the user's held keys are left alone.

* fix(computer-use): keep held modifiers from other X screens and settle remapped keys on early stop

* fix(computer-use): refuse a Linux raise when the target's workspace can't be read
2026-11-13 23:23:34 +00:00
Kelvin Amoaba 57c9991c98 fix(computer-use): refuse macOS background clicks that open a menu or dialog, and stop refusing plain AX presses (#42158)
* fix(computer-use): refuse macOS background actions that open a menu or dialog over the user

* fix(computer-use): let web comboboxes click in the background and stop probing a hung app

* fix(computer-use): refuse background drags that start on a menu owner

* docs(computer-use): note background drags on menu owners are refused

* fix(computer-use): classify the element under a drag's start and check AXConfirm/AXOpen secondary actions
2026-11-13 22:50:27 +00:00
Kelvin Amoaba 10302c46a8 fix(computer-use): stop Windows clicks, scrolls and drags from taking the screen without --restore-window (#42161)
* fix(computer-use): refuse Windows pointer fallbacks without --restore-window

Coordinate, right, middle, modified and multi-clicks, clicks on elements with no
primary pattern, unscrollable wheel scrolls and drags raised the window and
moved the real cursor without being asked. They now refuse with
background_unavailable before anything is sent. Coordinate and fractional
scrolls go through ScrollPattern first. With --restore-window only the target
window is raised (never a cloaked one), with a UIA activation fallback and a
second attempt, points are validated first and the cursor is put back behind
the input. A failing UIA pattern or disabled element is an error instead of a
real click, and delivery is measured after the post-action observe.

* fix(computer-use): settle Windows clicks before restoring the cursor and keep scroll writes honest

* fix(computer-use): restore the Windows cursor with SetCursorPos and hit-test coordinate scrolls

* test(computer-use): assert Windows raise outcomes, not attempt order

* fix(computer-use): report a Windows page scroll the provider ignores as not scrolled
2026-11-13 22:44:25 +00:00
OrcaWinandOrcaWin a36d1ddafd test: remove low-value bridge and native checks (#42105)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-13 11:15:10 -08:00
OrcaWinandOrcaWin c6b9ac9549 test: remove duplicate native policy checks (#42011)
* test: remove duplicate native policy checks

* test: trim repeated clipboard reads

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-13 04:43:35 -08:00
OrcaWinandOrcaWin 2f9b122201 test: remove native smoke and duplicate input checks (#42007)
* test: remove repeated focused Linux text insertion

* test: remove repeated foreground TextEdit replacement

* test: remove Notepad smoke and duplicate paste coverage

* test: drop repeated numeric row and scroll-work counters

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-13 04:23:13 -08:00
Kelvin Amoaba c5657bd5a7 feat(computer): type into a named text field without focusing it on Linux and macOS (#41421)
* feat(computer): type into a named text field without focusing it on Linux and macOS

* fix(computer): report unconfirmed Linux text readback and cover element typing

* test(computer): send an element with benchmark text only for targeted typing

* test(computer): pick gedit's editor, not its hidden overview map, in Linux e2e

* docs(computer): confirm focus before the unindexed type-text fallback

* fix(computer): report unreadable element text readback as readback_unsupported
2026-11-13 00:28:06 +00:00
Kelvin Amoaba c794f75e4e fix(computer-use): use UI Automation for Windows scroll, expand and slider actions (#41429)
* fix(computer-use): scroll, expand and set sliders on Windows without raising the window

* fix(computer-use): wait for Windows scroll and slider writes to settle before verifying

* fix(computer-use): reject NaN for Windows slider set-value

* test(computer-use): wait on the Windows fixture state with vi.waitFor and a schema

* test(computer-use): check activation per action against a holder window in the Windows fixture

* test(computer-use): log fixture window events for activation failures

* fix(computer-use): report foreground when a Windows app raises itself for a UI Automation action

WPF activates its own window for Scroll, ExpandCollapse, RangeValue and SelectionItem calls from any UIA client, so the runtime now compares the foreground window before and after a pattern action instead of assuming background. The Windows e2e checks delivery against the fixture's own activation count, with a holder window in another process.

* test(computer-use): skip an unstarted holder when closing the Windows fixture

* fix(computer-use): bound Windows pattern scroll paging and tighten slider read-back

* fix(computer-use): cap Windows slider read-back tolerance and run the UIA e2e only on CI
2026-11-12 23:17:10 +00:00
Kelvin Amoaba 792d4e8028 fix(computer): verify macOS type-text and paste-text by reading the field back (#41402)
* fix(computer): verify macOS type-text and paste-text sent as keys by reading the field back

When text can't be written through AXValue (Chromium/Electron fields, fields
that refuse the write), type-text and paste-text send keys or Cmd+V and always
reported unverified. Now the helper predicts the focused field's value from its
value and selection before sending, then reads it back until it settles:
verified on a match, unverified (text_mismatch) otherwise. Secure fields and
fields without a readable value and selection stay unverified as before, and
the result never repeats the typed text or the field's contents.

* fix(computer): keep the caret put after a refused macOS text write and skip unprovable readbacks

A refused AX value write no longer moves the caret before falling back to keys, so the keys and the prediction both use the user's selection. Text with control characters, a value the field already holds, and a field still filling at the 2 s cap stay unverified rather than verified or text_mismatch. The quiet window starts after the first read answers.

* fix(computer): bound macOS text readback size and say a mismatch can mean keys went elsewhere

* fix(computer): treat a macOS text readback past the cap as undetermined
2026-11-12 22:45:11 +00:00
Kelvin Amoaba 8ed0d047db feat(computer): show where snapshots were cut and read one element's subtree (#41482)
* feat(computer): show where snapshots were cut and read one element's subtree

* fix(computer): validate subtree targets against the fresh walk and keep scope for focused input

* fix(computer): return whole-window action results after subtree reads

* fix(computer): count kept records toward the macOS limit and index subtree reads against the latest cache

* fix(computer): index Linux/Windows subtree reads against the snapshot they started from
2026-11-12 22:22:18 +00:00
Kelvin Amoaba cd933ae08e feat(computer-use): add orca computer wait for text, enabled controls and window titles (#41433)
* feat(computer-use): add orca computer wait for text, enabled controls and window titles

* fix(computer-use): bound wait reads by the deadline and wait out missing Linux/Windows windows

* fix(computer-use): read disabled traits after role text with parentheses and bound the capability probe
2026-11-12 21:35:26 +00:00
Kelvin Amoaba 3cfdd60d3b fix(computer): check macOS click targets are enabled, in view and uncovered before clicking (#41519)
* fix(computer): check macOS click targets are enabled, in view and on top before sending input

* fix(computer): scope macOS click cover checks to the target window

* fix(computer): scroll before trusting container hits and stop hit walks at the shared container

* refactor(computer): share the one-scroll rule in the macOS click check
2026-11-12 21:23:42 +00:00
Kelvin Amoaba 11d9c11967 fix(computer-use): screenshot KDE Wayland windows through the desktop portal (#41564)
* fix(computer-use): capture KDE Wayland windows through the desktop portal

KWin is the only process on KDE Wayland that knows where a window is and
what covers it, so a one-shot KWin script reports window geometry and
stacking. Orca crops the xdg-desktop-portal screenshot to that window and
returns a screenshot error when the window is hidden, covered, or moves
during capture, or when the portal prompt is unanswered or denied.

* fix(computer-use): refuse KDE screenshots during Show Desktop or off every screen

* fix(computer-use): clean up oversized portal files and skip shaded KDE windows
2026-11-12 20:41:25 +00:00
Kelvin Amoaba 97fc86f0a0 fix(computer): select macOS list and table rows that a click leaves unselected (#41469)
* fix(computer): select list and table rows when a macOS click leaves them unselected

A plain click on an AXRow/AXCell answered success (AXPress) or unverified synthetic input while nothing got selected: AppKit rows have no AXPress, and background pointer input does not select them. After the click, read the selection back; if the row is still unselected, write it through the owning table/outline/list (AXSelectedCells/AXSelectedRows/AXSelectedChildren), falling back to the row's own AXSelected, and report verified only when the selection reads back on.

* fix(computer): find a cell's row through wrapper groups
2026-11-12 20:41:10 +00:00
Kelvin Amoaba 41c8b81372 fix(computer): capture covered Windows windows, refuse elevated targets, time-box hung windows (#41468) 2026-11-12 20:40:24 +00:00
OrcaWinandOrcaWin 270608e946 test: remove low-value runtime and native clipboard cases (#41539)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-12 04:59:45 -08:00
Kelvin Amoaba 02f5c8a88b fix(computer): move the macOS caret only after the text write lands (#41541)
When a field accepted the AX value write but kept its old value, the
helper had already moved the caret, so the fallback keys or Cmd+V went
in at the wrong place.
2026-11-12 12:55:02 +00:00
Kelvin Amoaba fa47b1a434 fix(computer): stop action results repeating the value or text an agent wrote (#41479)
* fix(computer): stop echoing written text and secure read-backs in action results

* fix(computer): treat a truncated set-value read-back as unverifiable

* fix(computer): accept code-point truncated read-backs as unverifiable
2026-11-12 09:25:49 +00:00
OrcaWinandOrcaWin affd908567 test: remove narrow parser, policy, and native projection tests (#41407)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-11 22:30:38 -08:00
lucumaandKelvin Amoaba 2c7a82cb09 fix(computer-use): capture Wayland windows with grim (#40422)
* fix(computer-use): capture Wayland windows with grim

* fix(computer-use): skip Wayland captures of windows that are not on screen

Sway and Hyprland report windows on other workspaces at coordinates that grim
would fill with whatever is visible there. Require the one matching window to be
visible, name why a capture was skipped, check for a supported compositor before
asking for grim, and load GdkPixbuf without needing Gdk.

* fix(computer-use): keep Wayland screenshots aligned with accessibility frames

Skip the capture when the compositor window size differs from the AT-SPI window
bounds, since element frames are measured against those bounds. Treat a running
Sway or Hyprland as Wayland even when XDG_SESSION_TYPE is tty.

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-12 05:16:41 +00:00
OrcaWinandOrcaWin bbe22681c2 test: remove notification, icon and native policy inventories (#41375)
* test: remove notification and native policy inventories

* test: remove icon projection samples and tray suite

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-11 20:54:07 -08:00
Kelvin Amoaba 134a7be89a fix(computer): stop macOS type-text and paste-text entering text twice (#41339)
* fix(computer): stop macOS type-text and paste-text entering text twice

Chromium answers an AX value read from a cache that trails a successful
write by about 100 ms. type-text and paste-text read the field once right
after writing, saw the old value, and typed or pasted the same text again
as keys. set-value read back the same stale value and reported that a
landed write did not take effect.

Both now wait up to 500 ms for the readback to settle, and text input
falls back to keys only when the field still holds its old value. Text
input into Chromium web content skips the AX write and sends real keys,
because the write fires no beforeinput/input events (none at all for a
contenteditable), so editors such as Discord's search never saw the text.

* fix(computer): bound the macOS value readback wait by wall clock

* docs(computer): say why text readback polls for async AX trees
2026-11-12 03:11:53 +00:00
Neil a82468b023 chore(deps): safely update vetted dependencies across workspaces (#41291)
* chore(deps): safely update vetted dependencies across workspaces

* fix(deps): deduplicate rolldown to 1.2.16 for electron-vite tsc parity
2026-11-11 17:58:44 -08:00
OrcaWinandOrcaWin b9d91d7fa4 test: remove low-value renderer launch and Windows checks (#41305)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-11 17:22:41 -08:00
OrcaWinandOrcaWin ce08e6b25e test: remove low-value CLI, mobile, and clipboard cases (#41273)
* test: remove low-value CLI, mobile, and clipboard cases

* test: trim unused keyboard synthesis fakes

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-11 15:16:34 -08:00
OrcaWinandOrcaWin b1106ba883 test: remove low-value suites, recorder snapshots, and repeated inputs (#41244)
* test: remove weak recorder scenarios and arithmetic suites

* test: remove low-value boundary suites and recorder cases

* test: remove mock suites and trim repetitive boundary inputs

* test: remove shallow provider and browser checks

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-11 14:14:48 -08:00
Neil 65d30b156a fix(computer-use): only SW_RESTORE minimized windows on Windows (#41253) 2026-11-11 13:45:40 -08:00
OrcaWinandOrcaWin 9576e55773 test: remove 1,144 low-value declarations (#41177)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-11 09:11:06 -08:00
108226bfe3 feat: combine localization and status-bar formatting (#40456)
* feat(appearance): let app chrome follow the terminal theme

Add an "App Chrome Appearance" setting (Default / Match Terminal) next to
Left Sidebar Appearance. In match-terminal mode the terminal theme's
background/foreground are written as document-root CSS variables
(--bg-titlebar, --background/--card/--popover/..., both sidebar token
families), so the tab strip, status bar, side panels, full-page views and
popovers all follow the terminal instead of the app theme. Left-sidebar
modes still win because they scope their own variables below the root.

The terminal color pair and token derivation move into
terminal-surface-colors.ts and are shared with the sidebar resolver.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(status-bar): configurable usage format template

Add Settings → Appearance → Status Bar → "Usage format": a template that
replaces the built-in per-provider usage text when non-empty. Placeholders
cover {provider}, {plan}, the 5h/7d/fable/30d windows as percentages
(following Used/Remaining), {x.reset} countdowns, {x.resetAt} clock times
and Gemini {buckets}; "[...]" groups drop out when a placeholder inside is
empty so one template works across providers with different windows.
Whitespace is rendered as authored (whitespace-pre).

Persisted as PersistedUIState.statusBarUsageFormat with a byProvider
override map reserved for later; the RPC UI-update schema gains the
optional field.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(appearance): document touched functions; surface usage format in search

Add one-line JSDoc to every function this branch adds or edits so the
review docstring gate passes. Include the usage-format entry in the
Status Bar section's search match so searching "template" or
"placeholder" no longer hides the parent row, and mention popovers in
the App Chrome Appearance descriptions since the setting styles them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(appearance): let file editors follow the terminal theme in match-terminal mode

With App Chrome Appearance = Match Terminal, the tab strip, status bar and
side panels took the terminal palette but every file pane kept the stock app
theme: Monaco (code, plain text, diffs, notebooks, markdown source) was
hard-wired to `vs`/`vs-dark`, and the markdown preview / rich editor painted
the fixed `--editor-surface` with GitHub-colored hljs tokens.

- `terminal-editor-palette.ts` derives an editor palette from the active
  terminal theme (background/foreground/cursor/selection + syntax roles mapped
  onto the ANSI slots) and builds a Monaco theme (`orca-terminal`) from it;
  light/dark is rated by the terminal background, so a light terminal theme
  under a dark OS setting still gets light styling.
- match-terminal chrome variables now include `--editor-surface` and
  `--syntax-*`; the hljs stylesheets read those ahead of their defaults.
- `useEditorSurfaceAppearance` / `useMonacoEditorTheme` replace the inline
  `isDark ? 'vs-dark' : 'vs'` computations; the diff-section chain passes the
  Monaco theme name instead of a dark flag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99
(cherry picked from commit dc85fadee0a2664adbf55a49dd3c97c9b10fc111)

* fix(status-bar): honor the usage template in compact usage mode

ProviderSegment only rendered a user template on the verbose branch, so
switching usage mode to compact silently fell back to the built-in
tightest-window label. A non-empty template now replaces the built-in
text in both modes; the mini bar stays verbose-only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99

* docs(appearance): document remaining functions touched by the diff

Adds one-line JSDoc to the editor surfaces, diff viewers, palette helpers
and UI-slice entry points this branch modifies so the diff's docstring
coverage clears the pre-merge threshold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99

* fix(editor): keep Monaco theme registration and preview clock out of render

The upgraded oxlint React rules flag reassigning a module variable during
render and calling Date.now() inside useMemo. Move the terminal Monaco
theme's signature cache into ensureTerminalMonacoTheme() and pin the
usage-format preview clock with a lazy useState initializer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99

* localization: complete Brazilian Portuguese catalogs

* fix(i18n): localize remaining hard-coded UI copy and complete Simplified Chinese coverage

Route the English literals and shared English labels that ignored the UI
language through the existing catalog: host labels, plugin cards and consent,
CLI and SSH errors, the checks pill, browser profile labels, shortcut groups,
app and context menus, and the macOS computer-use permission window. Shared
labels are translated where they render, so src/shared stays English for
mobile, CLI and older paired hosts.

- en.json gains 314 keys bootstrapped from inline fallbacks; four duplicate
  "Unassigned" keys collapse into translateUnassignedLabel()
- zh gains 337 entries and refreshes existing ones; the other nine locales get
  the newly extracted keys
- joinSentences ends a CJK sentence that has no final stop with 。 before the
  next one
- the desktop caller passes the computer-use helper its locale; orcad and the
  CLI stay Electron-free
- three files the copy pushed past max-lines each shed a focused module

* test: expect labeled roles in the editable context menu

The edit menu now passes explicit Cut, Copy and Select All labels so the roles render in the UI language; the upstream template assertion still expected bare roles.

* fix(i18n): key translated memos on the UI language without bare void reads

Upstream's React Compiler ratchet rejects `void language;`, which the compiler drops, and treats a react-hooks lint suppression as a bailout. The two host-label hooks now pass the language through readUiLanguageMemoInput so it stays a real memo input. ContextualTourOverlay drops its language key: getContextualTour is a static lookup, and step copy is localized at render.

* fix(i18n): translate editor theme settings

* Fix reactive localization and catalog extraction

* Fix combined localization validation

* Localize nested import failures and refine catalogs

* Handle older nested import responses

* Fix localized merge prompts and quota windows

* Address localization and runtime review feedback

* Keep host search and configuration examples usable

* Preserve configured names in add-project host selector

* Preserve host label origins across views

* Use localized fallback for missing local host

* Preserve custom names and refresh localized host labels

* Refresh task host labels without repeating searches

* Preserve Portuguese mobile tab translations

* Address localization review feedback

* fix(status-bar): import window visibility interval from its new path (#40951)

---------

Co-authored-by: lisi <lisi.see@bytedance.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: marlico77 <marlonssoficial@gmail.com>
Co-authored-by: x-Ai <5061489+x-Ai@users.noreply.github.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-10 18:21:19 -08:00
OrcaWinandOrcaWin 2093801982 test: remove low-value shared and native suites (#40172)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 01:02:16 -08:00
OrcaWinandOrcaWin 40abff3220 test: reconcile VM mobile and native test removals with current main (#40154)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 01:02:00 -08:00
OrcaWinandOrcaWin a489ef5ba3 test: reconcile approved test removals with current main (#40176)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-08 23:19:51 -08:00
OrcaWinandOrcaWin b69d67f699 test: remove low-value native ownership tests (#38557)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 05:44:00 -08:00
OrcaWinandOrcaWin 7deeabd41f test: remove low-value native validation tests (#38553)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 05:35:34 -08:00
OrcaWinandOrcaWin 00b56535c6 test: remove low-value native helper tests (#38552)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 05:25:57 -08:00