Commit Graph
2178 Commits
Author SHA1 Message Date
Neil 3e52963a9a docs(plugins): fix custom-editor authoring papercuts from dogfood (#37337)
- 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
2026-11-01 21:48:46 -08:00
Neil 9b39188021 refactor: organize session option and conversation owners (#37289) 2026-11-01 21:33:42 -08:00
Neil 591f2acbc8 docs(plugins): add a rich-editor recipe and list frame theme variables in the skill (#37306)
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.
2026-11-01 21:30:37 -08:00
Neil fa7c3f95fe feat(plugins): check custom editors and test them with mockEditorHost (#37293)
* 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.
2026-11-01 21:28:13 -08:00
NeilandClaude ac8c1125f0 feat(plugins): hooks that can change or block terminal sends and workspace creation (#37287)
* 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>
2026-11-01 21:12:57 -08:00
Brennan Benson 764bd0be44 Continue Fix checks and project actions through setup confirmation (#36539)
* 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
2026-11-01 20:39:09 -08:00
Neil a7ae68fc6f ci: full checks on main pushes, changed-file lint on PRs, Slack alert when main breaks (#37282)
* 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
2026-11-01 20:30:03 -08:00
Brennan BensonandMax Hsu 8e326f2629 Keep GitHub task assignees and rows current after dialog edits (#34245)
* 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>
2026-11-01 19:34:54 -08:00
Brennan Benson 5020bfead6 Keep Session History open when a chat workspace was deleted (#37200)
* 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
2026-11-01 19:31:05 -08:00
Neil b69963356d chore(terminal): bump xterm to 6.1.0-beta.336 and regenerate patches (#37266)
Port the xterm, webgl, search, serialize and image source patches to upstream
08829c7. Where upstream fixed the same bug (#6204 mouse NaN guard, #6226 warm-up
cancel on dispose, #6235/#6237 serialize width clamp) take upstream and keep only
Orca's remaining delta (domContainer warm-up gate, clipped wide-cell blanking).
Bump mobile's webgl subset patch alongside. Drop serialize fuzz seed normal:5,
which now round-trips.
2026-11-01 18:05:58 -08:00
Neil 8bb3b8bb93 refactor: group worktree jump palette owners (#37265) 2026-11-01 17:51:23 -08:00
Neil 81103271c1 docs(agents): drop casting section; casting lint explains the policy (#37244)
* 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
2026-11-01 17:34:17 -08:00
Neil 81ef1d2403 refactor: group locale catalog maintenance owners (#37254) 2026-11-01 17:25:41 -08:00
Jinjing 0377e8bd41 Simplify and improve Codex and Claude account switchers (#37255)
* Redesign account switcher presentation without changing account policy

* Improve account switcher readability for long labels and usage bars

* Simplify account switcher layout and menu actions

* Fix account switcher localization and fixture checks
2026-11-01 18:16:12 -07:00
Neil ecdbabeefa refactor: group workspace port scanning and assignment regression tests (#37250) 2026-11-01 16:48:20 -08:00
Neil 0509a2d83a refactor: group local PTY provider and shell readiness modules (#37235) 2026-11-01 16:16:22 -08:00
Kelvin Amoaba 03abca65dc feat(mobile): outline every text field at 3:1 with a focus ring, and drop the composer shadow (#37221) 2026-11-01 23:39:33 +00:00
Neil c550fbca06 refactor(browser): group agent browser adapter modules by owner (#37223) 2026-11-01 15:32:34 -08:00
Neil 8538b07f9a refactor(browser): group CLI and preload owners (#37182) 2026-11-01 14:57:05 -08:00
Jinjing 8e8fbe3478 Prevent activity previews over row controls (#37154)
* Prevent activity previews from opening over row controls

* Use standard icon sizes and include changed-code checks in lint
2026-11-01 14:59:02 -07:00
Neil 572a9c62e1 refactor(claude): group agent view owners (#37147) 2026-11-01 13:47:24 -08:00
Brennan BensonandOrca QA c18c358fce Keep child-worktree creation in the caller’s project (#35787)
* fix(cli): keep inferred worktree creation in the caller project

* Fix caller checkout ranking and creation guidance

* Share caller-host containment preparation across CLI selections

* Correct Windows CLI fixture syntax and snapshot command

* Match worktree fixture output to typed execution hosts

* Regenerate bundled workspace placement guidance

* Refuse ambiguous workspace ownership and preserve launch replay

* Scope runtime filesystem mocks to their aggregate tests

* Preserve launch proof semantics under strict test diagnostics

* Keep launch proof imports within their compiler project boundary

* Consolidate journal cleanup test imports

* Adapt launch fixtures to the current host settings contract

* Keep the CLI error formatter under the file-size limit

Move the selector-ambiguity workspace-choice check into selector-ambiguity-recovery.ts, which already owns that error's recovery text. Behavior is unchanged.

* Expect main's concise orchestration output in the workspace-choice CLI tests

Orchestration commands now print the one-line failure on stderr and the workspace choices and next steps on stdout (or compact JSON plus the stderr line with --json), and print concise success fields.

---------

Co-authored-by: Orca QA <orca-qa@users.noreply.github.com>
2026-11-01 13:35:47 -08:00
Kelvin Amoaba ebe94bc32e feat(mobile): rebuild the PR tab around what is blocking the merge (#36999)
The PR tab now leads with the PR's identity, one row per merge gate
(checks, unresolved threads, approvals, conflicts) that opens the screen or
sheet that resolves it, a changes card and a collapsed description. Close,
Unlink, Auto-merge, Edit title and Copy link move into the ⋯ menu.

Checks and Comments become pushed screens: failures open with their
annotation and Fix / Rerun / Open / Log on the failure, running checks
next, passed folded; comments filter by Unresolved / All / Hide bots with
Resolve and Reply on each thread and a comment box at the bottom.

Merge opens a sheet that lists only the methods the repo allows, starting
on its default. Reviewers move into a sheet with search to add and remove.

Every Create PR entry point opens one sheet: title and description seeded
from the branch's commits (shared seed rule in src/shared, GitHub's own
default), Write with AI, base picker and draft. It pushes first when
needed, works for all five providers and lands on the PR tab for GitHub.
2026-11-01 21:08:49 +00:00
Neil aa93f60ae4 refactor(acp): group history replay and catch-up owners (#37133) 2026-11-01 12:19:34 -08:00
Kelvin Amoaba 78484aac31 feat(mobile): one next-step bar under both Source Control tabs (#37104)
* feat(mobile): one next-step bar under both Source Control tabs

Changes and Pull request are the only segments. A bar at the foot of both
shows the branch's one next action: the commit box, push or pull, create
the review, resolve or fix with the workspace's agent, merge when ready,
merge, or why it can't. Commits opens as a pushed screen.

* fix(mobile): keep Merge reachable and show bar failures on both tabs

* test(mobile): expect the two Source Control segments in the page render test
2026-11-01 20:17:11 +00:00
Neil 520588fe97 refactor(codex): group app-server transport and lifecycle owners (#37109) 2026-11-01 11:05:38 -08:00
Kelvin Amoaba a3efdcb21b feat(mobile): GitHub review threads, viewed sync and line comments on the diff screen (#37073)
* feat(mobile): GitHub threads, viewed sync and line comments on the diff screen

Committed files of a GitHub pull request now show its review threads under
their lines with Reply and Resolve, take their viewed state from GitHub and
sync the checkbox and Viewed · next file back through setPRFileViewed. A tap
or a long-press drag picks lines and opens a sheet that sends the note to
the workspace's agent through the existing send path, or posts it as a
review comment. Threads and GitHub comments appear only while the local
branch is at the PR head, the same contents desktop shows them on;
otherwise the file says to push. openDiffForFile takes an optional line for
a thread's Open in diff.

* test(mobile): use a type import for the line-mutations recording adapter

* fix(mobile): name the staged or unstaged side in the jump sheet's file labels
2026-11-01 18:38:23 +00:00
Kelvin Amoaba 3edc370cdf feat(mobile): diff screen with jump to file, folded context and viewed/stage next (#36998)
The review screen becomes the one diff screen from the approved design.
It walks the Changes section the file came from (uncommitted, staged or on
the branch) or one commit's files, so 'N of M' and next/previous stay in
that list. The title opens a jump-to-file sheet built on the shared
source-control tree, with search and viewed boxes. Unchanged runs fold the
way desktop's diff does. The bar's main button is Stage · next file for
uncommitted files and Viewed · next file otherwise; Discard and Unstage move
to the menu. Filter chips, hunk jumps and Stage Reviewed are gone.

openDiffForFile also takes { kind: 'commit', commitOid, filePath }, read
through git.commitCompare and git.commitDiff.
2026-11-01 18:07:43 +00:00
Kelvin Amoaba 3b85ef84fc build(mobile): raise the page bundle's code fence to 9.5 MiB (#37014)
Main's page code is 9,414,296 of 9,437,184 bytes, and the Source Control
redesign branches add 7-31 KB each. The phone contract allows 10 MiB per
asset and 32 MiB in total, so the fence was our own budget, not a phone
limit; 9.5 MiB keeps it under the per-asset ceiling.
2026-11-01 17:51:38 +00:00
Neil a82538c3be refactor(runtime): organize session records and runtime modules (#37070) 2026-11-01 08:59:05 -08:00
Kelvin Amoaba f72daacc30 fix(browser): keep an agent's page drawing in a hidden worktree while it drives it (#37076) 2026-11-01 16:45:39 +00:00
OrcaWinandOrcaWin 9ce650839c test: remove 56 low-value tests and two suites (#37057)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 16:01:33 +00:00
Kelvin Amoaba d6f54f3561 fix(mobile): size the queued-message panel to its rows and fit translated Save/Cancel (#36928)
The queue card's invisible full-text line-count probe overflowed its two-line
row and stretched the queue's scroll range far past the real rows. Clip it to
the card text.

The queued-message editor drew Save and Cancel labels inside 38pt round icon
controls, so translated labels spilled over each other. They are now pills that
hug their label and truncate only when the row runs out of room.
2026-11-01 15:50:58 +00:00
Kelvin Amoaba 2eb80fb8a0 fix(mobile): show workspace images in session Markdown tabs (#36970)
* fix(mobile): show workspace images in session Markdown tabs

* fix(mobile): show workspace images restored by undo or paste

* fix(mobile): keep session image loader current and inside the workspace

* fix(mobile): classify entity-encoded image URLs by their decoded scheme

* refactor(mobile): classify editor images with the shared Markdown href router

* test(mobile): expect workspace image markup in the code-block selection check
2026-11-01 15:13:22 +00:00
OrcaWinandOrcaWin 0c2142cc16 test: remove 167 low-value tests and two CI tooling suites (#37053)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 15:02:31 +00:00
Neil 8503ecda71 plugins: check runs the worker and scenarios; RelativeTime (#37047)
- orca plugin check mounts the plugin's worker (main) on the same mock host
  as each panel, so plugin.request reaches its orca.panels.handle handlers
  as in Orca; a worker that fails to activate or deactivate is an issue
  named after its file. In orca/testing, a worker mounted on a host answers
  that host's panel requests unless `requests` stubs the name.
- Check scenarios: <entry>.check.ts (e.g. src/panel.check.ts) exports
  defineCheck({ name: { ...mockHost options, persisted, theme, events } });
  check renders the panel once per scenario and labels each result.
- RelativeTime (catalog 3, since 1.4.247) and { type: 'relative', at } Table
  cells: Orca ticks them (each second under a minute, then less often), so
  plugins never poll. Inline inside Text; test kit reads them as drawn.
- Typings, docs, skill guide, generated references; gallery shows it.
2026-11-01 06:56:19 -08:00
Neil b29e7f5316 refactor: group Claude structured session owners (#37036) 2026-11-01 06:33:21 -08:00
OrcaWinandOrcaWin 0646d26ff0 test: remove 157 low-value tests and route-contract suite (#37038)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 14:07:39 +00:00
Neil a37a5b3e2d Plugin dev emit reaches panels; trim the plugin authoring skill (#37026)
* feat(plugins): dev emit also reaches the plugin's open panels

orca plugin dev emit now publishes through the panel bridge to that dev plugin's open panels
that subscribed with orca.on, under the same approval and capability rules as the worker, and
reports delivered.panels. The bridge's publishEvent takes an optional pluginKey filter and
returns how many panels heard it. A panel-only plugin no longer needs a worker; an event
nothing listens for is refused.

* docs(skills): trim the plugin authoring guide; details move to references

The main guide drops from 299 to 121 lines: the decision table, build-less rules, core loop
(create → dev watch --check --shot → read the PNG → test → check → release-entry), approval
and top gotchas. Test/check and orca/testing (panels and workers), dev watch events, shot,
open and dev emit move to a hand-written references/workflow.md; the panel/worker/data and
agent status recipes to references/recipes.md, each with a read-when row. The guide test now
also scans hand-written references for commands and caps the main guide at 150 lines.
2026-11-01 05:58:04 -08:00
Neil e5b87cb8e6 Components catalog 2 and worker tests: forms, tabs, table, tree, markdown, code, images (#36997)
* plugins: components catalog 2 (forms, tabs, table, tree, markdown, code, images)

Adds 18 components to TSX components panels, drawn with Orca's own
primitives and gated by ui.catalog 2 / ui.has() (Orca 1.4.247):
Textarea, Checkbox, RadioGroup, Slider, Field, Tabs/Tab, Collapsible,
Toolbar, Grid, a virtualized Table with sort, selection and pull-based
paging, a keyboard Tree with lazy children, Markdown (sanitized, links
through the checked open path), CodeView (Orca's highlighter), Image
(header-checked plugin files read by main), KeyValue, Callout and
Skeleton, plus a tooltip prop on Button and IconButton.

Value controls share the edit protocol; handlers get plain JSON event
args, including small objects ({ keys }, { key, expanded }). The test kit
gains matching actions and hides unselected tabs and closed collapsibles;
a components-gallery example and e2e cover the catalog end to end.

* plugins: worker test harness, host refusals in tests and check

- orca/testing gains mountWorker(main, { host, events, commands }): it calls
  the default-exported activate(orca) with the orca object Orca itself builds
  (createPluginWorkerOrcaApi, moved to shared so the kit reuses it), backed by
  mockHost. emit() checks payloads against Orca's event schemas and only
  delivers subscribed events; command(), request() (the worker's
  orca.panels.handle, as a panel's plugin.request), posts, logs, refusals and
  deactivate(). Storage and settings share the mock host's in-memory store.
- orca plugin test loads a worker main's module graph as Orca's worker host
  does (.ts/.mts transform, Node resolution, no runtime orca import).
- mockHost records refusals (capability_denied, not_permitted, ...) even
  when plugin code catches them; panel.refusals exposes them and
  orca plugin check reports them as warnings. Check dedupes repeated issues.
- Typings, docs and a generated references/testing.md skill reference; the
  reference generator reads the split orca typings.
2026-11-01 05:43:15 -08:00
OrcaWinandOrcaWin 70256eab83 test: remove 181 low-value tests and 2 suites (#37024)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 13:09:05 +00:00
Neil 1392c8e894 Plugin dev loop: orca plugin open/shot, dev emit, and dogfood fixes (#37008)
* feat(plugins): orca plugin open and shot; dev watch --shot

- orca plugin open <key> [--panel|--editor] shows a panel in the right sidebar or a file in the
  plugin's custom editor, by changing renderer state only (no focus or window raise).
- orca plugin shot <key> [--panel] [--theme] [--width] [--out] [--json] waits for the panel's
  current code to draw, then crops webContents.capturePage to the panel (html guests included),
  with background throttling off while hidden. --width and --theme are temporary in-memory
  overrides; the PNG returns base64 (5 MiB cap), so --environment works.
- dev watch --shot <dir> writes a PNG per panel after the load and each good reload.
- The authoring skill's loop is now dev watch --check --shot → read the PNG → plugin test.

* fix(plugins): shots never disturb a visible Orca

- shot --theme is skipped while the Orca window is on screen (themeApplied: false with a
  themeReason); the override applies only to a hidden or minimized window.
- dev watch --shot opens the first panel (or --shot-panel <id>) once, then shoots it with
  ifShown: if the user moved the sidebar away it emits one shot_skipped instead of switching.

* fix(plugins): dev loop dogfood fixes; orca plugin dev emit

- dev watch: approval re-run command drops watch-only flags and old --approve; a folder added
  by a refused load is owned by the next approved load (Ctrl-C unloads it); check events
  carry the plugin's status (no green while pending/errored); reloaded prints before that
  reload's logs; --json errors are one NDJSON line.
- Errors: log, banner and check share source-mapped positions (a line-1 prelude hands sucrase
  mappings to the components runtime); check dedupes issues and locates syntax errors;
  Orca runtime frames and the error module's bogus location are dropped from logs.
- .orca/types tsconfig sets preserveSymlinks (tsc 7 loaded typings twice under /tmp).
- Templates' READMEs use dev watch.
- orca plugin dev emit <dir|key> <event> [--data] sends a test event to a dev plugin's worker
  through the real delivery rules (plugins.devEmit).

* test(plugins): fixed timestamp in the dev emit test

* fix(plugins): shot captures an html panel's guest itself

On Linux the main window's capturePage leaves a <webview> guest blank. The renderer now reports
the guest's rect, and main captures the guest's own webContents and draws it over the window
capture at that rect (raw bitmaps, nativeImage only). Components panels are drawn by the host,
so the window capture alone stays right for them.

* refactor(plugins): keep plugin-service and main-process-plugins under max-lines

After rebasing onto #37013 both files crossed 300 lines. The guest log sink moves into the
desktop view binding (bindPluginDesktopViews), and plugin-service tightens emitEvent and its
event-delivery imports.
2026-11-01 05:04:51 -08:00
Neil c8c092599b refactor: group renderer session launch owners (#37018) 2026-11-01 04:56:22 -08:00
Neil ec0d3cedd1 Plugin panels talk to their worker; panel storage, settings and agent events (#37013)
* feat(plugins): panels talk to their own worker, read storage, settings and events

- plugin.request (host API 1.2): a panel or editor asks its plugin's worker, which answers with
  orca.panels.handle(name); the worker pushes with orca.panels.post. Same plugin only, JSON
  checked, 1 MiB answers, 256 KiB/200-per-10s posts, a deadline and the panel's lifetime.
- Panels and editors get storage.*, settings.* and secrets.* behind the same capabilities, and
  storage/settings onDidChange on every surface; events.subscribe delivers workspace and agent
  events to panels that hold the read capability.
- contributes.settings: typed settings (a JSON Schema subset) with defaults and value checks.
- Frames get orca.plugin/storage/settings/secrets; components panels import plugin, storage,
  settings, secrets from 'orca', and atom(key, init, { persist: 'storage' }) shares a value with
  the worker. Workers get orca.panels/storage/settings/secrets sugar.
- One typed contract: declare module 'orca' { interface PluginRequests / PluginPanelEvents }.
- Desktop push channel per open panel session (plugins:openPanelPush).

* feat(plugins): Orca Settings shows and edits a plugin's contributes.settings

The plugin page lists declared settings with Orca's own controls (switch, picker, text and
number fields, Reset to default). Edits are checked against the declaration in main, written to
the plugin's settings, and reach open panels and the running worker through onDidChange.

* docs(plugins): hello-tsx talks to its worker; authoring guide covers panels, workers and data

The example now uses one of each: plugin.request answered by orca.panels.handle, a worker post
heard with plugin.on, a persist: 'storage' atom the worker watches, two contributes.settings and
agent.status.changed in the panel, all typed by one src/protocol.ts. The build-less TSX e2e
drives the whole loop.

* fix(plugins): typed bridge overloads, panel call budget, settings IPC and catalog keys

- PluginBridgeApi/PanelsApi use overloads: declared names are typed (and complete), any other
  name carries JSON; no never-unions for the type-aware lint.
- The per-plugin panel call budget is 120 per 10 s, since a panel loading storage atoms,
  settings and its first requests makes a burst; the hostile fixture floods past it.
- Settings IPC builds its host per call; the settings section's strings are in en.json.

* test(plugins): the example's declared settings show under the plugin with the person's value

* refactor(plugins): keep hello-tsx the minimal starter; the bridge demo is hello-worker-panel

hello-tsx goes back to a sandboxed-ui panel with no worker or capabilities. The worker, protocol,
storage atom, settings and events move to examples/plugins/hello-worker-panel, with their own
e2e (plugin-worker-panel) and PR route.

* feat(plugins): test kit covers the panel bridge and plugin data

mockHost keeps the plugin's storage, settings and secrets in memory (seeded with storage,
settings, secrets; read with host.data()) and fakes the worker with requests, so plugin.request,
storage/settings/secrets and persist: 'storage' atoms work under mount(), writes reach
onDidChange, and panel.post(event, payload) is what plugin.on hears. Typed by PluginRequests and
PluginPanelEvents.

* test(plugins): focusInGuest waits for the guest and retries focusing as one step

Under load the custom-editor guest could still be attaching, so executeJavaScript threw
'dom-ready' before the focus poll began. Wait for waitForGuestReady, then retry focusing the
webview and the element together, tolerating a guest that is still attaching or remounts.

* docs(plugins): the authoring skill covers panels, workers and data; persistence leaves the renderer

- skill-guides/orca-plugin-authoring.md gains Panels, workers and data (plugin.request/on,
  orca.panels.handle/post, persist: 'storage', contributes.settings, panel events, test kit), and
  its generated references read orca-services.d.ts for shell, files, on and the bridge types.
- After the dev-loop rebase, persisted-atom wiring (queue plus storage sync) moves to
  createDeclarativePersistence so the renderer stays under max-lines.

* feat(plugins): panels show agents: agents.list, terminal ids on agent events, workspace.changed

- agents.list (agent:read, every surface): the focused workspace's agents with terminalId,
  title, agent kind, state and stateStartedAt, from the hook server's store.
- agent.status.changed carries terminalId and title: paneKey mapped through the runtime's
  terminal list (tabId:leafId) or the status's terminal handle; looked up only while a plugin
  listens, in arrival order.
- workspace.readContext terminals carry title; workspace.changed (workspace:read) fires after
  workspace session writes when the focused workspace or its terminals change.
- Event subscriptions are kept per panel session, so one made before the push channel opens
  still counts.
- shell.openExternal never prompts on a hidden or minimized window: it settles
  { opened: false, reason: 'consent-unavailable' } and says so in the plugin log, which also
  notes 'waiting for the person to confirm' while a prompt is up; the rate budget is spent only
  when Orca acts. e2e launches never open a real browser or mail client.
- A worker may export activate as default or by name; docs, typings and the authoring skill
  document the entry, the agent events and a live agent status recipe.

* fix(plugins): the plugin page names the workspace.changed subscription

* fix(plugins): workers activate only by default export, and say so when it is named

Orca calls the worker module's default export. A module with a named `activate` and no default
now fails to start with an error naming the fix (`export default function activate(orca)`),
instead of being called by a fallback; docs, typings and the skill say default export.
hello-worker-panel gains a picker setting (suggestionOrder) the worker reads.
2026-11-01 04:40:17 -08:00
OrcaWinandOrcaWin 3a983d06fd test: remove 278 low-value declarations and 31 suites (#37007)
* test: remove 278 low-value declarations and 31 suites

* test: prune timeout baseline after test removal

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 12:37:19 +00:00
Blue DaydreamingandNeil 0e25b0e22b fix(readme-links): preserve commas in srcset URLs (#36957)
Tokenize srcset like the HTML parser: read each URL up to ASCII
whitespace, strip trailing separator commas, and skip descriptors
(including parenthesized commas) before the next candidate.

Fixes #36955

Co-authored-by: Neil <neil@stably.ai>
2026-11-01 04:15:42 -08:00
Neil 46bc075bf9 refactor(renderer): colocate Jira board and list owners (#37006) 2026-11-01 03:55:41 -08:00
OrcaWinandOrcaWin ed3e82a2e7 test: remove 699 low-value test declarations and 116 suites (#37002)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 11:34:06 +00:00
Neil b17d408416 Plugin dev loop: TS workers, hot reload with state, orca plugin dev watch, authoring skill (#36982)
* feat(plugins): build-less TypeScript workers

A worker's main may be .ts/.mts. The plugin host installs module.registerHooks scoped to the
plugin folder: .ts files are transpiled with the frames' sucrase options (lines kept, inline
source map, source maps on), relative imports fall back to the frames' candidate files, and a
value import of the type-only 'orca/worker' fails with a clear error. Needs engines.orca
>=1.4.246.

* feat(plugins): components panels hot reload with their state

- In dev folders a save swaps only the hidden guest: keyed memory atoms are handed to the new
  guest (ui.retain → ui.hydrate memory), dropped when an atom's version changes.
- A save that fails to load keeps the last good render and shows an inline file:line:col
  error banner; the next good save clears it. A subtle Reloaded mark follows a reload.
- Transpile and import errors carry line and column; dev worker restarts keep storage.

* feat(plugins): orca plugin dev watch

One command for the inner loop: refreshes .orca/types, dev-loads the folder, follows its frame
and worker logs (plugins.getLogs gains an optional cursor), prints reloads (optional
devChangeCount on list entries) and status changes, and unloads on Ctrl-C. --json streams
NDJSON events for agents.

* feat(skills): orca-plugin-authoring bundled skill guide

A guide for agents to build Orca plugins end to end (decision table, build-less rules, the
dev watch loop, test/check, validate, release-entry, approvals, gotchas) with references
generated from the component catalog, host API table, event schemas, manifest schema and CLI
specs, checked for drift. Fixes the components template's Reset to set(count, 0).

* feat(plugins): orca plugin dev watch --check; test kit details in the authoring skill

- --check runs orca plugin check after the load and after each reload (one at a time; saves
  made meanwhile fold into one rerun) and prints each panel's render or errors inline, as a
  `check` event with --json. Local folders only, since it runs the plugin's code here.
- The orca-plugin-authoring guide's Test and check section now documents orca plugin test and
  check from #36969 exactly (JSON results, exit codes, test placement, the orca/testing kit and
  its common mistakes), and the loop uses dev watch --check.

* refactor(plugins): move the components renderer's timing and helper constants to their own module
2026-11-01 03:32:25 -08:00
Neil 89f9ce08de refactor(shared): organize session contracts and projections (#36979)
* refactor(shared): organize session contracts and projections

* chore: tighten dropped-path flaky pattern allowance

* docs: preserve current agent instructions with valid formatting
2026-11-01 03:14:46 -08:00