Commit Graph
676 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin 9af8f63538 test: remove 79 low-value cloud, hook and search tests (#38642)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:58:24 -08:00
OrcaWinandOrcaWin 87631616a8 test: remove 60 low-value storage and CLI tests (#38631)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:34:32 -08:00
OrcaWinandOrcaWin 64cd31458d test: remove 31 low-value interaction and state tests (#38629)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:21:57 -08:00
Neil 87788aeae5 refactor(runtime): group terminal execution owners (#38517)
* refactor(runtime): group terminal execution owners

* fix(tooling): retarget terminal ANSI consumer owner
2026-11-05 03:46:49 -08:00
NeilandMatthew Wilkinson f660d8c47d feat(plugins): add permissioned desktop appearance publication (#38524)
* feat(plugins): add permissioned desktop appearance publication

* docs(plugins): add one-line API comments for appearance provider

* chore(plugins): regenerate declarative testing kit for appearance API

---------

Co-authored-by: Matthew Wilkinson <wilkinson.m@outlook.com>
2026-11-05 11:31:23 +00:00
Neil 2f217b4d0d refactor(daemon): group endpoint, provider, session and transport owners (#38462)
* refactor(daemon): group transport, provider, endpoint, and terminal owners

* refactor(daemon): consolidate owner imports and preserve pinned baseline sources

* refactor(daemon): import termination budgets from their defining owner

* fix(ci): retain serve mode coverage for extracted orcad startup

* fix daemon build smoke to load concrete argument owner

* read daemon protocol facts from historical defining paths

* route protocol revision owners through compatibility checks
2026-11-05 01:54:51 -08:00
Neil 41e77c0764 fix(cli): account list --json refreshes stale usage instead of none (#38314)
orca account list called accounts.list with refreshUsage:false, so on an
idle headless host the JSON's rateLimits stayed null. JSON output now
asks the host to refresh only stale usage windows (the same
refresh-if-stale an accounts.subscribe stream runs), via a new optional
refreshStaleUsage param. The host waits at most 10s for it, so slow
inactive-account probes can't push the CLI past its request timeout;
they keep running and land on the next call. Older hosts strip the unknown field and keep
their prior no-refresh behavior; human output still skips the refresh.

Fixes #37256
2026-11-05 01:49:20 -08:00
Jinwoo Hong 0d696aef33 Let a finished worker keep messaging its coordinator (#38357)
* Let a finished worker keep messaging its coordinator

* Tell a finished remote worker why its coordinator is out of reach

* Let a finished worker's ask wait for its answer instead of starting a follow-up

* Share the assignee check, keep the finished lookup in dispatch-lookup, and fix review findings

* Match a finished terminal worker by its process too; cover resume after a follow-up
2026-11-05 02:42:50 -05:00
Neil 9bd6272fdf refactor(tooling): organize build, CI, and test owners (#38130)
* refactor(tooling): organize test runtime and maintenance owners

* test(tooling): preserve relocated runtime fixture dependency edges

* refactor(tooling): preserve xterm routing owner checks

* ci(tooling): include routing owner in sparse checkout

* test(tooling): preserve copied workflow dependency closures

* fix(tooling): normalize hashed JSON assets in release parity

* fix(tooling): distinguish asset aliases from literal references

* fix(tooling): frame normalized asset reference payloads

* fix(tooling): normalize decoded JSON asset references

* refactor(tooling): organize build, CI and release owners

* fix(tooling): align moved generator and workflow path contracts

* fix(tooling): update generated plugin bundle owner banners

* test(tooling): create relocated mobile verifier fixture directories

* test(tooling): copy headless detector dependency closure

* test(tooling): align native batch policy fixtures with owner path

* fix(tooling): link moved reliability command to historical evidence

* fix(tooling): preserve nested sandbox owners and canonical guide source

* fix(tooling): target release version owners in checkout fixture
2026-11-04 21:08:19 -08:00
Jinwoo Hong 9658ec48ad fix(automations): accept Pi model and thinking extra arguments (#38020)
* fix(automations): accept Pi model and thinking extra arguments

* fix(automations): keep Pi provider pins and refuse unpinned inline keys

* fix(automations): match Pi value options to its argument parser

* fix(automations): refuse Pi model overrides beside unscoped inline keys

* test(automations): cover Pi's last-provider-wins key pin

* fix(automations): refuse any Pi custom Command text with --api-key

* fix(automations): drop the Pi inline-key pin guard

Pi already sends an unpinned inline key to the chosen model's provider and warns;
the user typed both the key and the model, so Orca does not refuse it.
2026-11-04 02:36:51 -05:00
Neil 7bf0377072 refactor: place terminal and workspace contracts with concrete owners (#38061) 2026-11-03 22:49:34 -08:00
Jinwoo Hong 7854cb61b1 Delete the legacy orchestration takeover guide (#38013)
* fix(automations): say the run's worktree was deleted; document plain run-use recovery

* revert(automations): drop the deleted-worktree wording change (not reproducible)

* docs(orchestration): list Tasks on recovery and note run-use drops other Runs

* docs(orchestration): delete the legacy takeover guide; keep orchestration docs to the normal flow
2026-11-04 01:37:09 -05:00
Neil f33197523d refactor: group Codex transport trust and journal owners (#38023) 2026-11-03 20:45:04 -08:00
Neil d09519f0f1 refactor: group workspace and runtime contracts by defining owner (#38018) 2026-11-03 20:19:21 -08:00
Kelvin AmoabaandPr1p 2e3c8fb530 fix(notifications): clear acknowledged desktop alerts (#37974)
Explicit worktree reads and session acknowledgements share the existing desktop dismissal authority. Desktop and phone copies preserve transport, physical workspace and session/cursor identity; Linux retains dismissible notification handles after banners expire.

Mailbox consumption keeps its existing semantics.

Fixes #37328
STA-13409

Co-authored-by: Pr1p <zwq19980411@gmail.com>
2026-11-04 04:03:39 +00:00
Neil 926f8bad13 refactor: organize terminal and runtime contract owners (#38011) 2026-11-03 19:56:34 -08:00
Neil da96fadec3 refactor: organize source-control contract owners (#37990) 2026-11-03 19:12:25 -08:00
Jinwoo Hong f138493be3 fix(browser): a split tab create joins a browser pane already beside the caller (#38006)
* fix(browser): a split tab create joins a browser pane already beside the caller

* fix(browser): the joined page is the pane's visible tab

* fix(browser): a split with an unknown caller still splits beside the active pane
2026-11-03 21:30:03 -05:00
OrcaWinandOrcaWin e1edc018f2 test: remove 228 low-value test declarations (#38004)
* test: remove 228 low-value test declarations

* test: brace retained phone fixture branch

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-03 17:59:29 -08:00
Neil 2c03c4b989 refactor: organize agent status and lifecycle owners (#37961) 2026-11-03 16:36:54 -08:00
OrcaWinandOrcaWin f22231dc29 test: remove 28 low-value test declarations (#37972)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-03 16:01:49 -08:00
Neil d5f2a17cd2 refactor: group agent launch contracts under concrete owners (#37915) 2026-11-03 14:45:49 -08:00
Kelvin Amoaba 7f885c19a6 fix(skills): rename computer use to orca-computer-use (#37659)
* fix(skills): rename computer use to orca-computer-use

* test(skills): resolve rename fixture after main cleanup
2026-11-03 21:05:37 +00:00
OrcaWinandOrcaWin bd5110671c test: remove 74 low-value test declarations (#37887)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-03 11:33:25 -08:00
OrcaWinandOrcaWin 106f1376e9 test: remove 37 low-value test declarations (#37885)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-03 11:22:34 -08:00
OrcaWinandOrcaWin f0a02936ac test: remove 96 low-value test declarations (#37882)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-03 11:19:42 -08:00
OrcaWin 29079b567f test: remove 151 low-value test declarations (#37870)
* test: remove 151 low-value test declarations

* test: prune obsolete wall-clock test exemptions
2026-11-03 11:07:43 -08:00
OrcaWin a38acbe354 test: remove 64 low-value test declarations (#37863) 2026-11-03 10:08:03 -08:00
OrcaWin 31fb68b669 test: remove 47 low-value test declarations (#37860) 2026-11-03 09:56:05 -08:00
OrcaWin 783722049a test: remove 39 low-value test declarations (#37857) 2026-11-03 09:40:16 -08:00
OrcaWin 39d02ae0bc test: remove 49 low-value test declarations (#37856) 2026-11-03 09:25:28 -08:00
OrcaWin e7542a3ca1 test: remove 52 low-value test declarations (#37854) 2026-11-03 09:07:13 -08:00
OrcaWin e95b0ca056 test: remove 58 low-value test declarations (#37853) 2026-11-03 08:53:10 -08:00
Alonso AlmeidaandAlonso Almeida 3b91fe4971 fix(cli): forward OpenCode --method and --answer from account add (#37622)
Forward OpenCode login methods and form answers into private account enrollment. Reject missing repeated values before login and preserve literal arguments through the common Windows process launcher, with terminal input, JSON output and cancellation retained.

Thanks to Alonso Almeida (@Alonsojrr14) for the original implementation and follow-up fixes. Tracked in #37621.

Co-authored-by: Alonso Almeida <alonsojr1269@gmail.com>
2026-11-03 01:12:19 -08:00
Brennan Benson 5c4331e729 perf(linear): load nested children with parent pages (#37667)
* perf(linear): load nested children with parent pages

* test(linear): bound nested child prefetch at the output cap
2026-11-02 22:26:34 -08:00
Brennan Benson ec8b2e2055 Read one full Linear ticket for planning and plain tickets for queues (#37656)
* docs(linear): use plain ticket reads for queues

* docs(linear): preserve selected queue ticket identity
2026-11-02 22:23:28 -08:00
Neil 3a714906a0 plugins: keep status bar plugins' workers running while enabled (#37630)
A plugin with a worker and status bar items is now started when enabled and kept warm,
like a plugin with hooks, through one shared resident-worker predicate and warmer.
2026-11-02 19:03:21 -08:00
Kelvin Amoaba eb55a5a6d3 feat(browser): --expect-url refuses a browser command when the page is at another URL (#37575)
* feat(browser): guard page commands with an expected URL

* fix(browser): refuse an empty --expect-url and check it on dialogs and the forwarding desktop

* fix(browser): recheck the expected URL right before keys go out

* refactor(browser): drop duplicate session type, dialog alias and per-capability sidecar fields

* chore(browser): satisfy the changed-code gates for the expected URL guard
2026-11-03 02:11:23 +00:00
Kelvin Amoaba f4d89b94c9 fix(dsh): show DSH hooks as partial when a profile is missing the hooks package (#37446)
* fix(dsh): report hooks as partial when a DSH profile cannot load the executor package

* fix(dsh): name only the broken profiles and print hook detail for failing states

* refactor(dsh): fold the profile package check into the installed branch
2026-11-03 02:09:18 +00:00
Neil 45a29352ea refactor: group host storage and worker infrastructure (#37606) 2026-11-02 17:34:32 -08:00
Kelvin Amoaba 8c7fb98d87 fix(orchestration): let a coordinator reach its worker when that terminal is still bound to an older Run (#37548)
* fix(orchestration): reach a terminal that still coordinates another Run through its worker Dispatch

A terminal can stay bound to an older Run while it works a Dispatch in another.
send --to <terminal> --run <its Dispatch's Run> was refused with
recipient_run_mismatch, and run-current never mentioned the Dispatch.

* fix(orchestration): say which terminal can safely take an older Run
2026-11-02 21:17:34 +00:00
Max Hsu 4eaa12fef2 fix(cli): let worktree set --comment "" clear the comment (#37515)
`worktree set` read --comment through getOptionalStringFlag, which turns
an empty value into undefined, so `--comment ""` and `--comment=` sent no
comment field and the stored comment survived while the command reported
ok:true. Keep an explicit empty value for this flag only; the shared
helper and the RPC schema are unchanged.

Fixes #37464
2026-11-02 20:49:15 +00:00
Brennan Benson 34fa209fe1 fix(orchestration): native chats get each orchestration message whole instead of a check pointer (#28567)
* fix(orchestration): steer mail notices into a busy native chat's running turn

A native-chat coordinator's mail notice always queued as a card until the whole turn ended, so a
coordinator busy in a long command never saw its workers' reports. Agents that take a message
mid-turn (Claude, Codex, Pi) now get the notice at once; agents that would cancel their turn for
it (ACP) still queue it.

* fix(orchestration): drain mail that arrives while a notice is pending

* fix(orchestration): native chats get each orchestration message whole instead of a check pointer

Each mail message is sent to a native-chat agent as its own chat message,
with the sender, type, subject, body, payload and exact reply command, and
is marked read once the chat accepts it. Heartbeats are marked read, never
sent. Mail an unacknowledged check batch holds stays with that batch.

* fix(orchestration): keep the at-most-once gate's mail-lane assertions, exhaustive sender switch

* Preserve native mail compatibility and drain delivery backlogs

* Drain native mail with a finite ordered pass and scoped operation ownership

* Bound mail formatting and honor accepted queue handoffs

* Run the native mail tests that open SQLite in the Node runtime project

* Preserve live mailbox ownership and recover full reports by id

* Use a typed runtime client in inbox compatibility test

* Preserve historical mail evidence and scope the test clock

* Map historical structured-send evidence to the current test command

* fix(orchestration): settle mail handoffs per message and recover interrupted consumers

* Hold native chat mail until the chat is idle, as terminal mail waits

A mail send admitted into a running turn cancels that turn for agents that
cannot take a message mid-turn (ACP: Grok, OpenCode, OMP, Antigravity): the
second of two reports cancelled the first before the agent saw it, and the
first report cut off the turn carrying the person's answer. Mail now waits
while the chat is working or a prompt waits on the person, for every agent,
and goes out at the idle edge, one message per turn, oldest first.

* test: cover idle orchestration report turns

* fix: preserve independent mail authorization through grouped delivery

* fix: preserve routed mail identity and private inbox state

* test: bound mailbox query work on repeated delivery

* fix(orchestration): consolidate terminal mail imports

* Validate mailbox query rows and type delivery fixtures

* Keep host forwarders typed and inline single-use mail evidence reader

* Declare the mail handoff store method boundary

* Preserve mailbox contracts across typed boundaries

* Retain existing main cleanup row boundaries

* Fix mailbox handoff fixtures and helper mail transfer

* Name the mailbox fixture constructor type

* test: complete mailbox dialog pane identity

* Keep structured mail ordering and ownership current at claim

* Bound mailbox preparation and immutable cohort selection

* Consolidate structured mail contract fixtures

* Consolidate duplicate mailbox imports

* Fix mail handoff type contracts and deterministic test fixtures

* Repair journal forwarding and align mail contract fixtures

* Fix mailbox corpus message type inference

* Correct personal provenance in ACP backlog fixtures

* Correct ACP mail contract measurement and epoch wake fixtures

* Retain full ACP contract diagnostic arguments

* Restore reliability gate coverage and consolidate mail fixtures

* Preserve unknown alias release coverage

* Route native reports through the durable chat queue

* Preserve exact legacy mail holds in queue lineage proof

* Use ordinary queued messages for worker reports

* Use semantic queue and check completion for report delivery

* Record bounded queue recovery work and request cleanup proofs

* Preserve report creation evidence and bounded source wakes

* Preserve report source work and check ownership

* Use ordinary report acceptance and incremental original history

* Retire completed mail opportunities with their current owner

* Retire routed source debt and complete joined mail contracts

* Exercise Run typed peek through the command transport

* Require the queued report submission in creator coverage

* Restore database callback API and align queue contract fixtures

* Fix empty legacy tab selection in restart fixtures

* Keep relation heading assertions scoped to each report

* Native chats receive each orchestration message whole, through the chat's own queue

Each orchestration message to a chat session becomes one ordinary chat message carrying the whole
message, sent with the chat's queue like a person's message: it waits behind running work or a
question and the agent is handed one per turn. A per-message record keeps the send's operation id,
so a restart finds the card instead of sending twice; the message is marked read once the agent is
handed it, and a check that takes it first deletes the waiting card. A message too large for one
chat message keeps today's pointer to check. Terminals are unchanged.

* Test that chats get each message whole, queued like a person's message

* Repeat a report the agent may not have taken only after a later turn or /clear

A send the agent rejected or left unanswered stays unread for check and is handed over again only once
a later turn ran or a /clear replaced its context, so edges alone never restart an agent that fails on
every start. A send whose record a rewind dropped is sent again, and a send that throws is retried on
the session's next journal edge. Tests follow chats getting each message whole.

* Hand a chat orchestration mail only while it is still owed

A queued mail card now runs only while its message is unread in its mailbox and that mailbox still belongs to
the chat: the queue asks at handover and drops a stale card without a turn (abandoned or settled Dispatch,
Run taken over by another chat, mail a check or reset took). Cleanup after check, moves, run-use, abandon,
reset and worker release deletes those cards visibly and never holds the action up; mail still owed goes to
the mailbox's current owner, and Orca's own deletion is never read as the person's.

A send that may have reached the agent is never sent again; check keeps it. A send the agent proved it never
got is sent once more, under a new id, only after a later turn or /clear ordered after that failure. A send
recorded but never admitted is admitted under its own id. Each outstanding send is read by key, never by
scanning the chat's history.

A refusal no longer loses its retry when an edge arrives mid-send, and a coordinator refused for queue room
gets its mail when the queue frees room. A chat worker's follow-up now takes its short Task first and then
each moved message whole, with no check needed. The guide says a working worker gets mail when its turn ends.

* Let the chat's host answer what became of each mail send, and let the person's cards pass mail Orca cannot decide on

The chat's host now answers for each send by its id: the card first, then the send itself, then a gone card's handoff found by key, and only then the admission receipt, which alone can prove nothing was admitted. A receipt whose journal detail is gone is in doubt however old its id, so a renewed id can no longer send the same message twice. A rejected send is repeated once only after a different turn was actually handed over and accepted, or a /clear was made, after the rejection; the queue's admission cursor no longer stands in for that. No answer walks the conversation's history.

The mailbox reserves each send and stamps the message delivered in one write before the host call, so a crash after admission never leaves it selectable again. A refusal before admission releases that exact reservation; every retirement and release is checked against the current attempt, and a record an older build saved without a stamp is repaired as it retires. A person's Delete consumes an oversized pointer's mail too.

Who holds a mailbox is read from durable facts: a Run moved to a terminal, a released worker, another host or an ended chat makes a waiting card stale, so it is withdrawn without a turn and its mail released for the real owner. Only a fact that cannot be read holds a card; the person's own cards behind it go on, later mail stays behind it, and selection and the handover check use the same rule. When the owner can be read again the queue is woken. A Task or a person's edited card never opens the mail database. An explicit Send of such a card now says what happened.

Parked mail is indexed by chat, wakes only that chat's mail, ignores streamed tokens, and drops the chat's journal watch with its last mailbox. Canonical session identity is reused per session store revision instead of rebuilt from every record on each check. Main's account-switch worker test now reads "unread and still owed".

* Let the queue alone decide which card goes next, and wake a terminal given back its mail

The queue now owns one rule for what can be handed over next, installed once on each chat's queue and read by the drain, the final handover check, queue publication and scheduling alike. Mail whose owner cannot be read keeps its place; the first of the person's own cards behind it goes instead. Held cards stay held, a returned, paused or edited card behind it still stops the queue, and later mail, from any mailbox, stays behind it. The rule walks only the queue's live cards, never its history. When nothing can be handed over nothing is published as next, so the chat reads as idle and /clear works; when the owner becomes readable again the queue is published and looked at again. Choosing and publishing the next card only reads custody; settling a stale card stays with the handover.

Mail a chat gives back after its Run or worker moved goes through the runtime's own delivery, so a terminal owner is pointed at it. A chat's journal watch now lasts as long as it has mail parked, through its own redrives, so a publication that changes nothing the mail waits on starts no pass. Session identity is cached until a record joins, leaves or is cleared, not rebuilt after every admission. An explicit Send of mail whose owner cannot be read says Orca couldn't read the chat's saved state rather than that it restarted.

* Find the person's next card past undecidable mail by walking only as far as it must, and ask mail authority only once nothing else stops a send

* Say plainly when Orca can't confirm queued mail is still this chat's, and that the person can try again

* Let parked mail's own watch be the only journal subscription for mail, and stop saving a send fence nothing reads

* Count the queue's order reads with plain index getters instead of a reflected proxy

* Read saved mail sends column by column, and build test fixtures as the types they stand for

* Keep main's words for every other refused queued Send; only undecidable mail says its message wasn't sent

* Let replay read the queue's handoff links, keep the host's last mail answer where the type can see it, and drop the removed test from the send gate

* Keep the queue's possible next cards in order as each one changes, reuse the last pick until the queue moves, and look up a send by its id

* Ask whether one chat's tab closed instead of listing every open tab to find it

* Settle a mailbox's earlier mail only when something it waits on moved, republish a chat once per pass, clean up only the mail a check, abandon or move touched, and act on a chat's status only when it changes

* Date the scaling test's extra tabs by the coordinator's recorded lease instead of the wall clock

* Keep nothing in memory for a mailbox a cleanup finds with no owner and no send left, unless a pass on it is still running

* Ask about a report whose send threw before handing over newer mail, under the id it was reserved with
2026-11-02 12:08:01 -08:00
Brennan Benson 9df4559e37 Keep valid automation history when repairing a damaged profile (#37336)
* Allow profile repair to replace damaged automation history metadata

* Keep verified automation history when repairing its placeholder

* Test structural profile open and repair output for kept automation history

Schema verification no longer reads automation history metadata, so the
read-concurrency tests now assert that open succeeds without reading it and
that ordinary reads still keep snapshots consistent and refuse corrupt
metadata. Add output coverage for the recovery-required message, the
startup failure text (English and a translation) and the bundled CLI
recovery route printing kept and backup-restored sections.
2026-11-02 10:26:24 -08:00
Neil 36f17a04a7 plugins: Box layout container for components panels (catalog 4) (#37420)
- Box (ui.catalog 4, since 1.4.248): direction, gap/padding/paddingX/
  paddingY/margin on the gap scale, align, justify, wrap, grow, shrink,
  width/height/min/max (px up to 4096 or whole percents), columns,
  scroll, border (true or a tone), radius, background (theme surfaces or
  tone tints). Strict props: hex colours, CSS lengths and unknown props
  are dropped with a warning like other components.
- Renderer maps props to theme tokens through data attributes; sizes
  reach inline style only as validated px or percents.
- Typings, docs, skill references, gallery Layout tab; orca/testing
  finds Boxes and summarizes danger or warning Boxes.
2026-11-02 01:05:57 -08:00
Neil d8a66e41c9 fix(wsl): name the stopped distro, not its raw hold code, wherever a held terminal is shown (#37380)
The terminal error banner and a paired host's held pane showed
terminal_held_wsl_distro_*:<distro> as is; the banner now swaps either
the code (older hosts) or the English sentence (newer hosts) for the
localized copy, and drops the issue link for it. A held start that
arrives as the sentence now gets the Start card too. The CLI names the
distro for an older server's raw hold code and for an unavailable WSL
folder. The banner's footer reports the shell whose spawn failed
(wsl.exe, say) instead of the client's default shell.
2026-11-01 23:17:46 -08:00
Neil cb031c4517 fix(plugins): merge disk writes into a custom editor's unsaved edits (#37343)
* fix(plugins): merge disk writes into a custom editor's unsaved edits

A write to the file on disk while a custom editor tab had unsaved edits
never reached the editor: the buffer kept the edits, Orca showed its
Reload/Overwrite banner, and the session's merge never ran. Now a frame
whose document session has merge announces it (editor.merges), and Orca
sends it the new disk text with the text the edits started from
(editor.document with ancestor). The session merges, posts the result,
and the tab stays unsaved with it; the banner is skipped. Without merge
the banner decides as before.

* test(editor): an explicit save under the changed-on-disk banner keeps the edits

* fix(plugins): make the outside merge exact, and narrow it to where it is

- The host settles a merge only on the session's edit made against the
  merge's own document version, and always commits that result to the
  buffer (even when it equals the disk text); silence past the 1 s flush
  deadline, a remount or a throwing merge leave the banner and the
  suspended autosave in place.
- Orca stamps exactly the disk snapshot the acknowledged merge used and
  records it as the next ancestor; a write that landed meanwhile puts the
  conflict back for its own merge.
- The ancestor is the tab's disk text recorded while clean and advanced on
  acknowledged merges, and must match the tab's disk baseline.
- Only a local file in one merging editor view, with no other tab on its
  buffer, takes this path; anything else gets the banner.
- Frame events keep reaching their handlers after the merge capability.

* fix(plugins): move nothing on a failed disk merge; advance the saved text on success

A merge that throws now leaves the session's document, baseline and
version untouched, so the user's next edit goes out against the old
version: Orca refuses it and keeps the banner instead of taking it as the
merge's acknowledgement. After an acknowledged merge the tab's saved text
moves to the disk text it used, so typing back to the old ancestor no
longer looks clean.

* chore(plugins): regenerate the testing bundle on main
2026-11-02 06:35:01 +00:00
NeilandClaude 5846caf2ba plugins: editor.save.before hook (format on save, or refuse the save) (#37347)
* plugins: editor.save.before hook (format on save, or refuse the save)

Explicit saves of text files from an editor tab run plugins' editor.save.before
in main before the write (local, SSH, WSL and folder workspaces all save through
that one renderer path). A plugin can return changed text or deny with a reason,
shown in the save error. The buffer takes the hook's text only if it is unchanged
since the hook started; edits made meanwhile stay dirty. Autosave, restart saves
and bytes documents are not hooked, and with no live plugin listing the hook the
save path adds no await.

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

* test(plugins): editor.save.before text reaches the visible Monaco model

The hook writes its text into the tab's draft, which reaches the model through
the same content-sync bridge as Reload from disk. A model-level test covers the
formatted text showing, the next keystroke editing it, and edits typed during the
hook staying in the model.

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

* plugins: editor.save.before review fixes: flush held typing, update the surviving view, keep the denial

- After the hook answers, pending view text (rich Markdown's serialize timer) is
  flushed before deciding whether the buffer still holds the hook's input.
- The hook's text goes to whichever view of the buffer record is still open, so
  closing the saving view keeps a sibling view in step with disk.
- The save-request bridge passes Errors through whole, so the toast shows the
  plugin and its reason instead of a generic failure.

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

* chore(plugins): regenerate after rebasing the save hook on main

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-02 06:19:50 +00:00
Neil 60e25bde45 feat(plugins): make the editor template the rich-editor recipe (#37349)
orca plugin create --template editor wrote an inline-script HTML editor
whose extension came from the folder name squashed to 12 letters. It now
writes the recipe: editor/main.ts (the view), editor/sync.ts (the
document session with a stand-in text merge), editor/sync.test.ts (a
mockEditorHost test of an outside write merged during a save), a
tsconfig on the generated typings, frame isolated, engines.orca
>=1.4.248, and extension .<id>. It passes plugin check and plugin test
as generated.
2026-11-01 22:04:31 -08:00
Neil 999160b3db feat(plugins): commands[].replaces lets a mod take over a built-in action (#37316)
* plugins: commands[].replaces lets a worker command take over a built-in action

A worker command with replaces: <action> (the declarative action list,
engines >=1.4.248, needs main) runs in place of that built-in from its
shortcut, plugin aliases and the sidebar menus; a failed or silent (2 s)
worker falls back to Orca's own. The install screen names each replacement,
the plugin page has a per-action switch (settings.pluginReplacementsOff), and
when two plugins replace one action the one installed first wins and the
other's log says so. Update review counts replaces as new access.

* fix(plugins): narrow replaced action ids before looking up their titles

* plugins: harden command replaces after review

- Consent includes the replaced actions, so adding replaces to a dev folder
  needs a new approval; CLI approval and update review name each takeover.
- Shortcuts main intercepts (Tasks, Workspace Board, history), search with a
  selection and floating maximize now go through the replacement too.
- A worker that only starts after the 2 s fallback no longer runs the
  command as well: main refuses to start it past the deadline.
- A workspace-only command does not replace an action without a workspace.
- An update keeps the plugin's first install time, so it keeps its takeover.
- Drop the commands.run promise until Orca offers it.

* plugins: commands.run always runs the built-in, never a replacement

A5b's commands.run dispatches with the 'plugin-host' source; the app
dispatcher now builds handlers that run Orca's own action for it, so a
plugin that replaces an action and calls commands.run cannot loop. Docs and
schema describe wrapping the built-in with commands.run; regenerated.
2026-11-01 21:59:27 -08:00