Pad Linear CLI and project-list columns using terminal display width (wide CJK/Hangul cells as 2 columns, combining marks and ZWJ sequences aligned to Orca's Unicode11 xterm provider) while preserving terminal-safe line sanitization.
Refs #11883
Co-authored-by: BaeTab <bhwoo48@gmail.com>
The orchestration skill guide and reference examples hardcoded --agent codex, leading coordinators on hosts without Codex installed to fail at agent_readiness. Replace hardcoded worker-start agent ids with <agent>, document how to pick an agent id across shared vs remote/WSL/--on execution hosts, and regenerate bundled skill guides.
Fixes#30495
* fix(orchestration): tell the coordinator when a worker is lost
A worker that could no longer run its task sent no mail: a failed start,
a person closing its pane, tab or chat, or a terminal gone after a restart.
Each now sends one "Worker lost without reporting" alert through the
turn-stop report, with its cause, last output and any leftover workspace.
An unexpected exit and a lost Codex app-server use the same path. An exit
or loss says the Dispatch is closed as failed and gives the retry command.
Failure text in the alert is redacted like terminal output.
The coordinator's own worker-stop stays silent, locally and on a paired
server. A finished turn is not reported when that turn's worker_done was
rejected; later turns still are. worker-read and worker-show say
"never started" for a start that never got a terminal.
* fix(orchestration): a lost worker's restart command names its Task id and suits its Task's state
- The command named the Task's label, not its id.
- Restart recovery puts the Task back to ready, which --retry-of refuses:
the command is a plain worker-start then.
- worker-show does not call a paired server's failed worker "never
started": its record carries no terminal details.
* test(orchestration): import the turn-stop report after main's test cleanup
* fix(cli): chat wait checks the chat's work state instead of reading its history every second
`orca chat wait` and `orca chat send --wait` polled `agentSession.history` once a second only to
learn whether the chat was still working. Each poll made the host build a transcript page, scan
every retained item twice for the running turn, and send the newest reply's full text, all
ignored by the waiter.
The host now answers `agentSession.workState` with just the facts a wait decides from (working,
a waiting question or approval, queued ids, the next queued send, the fence), and the journal's
running turn comes from its existing per-row turn index instead of a scan. The CLI polls that
read and falls back to history pages on hosts without it. The final transcript read is unchanged.
* test(cli): type the chat wait host test without assertions
* docs(cli): say what a work-state check skips, not that it does no history work
* test(cli): pin the chat wait's exact final reply and its single history read
* docs(cli): name the scan a work-state check skips
* ci: typecheck the chat wait host test with the cross-process test project
* feat(orchestration): deny a worker's permission prompt, and say when mail is held
A chat worker that stops at a permission prompt now escalates with the prompt
itself as structured data (approval id, state, worker, summary, allowed
actions). The coordinator can deny it with a reason through
`orchestration deny`; the worker carries on and gets the reason as mail.
Only a person can allow a prompt: the answer method decides "person" from
the transport, never from params. The stop report keys one escalation per
approval and sends one closing line when it is answered, and no longer tells
the coordinator that `orchestration send` answers a prompt.
`orchestration send` now warns when the delivery gate would hold the mail
right now (an open prompt, a blocked status, typed text), and says delivery
state is unknown for a worker on a paired server.
* fix(orchestration): only the desktop app counts as a person for worker approvals
A paired device can carry a remote CLI, so it is treated as an agent: it can deny with a reason but never allow.
* fix(orchestration): approval answers and held receipts follow the real gates
- A same-option answer counts as Orca's only when Orca recorded it; a retry returns the same
receipt with no second reason mail.
- An unreadable chat is not a closed prompt: the answer refuses, and the closer keeps watching.
- A closing line tells a reason only when it went to the worker as mail.
- The terminal held receipt prints the delivery gate's own refusal; the chat one prints what the
pointer's admission and queue gate would do (not attached, refused, or behind an open prompt).
* fix(orchestration): read the held receipt only after the mail is stored
An await before the insert let a worker settle meanwhile, so the mail could land on a settled
Dispatch after its follow-up scan. The closer also removes only the approval map it read.
* fix(orchestration): tell the coordinator not to block on a worker's permission prompt
The approval escalation now says the worker is waiting for permission, tells a chat
coordinator the user has been shown Allow/Deny (a terminal coordinator: a person must
answer it in Orca or the worker), asks it to carry on with other work and not message
the worker until the answer arrives, and offers deny only as the way out when the
prompt is holding up the task. The guide and CLI docs say the same.
* fix(orchestration): a paired coordinator without an Orca session id mails a deny reason from its Run
* feat(orchestration): answer a Claude terminal worker's permission prompt
A worker pane's PermissionRequest hook now waits for Orca's answer, so the coordinator can deny
it with a reason (the worker continues) and a person can allow it. One record per waiting hook,
keyed by Claude's prompt and tool call; it is answerable only while the hook waits and the dialog
is on screen, and anything else gets `{}` as before.
* test: annotate the fake screen instead of casting
* test: wait on the hang-up instead of sleeping
* fix(orchestration): claim a terminal answer only from what Claude shows
An answer is written only while a caught-up screen still shows the dialog
in the same process run, and claimed only once Claude shows it applied: the
hook's deny line for a deny, no other close for an allow. A Yes, a No or the
2:00 auto-block that wins the race is refused and named from the screen.
A hook that hangs up is not an answer: with the dialog still up the
coordinator is told a person must answer it in the worker's terminal.
A PermissionRequest entry the user made async stays async: it prints {}
first and never waits for a decision.
* fix(orchestration): name a terminal prompt's close from its tool_result
The screen could show an older prompt's close, so who answered is now read
from the tool_result Claude's transcript records for that tool call: Orca's
own deny text credits Orca, the user's No and the 2:00 safety-check block
name themselves, and a run names an allow. Hook events cannot say this: a
deny or a No fires no PostToolUse. The screen only says whether the dialog
is still up before a write, and a PostToolUse seen mid-answer is kept.
* fix(orchestration): read a prompt's tool_result without blocking main
The transcript read is async, reads only its tail, and skips any path that
is not a regular file, so a FIFO or device cannot stall the main process.
A closed prompt still awaiting its result gets one last read when the lead's
turn stops, so a result written late still names the close.
* feat(native-chat): answer workers' approvals from the coordinator chat
A worker's open permission prompt appears as a card at the end of its coordinator's chat, drawn
from the escalation payload as soon as it is stored. The person allows or denies it there; the
card's buttons answer the worker's own prompt over the desktop app's IPC, so only a person can
allow. Once answered, the card turns into a receipt saying who answered.
* fix(orchestration): read a terminal prompt's countdown when it is first escalated
* refactor(orchestration): give a terminal prompt's hold state its own module
* fix(native-chat): let a worker's approval card answer, and drop it once it lapses
The window's runtime calls never carried the orchestration contract
version, so the card's Allow and Deny were refused as an obsolete client.
The renderer ships with its main process, so desktop IPC states the current
contract. An open card whose agent's own countdown has passed, with no
closing message (the app restarted while it was open), is no longer shown.
* test: say why the desktop fence test's runtime stub is enough
* fix(orchestration): a chat worker's approval asks to allow its tool, like a terminal worker's
* fix(native-chat): pause the approval countdown while the window is hidden
* chore(i18n): protect the approval card's worker line copy
* fix(orchestration): close a terminal prompt's card as soon as Orca can't answer it
When the dialog leaves without an answer through Orca, the closing line is
published at once, so the coordinator's card becomes a receipt; a tool
result that arrives later adds a second line naming how it closed, without
waking the coordinator. On startup, open terminal prompts left by an earlier
run are closed the same way, since their holds lived in memory. A Claude
terminal card's reason is the warning Claude prints under the command.
* fix(orchestration): keep the dialog-warning patterns ASCII for the orcad bundle
* fix(native-chat): say when a deny reason reached the worker as a separate message
A coordinator's deny reason for a chat worker whose prompt takes no message is sent
as mail. The receipt showed it the same as a reason that went with the denial, so it
now labels it 'Reason, sent as a message'.
* chore(native-chat): follow main's moved window-activity and agent-session modules
* fix(orchestration): only Orca's own reports draw approval cards, and every card closes
- Cards and the startup sweep read approvals only from rows whose id is the stop report's own
stable id for that approval, through one shared parser; a worker's send cannot draw a card.
- A chat worker's card closes as soon as its own chat answers it (a journal watch replaces the
turn-edge check), when an answer finds the prompt already gone, and after a restart.
- A terminal coordinator is told nobody was shown the prompt and to tell the user; the
terminal-only close asks the same and goes out as an escalation.
- A chat coordinator's line names only the answers its card offers; a prompt with none is a
plain prompt with no card.
- A person's Deny on a chat worker mails no extra reason.
- A record a quit or budget end closed stays closed.
- One closed-approval builder; `waitingOn` becomes `awaitsReply`.
* fix(orchestration): a failing read cannot hang an answer, fail a stored send, or fail the database open
* refactor(orchestration): add the held-send line in send-delivery-hold, keeping send-methods under the size cap
* test(orchestration): read the worker's mail with a schema, not a cast
* fix(orchestration): an open approval stays visible and closes even behind many closed ones or a missing database
* feat(orchestration): records, import and settlement for workers a paired server owns (inert until B5)
* fix(orchestration): name the re-pair when a closed link refuses a send
* feat(orchestration): offline reads of workers a paired server owns (inert until B5)
worker-show from this Orca's record when the server can't be reached, labelled
with the server and when it last reported; remote rows in worker-list named by
server; unreachable failures said in the server's terms, apart from the
server's own unknown outcome.
* fix(orchestration): remote rows share the page limit, label re-made pairings, and say what the record's time means
* fix(orchestration): keep remote rows in every page's total, date the record by state only, and retry only by request ID
* chore(orchestration): annotate the remote count query's row type
* test(orchestration): check CLI views of remote workers at the CLI layer
* docs(orchestration): say remote rows get their own page limit
* feat(orchestration): run commands about a paired server's workers there, and switch new pairs to it
* feat(orchestration): offline show and server-named failures for forwarded commands
* fix(orchestration): forwarded start timeout, receipt Run and stop key in the caller's terms
* fix(orchestration): forwarded answers name this Orca's Run
* fix(orchestration): a remote worker's question is answered only by its Run's coordinator; tests for the forwarder
* fix(orchestration): a start answered after its Run was reset says so
* fix(orchestration): refuse a chat session terminal before asking any server; test the late start after a reset
* test(orchestration): lint
* fix(orchestration): review fixes for the forwarder: retry-of stays local, legacy retries stay legacy, unknown outcomes stay fenced, refused starts leave no Task
* chore(orchestration): no type assertions in the forwarder
* fix(orchestration): a start answered after a re-pair frees its Task
* fix(orchestration): worker-show of a worker whose pairing was re-made gives this Orca's record
* fix(orchestration): a retry with --on names the server's Task instead of resending its spec
* fix(orchestration): a read about a remote worker gives up within seconds on a sleeping server
worker-show then answers from this Orca's record, as it does for a server that is off. Changes keep their longer wait.
* fix(orchestration): a refused remote start keeps the Task it created, failed
A local start that fails after creating its Task leaves it failed; deleting it here left any dependent added while the start waited pointing at nothing.
* fix(orchestration): worker-show of a remote worker reads this Orca's record, never its server
Show answers at once whether the server is awake, asleep or off, and agrees with worker-list.
Its note says when the record is from and what the pull loop last heard from the server; a
prompt wait already arrives as the server's mail. worker-read stays forwarded with its 5 s cap.
* refactor(orchestration): drop the orphaned-start lookup; the server's queue item adopts a lost start
A start whose answer was lost stays reserved until the server's dispatch-insert item names its
Dispatch, which adopts it. The 30 s dispatchShow lookup and its two placement columns repeated that.
* fix(orchestration): a stop or abandon the server does not answer settles the Task here at once
As a local stop does, the Task goes blocked so it can be retried, and the stop stays owed with its
count. The first result stands: a later state from the server changes only the attempt's record.
* fix(orchestration): task-update on this Orca's own Task applies here, by the local rule
A Task placed on a paired server is this Orca's; its update goes through the ordinary owner, which
refuses it while the worker there holds it, exactly as for a local worker. Stop first: an
unanswered stop settles the Task here at once. Nothing is forwarded to the server.
* fix(orchestration): a link that can no longer answer fails the Tasks it held, with the reason
When a re-pair closes a link, or its server is removed from this Orca, each Task a worker there
still held fails here through the ordinary Task half ("The pairing with devB was re-made. Its
worker may still run there."), and its placements go. Before, the Task stayed dispatched for good.
* fix(orchestration): a paired Orca's reads on this server are no longer narrowed to its Run
* test(orchestration): a lost start is never looked up on its server
* fix(orchestration): review fixes for the remote Task settlements
- An abandon the server does not answer stops nothing, as a local abandon: it settles the Task here
and owes no stop, with abandon's own receipt.
- A link a re-pair or removal closes tells the Run's coordinator about each Task it failed, as a
local worker failure does, naming the server in the reason.
- An unreleased database drops the placement lookup columns and gains task_settled_here on open.
- A failure settling a removed server's Runs no longer ends the pull loop's bookkeeping.
* fix(orchestration): retries of a remote attempt follow the local rule, and owed stops go out on reconnect
A retry here may follow the Task's attempt on a paired server once it settled there or was
abandoned here, exactly as a local retry follows a local prior; an unproven stop, like a local
stop_unknown, leaves nothing to follow yet. When a server answers again, every stop and cancel
owed to it is due at once through the existing resend, so a retry there follows the proven stop.
* fix(orchestration): a re-pair settles held Tasks at once, lists the Run there, and refuses reuse of its Tasks
- the pull loop closes links of a changed pairing, so their held Tasks fail without a call through them
- worker-list --on lists a Run's workers by its server Run even after its link closed
- a start --on of a Task placed through a closed link is refused here, naming the server
- the server's restart recovery readies its Task, and this Orca follows as the local rule does
- a closed link's note gives why it closed and the server's recorded name
* fix(orchestration): review fixes for the re-pair settlements
- worker-list picks the Run's latest link a server Run answered for, so a refused start's new link hides nothing
- a start answered after a re-pair keeps its placement, so the Task's next start there is refused here
- worker-list --on errors read in this Orca's terms, as other forwarded reads do
* fix(orchestration): a re-pair fails a Task a stop left blocked, and a reset still fails a readied Task
- a closed link also fails a held Task an unanswered stop blocked, which nothing can prove now
- a server reset's removal fails the Task even after its recovery readied the server's Task
- a closed link keeps why it closed when a later queue item cannot be read
* fix(orchestration): a re-paired Run's worker-list says so plainly, with no new read path
- worker-list --on for a Run whose link a re-pair closed names the re-pair instead of runtime_error or an empty page
- a Task placed through an earlier pairing still starts on another server
* fix(orchestration): a re-made pairing's refusals keep their own error code
server_pairing_changed passes through RPC instead of becoming runtime_error.
* fix(orchestration): a re-pair fails a blocked Task only while its stop is owed
A Task a proven stop or an abandon blocked stays blocked; only an unanswered stop, which nothing can prove now, fails it.
* fix(orchestration): a refused start writes no link, and a re-paired Run's list tells a reset apart
- the refusal of a Task an earlier pairing placed runs before any link is written, so the Run's list still names the re-pair
- worker-list decides from the Run's newest link: closed says re-paired, a reset lists nothing, a link closed mid-call says re-paired
* test(orchestration): a paired Orca reads another Run's work on this server, and still cannot change it
* feat(browser): move extensions out of Experimental into Settings › Browser, on by default
The old experimentalBrowserExtensions key is retired on load so profiles that saved the old false default start with extensions on.
* test(startup): mock extension startup in the ready-phase identity test
Extensions now default on, so ready-phase startup installs extension support, which this browser-identity fixture's Electron and store fakes don't cover.
* fix(recipes): warn which credentials recipe scripts inherit, add opt-in passEnv allowlist
Recipe lifecycle scripts run locally with Orca's full environment. Keep that
default (provider CLIs and git auth rely on it) but name the credential-like
variables in Settings and let a recipe opt into passEnv so only listed
variables plus a safe base set reach its scripts.
* fix(recipes): fail closed on a malformed passEnv instead of dropping the recipe
Dropping the recipe let a stored snapshot or a same-id plugin recipe run with
the full environment. Keep it with an empty allowlist and a diagnostic, match
base variable names exactly outside Windows, and make the warning copy apply
to any recipe source.
* fix(recipes): import user-agent-platform from its new app-shell location
New profiles default artifactSharingEnabled to true. Existing users are
unchanged: stored settings win over defaults on load, and a stored profile
saved before the key existed loads as false instead of inheriting the new
default. The gate still requires an explicit true, sign-in is still
required, and web clients still mirror the host (their local fallback no
longer inherits the desktop default). showArtifactsButton is unchanged.
* fix(native-chat): show the page a browser run drove, not another chat's
* fix(browser): run each queued agent command in its own RPC call
* fix(native-chat): once a chat claims its browser activity, ignore unclaimed activity
* feat(cli): read and message agent chats with orca chat list/read/send
Carried over from #33115 (squashed onto current main; conflicts with chat rename resolved).
* feat(cli): wait for a chat to settle, read text from stdin, refuse paired hosts
chat send --wait and chat wait poll the history's working flag until the
chat is idle or waits on a question, keeping a queued message pending until
it runs. chat read is one history fetch and returns a cursor. Unattached
and paired-host refusals say what they mean.
* fix(cli): settle a held queued message, skip subagent rows, resolve chat list --worktree
* fix(cli): show chat errors, keep waiting through queue handoffs, return the whole settled turn
* fix(cli): settle any queued message the host will not send, show grouped questions and only answerable prompts
* test(cli): drive chat tests through a real client and fake timers
* fix(cli): describe chat --session, --wait and --state in command help
* fix(cli): report chat wait in chat list's states, reject unknown --state, flag truncated reads
* docs(cli): say chat wait settles on the chat's own turn; no truncated flag on held
* fix(cli): chat rename help asks for a session id, not a handle
---------
Co-authored-by: YangNuoCheng <42427439+YangNuoCheng@users.noreply.github.com>
Prints the notes the user left on a browser tab and has not sent, the same text the tab's Copy button gives (--json returns them). Reads the saved session, so it works for closed-and-restored tabs; SSH hosts reach it through the desktop browser bridge. A page drawn by a paired desktop reports that its notes stay there.
* feat(orchestration): a paired Orca as a Run's coordinator on the server it placed work on (inert)
The server half of remote-owned workers. A paired Orca's call names one of its
Runs; the server admits it as a peer caller kind, writes that Run at frame
receipt, and holds it to the one access check. Its workers' mail and state
queue home under a sequence no reset reuses. Nothing sends the envelope until
the coordinator side ships, so this changes nothing today.
* fix(orchestration): reserve the peer address, keep conversation kinds apart, queue a correction once with its result
* fix(orchestration): hold back a corrected Task's change whatever its latest attempt; rotate pulls in a stable order per database
* chore(orchestration): typed field read, cast rationales, a wake test on fake timers
* fix(orchestration): a peer's receipts per conversation, its sends only into its Run, a page that fits every conversation, pending adopted Tasks keep their gate
* fix(orchestration): a peer's follow-up places where its worker ran
* fix(orchestration): a peer's current/new-child start gets the --on placement refusal
* feat(workspaces): run setup and archive scripts for folder projects
Folder projects get the setup and archive scripts git projects have:
creating a workspace runs setup in a Setup tab, and removing one runs
archive first. The script sees the workspace's name and id, so
`orca worktree create` inside it attaches each new worktree to that
workspace, however the workspace was created.
- Folder creates (desktop IPC and runtime) prepare setup through the
shared setup prep; runtime creates start it with the worktree terminal
startup, so Setup-before-agent ordering matches.
- Runner files live in <folder>/.orca, one fresh file per launch, removed
with the workspace.
- Only the host whose catalog holds the folder reads its orca.yaml or runs
its scripts; a setup problem becomes a warning, never a failed create.
- Shared orca.yaml setup with no approval from an older client is skipped;
ask/inherit never refuses a folder create.
- No orca.yaml default tabs for folders, since every workspace shares the
directory.
- New capability worktree.folder-setup.v1 gates the Settings section on
runtime hosts; the composer, Settings and trust prompt reuse the
existing setup surfaces.
* i18n: add folder workspace hooks strings
* chore: drop the runner's sync-fs baseline and an array cast
* fix(workspaces): close review gaps in folder project setup
- Whole-project trust sends an explicit run for folder creates the
policy would run, since it carries no content hash.
- Folder setup skips file access for a skipped setup and never starts a
stopped WSL distro for a create nobody started; removal does the same.
- Runtime folder creates return the trust mismatch, so the window re-asks.
- The composer hides folder setup controls on hosts without
worktree.folder-setup.v1 and keeps their old explicit skip.
- Hook checks read a folder only on the host that owns it.
- Git archive hooks get the removed workspace's id; WSL hooks blank
inherited pane identity too.
- Runner files are written through the drive path WSL needs for its
drive mounts, and kept out of git status with .orca/.gitignore.
- The CLI's older-host warning covers --agent creates and --json output.
* fix(workspaces): wait for the folder setup capability and read orca.yaml once
Create now waits for a runtime host's folder-setup answer instead of
sending Skip while the probe is pending, and runtime setup reuses the
parsed orca.yaml when merging effective hooks.
* fix(workspaces): keep a failed folder setup probe unknown and retry it on create
* fix(workspaces): share folder setup capability answers with the composer
* fix(workspaces): re-ask the host for folder setup support on every create
* fix(settings): read orca.yaml for folder projects and use workspace copy in hook rows
QA found Settings reporting no orca.yaml for folder projects while the
composer ran that script, and the inner hook rows still said worktree.
* fix(folder-workspaces): open one Setup tab for an instant folder create
* fix(workspaces): run setup when a created workspace has only editor tabs
* perf(folder-workspaces): per-workspace runner dir, bounded setup answers, one archive config read
* fix(folder-workspaces): retain setup capability for active consumers
* fix(folder-workspaces): match hook search to workspace descriptions
* fix(i18n): drop obsolete hook search descriptions
* test(folder-workspaces): follow relocated setup trust modules
* feat(plugins): add editor.readTypography and editor.typography.changed
Plugins that render code next to Orca's editor had to open the private
profile database and reimplement Orca's font rules to match it. Host API 1.6
adds editor.readTypography (no capability; worker, panel and editor frames):
the font family and CSS stack, size with editor zoom, weight, line height in
px, ligatures, word wrap and minimap that the file editor resolves now.
editor.typography.changed carries the same values after a settings write or
an editor zoom changes them; it is the first event that needs no capability.
The pure resolution (editor typography, editor zoom, monospace font stack)
moves to src/shared so main and the renderer use one implementation.
* fix(plugins): keep editor typography resolution from throwing in main
A hand-edited profile with a non-string font family made the shared resolver
throw, which the main-process watcher would surface at startup and on every
settings write. Font values are now type-checked, the watcher catches and
logs, and it reads live settings so a write without listeners cannot leave the
event payload stale. Over-long font families are cut to the schema bound
instead of failing every read. Regenerates the testing runtime.
worker-start defaulted --setup to run, so new worker worktrees ran the
setup script even when the project had setup turned off. Without an
explicit --setup, a worker now skips setup when the project skips it by
default; run-by-default and ask keep running it as before. Remote
workers resolve this on the host that owns the project.
* docs: load Orca browser guidance for ordinary web tasks
Extend the Orca CLI skill description to include local and external page opening, reading, testing, and captures while working in Orca. Preserve explicitly chosen browser tools and the Computer Use boundary. Regenerate discovery/install bytes and append the new digest.
Fixes#39880
* fix: route existing Edge windows to desktop browser control
* docs: preserve configured desktop-control tool precedence
* docs(skills): scope orca-cli browser trigger to page work and keep the Computer Use rule
Drop "reading" so doc lookups stay on fetch tools, say plain HTTP/API calls don't need the skill, and restore the original Computer Use sentence and guide body, which the issue didn't ask to change.
* docs(skills): list Edge among existing browser windows in the orca-cli guide
The wider page trigger makes "screenshot my open Edge tab" load orca-cli, and the guide named only Chrome and Safari as windows that go to desktop control.
---------
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
* feat(orchestration): mail agents on a paired server with send --on, replies come back by themselves
* fix(orchestration): gate --on on the carrying Orca, ack retried deliveries, refuse payloads and federated workers
* chore(orchestration): annotate peer-mail row casts and drop a wall-clock wait in its test
* chore(orchestration): name mail-between-servers codes server_mail_unsupported and mail_requires_server_pairing
* docs(cli): list --on in the orchestration reply usage
* fix(orchestration): name --environment, the flag on main, in agent mail refusals and the guide
* chore(orchestration): mark the two deliberate agent-kind branches mail between servers needs
* docs(cli): leave --on out of the reply usage; it is accepted only to refuse it
* fix(orchestration): keep peer conversations to peer ids, survive resets and re-pairs, keep pulling on a registry error
- A server takes only peerconv_ conversation ids, so a paired computer cannot name another Orca's dispatch in the relay.
- A replayed reply after a mail reset is acknowledged, not retried forever; reset tasks keeps replies waiting to be pulled.
- A re-paired server starts a new conversation instead of refusing every later send and reply.
- A failed registry read keeps the pull loop retrying.
- Drop the two ast-grep-ignore lines that only #40193's rule needed.
* fix(orchestration): worker-start --on runs on the caller's own Orca, like send --on
An inherited ORCA_ENVIRONMENT sent worker-start --on to that server, so the
--on command the agent refusal suggests did not work. One rule now keeps
send, reply and worker-start with --on on the caller's own Orca.
* fix(orchestration): refuse reply --on on both sides of a conversation between servers
The side that opened the conversation still took --on when it named the right
server; the reply usage says --on is accepted only to refuse it.
transcribe-cpp is now the only on-device engine on every platform, so
the sherpa-onnx packages, their packaging (extraResources, the darwin
libonnxruntime prune, the native-variant assert and the Linux libstdc++
exemption), the sherpa recognizer in the speech process and the
per-model engine choice all go. Hotwords are written as plain terms.
* feat(speech): run GGUF models on transcribe-cpp, falling back to the CPU
The speech host child can now load a second engine. A model whose files
are GGUF runs on transcribe-cpp (Metal on Apple silicon, Vulkan on
Windows and Linux, CPU otherwise); everything else stays on sherpa-onnx,
which remains the only engine on Intel Macs.
A GPU that fails to load, errors, stalls for 25 s or crashes the process
moves the dictation to a CPU-only process (TRANSCRIBE_BACKENDS=cpu) that
replays the audio the GPU had not decoded yet, so no words are lost or
repeated. A GPU that crashed or would not load is remembered per
transcribe-cpp version and OS release, and voice.speechGpu = 'off' keeps
it on the CPU.
Packaging copies transcribe-cpp, koffi and the target's native package
into resources/node_modules outside asar, fails when a target's package
is missing, and ships the MSVC runtime beside transcribe.dll on Windows.
No catalog model is GGUF yet, so nothing runs on transcribe-cpp until
the catalog change that follows.
* fix(speech): keep the speech queue running after a failed task, and drop audio frames after a discard
* fix(speech): keep the engine's file reads off the main thread's hot paths
The engine lookup and the GPU failure marker are read once per process
instead of on every dictation start and mobile catalog request, the marker
is written asynchronously, and the child reads the hotwords file with
fs/promises. The baseline moves the existing engine presence checks from
stt-worker-paths to the shared package table and adds the once-per-process
marker reads.
* feat(plugins): add workspace.rename and project names in workspace.list
Plugins that name workspaces had to read Orca's private runtime token and call
worktree.set over the runtime socket, bypassing capability consent. workspace.rename
(workspace:write, worker only, host API 1.5) does the same update as a sidebar
rename. workspace.list rows gain the project name so plugins can prefix names
without reading the runtime's repo list.
* fix(plugins): harden workspace.rename against twin folders and hidden characters
Folder renames require a unique folder id, so twins on two hosts are not both renamed,
and fail when no folder has the id. Names refuse C1, bidi and zero-width characters,
which could make a label read as another workspace's name.
* fix(plugins): workspace.rename matches a sidebar rename for folders and reports kept names
A folder rename also cancels a pending first-agent-message rename, so the automatic
title cannot replace the plugin's name. A rename Orca does not apply (during a WSL
move) is a conflict instead of a silent success. workspace.list's project is optional,
so mocks written for host API 1.4 still validate. More invisible characters are refused.
* refactor: move atomic publication to its filesystem owner
* refactor: group shared browser definitions by feature
* refactor: bind proxy process and session contracts to defining owners
* refactor: consolidate direct session contract type imports
* refactor: retain atomic publication test timing under moved owner
* fix(benchmark): resolve historical tunnel framing source before loading
* feat(cli): add orca vm env doctor to check a workspace environment
Checks required CLIs (git plus what the repo manifests imply), agent CLIs
and their sign-in, Git fetch and a dry-run push, the orca.yaml setup script
(optionally re-running it with Orca's runner), and free disk. Pass/warn/fail
with --json; checks live in src/main/environment-doctor for runtime reuse.
* fix(env-doctor): ship the doctor modules in the packaged CLI and share the check formatter
* fix(env-doctor): run Git probes in the C locale so folder detection is locale-independent
worker-start --on <server> --worktree new-child now tells the server that
orchestration picked the parent, so the server records the child's lineage as
orchestration, as a local child is, instead of cli. Older coordinators omit the
field and keep cli. The guide now shows new-child first and new-top-level as
the no-parent choice.
* refactor: separate execution route and child exit owners
* refactor: move browser data into defining feature owners
* refactor: give runtime RPC entry its shutdown implementation
* refactor: use defining process types and colocate host telemetry test
* docs(process-host): point piped child contract to Node owner
* docs(process-host): clarify both piped contract owners
* feat(cli): create workspaces on environment recipes
`orca worktree create --recipe <id>` creates the workspace on a new
environment from one of the repo's environment recipes, and
`orca vm recipe list` shows which recipes it accepts.
The desktop app on the provisioning computer runs the same main-side
provisioning the composer uses (write-ahead record, per-step timeouts,
cancellation), registers the project on the environment's Orca server,
then creates (orca-worktree) or adopts (provisioned-root) the
workspace there. Named progress steps ride on long-poll keepalive
frames, so the CLI prints them to stderr; older CLIs ignore them. A
failure after the VM exists destroys it through the shared cleanup and
returns recipe_workspace_create_failed with the failed step, the
recipe failure code and whether the destroy finished. Ctrl+C aborts
the request and destroys a started environment.
Paired devices cannot start a recipe create. Hosts advertise
worktree.recipe-create.v1 only when the desktop wires the recipe
service, so orcad and older hosts are refused before anything runs.
Based on #39228 by jutaz, a port of #28439.
Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>
* fix(cli): report the VM outcome when connecting fails; record no cross-host parent
* fix(vm-recipes): destroy the VM when recording its environment fails; reset exitCode in CLI tests
* perf(types): keep recipe orchestration out of the runtime's type graph
---------
Co-authored-by: Justas Brazauskas <brazauskasjustas@gmail.com>
* refactor: use concrete browser and input owners
* refactor: bind remote runtime callers to concrete transport owners
* Use checked subscription mock argument types
* Type browser lease mock with its subscription contract
* refactor: bind sleeping VM status probe test to socket owner
A reset that reclaims a crashed run's lock now puts that record back on release,
without overwriting a lock another start took, so the next start still reports the
crash. Starts without a rotating marker delete leftover .next staged files (one holds
a secret key); an unreadable marker leaves them for recovery by hand.
Co-authored-by: Claude <noreply@anthropic.com>
Cloning always went into <parent>/<repo name>, so a same-named repository
from another owner (or any non-empty folder of that name) could not be
cloned into the same parent. Before cloning, Orca now checks the target
on the clone host. If it is taken, the clone forms show a Folder name
field with a free suggestion (<repo>-<owner>, then <repo>-2...) and clone
into that instead. RPC repo.clone and `orca project setup-clone` accept
the folder name too.