* Hide projects from the sidebar without stopping them
Adds Repo.hiddenAt, a per-host, view-only flag. A hidden project's
workspaces, empty header and project-filter entry leave the desktop
sidebar, the paired phone's list, the new-workspace picker and the
palette's project filter. Its terminals, agents and automations keep
running, and repo.list / worktree.ps still list it.
- Hide Project in the project menu (toast with Undo), a collapsed
"N hidden projects" list under the workspace list with Show buttons,
and a Hide from sidebar switch in Settings > Projects.
- repo.setHidden RPC ({repo, repoHostId?, hidden} -> {repo, hostId,
hidden}) and `orca repo hide|unhide [--host]`; `repo list` marks
hidden rows.
- Opening a hidden project's workspace (notification, CLI, deep link)
focuses it without unhiding it, lifting sidebar filters, or leaving a
pending sidebar reveal.
- repo.update echo check: a host that drops hiddenAt reports failure
instead of reading as hidden.
* Address hidden-projects review: multi-host hide, picker scope, mute, stale filters, shared predicate, restore list styling
* Hidden projects re-review: keep saved filters, Agents filter, composer seed, per-toast Undo, shared default host
* Hidden projects: address review threads (pre-feed, palette search, notices, dialog default, seed remap, row keys, a11y)
* Hidden projects: no implicit dialog default when every project is hidden
* feat(plugins): host API 1.9: agent.listSessions (history:read), resume past sessions, agents.list task titles
* test(plugins): host API 1.9 coverage; regenerate plugin artifacts
* fix(plugins): host API 1.9 review fixes
- agent.resume starts a past session where the desktop's Resume would: the same preparation
request and answer handling (now shared), and the transcript in the home it pins
- AI Vault list cache keeps four scopes, so plugin reads never evict the panel's list
- list fingerprints ignore scan id and issues, so an unchanged history revalidates
- workspace mapping resolves symlinked workspaces and prefers a project over a folder
- agents.list task only for open dispatches, read at most once a second
- running matches OpenCode versions; history reads reset when the vault list is invalidated
- truncation, consent copy and limitations documented
* fix(plugins): forced history refresh supersedes cached scopes; resume legacy Codex sessions from their recorded transcript
* fix(plugins): address host API 1.9 review threads
- a scan that began before a forced history refresh no longer caches its older result
- list fingerprints count which issues there are (not their wording)
- symlinked workspaces rank by their resolved folder
- a session-only status row is no live pane: resume prepares the session
- a failed task-title read leaves agents.list rows intact
- the symlink test uses a junction on Windows
* test(ai-vault): order the stale scan before the forced refresh
* feat(plugins): proposed tier for host methods not yet frozen
A method spec may set `proposed: true`: only development plugins may call
it (others get not_permitted), and the minor, frame/worker method lists,
typings and skill references omit it. The reference renders such methods
in a separate Proposed section; dev workers' host.has answers for them.
* feat(plugins): param capabilities, host confirmations, automation provenance
- PluginHostMethodSpec.paramCapabilities: a passed param can require a
second capability; executePluginHostCall and the mock host refuse it with
capability_denied before any audit or effect, and the reference shows it.
- confirmPluginAction generalizes the external-open prompt into a host-owned
confirmation, exposed as PluginHostServices.confirm (desktop only; absent
in headless serve). It re-checks the plugin's approval after the answer.
- Automations record createdBy { kind: 'plugin', pluginKey, name }, set by
the runtime from the in-process plugin caller (RpcContext.plugin), never
from params; the Automations detail shows "Created by <plugin>".
* feat(plugins): workspace:create, automation:read and automation:write capabilities
New closed-enum kinds (older Orcas refuse such manifests with the engines
message), worker-only, with consent copy that names what each allows;
release floor PLUGIN_HOST_API_1_8_SINCE (1.4.259) joins
PLUGIN_SCHEMA_NEWEST_SINCE. agent:launch copy now says it also resumes.
* feat(plugins): host API 1.8 methods: workspace.create, agent.resume, automation.*
- workspace.create (workspace:create; agent also needs agent:launch): a
worktree in a Git project, as orca worktree create does; with agent, the
CLI's agent.launch create-worktree path, so the agent starts after setup.
Setup is skipped or follows the project's settings; never run, an
approved hash or a startup command.
- agent.resume (agent:launch): terminal.ensureAgentSession by session id;
started is false when a terminal already ran it. agents.list rows and
agent.status.changed carry sessionId.
- automation.list/create/update/delete (automation:read/write): create
forwards only name, prompt, agent, target, schedule, time zone and
enabled; update/delete of automations another plugin or the person made
ask the person first and report cancelled or consent-unavailable.
* test(plugins): host API 1.8 coverage; regenerate plugin artifacts
Covers param capabilities (host and mock host), workspace.create payloads
and refusals, agent.resume keys and adoption, sessionId on agents.list,
automation projection, forbidden create fields, confirmation outcomes,
runtime-set provenance and capability access growth. Regenerates the
reference, schemas, typings, declarative runtime and skill references.
* fix(plugins): host API 1.8 review fixes
- Confirmations spend the frame dialog budget, allow one question per
plugin at a time and pause after a refusal (rate_limited); a worker's
question shows in the focused window, else the first visible one.
- Changing what an automation with extra agent settings runs (prompt,
schedule, resuming) asks first even for its creator, showing the prompt.
- Removing, disabling or blocking a plugin pauses its automations and ends
its ownership (createdBy.endedAt), so neither re-enabling nor a reinstall
under the key resumes or edits them silently; the remove dialog says so.
- workspace.create and agent.resume record the terminals they return as
the plugin's own; a launch that fails after its worktree exists names it.
- Setup-decision refusals are told by the runtime's error class (kept as
the in-process RPC error's cause); generated names see every worktree
of the project; resume transcripts match the workspace and host.
- Created by shows the plugin id beside its name.
* fix(plugins): end automation ownership only on uninstall, disable or block
- The ownership sweep no longer reads discovery: only an uninstall
(announced by the removal path), the disabled list, the kill list or
the plugin-system switch end it, and only once the service is ready,
so an unreadable plugins folder pauses nothing. An install under the
same key after a removal keeps what it creates.
- A new time zone on an automation with extra agent settings asks first.
- A failed launch names only a new worktree made from the requested name.
- Settings' plugins-off state and the CLI's plugin system off and plugin
disable say that plugin-created automations are paused and stay so.
* fix(plugins): address host API 1.8 review threads
- Confirmations close when the worker's call ends, freeing the plugin's
turn; they name the automation (short id, project, workspace,
schedule), show any new prompt, and are refused as `changed` when the
automation was edited while the person was asked.
- automation.create takes hostId (through the project's setup on that
host) and a creationKey scoped to the plugin; the runtime rechecks the
plugin's approval right before the write.
- agent.resume records only terminals it started; both it and
workspace.create recheck approval before recording.
- automation.list never cuts a schedule (null when too long) or fails on
an id too long to show.
- The Automations detail says when a creator plugin was removed or
disabled.
* feat(plugins): host API 1.7 — workspace ids, project/terminal list, terminal focus/close
Plugins that track workspaces and terminals across Orca had to read the private runtime
token or shell out to the CLI. Host API 1.7 gives them the same through consented methods:
- workspace.readContext (and workspace.changed) carry `workspaceId`, the id workspace.list
gives; workspace.created/removed and agent.status.changed add `workspaceListId` beside
their existing raw `workspaceId`, which keeps its meaning.
- workspace.list rows name their `projectId`; opt-in `includeStatus` joins each row's agent
state, unread flag, live terminal count and last activity from worktree.ps.
- project.list (workspace:read), terminal.list (workspace:read), terminal.focus
(workspace:write, desktop only, steers only this window) and terminal.close
(terminal:send, reports whether the process is known to have stopped).
- Runtime refusals (unknown or ambiguous workspace, stale or exited terminal) reach plugins
as fixed messages instead of runtime wording.
- Consent copy for workspace:read, workspace:write and terminal:send says what they now
allow; terminal.focus and terminal.close are audited by terminal id.
- PLUGIN_SCHEMA_NEWEST_SINCE covers the editor typography and theme video floors it missed,
and the provisional 1.7 floor, so development builds accept plugins requiring them.
* fix(plugins): narrow terminal.close and harden host API 1.7 from review
- terminal.close closes only terminals of the focused workspace (the check terminal.sendText
uses) or ones this plugin opened with terminal.create or agent.launch, recorded in a bounded
per-plugin registry that is forgotten when its worker stops or it is disabled or removed.
terminal.focus stays any-terminal; summaries and terminal:send copy say so.
- Lifecycle events carry the worktree's identity and host: from the new row on create, and read
host-qualified before the purge on every removal path. agent.status.changed looks up the
identity on the reporting host only. The global removed-identity map is gone.
- includeStatus shares one in-flight worktree.ps and a 1 s cache across plugins, and reports
statusTruncated when that listing stopped short.
- Stored remote contexts get their identity host-qualified; panels and editors never get a raw,
path-bearing workspace id from readContext or workspace.changed.
- Runtime refusals map to fixed messages (tab pinned, no window, tab gone, host disconnected);
any other runtime error or malformed answer is a fixed action_failed with the detail logged.
- hostId is `local`, `ssh:` or `runtime:` in both workspace.list and project.list; rows past the
id or path bounds are left out with truncated set instead of failing the list.
- The mock testing host answers terminal.focus and terminal.close by default.
* fix(plugins): keep shipped host API values and codes; honest terminal results
- workspace.list hostId keeps the values 1.3 shipped (recorded host, else null; folder rows
their executionHostId); project.list always names the host. Both summaries say which.
- Methods that shipped before 1.7 report every runtime refusal as action_failed, as before;
the unavailable/conflict mapping applies to 1.7 methods only.
- includeStatus shares a pending worktree.ps however long it runs; the 1 s TTL starts when it
lands.
- The opened-terminal registry records only for a call still approved and not cancelled, and is
pruned on disable or removal only, so event-driven workers keep close rights across restarts.
- terminal.close answers { closed: true }: a local close cannot tell whether the process exited.
terminal.focus answers focused: false when the request was superseded or not navigated.
- workspace.list and project.list cut labels to 512 instead of failing the list.
- Removal events from the runtime job and the IPC retry are tested to carry the identity read
before the purge; folder deletion carries its host.
* fix(plugins): name the status-listing owner type
* fix(computer): stop echoing written text and secure read-backs in action results
* fix(computer): treat a truncated set-value read-back as unverifiable
* fix(computer): accept code-point truncated read-backs as unverifiable
* fix(cli): report connected agent hook status from the sqlite file
Status always said appliedBy offline and named orca-data.json, even when the app was connected and the setting lived only in profile-state.db.
* fix(cli): read agent hook status from the running app
When the runtime answers, status takes agentStatusHooksEnabled from
settings.get instead of the disk, so appliedBy: runtime is true. The
settings path rule lives next to the reader, and on/off report the
SQLite file when the runtime applied the change.
---------
Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
* perf(orchestration): read released worker output from its original instead of a saved copy
* fix(orchestration): keep refusal codes on released chat reads and locate legacy remote transcripts
* test(orchestration): prune flaky-pattern baseline for removed archive tests; guard a cursor read
* fix(orchestration): keep locator fields when stripping copies; never let the optional receipt page block remote release
* test(orchestration): drop removed archive tests from the node-runtime test list
* refactor(orchestration): drop the background strip; old rows keep their saved copy and its reader
* fix(orchestration): give reference rows the empty copy fields older Orca reads, with a note
* test(orchestration): give the slow-exit release mock a stored archive body
* fix(orchestration): record a transcript reference only for agents the reader can open
* fix(orchestration): hide approve from help; approval follow-ups
- Hide 'orchestration approve' from group help; its own --help still works.
- Mark a terminal worker's approval reported only once its escalation was sent,
so a prompt whose report was skipped gets no stray closing line.
- Hold back a worker approval receipt older than every loaded chat message
instead of drawing it below newer replies.
* fix(orchestration): count a stored stop report as sent when its wake fails
* feat(orchestration): let coordinators approve worker permission prompts when the user turns it on
One setting on the orchestration page, off by default. When on, the
escalation offers orchestration approve and deny, both with a reason, and
the user still sees Allow/Deny: the first answer wins. A prompt the
worker's agent lets only a person approve is refused and stays with the
user. The machine running the worker enforces its own setting.
* fix(native-chat): a worker approval's receipt shows the command, not its tool input as JSON
* test(orchestration): list every worker-side case in the coordinator approval table
* chore(i18n): ship the coordinator approval setting's search keywords in the runtime catalog
* fix(orchestration): a reasonless allow keeps the person's refusal, and terminal checks no hook may approve are person-only
* fix(orchestration): address review on coordinator approvals
- A person-only chat prompt answered meanwhile reports as closed.
- A terminal allow reads Claude's warning from the screen it checks, so a
late-painted person-only warning still refuses before the hook is used.
- The receipt keeps a chat worker's whole command.
- orchestration approve prints the reason it sent.
* fix(native-chat): read the receipt's command through a parsed shape, not Reflect
* docs(skills): drop worker permission prompt guidance; the escalation carries it
The numeric reasoning_effort a model sees is not on a 0-100 scale
(claude-opus-5-5: low=5, medium=10, high=15, xhigh=40). Workers launched
with --effort high read 15 as low and misreported their effort.
* Revert "Make chat wait check the chat's work state instead of reading its history every second (#41129)"
This reverts commit 9a10464bec.
* Revert "feat(cli): read, message and wait on agent chats with orca chat list/read/send/wait (#40836)"
This reverts commit c2e6ebbf0b.
* fix(browser): stop agent clicks from opening the system file picker
An agent click on a file input opened the macOS Open panel, which brought
Orca's window forward over the app the user was in. Page actions now catch
the picker the way upload does and tell the agent to use upload.
* fix(browser): enable Page, cancel the picker, and clean up outside host scope
* fix(browser): limit picker blocking to input delivery and bound its setup
* perf(browser): skip picker blocking for actions without user activation
* fix(browser): bound picker interception cleanup on a hung page
* fix(browser): bound the picker interception setup as a whole
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