* Add Orca's own bundled-skill planner and installer (not wired in yet)
One planner decides what installing Orca's bundled skills does to each
target folder; execute re-plans under per-path locks and runs only a plan
whose digest still matches; a shared summary derives badge, wording and
exit code. A copy counts as Orca's untouched one only when its SKILL.md
bytes match a version some build shipped (resources/skills/released-digests.json,
generated from git history and checked add-only).
Nothing calls this yet; the npx path is unchanged.
* Report left-alone folders as warnings and keep backups in the home
A leave is no longer a failure: the outcome line says what happened plus
"N left alone: <reason>", and the exit code is 1 only for a failed or
changed op. Backups for every scope go to <home>/.agents/.orca-skill-backups
on the executing host, so a project Replace never writes into the repo;
moving there falls back to copy, verify, then remove across filesystems.
* Update Orca's skills with Orca's own installer instead of npx skills
The app's Update skills dialog, badge, nudge and status pills now read the
bundled-skill plan and summary, and Update executes the reviewed plan's
digest. `orca skills install|update` runs the same planner in-process with
--dry-run, --force, --json and per-summary exit codes. Removes both npx
spawn sites, the freshness inventory modules and the npx round-trip CI.
* Update only where the skill already is; one provider-root rule for app and CLI
installedOnly now drops every location that holds nothing (keeping the shared slot
only when an existing agent link points at it), so Update never adds a skill for
another agent. The app and CLI resolve the Claude skills folder through the same
rule in localBundledSkillInput; a test asserts both plan identically.
* Compact Update skills dialog: one row per skill, locations named by agent
summarizeBundledSkillPlan now returns each skill's locations, labelled by
agent (or "Shared folder") with a ~-collapsed path; the dialog shows one row
per skill that needs something, collapses up-to-date skills into one line, and
lists every location behind "Show all locations". The result reads "Updated N
skills · M left alone". Under installedOnly a Replace with no shared copy
replaces in place instead of adding one.
* fix(skills): keep location paths readable by putting the state under the path
* fix(skills): hold the last plan in state, not a ref mutated during render
Split the update dialog's rows, headline and footer into components, move the Update label
next to the other plan copy, and use z.strictObject for the request schemas.
* Escape non-ASCII characters in bundled-skill regex and wording
The orcad bundle rejects a literal non-ASCII character in a regex.
* fix(cli): escape non-ASCII apostrophes in the skills install help text
* Plan and update Orca's skills on paired servers, SSH hosts and WSL
* Show the skills pill for paired hosts; real-WSL installer test
* test(orcad): check the bundled CLI plans a skill install without npx
Drop the deleted roundtrip workflow's group from the closed-PR cancellation fixture.
* Let the WSL installer create the backups folder itself
* Review fixes: follow the active workspace's host, keep hosts' plans and runs apart, never boot WSL for a background check
* test: execute requests carry the plan request; CLI pill follows the local target
* Write large WSL skill files in chunks that stay under the command-line limit
* Make bundled-skill test fixtures link folders the way the product does on Windows
Directory links in fixtures are junctions on Windows, which need no
Developer Mode; the one file-link fixture is skipped there.
* Let a client ask a host to install named Orca skills, not only update installed ones
* Plan an SSH workspace on the managed server that serves its host; ask to connect otherwise
* Translate the remote skill states into every locale
* Resolve legacy skill agent keys canonically
* Reject stale skill replacements when auxiliary content changes
* Remove the Windows-hosted WSL bundled skill installer
* Wait for active workspace ownership before planning bundled skills
* Keep ordinary bundled skill classification shallow
* Leave unreadable skill replacements alone without aborting plans
* Pass force-all through shallow planning and describe unreadable copies
* Clarify skill update statuses and folder details
* Keep selected skill replacements in place with one status
* Report completed skill replacements with their backup confirmation
* Clarify available skill updates and skipped copies
* Keep skill update results in preview order
* Show each skill skip reason once
* Count skipped skills instead of skipped folders
* Make installer input and link tests work on Windows
* Bound bundled skill classification reads and parse names linearly
* Keep workspace skill roots inside the resolved workspace
* Compare workspace skill roots with native path semantics
* Restrict bundled skill backups to their owner on POSIX
* Keep bundled skill updates on the proven local workspace host
* Keep recovered skills needing attention until they are updated
* Count completed skill updates in the status tooltip
* Sync the runtime localization catalog
* refactor(main): agent detection, automations, AI vault and ephemeral VM drop SSH provider arms
* refactor(skills): refuse SSH skill destinations at the branch and delete the relay skill services
* test(preflight): clear the local-detection mock before the SSH refusal cases
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(native-chat): a /compact sent while the agent works waits in line instead of being refused
* test(native-chat): build the admission test's submissions without a type assertion
* fix(native-chat): a /clear refused while the agent works says so plainly; a /compact behind an unsent message waits for it quietly
* test(native-chat): name the admission test's cases for the sends they model
* fix(native-chat): a /compact refused while the agent works reads plainly too; a command card offers no Edit
* test(native-chat): a refused /compact reads the plain sentence
* fix(native-chat): a refused command card is spent and said once; a command card offers Send while the agent is idle; /compact behind an unsent message is not taken
* test(native-chat): keep the queued receipt's narrowing inside the wait
* fix(native-chat): spend a command card only when its own turn says why; refuse a queued command without a hand-off, with its reason; a queue send on its way reads as sending
* fix(native-chat): a recorded send is no sending card; queue lists land at once; a spent card's wait says to run it again; only /compact or /clear give way to returned text
* refactor(native-chat): derive the sending cards inside the queued-messages hook
* fix(native-chat): keep protocol-version and the agent-session params under the line limit; the send capabilities get their own module
* fix(native-chat): with the agent idle, a command behind this window's own unsent message says it is still being sent
* fix(native-chat): the queued-commands capability stays a plain constant beside the others; main's send capabilities back to its text
* test(native-chat): keep the rewind suite under its line limit after main's growth
* fix(native-chat): one import per module in the command send; a rewind on its way holds commands, tested
* test(native-chat): type the rewind module mock with a type import
* test(native-chat): a command card cut short by a restart waits or is kept like any card; kept-card captions name only controls shown
* fix(native-chat): a held command card, which the queue skips, no longer forces later sends to queue
* fix(native-chat): a command's refusal line goes once what it waits on is gone
A refusal that names something the chat shows (the agent working, a pending prompt, background
tasks, an unsent message) is said only while that still holds, derived each render, and dropped
once it ends. Other composer errors are unchanged.
* fix(mobile): a command's refusal banner goes once what it waits on is gone
The phone's banner keeps a refusal naming the agent working or a pending prompt only while the
chat still shows it, dropped each render once it ends. Background tasks, which the phone can't
see, and generic errors behave as before. The host-reason mapping is shared with desktop.
* fix(native-chat): a refusal behind an earlier message names whether it is being sent or offers Retry
Each line now goes when its own state ends: a send that fails stops being sent, and a resend
stops offering Retry.
* test(native-chat): a Stop behind a typed /compact keeps the taken-back message on screen; the in-doubt case says so
* fix(native-chat): a command refused while the queue is about to send reads working, as the pane does
* Update held command fixture for the merged queue model
* Restart one host at a time in the recovery ordering test
* fix: preserve person queue reserve for chat commands
* Add skill deletion with cross-platform transaction safety
Implements end-to-end skill removal with placement enumeration, dependency guards, and transactional recovery. Covers native, WSL, and remote hosts; users can delete canonical directories and alias placements (symlinked directories or files) in a single atomic batch. Includes UI selection flow, preview, confirmation, and results band. Block reasons (bundled, plugin, unowned, stale) gate deletions that would fail or contradict user intent.
* Organize IPC handlers into module subdirectories
Move register-core-handlers and skill-delete-ipc-handlers into
dedicated subdirectories for improved code organization and to
reduce the flat structure in src/main/ipc/.
* Make skill deletion recovery transactions idempotent
Defer journal cleanup until both staging removal and receipt cleanup succeed, leaving the journal in place for startup to retry if either operation fails. This ensures the recovery process is safe to run multiple times without leaving partially-deleted skills.
* Consolidate skill-delete files into dedicated module
Reorganize skill deletion functionality into a modular structure under
`src/main/skills/skill-delete/` with simplified file names. Remove the
redundant `skill-delete-` prefix from file names since they now live in
the dedicated directory. Update all import paths throughout the codebase
to reflect the new structure, including imports from IPC handlers and
RPC methods.
* Fix broken import paths and add deletion robustness improvements
Import paths using `..//'` were invalid and broken. Replace with explicit
module names (`skill-discovery-sources`, `skill-install-filesystem`, etc.)
to clarify dependencies.
- Bind WSL filesystem methods to preserve `this` context
- Keep recovery journal when rollback rename fails, so startup can retry
- Skip symlink-based tests on Windows where they cannot run
- Only treat ENOENT/ENOTDIR as empty directories; propagate other errors
- Fix cross-platform path parent calculation to handle drive roots
- Replace shared constant with localized string for user-facing message
- Use `runProcess` for WSL integration test instead of bare `execFile`
* Add batch limit for skill deletion and improve host availability checkin
- Limit concurrent deletions to prevent remote host overload
- Add retry logic for capability probing to handle transient unavailability
- Add reprobe() method to recheck capability after errors or user refresh
- Fix status logic: receipt cleanup is best-effort, completion depends only on content removal
- Improve error message for unreachable hosts