@ai-substrate/engineering-harness 0.2.0-canary.45
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 +119 -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,66 @@
|
|
|
1
|
+
import { formatError, formatOk } from '../output/envelope.js';
|
|
2
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
3
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
4
|
+
import { scaffoldExtension } from '../services/scaffold/scaffold-service.js';
|
|
5
|
+
/**
|
|
6
|
+
* Variant-aware "what next". A `--wrap` scaffold already has a working `run()`,
|
|
7
|
+
* so telling the author to "implement run()" is misleading (MH-003) — point them
|
|
8
|
+
* at running/reviewing it instead. A minimal stub genuinely needs implementing.
|
|
9
|
+
*/
|
|
10
|
+
function nextActionFor(variant, path, verb) {
|
|
11
|
+
if (variant === 'record-ts') {
|
|
12
|
+
return `Edit the template body in ${path}, then run \`harness record ${verb}\`. \`harness doctor\` confirms it loaded.`;
|
|
13
|
+
}
|
|
14
|
+
const isWrap = variant.startsWith('wrap');
|
|
15
|
+
return isWrap
|
|
16
|
+
? `Run \`harness ${verb}\` to try it (run() already wraps your command); edit ${path} to tweak. \`harness doctor\` confirms it loaded.`
|
|
17
|
+
: `Edit ${path} to implement run(), then run \`harness ${verb}\`. \`harness doctor\` confirms it loaded.`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register the `new` command — scaffolds a fresh, loadable extension into the
|
|
21
|
+
* repo's `.harness/extensions/`. A CORE command (reserved, like `help`/`doctor`,
|
|
22
|
+
* runs even in `--no-extensions` mode); it owns no business logic — the
|
|
23
|
+
* `scaffold-service` validates + writes, and this act maps the outcome onto the
|
|
24
|
+
* Envelope + exit code (ok → 0, error → 1).
|
|
25
|
+
*/
|
|
26
|
+
export function registerNewAct(program, io, deps) {
|
|
27
|
+
program
|
|
28
|
+
.command('new')
|
|
29
|
+
.description('Scaffold a new extension package into .harness/extensions/<name>/ (entry + instructions.md)')
|
|
30
|
+
.argument('<name>', 'verb name (lowercase, hyphenated — becomes `harness <name>`)')
|
|
31
|
+
.option('--wrap <command>', 'wrap a real repo command, e.g. --wrap "npm test"')
|
|
32
|
+
.option('--js', 'emit a plain .js starter (JSDoc contract, no TypeScript)')
|
|
33
|
+
.option('--record', 'scaffold a record-type extension (`harness record <name>`) instead of a verb')
|
|
34
|
+
.option('--force', 'overwrite an existing extension file')
|
|
35
|
+
.action((name, opts) => {
|
|
36
|
+
const outcome = scaffoldExtension({ name, wrap: opts.wrap, js: opts.js, record: opts.record, force: opts.force }, { fs: deps.fs, proc: deps.proc });
|
|
37
|
+
const envelope = outcome.ok
|
|
38
|
+
? formatOk('new', {
|
|
39
|
+
path: outcome.path,
|
|
40
|
+
instructionsPath: outcome.instructionsPath,
|
|
41
|
+
verb: outcome.verb,
|
|
42
|
+
variant: outcome.variant,
|
|
43
|
+
}, deps.clock, { next_action: nextActionFor(outcome.variant, outcome.path, outcome.verb) })
|
|
44
|
+
: formatError('new', outcome.code, outcome.message, deps.clock, {
|
|
45
|
+
next_action: outcome.next_action,
|
|
46
|
+
});
|
|
47
|
+
const port = io.mode === 'json'
|
|
48
|
+
? createOutputPort('json', io.writers)
|
|
49
|
+
: {
|
|
50
|
+
emit: (e) => {
|
|
51
|
+
if (e.status === 'ok' && outcome.ok) {
|
|
52
|
+
io.writers.out(`Created ${outcome.path}\n`);
|
|
53
|
+
io.writers.out(`Created ${outcome.instructionsPath} (author the agent briefing)\n`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
io.writers.err(`harness new: ${e.error?.message ?? 'failed'}\n`);
|
|
57
|
+
if (e.next_action)
|
|
58
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
59
|
+
}
|
|
60
|
+
io.writers.out(`new: ${e.status}\n`);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
exitWithEnvelope(envelope, port);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=new.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/acts/new.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 { FsPort } from '../adapters/fs/fs-port.js';
|
|
5
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
6
|
+
import { type CliIo } from '../output/output-port.js';
|
|
7
|
+
/** The ports the `observe` act injects into the observe service (a subset of VerbActDeps). */
|
|
8
|
+
export interface ObserveActDeps {
|
|
9
|
+
fs: FsPort;
|
|
10
|
+
proc: ProcessPort;
|
|
11
|
+
clock: Clock;
|
|
12
|
+
env: EnvPort;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Register the `observe` command — CLI-owned in-flight friction capture into the
|
|
16
|
+
* gitignored transient buffer (`.harness/temp/<bucket>/session-buffer.md`), plus
|
|
17
|
+
* the `--list`/`--clear` drain surface that sweeps ALL buckets by default
|
|
18
|
+
* (plan 015 D-12). A CORE command (reserved, like `record`/`instructions`). It
|
|
19
|
+
* owns no business logic — `observe-service` resolves identity, validates,
|
|
20
|
+
* assigns IDs, and appends; this act maps outcomes onto the Envelope + exit code
|
|
21
|
+
* (ok → 0, unconfigured → 2, error → 1).
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerObserveAct(program: Command, io: CliIo, deps: ObserveActDeps): void;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { formatError, formatOk, formatUnconfigured } 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 { OBSERVATION_KINDS, OBSERVATION_SEVERITIES } from '../services/observe/buffer-codec.js';
|
|
6
|
+
import { captureObservation, clearObservations, listObservations, } from '../services/observe/observe-service.js';
|
|
7
|
+
/**
|
|
8
|
+
* Register the `observe` command — CLI-owned in-flight friction capture into the
|
|
9
|
+
* gitignored transient buffer (`.harness/temp/<bucket>/session-buffer.md`), plus
|
|
10
|
+
* the `--list`/`--clear` drain surface that sweeps ALL buckets by default
|
|
11
|
+
* (plan 015 D-12). A CORE command (reserved, like `record`/`instructions`). It
|
|
12
|
+
* owns no business logic — `observe-service` resolves identity, validates,
|
|
13
|
+
* assigns IDs, and appends; this act maps outcomes onto the Envelope + exit code
|
|
14
|
+
* (ok → 0, unconfigured → 2, error → 1).
|
|
15
|
+
*/
|
|
16
|
+
export function registerObserveAct(program, io, deps) {
|
|
17
|
+
const kinds = Object.keys(OBSERVATION_KINDS).join(' | ');
|
|
18
|
+
program
|
|
19
|
+
.command('observe')
|
|
20
|
+
.description('Capture one friction observation to the gitignored transient buffer (.harness/temp/)')
|
|
21
|
+
.argument('[description]', 'what you noticed (>=10 chars); omit with --list/--clear')
|
|
22
|
+
.option('--kind <kind>', `entry kind: ${kinds}`)
|
|
23
|
+
.option('--target <target>', 'free-form target, e.g. tooling | project-sensor | skill')
|
|
24
|
+
.option('--severity <severity>', `severity: ${OBSERVATION_SEVERITIES.join(' | ')}`)
|
|
25
|
+
.option('--workaround <text>', 'what you did to get past it')
|
|
26
|
+
.option('--suggested-encoding <text>', 'a hint for the retro drain encoding flow')
|
|
27
|
+
.option('--agent <slug>', 'bucket override (else HARNESS_AGENT env, else "agent")')
|
|
28
|
+
.option('--list', 'list pending observations (all buckets by default)')
|
|
29
|
+
.option('--clear', 'truncate pending observations (all buckets by default; files kept)')
|
|
30
|
+
.action((description, opts) => {
|
|
31
|
+
const serviceDeps = deps;
|
|
32
|
+
if (opts.list) {
|
|
33
|
+
const outcome = listObservations({ agent: opts.agent }, serviceDeps);
|
|
34
|
+
if (!outcome.ok) {
|
|
35
|
+
exitWithEnvelope(failureEnvelope(outcome, deps.clock), portFor(io, 'list'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const envelope = formatOk('observe', {
|
|
39
|
+
observations: outcome.observations,
|
|
40
|
+
buckets_scanned: outcome.buckets_scanned,
|
|
41
|
+
malformed_skipped: outcome.malformed_skipped,
|
|
42
|
+
}, deps.clock, {
|
|
43
|
+
next_action: 'Drain: save what matters via `harness record retro`, then `harness observe --clear`.',
|
|
44
|
+
});
|
|
45
|
+
const port = io.mode === 'json'
|
|
46
|
+
? createOutputPort('json', io.writers)
|
|
47
|
+
: {
|
|
48
|
+
emit: () => {
|
|
49
|
+
for (const o of outcome.observations) {
|
|
50
|
+
io.writers.out(`[${o.kind}${o.target ? `/${o.target}` : ''}] ${o.bucket}:${o.id} ${o.description}\n`);
|
|
51
|
+
}
|
|
52
|
+
io.writers.out(`observe: ${outcome.observations.length} pending across ${outcome.buckets_scanned.length} bucket(s)` +
|
|
53
|
+
`${outcome.malformed_skipped > 0 ? `, ${outcome.malformed_skipped} malformed skipped` : ''}\n`);
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
exitWithEnvelope(envelope, port);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (opts.clear) {
|
|
60
|
+
const outcome = clearObservations({ agent: opts.agent }, serviceDeps);
|
|
61
|
+
if (!outcome.ok) {
|
|
62
|
+
exitWithEnvelope(failureEnvelope(outcome, deps.clock), portFor(io, 'clear'));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const envelope = formatOk('observe', {
|
|
66
|
+
cleared: outcome.cleared,
|
|
67
|
+
buckets_scanned: outcome.buckets_scanned,
|
|
68
|
+
malformed_skipped: outcome.malformed_skipped,
|
|
69
|
+
}, deps.clock);
|
|
70
|
+
const port = io.mode === 'json'
|
|
71
|
+
? createOutputPort('json', io.writers)
|
|
72
|
+
: {
|
|
73
|
+
emit: () => {
|
|
74
|
+
io.writers.out(`observe: cleared ${outcome.cleared} entr(y/ies)\n`);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
exitWithEnvelope(envelope, port);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const outcome = captureObservation({
|
|
81
|
+
description,
|
|
82
|
+
kind: opts.kind,
|
|
83
|
+
target: opts.target,
|
|
84
|
+
severity: opts.severity,
|
|
85
|
+
workaround: opts.workaround,
|
|
86
|
+
suggestedEncoding: opts.suggestedEncoding,
|
|
87
|
+
agent: opts.agent,
|
|
88
|
+
}, serviceDeps);
|
|
89
|
+
if (!outcome.ok) {
|
|
90
|
+
exitWithEnvelope(failureEnvelope(outcome, deps.clock), portFor(io, 'capture'));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const envelope = formatOk('observe', { bucket: outcome.bucket, id: outcome.id, kind: outcome.kind, path: outcome.path }, deps.clock, {
|
|
94
|
+
evidence: [{ label: 'observation buffer', path: outcome.path }],
|
|
95
|
+
next_action: 'Keep working — drain at session end with `harness observe --list` then `harness record retro`.',
|
|
96
|
+
});
|
|
97
|
+
const port = io.mode === 'json'
|
|
98
|
+
? createOutputPort('json', io.writers)
|
|
99
|
+
: {
|
|
100
|
+
emit: () => {
|
|
101
|
+
io.writers.out(`Captured ${outcome.id} → ${outcome.path}\n`);
|
|
102
|
+
io.writers.out('observe: ok\n');
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
exitWithEnvelope(envelope, port);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** Map a service failure onto the canonical envelope (unconfigured → 2, error → 1). */
|
|
109
|
+
function failureEnvelope(outcome, clock) {
|
|
110
|
+
return outcome.status === 'unconfigured'
|
|
111
|
+
? formatUnconfigured('observe', outcome.next_action, clock)
|
|
112
|
+
: formatError('observe', outcome.code ?? ErrorCodes.UNKNOWN, outcome.message, clock, {
|
|
113
|
+
next_action: outcome.next_action,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/** Human-mode failure port (JSON mode uses the standard port). */
|
|
117
|
+
function portFor(io, what) {
|
|
118
|
+
return io.mode === 'json'
|
|
119
|
+
? createOutputPort('json', io.writers)
|
|
120
|
+
: {
|
|
121
|
+
emit: (e) => {
|
|
122
|
+
io.writers.err(`harness observe: ${e.error?.message ?? e.next_action ?? 'failed'}\n`);
|
|
123
|
+
if (e.next_action)
|
|
124
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
125
|
+
io.writers.out(`observe (${what}): ${e.status}\n`);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=observe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observe.js","sourceRoot":"","sources":["../../src/acts/observe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
4
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
5
|
+
import { type CliIo } from '../output/output-port.js';
|
|
6
|
+
import type { RecordRegistry } from '../services/record/registry.js';
|
|
7
|
+
/** The ports the `record` act injects into the record service (a subset of VerbActDeps). */
|
|
8
|
+
export interface RecordActDeps {
|
|
9
|
+
fs: FsPort;
|
|
10
|
+
proc: ProcessPort;
|
|
11
|
+
clock: Clock;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Register the `record` command — scaffolds a record file from a record type's
|
|
15
|
+
* template into `.harness/records/<type>/` and returns its path for the calling
|
|
16
|
+
* agent to fill. A CORE command (reserved, like `help`/`doctor`/`new`/`docs`/
|
|
17
|
+
* `skills`; runs even in `--no-extensions` mode). It owns no business logic — the
|
|
18
|
+
* `record-service` resolves the type + path + writes, and this act maps the
|
|
19
|
+
* outcome onto the Envelope + exit code (ok → 0, error → 1, unconfigured → 2).
|
|
20
|
+
*
|
|
21
|
+
* `harness record` (bare) and `harness record --list` both emit the orientation
|
|
22
|
+
* listing of available types (core ∪ extension), non-blocking, exit 0.
|
|
23
|
+
*/
|
|
24
|
+
export declare function registerRecordAct(program: Command, io: CliIo, deps: RecordActDeps, registry: RecordRegistry): void;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { formatError, formatOk, formatUnconfigured } 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 { createRecord } from '../services/record/record-service.js';
|
|
6
|
+
/**
|
|
7
|
+
* Register the `record` command — scaffolds a record file from a record type's
|
|
8
|
+
* template into `.harness/records/<type>/` and returns its path for the calling
|
|
9
|
+
* agent to fill. A CORE command (reserved, like `help`/`doctor`/`new`/`docs`/
|
|
10
|
+
* `skills`; runs even in `--no-extensions` mode). It owns no business logic — the
|
|
11
|
+
* `record-service` resolves the type + path + writes, and this act maps the
|
|
12
|
+
* outcome onto the Envelope + exit code (ok → 0, error → 1, unconfigured → 2).
|
|
13
|
+
*
|
|
14
|
+
* `harness record` (bare) and `harness record --list` both emit the orientation
|
|
15
|
+
* listing of available types (core ∪ extension), non-blocking, exit 0.
|
|
16
|
+
*/
|
|
17
|
+
export function registerRecordAct(program, io, deps, registry) {
|
|
18
|
+
program
|
|
19
|
+
.command('record')
|
|
20
|
+
.description('Scaffold a record file from a record type into .harness/records/<type>/ (returns its path)')
|
|
21
|
+
.argument('[type]', 'record type to create; omit (or use --list) to list available types')
|
|
22
|
+
.option('--slug <slug>', 'optional filename slug (lowercased to [a-z0-9-])')
|
|
23
|
+
.option('--list', 'list available record types (core ∪ extension)')
|
|
24
|
+
.action((type, opts) => {
|
|
25
|
+
if (opts.list || type === undefined) {
|
|
26
|
+
emitList(io, deps.clock, registry);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const outcome = createRecord({ type, slug: opts.slug }, registry, deps);
|
|
30
|
+
if (outcome.ok) {
|
|
31
|
+
const envelope = formatOk('record', { type: outcome.type, path: outcome.path, source: outcome.source }, deps.clock, {
|
|
32
|
+
evidence: [{ label: `${outcome.type} record`, path: outcome.path }],
|
|
33
|
+
next_action: `Open and fill ${outcome.path}, then save.`,
|
|
34
|
+
});
|
|
35
|
+
const port = io.mode === 'json'
|
|
36
|
+
? createOutputPort('json', io.writers)
|
|
37
|
+
: {
|
|
38
|
+
emit: () => {
|
|
39
|
+
io.writers.out(`Created ${outcome.path}\n`);
|
|
40
|
+
io.writers.out('record: ok\n');
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
exitWithEnvelope(envelope, port);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const envelope = outcome.status === 'unconfigured'
|
|
47
|
+
? formatUnconfigured('record', outcome.next_action, deps.clock)
|
|
48
|
+
: formatError('record', outcome.code ?? ErrorCodes.UNKNOWN, outcome.message, deps.clock, {
|
|
49
|
+
next_action: outcome.next_action,
|
|
50
|
+
});
|
|
51
|
+
const port = io.mode === 'json'
|
|
52
|
+
? createOutputPort('json', io.writers)
|
|
53
|
+
: {
|
|
54
|
+
emit: (e) => {
|
|
55
|
+
io.writers.err(`harness record: ${e.error?.message ?? e.next_action ?? 'failed'}\n`);
|
|
56
|
+
if (e.next_action)
|
|
57
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
58
|
+
io.writers.out(`record: ${e.status}\n`);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
exitWithEnvelope(envelope, port);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** Emit the orientation listing of available record types (core ∪ extension). */
|
|
65
|
+
function emitList(io, clock, registry) {
|
|
66
|
+
const types = registry.types.map((t) => ({
|
|
67
|
+
type: t.type,
|
|
68
|
+
description: t.description,
|
|
69
|
+
source: t.source,
|
|
70
|
+
...(t.entryPath && { entryPath: t.entryPath }),
|
|
71
|
+
}));
|
|
72
|
+
const envelope = formatOk('record', { types }, clock, {
|
|
73
|
+
next_action: 'Create one with `harness record <type> --slug "<name>"`.',
|
|
74
|
+
});
|
|
75
|
+
const port = io.mode === 'json'
|
|
76
|
+
? createOutputPort('json', io.writers)
|
|
77
|
+
: { emit: () => io.writers.out(renderListText(registry)) };
|
|
78
|
+
exitWithEnvelope(envelope, port);
|
|
79
|
+
}
|
|
80
|
+
/** Human-readable listing of record types. */
|
|
81
|
+
function renderListText(registry) {
|
|
82
|
+
const lines = ['harness record — available types:'];
|
|
83
|
+
if (registry.types.length === 0) {
|
|
84
|
+
lines.push(' (none)');
|
|
85
|
+
}
|
|
86
|
+
for (const t of registry.types) {
|
|
87
|
+
const provenance = t.source === 'extension' ? `[extension] ${t.entryPath ?? ''}`.trim() : '[core]';
|
|
88
|
+
lines.push(` • ${t.type}\t${t.description}\t${provenance}`);
|
|
89
|
+
}
|
|
90
|
+
lines.push('', ' harness record <type> [--slug "<name>"]');
|
|
91
|
+
return `${lines.join('\n')}\n`;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/acts/record.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { ExecPort } from '../adapters/exec/exec-port.js';
|
|
4
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
5
|
+
import { type CliIo } from '../output/output-port.js';
|
|
6
|
+
/** The ports the `skills` act injects — a subset of VerbActDeps (no fs/git/env needed). */
|
|
7
|
+
export interface SkillsActDeps {
|
|
8
|
+
exec: ExecPort;
|
|
9
|
+
proc: ProcessPort;
|
|
10
|
+
clock: Clock;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register the `skills` command + its `install` subcommand — a first-class CORE
|
|
14
|
+
* capability (reserved, like `help`/`doctor`/`new`/`docs`; it ships with the
|
|
15
|
+
* published CLI so the harness can install its own skills in any repo). It owns
|
|
16
|
+
* no install logic: it is a transparent PASS-THROUGH to Vercel's `npx skills add`
|
|
17
|
+
* (Principle 8, wrap-don't-rebuild — that tool already owns the CLI-target × scope
|
|
18
|
+
* matrix). The act:
|
|
19
|
+
* - builds the exact argv with the pure `buildInstallArgv` (always `-y`, so the
|
|
20
|
+
* blocking interactive picker never appears);
|
|
21
|
+
* - **announces the exact `npx …` command before running it** — to stderr in
|
|
22
|
+
* human mode, and inside the envelope (`data.command` + `next_action`) in JSON
|
|
23
|
+
* mode, so the `--json` stdout stays a single parseable envelope (Principle 4);
|
|
24
|
+
* - shells out ONLY through the injected `ExecPort` (no direct child/shell);
|
|
25
|
+
* - maps the result onto an Envelope + exit code (ok → 0, `E170` → 1).
|
|
26
|
+
*
|
|
27
|
+
* Targets are flags, not a blocking prompt: the harness CLI is agent-first and
|
|
28
|
+
* non-blocking, so a missing `--target` returns `E108` with a `next_action` that
|
|
29
|
+
* enumerates the valid targets. The *skill* (`eng-harness-0-adopt`) is what asks
|
|
30
|
+
* the user, then runs this with flags.
|
|
31
|
+
*/
|
|
32
|
+
export declare function registerSkillsAct(program: Command, io: CliIo, deps: SkillsActDeps): void;
|