@lannguyensi/harness 0.5.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/CHANGELOG.md +552 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/cli/add/index.d.ts +14 -0
- package/dist/cli/add/index.js +71 -0
- package/dist/cli/add/index.js.map +1 -0
- package/dist/cli/add/mutate.d.ts +39 -0
- package/dist/cli/add/mutate.js +36 -0
- package/dist/cli/add/mutate.js.map +1 -0
- package/dist/cli/adopt/derive.d.ts +38 -0
- package/dist/cli/adopt/derive.js +94 -0
- package/dist/cli/adopt/derive.js.map +1 -0
- package/dist/cli/adopt/index.d.ts +20 -0
- package/dist/cli/adopt/index.js +156 -0
- package/dist/cli/adopt/index.js.map +1 -0
- package/dist/cli/apply/apply.d.ts +49 -0
- package/dist/cli/apply/apply.js +333 -0
- package/dist/cli/apply/apply.js.map +1 -0
- package/dist/cli/apply/generate-memory-index.d.ts +17 -0
- package/dist/cli/apply/generate-memory-index.js +167 -0
- package/dist/cli/apply/generate-memory-index.js.map +1 -0
- package/dist/cli/apply/generate-settings.d.ts +15 -0
- package/dist/cli/apply/generate-settings.js +87 -0
- package/dist/cli/apply/generate-settings.js.map +1 -0
- package/dist/cli/apply/index.d.ts +1 -0
- package/dist/cli/apply/index.js +2 -0
- package/dist/cli/apply/index.js.map +1 -0
- package/dist/cli/audit.d.ts +36 -0
- package/dist/cli/audit.js +121 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/describe.d.ts +13 -0
- package/dist/cli/describe.js +26 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/diff/engine.d.ts +21 -0
- package/dist/cli/diff/engine.js +161 -0
- package/dist/cli/diff/engine.js.map +1 -0
- package/dist/cli/diff/git.d.ts +6 -0
- package/dist/cli/diff/git.js +32 -0
- package/dist/cli/diff/git.js.map +1 -0
- package/dist/cli/diff/index.d.ts +15 -0
- package/dist/cli/diff/index.js +39 -0
- package/dist/cli/diff/index.js.map +1 -0
- package/dist/cli/diff/since-apply.d.ts +57 -0
- package/dist/cli/diff/since-apply.js +255 -0
- package/dist/cli/diff/since-apply.js.map +1 -0
- package/dist/cli/doctor/format.d.ts +2 -0
- package/dist/cli/doctor/format.js +126 -0
- package/dist/cli/doctor/format.js.map +1 -0
- package/dist/cli/doctor/index.d.ts +14 -0
- package/dist/cli/doctor/index.js +281 -0
- package/dist/cli/doctor/index.js.map +1 -0
- package/dist/cli/doctor/types.d.ts +46 -0
- package/dist/cli/doctor/types.js +2 -0
- package/dist/cli/doctor/types.js.map +1 -0
- package/dist/cli/dry-run.d.ts +46 -0
- package/dist/cli/dry-run.js +168 -0
- package/dist/cli/dry-run.js.map +1 -0
- package/dist/cli/exit-codes.d.ts +10 -0
- package/dist/cli/exit-codes.js +15 -0
- package/dist/cli/exit-codes.js.map +1 -0
- package/dist/cli/explain.d.ts +14 -0
- package/dist/cli/explain.js +97 -0
- package/dist/cli/explain.js.map +1 -0
- package/dist/cli/export.d.ts +31 -0
- package/dist/cli/export.js +84 -0
- package/dist/cli/export.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +549 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init/index.d.ts +17 -0
- package/dist/cli/init/index.js +57 -0
- package/dist/cli/init/index.js.map +1 -0
- package/dist/cli/init/templates.d.ts +4 -0
- package/dist/cli/init/templates.js +175 -0
- package/dist/cli/init/templates.js.map +1 -0
- package/dist/cli/list.d.ts +12 -0
- package/dist/cli/list.js +118 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/loader.d.ts +24 -0
- package/dist/cli/loader.js +74 -0
- package/dist/cli/loader.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +6 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/policy/intercept.d.ts +34 -0
- package/dist/cli/policy/intercept.js +172 -0
- package/dist/cli/policy/intercept.js.map +1 -0
- package/dist/cli/remove/index.d.ts +18 -0
- package/dist/cli/remove/index.js +95 -0
- package/dist/cli/remove/index.js.map +1 -0
- package/dist/cli/remove/mutate.d.ts +9 -0
- package/dist/cli/remove/mutate.js +68 -0
- package/dist/cli/remove/mutate.js.map +1 -0
- package/dist/cli/validate/checks.d.ts +23 -0
- package/dist/cli/validate/checks.js +253 -0
- package/dist/cli/validate/checks.js.map +1 -0
- package/dist/cli/validate/index.d.ts +18 -0
- package/dist/cli/validate/index.js +50 -0
- package/dist/cli/validate/index.js.map +1 -0
- package/dist/cli/validate/types.d.ts +7 -0
- package/dist/cli/validate/types.js +5 -0
- package/dist/cli/validate/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/io/atomic-write.d.ts +8 -0
- package/dist/io/atomic-write.js +30 -0
- package/dist/io/atomic-write.js.map +1 -0
- package/dist/io/harness-lock.d.ts +33 -0
- package/dist/io/harness-lock.js +260 -0
- package/dist/io/harness-lock.js.map +1 -0
- package/dist/io/last-apply.d.ts +20 -0
- package/dist/io/last-apply.js +123 -0
- package/dist/io/last-apply.js.map +1 -0
- package/dist/io/lock.d.ts +11 -0
- package/dist/io/lock.js +33 -0
- package/dist/io/lock.js.map +1 -0
- package/dist/io/patch.d.ts +10 -0
- package/dist/io/patch.js +8 -0
- package/dist/io/patch.js.map +1 -0
- package/dist/io/restart-hints.d.ts +5 -0
- package/dist/io/restart-hints.js +59 -0
- package/dist/io/restart-hints.js.map +1 -0
- package/dist/io/three-state.d.ts +7 -0
- package/dist/io/three-state.js +20 -0
- package/dist/io/three-state.js.map +1 -0
- package/dist/io/validate-before-write.d.ts +12 -0
- package/dist/io/validate-before-write.js +23 -0
- package/dist/io/validate-before-write.js.map +1 -0
- package/dist/overrides/index.d.ts +2 -0
- package/dist/overrides/index.js +3 -0
- package/dist/overrides/index.js.map +1 -0
- package/dist/overrides/machines.d.ts +12 -0
- package/dist/overrides/machines.js +46 -0
- package/dist/overrides/machines.js.map +1 -0
- package/dist/overrides/merge.d.ts +6 -0
- package/dist/overrides/merge.js +173 -0
- package/dist/overrides/merge.js.map +1 -0
- package/dist/policies/duration.d.ts +5 -0
- package/dist/policies/duration.js +50 -0
- package/dist/policies/duration.js.map +1 -0
- package/dist/policies/extract.d.ts +50 -0
- package/dist/policies/extract.js +190 -0
- package/dist/policies/extract.js.map +1 -0
- package/dist/policies/index.d.ts +5 -0
- package/dist/policies/index.js +6 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/ledger-client.d.ts +39 -0
- package/dist/policies/ledger-client.js +378 -0
- package/dist/policies/ledger-client.js.map +1 -0
- package/dist/policies/requires.d.ts +44 -0
- package/dist/policies/requires.js +146 -0
- package/dist/policies/requires.js.map +1 -0
- package/dist/policies/timestamp.d.ts +14 -0
- package/dist/policies/timestamp.js +36 -0
- package/dist/policies/timestamp.js.map +1 -0
- package/dist/probes/mcp.d.ts +29 -0
- package/dist/probes/mcp.js +226 -0
- package/dist/probes/mcp.js.map +1 -0
- package/dist/probes/memory.d.ts +24 -0
- package/dist/probes/memory.js +89 -0
- package/dist/probes/memory.js.map +1 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/intercept.d.ts +53 -0
- package/dist/runtime/intercept.js +181 -0
- package/dist/runtime/intercept.js.map +1 -0
- package/dist/runtime/ledger-record.d.ts +43 -0
- package/dist/runtime/ledger-record.js +239 -0
- package/dist/runtime/ledger-record.js.map +1 -0
- package/dist/runtime/session-id.d.ts +10 -0
- package/dist/runtime/session-id.js +37 -0
- package/dist/runtime/session-id.js.map +1 -0
- package/dist/schema/extract.d.ts +5 -0
- package/dist/schema/extract.js +23 -0
- package/dist/schema/extract.js.map +1 -0
- package/dist/schema/grounding.d.ts +65 -0
- package/dist/schema/grounding.js +21 -0
- package/dist/schema/grounding.js.map +1 -0
- package/dist/schema/hooks.d.ts +86 -0
- package/dist/schema/hooks.js +42 -0
- package/dist/schema/hooks.js.map +1 -0
- package/dist/schema/index.d.ts +961 -0
- package/dist/schema/index.js +55 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/memory.d.ts +131 -0
- package/dist/schema/memory.js +38 -0
- package/dist/schema/memory.js.map +1 -0
- package/dist/schema/policies.d.ts +412 -0
- package/dist/schema/policies.js +53 -0
- package/dist/schema/policies.js.map +1 -0
- package/dist/schema/requires.d.ts +115 -0
- package/dist/schema/requires.js +57 -0
- package/dist/schema/requires.js.map +1 -0
- package/dist/schema/tools.d.ts +283 -0
- package/dist/schema/tools.js +66 -0
- package/dist/schema/tools.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { add } from "./add/index.js";
|
|
3
|
+
import { adopt } from "./adopt/index.js";
|
|
4
|
+
import { apply, DRIFT_HINT_MESSAGE, } from "./apply/index.js";
|
|
5
|
+
import { isRemoveType, KNOWN_REMOVE_TYPES, remove } from "./remove/index.js";
|
|
6
|
+
import { describe, isPillar } from "./describe.js";
|
|
7
|
+
import { diff as diffRun } from "./diff/index.js";
|
|
8
|
+
import { diffSinceApply } from "./diff/since-apply.js";
|
|
9
|
+
import { exportManifest } from "./export.js";
|
|
10
|
+
import { doctor } from "./doctor/index.js";
|
|
11
|
+
import { format as formatDoctor } from "./doctor/format.js";
|
|
12
|
+
import { EX_FAIL, EX_USAGE, HarnessExitError } from "./exit-codes.js";
|
|
13
|
+
import { explain } from "./explain.js";
|
|
14
|
+
import { init, isTemplate, KNOWN_TEMPLATES } from "./init/index.js";
|
|
15
|
+
import { isListCategory, list } from "./list.js";
|
|
16
|
+
import { audit } from "./audit.js";
|
|
17
|
+
import { dryRun } from "./dry-run.js";
|
|
18
|
+
import { runInterceptCli } from "./policy/intercept.js";
|
|
19
|
+
import { formatReport, validate } from "./validate/index.js";
|
|
20
|
+
export function buildProgram(opts = {}) {
|
|
21
|
+
const stdout = opts.stdout ?? ((s) => process.stdout.write(s));
|
|
22
|
+
const stderr = opts.stderr ?? ((s) => process.stderr.write(s));
|
|
23
|
+
const program = new Command();
|
|
24
|
+
program
|
|
25
|
+
.name("harness")
|
|
26
|
+
.description("Declarative control plane for agent harnesses")
|
|
27
|
+
.version("0.4.0")
|
|
28
|
+
.configureOutput({
|
|
29
|
+
writeOut: stdout,
|
|
30
|
+
writeErr: stderr,
|
|
31
|
+
})
|
|
32
|
+
.exitOverride((err) => {
|
|
33
|
+
// Commander exits with code 0 + writes the help/version text itself for
|
|
34
|
+
// --help and --version. Suppress our re-throw on those so we don't get
|
|
35
|
+
// a duplicate stderr line + a non-zero exit on a successful display.
|
|
36
|
+
if (err.exitCode === 0) {
|
|
37
|
+
throw new HarnessExitError("", 0);
|
|
38
|
+
}
|
|
39
|
+
// unknownOption / unknownCommand / missingArgument exit 1 by default.
|
|
40
|
+
// Map them to EX_USAGE per ARCHITECTURE §9 sysexits, and pass empty
|
|
41
|
+
// message because Commander already wrote the human-readable text.
|
|
42
|
+
const code = err.exitCode === 1 ? EX_USAGE : (err.exitCode ?? EX_USAGE);
|
|
43
|
+
throw new HarnessExitError("", code);
|
|
44
|
+
});
|
|
45
|
+
program
|
|
46
|
+
.command("describe")
|
|
47
|
+
.description("Print the effective merged manifest")
|
|
48
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
49
|
+
.option("--project <name>", "apply per-project overrides for this project name")
|
|
50
|
+
.option("--pillar <pillar>", "filter output to one section: grounding | tools | memory | hooks | policies")
|
|
51
|
+
.option("--json", "emit JSON instead of YAML")
|
|
52
|
+
.action((options) => {
|
|
53
|
+
let pillar;
|
|
54
|
+
if (options.pillar !== undefined) {
|
|
55
|
+
if (!isPillar(options.pillar)) {
|
|
56
|
+
throw new HarnessExitError(`unknown pillar "${options.pillar}"; expected one of grounding, tools, memory, hooks, policies`, EX_USAGE);
|
|
57
|
+
}
|
|
58
|
+
pillar = options.pillar;
|
|
59
|
+
}
|
|
60
|
+
const result = describe({
|
|
61
|
+
configPath: options.config,
|
|
62
|
+
project: options.project,
|
|
63
|
+
pillar,
|
|
64
|
+
json: options.json,
|
|
65
|
+
});
|
|
66
|
+
stdout(result.output);
|
|
67
|
+
if (!result.output.endsWith("\n"))
|
|
68
|
+
stdout("\n");
|
|
69
|
+
});
|
|
70
|
+
program
|
|
71
|
+
.command("validate")
|
|
72
|
+
.description("Lint the manifest + referenced assets")
|
|
73
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
74
|
+
.option("--project <name>", "apply per-project overrides for this project name")
|
|
75
|
+
.option("--strict", "promote warnings to errors")
|
|
76
|
+
.action((options) => {
|
|
77
|
+
const result = validate({
|
|
78
|
+
configPath: options.config,
|
|
79
|
+
project: options.project,
|
|
80
|
+
strict: options.strict,
|
|
81
|
+
});
|
|
82
|
+
const report = formatReport(result);
|
|
83
|
+
if (result.diagnostics.length > 0)
|
|
84
|
+
stderr(report);
|
|
85
|
+
else
|
|
86
|
+
stdout(report);
|
|
87
|
+
if (result.errorCount > 0) {
|
|
88
|
+
throw new HarnessExitError("", EX_FAIL);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
program
|
|
92
|
+
.command("doctor")
|
|
93
|
+
.description("Health summary across all pillars")
|
|
94
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
95
|
+
.option("--project <name>", "apply per-project overrides for this project name")
|
|
96
|
+
.option("--shallow", "skip MCP probes (CLI --version probes still run); report manifest-reference state only")
|
|
97
|
+
.action(async (options) => {
|
|
98
|
+
const report = await doctor({
|
|
99
|
+
configPath: options.config,
|
|
100
|
+
project: options.project,
|
|
101
|
+
shallow: options.shallow,
|
|
102
|
+
});
|
|
103
|
+
stdout(formatDoctor(report));
|
|
104
|
+
});
|
|
105
|
+
program
|
|
106
|
+
.command("list <category>")
|
|
107
|
+
.description("Flat denormalised listing per category: mcp / cli / skills / memories / hooks / policies")
|
|
108
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
109
|
+
.option("--project <name>", "apply per-project overrides")
|
|
110
|
+
.option("--filter <substr>", "case-insensitive substring filter on name (or path for memories)")
|
|
111
|
+
.option("--json", "emit JSON array instead of an aligned text table")
|
|
112
|
+
.action((category, options) => {
|
|
113
|
+
if (!isListCategory(category)) {
|
|
114
|
+
throw new HarnessExitError(`unknown list category "${category}"; expected one of mcp, cli, skills, memories, hooks, policies`, EX_USAGE);
|
|
115
|
+
}
|
|
116
|
+
const result = list(category, {
|
|
117
|
+
configPath: options.config,
|
|
118
|
+
project: options.project,
|
|
119
|
+
filter: options.filter,
|
|
120
|
+
json: options.json,
|
|
121
|
+
});
|
|
122
|
+
stdout(result.output);
|
|
123
|
+
});
|
|
124
|
+
program
|
|
125
|
+
.command("diff")
|
|
126
|
+
.description("Diff the manifest against a git ref (--since <ref>) or against the last " +
|
|
127
|
+
"applied state (--since-apply). --memory-detail expands per-memory-dir " +
|
|
128
|
+
"Merkle drift back to per-file changes.")
|
|
129
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
130
|
+
.option("--project <name>", "apply per-project overrides")
|
|
131
|
+
.option("--since <ref>", "git ref to diff against")
|
|
132
|
+
.option("--since-apply", "diff against harness.generated/.last-apply")
|
|
133
|
+
.option("--memory-detail", "expand per-memory-dir drift to per-file changes")
|
|
134
|
+
.option("--json", "emit structured JSON output")
|
|
135
|
+
.action((options) => {
|
|
136
|
+
if (options.since && options.sinceApply) {
|
|
137
|
+
throw new HarnessExitError("--since <ref> and --since-apply are mutually exclusive", EX_USAGE);
|
|
138
|
+
}
|
|
139
|
+
if (options.sinceApply) {
|
|
140
|
+
const r = diffSinceApply({
|
|
141
|
+
...(options.config !== undefined ? { configPath: options.config } : {}),
|
|
142
|
+
...(options.memoryDetail ? { memoryDetail: true } : {}),
|
|
143
|
+
});
|
|
144
|
+
if (options.json) {
|
|
145
|
+
stdout(`${JSON.stringify(r.json, null, 2)}\n`);
|
|
146
|
+
}
|
|
147
|
+
else if (!r.hasDrift) {
|
|
148
|
+
stdout("no drift since last apply\n");
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
stdout(r.output);
|
|
152
|
+
}
|
|
153
|
+
for (const w of r.warnings) {
|
|
154
|
+
stderr(`warning: ${w}\n`);
|
|
155
|
+
}
|
|
156
|
+
if (r.hasDrift)
|
|
157
|
+
throw new HarnessExitError("", EX_FAIL);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const result = diffRun({
|
|
161
|
+
configPath: options.config,
|
|
162
|
+
project: options.project,
|
|
163
|
+
since: options.since,
|
|
164
|
+
});
|
|
165
|
+
stdout(result.output);
|
|
166
|
+
});
|
|
167
|
+
program
|
|
168
|
+
.command("init")
|
|
169
|
+
.description("Bootstrap a starter harness.yaml from a template")
|
|
170
|
+
.option("--template <name>", `template to instantiate: ${KNOWN_TEMPLATES.join(" | ")} (default: minimal)`)
|
|
171
|
+
.option("--force", "overwrite an existing manifest")
|
|
172
|
+
.option("--config <path>", "manifest path to write (default: ~/.claude/harness.yaml)")
|
|
173
|
+
.action(async (options) => {
|
|
174
|
+
if (options.template !== undefined && !isTemplate(options.template)) {
|
|
175
|
+
throw new HarnessExitError(`unknown template "${options.template}"; expected one of ${KNOWN_TEMPLATES.join(", ")}`, EX_USAGE);
|
|
176
|
+
}
|
|
177
|
+
const result = await init({
|
|
178
|
+
template: options.template,
|
|
179
|
+
force: options.force,
|
|
180
|
+
configPath: options.config,
|
|
181
|
+
});
|
|
182
|
+
if (result.stderr)
|
|
183
|
+
stderr(result.stderr);
|
|
184
|
+
stdout(result.stdout);
|
|
185
|
+
});
|
|
186
|
+
const addCmd = program
|
|
187
|
+
.command("add")
|
|
188
|
+
.description("Insert a new entry into harness.yaml (managed mutation)");
|
|
189
|
+
function addCommonOptions(c) {
|
|
190
|
+
return c
|
|
191
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
192
|
+
.option("--dry-run", "print the unified diff and exit without writing");
|
|
193
|
+
}
|
|
194
|
+
function parseBlocking(s) {
|
|
195
|
+
if (s === "false")
|
|
196
|
+
return false;
|
|
197
|
+
if (s === "soft" || s === "hard")
|
|
198
|
+
return s;
|
|
199
|
+
throw new HarnessExitError(`invalid --blocking value "${s}"; expected one of false, soft, hard`, EX_USAGE);
|
|
200
|
+
}
|
|
201
|
+
function parseIntFlag(s, label) {
|
|
202
|
+
const n = Number.parseInt(s, 10);
|
|
203
|
+
if (!Number.isFinite(n) || String(n) !== s.trim()) {
|
|
204
|
+
throw new HarnessExitError(`invalid ${label} value "${s}"; expected an integer`, EX_USAGE);
|
|
205
|
+
}
|
|
206
|
+
return n;
|
|
207
|
+
}
|
|
208
|
+
async function runAdd(action, opts) {
|
|
209
|
+
const result = await add(action, { configPath: opts.config, dryRun: opts.dryRun });
|
|
210
|
+
if (opts.dryRun) {
|
|
211
|
+
stdout(result.diff);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
stdout(`added ${result.type} ${JSON.stringify(result.name)} to ${result.path}\n`);
|
|
215
|
+
}
|
|
216
|
+
addCommonOptions(addCmd
|
|
217
|
+
.command("mcp <name>")
|
|
218
|
+
.description("Add an MCP server entry under tools.mcp[]")
|
|
219
|
+
.option("--command <cmd>", "argv-style command; comma-separated for multi-token")
|
|
220
|
+
.option("--health-verb <v>", "MCP verb to invoke for liveness")
|
|
221
|
+
.option("--health-timeout-ms <n>", "verb timeout in ms (default 5000 when --health-verb is set)")
|
|
222
|
+
.option("--enabled <bool>", "true|false (default true)")).action(async (name, options) => {
|
|
223
|
+
const command = options.command
|
|
224
|
+
? options.command.includes(",")
|
|
225
|
+
? options.command.split(",").map((s) => s.trim())
|
|
226
|
+
: options.command
|
|
227
|
+
: "";
|
|
228
|
+
if (!command) {
|
|
229
|
+
throw new HarnessExitError("harness add mcp: --command is required", EX_USAGE);
|
|
230
|
+
}
|
|
231
|
+
const entry = {
|
|
232
|
+
name,
|
|
233
|
+
command,
|
|
234
|
+
};
|
|
235
|
+
if (options.healthVerb !== undefined) {
|
|
236
|
+
const timeoutMs = options.healthTimeoutMs
|
|
237
|
+
? parseIntFlag(options.healthTimeoutMs, "--health-timeout-ms")
|
|
238
|
+
: 5000;
|
|
239
|
+
entry.health = {
|
|
240
|
+
verb: options.healthVerb,
|
|
241
|
+
timeout_ms: timeoutMs,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
if (options.enabled !== undefined) {
|
|
245
|
+
if (options.enabled !== "true" && options.enabled !== "false") {
|
|
246
|
+
throw new HarnessExitError(`invalid --enabled value "${options.enabled}"; expected true or false`, EX_USAGE);
|
|
247
|
+
}
|
|
248
|
+
entry.enabled = options.enabled === "true";
|
|
249
|
+
}
|
|
250
|
+
await runAdd({ type: "mcp", entry: entry }, { config: options.config, dryRun: options.dryRun });
|
|
251
|
+
});
|
|
252
|
+
addCommonOptions(addCmd
|
|
253
|
+
.command("cli <name>")
|
|
254
|
+
.description("Add a CLI tool entry under tools.cli[]")
|
|
255
|
+
.requiredOption("--binary <b>", "binary name on PATH or absolute path")
|
|
256
|
+
.option("--required", "validate fails if the binary is missing")
|
|
257
|
+
.option("--min-version <v>", "minimum semver")).action(async (name, options) => {
|
|
258
|
+
const entry = {
|
|
259
|
+
name,
|
|
260
|
+
binary: options.binary,
|
|
261
|
+
};
|
|
262
|
+
if (options.required)
|
|
263
|
+
entry.required = true;
|
|
264
|
+
if (options.minVersion !== undefined)
|
|
265
|
+
entry.min_version = options.minVersion;
|
|
266
|
+
await runAdd({ type: "cli", entry }, { config: options.config, dryRun: options.dryRun });
|
|
267
|
+
});
|
|
268
|
+
addCommonOptions(addCmd
|
|
269
|
+
.command("skill <name>")
|
|
270
|
+
.description("Enable a skill by name under tools.skills.enabled[]")).action(async (name, options) => {
|
|
271
|
+
await runAdd({ type: "skill", entry: name }, { config: options.config, dryRun: options.dryRun });
|
|
272
|
+
});
|
|
273
|
+
addCommonOptions(addCmd
|
|
274
|
+
.command("hook <name>")
|
|
275
|
+
.description("Add a hook entry under hooks[]")
|
|
276
|
+
.requiredOption("--event <e>", "runtime event (e.g. SessionStart, PreToolUse)")
|
|
277
|
+
.requiredOption("--command <c>", "shell command (executable path or script with args)")
|
|
278
|
+
.option("--match <r>", "tool-name regex filter (PreToolUse / PostToolUse only)")
|
|
279
|
+
.option("--blocking <m>", "false | soft | hard (default false)")
|
|
280
|
+
.option("--budget-ms <n>", "timeout in ms (default 30000)")).action(async (name, options) => {
|
|
281
|
+
const entry = {
|
|
282
|
+
name,
|
|
283
|
+
event: options.event,
|
|
284
|
+
command: options.command,
|
|
285
|
+
blocking: options.blocking !== undefined ? parseBlocking(options.blocking) : false,
|
|
286
|
+
};
|
|
287
|
+
if (options.match !== undefined)
|
|
288
|
+
entry.match = options.match;
|
|
289
|
+
if (options.budgetMs !== undefined) {
|
|
290
|
+
entry.budget_ms = parseIntFlag(options.budgetMs, "--budget-ms");
|
|
291
|
+
}
|
|
292
|
+
await runAdd({ type: "hook", entry }, { config: options.config, dryRun: options.dryRun });
|
|
293
|
+
});
|
|
294
|
+
program
|
|
295
|
+
.command("export")
|
|
296
|
+
.description("Emit the effective merged manifest as a single self-contained YAML " +
|
|
297
|
+
"(or JSON). --sanitize redacts /home/<user>/ paths and env values whose " +
|
|
298
|
+
"key looks credential-shaped.")
|
|
299
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
300
|
+
.option("--project <name>", "apply per-project overrides for this project name")
|
|
301
|
+
.option("--sanitize", "redact /home/<user>/ paths and credential-shaped env values")
|
|
302
|
+
.option("--json", "emit JSON instead of YAML")
|
|
303
|
+
.option("-o, --output <file>", "write to <file> atomically instead of stdout")
|
|
304
|
+
.action((options) => {
|
|
305
|
+
const result = exportManifest({
|
|
306
|
+
configPath: options.config,
|
|
307
|
+
project: options.project,
|
|
308
|
+
sanitize: options.sanitize,
|
|
309
|
+
json: options.json,
|
|
310
|
+
outputPath: options.output,
|
|
311
|
+
});
|
|
312
|
+
if (result.wroteTo === null) {
|
|
313
|
+
stdout(result.output);
|
|
314
|
+
if (!result.output.endsWith("\n"))
|
|
315
|
+
stdout("\n");
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
stderr(`wrote ${result.wroteTo}\n`);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
program
|
|
322
|
+
.command("adopt <file>")
|
|
323
|
+
.description("Capture hand-edits from a runtime file (today: ~/.claude/settings.json) " +
|
|
324
|
+
"into the manifest. Diffs against the manifest's current declarations and " +
|
|
325
|
+
"prompts y/N before writing.")
|
|
326
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
327
|
+
.option("--yes", "skip the confirmation prompt (for non-interactive use)")
|
|
328
|
+
.action(async (file, options) => {
|
|
329
|
+
const result = await adopt(file, { configPath: options.config, yes: options.yes });
|
|
330
|
+
if (result.outcome === "no-drift") {
|
|
331
|
+
stdout(`nothing to adopt (no drift between ${file} and ${result.manifestPath})\n`);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (result.outcome === "declined") {
|
|
335
|
+
stdout(`adoption declined; ${result.manifestPath} unchanged\n`);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
stdout(`adopted ${result.driftCount} hook${result.driftCount === 1 ? "" : "s"} ` +
|
|
339
|
+
`from ${result.settingsPath} into ${result.manifestPath} ` +
|
|
340
|
+
`(names: ${result.adoptedNames.join(", ")})\n`);
|
|
341
|
+
});
|
|
342
|
+
program
|
|
343
|
+
.command("apply")
|
|
344
|
+
.description("Regenerate harness.generated/ outputs (settings.json + MEMORY.md index) " +
|
|
345
|
+
"from the manifest. Refuses to overwrite hand-edits without --overwrite-drift; " +
|
|
346
|
+
"use `harness adopt <file>` to capture them back into the manifest instead.")
|
|
347
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
348
|
+
.option("--project <name>", "apply per-project overrides for this project name")
|
|
349
|
+
.option("--dry-run", "print the would-be diff + restart hints; do not write")
|
|
350
|
+
.option("--overwrite-drift", "discard any on-disk hand-edits to harness.generated/ files (prompts for `yes`)")
|
|
351
|
+
.action(async (options) => {
|
|
352
|
+
const result = await apply({
|
|
353
|
+
...(options.config !== undefined ? { configPath: options.config } : {}),
|
|
354
|
+
...(options.project !== undefined ? { project: options.project } : {}),
|
|
355
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
356
|
+
...(options.overwriteDrift ? { overwriteDrift: true } : {}),
|
|
357
|
+
});
|
|
358
|
+
if (result.outcome === "drift-refuse") {
|
|
359
|
+
for (const f of result.files) {
|
|
360
|
+
if (f.diff) {
|
|
361
|
+
stderr(`drift detected in ${f.path}:\n`);
|
|
362
|
+
stderr(f.diff);
|
|
363
|
+
if (!f.diff.endsWith("\n"))
|
|
364
|
+
stderr("\n");
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
stderr(`${DRIFT_HINT_MESSAGE}\n`);
|
|
368
|
+
throw new HarnessExitError("", EX_FAIL);
|
|
369
|
+
}
|
|
370
|
+
if (result.outcome === "drift-discarded") {
|
|
371
|
+
stdout("overwrite-drift declined; nothing written\n");
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const changedFiles = result.files.filter((f) => f.changed);
|
|
375
|
+
if (result.outcome === "no-changes") {
|
|
376
|
+
stdout("no changes\n");
|
|
377
|
+
}
|
|
378
|
+
else if (result.outcome === "would-apply") {
|
|
379
|
+
stdout(`would apply ${changedFiles.length} file(s):\n`);
|
|
380
|
+
for (const f of changedFiles) {
|
|
381
|
+
stdout(` ${f.path}\n`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
stdout(`applied ${changedFiles.length} file(s):\n`);
|
|
386
|
+
for (const f of changedFiles) {
|
|
387
|
+
stdout(` ${f.path}\n`);
|
|
388
|
+
}
|
|
389
|
+
stdout(`harness.lock written to ${result.lockPath}\n`);
|
|
390
|
+
}
|
|
391
|
+
for (const d of result.lockDrift) {
|
|
392
|
+
if (d.reason === "missing") {
|
|
393
|
+
stderr(`asset drift detected: ${d.entry.path} missing since last apply\n`);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
stderr(`asset drift detected: ${d.entry.path} changed since last apply\n`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
for (const w of result.warnings) {
|
|
400
|
+
stderr(`warning: ${w}\n`);
|
|
401
|
+
}
|
|
402
|
+
for (const h of result.restartHints) {
|
|
403
|
+
stderr(`restart hint: ${h}\n`);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
program
|
|
407
|
+
.command("remove <type> <name>")
|
|
408
|
+
.description(`Remove an entry by name. <type> is one of ${KNOWN_REMOVE_TYPES.join(" | ")}. ` +
|
|
409
|
+
"Refuses to remove a hook still referenced by a policy unless --force.")
|
|
410
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
411
|
+
.option("--dry-run", "print the unified diff and exit without writing")
|
|
412
|
+
.option("--force", "remove even if a policy references this entry (dangling policy.hook is then caught by schema)")
|
|
413
|
+
.action(async (type, name, options) => {
|
|
414
|
+
if (!isRemoveType(type)) {
|
|
415
|
+
throw new HarnessExitError(`unknown remove type "${type}"; expected one of ${KNOWN_REMOVE_TYPES.join(", ")}`, EX_USAGE);
|
|
416
|
+
}
|
|
417
|
+
const result = await remove(type, name, {
|
|
418
|
+
configPath: options.config,
|
|
419
|
+
dryRun: options.dryRun,
|
|
420
|
+
force: options.force,
|
|
421
|
+
});
|
|
422
|
+
if (result.forcedReferences.length > 0) {
|
|
423
|
+
stderr(`(forced removal — referenced by: ${result.forcedReferences.join(", ")})\n`);
|
|
424
|
+
}
|
|
425
|
+
if (options.dryRun) {
|
|
426
|
+
stdout(result.diff);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
stdout(`removed ${result.type} ${JSON.stringify(result.name)} from ${result.path}\n`);
|
|
430
|
+
});
|
|
431
|
+
program
|
|
432
|
+
.command("explain <policy>")
|
|
433
|
+
.description("Print a policy's definition; --trace reads the last recorded evaluation")
|
|
434
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
435
|
+
.option("--project <name>", "apply per-project overrides")
|
|
436
|
+
.option("--json", "emit JSON instead of YAML")
|
|
437
|
+
.option("--trace", "include the full decision trail from the most recent evaluation")
|
|
438
|
+
.option("--session <id>", "grounding session whose audit log to read (default: $CLAUDE_SESSION_ID, then 'default')")
|
|
439
|
+
.action(async (policyName, options) => {
|
|
440
|
+
const explainOpts = {};
|
|
441
|
+
if (options.config)
|
|
442
|
+
explainOpts.configPath = options.config;
|
|
443
|
+
if (options.project)
|
|
444
|
+
explainOpts.project = options.project;
|
|
445
|
+
if (options.json)
|
|
446
|
+
explainOpts.json = options.json;
|
|
447
|
+
if (options.trace)
|
|
448
|
+
explainOpts.trace = options.trace;
|
|
449
|
+
if (options.session)
|
|
450
|
+
explainOpts.sessionId = options.session;
|
|
451
|
+
const result = await explain(policyName, explainOpts);
|
|
452
|
+
stdout(result.output);
|
|
453
|
+
});
|
|
454
|
+
program
|
|
455
|
+
.command("audit")
|
|
456
|
+
.description("Replay policy decisions from the evidence ledger for a time window")
|
|
457
|
+
.option("--since <duration>", "time window (default: 24h)")
|
|
458
|
+
.option("--policy <name>", "filter to a single policy by name")
|
|
459
|
+
.option("--outcome <outcome>", "filter by decision outcome (allow / deny / warn-degraded)")
|
|
460
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
461
|
+
.option("--project <name>", "apply per-project overrides")
|
|
462
|
+
.option("--session <id>", "grounding session whose audit log to read (default: $CLAUDE_SESSION_ID, then 'default')")
|
|
463
|
+
.option("--json", "emit JSON instead of a table")
|
|
464
|
+
.action(async (options) => {
|
|
465
|
+
const auditOpts = {};
|
|
466
|
+
if (options.since)
|
|
467
|
+
auditOpts.since = options.since;
|
|
468
|
+
if (options.policy)
|
|
469
|
+
auditOpts.policy = options.policy;
|
|
470
|
+
if (options.outcome)
|
|
471
|
+
auditOpts.outcome = options.outcome;
|
|
472
|
+
if (options.config)
|
|
473
|
+
auditOpts.configPath = options.config;
|
|
474
|
+
if (options.project)
|
|
475
|
+
auditOpts.project = options.project;
|
|
476
|
+
if (options.session)
|
|
477
|
+
auditOpts.sessionId = options.session;
|
|
478
|
+
if (options.json)
|
|
479
|
+
auditOpts.json = options.json;
|
|
480
|
+
const result = await audit(auditOpts);
|
|
481
|
+
stdout(result.output);
|
|
482
|
+
});
|
|
483
|
+
program
|
|
484
|
+
.command("dry-run <prompt>")
|
|
485
|
+
.description("Statically predict which hooks fire / policies match / memories route for a prompt")
|
|
486
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
487
|
+
.option("--project <name>", "apply per-project overrides")
|
|
488
|
+
.option("--tool <name>", "simulate a PreToolUse event for this tool name")
|
|
489
|
+
.option("--tool-args <json>", "JSON for tool_input (default: {})")
|
|
490
|
+
.option("--json", "emit JSON instead of YAML")
|
|
491
|
+
.action((prompt, options) => {
|
|
492
|
+
const dryRunOpts = {};
|
|
493
|
+
if (options.config)
|
|
494
|
+
dryRunOpts.configPath = options.config;
|
|
495
|
+
if (options.project)
|
|
496
|
+
dryRunOpts.project = options.project;
|
|
497
|
+
if (options.tool)
|
|
498
|
+
dryRunOpts.tool = options.tool;
|
|
499
|
+
if (options.toolArgs)
|
|
500
|
+
dryRunOpts.toolArgs = options.toolArgs;
|
|
501
|
+
if (options.json)
|
|
502
|
+
dryRunOpts.json = options.json;
|
|
503
|
+
const result = dryRun(prompt, dryRunOpts);
|
|
504
|
+
stdout(result.output);
|
|
505
|
+
});
|
|
506
|
+
const policy = program.command("policy").description("Policy runtime verbs");
|
|
507
|
+
policy
|
|
508
|
+
.command("intercept")
|
|
509
|
+
.description("PreToolUse hook entrypoint: read tool-event JSON from stdin, evaluate matching policies, emit Claude Code deny JSON on block")
|
|
510
|
+
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
511
|
+
.option("--project <name>", "apply per-project overrides")
|
|
512
|
+
.option("--ledger-timeout <ms>", "per-call ledger timeout in milliseconds")
|
|
513
|
+
.option("--verbose", "emit a stderr diagnostic block for each non-allow decision (also enabled by HARNESS_POLICY_VERBOSE=1)")
|
|
514
|
+
.action(async (options) => {
|
|
515
|
+
const cliOpts = {};
|
|
516
|
+
if (options.config)
|
|
517
|
+
cliOpts.configPath = options.config;
|
|
518
|
+
if (options.project)
|
|
519
|
+
cliOpts.project = options.project;
|
|
520
|
+
if (options.ledgerTimeout) {
|
|
521
|
+
const n = Number.parseInt(options.ledgerTimeout, 10);
|
|
522
|
+
if (Number.isFinite(n) && n > 0)
|
|
523
|
+
cliOpts.ledgerTimeoutMs = n;
|
|
524
|
+
}
|
|
525
|
+
if (options.verbose)
|
|
526
|
+
cliOpts.verbose = options.verbose;
|
|
527
|
+
await runInterceptCli(cliOpts);
|
|
528
|
+
});
|
|
529
|
+
return program;
|
|
530
|
+
}
|
|
531
|
+
export async function run(opts = {}) {
|
|
532
|
+
const argv = opts.argv ?? process.argv.slice(2);
|
|
533
|
+
const stderr = opts.stderr ?? ((s) => process.stderr.write(s));
|
|
534
|
+
const program = buildProgram(opts);
|
|
535
|
+
try {
|
|
536
|
+
await program.parseAsync(argv, { from: "user" });
|
|
537
|
+
return 0;
|
|
538
|
+
}
|
|
539
|
+
catch (err) {
|
|
540
|
+
if (err instanceof HarnessExitError) {
|
|
541
|
+
if (err.exitCode !== 0 && err.message)
|
|
542
|
+
stderr(`${err.message}\n`);
|
|
543
|
+
return err.exitCode;
|
|
544
|
+
}
|
|
545
|
+
stderr(`${err.message ?? err}\n`);
|
|
546
|
+
return 70;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type TemplateName } from "./templates.js";
|
|
2
|
+
export interface InitOptions {
|
|
3
|
+
template?: TemplateName;
|
|
4
|
+
force?: boolean;
|
|
5
|
+
configPath?: string;
|
|
6
|
+
homeDir?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface InitResult {
|
|
9
|
+
path: string;
|
|
10
|
+
template: TemplateName;
|
|
11
|
+
overwrote: boolean;
|
|
12
|
+
stdout: string;
|
|
13
|
+
stderr: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function init(opts?: InitOptions): Promise<InitResult>;
|
|
16
|
+
export declare const KNOWN_TEMPLATES: TemplateName[];
|
|
17
|
+
export declare function isTemplate(s: string): s is TemplateName;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { atomicWriteFile } from "../../io/atomic-write.js";
|
|
5
|
+
import { withFileLock } from "../../io/lock.js";
|
|
6
|
+
import { formatValidationErrors, validateBeforeWrite, } from "../../io/validate-before-write.js";
|
|
7
|
+
import { parse as parseYaml } from "yaml";
|
|
8
|
+
import { EX_FAIL, EX_SOFTWARE, HarnessExitError } from "../exit-codes.js";
|
|
9
|
+
import { getTemplate } from "./templates.js";
|
|
10
|
+
const DEFAULT_BASENAME = "harness.yaml";
|
|
11
|
+
const LOCK_BASENAME = ".harness.lock";
|
|
12
|
+
function defaultHome(opts) {
|
|
13
|
+
return opts.homeDir ?? path.join(os.homedir(), ".claude");
|
|
14
|
+
}
|
|
15
|
+
function resolveTargetPath(opts) {
|
|
16
|
+
if (opts.configPath)
|
|
17
|
+
return path.resolve(opts.configPath);
|
|
18
|
+
return path.join(defaultHome(opts), DEFAULT_BASENAME);
|
|
19
|
+
}
|
|
20
|
+
export async function init(opts = {}) {
|
|
21
|
+
const target = resolveTargetPath(opts);
|
|
22
|
+
const template = opts.template ?? "minimal";
|
|
23
|
+
const content = getTemplate(template);
|
|
24
|
+
// Validate the template before any disk work — a broken template is a code
|
|
25
|
+
// bug, not a user error, but failing loud here makes that bug obvious.
|
|
26
|
+
const validation = validateBeforeWrite(parseYaml(content));
|
|
27
|
+
if (!validation.ok) {
|
|
28
|
+
throw new HarnessExitError(`template "${template}" failed validation:\n${formatValidationErrors(validation.errors)}`, EX_SOFTWARE);
|
|
29
|
+
}
|
|
30
|
+
const lockPath = path.join(path.dirname(target), LOCK_BASENAME);
|
|
31
|
+
// Existence check + write inside the lock so two concurrent `init` calls
|
|
32
|
+
// can't both pass the !force guard and clobber each other.
|
|
33
|
+
let exists = false;
|
|
34
|
+
await withFileLock(lockPath, () => {
|
|
35
|
+
exists = fs.existsSync(target);
|
|
36
|
+
if (exists && !opts.force) {
|
|
37
|
+
throw new HarnessExitError(`harness manifest already exists at ${target}; pass --force to overwrite`, EX_FAIL);
|
|
38
|
+
}
|
|
39
|
+
atomicWriteFile(target, content);
|
|
40
|
+
});
|
|
41
|
+
const stderr = exists ? `(overwriting existing manifest at ${target})\n` : "";
|
|
42
|
+
const stdout = [
|
|
43
|
+
`harness manifest written to ${target} (template: ${template})`,
|
|
44
|
+
"",
|
|
45
|
+
"Next steps:",
|
|
46
|
+
` harness validate --config ${target}`,
|
|
47
|
+
` harness describe --config ${target}`,
|
|
48
|
+
` harness doctor --config ${target}`,
|
|
49
|
+
"",
|
|
50
|
+
].join("\n");
|
|
51
|
+
return { path: target, template, overwrote: exists, stdout, stderr };
|
|
52
|
+
}
|
|
53
|
+
export const KNOWN_TEMPLATES = ["minimal", "full"];
|
|
54
|
+
export function isTemplate(s) {
|
|
55
|
+
return KNOWN_TEMPLATES.includes(s);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=index.js.map
|