Files
orca/src/cli/specs/project.ts
T
Neil 4cc7e7859a fix(cli): route --host runtime:<id> to that server instead of answering locally (#15364)
* fix(cli): route --host runtime:<id> to that server instead of answering locally

`--host` was only ever a local filter over whatever runtime the CLI happened
to connect to, so `--host runtime:<id>` silently answered for (and mutated)
the local machine. A real environment id and a made-up one were
indistinguishable: both returned ok:true with an empty list and the local
runtimeId in _meta, and `project setup-clone --host runtime:<id>` cloned into
the caller's own machine.

Resolve the flag before the client is built: unparseable host ids and runtime
ids that no paired environment owns are rejected, and a known runtime id
selects that environment as the connection (conflicting with --pairing-code or
a different --environment is an error). Once routed, a host filter also
accepts the runtime's own `local`-stamped rows, since both spellings name the
machine we are now talking to.

* fix(cli): close --host routing gaps found in review

- Conflict-check an ambient ORCA_ENVIRONMENT, not just the --environment flag.
  `ORCA_ENVIRONMENT=staging orca ... --host runtime:<prod-id>` silently routed
  to prod while the flag spelling errored. An ambient pairing code still loses
  to the explicit flag, because it cannot be resolved to an id to compare.
- Attach the known environment ids to the unknown-id error as `error.data`, so
  a --json consumer can retry without parsing prose, and say outright that
  runtime:<id> matches ids only and never environment names.
- Fix four command examples that documented `--host runtime:gpu`. `gpu` is an
  environment name, so every one of them would now be rejected; use an id.
- Cover the routed connection on `worktree create` and `automations create`
  (the mutating paths), the `--environment X --host local` filter-only case,
  and assert error.code/error.data rather than only substrings.

* test(cli): pin execution-host-flag to the deferred error-class import

index.ts now loads execution-host-flag.ts on every invocation, making it the
sixth module on the --help path. It imports RuntimeClientError from
./runtime/types today, but nothing enforced that; switching it to the barrel
would silently drag zod/ws/tweetnacl back onto --help, which is exactly what
this guard exists to prevent. Verified the assertion fails when the import is
flipped to the barrel.
2026-08-18 14:12:24 -07:00

127 lines
6.0 KiB
TypeScript

import type { CommandSpec } from '../args'
import { GLOBAL_FLAGS } from '../args'
export const PROJECT_COMMAND_SPECS: CommandSpec[] = [
{
path: ['project', 'list'],
summary: 'List durable projects known to Orca',
usage: 'orca project list [--json]',
allowedFlags: [...GLOBAL_FLAGS],
examples: ['orca project list', 'orca project list --json']
},
{
path: ['project', 'setups'],
summary: 'List project host setups',
usage: 'orca project setups [--project <id>] [--host <host-id>] [--json]',
allowedFlags: [...GLOBAL_FLAGS, 'project', 'host'],
notes: [
'A setup means a project is available on a host at a concrete filesystem path.',
'--host runtime:<environment-id> runs the command on that paired Orca server instead of filtering this runtime; unknown environment ids are rejected rather than answered with an empty list.',
'Run `orca environment list` to see the environment ids that runtime:<environment-id> accepts. It matches ids only, never environment names.',
"A routed --host runtime:<id> also lists that server's own local-stamped setups, because both spellings name the machine the command reached."
],
examples: [
'orca project setups',
'orca project setups --project github:stablyai/orca',
'orca project setups --host local',
'orca project setups --host runtime:03ef704c-b180-4b10-998d-e28fbd5de9a3'
]
},
{
path: ['project', 'setup-existing-folder'],
summary: 'Make a project available on a host by importing an existing folder',
usage:
'orca project setup-existing-folder --project <id> --host <host-id> --path <path> [--kind git|folder] [--display-name <name>] [--json]',
allowedFlags: [...GLOBAL_FLAGS, 'project', 'host', 'path', 'kind', 'display-name'],
notes: [
'For remote runtimes, --path must be an absolute path on the remote server.',
'--host runtime:<environment-id> targets that paired Orca server; use the id from `orca environment list`, not the environment name.',
'SSH targets are set up through the desktop UI because the desktop client owns SSH connections.'
],
examples: [
'orca project setup-existing-folder --project github:stablyai/orca --host local --path ~/orca',
'orca project setup-existing-folder --project github:stablyai/orca --host runtime:03ef704c-b180-4b10-998d-e28fbd5de9a3 --path /home/me/orca --kind git --json'
]
},
{
path: ['project', 'setup-clone'],
summary: 'Make a project available on a host by cloning a repository',
usage:
'orca project setup-clone --project <id> --host <host-id> --url <clone-url> --destination <path> [--display-name <name>] [--json]',
allowedFlags: [...GLOBAL_FLAGS, 'project', 'host', 'url', 'destination', 'display-name'],
notes: [
'For remote runtimes, --destination must be an absolute parent directory on the remote server.',
'--host runtime:<environment-id> targets that paired Orca server; use the id from `orca environment list`, not the environment name.',
'SSH targets are cloned through the desktop UI because the desktop client owns SSH connections.'
],
examples: [
'orca project setup-clone --project github:stablyai/orca --host local --url https://github.com/stablyai/orca.git --destination ~/src',
'orca project setup-clone --project github:stablyai/orca --host runtime:03ef704c-b180-4b10-998d-e28fbd5de9a3 --url https://github.com/stablyai/orca.git --destination /srv --json'
]
},
{
path: ['project', 'setup-create'],
summary: 'Create independent project host setup metadata',
usage:
'orca project setup-create --project <id> --host <host-id> [--setup-id <id>] [--path <path>] [--kind git|folder] [--display-name <name>] [--worktree-base-path <path>] [--git-username <name>] [--state ready|not-set-up|setting-up|error|unsupported] [--method imported-existing-folder|cloned|provisioned] [--json]',
allowedFlags: [
...GLOBAL_FLAGS,
'project',
'host',
'setup-id',
'path',
'kind',
'display-name',
'worktree-base-path',
'git-username',
'state',
'method'
],
notes: [
'Creates setup metadata without registering a repo compatibility record.',
'--host runtime:<environment-id> targets that paired Orca server; use the id from `orca environment list`, not the environment name.',
'Use setup-existing-folder when Orca should import and manage an actual checkout path now.'
],
examples: [
'orca project setup-create --project github:stablyai/orca --host runtime:03ef704c-b180-4b10-998d-e28fbd5de9a3 --state setting-up --method provisioned --json'
]
},
{
path: ['project', 'setup-update'],
summary: 'Update project host setup metadata',
usage:
'orca project setup-update --setup <setup-id> [--display-name <name>] [--path <path>] [--worktree-base-path <path>] [--git-username <name>] [--kind git|folder] [--state ready|not-set-up|setting-up|error|unsupported] [--method legacy-repo|imported-existing-folder|cloned|provisioned] [--json]',
allowedFlags: [
...GLOBAL_FLAGS,
'setup',
'display-name',
'path',
'worktree-base-path',
'git-username',
'kind',
'state',
'method'
],
notes: [
'Repo-backed setups mirror safe fields onto the repo record.',
'Path and availability state changes are only supported for independent setup records.'
],
examples: [
'orca project setup-update --setup github:stablyai/orca::gpu --display-name "GPU VM"',
'orca project setup-update --setup github:stablyai/orca::gpu --path /srv/orca --state ready --json'
]
},
{
path: ['project', 'setup-delete'],
destructive: true,
summary: 'Remove a project host setup',
usage: 'orca project setup-delete --setup <setup-id> [--json]',
allowedFlags: [...GLOBAL_FLAGS, 'setup'],
notes: [
'Independent setups are removed directly.',
'Repo-backed setups remove the registered repo compatibility record.'
],
examples: ['orca project setup-delete --setup github:stablyai/orca::gpu --json']
}
]