* Keep opened GitHub work items bound to their exact repository
* Bind GitHub work item ownership through consumers and dispatch
* Keep empty mention lists from consuming selection keys
* Preserve GitHub action and consumer ownership across resource changes
* Exercise repository account updates through their production store action
* Exercise account publication and cache settlement through GitHub consumers
* Simplify fork PR contract verification
* Make contract verification imports and clocks deterministic
* Correct mobile task test fixtures and model types
* Correct task recording fixtures and CI types
* Correct task fixture types and static checks
* Consolidate replay test RPC imports
* Separate GitHub metadata imports from Linear hooks
* Scope mobile PR sidebar reads to the selected resource
* Separate desktop GitHub changes from phone updates
* Fix relay authority probe census across topology cases
* Repair repository owner proof fixtures and compiler allocation
* Preserve repository row observation in host lookup
* Seed metadata fixture before server-side store acquisition
* Preserve nullable fixture settings and discover mixed test types
* Preserve GitHub detail argument types and optional capabilities
* Let keyed details queries own pending read replacement
* Repair GitHub RPC and relay test fixture boundaries
* Verify expected GitHub account at repository execution capture
* Preserve captured GitHub account expectations through client dispatch
* Retain observed runtime status after switching environments
* Fix account contract fixture types and RPC setup timing
* Restore the negative-capability switch probe assertion
* Align account fixtures with runtime identity and configured origin
* Consolidate details test imports
* Drop duplicate fork pull request identity tests
* test: remove 25 low-value checks and six complete suites
* Remove deleted startup benchmark from plugin CI routes
* Remove CI route for deleted pet layout smoke suite
* test: repair retained E2E labels and collision lifetimes
* test: remove synthetic activation collision scaffolding
* fix: activate folders opened on the selected runtime
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(wsl-hosts): a stopped distro still lists all its projects after a restart
The desktop now keeps each WSL host's last project list (from the repo.list
answers the window already receives) and seeds those rows at startup before any
live host catalog is requested. The first live list replaces them, so projects
deleted on the host disappear on that fetch. Loading the saved list is a desktop
read only: no wsl.exe, no host RPC, no \\wsl.localhost access. The saved list is
cleared when the host is removed.
* fix(wsl-hosts): pin saved project list writes, removal, WSL gate and seed races
- Exempt HostRepoCatalogSnapshotPersistence.environmentId from the id-only
store write ratchet like the paired-server layout snapshot (the id names the host).
- A live list applied before the startup seed now skips that host's seed, and
a live answer requested before the seed may still drop seeded rows.
- Tests now count saves, cover remove then re-add, check paired servers in
storage and in the listing, and cover both seed/live-list orderings.
* ci: refresh unit shard timings from a 12-shard four-worker run
Replaces the October 25 five-shard eight-worker baseline with run 41403569437,
which includes the November 1 test-time fixes. On an independent run's
measurements the projected per-shard spread falls from 12.0% to 7.4%.
* ci: average unit shard timings over five runs
A single run's per-file noise left this PR's own run 21.8% apart. The importer
now accepts several complete runs and averages each file; held out, the
averaged baseline projects 3.8% against 10.2% for the October 25 baseline.
Deletes terminal-tail-redraw-wall-time: its result equality duplicates the
randomized equivalence suite and its complexity claim is pinned by the
join-counting scaling suite; it only added a 3x wall-clock race.
Shrinks scaling suites whose bounds are exact or log-bounded formulas in n to
the smallest population that still separates linear from superlinear work, and
pairs a worktree-poll test's scans so it no longer waits out the 5 s scan timeout.
* test: restore plugin routing and prompt receipt checks on main
* test: flush pending receipts before releasing the prompt write
* test: route screenshot CLI sources to the journeys that run them
- shot --act: say edits only dirty the tab; end with Cmd/Ctrl+S to save
- manifest: compound suffixes like .sketch.json open by default
- cli.md: list plugin check's exit codes, including plugin_check_failed
- workflow: how to run and stop the dev app from a source checkout
- plugin create --help: real descriptions for --template/--publisher/--id/--name
- recipes: declaration file for vendored ESM libraries
recipes.md gains "A rich editor with a library" beside the hooks and status
bar recipes: an isolated-frame custom editor that vendors its library behind
an import map, syncs through orca.document.session with a merge by id, and
tests that sync with mockEditorHost. host-api.md lists every --orca-* frame
variable and what it paints, generated from the frame token allowlist.
* feat(plugins): check custom editors statically and add mockEditorHost
orca plugin check now follows each custom editor entry (local script src,
inline module scripts, relative imports), transpiled and resolved as the
frame loader does, and fails at file:line:column on syntax errors, missing
files, refused imports, string eval/Function and files over their size
cap, with no running Orca. The check ships in the test hooks bundle.
orca/testing gains mockEditorHost: it runs the frame shell's real
window.orca (document API and session) over an in-memory text or bytes
file, with edits, replace, conflictNext, flush, setTheme and dispose.
Typings, docs and the skill guide cover both.
* feat(plugins): warn on editor eval and check editors in dev watch
editor_eval comes from a lexical scan that can misread rare code, so it is
now a warning that does not fail orca plugin check. dev watch --check runs
the editor check beside the panel check and reports it under editors.
* fix(plugins): check editors by the frame protocol's rules; mock blocks lost saves
The static editor check now reads files through the loader's contained
reader (symlinks out of the plugin are refused), runs only JavaScript
script types, honors the page's import map for native modules, classifies
files by the protocol's content types (JSON imports, extensionless HTML
entries), decodes escaped script URLs, and uses the protocol's caps: 10 MiB
entry, 1 MiB transpiled module, 16 MiB checked dependency.
mockEditorHost refuses an oversized edit before reading it and then rejects
flush() until a later edit lands, as Orca blocks the save.
* test(plugins): type mockEditorHost's frame API instead of reflecting on it
* fix(plugins): keep main's case-spelling check and hook typings through the rebase
The rebase onto main resolved plugin-artifact-validation.ts and
orca-testing.d.ts to B4's side; this puts back main's exact-path-spelling
check and hooks typings beside B4's contained reader and mockEditorHost
types, and regenerates the testing bundle.
* plugins: contributes.hooks runtime with terminal.send and workspace.create hooks
Workers register orca.hooks.on(hook, (event, next) => ...). Orca runs listed
plugins in order before it acts: next(event) continues with allowed fields
changed, { deny } stops, nothing passes. A plugin past its 2 s deadline, or
one that throws, crashes or is disabled, counts as passing and is logged with
plugin, hook and duration. First hooks: terminal.send (runtime sendTerminal),
workspace.create.before (IPC and runtime creates, folders included) and
observe-only workspace.create.after. orca/testing mountWorker gains
hooks.fire. Needs main + trusted-worker and engines.orca >=1.4.248.
Co-Authored-By: Claude <noreply@anthropic.com>
* plugins: keep hook plugins' workers started; bound start-up separately from the hook deadline
Workers of enabled plugins that list hooks start as soon as they are approved
and are never idle-reaped; crash restarts follow the manager's policy. A hook
waits up to the worker ready timeout for start-up, then gives the handler its
full 2 s, so a cold worker no longer lets the first hooked action through.
Co-Authored-By: Claude <noreply@anthropic.com>
* plugins: give hook workers their own soft cap instead of the active-worker cap
Always-running hook workers no longer hold slots of the shared 5-worker cap, so
many hook plugins cannot starve the rest. They have a soft cap of 16; past it a
hook worker waits for another to stop, logged once.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(plugins): type the hook warmer's ensureWorker mock
* plugins: address hook review: ordering, human input, overflow, revalidation, folder creates
- Hook workers past the soft cap start as overflow (logged once) instead of
waiting, so reconciliation, disable and uninstall never hang.
- Writes to one terminal stay in order while terminal.send decides, so a later
Enter cannot submit the previous line.
- terminal.send runs only for programmatic sends (main, plugins, the CLI);
desktop, mobile and legacy client input is a person's typing.
- Text a hook rewrote passes the AI Vault resume check again.
- Project-group folder workspace creates (RPC, agent launch, window) run the
workspace.create hooks through one boundary.
- A decision from a plugin disabled or changed while it ran is discarded.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(plugins): drive hook start-up timing with fake-timer deferreds, no real sleeps
Co-Authored-By: Claude <noreply@anthropic.com>
* plugins: only the hook decision holds a terminal's write order
A delivery that waits (a permission prompt, the launch composer) no longer
blocks later writes, and a person's input, interrupts and query replies never
wait behind a pending decision.
Co-Authored-By: Claude <noreply@anthropic.com>
* plugins: hook DX: onError deny, denied_by_plugin, a Hooks reference, --template hook
- contributes.hooks[].onError: "deny" makes a throw, timeout, crash or bad
answer refuse the action, naming the plugin; the default still passes.
orca/testing mountWorker honours it, and mockHost answers fire-and-forget
methods (result { ok: true }) with success by default.
- A plugin denial reaches RPC clients as denied_by_plugin with the plugin and
reason, and the CLI no longer suggests a retry for it.
- The skill's host-api reference gains a generated Hooks section (event, what
next may change, stop result); the recipe passes sends through unchanged and
warns against awaiting other calls before deciding.
- orca plugin create --template hook: a worker-only terminal.send guard that
fails closed, with a test.
Co-Authored-By: Claude <noreply@anthropic.com>
* plugins: regenerate hook docs on main; bind the plugin runtime and its hook runner in one call
Keeps main-process-plugins.ts under 300 lines now that status bar items landed.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Resume direct work item launches after setup confirmation
* Preserve setup review and settle cancelled work item preparation
* Fix setup test types and synchronize localization artifacts
* Keep accepted setup launches owned through completion
* fix: declare accepted create dialog result
* fix: report direct launch preparation failures
* Reuse workspace setup preparation and section
* Use compact dialog description for setup help
* Construct omitted setup decision fixture through serialization
* Match optional signal in background setup trust test
* ci: full checks on main pushes, changed-file lint on PRs, Slack alert when main breaks
PR Checks now also runs on every push to main, with each commit in its own
concurrency group so main runs never cancel one another. On a push the path
router gets an empty diff, which already fails closed to every job, and the
input-scoped steps (localization extraction, VM rollback replay, orcad smoke)
run in full. Advisory E2E lanes stay PR-only.
On PRs the per-file passes (root oxlint, JS-plugin oxlint, anti-slop, ast-grep
and oxfmt) check only the changed paths. Everything is checked when the diff
cannot be resolved, a lint toolchain input changes (oxlint/oxfmt/ast-grep
configs and plugins, package.json, the lockfile, .gitignore, pr.yml), or more
than 1500 paths change. Whole-program checks stay unscoped.
A new workflow follows completed main runs and posts to the release Slack
webhook only when main turns red, and once when it turns green again.
* ci: alert once per main health streak and tolerate a malformed Slack mapping
* fix(tasks): publish confirmed dialog assignee changes to the list
Record successful per-login changes in the existing assignee snapshot and
patch the Tasks cache. Qualify snapshot writers, composition and quiet
release by canonical repository so fork and host twins stay isolated.
Co-authored-by: Max Hsu <maxmilian@gmail.com>
* test(tasks): bound confirmed assignee publication work
* Add explicit task refresh through registered details
* Refresh registered tasks with finite request ownership
* Preserve addressed task display and ordinary edit boundaries
* Derive task membership from owned rows and batch cache updates
* Preserve task list intent across account changes and query resets
* Preserve GitHub task content through final delivery
* Preserve accepted task content across cold query changes
* Batch finite task delivery publications and index ordered list folds
* Capture immutable Tasks publication inputs and translate Refresh feedback
* Preserve live scalar settlement beside captured publication inputs
* test: make task refresh contracts deterministic for static checks
* test: derive lifetime token annotations from production origins
* test: initialize current repo catalog defaults for refresh fixtures
* Fix refresh import dependencies for static checks
* Fix GitHub task refresh adapters and verification inputs
* Exercise omitted mutation observation in overlap contract
* fix(tasks): refresh live list bases and align delivery contracts
* test(tasks): retain actual pagination setter inputs
* fix(tasks): express page array mutability with checked overloads
* fix(tasks): preserve complete models through refresh stages
* fix(tasks): align origin and query row input contracts
* test: declare portable task refresh mock contracts
* test: allow zero-argument task refresh mutation calls
* Keep GitHub task copies fresh after edits and refresh
* Keep task rows visible and simplify the shared task record
Rows are never filtered for a stale connection or account binding; only a
current record for the row's own repo overlays its facts, derived at read
from repoId/repoHostId. Records cover issues only, conflicts compare only
state, title, label names and assignee logins, and truncated Project lists
never count as conflicts. Project tables stay raw in the store and are
projected where they are read.
Ordinary local dialog opens keep cached, lenient reads; only Refresh asks
for the fresh, strict read. Refresh waits on the record's own pending edits
instead of a second write registry, reports a failed user Refresh once
through the existing toast, and explains in its tooltip when the server
needs an update. Background verification never shows a failure.
A successful dialog assign keeps the selection until a newer reading lands,
main's soft-hide for Tasks-row edits is unchanged, and pins/eviction are
gone because only user edits and Refreshes create records.
* Let saved descriptions win over Refresh and roll back disposed edits
Refresh is now the only fresh, strict read: it writes the same details
entry ordinary loads use, and later reopens and post-edit refetches go
back to the cached, lenient path. An issue's saved description supersedes
any read already in flight, so Refresh rereads after the save instead of
restoring the older body. A failed Refresh with nothing loaded yet leaves
only the body's existing load error.
A record disposed while its edit is in flight still settles the copies its
edit patched, so a failed edit rolls back in Tasks and the dialog as before.
A record whose own connection fence went stale is dropped when next
looked up. Rows without a record pass through acceptSearch unchanged.
* Settle disposed edits through their owner and connect Project edits
A late edit whose record was disposed mid-flight now finishes through the
same base/pending reducer: copies receive only that operation's own change
(one label or login added or removed, a state set), a replacement record
reconciles with its own item read, and settle never returns null so dialog
and Tasks rollback always run. Untracked edits publish the same semantic
change at begin and undo it on failure. Dialog callers stop re-patching
Tasks rows; an unsupported server's live record keeps new edits joined
until its last one settles.
Refresh clicked during the first details load waits for that load, then
runs the strict read; a failed click always shows its one toast and never
installs an inline load error.
Project-row issue edits now publish to Tasks copies with no prior record,
seeded from a complete Tasks row for the matched repo binding, or
established by an item read after the edit lands.
* Give a task record its base only from an accepted provider reading
Starting an edit or a Refresh no longer turns the caller's cached row into
the record's full value. Until an owned canonical read is accepted, a record
holds only its pending changes and the coalesced successful ones, and every
copy (Tasks rows, pickers, the board) shows its own facts plus only those
changes. A successful edit applies just its change to the stored copies and
keeps it until one coalesced read through the existing read lane
establishes the base; a failed edit with nothing else owed retires the
owner, and a failed first Refresh leaves nothing behind. Search deliveries
and board fetches wake a read still owed.
Edits are now semantic change values (set title or state, add or remove a
named label or login) instead of closures, so they coalesce and apply to any
copy. Project edits keep their producer but no longer seed from a cached
row, and the separate establishing read is gone. A Project save with no
title, label or assignee change (a body-only save) skips the record
entirely.
* Keep pending task edits out of stored copies and re-admit queued reads
Accepted records now follow the rule records without a reading already
followed: stored Tasks copies hold only accepted readings and confirmed
changes, and pending changes reach users only through read-time projection.
A search during a pending edit stores the accepted facts, never the edit; a
failed or disposed edit just drops its token instead of computing an undo
over current copies, so a newer reading can't be overwritten by an old
edit's rollback. The cross-copy undo helper is removed.
Without a tracked owner (no binding, or a server without the item route),
other copies change only when an edit succeeds, and a board edit on a
server known to lack the item route stays board-only. Dialog state and
label edits roll back to what the dialog showed.
A canonical read queued behind another one re-enters admission after each
wait, so a Refresh clicked after a discarded one still reads, and a read
whose binding or server support went away meanwhile ends without leaving
an owner.
* Store only readings, keep task data across reconnects, park failed reads
Stored Tasks copies (the fresh-cache fetch return, details settle) hold only
accepted readings and confirmed edits; Cmd-J applies its open-only filter to
what it shows, pending edits included. Records, details entries and
optimistic comments are keyed by account binding and issue; a connection
change re-captures the binding and fences each read and send without
deleting what the dialog shows. A server's missing route marks only the
connection that answered. An unusable canonical read keeps what is known
and waits for the next provider delivery, which retries one owed read per
binding, the longest-waiting first. The dialog's label chips follow the
displayed item, and the duplicate target fence and write-only details
generation are removed.
* Park only reads that were owed, so a failed Refresh never delays a later one
A failed Refresh on a record with nothing owed no longer marks it as a parked
retry; a later obligation on that issue reads on the next delivery instead of
waiting behind every parked record. The refresh hook stops returning its
unused target.
* Keep the ordinary-open details case after main removed its suite
Ports the one case that pins an ordinary open with an issue repository to the
cached, lenient read (a failed timeline read still returns details) into the
main details suite.
* Keep pull-request lookups off the task records and repair CI tests
Pull requests never have a task record, so their lookups no longer load the
store or report a search reading; terminal PR-link confirmation reads as on
main. Tests follow the explicit canonical details flag, the current dialog edit
signature (records hold a dialog close over a lagging search), confirmed-only
untracked publication, and a fixed board timestamp.
* Keep main's close hold where no task record can own it, and split the record cache
A dialog close or reopen that no task record can own (no binding, or a server
without the item route) keeps main's confirmed-state hold, so a lagging search
cannot show the issue open again; a record that takes over retires it. Tracked
edits still go through the record only.
The record cache moves, unchanged, into model, owners and reads layers under
the Project-facing cache, so no module needs a max-lines exception.
* Hold an untracked dialog close only after it is confirmed
A dialog close or reopen no record can own changes no stored copy while the
request runs, so a refresh during a failed request leaves every copy as it was
and nothing needs undoing. At success the edit is admitted again: a record that
can now own it (after a reconnect or upgrade) settles it, otherwise main's
confirmed-state hold is asserted and the change is published once.
* Name the task binding incarnation token type
The binding incarnation, compared by reference, gets its own named type instead
of the broad object type; no behavior change.
* Import Cmd-J task search results from one statement
* Type changed code without assertions and keep the assignee callback stable
Tests build typed fixtures and hoisted mocks instead of casting; the landing
refresh takes only the model parts it reads. Lookups and the comments parse
annotate their values instead of asserting them. The edit section's empty
assignee list is one shared value, so its toggle callback keeps its identity.
* Stamp the opened row onto main's details item before it reaches typed record reads
* Pin the parked-read and board-read budgets at 10 and 100 records
* Size the dialog's Refresh task button like Copy link and Open on GitHub
---------
Co-authored-by: Max Hsu <maxmilian@gmail.com>
* Keep deleted-workspace chat Resume in History
* Address review: keep notification bounce, announce History toast, tidy refusal outcome
* Fix mobile type narrowing in History open failure
* Re-measure mobile web bundle sweep after History notice import removal
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.
* docs(agents): drop casting section; casting lint now explains the policy
The changed-code casting scan already enforces no type assertions (as const allowed)
and SAFETY:-annotated suppressions. Its diagnostics now print the allowed
alternatives and the exact suppression form, so AGENTS.md no longer needs to.
* docs(agents): oxfmt AGENTS.md so CI formatting check passes