Files
orca/docs/site
Jinwoo Hong d3dbd9683f Update Orca's skills with Orca's own installer instead of npx skills (#31688)
* 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

* 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.

* 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.

* Resolve legacy skill agent keys canonically

* Reject stale skill replacements when auxiliary content changes

* 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 recovered skills needing attention until they are updated

* Count completed skill updates in the status tooltip

* Sync the runtime localization catalog
2026-10-22 22:35:14 -04:00
..

@orca/docs

This package contains the product documentation and public media intended to ship alongside Orca's source code.

Open-source product documentation for Orca, served at /docs (same URL shape as https://www.onorca.dev/docs).

This package is a self-contained Next.js app. It is intentionally not a root monorepo workspace member, so installing Electron app dependencies does not pull Next/fumadocs.

Local development

Use Node.js 24 and the pnpm version pinned in package.json. CI reads the Node.js version from this package's engines.node field.

cd docs/site
pnpm install
pnpm dev

Open http://localhost:3004/docs.

Linting

Run pnpm lint inside this directory. The isolated Oxlint configuration keeps the native equivalents of the previous Next.js, React, React hooks and accessibility checks at their existing severities, including alt text on Next.js Image components. Generated Next.js and MDX output is excluded. Oxlint also reports its default correctness warnings.

The migration does not provide equivalents for React's deprecated-API check, React Compiler configuration/gating diagnostics, or Next.js's relative location.assign advisory. JSX variable-use bookkeeping is handled by Oxlint's parser. Keep TypeScript and the production Next.js build in the validation workflow; this is not a claim of complete ESLint rule parity.

Production build

cd docs/site
pnpm install
pnpm build
pnpm start

pnpm start serves the production build on port 3004. Paths:

Path Purpose
/ Redirects to /docs
/docs Docs index
/docs/... Nested doc pages from content/docs
/docs/api/search Fumadocs search index
/docs/og/... Per-page Open Graph image route

Layout

  • content/docs/ — MDX pages + meta.json navigation
  • public/docs/ — docs-only media, logo, and favicon (GIFs, posters, screenshots)
  • src/app/docs/ — fumadocs routes, OG images
  • src/components/ — docs-scoped chrome (header/footer/search), not marketing site

Updating content

Treat the documentation tree as a deliberate publication boundary. Before importing source material, review the diff for internal references, credentials, third-party media rights, and feature/version claims, then copy only approved pages and assets. Keep the app shell and deployment configuration in this repository so a docs-only pull request can be reviewed and built independently.

Same-domain routing

The docs app is a separate Vercel project (the docs zone) and keeps the public /docs URL namespace. The marketing site remains the default zone for www.onorca.dev; configure its Next/Vercel proxy with these beforeFiles rewrites, replacing DOCS_ORIGIN with the docs project's production URL:

return {
  beforeFiles: [
    {
      source: '/docs',
      destination: `${DOCS_ORIGIN}/docs`
    },
    {
      source: '/docs/:path*',
      destination: `${DOCS_ORIGIN}/docs/:path*`
    },
    {
      source: '/docs-static/:path*',
      destination: `${DOCS_ORIGIN}/docs-static/:path*`
    }
  ]
}

/docs-static is the docs zone's assetPrefix; it prevents _next asset collisions with the marketing zone. Keep the rewrites in the default zone and use ordinary <a> links when navigating between zones. Do not add basePath: '/docs' to this app: its route tree and Fumadocs baseUrl already include /docs, so doing so would publish /docs/docs/... URLs. If a future deployment needs basePath, first move the route tree to an unprefixed src/app/[[...slug]] shape and update every generated/link URL together.

Deploy (Vercel)

  1. Create a Vercel project with Root Directory unset (.). The workflow invokes Vercel from docs/site, so that directory is already the deployment root; setting it again would resolve docs/site/docs/site. Leave automatic Git deployments disabled so this workflow remains the only deployment path.
  2. Framework preset: Next.js. This package's engines.node selects Node.js 24 for Vercel builds and functions. vercel.json pins install (pnpm install --frozen-lockfile) and build (pnpm build) over the dashboard settings; this package has its own lockfile beside the root workspace.
  3. Set GitHub Actions secrets (required by the production deploy job):
    • VERCEL_TOKEN
    • VERCEL_ORG_ID
    • VERCEL_PROJECT_ID (docs project, not the marketing site)
  4. Protect the docs-production GitHub environment with required reviewers and custom deployment branch policies for main and v* tags. The release-cut dispatch runs from main; the direct published-release fallback runs from a stable tag, while the workflow still authorizes only exact stable tags.
  5. Prepare the three rewrites above in the www.onorca.dev marketing project, but leave them disabled until the docs deployment is verified. A Vercel custom domain cannot delegate only /docs by itself; the default zone must proxy both page/API/media requests and /docs-static assets. Keep the marketing project's old docs routes available for rollback during the transition; putting the proxy rules in beforeFiles ensures they win once enabled.
  6. Deploy a stable desktop tag that contains docs/site, verify the docs origin, then enable the marketing rewrites. Tags cut before this package was added cannot bootstrap the docs project because production intentionally checks out the tag's exact commit. Remove the old marketing docs routes in a follow-up after the proxy is stable.

.github/workflows/docs.yml runs credential-free checks for every pull request. It intentionally does not deploy PR previews: a PR-controlled build must not receive Vercel credentials. A maintainer can add a separate trusted preview workflow later. Production deploys only from an authorized stable desktop release: an exact vX.Y.Z tag, a published non-prerelease release, and the github-actions[bot] release author. Manual dispatch must run from the default branch and name an existing release that meets the same checks. Mobile, prerelease, draft, and human-authored releases are skipped. Fork pull requests remain build-only because GitHub does not expose deployment secrets to fork jobs.

Versioning

versioning.config.ts keeps the current unversioned /docs URLs stable while reserving content/versions/<id> for future snapshots. Versioned routes are not live yet; when they are needed, add the corresponding loader/routes and a version entry. The release workflow can then deploy them without a trigger change.

Isolation from the desktop app

  • Own package.json + pnpm-lock.yaml under docs/site/
  • Not listed in the root pnpm-workspace.yaml; its own pnpm-workspace.yaml makes it a separate workspace root and holds its pnpm settings, which pnpm 12 ignores under --ignore-workspace
  • Engineering notes remain in repo-root docs/ — do not confuse with this package