@lannguyensi/harness 0.23.2 → 0.24.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 +17 -0
- package/dist/cli/add/index.js +2 -2
- package/dist/cli/add/index.js.map +1 -1
- package/dist/cli/adopt/index.js +2 -2
- package/dist/cli/adopt/index.js.map +1 -1
- package/dist/cli/apply/apply.d.ts +19 -0
- package/dist/cli/apply/apply.js +65 -6
- package/dist/cli/apply/apply.js.map +1 -1
- package/dist/cli/apply/generate-codex-config.js +43 -36
- package/dist/cli/apply/generate-codex-config.js.map +1 -1
- package/dist/cli/apply/index.d.ts +2 -1
- package/dist/cli/apply/index.js +1 -0
- package/dist/cli/apply/index.js.map +1 -1
- package/dist/cli/apply/install-codex-config.d.ts +28 -0
- package/dist/cli/apply/install-codex-config.js +171 -0
- package/dist/cli/apply/install-codex-config.js.map +1 -0
- package/dist/cli/approve/understanding.d.ts +1 -1
- package/dist/cli/approve/understanding.js +55 -30
- package/dist/cli/approve/understanding.js.map +1 -1
- package/dist/cli/diff/since-apply.js +2 -2
- package/dist/cli/diff/since-apply.js.map +1 -1
- package/dist/cli/index.js +69 -36
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/composer.js +1 -1
- package/dist/cli/init/composer.js.map +1 -1
- package/dist/cli/init/index.js +2 -2
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/interactive.js +15 -5
- package/dist/cli/init/interactive.js.map +1 -1
- package/dist/cli/init/profiles.d.ts +2 -2
- package/dist/cli/init/profiles.js +5 -5
- package/dist/cli/init/profiles.js.map +1 -1
- package/dist/cli/init/templates.d.ts +2 -2
- package/dist/cli/init/templates.js +3 -3
- package/dist/cli/loader.js +12 -8
- package/dist/cli/loader.js.map +1 -1
- package/dist/cli/main.js +4 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/migrate-home/index.d.ts +39 -0
- package/dist/cli/migrate-home/index.js +194 -0
- package/dist/cli/migrate-home/index.js.map +1 -0
- package/dist/cli/pack/add.js +2 -2
- package/dist/cli/pack/add.js.map +1 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.js +16 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/remove.js +2 -2
- package/dist/cli/pack/remove.js.map +1 -1
- package/dist/cli/remove/index.js +2 -2
- package/dist/cli/remove/index.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution.js +23 -13
- package/dist/policy-packs/builtin/understanding-before-execution.js.map +1 -1
- package/dist/runtime/home-dir.d.ts +39 -0
- package/dist/runtime/home-dir.js +105 -0
- package/dist/runtime/home-dir.js.map +1 -0
- package/dist/runtime/intercept.js +10 -6
- package/dist/runtime/intercept.js.map +1 -1
- package/dist/runtime/tool-name-aliases.d.ts +7 -0
- package/dist/runtime/tool-name-aliases.js +74 -0
- package/dist/runtime/tool-name-aliases.js.map +1 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -56,6 +56,7 @@ import { runPackHookBranchProtectionCli } from "./pack/hook-branch-protection.js
|
|
|
56
56
|
import { gateDisable, GateDisableError } from "./gate/disable.js";
|
|
57
57
|
import { gateEnable, GateEnableError } from "./gate/enable.js";
|
|
58
58
|
import { uninstall, UninstallError } from "./uninstall/index.js";
|
|
59
|
+
import { migrateHome } from "./migrate-home/index.js";
|
|
59
60
|
import { pause as pauseHarness, resume as resumeHarness } from "./pause/index.js";
|
|
60
61
|
import { formatSmokeReport, runSmoke, splitCommaList, } from "./smoke/index.js";
|
|
61
62
|
import { formatReport, validate } from "./validate/index.js";
|
|
@@ -88,7 +89,7 @@ export function buildProgram(opts = {}) {
|
|
|
88
89
|
program
|
|
89
90
|
.command("describe")
|
|
90
91
|
.description("Print the effective merged manifest")
|
|
91
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
92
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
92
93
|
.option("--project <name>", "apply per-project overrides for this project name")
|
|
93
94
|
.option("--pillar <pillar>", "filter output to one section: grounding | tools | memory | hooks | policies | workflows | review_templates")
|
|
94
95
|
.option("--json", "emit JSON instead of YAML")
|
|
@@ -113,7 +114,7 @@ export function buildProgram(opts = {}) {
|
|
|
113
114
|
program
|
|
114
115
|
.command("validate")
|
|
115
116
|
.description("Lint the manifest + referenced assets")
|
|
116
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
117
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
117
118
|
.option("--project <name>", "apply per-project overrides for this project name")
|
|
118
119
|
.option("--strict", "promote warnings to errors")
|
|
119
120
|
.option("--check-lock", "surface harness.lock asset-content drift as warnings (or errors with --strict)")
|
|
@@ -136,7 +137,7 @@ export function buildProgram(opts = {}) {
|
|
|
136
137
|
program
|
|
137
138
|
.command("doctor")
|
|
138
139
|
.description("Health summary across all pillars")
|
|
139
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
140
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
140
141
|
.option("--project <name>", "apply per-project overrides for this project name")
|
|
141
142
|
.option("--shallow", "skip MCP probes (CLI --version probes still run); report manifest-reference state only")
|
|
142
143
|
.option("--target <runtime>", `additionally evaluate the harness-side adapter health for a runtime (allowed: ${KNOWN_DOCTOR_TARGETS.join(", ")})`)
|
|
@@ -166,7 +167,7 @@ export function buildProgram(opts = {}) {
|
|
|
166
167
|
program
|
|
167
168
|
.command("list <category>")
|
|
168
169
|
.description("Flat denormalised listing per category: mcp / cli / skills / memories / hooks / policies / workflows")
|
|
169
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
170
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
170
171
|
.option("--project <name>", "apply per-project overrides")
|
|
171
172
|
.option("--filter <substr>", "case-insensitive substring filter on name (or path for memories)")
|
|
172
173
|
.option("--json", "emit JSON array instead of an aligned text table")
|
|
@@ -187,7 +188,7 @@ export function buildProgram(opts = {}) {
|
|
|
187
188
|
.description("Diff the manifest against a git ref (--since <ref>) or against the last " +
|
|
188
189
|
"applied state (--since-apply). --memory-detail expands per-memory-dir " +
|
|
189
190
|
"Merkle drift back to per-file changes.")
|
|
190
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
191
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
191
192
|
.option("--project <name>", "apply per-project overrides")
|
|
192
193
|
.option("--since <ref>", "git ref to diff against")
|
|
193
194
|
.option("--since-apply", "diff against harness.generated/.last-apply")
|
|
@@ -230,8 +231,8 @@ export function buildProgram(opts = {}) {
|
|
|
230
231
|
.description("Bootstrap a starter harness.yaml from a template")
|
|
231
232
|
.option("--template <name>", `template to instantiate: ${KNOWN_TEMPLATES.join(" | ")} (default: minimal)`)
|
|
232
233
|
.option("--force", "overwrite an existing manifest")
|
|
233
|
-
.option("--config <path>", "manifest path to write (default: ~/.claude/harness.yaml)")
|
|
234
|
-
.option("--probe", "skip writing, print a JSON snapshot of detected runtimes (Claude Code, Codex), the existing ~/.claude/harness.yaml, and MCP servers wired in settings.json. Read-only.")
|
|
234
|
+
.option("--config <path>", "manifest path to write (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
235
|
+
.option("--probe", "skip writing, print a JSON snapshot of detected runtimes (Claude Code, Codex), the existing ~/.harness/harness.yaml (or legacy ~/.claude/harness.yaml), and MCP servers wired in settings.json. Read-only.")
|
|
235
236
|
.option("--interactive", "run the guided wizard (detect environment, pick profile, preview + write). Mutually exclusive with --probe / --template.")
|
|
236
237
|
.action(async (options) => {
|
|
237
238
|
if (options.probe && options.interactive) {
|
|
@@ -275,7 +276,7 @@ export function buildProgram(opts = {}) {
|
|
|
275
276
|
.description("Insert a new entry into harness.yaml (managed mutation)");
|
|
276
277
|
function addCommonOptions(c) {
|
|
277
278
|
return c
|
|
278
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
279
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
279
280
|
.option("--dry-run", "print the unified diff and exit without writing");
|
|
280
281
|
}
|
|
281
282
|
function parseBlocking(s) {
|
|
@@ -383,7 +384,7 @@ export function buildProgram(opts = {}) {
|
|
|
383
384
|
.description("Emit the effective merged manifest as a single self-contained YAML " +
|
|
384
385
|
"(or JSON). --sanitize redacts /home/<user>/ paths and env values whose " +
|
|
385
386
|
"key looks credential-shaped.")
|
|
386
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
387
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
387
388
|
.option("--project <name>", "apply per-project overrides for this project name")
|
|
388
389
|
.option("--sanitize", "redact /home/<user>/ paths and credential-shaped env values")
|
|
389
390
|
.option("--json", "emit JSON instead of YAML")
|
|
@@ -410,7 +411,7 @@ export function buildProgram(opts = {}) {
|
|
|
410
411
|
.description("Capture hand-edits from a runtime file (today: ~/.claude/settings.json) " +
|
|
411
412
|
"into the manifest. Diffs against the manifest's current declarations and " +
|
|
412
413
|
"prompts y/N before writing.")
|
|
413
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
414
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
414
415
|
.option("--yes", "skip the confirmation prompt (for non-interactive use)")
|
|
415
416
|
.action(async (file, options) => {
|
|
416
417
|
const result = await adopt(file, { configPath: options.config, yes: options.yes });
|
|
@@ -441,7 +442,7 @@ export function buildProgram(opts = {}) {
|
|
|
441
442
|
.description("Regenerate harness.generated/ outputs (settings.json + MEMORY.md index) " +
|
|
442
443
|
"from the manifest. Refuses to overwrite hand-edits without --overwrite-drift; " +
|
|
443
444
|
"use `harness adopt <file>` to capture them back into the manifest instead.")
|
|
444
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
445
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
445
446
|
.option("--project <name>", "apply per-project overrides for this project name")
|
|
446
447
|
.option("--dry-run", "print the would-be diff + restart hints; do not write")
|
|
447
448
|
.option("--overwrite-drift", "discard any on-disk hand-edits to harness.generated/ files (prompts for `yes`)")
|
|
@@ -452,6 +453,8 @@ export function buildProgram(opts = {}) {
|
|
|
452
453
|
.option("--runtime <runtime>", `policy-pack adapter runtime (${KNOWN_RUNTIMES.join(" | ")}; default: claude-code). ` +
|
|
453
454
|
"Selects which adapter shape policy-pack hooks expand into and which artefacts apply writes. " +
|
|
454
455
|
"`codex` emits harness.generated/codex/config.toml in place of settings.json.")
|
|
456
|
+
.option("--install", "with --runtime codex, merge the generated hook block into ~/.codex/config.toml")
|
|
457
|
+
.option("--codex-config <path>", "with --runtime codex --install, override the Codex config path (default ~/.codex/config.toml)")
|
|
455
458
|
.option("--quiet", "suppress the post-apply Next-steps hint")
|
|
456
459
|
.option("--json", "emit a structured JSON summary instead of prose (implies --quiet)")
|
|
457
460
|
.action(async (options) => {
|
|
@@ -478,6 +481,10 @@ export function buildProgram(opts = {}) {
|
|
|
478
481
|
...(options.merge ? { merge: true } : {}),
|
|
479
482
|
...(options.force ? { force: true } : {}),
|
|
480
483
|
...(runtime !== undefined ? { runtime } : {}),
|
|
484
|
+
...(options.install ? { installCodex: true } : {}),
|
|
485
|
+
...(options.codexConfig !== undefined
|
|
486
|
+
? { codexConfigPath: options.codexConfig }
|
|
487
|
+
: {}),
|
|
481
488
|
});
|
|
482
489
|
if (options.json) {
|
|
483
490
|
// Machine-readable: one JSON object on stdout regardless of
|
|
@@ -532,6 +539,9 @@ export function buildProgram(opts = {}) {
|
|
|
532
539
|
for (const f of changedFiles) {
|
|
533
540
|
stdout(` ${f.path}\n`);
|
|
534
541
|
}
|
|
542
|
+
if (result.codexConfigInstall?.changed) {
|
|
543
|
+
stdout(` ${result.codexConfigInstall.configPath} (Codex install)\n`);
|
|
544
|
+
}
|
|
535
545
|
}
|
|
536
546
|
else {
|
|
537
547
|
stdout(`applied ${changedFiles.length} file(s):\n`);
|
|
@@ -546,6 +556,12 @@ export function buildProgram(opts = {}) {
|
|
|
546
556
|
stdout(`wrote target: ${result.targetPath}\n`);
|
|
547
557
|
}
|
|
548
558
|
}
|
|
559
|
+
if (result.codexConfigInstall?.written) {
|
|
560
|
+
stdout(`${result.codexConfigInstall.summary}\n`);
|
|
561
|
+
if (result.codexConfigInstall.backupPath) {
|
|
562
|
+
stdout(`backup written to ${result.codexConfigInstall.backupPath}\n`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
549
565
|
stdout(`harness.lock written to ${result.lockPath}\n`);
|
|
550
566
|
if (!options.quiet) {
|
|
551
567
|
// The hint passes `targetPath` only when the target was
|
|
@@ -587,7 +603,7 @@ export function buildProgram(opts = {}) {
|
|
|
587
603
|
.command("remove <type> <name>")
|
|
588
604
|
.description(`Remove an entry by name. <type> is one of ${KNOWN_REMOVE_TYPES.join(" | ")}. ` +
|
|
589
605
|
"Refuses to remove a hook still referenced by a policy unless --force.")
|
|
590
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
606
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
591
607
|
.option("--dry-run", "print the unified diff and exit without writing")
|
|
592
608
|
.option("--force", "remove even if a policy references this entry (dangling policy.hook is then caught by schema)")
|
|
593
609
|
.action(async (type, name, options) => {
|
|
@@ -615,7 +631,7 @@ export function buildProgram(opts = {}) {
|
|
|
615
631
|
packCmd
|
|
616
632
|
.command("add <name>")
|
|
617
633
|
.description("Insert a new policy_packs entry. <name> must be a known builtin (see docs/policy-packs/).")
|
|
618
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
634
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
619
635
|
.option("--mode <mode>", "pack-specific config.mode value (e.g. fast_confirm | grill_me | strict)")
|
|
620
636
|
.option("--source <src>", "pack source (default: builtin)")
|
|
621
637
|
.option("--description <text>", "operator-facing description")
|
|
@@ -645,7 +661,7 @@ export function buildProgram(opts = {}) {
|
|
|
645
661
|
.command("remove <name>")
|
|
646
662
|
.description("Remove a policy_packs entry. Refuses without --force when applied state " +
|
|
647
663
|
"is recorded in .last-apply.")
|
|
648
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
664
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
649
665
|
.option("--dry-run", "print the unified diff and exit without writing")
|
|
650
666
|
.option("--force", "remove the manifest entry AND clean up the on-disk pack files + .last-apply state")
|
|
651
667
|
.action(async (name, options) => {
|
|
@@ -673,7 +689,7 @@ export function buildProgram(opts = {}) {
|
|
|
673
689
|
packHookCmd
|
|
674
690
|
.command("pre-tool-use")
|
|
675
691
|
.description("PreToolUse blocker: read tool-event JSON from stdin, consult ledger + persisted report, emit deny JSON on block")
|
|
676
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
692
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
677
693
|
.option("--project <name>", "apply per-project overrides")
|
|
678
694
|
.option("--pack <name>", "pack name to evaluate (default: understanding-before-execution)")
|
|
679
695
|
.option("--ledger-timeout <ms>", "per-call ledger timeout in milliseconds")
|
|
@@ -698,7 +714,7 @@ export function buildProgram(opts = {}) {
|
|
|
698
714
|
packHookCmd
|
|
699
715
|
.command("post-tool-use")
|
|
700
716
|
.description("PostToolUse marker-expiry: read tool-event JSON from stdin, delete the per-session approval marker when the just-completed tool matches config.approval_lifecycle.expire_on_tool_match (agent-tasks/d8ee60ca)")
|
|
701
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
717
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
702
718
|
.option("--project <name>", "apply per-project overrides")
|
|
703
719
|
.option("--pack <name>", "pack name to evaluate (default: understanding-before-execution)")
|
|
704
720
|
.action(async (options) => {
|
|
@@ -714,7 +730,7 @@ export function buildProgram(opts = {}) {
|
|
|
714
730
|
packHookCmd
|
|
715
731
|
.command("track-active-claim")
|
|
716
732
|
.description("PostToolUse: read tool-event JSON from stdin, maintain ~/.claude/harness.generated/active-claim on agent-tasks task_start / task_finish / task_abandon so `harness approve understanding` can auto-resolve the task id without --task (harness/494fd1e5).")
|
|
717
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
733
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
718
734
|
.option("--project <name>", "apply per-project overrides")
|
|
719
735
|
.option("--pack <name>", "pack name to evaluate (default: understanding-before-execution)")
|
|
720
736
|
.action(async (options) => {
|
|
@@ -733,7 +749,7 @@ export function buildProgram(opts = {}) {
|
|
|
733
749
|
packHookCmd
|
|
734
750
|
.command("codex-pre-tool-use")
|
|
735
751
|
.description("Codex PreToolUse blocker: read tool-event JSON from stdin, consult ledger + persisted report, exit 2 with stderr reason on block")
|
|
736
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
752
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
737
753
|
.option("--project <name>", "apply per-project overrides")
|
|
738
754
|
.option("--pack <name>", "pack name to evaluate (default: understanding-before-execution)")
|
|
739
755
|
.option("--ledger-timeout <ms>", "per-call ledger timeout in milliseconds")
|
|
@@ -761,7 +777,7 @@ export function buildProgram(opts = {}) {
|
|
|
761
777
|
packHookCmd
|
|
762
778
|
.command("codex-user-prompt-submit")
|
|
763
779
|
.description("Codex UserPromptSubmit injector: emit the Understanding-Gate instruction template on stdout for Codex to prepend to additional_instructions")
|
|
764
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
780
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
765
781
|
.option("--project <name>", "apply per-project overrides")
|
|
766
782
|
.option("--pack <name>", "pack name to evaluate (default: understanding-before-execution)")
|
|
767
783
|
.action(async (options) => {
|
|
@@ -779,7 +795,7 @@ export function buildProgram(opts = {}) {
|
|
|
779
795
|
.description("PreToolUse blocker for the branch-protection pack: read tool-event JSON from stdin, consult the " +
|
|
780
796
|
"evidence ledger, emit a deny envelope on protected branches unless either a fresh " +
|
|
781
797
|
"`branch:non-protected` tag (within 5m) or a `branch-protection-ack` override is present.")
|
|
782
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
798
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
783
799
|
.option("--project <name>", "apply per-project overrides")
|
|
784
800
|
.option("--ledger-timeout <ms>", "per-call ledger timeout in milliseconds")
|
|
785
801
|
.option("--cwd <path>", "override cwd resolution (default: stdin event.cwd then process.cwd())")
|
|
@@ -804,7 +820,7 @@ export function buildProgram(opts = {}) {
|
|
|
804
820
|
packHookCmd
|
|
805
821
|
.command("codex-stop")
|
|
806
822
|
.description("Codex Stop-equivalent: parse the agent's last message for an Understanding Report and persist it under .understanding-gate/reports/ as approvalStatus:pending. Failure modes resolve to exit 0 (capture must never block the agent's stop path).")
|
|
807
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
823
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
808
824
|
.option("--project <name>", "apply per-project overrides")
|
|
809
825
|
.option("--pack <name>", "pack name to evaluate (default: understanding-before-execution)")
|
|
810
826
|
.option("--reports-dir <path>", "override the persisted-report directory (default: ./.understanding-gate/reports)")
|
|
@@ -830,7 +846,7 @@ export function buildProgram(opts = {}) {
|
|
|
830
846
|
packCmd
|
|
831
847
|
.command("list")
|
|
832
848
|
.description("Print policy_packs entries as a flat table or JSON.")
|
|
833
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
849
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
834
850
|
.option("--project <name>", "apply per-project overrides")
|
|
835
851
|
.option("--enabled-only", "skip entries with enabled: false")
|
|
836
852
|
.option("--json", "emit JSON array instead of an aligned text table")
|
|
@@ -854,7 +870,7 @@ export function buildProgram(opts = {}) {
|
|
|
854
870
|
.command("understanding")
|
|
855
871
|
.description("Mark the latest Understanding Report as approved AND write the evidence-ledger tag. " +
|
|
856
872
|
"Round-trips both sources so harnessed and solo (@lannguyensi/understanding-gate) stacks stay in sync.")
|
|
857
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
873
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
858
874
|
.option("--project <name>", "apply per-project overrides")
|
|
859
875
|
.option("--session <id>", "explicit session id (default: $CLAUDE_SESSION_ID)")
|
|
860
876
|
.option("--task <id>", "agent-tasks task id — when set, also writes a task-scoped marker so the next task re-prompts for an Understanding Report (harness/1ee26e77)")
|
|
@@ -880,9 +896,13 @@ export function buildProgram(opts = {}) {
|
|
|
880
896
|
// a wrong id before it lands in the ledger.
|
|
881
897
|
const sourceNote = result.sessionSource === "pending-approval"
|
|
882
898
|
? " (resolved from .pending-approval staged by the gate hook)"
|
|
883
|
-
: result.sessionSource === "env"
|
|
899
|
+
: result.sessionSource === "env-claude"
|
|
884
900
|
? " (from $CLAUDE_SESSION_ID)"
|
|
885
|
-
: ""
|
|
901
|
+
: result.sessionSource === "env-codex"
|
|
902
|
+
? " (from $CODEX_SESSION_ID)"
|
|
903
|
+
: result.sessionSource === "newest-report"
|
|
904
|
+
? " (resolved from sessionId field of the newest persisted Understanding Report)"
|
|
905
|
+
: "";
|
|
886
906
|
lines.push(`session: ${result.sessionId}${sourceNote}`);
|
|
887
907
|
if (result.marker.ok) {
|
|
888
908
|
lines.push(`marker: ✓ ${result.marker.filePath} (canonical gate signal)`);
|
|
@@ -923,7 +943,7 @@ export function buildProgram(opts = {}) {
|
|
|
923
943
|
program
|
|
924
944
|
.command("explain [policy]")
|
|
925
945
|
.description("Print a policy's definition; --trace reads the last recorded evaluation; --last traces the most recent decision in the ledger")
|
|
926
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
946
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
927
947
|
.option("--project <name>", "apply per-project overrides")
|
|
928
948
|
.option("--json", "emit JSON instead of YAML")
|
|
929
949
|
.option("--trace", "include the full decision trail from the most recent evaluation")
|
|
@@ -965,7 +985,7 @@ export function buildProgram(opts = {}) {
|
|
|
965
985
|
.option("--since <duration>", "time window (default: 24h)")
|
|
966
986
|
.option("--policy <name>", "filter to a single policy by name")
|
|
967
987
|
.option("--outcome <outcome>", "filter by decision outcome (allow / deny / warn-degraded)")
|
|
968
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
988
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
969
989
|
.option("--project <name>", "apply per-project overrides")
|
|
970
990
|
.option("--session <id>", "grounding session whose audit log to read (default: $CLAUDE_SESSION_ID, then 'default')")
|
|
971
991
|
.option("--json", "emit JSON instead of a table")
|
|
@@ -991,7 +1011,7 @@ export function buildProgram(opts = {}) {
|
|
|
991
1011
|
program
|
|
992
1012
|
.command("session-export [sessionId]")
|
|
993
1013
|
.description("Export a chronological audit artifact joining the on-disk transcript JSONL and the evidence ledger for a session")
|
|
994
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1014
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
995
1015
|
.option("--project <name>", "apply per-project overrides")
|
|
996
1016
|
.option("--format <fmt>", "output format: json (default) or jsonl", "json")
|
|
997
1017
|
.option("-o, --out <file>", "write the export to <file> instead of stdout")
|
|
@@ -1022,7 +1042,7 @@ export function buildProgram(opts = {}) {
|
|
|
1022
1042
|
program
|
|
1023
1043
|
.command("dry-run <prompt>")
|
|
1024
1044
|
.description("Statically predict which hooks fire / policies match / memories route for a prompt")
|
|
1025
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1045
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1026
1046
|
.option("--project <name>", "apply per-project overrides")
|
|
1027
1047
|
.option("--tool <name>", "simulate a PreToolUse event for this tool name")
|
|
1028
1048
|
.option("--tool-args <json>", "JSON for tool_input (default: {})")
|
|
@@ -1049,7 +1069,7 @@ export function buildProgram(opts = {}) {
|
|
|
1049
1069
|
"Replaces the hand-rolled dogfood recipes under dogfood/phase5/.")
|
|
1050
1070
|
.requiredOption("--prompt <text>", "Prompt fed to claude -p")
|
|
1051
1071
|
.requiredOption("--output-dir <path>", "Directory for stream.jsonl + stderr.log + settings.json")
|
|
1052
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1072
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1053
1073
|
.option("--project <name>", "apply per-project overrides")
|
|
1054
1074
|
.option("--session-id <id>", "session id (default: fresh uuid)")
|
|
1055
1075
|
.option("--claude-bin <path>", "claude binary (default: $CLAUDE_BIN, then 'claude' on PATH)")
|
|
@@ -1110,7 +1130,7 @@ export function buildProgram(opts = {}) {
|
|
|
1110
1130
|
.command("preflight")
|
|
1111
1131
|
.description("Alias for `harness session-start preflight`: run agent-preflight against the session cwd " +
|
|
1112
1132
|
"and, on a ready:true result, record a `preflight:${REPO}` fact to the evidence ledger.")
|
|
1113
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1133
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1114
1134
|
.option("--project <name>", "apply per-project overrides")
|
|
1115
1135
|
.option("--session <id>", "explicit session id (overrides stdin event + env)")
|
|
1116
1136
|
.option("--timeout <ms>", "agent-preflight subprocess timeout in milliseconds (default 60000)")
|
|
@@ -1148,7 +1168,7 @@ export function buildProgram(opts = {}) {
|
|
|
1148
1168
|
"record a `preflight:${REPO}` fact to the evidence ledger so the preflight-before-* policies have a " +
|
|
1149
1169
|
"fresh tag to match. Reads SessionStart event JSON from stdin ({ session_id, cwd, hook_event_name }). " +
|
|
1150
1170
|
"blocking:false — every failure path logs to stderr and exits 0.")
|
|
1151
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1171
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1152
1172
|
.option("--project <name>", "apply per-project overrides")
|
|
1153
1173
|
.option("--session <id>", "explicit session id (overrides stdin event + env). Use for manual / scripted invocations " +
|
|
1154
1174
|
"where no SessionStart event JSON is piped on stdin. Without it the resolver tries " +
|
|
@@ -1187,7 +1207,7 @@ export function buildProgram(opts = {}) {
|
|
|
1187
1207
|
"record a `branch:non-protected:<branch>` fact to the evidence ledger so the pack's PreToolUse " +
|
|
1188
1208
|
"blocker has a fresh tag to satisfy its 5-minute freshness window. Also runnable on demand from " +
|
|
1189
1209
|
"the operator's shell. blocking:false — every failure path logs to stderr and exits 0.")
|
|
1190
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1210
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1191
1211
|
.option("--project <name>", "apply per-project overrides")
|
|
1192
1212
|
.option("--session <id>", "explicit session id (overrides stdin event + env)")
|
|
1193
1213
|
.option("--cwd <path>", "override cwd resolution (default: stdin event.cwd then process.cwd())")
|
|
@@ -1421,12 +1441,25 @@ export function buildProgram(opts = {}) {
|
|
|
1421
1441
|
}
|
|
1422
1442
|
});
|
|
1423
1443
|
program
|
|
1444
|
+
.command("migrate-home")
|
|
1445
|
+
.description("Move harness operator-state from the legacy ~/.claude/ root to the runtime-neutral " +
|
|
1446
|
+
"~/.harness/ root introduced in v0.24.0. Dry-run by default; pass --apply to perform " +
|
|
1447
|
+
"the move. Re-running on already-migrated state is a no-op. Moves: harness.yaml, " +
|
|
1448
|
+
"harness.generated/, .understanding-gate/, harness.lock. Does NOT touch settings.json " +
|
|
1449
|
+
"or any other ~/.claude/ contents.")
|
|
1450
|
+
.option("--apply", "perform the move (default: dry-run report only)")
|
|
1451
|
+
.action(async (options) => {
|
|
1452
|
+
const result = migrateHome({ ...(options.apply ? { apply: true } : {}) });
|
|
1453
|
+
if (result.outcome === "target-conflict") {
|
|
1454
|
+
throw new HarnessExitError("", EX_FAIL);
|
|
1455
|
+
}
|
|
1456
|
+
})
|
|
1424
1457
|
.command("pause")
|
|
1425
1458
|
.description("Temporarily make all harness hooks dormant by writing a sentinel under harness.generated/. " +
|
|
1426
1459
|
"Operator-only (refuses when $CLAUDE_SESSION_ID is set or stdin is non-TTY). Intended for " +
|
|
1427
1460
|
"lockout recovery, debug A/B-tests, and incident hotfixes. NOT for routine gate bypass: " +
|
|
1428
1461
|
"for permanent per-policy disable, edit `policies[].enabled` in the manifest.")
|
|
1429
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1462
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1430
1463
|
.option("--project <name>", "apply per-project overrides")
|
|
1431
1464
|
.option("--for <duration>", "auto-resume after this duration (e.g. 5m, 1h, PT30S; default: 15m)")
|
|
1432
1465
|
.option("--indefinite", "skip auto-expiry (requires --i-am-the-operator-and-accept-no-auto-resume)")
|
|
@@ -1476,7 +1509,7 @@ export function buildProgram(opts = {}) {
|
|
|
1476
1509
|
.command("resume")
|
|
1477
1510
|
.description("Delete the pause sentinel and re-enable harness hooks. Operator-only. Idempotent: " +
|
|
1478
1511
|
"running against an un-paused install exits 0 with a notice.")
|
|
1479
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1512
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1480
1513
|
.option("--project <name>", "apply per-project overrides")
|
|
1481
1514
|
.option("--i-am-the-operator", "acknowledge a scripted / non-TTY invocation (otherwise refused)")
|
|
1482
1515
|
.action(async (options) => {
|
|
@@ -1516,7 +1549,7 @@ export function buildProgram(opts = {}) {
|
|
|
1516
1549
|
"Stdin shape (per Claude Code hook protocol): " +
|
|
1517
1550
|
"{ session_id, hook_event_name, tool_name, tool_input, cwd?, transcript_path? }. " +
|
|
1518
1551
|
"hook_event_name is required for any policy to match; if missing or unmatched, a one-line diagnostic is written to stderr.")
|
|
1519
|
-
.option("--config <path>", "manifest path (default: ~/.claude/harness.yaml)")
|
|
1552
|
+
.option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
|
|
1520
1553
|
.option("--project <name>", "apply per-project overrides")
|
|
1521
1554
|
.option("--ledger-timeout <ms>", "per-call ledger timeout in milliseconds")
|
|
1522
1555
|
.option("--verbose", "emit a stderr diagnostic block for each non-allow decision (also enabled by HARNESS_POLICY_VERBOSE=1)")
|