mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
* skills: rewrite the seven non-orchestration guides to one outcome-first standard
Every guide leads with Result / Done / Safe failure, states conditions instead of case lists, keeps one done bar and one autonomy envelope, and loads references at the point of use via `skills get <topic> --full`. orca-cli drops from 424 to 260 always-loaded lines with three references; orca-per-workspace-env from 794 to 397 with five.
Defects fixed in shipped guides: `emulator camera` (no such command), iOS `permissions` (backend refuses it), Android pane described as in development, `relayGracePeriodSeconds: 0` documented as immediate teardown (it is unbounded), doctor `ok: true` hiding `warn`, an SSH exemplar setting both `jumpHost` and `proxyCommand`, a provisioned-root fetch from `origin`, and the Linear unconfirmed-write rule keyed on four verbs when ten emit it.
The resolver ladder, placeholder rule, and older-binary fallback shared by every installable SKILL.md now come from one skill-stubs/_shared/cli-resolution.md fragment composed by the generator, which also bundles per-guide references into --full. New guards: every ORCA invocation and flag resolves against COMMAND_SPECS, descriptions carry no angle-bracket tokens, reference routing is checked both ways, and an always-loaded size ratchet (300 lines) that guides may leave but never join.
* skills: address review on the SSH recipe and the parity guard
- ssh-host create script: route the bootstrap ssh through the chosen jump host or proxy command, refuse both at once, use StrictHostKeyChecking=accept-new instead of a blind ssh-keyscan append, and pass gh_token/project_root/repo_url/repo_ref to the remote bash via printf %q so a quote in a value cannot break out of the command.
- per-workspace-env envelope: the step-10 workspace test the user asked for is no longer forbidden by the same paragraph.
- linear guides: name the full verb, ORCA linear list-issues.
- parity guard: a prefix reference such as ORCA linear --help or ORCA emulator --webcam now has its flags checked against every command under that prefix; only an exact path or an explicit ... was checked before.
* skills: tighten prose in the seven rewritten guides
Shorter outcome spines, one idea per sentence, no restated rationale after a rule. No rule, command, or pinned phrase changes; 47 net lines fewer across the guides and references.
* skills: route orca-cli and per-workspace-env gates through --reference
Both guides told agents to load --full at a gate because the per-reference
selector did not exist when they were written. Now that main serves
`skills get <topic> --reference references/<file>.md`, load only the
named file and keep --full as the fallback for an older CLI, matching the
orchestration kernel.
* skills: drop outcome-spine boilerplate from the CLI-wrapper guides
The Result/Done/Safe-failure preambles and Next Action closers restated
rules the body already carries. Agents stop fine without them, and for
a CLI wrapper the command surface is the guide. Keeps the one substantive
rule computer-use's Done block added (never report unverified as success)
inside Action Rules. orchestration and per-workspace-env keep theirs:
those are multi-step workflows where the done bar is load-bearing.
(cherry picked from commit 44a74baf73)
* skills: trim the guides and stubs to what agents actually need
- Drop the Result/Done/Safe-failure preambles and Next Action closers from
the six CLI-wrapper guides; the one substantive rule (never report an
unverified computer-use action as success) moves into Action Rules.
- Drop the 'guide may be stale, trust --help' lines: the guide is served by
the binary that runs the commands, so it cannot be stale relative to it.
- Drop the status --json / open --json preflight from every guide; the stub
no-guessing paragraph now says to start Orca only when a command reports
it is not running.
- Cut the ORCA placeholder paragraph in each guide to one line that points
back at the stub's resolution.
- Trim the orchestration, orca-cli, and computer-use descriptions to trigger
phrases plus one line of scope.
- Remove the older-binary fallback section from every stub (and its two
shared blocks); a binary without skills get gets one sentence.
- Remove the guide size ratchet test.
* skills: apply independent review cleanup
* skills: clarify guide loading and Linear command discovery
* skills: harden environment recipe examples
* test: complete branch rename journal doubles
* skills: clarify custom Codex launch and refresh model example
* test: deduplicate journal fix now present on main
94 lines
3.4 KiB
JavaScript
94 lines
3.4 KiB
JavaScript
import { execFile } from 'node:child_process'
|
|
import { readFile } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
import { promisify } from 'node:util'
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
const run = promisify(execFile)
|
|
const referenceRoot = resolve(
|
|
import.meta.dirname,
|
|
'../../skill-guides/orca-per-workspace-env/references'
|
|
)
|
|
const vercel = await readFile(resolve(referenceRoot, 'provider-vercel.md'), 'utf8')
|
|
const ssh = await readFile(resolve(referenceRoot, 'ssh-host.md'), 'utf8')
|
|
const cleanup = vercel.match(/```bash\n(cleanup_snapshot\(\) \{[\s\S]*?\n\})\n```/u)?.[1]
|
|
|
|
async function runShell(script, env = {}) {
|
|
try {
|
|
const output = await run('bash', ['-c', script], {
|
|
env: { ...process.env, ORCA_BACKGROUND_LAUNCH: '1', ...env }
|
|
})
|
|
return { ...output, code: 0 }
|
|
} catch (error) {
|
|
return { stdout: error.stdout, stderr: error.stderr, code: error.code }
|
|
}
|
|
}
|
|
|
|
describe.skipIf(process.platform === 'win32')('recipe shell examples', () => {
|
|
it.each(['base', 'auth'])('cleans the %s sandbox on failure and success', async (phase) => {
|
|
expect(cleanup).toBeDefined()
|
|
const trap = vercel.match(new RegExp(`trap 'cleanup_snapshot "\\$${phase}"' EXIT`, 'u'))?.[0]
|
|
expect(trap).toBeDefined()
|
|
expect(vercel.indexOf(trap)).toBeLessThan(
|
|
vercel.indexOf(`vercel sandbox create --name "$${phase}"`)
|
|
)
|
|
for (const exitCode of [0, 7]) {
|
|
const result = await runShell(`set -euo pipefail
|
|
${cleanup}
|
|
vercel_args=(--scope test-scope)
|
|
${phase}=unique-test-sandbox
|
|
vercel() { printf '%s\\n' "$@"; }
|
|
${trap}
|
|
exit ${exitCode}`)
|
|
expect(result.code).toBe(exitCode)
|
|
expect(result.stderr).toBe('sandbox\nremove\nunique-test-sandbox\n--scope\ntest-scope\n')
|
|
}
|
|
})
|
|
|
|
it('reports failed cleanup even after an otherwise successful snapshot', async () => {
|
|
const result = await runShell(`set -euo pipefail
|
|
${cleanup}
|
|
vercel_args=()
|
|
vercel() { return 9; }
|
|
trap 'cleanup_snapshot unique-test-sandbox' EXIT
|
|
exit 0`)
|
|
expect(result.code).toBe(1)
|
|
expect(result.stderr).toContain('Sandbox cleanup failed for unique-test-sandbox')
|
|
})
|
|
|
|
it('disables Git prompts when the Vercel token is absent', async () => {
|
|
const prefix = vercel.match(
|
|
/-- bash -lc 'set -euo pipefail; cd "\$ORCA_PROJECT_ROOT"; \\\n([\s\S]*?) git fetch/u
|
|
)?.[1]
|
|
expect(prefix).toBeDefined()
|
|
const result = await runShell(
|
|
`set -euo pipefail\nunset GH_TOKEN\n${prefix}\nprintf '%s' "$GIT_TERMINAL_PROMPT"`
|
|
)
|
|
expect(result.code).toBe(0)
|
|
expect(result.stdout).toBe('0')
|
|
})
|
|
|
|
it('uses host credentials and refuses unverified SSH hosts without forwarding tokens', async () => {
|
|
const script = ssh.match(/```bash\n(#!\/usr\/bin\/env bash[\s\S]*?)\n```/u)?.[1]
|
|
expect(script).toBeDefined()
|
|
const sync = script.slice(0, script.indexOf('# 2. print'))
|
|
const result = await runShell(
|
|
`ssh() { printf '%s\\n' "$@"; }
|
|
ssh_username=worker
|
|
host=example.test
|
|
ssh_port=2222
|
|
project_root='/remote/path with spaces'
|
|
repo_url=https://example.test/org/repo.git
|
|
repo_ref=main
|
|
${sync}`,
|
|
{ GH_TOKEN: 'test-token-must-not-be-forwarded' }
|
|
)
|
|
expect(result.code).toBe(0)
|
|
expect(result.stderr).toContain('StrictHostKeyChecking=yes')
|
|
expect(result.stderr).toContain('BatchMode=yes')
|
|
expect(result.stderr).not.toContain('test-token-must-not-be-forwarded')
|
|
expect(result.stderr).not.toContain('GH_TOKEN=')
|
|
expect(script).toContain('export GIT_TERMINAL_PROMPT=0')
|
|
})
|
|
})
|