@ai-substrate/engineering-harness 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/harness/cli/bin/harness.js +12 -0
- package/harness/cli/dist/acts/docs.d.ts +17 -0
- package/harness/cli/dist/acts/docs.js +73 -0
- package/harness/cli/dist/acts/docs.js.map +1 -0
- package/harness/cli/dist/acts/doctor.d.ts +14 -0
- package/harness/cli/dist/acts/doctor.js +43 -0
- package/harness/cli/dist/acts/doctor.js.map +1 -0
- package/harness/cli/dist/acts/help.d.ts +14 -0
- package/harness/cli/dist/acts/help.js +29 -0
- package/harness/cli/dist/acts/help.js.map +1 -0
- package/harness/cli/dist/acts/init.d.ts +22 -0
- package/harness/cli/dist/acts/init.js +61 -0
- package/harness/cli/dist/acts/init.js.map +1 -0
- package/harness/cli/dist/acts/instructions.d.ts +21 -0
- package/harness/cli/dist/acts/instructions.js +75 -0
- package/harness/cli/dist/acts/instructions.js.map +1 -0
- package/harness/cli/dist/acts/new.d.ts +19 -0
- package/harness/cli/dist/acts/new.js +66 -0
- package/harness/cli/dist/acts/new.js.map +1 -0
- package/harness/cli/dist/acts/observe.d.ts +23 -0
- package/harness/cli/dist/acts/observe.js +129 -0
- package/harness/cli/dist/acts/observe.js.map +1 -0
- package/harness/cli/dist/acts/record.d.ts +24 -0
- package/harness/cli/dist/acts/record.js +93 -0
- package/harness/cli/dist/acts/record.js.map +1 -0
- package/harness/cli/dist/acts/skills.d.ts +32 -0
- package/harness/cli/dist/acts/skills.js +256 -0
- package/harness/cli/dist/acts/skills.js.map +1 -0
- package/harness/cli/dist/acts/update.d.ts +23 -0
- package/harness/cli/dist/acts/update.js +297 -0
- package/harness/cli/dist/acts/update.js.map +1 -0
- package/harness/cli/dist/acts/verb.d.ts +27 -0
- package/harness/cli/dist/acts/verb.js +56 -0
- package/harness/cli/dist/acts/verb.js.map +1 -0
- package/harness/cli/dist/adapters/clock/clock-port.d.ts +10 -0
- package/harness/cli/dist/adapters/clock/clock-port.js +2 -0
- package/harness/cli/dist/adapters/clock/clock-port.js.map +1 -0
- package/harness/cli/dist/adapters/clock/fake-clock.d.ts +15 -0
- package/harness/cli/dist/adapters/clock/fake-clock.js +25 -0
- package/harness/cli/dist/adapters/clock/fake-clock.js.map +1 -0
- package/harness/cli/dist/adapters/clock/system-clock.d.ts +5 -0
- package/harness/cli/dist/adapters/clock/system-clock.js +7 -0
- package/harness/cli/dist/adapters/clock/system-clock.js.map +1 -0
- package/harness/cli/dist/adapters/env/env-port.d.ts +17 -0
- package/harness/cli/dist/adapters/env/env-port.js +2 -0
- package/harness/cli/dist/adapters/env/env-port.js.map +1 -0
- package/harness/cli/dist/adapters/env/fake-env.d.ts +15 -0
- package/harness/cli/dist/adapters/env/fake-env.js +24 -0
- package/harness/cli/dist/adapters/env/fake-env.js.map +1 -0
- package/harness/cli/dist/adapters/env/node-env.d.ts +6 -0
- package/harness/cli/dist/adapters/env/node-env.js +16 -0
- package/harness/cli/dist/adapters/env/node-env.js.map +1 -0
- package/harness/cli/dist/adapters/exec/exec-port.d.ts +22 -0
- package/harness/cli/dist/adapters/exec/exec-port.js +2 -0
- package/harness/cli/dist/adapters/exec/exec-port.js.map +1 -0
- package/harness/cli/dist/adapters/exec/fake-exec.d.ts +25 -0
- package/harness/cli/dist/adapters/exec/fake-exec.js +25 -0
- package/harness/cli/dist/adapters/exec/fake-exec.js.map +1 -0
- package/harness/cli/dist/adapters/exec/node-exec.d.ts +14 -0
- package/harness/cli/dist/adapters/exec/node-exec.js +38 -0
- package/harness/cli/dist/adapters/exec/node-exec.js.map +1 -0
- package/harness/cli/dist/adapters/fs/fake-fs.d.ts +22 -0
- package/harness/cli/dist/adapters/fs/fake-fs.js +63 -0
- package/harness/cli/dist/adapters/fs/fake-fs.js.map +1 -0
- package/harness/cli/dist/adapters/fs/fs-port.d.ts +20 -0
- package/harness/cli/dist/adapters/fs/fs-port.js +2 -0
- package/harness/cli/dist/adapters/fs/fs-port.js.map +1 -0
- package/harness/cli/dist/adapters/fs/node-fs.d.ts +9 -0
- package/harness/cli/dist/adapters/fs/node-fs.js +30 -0
- package/harness/cli/dist/adapters/fs/node-fs.js.map +1 -0
- package/harness/cli/dist/adapters/git/exec-git.d.ts +6 -0
- package/harness/cli/dist/adapters/git/exec-git.js +21 -0
- package/harness/cli/dist/adapters/git/exec-git.js.map +1 -0
- package/harness/cli/dist/adapters/git/fake-git.d.ts +15 -0
- package/harness/cli/dist/adapters/git/fake-git.js +20 -0
- package/harness/cli/dist/adapters/git/fake-git.js.map +1 -0
- package/harness/cli/dist/adapters/git/git-port.d.ts +12 -0
- package/harness/cli/dist/adapters/git/git-port.js +2 -0
- package/harness/cli/dist/adapters/git/git-port.js.map +1 -0
- package/harness/cli/dist/adapters/loader/fake-loader.d.ts +13 -0
- package/harness/cli/dist/adapters/loader/fake-loader.js +25 -0
- package/harness/cli/dist/adapters/loader/fake-loader.js.map +1 -0
- package/harness/cli/dist/adapters/loader/jiti-loader.d.ts +15 -0
- package/harness/cli/dist/adapters/loader/jiti-loader.js +29 -0
- package/harness/cli/dist/adapters/loader/jiti-loader.js.map +1 -0
- package/harness/cli/dist/adapters/loader/module-loader-port.d.ts +12 -0
- package/harness/cli/dist/adapters/loader/module-loader-port.js +2 -0
- package/harness/cli/dist/adapters/loader/module-loader-port.js.map +1 -0
- package/harness/cli/dist/adapters/process/fake-process.d.ts +13 -0
- package/harness/cli/dist/adapters/process/fake-process.js +21 -0
- package/harness/cli/dist/adapters/process/fake-process.js.map +1 -0
- package/harness/cli/dist/adapters/process/node-process.d.ts +6 -0
- package/harness/cli/dist/adapters/process/node-process.js +17 -0
- package/harness/cli/dist/adapters/process/node-process.js.map +1 -0
- package/harness/cli/dist/adapters/process/process-port.d.ts +13 -0
- package/harness/cli/dist/adapters/process/process-port.js +2 -0
- package/harness/cli/dist/adapters/process/process-port.js.map +1 -0
- package/harness/cli/dist/adapters/version-lookup/fake-version-lookup.d.ts +13 -0
- package/harness/cli/dist/adapters/version-lookup/fake-version-lookup.js +21 -0
- package/harness/cli/dist/adapters/version-lookup/fake-version-lookup.js.map +1 -0
- package/harness/cli/dist/adapters/version-lookup/node-version-lookup.d.ts +18 -0
- package/harness/cli/dist/adapters/version-lookup/node-version-lookup.js +51 -0
- package/harness/cli/dist/adapters/version-lookup/node-version-lookup.js.map +1 -0
- package/harness/cli/dist/adapters/version-lookup/version-lookup-port.d.ts +19 -0
- package/harness/cli/dist/adapters/version-lookup/version-lookup-port.js +2 -0
- package/harness/cli/dist/adapters/version-lookup/version-lookup-port.js.map +1 -0
- package/harness/cli/dist/app.d.ts +70 -0
- package/harness/cli/dist/app.js +221 -0
- package/harness/cli/dist/app.js.map +1 -0
- package/harness/cli/dist/index.d.ts +2 -0
- package/harness/cli/dist/index.js +26 -0
- package/harness/cli/dist/index.js.map +1 -0
- package/harness/cli/dist/output/envelope.d.ts +68 -0
- package/harness/cli/dist/output/envelope.js +56 -0
- package/harness/cli/dist/output/envelope.js.map +1 -0
- package/harness/cli/dist/output/error-codes.d.ts +57 -0
- package/harness/cli/dist/output/error-codes.js +57 -0
- package/harness/cli/dist/output/error-codes.js.map +1 -0
- package/harness/cli/dist/output/exit.d.ts +29 -0
- package/harness/cli/dist/output/exit.js +36 -0
- package/harness/cli/dist/output/exit.js.map +1 -0
- package/harness/cli/dist/output/output-port.d.ts +54 -0
- package/harness/cli/dist/output/output-port.js +55 -0
- package/harness/cli/dist/output/output-port.js.map +1 -0
- package/harness/cli/dist/output/style.d.ts +33 -0
- package/harness/cli/dist/output/style.js +68 -0
- package/harness/cli/dist/output/style.js.map +1 -0
- package/harness/cli/dist/services/config/load-config.d.ts +27 -0
- package/harness/cli/dist/services/config/load-config.js +114 -0
- package/harness/cli/dist/services/config/load-config.js.map +1 -0
- package/harness/cli/dist/services/docs/contract.d.ts +41 -0
- package/harness/cli/dist/services/docs/contract.js +14 -0
- package/harness/cli/dist/services/docs/contract.js.map +1 -0
- package/harness/cli/dist/services/docs/docs-content.d.ts +37 -0
- package/harness/cli/dist/services/docs/docs-content.js +48 -0
- package/harness/cli/dist/services/docs/docs-content.js.map +1 -0
- package/harness/cli/dist/services/docs/docs-service.d.ts +26 -0
- package/harness/cli/dist/services/docs/docs-service.js +25 -0
- package/harness/cli/dist/services/docs/docs-service.js.map +1 -0
- package/harness/cli/dist/services/doctor/doctor-service.d.ts +69 -0
- package/harness/cli/dist/services/doctor/doctor-service.js +237 -0
- package/harness/cli/dist/services/doctor/doctor-service.js.map +1 -0
- package/harness/cli/dist/services/extensions/contract.d.ts +138 -0
- package/harness/cli/dist/services/extensions/contract.js +17 -0
- package/harness/cli/dist/services/extensions/contract.js.map +1 -0
- package/harness/cli/dist/services/extensions/discovery.d.ts +53 -0
- package/harness/cli/dist/services/extensions/discovery.js +116 -0
- package/harness/cli/dist/services/extensions/discovery.js.map +1 -0
- package/harness/cli/dist/services/extensions/registry.d.ts +63 -0
- package/harness/cli/dist/services/extensions/registry.js +165 -0
- package/harness/cli/dist/services/extensions/registry.js.map +1 -0
- package/harness/cli/dist/services/extensions/verb-context.d.ts +44 -0
- package/harness/cli/dist/services/extensions/verb-context.js +97 -0
- package/harness/cli/dist/services/extensions/verb-context.js.map +1 -0
- package/harness/cli/dist/services/help/help-service.d.ts +42 -0
- package/harness/cli/dist/services/help/help-service.js +108 -0
- package/harness/cli/dist/services/help/help-service.js.map +1 -0
- package/harness/cli/dist/services/init/governance-template.d.ts +27 -0
- package/harness/cli/dist/services/init/governance-template.js +72 -0
- package/harness/cli/dist/services/init/governance-template.js.map +1 -0
- package/harness/cli/dist/services/init/init-service.d.ts +38 -0
- package/harness/cli/dist/services/init/init-service.js +44 -0
- package/harness/cli/dist/services/init/init-service.js.map +1 -0
- package/harness/cli/dist/services/instructions/core-instructions.d.ts +11 -0
- package/harness/cli/dist/services/instructions/core-instructions.js +80 -0
- package/harness/cli/dist/services/instructions/core-instructions.js.map +1 -0
- package/harness/cli/dist/services/instructions/instructions-service.d.ts +52 -0
- package/harness/cli/dist/services/instructions/instructions-service.js +53 -0
- package/harness/cli/dist/services/instructions/instructions-service.js.map +1 -0
- package/harness/cli/dist/services/observe/buffer-codec.d.ts +51 -0
- package/harness/cli/dist/services/observe/buffer-codec.js +139 -0
- package/harness/cli/dist/services/observe/buffer-codec.js.map +1 -0
- package/harness/cli/dist/services/observe/observe-service.d.ts +87 -0
- package/harness/cli/dist/services/observe/observe-service.js +221 -0
- package/harness/cli/dist/services/observe/observe-service.js.map +1 -0
- package/harness/cli/dist/services/record/contract.d.ts +32 -0
- package/harness/cli/dist/services/record/contract.js +17 -0
- package/harness/cli/dist/services/record/contract.js.map +1 -0
- package/harness/cli/dist/services/record/core-types/retro.d.ts +20 -0
- package/harness/cli/dist/services/record/core-types/retro.js +55 -0
- package/harness/cli/dist/services/record/core-types/retro.js.map +1 -0
- package/harness/cli/dist/services/record/record-service.d.ts +38 -0
- package/harness/cli/dist/services/record/record-service.js +144 -0
- package/harness/cli/dist/services/record/record-service.js.map +1 -0
- package/harness/cli/dist/services/record/registry.d.ts +46 -0
- package/harness/cli/dist/services/record/registry.js +71 -0
- package/harness/cli/dist/services/record/registry.js.map +1 -0
- package/harness/cli/dist/services/scaffold/scaffold-service.d.ts +29 -0
- package/harness/cli/dist/services/scaffold/scaffold-service.js +88 -0
- package/harness/cli/dist/services/scaffold/scaffold-service.js.map +1 -0
- package/harness/cli/dist/services/scaffold/templates.d.ts +42 -0
- package/harness/cli/dist/services/scaffold/templates.js +178 -0
- package/harness/cli/dist/services/scaffold/templates.js.map +1 -0
- package/harness/cli/dist/services/shared/posix-path.d.ts +54 -0
- package/harness/cli/dist/services/shared/posix-path.js +94 -0
- package/harness/cli/dist/services/shared/posix-path.js.map +1 -0
- package/harness/cli/dist/services/shared/temp.d.ts +24 -0
- package/harness/cli/dist/services/shared/temp.js +29 -0
- package/harness/cli/dist/services/shared/temp.js.map +1 -0
- package/harness/cli/dist/services/skills/contract.d.ts +52 -0
- package/harness/cli/dist/services/skills/contract.js +55 -0
- package/harness/cli/dist/services/skills/contract.js.map +1 -0
- package/harness/cli/dist/services/skills/skills-service.d.ts +73 -0
- package/harness/cli/dist/services/skills/skills-service.js +132 -0
- package/harness/cli/dist/services/skills/skills-service.js.map +1 -0
- package/harness/cli/dist/services/update/banner.d.ts +26 -0
- package/harness/cli/dist/services/update/banner.js +28 -0
- package/harness/cli/dist/services/update/banner.js.map +1 -0
- package/harness/cli/dist/services/update/cache.d.ts +21 -0
- package/harness/cli/dist/services/update/cache.js +61 -0
- package/harness/cli/dist/services/update/cache.js.map +1 -0
- package/harness/cli/dist/services/update/constants.d.ts +9 -0
- package/harness/cli/dist/services/update/constants.js +10 -0
- package/harness/cli/dist/services/update/constants.js.map +1 -0
- package/harness/cli/dist/services/update/install.d.ts +26 -0
- package/harness/cli/dist/services/update/install.js +78 -0
- package/harness/cli/dist/services/update/install.js.map +1 -0
- package/harness/cli/dist/services/update/semver.d.ts +16 -0
- package/harness/cli/dist/services/update/semver.js +108 -0
- package/harness/cli/dist/services/update/semver.js.map +1 -0
- package/harness/cli/dist/services/update/update-service.d.ts +46 -0
- package/harness/cli/dist/services/update/update-service.js +91 -0
- package/harness/cli/dist/services/update/update-service.js.map +1 -0
- package/harness/cli/dist/version.d.ts +8 -0
- package/harness/cli/dist/version.js +15 -0
- package/harness/cli/dist/version.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { formatDegraded, formatError, formatOk } from '../output/envelope.js';
|
|
2
|
+
import { ErrorCodes } from '../output/error-codes.js';
|
|
3
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
4
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
5
|
+
import { DEFAULT_SKILLS_SOURCE, KNOWN_SKILL_TARGETS, LEGACY_SKILL_SLUGS, } from '../services/skills/contract.js';
|
|
6
|
+
import { buildInstallArgv, buildRemoveArgv, formatInstallCommand, resolveSkillsSource, } from '../services/skills/skills-service.js';
|
|
7
|
+
const SKILLS_DOCS_URL = 'https://github.com/vercel-labs/skills';
|
|
8
|
+
const MAX_STDERR_TAIL = 800;
|
|
9
|
+
/**
|
|
10
|
+
* Emit an actionable `E108` (invalid args) and exit 1 — shared by the install/update
|
|
11
|
+
* subcommands. Never blocks on a prompt: the CLI is agent-first, so a bad flag combo
|
|
12
|
+
* returns guidance, not a hang. JSON → a single envelope on stdout; human → stderr
|
|
13
|
+
* lines prefixed with `label` (e.g. `harness skills install`).
|
|
14
|
+
*/
|
|
15
|
+
function failInvalidArgs(io, deps, label, message, next_action) {
|
|
16
|
+
const envelope = formatError('skills', ErrorCodes.INVALID_ARGS, message, deps.clock, {
|
|
17
|
+
next_action,
|
|
18
|
+
});
|
|
19
|
+
const port = io.mode === 'json'
|
|
20
|
+
? createOutputPort('json', io.writers)
|
|
21
|
+
: {
|
|
22
|
+
emit: (e) => {
|
|
23
|
+
io.writers.err(`${label}: ${e.error?.message ?? 'failed'}\n`);
|
|
24
|
+
if (e.next_action)
|
|
25
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
exitWithEnvelope(envelope, port);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Register the `skills` command + its `install` subcommand — a first-class CORE
|
|
32
|
+
* capability (reserved, like `help`/`doctor`/`new`/`docs`; it ships with the
|
|
33
|
+
* published CLI so the harness can install its own skills in any repo). It owns
|
|
34
|
+
* no install logic: it is a transparent PASS-THROUGH to Vercel's `npx skills add`
|
|
35
|
+
* (Principle 8, wrap-don't-rebuild — that tool already owns the CLI-target × scope
|
|
36
|
+
* matrix). The act:
|
|
37
|
+
* - builds the exact argv with the pure `buildInstallArgv` (always `-y`, so the
|
|
38
|
+
* blocking interactive picker never appears);
|
|
39
|
+
* - **announces the exact `npx …` command before running it** — to stderr in
|
|
40
|
+
* human mode, and inside the envelope (`data.command` + `next_action`) in JSON
|
|
41
|
+
* mode, so the `--json` stdout stays a single parseable envelope (Principle 4);
|
|
42
|
+
* - shells out ONLY through the injected `ExecPort` (no direct child/shell);
|
|
43
|
+
* - maps the result onto an Envelope + exit code (ok → 0, `E170` → 1).
|
|
44
|
+
*
|
|
45
|
+
* Targets are flags, not a blocking prompt: the harness CLI is agent-first and
|
|
46
|
+
* non-blocking, so a missing `--target` returns `E108` with a `next_action` that
|
|
47
|
+
* enumerates the valid targets. The *skill* (`eng-harness-0-adopt`) is what asks
|
|
48
|
+
* the user, then runs this with flags.
|
|
49
|
+
*/
|
|
50
|
+
export function registerSkillsAct(program, io, deps) {
|
|
51
|
+
const skills = program
|
|
52
|
+
.command('skills')
|
|
53
|
+
.description("Install this harness's skills via the Vercel `npx skills` CLI");
|
|
54
|
+
// Bare `harness skills` → agent-friendly orientation (no blocking, exit 0).
|
|
55
|
+
skills.action(() => {
|
|
56
|
+
const envelope = formatOk('skills', { subcommands: ['install', 'update'], installer: SKILLS_DOCS_URL }, deps.clock, {
|
|
57
|
+
next_action: 'Run `harness skills install --target <cli> [--global]` (or `update` to refresh + prune).',
|
|
58
|
+
});
|
|
59
|
+
const port = io.mode === 'json'
|
|
60
|
+
? createOutputPort('json', io.writers)
|
|
61
|
+
: {
|
|
62
|
+
emit: () => io.writers.out("harness skills — install this harness's skills.\n" +
|
|
63
|
+
' harness skills install --target <cli> [--global] # add / refresh\n' +
|
|
64
|
+
' harness skills update --target <cli> [--global] # refresh to latest + prune renamed/removed\n'),
|
|
65
|
+
};
|
|
66
|
+
exitWithEnvelope(envelope, port);
|
|
67
|
+
});
|
|
68
|
+
skills
|
|
69
|
+
.command('install')
|
|
70
|
+
.description("Install this repo's skills into a CLI (pass-through to `npx skills add`, always -y)")
|
|
71
|
+
.option('-t, --target <cli...>', `CLI target(s), repeatable: ${KNOWN_SKILL_TARGETS.join(', ')}`)
|
|
72
|
+
.option('-g, --global', 'install globally (omit for a project-local install)')
|
|
73
|
+
.option('--source <repo>', 'skills source (owner/repo or local path)', DEFAULT_SKILLS_SOURCE)
|
|
74
|
+
.option('-b, --branch <ref>', 'install from a branch (single-segment; rewrites a GitHub source to /tree/<ref>). Also accepted as --source owner/repo#ref')
|
|
75
|
+
.option('-s, --skill <slug...>', 'install only specific skill slug(s)')
|
|
76
|
+
.action(async (opts) => {
|
|
77
|
+
const targets = opts.target ?? [];
|
|
78
|
+
const jsonPort = () => createOutputPort('json', io.writers);
|
|
79
|
+
// No target → at least one CLI target is required. Fail fast with an actionable
|
|
80
|
+
// E108 (never block on a prompt — the CLI is agent-first).
|
|
81
|
+
if (targets.length === 0) {
|
|
82
|
+
failInvalidArgs(io, deps, 'harness skills install', 'no --target given: at least one CLI target is required.', `Pass --target <cli> (one or more of: ${KNOWN_SKILL_TARGETS.join(', ')}). Example: harness skills install --target github-copilot --global`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Resolve --source (+ --branch / a `#ref` suffix) into the specifier the
|
|
86
|
+
// Vercel installer truly accepts (a GitHub /tree/<ref> URL for a branch).
|
|
87
|
+
const resolved = resolveSkillsSource(opts.source, opts.branch);
|
|
88
|
+
if (!resolved.ok) {
|
|
89
|
+
failInvalidArgs(io, deps, 'harness skills install', resolved.reason, `Re-run with a valid source/branch. ${resolved.reason}`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const installOpts = {
|
|
93
|
+
source: resolved.source,
|
|
94
|
+
targets,
|
|
95
|
+
global: Boolean(opts.global),
|
|
96
|
+
skills: opts.skill,
|
|
97
|
+
};
|
|
98
|
+
const argv = buildInstallArgv(installOpts);
|
|
99
|
+
const command = formatInstallCommand(argv);
|
|
100
|
+
// Announce BEFORE running. Human → stderr; JSON → folded into the envelope (data + next_action),
|
|
101
|
+
// never prose on stdout (keeps `--json` stdout a single valid envelope).
|
|
102
|
+
if (io.mode !== 'json') {
|
|
103
|
+
io.writers.err(`harness skills install — about to run:\n ${command}\n` +
|
|
104
|
+
`(wraps the Vercel skills installer — more at ${SKILLS_DOCS_URL})\n`);
|
|
105
|
+
}
|
|
106
|
+
const result = await deps.exec.run('npx', argv, { cwd: deps.proc.cwd() });
|
|
107
|
+
if (result.ok) {
|
|
108
|
+
const envelope = formatOk('skills', {
|
|
109
|
+
command,
|
|
110
|
+
targets,
|
|
111
|
+
global: Boolean(opts.global),
|
|
112
|
+
source: resolved.source,
|
|
113
|
+
...(resolved.branch ? { branch: resolved.branch } : {}),
|
|
114
|
+
installer: SKILLS_DOCS_URL,
|
|
115
|
+
}, deps.clock, {
|
|
116
|
+
next_action: `Skills installed for ${targets.join(', ')}. Verify with your CLI's skills listing.`,
|
|
117
|
+
});
|
|
118
|
+
const port = io.mode === 'json'
|
|
119
|
+
? jsonPort()
|
|
120
|
+
: {
|
|
121
|
+
emit: () => {
|
|
122
|
+
if (result.stdout.trim())
|
|
123
|
+
io.writers.out(`${result.stdout.replace(/\n$/, '')}\n`);
|
|
124
|
+
io.writers.out(`skills install: ok (${targets.join(', ')})\n`);
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
exitWithEnvelope(envelope, port);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const envelope = formatError('skills', ErrorCodes.SKILLS_INSTALL_FAILED, `\`npx skills add\` failed (exit ${result.code}).`, deps.clock, {
|
|
131
|
+
next_action: `Check network + that \`npx\` is available, then re-run: ${command}`,
|
|
132
|
+
details: { command, stderr_tail: result.stderr.slice(-MAX_STDERR_TAIL) },
|
|
133
|
+
});
|
|
134
|
+
const port = io.mode === 'json'
|
|
135
|
+
? jsonPort()
|
|
136
|
+
: {
|
|
137
|
+
emit: (e) => {
|
|
138
|
+
if (result.stderr.trim())
|
|
139
|
+
io.writers.err(`${result.stderr.replace(/\n$/, '')}\n`);
|
|
140
|
+
io.writers.err(`harness skills install: ${e.error?.message ?? 'failed'}\n`);
|
|
141
|
+
if (e.next_action)
|
|
142
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
exitWithEnvelope(envelope, port);
|
|
146
|
+
});
|
|
147
|
+
skills
|
|
148
|
+
.command('update')
|
|
149
|
+
.description("Update this repo's skills to latest AND prune renamed/removed ones (refresh via `npx skills add`, then `npx skills remove` the legacy slugs)")
|
|
150
|
+
.option('-t, --target <cli...>', `CLI target(s), repeatable: ${KNOWN_SKILL_TARGETS.join(', ')}`)
|
|
151
|
+
.option('-g, --global', 'update the global install (omit for a project-local update)')
|
|
152
|
+
.option('--source <repo>', 'skills source (owner/repo or local path)', DEFAULT_SKILLS_SOURCE)
|
|
153
|
+
.option('-b, --branch <ref>', 'update from a branch (single-segment; rewrites a GitHub source to /tree/<ref>). Also accepted as --source owner/repo#ref')
|
|
154
|
+
.action(async (opts) => {
|
|
155
|
+
const targets = opts.target ?? [];
|
|
156
|
+
const jsonPort = () => createOutputPort('json', io.writers);
|
|
157
|
+
// No target → at least one CLI target is required (same agent-first E108 as install).
|
|
158
|
+
if (targets.length === 0) {
|
|
159
|
+
failInvalidArgs(io, deps, 'harness skills update', 'no --target given: at least one CLI target is required.', `Pass --target <cli> (one or more of: ${KNOWN_SKILL_TARGETS.join(', ')}). Example: harness skills update --target github-copilot --global`);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const resolved = resolveSkillsSource(opts.source, opts.branch);
|
|
163
|
+
if (!resolved.ok) {
|
|
164
|
+
failInvalidArgs(io, deps, 'harness skills update', resolved.reason, `Re-run with a valid source/branch. ${resolved.reason}`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const global = Boolean(opts.global);
|
|
168
|
+
const refreshArgv = buildInstallArgv({ source: resolved.source, targets, global });
|
|
169
|
+
const refreshCommand = formatInstallCommand(refreshArgv);
|
|
170
|
+
const removeOpts = { slugs: [...LEGACY_SKILL_SLUGS], targets, global };
|
|
171
|
+
const pruneArgv = buildRemoveArgv(removeOpts);
|
|
172
|
+
const pruneCommand = formatInstallCommand(pruneArgv);
|
|
173
|
+
// Announce BOTH commands before running. Human → stderr; JSON → folded into the
|
|
174
|
+
// envelope (refresh_command + prune_command), never prose on stdout.
|
|
175
|
+
if (io.mode !== 'json') {
|
|
176
|
+
io.writers.err(`harness skills update — about to run:\n ${refreshCommand}\n ${pruneCommand}\n` +
|
|
177
|
+
`(refresh to latest, then prune renamed/removed skills — wraps the Vercel skills installer; more at ${SKILLS_DOCS_URL})\n`);
|
|
178
|
+
}
|
|
179
|
+
const cwd = deps.proc.cwd();
|
|
180
|
+
// 1) Refresh: install/refresh the current published set (also pulls any NEW skills).
|
|
181
|
+
// If this fails we DON'T prune — the existing skills stay intact (no regression).
|
|
182
|
+
const refresh = await deps.exec.run('npx', refreshArgv, { cwd });
|
|
183
|
+
if (!refresh.ok) {
|
|
184
|
+
const envelope = formatError('skills', ErrorCodes.SKILLS_INSTALL_FAILED, `\`npx skills add\` (refresh) failed (exit ${refresh.code}); skills left unchanged (prune not attempted).`, deps.clock, {
|
|
185
|
+
next_action: `Check network + that \`npx\` is available, then re-run: harness skills update --target ${targets.join(' --target ')}${global ? ' --global' : ''}`,
|
|
186
|
+
details: {
|
|
187
|
+
command: refreshCommand,
|
|
188
|
+
stderr_tail: refresh.stderr.slice(-MAX_STDERR_TAIL),
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
const port = io.mode === 'json'
|
|
192
|
+
? jsonPort()
|
|
193
|
+
: {
|
|
194
|
+
emit: (e) => {
|
|
195
|
+
if (refresh.stderr.trim())
|
|
196
|
+
io.writers.err(`${refresh.stderr.replace(/\n$/, '')}\n`);
|
|
197
|
+
io.writers.err(`harness skills update: ${e.error?.message ?? 'failed'}\n`);
|
|
198
|
+
if (e.next_action)
|
|
199
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
exitWithEnvelope(envelope, port);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// 2) Prune: remove the renamed/removed legacy slugs (no-ops on any not installed).
|
|
206
|
+
const prune = await deps.exec.run('npx', pruneArgv, { cwd });
|
|
207
|
+
const baseData = {
|
|
208
|
+
refresh_command: refreshCommand,
|
|
209
|
+
prune_command: pruneCommand,
|
|
210
|
+
pruned_candidates: [...LEGACY_SKILL_SLUGS],
|
|
211
|
+
targets,
|
|
212
|
+
global,
|
|
213
|
+
source: resolved.source,
|
|
214
|
+
...(resolved.branch ? { branch: resolved.branch } : {}),
|
|
215
|
+
installer: SKILLS_DOCS_URL,
|
|
216
|
+
};
|
|
217
|
+
if (prune.ok) {
|
|
218
|
+
const envelope = formatOk('skills', baseData, deps.clock, {
|
|
219
|
+
next_action: `Skills updated for ${targets.join(', ')} — refreshed to latest and pruned renamed/removed slugs. Verify with your CLI's skills listing.`,
|
|
220
|
+
});
|
|
221
|
+
const port = io.mode === 'json'
|
|
222
|
+
? jsonPort()
|
|
223
|
+
: {
|
|
224
|
+
emit: () => {
|
|
225
|
+
if (refresh.stdout.trim())
|
|
226
|
+
io.writers.out(`${refresh.stdout.replace(/\n$/, '')}\n`);
|
|
227
|
+
io.writers.out(`skills update: ok (${targets.join(', ')}) — refreshed + pruned\n`);
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
exitWithEnvelope(envelope, port);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
// Refresh succeeded but prune failed → degraded (exit 0): latest IS installed, but
|
|
234
|
+
// renamed copies may linger. Honest, recoverable — re-run the prune by hand.
|
|
235
|
+
const envelope = formatDegraded('skills', {
|
|
236
|
+
...baseData,
|
|
237
|
+
prune_failed: true,
|
|
238
|
+
prune_stderr_tail: prune.stderr.slice(-MAX_STDERR_TAIL),
|
|
239
|
+
}, `Refreshed to latest, but pruning renamed skills failed (exit ${prune.code}). Re-run the prune manually: ${pruneCommand}`, deps.clock);
|
|
240
|
+
const port = io.mode === 'json'
|
|
241
|
+
? jsonPort()
|
|
242
|
+
: {
|
|
243
|
+
emit: (e) => {
|
|
244
|
+
if (refresh.stdout.trim())
|
|
245
|
+
io.writers.out(`${refresh.stdout.replace(/\n$/, '')}\n`);
|
|
246
|
+
if (prune.stderr.trim())
|
|
247
|
+
io.writers.err(`${prune.stderr.replace(/\n$/, '')}\n`);
|
|
248
|
+
io.writers.out(`skills update: refreshed (${targets.join(', ')}); prune incomplete\n`);
|
|
249
|
+
if (e.next_action)
|
|
250
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
exitWithEnvelope(envelope, port);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/acts/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { EnvPort } from '../adapters/env/env-port.js';
|
|
4
|
+
import type { ExecPort } from '../adapters/exec/exec-port.js';
|
|
5
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
6
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
7
|
+
import { type CliIo } from '../output/output-port.js';
|
|
8
|
+
/** The ports the `update`/`self-install` acts inject — a subset of VerbActDeps (no git). */
|
|
9
|
+
export interface UpdateActDeps {
|
|
10
|
+
exec: ExecPort;
|
|
11
|
+
fs: FsPort;
|
|
12
|
+
env: EnvPort;
|
|
13
|
+
clock: Clock;
|
|
14
|
+
proc: ProcessPort;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Register `harness update` (+ `--check` / `--pin` / `--target`) and `self-install`.
|
|
18
|
+
* CORE commands that keep the globally-installed CLI current from the GitHub
|
|
19
|
+
* Packages release (plan 018) AND reconcile this harness's skills. Every `update`
|
|
20
|
+
* envelope carries a `skills` sub-object: report-only without `--target`,
|
|
21
|
+
* refreshed+pruned with it. `installed` is the running version.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerUpdateAct(program: Command, io: CliIo, deps: UpdateActDeps, installed: string): void;
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { NodeVersionLookup } from '../adapters/version-lookup/node-version-lookup.js';
|
|
2
|
+
import { formatDegraded, formatError, formatOk } from '../output/envelope.js';
|
|
3
|
+
import { ErrorCodes } from '../output/error-codes.js';
|
|
4
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
5
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
6
|
+
import { DEFAULT_SKILLS_SOURCE, KNOWN_SKILL_TARGETS, LEGACY_SKILL_SLUGS, } from '../services/skills/contract.js';
|
|
7
|
+
import { buildInstallArgv, buildRemoveArgv, formatInstallCommand, } from '../services/skills/skills-service.js';
|
|
8
|
+
import { PACKAGE_NAME } from '../services/update/constants.js';
|
|
9
|
+
import { classifyInstallFailure, formatNpmCommand, normalizePin, npmInstallArgv, } from '../services/update/install.js';
|
|
10
|
+
import { isValidVersion } from '../services/update/semver.js';
|
|
11
|
+
import { runCheck } from '../services/update/update-service.js';
|
|
12
|
+
const MAX_STDERR_TAIL = 800;
|
|
13
|
+
const severity = (s) => s === 'error' ? 3 : s === 'unconfigured' ? 2 : s === 'degraded' ? 1 : 0;
|
|
14
|
+
const worst = (a, b) => (severity(a) >= severity(b) ? a : b);
|
|
15
|
+
/**
|
|
16
|
+
* Run a global `npm i -g <pkg>@<spec>` and build the outcome (no exit). Announces
|
|
17
|
+
* the exact command first (human → stderr), shells ONLY through the injected
|
|
18
|
+
* ExecPort, and maps a failure via `classifyInstallFailure` (AC10).
|
|
19
|
+
*/
|
|
20
|
+
async function runNpmInstall(io, deps, commandName, installed, spec, installedAfter) {
|
|
21
|
+
const argv = npmInstallArgv(spec);
|
|
22
|
+
const command = formatNpmCommand(argv);
|
|
23
|
+
if (io.mode !== 'json') {
|
|
24
|
+
io.writers.err(`harness ${commandName} — about to run:\n ${command}\n`);
|
|
25
|
+
}
|
|
26
|
+
const result = await deps.exec.run('npm', argv, { cwd: deps.proc.cwd() });
|
|
27
|
+
if (result.ok) {
|
|
28
|
+
return {
|
|
29
|
+
status: 'ok',
|
|
30
|
+
data: { installed_before: installed, installed_after: installedAfter, command },
|
|
31
|
+
next_action: `Done. Verify with \`harness --version\`${installedAfter ? ` (expecting ${installedAfter})` : ''}.`,
|
|
32
|
+
summary: `${commandName}: ok${installedAfter ? ` (${installedAfter})` : ''}`,
|
|
33
|
+
stdout: result.stdout,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const failure = classifyInstallFailure(result, command, spec === 'latest' ? undefined : { pinned: spec });
|
|
37
|
+
return {
|
|
38
|
+
status: 'error',
|
|
39
|
+
data: { command },
|
|
40
|
+
error: {
|
|
41
|
+
code: failure.code,
|
|
42
|
+
message: failure.message,
|
|
43
|
+
details: { command, stderr_tail: result.stderr.slice(-MAX_STDERR_TAIL) },
|
|
44
|
+
},
|
|
45
|
+
next_action: failure.next_action,
|
|
46
|
+
summary: `${commandName}: failed`,
|
|
47
|
+
stderr: result.stderr,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Emit a single binary envelope (self-install, and the update error-early path), then exit. */
|
|
51
|
+
function emitBinary(io, deps, commandName, o) {
|
|
52
|
+
const jsonPort = () => createOutputPort('json', io.writers);
|
|
53
|
+
if (o.status === 'error' && o.error) {
|
|
54
|
+
const envelope = formatError(commandName, o.error.code, o.error.message, deps.clock, {
|
|
55
|
+
next_action: o.next_action,
|
|
56
|
+
details: o.error.details,
|
|
57
|
+
});
|
|
58
|
+
const port = io.mode === 'json'
|
|
59
|
+
? jsonPort()
|
|
60
|
+
: {
|
|
61
|
+
emit: (e) => {
|
|
62
|
+
if (o.stderr?.trim())
|
|
63
|
+
io.writers.err(`${o.stderr.replace(/\n$/, '')}\n`);
|
|
64
|
+
io.writers.err(`harness ${commandName}: ${e.error?.message ?? 'failed'}\n`);
|
|
65
|
+
if (e.next_action)
|
|
66
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
exitWithEnvelope(envelope, port);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const envelope = formatOk(commandName, o.data, deps.clock, { next_action: o.next_action });
|
|
73
|
+
const port = io.mode === 'json'
|
|
74
|
+
? jsonPort()
|
|
75
|
+
: {
|
|
76
|
+
emit: () => {
|
|
77
|
+
if (o.stdout?.trim())
|
|
78
|
+
io.writers.out(`${o.stdout.replace(/\n$/, '')}\n`);
|
|
79
|
+
io.writers.out(`${o.summary}\n`);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
exitWithEnvelope(envelope, port);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The skills half of `harness update`. With `--target` (and not `--check`) it
|
|
86
|
+
* reconciles via the EXISTING skills-update path — refresh (`npx skills add`)
|
|
87
|
+
* then prune the legacy slugs (`npx skills remove`), reusing the already-exported
|
|
88
|
+
* helpers (KF-05). Refresh-fail ⇒ error; prune-fail ⇒ degraded. Without a target
|
|
89
|
+
* (or under `--check`) it is REPORT-ONLY: it mutates nothing, lists the prune
|
|
90
|
+
* candidates, and suggests the exact command (AC13/AC14).
|
|
91
|
+
*/
|
|
92
|
+
async function skillsOutcome(io, deps, opts) {
|
|
93
|
+
const targets = opts.target ?? [];
|
|
94
|
+
const global = Boolean(opts.global);
|
|
95
|
+
const reconcile = !opts.check && targets.length > 0;
|
|
96
|
+
if (!reconcile) {
|
|
97
|
+
return {
|
|
98
|
+
status: 'ok',
|
|
99
|
+
skills: {
|
|
100
|
+
reconciled: false,
|
|
101
|
+
prune_candidates: [...LEGACY_SKILL_SLUGS],
|
|
102
|
+
suggested_command: 'harness skills update --target <cli>',
|
|
103
|
+
},
|
|
104
|
+
next_action: `To also refresh + prune this harness's skills, run: harness skills update --target <cli> (targets: ${KNOWN_SKILL_TARGETS.join(', ')}).`,
|
|
105
|
+
summary: `skills: report-only — run \`harness skills update --target <cli>\` to refresh + prune (${LEGACY_SKILL_SLUGS.length} legacy slugs tracked)`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const refreshArgv = buildInstallArgv({ source: DEFAULT_SKILLS_SOURCE, targets, global });
|
|
109
|
+
const refreshCommand = formatInstallCommand(refreshArgv);
|
|
110
|
+
const pruneArgv = buildRemoveArgv({ slugs: [...LEGACY_SKILL_SLUGS], targets, global });
|
|
111
|
+
const pruneCommand = formatInstallCommand(pruneArgv);
|
|
112
|
+
if (io.mode !== 'json') {
|
|
113
|
+
io.writers.err(`harness update — reconciling skills:\n ${refreshCommand}\n ${pruneCommand}\n`);
|
|
114
|
+
}
|
|
115
|
+
const cwd = deps.proc.cwd();
|
|
116
|
+
// Refresh first; if it fails we DON'T prune (existing skills stay intact).
|
|
117
|
+
const refresh = await deps.exec.run('npx', refreshArgv, { cwd });
|
|
118
|
+
if (!refresh.ok) {
|
|
119
|
+
return {
|
|
120
|
+
status: 'error',
|
|
121
|
+
skills: {
|
|
122
|
+
reconciled: true,
|
|
123
|
+
refreshed: false,
|
|
124
|
+
pruned: false,
|
|
125
|
+
targets,
|
|
126
|
+
global,
|
|
127
|
+
refresh_command: refreshCommand,
|
|
128
|
+
stderr_tail: refresh.stderr.slice(-MAX_STDERR_TAIL),
|
|
129
|
+
},
|
|
130
|
+
next_action: `Skills refresh failed (exit ${refresh.code}); skills left unchanged. Re-run: ${refreshCommand}`,
|
|
131
|
+
summary: `skills: refresh failed (${targets.join(', ')})`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const prune = await deps.exec.run('npx', pruneArgv, { cwd });
|
|
135
|
+
if (prune.ok) {
|
|
136
|
+
return {
|
|
137
|
+
status: 'ok',
|
|
138
|
+
skills: {
|
|
139
|
+
reconciled: true,
|
|
140
|
+
refreshed: true,
|
|
141
|
+
pruned: true,
|
|
142
|
+
targets,
|
|
143
|
+
global,
|
|
144
|
+
refresh_command: refreshCommand,
|
|
145
|
+
prune_command: pruneCommand,
|
|
146
|
+
pruned_candidates: [...LEGACY_SKILL_SLUGS],
|
|
147
|
+
},
|
|
148
|
+
next_action: `Skills reconciled for ${targets.join(', ')} (refreshed + pruned).`,
|
|
149
|
+
summary: `skills: reconciled (${targets.join(', ')}) — refreshed + pruned`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
status: 'degraded',
|
|
154
|
+
skills: {
|
|
155
|
+
reconciled: true,
|
|
156
|
+
refreshed: true,
|
|
157
|
+
pruned: false,
|
|
158
|
+
targets,
|
|
159
|
+
global,
|
|
160
|
+
refresh_command: refreshCommand,
|
|
161
|
+
prune_command: pruneCommand,
|
|
162
|
+
prune_stderr_tail: prune.stderr.slice(-MAX_STDERR_TAIL),
|
|
163
|
+
},
|
|
164
|
+
next_action: `Skills refreshed but prune failed (exit ${prune.code}). Re-run the prune: ${pruneCommand}`,
|
|
165
|
+
summary: `skills: refreshed (${targets.join(', ')}); prune incomplete`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/** Compute the binary (CLI) outcome for the chosen mode (--check / --pin / bare). */
|
|
169
|
+
async function binaryOutcome(io, deps, installed, opts) {
|
|
170
|
+
const lookup = new NodeVersionLookup(deps.exec, PACKAGE_NAME, deps.proc.cwd());
|
|
171
|
+
if (opts.check) {
|
|
172
|
+
const result = await runCheck({ fs: deps.fs, env: deps.env, clock: deps.clock, lookup }, installed, {
|
|
173
|
+
force: true,
|
|
174
|
+
});
|
|
175
|
+
const available = result.update_available !== null;
|
|
176
|
+
return {
|
|
177
|
+
status: 'ok',
|
|
178
|
+
data: { installed, latest: result.latest, update_available: available },
|
|
179
|
+
next_action: available
|
|
180
|
+
? `A newer version (${result.latest}) is available. Run \`harness update\` to upgrade.`
|
|
181
|
+
: result.latest
|
|
182
|
+
? `You are on the latest version (${installed}).`
|
|
183
|
+
: 'Could not determine the latest version (registry unreachable or auth missing).',
|
|
184
|
+
summary: `update --check: installed ${installed}, latest ${result.latest ?? 'unknown'}${available ? ' — update available' : ''}`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (opts.pin) {
|
|
188
|
+
const spec = normalizePin(opts.pin);
|
|
189
|
+
// --pin is for ONE concrete version (AC3). Reject dist-tags like `latest`/
|
|
190
|
+
// `canary` — bare `harness update` is the way to track @latest (companion F005).
|
|
191
|
+
if (!isValidVersion(spec)) {
|
|
192
|
+
return {
|
|
193
|
+
status: 'error',
|
|
194
|
+
data: { pin: opts.pin },
|
|
195
|
+
error: {
|
|
196
|
+
code: ErrorCodes.INVALID_ARGS,
|
|
197
|
+
message: `--pin needs a concrete version (e.g. v0.3.0), not '${opts.pin}'.`,
|
|
198
|
+
},
|
|
199
|
+
next_action: `Pass an exact version: harness update --pin v0.3.0 (run harness update --check for the latest, or bare harness update to track @latest).`,
|
|
200
|
+
summary: `update --pin: invalid version '${opts.pin}'`,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
return runNpmInstall(io, deps, 'update', installed, spec, spec);
|
|
204
|
+
}
|
|
205
|
+
const result = await runCheck({ fs: deps.fs, env: deps.env, clock: deps.clock, lookup }, installed, {
|
|
206
|
+
force: true,
|
|
207
|
+
});
|
|
208
|
+
if (result.latest && result.update_available === null) {
|
|
209
|
+
const command = formatNpmCommand(npmInstallArgv('latest'));
|
|
210
|
+
return {
|
|
211
|
+
status: 'ok',
|
|
212
|
+
data: {
|
|
213
|
+
installed_before: installed,
|
|
214
|
+
installed_after: installed,
|
|
215
|
+
command,
|
|
216
|
+
already_latest: true,
|
|
217
|
+
},
|
|
218
|
+
next_action: `Already on the latest version (${installed}).`,
|
|
219
|
+
summary: `update: already on latest (${installed})`,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return runNpmInstall(io, deps, 'update', installed, 'latest', result.latest);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Register `harness update` (+ `--check` / `--pin` / `--target`) and `self-install`.
|
|
226
|
+
* CORE commands that keep the globally-installed CLI current from the GitHub
|
|
227
|
+
* Packages release (plan 018) AND reconcile this harness's skills. Every `update`
|
|
228
|
+
* envelope carries a `skills` sub-object: report-only without `--target`,
|
|
229
|
+
* refreshed+pruned with it. `installed` is the running version.
|
|
230
|
+
*/
|
|
231
|
+
export function registerUpdateAct(program, io, deps, installed) {
|
|
232
|
+
program
|
|
233
|
+
.command('update')
|
|
234
|
+
.description('Update the globally-installed harness CLI from the registry (and reconcile skills with --target)')
|
|
235
|
+
.option('--check', 'check for a newer version without installing (exit 0)')
|
|
236
|
+
.option('--pin <version>', 'install one exact version (e.g. v0.3.0), not persisted')
|
|
237
|
+
.option('-t, --target <cli...>', `also reconcile skills for CLI target(s): ${KNOWN_SKILL_TARGETS.join(', ')}`)
|
|
238
|
+
.option('-g, --global', 'with --target: reconcile the global skills install')
|
|
239
|
+
.action(async (opts) => {
|
|
240
|
+
const binary = await binaryOutcome(io, deps, installed, opts);
|
|
241
|
+
// Binary failure → pure error envelope; skip skills (fix the CLI update first).
|
|
242
|
+
if (binary.status === 'error') {
|
|
243
|
+
emitBinary(io, deps, 'update', binary);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const skills = await skillsOutcome(io, deps, opts);
|
|
247
|
+
const status = worst(binary.status, skills.status);
|
|
248
|
+
const data = { ...binary.data, skills: skills.skills };
|
|
249
|
+
const jsonPort = () => createOutputPort('json', io.writers);
|
|
250
|
+
// Skills refresh failed → error/1 (AC14), with the combined data in details.
|
|
251
|
+
if (status === 'error') {
|
|
252
|
+
const envelope = formatError('update', ErrorCodes.SKILLS_INSTALL_FAILED, 'the CLI is current, but the skills refresh failed.', deps.clock, { next_action: skills.next_action, details: data });
|
|
253
|
+
const port = io.mode === 'json'
|
|
254
|
+
? jsonPort()
|
|
255
|
+
: {
|
|
256
|
+
emit: (e) => {
|
|
257
|
+
io.writers.out(`${binary.summary}\n`);
|
|
258
|
+
io.writers.err(`harness update: ${e.error?.message ?? 'failed'}\n`);
|
|
259
|
+
if (e.next_action)
|
|
260
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
exitWithEnvelope(envelope, port);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const next_action = status === 'degraded'
|
|
267
|
+
? skills.next_action
|
|
268
|
+
: [binary.next_action, skills.next_action].filter(Boolean).join(' · ');
|
|
269
|
+
const envelope = status === 'degraded'
|
|
270
|
+
? formatDegraded('update', data, next_action, deps.clock)
|
|
271
|
+
: formatOk('update', data, deps.clock, { next_action });
|
|
272
|
+
const port = io.mode === 'json'
|
|
273
|
+
? jsonPort()
|
|
274
|
+
: {
|
|
275
|
+
emit: () => {
|
|
276
|
+
if (binary.stdout?.trim())
|
|
277
|
+
io.writers.out(`${binary.stdout.replace(/\n$/, '')}\n`);
|
|
278
|
+
io.writers.out(`${binary.summary}\n`);
|
|
279
|
+
io.writers.out(`${skills.summary}\n`);
|
|
280
|
+
if (next_action)
|
|
281
|
+
io.writers.err(`→ ${next_action}\n`);
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
exitWithEnvelope(envelope, port);
|
|
285
|
+
});
|
|
286
|
+
program
|
|
287
|
+
.command('self-install')
|
|
288
|
+
.description('Install the harness CLI globally from the registry (first-time bootstrap)')
|
|
289
|
+
.action(async () => {
|
|
290
|
+
// Convenience global install from the public npm registry. A registry or
|
|
291
|
+
// transport failure surfaces as a classified error + next_action via
|
|
292
|
+
// classifyInstallFailure (AC4/AC10). No skills phase.
|
|
293
|
+
const o = await runNpmInstall(io, deps, 'self-install', installed, 'latest', null);
|
|
294
|
+
emitBinary(io, deps, 'self-install', o);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/acts/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { EnvPort } from '../adapters/env/env-port.js';
|
|
4
|
+
import type { ExecPort } from '../adapters/exec/exec-port.js';
|
|
5
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
6
|
+
import type { GitPort } from '../adapters/git/git-port.js';
|
|
7
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
8
|
+
import { type CliIo } from '../output/output-port.js';
|
|
9
|
+
import type { HarnessVerb } from '../services/extensions/contract.js';
|
|
10
|
+
/** The ports a verb act needs: the ctx ports + the process port for cwd. */
|
|
11
|
+
export interface VerbActDeps {
|
|
12
|
+
exec: ExecPort;
|
|
13
|
+
fs: FsPort;
|
|
14
|
+
env: EnvPort;
|
|
15
|
+
git: GitPort;
|
|
16
|
+
clock: Clock;
|
|
17
|
+
proc: ProcessPort;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register ONE extension verb as a top-level `harness <verb>` subcommand. Thin:
|
|
21
|
+
* it maps the declarative `HarnessVerb` onto commander (name, description,
|
|
22
|
+
* options, args), and its action parses opts/args → builds the `VerbContext`
|
|
23
|
+
* (cwd from the process port) → `await runVerb` → exits via the kernel (so the
|
|
24
|
+
* status→exit mapping + `process.exit` confinement are unchanged). No business
|
|
25
|
+
* logic lives here. Returns the created Command (usage is inspectable).
|
|
26
|
+
*/
|
|
27
|
+
export declare function registerVerbAct(program: Command, verb: HarnessVerb, deps: VerbActDeps, io: CliIo): Command;
|