@harness-engineering/cli 2.7.0 → 2.8.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.
Files changed (143) hide show
  1. package/dist/agents/personas/adversarial-reviewer.yaml +43 -0
  2. package/dist/agents/personas/frontend-races-reviewer.yaml +54 -0
  3. package/dist/agents/personas/typescript-strict-reviewer.yaml +53 -0
  4. package/dist/agents/skills/CHANGELOG.md +12 -0
  5. package/dist/agents/skills/claude-code/align-design-system/SKILL.md +18 -0
  6. package/dist/agents/skills/claude-code/align-design-system/skill.yaml +3 -0
  7. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +37 -5
  8. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +107 -22
  9. package/dist/agents/skills/claude-code/harness-code-review/references/confidence-rubric.md +45 -0
  10. package/dist/agents/skills/claude-code/harness-code-review/references/risk-keywords.md +40 -0
  11. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +3 -0
  12. package/dist/agents/skills/claude-code/harness-compound/SKILL.md +7 -4
  13. package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +277 -0
  14. package/dist/agents/skills/claude-code/harness-ideate/references/scoring.md +88 -0
  15. package/dist/agents/skills/claude-code/harness-ideate/skill.yaml +66 -0
  16. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +14 -4
  17. package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +12 -16
  18. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +34 -6
  19. package/dist/agents/skills/claude-code/harness-strategy/SKILL.md +152 -0
  20. package/dist/agents/skills/claude-code/harness-strategy/references/interview.md +122 -0
  21. package/dist/agents/skills/claude-code/harness-strategy/skill.yaml +54 -0
  22. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +76 -10
  23. package/dist/agents/skills/claude-code/naming-craft/SKILL.md +74 -2
  24. package/dist/agents/skills/codex/align-design-system/SKILL.md +18 -0
  25. package/dist/agents/skills/codex/align-design-system/skill.yaml +3 -0
  26. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +37 -5
  27. package/dist/agents/skills/codex/harness-code-review/SKILL.md +107 -22
  28. package/dist/agents/skills/codex/harness-code-review/references/confidence-rubric.md +45 -0
  29. package/dist/agents/skills/codex/harness-code-review/references/risk-keywords.md +40 -0
  30. package/dist/agents/skills/codex/harness-code-review/skill.yaml +3 -0
  31. package/dist/agents/skills/codex/harness-compound/SKILL.md +7 -4
  32. package/dist/agents/skills/codex/harness-ideate/SKILL.md +277 -0
  33. package/dist/agents/skills/codex/harness-ideate/references/scoring.md +88 -0
  34. package/dist/agents/skills/codex/harness-ideate/skill.yaml +66 -0
  35. package/dist/agents/skills/codex/harness-planning/SKILL.md +14 -4
  36. package/dist/agents/skills/codex/harness-pulse/SKILL.md +12 -16
  37. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +34 -6
  38. package/dist/agents/skills/codex/harness-strategy/SKILL.md +152 -0
  39. package/dist/agents/skills/codex/harness-strategy/references/interview.md +122 -0
  40. package/dist/agents/skills/codex/harness-strategy/skill.yaml +54 -0
  41. package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +76 -10
  42. package/dist/agents/skills/codex/naming-craft/SKILL.md +74 -2
  43. package/dist/agents/skills/cursor/align-design-system/SKILL.md +18 -0
  44. package/dist/agents/skills/cursor/align-design-system/skill.yaml +3 -0
  45. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +37 -5
  46. package/dist/agents/skills/cursor/harness-code-review/SKILL.md +107 -22
  47. package/dist/agents/skills/cursor/harness-code-review/references/confidence-rubric.md +45 -0
  48. package/dist/agents/skills/cursor/harness-code-review/references/risk-keywords.md +40 -0
  49. package/dist/agents/skills/cursor/harness-code-review/skill.yaml +3 -0
  50. package/dist/agents/skills/cursor/harness-compound/SKILL.md +7 -4
  51. package/dist/agents/skills/cursor/harness-ideate/SKILL.md +277 -0
  52. package/dist/agents/skills/cursor/harness-ideate/references/scoring.md +88 -0
  53. package/dist/agents/skills/cursor/harness-ideate/skill.yaml +66 -0
  54. package/dist/agents/skills/cursor/harness-planning/SKILL.md +14 -4
  55. package/dist/agents/skills/cursor/harness-pulse/SKILL.md +12 -16
  56. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +34 -6
  57. package/dist/agents/skills/cursor/harness-strategy/SKILL.md +152 -0
  58. package/dist/agents/skills/cursor/harness-strategy/references/interview.md +122 -0
  59. package/dist/agents/skills/cursor/harness-strategy/skill.yaml +54 -0
  60. package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +76 -10
  61. package/dist/agents/skills/cursor/naming-craft/SKILL.md +74 -2
  62. package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +18 -0
  63. package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +3 -0
  64. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +37 -5
  65. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +107 -22
  66. package/dist/agents/skills/gemini-cli/harness-code-review/references/confidence-rubric.md +45 -0
  67. package/dist/agents/skills/gemini-cli/harness-code-review/references/risk-keywords.md +40 -0
  68. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +3 -0
  69. package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +7 -4
  70. package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +277 -0
  71. package/dist/agents/skills/gemini-cli/harness-ideate/references/scoring.md +88 -0
  72. package/dist/agents/skills/gemini-cli/harness-ideate/skill.yaml +66 -0
  73. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +14 -4
  74. package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +12 -16
  75. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +34 -6
  76. package/dist/agents/skills/gemini-cli/harness-strategy/SKILL.md +152 -0
  77. package/dist/agents/skills/gemini-cli/harness-strategy/references/interview.md +122 -0
  78. package/dist/agents/skills/gemini-cli/harness-strategy/skill.yaml +54 -0
  79. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +76 -10
  80. package/dist/agents/skills/gemini-cli/naming-craft/SKILL.md +74 -2
  81. package/dist/agents/skills/package.json +1 -1
  82. package/dist/agents/skills/tests/harness-strategy.test.ts +145 -0
  83. package/dist/agents-md-WMJO5HSM.js +13 -0
  84. package/dist/analyzer-V633GUHY-MBCQWKDU.js +26 -0
  85. package/dist/{architecture-ZTEHGIHD.js → architecture-EVYVGPRZ.js} +6 -6
  86. package/dist/{assess-project-OKDW3YSK.js → assess-project-KZG563SO.js} +1 -1
  87. package/dist/bin/harness-mcp.js +17 -17
  88. package/dist/bin/harness.js +27 -27
  89. package/dist/{check-phase-gate-YJWFDW66.js → check-phase-gate-MK364VXS.js} +6 -6
  90. package/dist/{chunk-6UHDQP2N.js → chunk-2N4OENGE.js} +1 -1
  91. package/dist/{chunk-OLTVDPA2.js → chunk-2SNRCAC3.js} +3 -3
  92. package/dist/{chunk-HLPY3RHE.js → chunk-4BDOSCNY.js} +909 -559
  93. package/dist/{chunk-S7GEONXL.js → chunk-5XL5QJ5B.js} +2 -2
  94. package/dist/{chunk-OQE6ME2Z.js → chunk-7EQAZKJ5.js} +2 -2
  95. package/dist/{chunk-QUPC37UB.js → chunk-ACOOG3UW.js} +6 -6
  96. package/dist/{chunk-B4OLYXZ4.js → chunk-B7KMTHN3.js} +89 -7
  97. package/dist/{chunk-OH3NXXUY.js → chunk-BDGTZRZ6.js} +11 -1
  98. package/dist/{chunk-P7EO7USC.js → chunk-C7J55C6E.js} +10 -10
  99. package/dist/{chunk-4EGPFB7V.js → chunk-CAQPSFPT.js} +4753 -744
  100. package/dist/{chunk-TIH53QXY.js → chunk-CLI4K2CH.js} +1 -1
  101. package/dist/{chunk-ZKA3TGYS.js → chunk-EEFRPEWT.js} +1 -1
  102. package/dist/{chunk-TIZ3L6CU.js → chunk-FZ5MBXEG.js} +6 -6
  103. package/dist/{chunk-IY2TZLY5.js → chunk-GOHWCHCS.js} +1809 -812
  104. package/dist/{chunk-VG6UK6G6.js → chunk-HRSE6IQD.js} +2 -2
  105. package/dist/{chunk-67RP7MLR.js → chunk-KBCPELBC.js} +3 -3
  106. package/dist/{chunk-MQG7FHXX.js → chunk-KI6PHH6Q.js} +3 -3
  107. package/dist/{chunk-HMMSWRWR.js → chunk-LADPYELQ.js} +23 -3
  108. package/dist/{chunk-W3PDVZ4I.js → chunk-N55WOGN3.js} +90 -21
  109. package/dist/{chunk-H2ZJOJ7A.js → chunk-PP6ZRL5T.js} +316 -42
  110. package/dist/{chunk-B3B64OPD.js → chunk-STESM73J.js} +2 -2
  111. package/dist/{chunk-WOXR6I3R.js → chunk-UBZQE3JN.js} +2 -2
  112. package/dist/{chunk-6T5AYG5S.js → chunk-UJFNIWC7.js} +5 -5
  113. package/dist/{chunk-CXAHK5PJ.js → chunk-UUO4K7NX.js} +9 -9
  114. package/dist/{chunk-Z2GUITAS.js → chunk-UXPWSV3B.js} +9 -9
  115. package/dist/{chunk-PARV3G2F.js → chunk-VBNJAKUH.js} +2 -2
  116. package/dist/{chunk-XTIPZUPR.js → chunk-X4EFYVCZ.js} +2 -2
  117. package/dist/{ci-workflow-YGTQTNVC.js → ci-workflow-IW2H5DC4.js} +5 -5
  118. package/dist/{dist-E3SAAHCM.js → dist-ICW4QUEW.js} +5 -1
  119. package/dist/{dist-XIJWWQ5N.js → dist-JCFK263L.js} +52 -4
  120. package/dist/{dist-R3TOOPJ7.js → dist-OWHMNL4W.js} +1 -1
  121. package/dist/{docs-KCTLXK2G.js → docs-7CP6VV42.js} +6 -6
  122. package/dist/engine-MKJEBWU7.js +13 -0
  123. package/dist/{entropy-M27JUL3V.js → entropy-6JOZJYG7.js} +5 -5
  124. package/dist/{feedback-W25QO3OL.js → feedback-T65AEJEG.js} +1 -1
  125. package/dist/{generate-agent-definitions-RNMU5U5R.js → generate-agent-definitions-4VI4YTO2.js} +6 -6
  126. package/dist/{glob-helper-EX4YZKZO.js → glob-helper-GLZAURJC.js} +1 -1
  127. package/dist/{graph-loader-EIFEOUVI.js → graph-loader-HHXN5FLP.js} +1 -1
  128. package/dist/index.d.ts +627 -6
  129. package/dist/index.js +27 -27
  130. package/dist/{loader-HZKJ5ABV.js → loader-AWTHHE3A.js} +5 -5
  131. package/dist/{mcp-NEAPIDTT.js → mcp-JBIBINO2.js} +17 -17
  132. package/dist/{performance-3AVQUDRG.js → performance-NCOUDOMW.js} +6 -6
  133. package/dist/{review-pipeline-KA7SGUXJ.js → review-pipeline-YIC6JPMY.js} +5 -5
  134. package/dist/{runtime-IP6FVV5M.js → runtime-5MHV4UEE.js} +5 -5
  135. package/dist/{scan-LYKLM4EQ.js → scan-P7YFKB77.js} +1 -1
  136. package/dist/{security-EAR4FJWI.js → security-VZPJNIDP.js} +1 -1
  137. package/dist/{validate-EVH3UXIC.js → validate-7BE4VTFI.js} +6 -6
  138. package/dist/validate-cross-check-F7GEBRDH.js +13 -0
  139. package/package.json +7 -7
  140. package/dist/agents-md-267R2NUJ.js +0 -13
  141. package/dist/analyzer-VY6DJVOU-WYKV3TTW.js +0 -26
  142. package/dist/engine-J64WPH5K.js +0 -13
  143. package/dist/validate-cross-check-SNE3SQOB.js +0 -13
@@ -1,26 +1,26 @@
1
1
  import {
2
2
  generateRuntime
3
- } from "./chunk-S7GEONXL.js";
3
+ } from "./chunk-5XL5QJ5B.js";
4
4
  import {
5
5
  generateAgentsMd
6
- } from "./chunk-OQE6ME2Z.js";
6
+ } from "./chunk-7EQAZKJ5.js";
7
7
  import {
8
8
  generateCIWorkflow
9
- } from "./chunk-B3B64OPD.js";
9
+ } from "./chunk-STESM73J.js";
10
10
  import {
11
11
  createGenerateAgentDefinitionsCommand,
12
12
  generateAgentDefinitions
13
- } from "./chunk-ZKA3TGYS.js";
13
+ } from "./chunk-EEFRPEWT.js";
14
14
  import {
15
15
  toKebabCase
16
16
  } from "./chunk-KET4QQZB.js";
17
17
  import {
18
18
  createScanCommand,
19
19
  loadIngestOptions
20
- } from "./chunk-6UHDQP2N.js";
20
+ } from "./chunk-2N4OENGE.js";
21
21
  import {
22
22
  TemplateEngine
23
- } from "./chunk-WOXR6I3R.js";
23
+ } from "./chunk-UBZQE3JN.js";
24
24
  import {
25
25
  generate,
26
26
  validate
@@ -31,7 +31,7 @@ import {
31
31
  import {
32
32
  listPersonas,
33
33
  loadPersona
34
- } from "./chunk-XTIPZUPR.js";
34
+ } from "./chunk-X4EFYVCZ.js";
35
35
  import {
36
36
  runPersona
37
37
  } from "./chunk-GISMXMVL.js";
@@ -46,19 +46,21 @@ import {
46
46
  OutputMode,
47
47
  createCheckPhaseGateCommand,
48
48
  findFiles
49
- } from "./chunk-OLTVDPA2.js";
49
+ } from "./chunk-2SNRCAC3.js";
50
50
  import {
51
51
  appendFrameworkAgents,
52
52
  captureHealthSnapshot,
53
53
  createAdviseSkillsCommand,
54
54
  createGenerateSlashCommandsCommand,
55
55
  ensureHarnessGitignore,
56
+ findOrchestratorMd,
56
57
  generateSlashCommands,
57
58
  handleGetImpact,
58
59
  handleOrphanDeletion,
59
60
  isSnapshotFresh,
60
61
  loadCachedSnapshot,
61
62
  persistToolingConfig,
63
+ readBackendsFromOrchestratorMd,
62
64
  recommend,
63
65
  runAlignDesignSystem,
64
66
  runAudit,
@@ -72,13 +74,13 @@ import {
72
74
  runSecurityCraft,
73
75
  runSpecCraft,
74
76
  runTestCraft
75
- } from "./chunk-4EGPFB7V.js";
77
+ } from "./chunk-CAQPSFPT.js";
76
78
  import {
77
79
  VALID_PLATFORMS
78
80
  } from "./chunk-3ISINLYT.js";
79
81
  import {
80
82
  loadGraphStore
81
- } from "./chunk-TIH53QXY.js";
83
+ } from "./chunk-CLI4K2CH.js";
82
84
  import {
83
85
  loadOrRebuildIndex
84
86
  } from "./chunk-27AJKSQY.js";
@@ -97,7 +99,7 @@ import {
97
99
  BranchingConfigSchema,
98
100
  findConfigFile,
99
101
  resolveConfig
100
- } from "./chunk-B4OLYXZ4.js";
102
+ } from "./chunk-B7KMTHN3.js";
101
103
  import {
102
104
  logger
103
105
  } from "./chunk-EBJQ6N4M.js";
@@ -189,9 +191,10 @@ import {
189
191
  validatePulseConfig,
190
192
  validateRoadmapMode,
191
193
  validateSolutionsDir,
194
+ validateStrategy,
192
195
  writeConfig,
193
196
  writeLockfile
194
- } from "./chunk-IY2TZLY5.js";
197
+ } from "./chunk-GOHWCHCS.js";
195
198
  import {
196
199
  CLI_VERSION
197
200
  } from "./chunk-BM3PWGXQ.js";
@@ -204,20 +207,20 @@ import {
204
207
  detectDocDrift,
205
208
  generateSuggestions,
206
209
  validateDependencies
207
- } from "./chunk-W3PDVZ4I.js";
210
+ } from "./chunk-N55WOGN3.js";
208
211
  import {
209
212
  Err,
210
213
  INDEXED_FILE_KINDS,
211
214
  INSIGHTS_KEYS,
212
215
  Ok,
213
216
  init_dist
214
- } from "./chunk-OH3NXXUY.js";
217
+ } from "./chunk-BDGTZRZ6.js";
215
218
  import {
216
219
  DEFAULT_SKIP_DIRS,
217
220
  DesignConstraintAdapter,
218
221
  GraphStore,
219
222
  init_dist as init_dist2
220
- } from "./chunk-H2ZJOJ7A.js";
223
+ } from "./chunk-PP6ZRL5T.js";
221
224
  import {
222
225
  ArchConfigSchema,
223
226
  TimelineManager
@@ -228,7 +231,7 @@ import {
228
231
  } from "./chunk-KFQGP6VL.js";
229
232
 
230
233
  // src/index.ts
231
- import { Command as Command118 } from "commander";
234
+ import { Command as Command120 } from "commander";
232
235
 
233
236
  // src/commands/add.ts
234
237
  init_dist3();
@@ -417,7 +420,7 @@ function registerSkillsCommand(adoption) {
417
420
  const globalOpts = cmd.optsWithGlobals();
418
421
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
419
422
  const cwd = process.cwd();
420
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-XIJWWQ5N.js");
423
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-JCFK263L.js");
421
424
  const records = readAdoptionRecords(cwd);
422
425
  if (records.length === 0) {
423
426
  if (globalOpts.json) {
@@ -453,7 +456,7 @@ function registerRecentCommand(adoption) {
453
456
  const globalOpts = cmd.optsWithGlobals();
454
457
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
455
458
  const cwd = process.cwd();
456
- const { readAdoptionRecords } = await import("./dist-XIJWWQ5N.js");
459
+ const { readAdoptionRecords } = await import("./dist-JCFK263L.js");
457
460
  const records = readAdoptionRecords(cwd);
458
461
  if (records.length === 0) {
459
462
  if (globalOpts.json) {
@@ -531,7 +534,7 @@ function registerSkillCommand(adoption) {
531
534
  adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
532
535
  const globalOpts = cmd.optsWithGlobals();
533
536
  const cwd = process.cwd();
534
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-XIJWWQ5N.js");
537
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-JCFK263L.js");
535
538
  const records = readAdoptionRecords(cwd);
536
539
  const skillRecords = records.filter((r) => r.skill === name);
537
540
  if (skillRecords.length === 0) {
@@ -846,6 +849,9 @@ function createAlignDesignSystemCommand() {
846
849
  ).option(
847
850
  "--design-strictness <level>",
848
851
  "Override design.strictness: strict | standard | permissive"
852
+ ).option(
853
+ "--revert",
854
+ "Inverse-apply the most-recent batch recorded at .harness/align/last-batch.json. Skips files edited externally since the apply."
849
855
  ).action(async (opts, cmd) => {
850
856
  const globalOpts = cmd.optsWithGlobals();
851
857
  const outputMode = resolveOutputMode(globalOpts);
@@ -856,6 +862,7 @@ function createAlignDesignSystemCommand() {
856
862
  if (opts.files !== void 0) input.files = opts.files;
857
863
  if (opts.mode !== void 0) input.mode = opts.mode;
858
864
  if (opts.designStrictness !== void 0) input.designStrictness = opts.designStrictness;
865
+ if (opts.revert === true) input.revert = true;
859
866
  let result;
860
867
  try {
861
868
  result = await runAlignDesignSystem(input);
@@ -882,7 +889,11 @@ function printAlignResult(result, mode, _formatter) {
882
889
  const verbose = mode === OutputMode.VERBOSE;
883
890
  const { summary, outcomes, meta } = result;
884
891
  if (outcomes.length === 0) {
885
- console.log("No drift findings to align.");
892
+ if (meta.revert === true) {
893
+ console.log("No batch to revert (.harness/align/last-batch.json missing or empty).");
894
+ } else {
895
+ console.log("No drift findings to align.");
896
+ }
886
897
  return;
887
898
  }
888
899
  const byFile = /* @__PURE__ */ new Map();
@@ -912,8 +923,9 @@ ${file}`);
912
923
  }
913
924
  }
914
925
  console.log("");
926
+ const action = meta.revert === true ? "reverted" : "applied";
915
927
  console.log(
916
- `Summary: ${summary.applied} applied, ${summary.suggestions} suggestions, ${summary.skipped} skipped, ${summary.failed} failed (${summary.filesModified} files modified, ${summary.durationMs}ms)`
928
+ `Summary: ${summary.applied} ${action}, ${summary.suggestions} suggestions, ${summary.skipped} skipped, ${summary.failed} failed (${summary.filesModified} files modified, ${summary.durationMs}ms)`
917
929
  );
918
930
  if (meta.dryRun) {
919
931
  console.log("(dry-run \u2014 no files written)");
@@ -1124,7 +1136,7 @@ function runBackfillSkillProvenance(projectRoot2) {
1124
1136
  }
1125
1137
  function createBackfillSkillProvenanceCommand() {
1126
1138
  const cmd = new Command8("backfill-skill-provenance").description(
1127
- "Stamp `provenance: user-authored` on every catalog skill missing the field (Hermes Phase 4 one-shot)"
1139
+ "Stamp `provenance: user-authored` on every catalog skill missing the field (one-shot migration)"
1128
1140
  ).option("--root <path>", "Project root containing agents/skills/", process.cwd()).action((opts) => {
1129
1141
  const result = runBackfillSkillProvenance(opts.root);
1130
1142
  console.log(JSON.stringify(result, null, 2));
@@ -1652,9 +1664,9 @@ ${name} (${count} finding${count === 1 ? "" : "s"})`);
1652
1664
  }
1653
1665
  function printAnatomyFindings(findings, verbose) {
1654
1666
  const byFile = groupByFile(findings, (f) => f.file);
1655
- for (const [file, fs47] of byFile) {
1667
+ for (const [file, fs48] of byFile) {
1656
1668
  console.log(` ${file}`);
1657
- for (const f of fs47) {
1669
+ for (const f of fs48) {
1658
1670
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1659
1671
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1660
1672
  if (verbose) {
@@ -1665,9 +1677,9 @@ function printAnatomyFindings(findings, verbose) {
1665
1677
  }
1666
1678
  function printCraftFindings(findings, verbose) {
1667
1679
  const byFile = groupByFile(findings, (f) => f.target.file);
1668
- for (const [file, fs47] of byFile) {
1680
+ for (const [file, fs48] of byFile) {
1669
1681
  console.log(` ${file}`);
1670
- for (const f of fs47) {
1682
+ for (const f of fs48) {
1671
1683
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
1672
1684
  const sev = craftTierToSeverity(f.tier);
1673
1685
  console.log(
@@ -1681,9 +1693,9 @@ function printCraftFindings(findings, verbose) {
1681
1693
  }
1682
1694
  function printDriftFindings(findings, verbose) {
1683
1695
  const byFile = groupByFile(findings, (f) => f.file);
1684
- for (const [file, fs47] of byFile) {
1696
+ for (const [file, fs48] of byFile) {
1685
1697
  console.log(` ${file}`);
1686
- for (const f of fs47) {
1698
+ for (const f of fs48) {
1687
1699
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1688
1700
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1689
1701
  if (verbose) {
@@ -1694,9 +1706,9 @@ function printDriftFindings(findings, verbose) {
1694
1706
  }
1695
1707
  function printBrandFindings(findings, verbose) {
1696
1708
  const byFile = groupByFile(findings, (f) => f.file);
1697
- for (const [file, fs47] of byFile) {
1709
+ for (const [file, fs48] of byFile) {
1698
1710
  console.log(` ${file}`);
1699
- for (const f of fs47) {
1711
+ for (const f of fs48) {
1700
1712
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1701
1713
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1702
1714
  if (verbose) {
@@ -2015,10 +2027,10 @@ async function runCheckSecurity(cwd, options) {
2015
2027
  const projectRoot2 = path9.resolve(cwd);
2016
2028
  let configData = {};
2017
2029
  try {
2018
- const fs47 = await import("fs");
2030
+ const fs48 = await import("fs");
2019
2031
  const configPath = path9.join(projectRoot2, "harness.config.json");
2020
- if (fs47.existsSync(configPath)) {
2021
- const raw = fs47.readFileSync(configPath, "utf-8");
2032
+ if (fs48.existsSync(configPath)) {
2033
+ const raw = fs48.readFileSync(configPath, "utf-8");
2022
2034
  const parsed = JSON.parse(raw);
2023
2035
  configData = parsed.security ?? {};
2024
2036
  }
@@ -2786,10 +2798,10 @@ ${dryRun ? "Would remove" : "Removed"} ${totalRemoved} stale entry(ies) across t
2786
2798
  function createCleanupSessionsCommand() {
2787
2799
  const command = new Command21("cleanup-sessions").description(
2788
2800
  "Remove stale entries from .harness/. Default: only .harness/sessions/ (no write in 24h)."
2789
- ).option("--dry-run", "List stale entries without deleting them", false).option("--path <path>", "Project root path", ".").option("--all", "Hermes Phase 2: sweep every registered .harness/ target").option(
2801
+ ).option("--dry-run", "List stale entries without deleting them", false).option("--path <path>", "Project root path", ".").option("--all", "Sweep every registered .harness/ target").option(
2790
2802
  "--include <list>",
2791
- "Hermes Phase 2: comma-separated target names (mutually-exclusive with --exclude/--all)"
2792
- ).option("--exclude <list>", "Hermes Phase 2: comma-separated target names to skip").action(async (opts, cmd) => {
2803
+ "Comma-separated target names (mutually-exclusive with --exclude/--all)"
2804
+ ).option("--exclude <list>", "Comma-separated target names to skip").action(async (opts, cmd) => {
2793
2805
  const globalOpts = cmd.optsWithGlobals();
2794
2806
  const cwd = path12.resolve(opts.path);
2795
2807
  const asJson = Boolean(globalOpts.json);
@@ -2979,10 +2991,10 @@ function printResult2(result, mode, _formatter) {
2979
2991
  list.push(f);
2980
2992
  bySurface.set(f.target.surface, list);
2981
2993
  }
2982
- for (const [surface, fs47] of bySurface) {
2994
+ for (const [surface, fs48] of bySurface) {
2983
2995
  console.log(`
2984
2996
  [${surface}]`);
2985
- for (const f of fs47) {
2997
+ for (const f of fs48) {
2986
2998
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
2987
2999
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.file}${line}`);
2988
3000
  console.log(` "${truncate(f.target.snippet, 80)}"`);
@@ -4210,11 +4222,11 @@ import { Command as Command35 } from "commander";
4210
4222
  // src/commands/graph/status.ts
4211
4223
  import * as path16 from "path";
4212
4224
  async function readConnectorSyncStatus(graphDir) {
4213
- const fs47 = await import("fs/promises");
4225
+ const fs48 = await import("fs/promises");
4214
4226
  const result = {};
4215
4227
  try {
4216
4228
  const syncMetaPath = path16.join(graphDir, "sync-metadata.json");
4217
- const syncMeta = JSON.parse(await fs47.readFile(syncMetaPath, "utf-8"));
4229
+ const syncMeta = JSON.parse(await fs48.readFile(syncMetaPath, "utf-8"));
4218
4230
  for (const [name, data] of Object.entries(syncMeta.connectors ?? {})) {
4219
4231
  result[name] = data.lastSyncTimestamp;
4220
4232
  }
@@ -4223,7 +4235,7 @@ async function readConnectorSyncStatus(graphDir) {
4223
4235
  return result;
4224
4236
  }
4225
4237
  async function runGraphStatus(projectPath) {
4226
- const { GraphStore: GraphStore2, loadGraphMetadata } = await import("./dist-R3TOOPJ7.js");
4238
+ const { GraphStore: GraphStore2, loadGraphMetadata } = await import("./dist-OWHMNL4W.js");
4227
4239
  const graphDir = path16.join(projectPath, ".harness", "graph");
4228
4240
  const metaResult = await loadGraphMetadata(graphDir);
4229
4241
  if (metaResult.status === "not_found") {
@@ -4275,7 +4287,7 @@ async function runGraphStatus(projectPath) {
4275
4287
  // src/commands/graph/export.ts
4276
4288
  import * as path17 from "path";
4277
4289
  async function runGraphExport(projectPath, format) {
4278
- const { GraphStore: GraphStore2 } = await import("./dist-R3TOOPJ7.js");
4290
+ const { GraphStore: GraphStore2 } = await import("./dist-OWHMNL4W.js");
4279
4291
  const graphDir = path17.join(projectPath, ".harness", "graph");
4280
4292
  const store = new GraphStore2();
4281
4293
  const loaded = await store.load(graphDir);
@@ -4311,7 +4323,7 @@ import * as path20 from "path";
4311
4323
  import { Command as Command33 } from "commander";
4312
4324
  import * as path18 from "path";
4313
4325
  async function runQuery(projectPath, rootNodeId, opts) {
4314
- const { GraphStore: GraphStore2, ContextQL } = await import("./dist-R3TOOPJ7.js");
4326
+ const { GraphStore: GraphStore2, ContextQL } = await import("./dist-OWHMNL4W.js");
4315
4327
  const store = new GraphStore2();
4316
4328
  const graphDir = path18.join(projectPath, ".harness", "graph");
4317
4329
  const loaded = await store.load(graphDir);
@@ -4364,15 +4376,22 @@ import { Command as Command34 } from "commander";
4364
4376
  import * as path19 from "path";
4365
4377
  async function loadConnectorConfig(projectPath, source) {
4366
4378
  try {
4367
- const fs47 = await import("fs/promises");
4379
+ const fs48 = await import("fs/promises");
4368
4380
  const configPath = path19.join(projectPath, "harness.config.json");
4369
- const config = JSON.parse(await fs47.readFile(configPath, "utf-8"));
4381
+ const config = JSON.parse(await fs48.readFile(configPath, "utf-8"));
4370
4382
  const connector = config.graph?.connectors?.[source];
4371
4383
  return connector ?? {};
4372
4384
  } catch {
4373
4385
  return {};
4374
4386
  }
4375
4387
  }
4388
+ async function ingestBusinessKnowledge(bk, projectPath) {
4389
+ return mergeResults(
4390
+ await bk.ingest(path19.join(projectPath, "docs", "knowledge")),
4391
+ await bk.ingestSolutions(path19.join(projectPath, "docs", "solutions")),
4392
+ await bk.ingestStrategy(path19.join(projectPath, "STRATEGY.md"))
4393
+ );
4394
+ }
4376
4395
  function mergeResults(...results) {
4377
4396
  return results.reduce(
4378
4397
  (acc, r) => ({
@@ -4399,6 +4418,7 @@ async function runIngest(projectPath, source, opts) {
4399
4418
  CodeIngestor,
4400
4419
  TopologicalLinker,
4401
4420
  KnowledgeIngestor,
4421
+ BusinessKnowledgeIngestor,
4402
4422
  GitIngestor,
4403
4423
  RequirementIngestor,
4404
4424
  SyncManager,
@@ -4408,7 +4428,7 @@ async function runIngest(projectPath, source, opts) {
4408
4428
  ConfluenceConnector,
4409
4429
  FigmaConnector,
4410
4430
  MiroConnector
4411
- } = await import("./dist-R3TOOPJ7.js");
4431
+ } = await import("./dist-OWHMNL4W.js");
4412
4432
  const graphDir = path19.join(projectPath, ".harness", "graph");
4413
4433
  const store = new GraphStore2();
4414
4434
  await store.load(graphDir);
@@ -4418,11 +4438,13 @@ async function runIngest(projectPath, source, opts) {
4418
4438
  const codeResult = await new CodeIngestor(store, ingestOptions).ingest(projectPath);
4419
4439
  new TopologicalLinker(store).link();
4420
4440
  const knowledgeResult = await new KnowledgeIngestor(store).ingestAll(projectPath);
4441
+ const bkInst = new BusinessKnowledgeIngestor(store);
4442
+ const bkResult = await ingestBusinessKnowledge(bkInst, projectPath);
4421
4443
  const reqResult = await new RequirementIngestor(store).ingestSpecs(
4422
4444
  path19.join(projectPath, "docs", "changes")
4423
4445
  );
4424
4446
  const gitResult = await new GitIngestor(store).ingest(projectPath);
4425
- const { createExtractionRunner } = await import("./dist-R3TOOPJ7.js");
4447
+ const { createExtractionRunner } = await import("./dist-OWHMNL4W.js");
4426
4448
  const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
4427
4449
  const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
4428
4450
  const syncManager = new SyncManager(store, graphDir);
@@ -4443,6 +4465,7 @@ async function runIngest(projectPath, source, opts) {
4443
4465
  const merged = mergeResults(
4444
4466
  codeResult,
4445
4467
  knowledgeResult,
4468
+ bkResult,
4446
4469
  reqResult,
4447
4470
  gitResult,
4448
4471
  signalsResult,
@@ -4456,9 +4479,12 @@ async function runIngest(projectPath, source, opts) {
4456
4479
  result = await new CodeIngestor(store, ingestOptions).ingest(projectPath);
4457
4480
  new TopologicalLinker(store).link();
4458
4481
  break;
4459
- case "knowledge":
4460
- result = await new KnowledgeIngestor(store).ingestAll(projectPath);
4482
+ case "knowledge": {
4483
+ const knowledge = await new KnowledgeIngestor(store).ingestAll(projectPath);
4484
+ const bk = await ingestBusinessKnowledge(new BusinessKnowledgeIngestor(store), projectPath);
4485
+ result = mergeResults(knowledge, bk);
4461
4486
  break;
4487
+ }
4462
4488
  case "git":
4463
4489
  result = await new GitIngestor(store).ingest(projectPath);
4464
4490
  break;
@@ -4468,7 +4494,7 @@ async function runIngest(projectPath, source, opts) {
4468
4494
  );
4469
4495
  break;
4470
4496
  case "business-signals": {
4471
- const { createExtractionRunner } = await import("./dist-R3TOOPJ7.js");
4497
+ const { createExtractionRunner } = await import("./dist-OWHMNL4W.js");
4472
4498
  const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
4473
4499
  result = await createExtractionRunner().run(projectPath, store, extractedDir);
4474
4500
  break;
@@ -4504,35 +4530,41 @@ async function runIngest(projectPath, source, opts) {
4504
4530
  await store.save(graphDir);
4505
4531
  return result;
4506
4532
  }
4533
+ function printIngestSummary(result, label) {
4534
+ console.log(
4535
+ `Ingested (${label}): +${result.nodesAdded} nodes, +${result.edgesAdded} edges (${result.durationMs}ms)`
4536
+ );
4537
+ if (result.errors.length === 0) return;
4538
+ console.warn(` ${result.errors.length} parse/skip warning(s):`);
4539
+ for (const err of result.errors) console.warn(` - ${err}`);
4540
+ }
4541
+ async function handleIngestAction(opts, cmd) {
4542
+ if (!opts.source && !opts.all) {
4543
+ console.error("Error: --source or --all is required");
4544
+ process.exit(1);
4545
+ }
4546
+ const globalOpts = cmd.optsWithGlobals();
4547
+ const projectPath = path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
4548
+ try {
4549
+ const runOpts = {};
4550
+ if (opts.full !== void 0) runOpts.full = opts.full;
4551
+ if (opts.all !== void 0) runOpts.all = opts.all;
4552
+ const result = await runIngest(projectPath, opts.source ?? "", runOpts);
4553
+ if (globalOpts.json) {
4554
+ console.log(JSON.stringify(result));
4555
+ } else {
4556
+ printIngestSummary(result, opts.all ? "all" : opts.source ?? "");
4557
+ }
4558
+ } catch (err) {
4559
+ console.error("Ingest failed:", err instanceof Error ? err.message : err);
4560
+ process.exit(2);
4561
+ }
4562
+ }
4507
4563
  function createIngestCommand() {
4508
4564
  return new Command34("ingest").description("Ingest data into the knowledge graph").option(
4509
4565
  "--source <name>",
4510
4566
  "Source to ingest (code, knowledge, git, requirements, business-signals, jira, slack, ci, confluence, figma, miro)"
4511
- ).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(async (opts, cmd) => {
4512
- if (!opts.source && !opts.all) {
4513
- console.error("Error: --source or --all is required");
4514
- process.exit(1);
4515
- }
4516
- const globalOpts = cmd.optsWithGlobals();
4517
- const projectPath = path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
4518
- try {
4519
- const result = await runIngest(projectPath, opts.source ?? "", {
4520
- full: opts.full,
4521
- all: opts.all
4522
- });
4523
- if (globalOpts.json) {
4524
- console.log(JSON.stringify(result));
4525
- } else {
4526
- const label = opts.all ? "all" : opts.source;
4527
- console.log(
4528
- `Ingested (${label}): +${result.nodesAdded} nodes, +${result.edgesAdded} edges (${result.durationMs}ms)`
4529
- );
4530
- }
4531
- } catch (err) {
4532
- console.error("Ingest failed:", err instanceof Error ? err.message : err);
4533
- process.exit(2);
4534
- }
4535
- });
4567
+ ).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(handleIngestAction);
4536
4568
  }
4537
4569
 
4538
4570
  // src/commands/graph/index.ts
@@ -5356,6 +5388,7 @@ var ALL_MCP_TOOLS = [
5356
5388
  "run_design_pipeline",
5357
5389
  // craft-pipeline #1 — naming-craft LLM-judgment ceiling skill
5358
5390
  "naming_craft",
5391
+ "naming_craft_finalize",
5359
5392
  // craft-pipeline #6 — spec-craft LLM-judgment ceiling skill
5360
5393
  "spec_craft",
5361
5394
  // craft-pipeline #5 — copy-craft LLM-judgment ceiling skill (6 surfaces)
@@ -5365,7 +5398,19 @@ var ALL_MCP_TOOLS = [
5365
5398
  // craft-pipeline #9 — knowledge-craft LLM-judgment ceiling skill (docs/knowledge/ entries)
5366
5399
  "knowledge_craft",
5367
5400
  // craft-pipeline #10 — security-craft LLM-judgment ceiling skill (AST-driven, conservative-confidence)
5368
- "security_craft"
5401
+ "security_craft",
5402
+ // strategic-anchor — STRATEGY.md read/validate/write so projects can call
5403
+ // these via MCP without needing @harness-engineering/core in node_modules
5404
+ "validate_strategy",
5405
+ "read_strategy",
5406
+ "write_strategy",
5407
+ // strategic-anchor — pulse config writer + STRATEGY.md seed extractor
5408
+ "write_pulse_config",
5409
+ "seed_pulse_from_strategy",
5410
+ // strategic-anchor — compound lock acquire/release (server holds the handle;
5411
+ // skill threads a token between calls)
5412
+ "acquire_compound_lock",
5413
+ "release_compound_lock"
5369
5414
  ];
5370
5415
  async function runCursorToolPicker() {
5371
5416
  try {
@@ -5738,12 +5783,10 @@ function renderPretty(report) {
5738
5783
  }
5739
5784
  }
5740
5785
  function createInsightsCommand() {
5741
- return new Command44("insights").description(
5742
- "Composite project report \u2014 health, entropy, decay, attention, impact (Hermes Phase 1)."
5743
- ).option("--json", "Emit JSON to stdout instead of pretty text").option("--skip <list>", `Comma-separated keys to skip (${INSIGHTS_KEYS.join(",")})`).action(async (opts) => {
5786
+ return new Command44("insights").description("Composite project report \u2014 health, entropy, decay, attention, impact.").option("--json", "Emit JSON to stdout instead of pretty text").option("--skip <list>", `Comma-separated keys to skip (${INSIGHTS_KEYS.join(",")})`).action(async (opts) => {
5744
5787
  const cwd = process.cwd();
5745
5788
  const skip = parseSkip2(opts.skip);
5746
- const { composeInsights } = await import("./dist-XIJWWQ5N.js");
5789
+ const { composeInsights } = await import("./dist-JCFK263L.js");
5747
5790
  const report = await composeInsights(cwd, { skip });
5748
5791
  if (opts.json) {
5749
5792
  console.log(JSON.stringify(report, null, 2));
@@ -6915,10 +6958,10 @@ function printResult3(result, mode, _formatter) {
6915
6958
  list.push(f);
6916
6959
  byFile.set(f.target.file, list);
6917
6960
  }
6918
- for (const [file, fs47] of byFile) {
6961
+ for (const [file, fs48] of byFile) {
6919
6962
  console.log(`
6920
6963
  ${file}`);
6921
- for (const f of fs47) {
6964
+ for (const f of fs48) {
6922
6965
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.relative}`);
6923
6966
  console.log(` ${f.message}`);
6924
6967
  if (verbose) console.log(` source: ${f.cite.source}`);
@@ -6941,9 +6984,9 @@ function createKnowledgePipelineCommand() {
6941
6984
  const projectDir = process.cwd();
6942
6985
  try {
6943
6986
  const graphDir = path39.join(projectDir, ".harness", "graph");
6944
- const fs47 = await import("fs/promises");
6945
- await fs47.mkdir(graphDir, { recursive: true });
6946
- const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-R3TOOPJ7.js");
6987
+ const fs48 = await import("fs/promises");
6988
+ await fs48.mkdir(graphDir, { recursive: true });
6989
+ const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-OWHMNL4W.js");
6947
6990
  const store = new GraphStore2();
6948
6991
  try {
6949
6992
  await store.load(graphDir);
@@ -6999,6 +7042,7 @@ function createKnowledgePipelineCommand() {
6999
7042
  iterations: result.iterations,
7000
7043
  findings: result.findings,
7001
7044
  extraction: result.extraction,
7045
+ errors: result.errors,
7002
7046
  gaps: {
7003
7047
  domains: result.gaps.domains.length,
7004
7048
  totalEntries: result.gaps.totalEntries,
@@ -7039,7 +7083,7 @@ function createKnowledgePipelineCommand() {
7039
7083
  ` Findings: ${result.findings.new} new, ${result.findings.stale} stale, ${result.findings.drifted} drifted, ${result.findings.contradicting} contradicting`
7040
7084
  );
7041
7085
  console.log(
7042
- ` Extraction: ${result.extraction.codeSignals} code signals, ${result.extraction.diagrams} diagrams, ${result.extraction.linkerFacts} linker facts, ${result.extraction.businessKnowledge} business knowledge, ${result.extraction.images} images`
7086
+ ` Extraction: ${result.extraction.codeSignals} code signals, ${result.extraction.diagrams} diagrams, ${result.extraction.linkerFacts} linker facts, ${result.extraction.businessKnowledge} business knowledge, ${result.extraction.decisions} decisions, ${result.extraction.images} images`
7043
7087
  );
7044
7088
  console.log(
7045
7089
  ` Gaps: ${result.gaps.domains.length} domains \u2014 ${result.gaps.totalEntries} documented / ${result.gaps.totalExtracted} extracted / ${result.gaps.totalGaps} undocumented`
@@ -7050,6 +7094,13 @@ function createKnowledgePipelineCommand() {
7050
7094
  if (result.remediations.length > 0) {
7051
7095
  console.log(` Remediations: ${result.remediations.length} applied`);
7052
7096
  }
7097
+ if (result.errors.length > 0) {
7098
+ console.warn("");
7099
+ console.warn(` ${result.errors.length} ingestion warning(s):`);
7100
+ for (const err of result.errors) {
7101
+ console.warn(` - ${err}`);
7102
+ }
7103
+ }
7053
7104
  if (result.materialization) {
7054
7105
  const mat = result.materialization;
7055
7106
  console.log(
@@ -7351,7 +7402,7 @@ function printListTable(rows) {
7351
7402
  }
7352
7403
  function createMaintenanceCommand() {
7353
7404
  const command = new Command59("maintenance").description(
7354
- "Hermes Phase 2 \u2014 inspect built-in + custom maintenance tasks and their persisted outputs"
7405
+ "Inspect built-in + custom maintenance tasks and their persisted outputs"
7355
7406
  );
7356
7407
  command.command("list").description("List all resolved maintenance tasks (built-in + customTasks)").option("--json", "Emit machine-readable JSON", false).option("--path <path>", "Project root path", ".").action(async (opts) => {
7357
7408
  const cwd = path41.resolve(opts.path);
@@ -7445,7 +7496,7 @@ function createMcpCommand() {
7445
7496
  parseBudget
7446
7497
  ).action(async (opts) => {
7447
7498
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
7448
- import("./mcp-NEAPIDTT.js"),
7499
+ import("./mcp-JBIBINO2.js"),
7449
7500
  import("./tool-tiers-B7JC2XC3.js")
7450
7501
  ]);
7451
7502
  if (opts.tools && opts.tools.length > 0) {
@@ -7606,14 +7657,150 @@ function createMcpGuardCommand() {
7606
7657
  }
7607
7658
 
7608
7659
  // src/commands/migrate.ts
7609
- init_dist3();
7610
- init_dist2();
7660
+ import { Command as Command63 } from "commander";
7661
+
7662
+ // src/commands/migrate-backends.ts
7611
7663
  import { Command as Command62 } from "commander";
7612
7664
  import * as fs27 from "fs";
7613
7665
  import * as path43 from "path";
7666
+ import chalk9 from "chalk";
7667
+ import { parse as parseYaml2 } from "yaml";
7668
+ async function runMigrateBackends(opts = {}) {
7669
+ const cwd = opts.cwd ?? process.cwd();
7670
+ const mdPath = findOrchestratorMd(cwd);
7671
+ if (mdPath === null) {
7672
+ return {
7673
+ status: "noop",
7674
+ message: "No harness.orchestrator.md found \u2014 nothing to migrate.",
7675
+ exitCode: ExitCode.SUCCESS
7676
+ };
7677
+ }
7678
+ const backends = readBackendsFromOrchestratorMd(cwd);
7679
+ if (backends === null) {
7680
+ return {
7681
+ status: "noop",
7682
+ message: `Found ${mdPath} but no agent.backends to migrate.`,
7683
+ exitCode: ExitCode.SUCCESS
7684
+ };
7685
+ }
7686
+ const routing = readRoutingFromOrchestratorMd(mdPath);
7687
+ const jsonPath = path43.join(path43.dirname(mdPath), "harness.config.json");
7688
+ if (!fs27.existsSync(jsonPath)) {
7689
+ return {
7690
+ status: "error",
7691
+ message: `harness.config.json not found at ${jsonPath}. Run \`harness init\` first, then re-run this migration.`,
7692
+ exitCode: ExitCode.ERROR
7693
+ };
7694
+ }
7695
+ let configRaw;
7696
+ try {
7697
+ configRaw = fs27.readFileSync(jsonPath, "utf-8");
7698
+ } catch (err) {
7699
+ return {
7700
+ status: "error",
7701
+ message: `Failed to read ${jsonPath}: ${err instanceof Error ? err.message : String(err)}`,
7702
+ exitCode: ExitCode.ERROR
7703
+ };
7704
+ }
7705
+ let configObj;
7706
+ try {
7707
+ configObj = JSON.parse(configRaw);
7708
+ } catch (err) {
7709
+ return {
7710
+ status: "error",
7711
+ message: `${jsonPath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
7712
+ exitCode: ExitCode.ERROR
7713
+ };
7714
+ }
7715
+ const agent = configObj.agent ?? {};
7716
+ const existingBackends = agent.backends;
7717
+ if (existingBackends !== void 0 && !opts.force) {
7718
+ return {
7719
+ status: "error",
7720
+ message: `${jsonPath} already declares agent.backends. Re-run with --force to overwrite, or merge manually.`,
7721
+ exitCode: ExitCode.ERROR
7722
+ };
7723
+ }
7724
+ const nextAgent = { ...agent, backends };
7725
+ if (routing !== null) nextAgent.routing = routing;
7726
+ const nextConfig = { ...configObj, agent: nextAgent };
7727
+ const nextJson = JSON.stringify(nextConfig, null, 2) + "\n";
7728
+ if (opts.dryRun) {
7729
+ logger.info(chalk9.bold("--- dry run ---"));
7730
+ logger.info(`Would write ${Object.keys(backends).length} backend(s) to ${jsonPath}:`);
7731
+ for (const name of Object.keys(backends)) {
7732
+ logger.info(` \u2022 ${name}`);
7733
+ }
7734
+ if (routing !== null) {
7735
+ logger.info("Would also copy agent.routing.");
7736
+ }
7737
+ return {
7738
+ status: "ok",
7739
+ message: "(dry-run) migration plan above \u2014 re-run without --dry-run to apply.",
7740
+ exitCode: ExitCode.SUCCESS
7741
+ };
7742
+ }
7743
+ try {
7744
+ fs27.writeFileSync(jsonPath, nextJson);
7745
+ } catch (err) {
7746
+ return {
7747
+ status: "error",
7748
+ message: `Failed to write ${jsonPath}: ${err instanceof Error ? err.message : String(err)}`,
7749
+ exitCode: ExitCode.ERROR
7750
+ };
7751
+ }
7752
+ return {
7753
+ status: "ok",
7754
+ message: `Migrated ${Object.keys(backends).length} backend(s)${routing !== null ? " + routing" : ""} from ${mdPath} to ${jsonPath}. You can leave the entries in harness.orchestrator.md (orchestrator still reads them) or remove them once the orchestrator config picks up the JSON source.`,
7755
+ exitCode: ExitCode.SUCCESS
7756
+ };
7757
+ }
7758
+ function readRoutingFromOrchestratorMd(mdPath) {
7759
+ let raw;
7760
+ try {
7761
+ raw = fs27.readFileSync(mdPath, "utf-8");
7762
+ } catch {
7763
+ return null;
7764
+ }
7765
+ const parts = raw.split("---");
7766
+ if (parts.length < 3) return null;
7767
+ let parsed;
7768
+ try {
7769
+ parsed = parseYaml2(parts[1].trim());
7770
+ } catch {
7771
+ return null;
7772
+ }
7773
+ if (parsed === null || typeof parsed !== "object") return null;
7774
+ const agent = parsed.agent;
7775
+ if (agent === null || typeof agent !== "object") return null;
7776
+ const routing = agent.routing;
7777
+ return routing ?? null;
7778
+ }
7779
+ function createBackendsSubcommand() {
7780
+ return new Command62("backends").description(
7781
+ "Copy agent.backends (and routing) from harness.orchestrator.md into harness.config.json."
7782
+ ).option("--dry-run", "Show what would change without writing", false).option("--force", "Overwrite existing agent.backends in harness.config.json", false).action(async (options) => {
7783
+ const result = await runMigrateBackends({
7784
+ dryRun: options.dryRun ?? false,
7785
+ force: options.force ?? false
7786
+ });
7787
+ if (result.status === "error") {
7788
+ logger.error(result.message);
7789
+ process.exit(result.exitCode);
7790
+ }
7791
+ logger.info(result.message);
7792
+ process.exit(result.exitCode);
7793
+ });
7794
+ }
7795
+
7796
+ // src/commands/migrate.ts
7797
+ init_dist3();
7798
+ init_dist2();
7799
+ import * as fs28 from "fs";
7800
+ import * as path44 from "path";
7614
7801
  import * as readline from "readline";
7615
7802
  import { execFileSync as execFileSync4 } from "child_process";
7616
- import chalk9 from "chalk";
7803
+ import chalk10 from "chalk";
7617
7804
  function isGitRepo(cwd) {
7618
7805
  try {
7619
7806
  execFileSync4("git", ["rev-parse", "--is-inside-work-tree"], { cwd, stdio: "pipe" });
@@ -7624,25 +7811,25 @@ function isGitRepo(cwd) {
7624
7811
  }
7625
7812
  function readJson2(p) {
7626
7813
  try {
7627
- return JSON.parse(fs27.readFileSync(p, "utf8"));
7814
+ return JSON.parse(fs28.readFileSync(p, "utf8"));
7628
7815
  } catch {
7629
7816
  return null;
7630
7817
  }
7631
7818
  }
7632
7819
  function listDirs(p) {
7633
- if (!fs27.existsSync(p)) return [];
7634
- return fs27.readdirSync(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
7820
+ if (!fs28.existsSync(p)) return [];
7821
+ return fs28.readdirSync(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
7635
7822
  }
7636
7823
  function listFiles(p, predicate) {
7637
- if (!fs27.existsSync(p)) return [];
7638
- return fs27.readdirSync(p, { withFileTypes: true }).filter((e) => e.isFile() && predicate(e.name)).map((e) => e.name);
7824
+ if (!fs28.existsSync(p)) return [];
7825
+ return fs28.readdirSync(p, { withFileTypes: true }).filter((e) => e.isFile() && predicate(e.name)).map((e) => e.name);
7639
7826
  }
7640
7827
  function walk(dir, predicate) {
7641
- if (!fs27.existsSync(dir)) return [];
7828
+ if (!fs28.existsSync(dir)) return [];
7642
7829
  const out = [];
7643
- for (const entry of fs27.readdirSync(dir, { withFileTypes: true })) {
7830
+ for (const entry of fs28.readdirSync(dir, { withFileTypes: true })) {
7644
7831
  if (DEFAULT_SKIP_DIRS.has(entry.name)) continue;
7645
- const full = path43.join(dir, entry.name);
7832
+ const full = path44.join(dir, entry.name);
7646
7833
  if (entry.isDirectory()) out.push(...walk(full, predicate));
7647
7834
  else if (predicate(full)) out.push(full);
7648
7835
  }
@@ -7654,11 +7841,11 @@ function extractAutopilotTopic(state) {
7654
7841
  }
7655
7842
  function buildAutopilotMap(cwd) {
7656
7843
  const map = /* @__PURE__ */ new Map();
7657
- const sessionsDir = path43.join(cwd, ".harness", "sessions");
7658
- if (!fs27.existsSync(sessionsDir)) return map;
7844
+ const sessionsDir = path44.join(cwd, ".harness", "sessions");
7845
+ if (!fs28.existsSync(sessionsDir)) return map;
7659
7846
  for (const session of listDirs(sessionsDir)) {
7660
7847
  if (!session.startsWith("changes--")) continue;
7661
- const state = readJson2(path43.join(sessionsDir, session, "autopilot-state.json"));
7848
+ const state = readJson2(path44.join(sessionsDir, session, "autopilot-state.json"));
7662
7849
  if (!state) continue;
7663
7850
  const topic = extractAutopilotTopic(state);
7664
7851
  if (!topic) continue;
@@ -7671,7 +7858,7 @@ function buildAutopilotMap(cwd) {
7671
7858
  function extractTopicFromHeader(planAbs, proposalTopics) {
7672
7859
  let text;
7673
7860
  try {
7674
- text = fs27.readFileSync(planAbs, "utf8").slice(0, 4e3);
7861
+ text = fs28.readFileSync(planAbs, "utf8").slice(0, 4e3);
7675
7862
  } catch {
7676
7863
  return null;
7677
7864
  }
@@ -7696,8 +7883,8 @@ function extractTopicFromFilename(filename, proposalTopics) {
7696
7883
  return best;
7697
7884
  }
7698
7885
  function resolveDocsDir(cwd) {
7699
- const configPath = path43.join(cwd, "harness.config.json");
7700
- const configResult = fs27.existsSync(configPath) ? resolveConfig(configPath) : null;
7886
+ const configPath = path44.join(cwd, "harness.config.json");
7887
+ const configResult = fs28.existsSync(configPath) ? resolveConfig(configPath) : null;
7701
7888
  let docsDir;
7702
7889
  if (configResult?.ok) {
7703
7890
  docsDir = configResult.value.docsDir;
@@ -7709,16 +7896,16 @@ function resolveDocsDir(cwd) {
7709
7896
  } else {
7710
7897
  docsDir = "./docs";
7711
7898
  }
7712
- const docsAbs = path43.resolve(cwd, docsDir);
7713
- const relRaw = path43.relative(cwd, docsAbs).replaceAll("\\", "/");
7899
+ const docsAbs = path44.resolve(cwd, docsDir);
7900
+ const relRaw = path44.relative(cwd, docsAbs).replaceAll("\\", "/");
7714
7901
  return relRaw === "" ? "docs" : relRaw;
7715
7902
  }
7716
7903
  function collectAdrMoves(cwd, docsRel) {
7717
7904
  const moves = [];
7718
- const legacyAdrDir = path43.join(cwd, ".harness", "architecture");
7719
- if (!fs27.existsSync(legacyAdrDir)) return moves;
7905
+ const legacyAdrDir = path44.join(cwd, ".harness", "architecture");
7906
+ if (!fs28.existsSync(legacyAdrDir)) return moves;
7720
7907
  for (const topic of listDirs(legacyAdrDir)) {
7721
- const topicSrc = path43.join(legacyAdrDir, topic);
7908
+ const topicSrc = path44.join(legacyAdrDir, topic);
7722
7909
  for (const file of listFiles(topicSrc, (n) => n.endsWith(".md"))) {
7723
7910
  moves.push({
7724
7911
  src: `.harness/architecture/${topic}/${file}`,
@@ -7730,9 +7917,9 @@ function collectAdrMoves(cwd, docsRel) {
7730
7917
  }
7731
7918
  function collectProposalTopics(cwd) {
7732
7919
  const topics = /* @__PURE__ */ new Set();
7733
- const changesDir = path43.join(cwd, "docs", "changes");
7920
+ const changesDir = path44.join(cwd, "docs", "changes");
7734
7921
  for (const topic of listDirs(changesDir)) {
7735
- if (fs27.existsSync(path43.join(changesDir, topic, "proposal.md"))) {
7922
+ if (fs28.existsSync(path44.join(changesDir, topic, "proposal.md"))) {
7736
7923
  topics.add(topic);
7737
7924
  }
7738
7925
  }
@@ -7759,12 +7946,12 @@ async function buildPlan(opts) {
7759
7946
  orphanPlans: [],
7760
7947
  proposalTopics: collectProposalTopics(cwd)
7761
7948
  };
7762
- const legacyPlanDir = path43.join(cwd, "docs", "plans");
7763
- if (!fs27.existsSync(legacyPlanDir)) return plan;
7949
+ const legacyPlanDir = path44.join(cwd, "docs", "plans");
7950
+ if (!fs28.existsSync(legacyPlanDir)) return plan;
7764
7951
  const autopilotMap = buildAutopilotMap(cwd);
7765
7952
  for (const file of listFiles(legacyPlanDir, (n) => n.endsWith(".md") && n !== "index.md")) {
7766
7953
  const planRel = `docs/plans/${file}`;
7767
- const planAbs = path43.join(legacyPlanDir, file);
7954
+ const planAbs = path44.join(legacyPlanDir, file);
7768
7955
  const subdir = file.includes("VERIFICATION") ? "verifications" : "plans";
7769
7956
  const classified = classifyPlan(planRel, planAbs, file, autopilotMap, plan.proposalTopics);
7770
7957
  if (classified) {
@@ -7782,8 +7969,8 @@ async function buildPlan(opts) {
7782
7969
  return plan;
7783
7970
  }
7784
7971
  function gitMv(cwd, src, dest, useGit) {
7785
- const destAbs = path43.join(cwd, dest);
7786
- fs27.mkdirSync(path43.dirname(destAbs), { recursive: true });
7972
+ const destAbs = path44.join(cwd, dest);
7973
+ fs28.mkdirSync(path44.dirname(destAbs), { recursive: true });
7787
7974
  if (useGit) {
7788
7975
  try {
7789
7976
  execFileSync4("git", ["mv", src, dest], { cwd, stdio: "pipe" });
@@ -7791,7 +7978,7 @@ function gitMv(cwd, src, dest, useGit) {
7791
7978
  } catch {
7792
7979
  }
7793
7980
  }
7794
- fs27.renameSync(path43.join(cwd, src), destAbs);
7981
+ fs28.renameSync(path44.join(cwd, src), destAbs);
7795
7982
  }
7796
7983
  function executeMigration(plan) {
7797
7984
  let moved = 0;
@@ -7823,13 +8010,13 @@ function updateReferences(plan) {
7823
8010
  let files = 0;
7824
8011
  let replacements = 0;
7825
8012
  const targets = [
7826
- ...walk(path43.join(plan.cwd, "docs"), (p) => p.endsWith(".md")),
7827
- ...walk(path43.join(plan.cwd, ".harness", "sessions"), (p) => p.endsWith(".json"))
8013
+ ...walk(path44.join(plan.cwd, "docs"), (p) => p.endsWith(".md")),
8014
+ ...walk(path44.join(plan.cwd, ".harness", "sessions"), (p) => p.endsWith(".json"))
7828
8015
  ];
7829
8016
  for (const target of targets) {
7830
8017
  let text;
7831
8018
  try {
7832
- text = fs27.readFileSync(target, "utf8");
8019
+ text = fs28.readFileSync(target, "utf8");
7833
8020
  } catch {
7834
8021
  continue;
7835
8022
  }
@@ -7842,7 +8029,7 @@ function updateReferences(plan) {
7842
8029
  count += occurrences;
7843
8030
  }
7844
8031
  if (count > 0 && result !== text) {
7845
- fs27.writeFileSync(target, result);
8032
+ fs28.writeFileSync(target, result);
7846
8033
  files++;
7847
8034
  replacements += count;
7848
8035
  }
@@ -7901,7 +8088,7 @@ async function resolveOrphans(plan, opts) {
7901
8088
  }
7902
8089
  function bucketOrphans(plan, topic) {
7903
8090
  for (const src of plan.orphanPlans) {
7904
- const file = path43.basename(src);
8091
+ const file = path44.basename(src);
7905
8092
  const isVerification = file.includes("VERIFICATION");
7906
8093
  const subdir = isVerification ? "verifications" : "plans";
7907
8094
  plan.planMoves.push({
@@ -7916,7 +8103,7 @@ function bucketOrphans(plan, topic) {
7916
8103
  }
7917
8104
  function summarize(plan) {
7918
8105
  console.log("");
7919
- console.log(chalk9.bold(" Migration plan"));
8106
+ console.log(chalk10.bold(" Migration plan"));
7920
8107
  console.log("");
7921
8108
  if (plan.adrMoves.length === 0 && plan.planMoves.length === 0 && plan.orphanPlans.length === 0) {
7922
8109
  logger.success(" Nothing to migrate. Layout is already up to date.");
@@ -7935,7 +8122,7 @@ function summarize(plan) {
7935
8122
  logger.info(
7936
8123
  ` Plan moves: ${plan.planMoves.length} file(s) \u2014 docs/plans/ \u2192 docs/changes/<topic>/{plans,verifications}/`
7937
8124
  );
7938
- for (const [via, n] of Object.entries(byVia)) console.log(chalk9.dim(` via ${via}: ${n}`));
8125
+ for (const [via, n] of Object.entries(byVia)) console.log(chalk10.dim(` via ${via}: ${n}`));
7939
8126
  }
7940
8127
  if (plan.orphanPlans.length > 0) {
7941
8128
  logger.warn(` Orphan plans: ${plan.orphanPlans.length} (no proposal match \u2014 needs decision)`);
@@ -7943,10 +8130,10 @@ function summarize(plan) {
7943
8130
  console.log("");
7944
8131
  }
7945
8132
  async function detectLegacyArtifacts(cwd) {
7946
- const adrLegacyDir = path43.join(cwd, ".harness", "architecture");
7947
- const adrLegacy = fs27.existsSync(adrLegacyDir) && listDirs(adrLegacyDir).length > 0;
7948
- const planLegacyDir = path43.join(cwd, "docs", "plans");
7949
- const planLegacy = fs27.existsSync(planLegacyDir) && listFiles(planLegacyDir, (n) => n.endsWith(".md") && n !== "index.md").length > 0;
8133
+ const adrLegacyDir = path44.join(cwd, ".harness", "architecture");
8134
+ const adrLegacy = fs28.existsSync(adrLegacyDir) && listDirs(adrLegacyDir).length > 0;
8135
+ const planLegacyDir = path44.join(cwd, "docs", "plans");
8136
+ const planLegacy = fs28.existsSync(planLegacyDir) && listFiles(planLegacyDir, (n) => n.endsWith(".md") && n !== "index.md").length > 0;
7950
8137
  return { adrLegacy, planLegacy };
7951
8138
  }
7952
8139
  async function confirmApply(opts) {
@@ -8014,7 +8201,7 @@ async function runMigrate(opts) {
8014
8201
  });
8015
8202
  }
8016
8203
  function createMigrateCommand() {
8017
- return new Command62("migrate").description("Migrate legacy harness artifact locations to current layout").option("--dry-run", "Show the migration plan without moving files", false).option("--yes", "Skip confirmation prompt", false).option(
8204
+ const cmd = new Command63("migrate").description("Migrate legacy harness artifact locations to current layout").option("--dry-run", "Show the migration plan without moving files", false).option("--yes", "Skip confirmation prompt", false).option(
8018
8205
  "--skip-references",
8019
8206
  "Do not update path references in docs/sessions after moves",
8020
8207
  false
@@ -8033,12 +8220,158 @@ function createMigrateCommand() {
8033
8220
  }
8034
8221
  process.exit(result.value.movesFailed === 0 ? ExitCode.SUCCESS : ExitCode.ERROR);
8035
8222
  });
8223
+ cmd.addCommand(createBackendsSubcommand());
8224
+ return cmd;
8225
+ }
8226
+
8227
+ // src/commands/models.ts
8228
+ import { Command as Command64 } from "commander";
8229
+ import { defaultFetchModels } from "@harness-engineering/orchestrator";
8230
+ function errorResult(message, partial) {
8231
+ return {
8232
+ status: "error",
8233
+ endpoint: "",
8234
+ configured: [],
8235
+ detected: [],
8236
+ resolved: null,
8237
+ error: message,
8238
+ exitCode: ExitCode.ERROR,
8239
+ ...partial
8240
+ };
8241
+ }
8242
+ function pickConfiguredList(model) {
8243
+ if (typeof model === "string") return [model];
8244
+ if (Array.isArray(model)) return model.filter((m) => typeof m === "string");
8245
+ return [];
8246
+ }
8247
+ function locateBackend(opts) {
8248
+ const resolved = resolveConfig(opts.configPath);
8249
+ if (!resolved.ok) {
8250
+ return errorResult(`Could not load harness.config.json: ${resolved.error.message}`);
8251
+ }
8252
+ const backends = resolved.value.agent?.backends;
8253
+ const name = opts.backend ?? defaultLocalBackend(backends);
8254
+ if (name === null) {
8255
+ return errorResult(
8256
+ 'No local backend in agent.backends. Declare one with type "local" or "pi", or pass --endpoint <url>.'
8257
+ );
8258
+ }
8259
+ const def = backends?.[name];
8260
+ if (def === void 0) {
8261
+ return errorResult(`agent.backends["${name}"] not found.`);
8262
+ }
8263
+ return { name, def };
8264
+ }
8265
+ function resolveProbeContext(opts) {
8266
+ if (opts.endpoint !== void 0) {
8267
+ return {
8268
+ endpoint: opts.endpoint,
8269
+ configured: [],
8270
+ apiKey: opts.apiKey ?? "local",
8271
+ backendLabel: opts.backend
8272
+ };
8273
+ }
8274
+ const located = locateBackend(opts);
8275
+ if ("status" in located) return located;
8276
+ const ep = located.def.endpoint;
8277
+ if (typeof ep !== "string") {
8278
+ return errorResult(`agent.backends["${located.name}"]: missing or invalid 'endpoint'.`);
8279
+ }
8280
+ const explicitKey = typeof located.def.apiKey === "string" ? located.def.apiKey : void 0;
8281
+ return {
8282
+ endpoint: ep,
8283
+ configured: pickConfiguredList(located.def.model),
8284
+ apiKey: opts.apiKey ?? explicitKey ?? "local",
8285
+ backendLabel: located.name
8286
+ };
8287
+ }
8288
+ async function runModelsProbe(opts) {
8289
+ const ctx = resolveProbeContext(opts);
8290
+ if ("status" in ctx) return ctx;
8291
+ let detected;
8292
+ try {
8293
+ detected = await defaultFetchModels(ctx.endpoint, ctx.apiKey);
8294
+ } catch (err) {
8295
+ return {
8296
+ status: "error",
8297
+ ...ctx.backendLabel !== void 0 ? { backend: ctx.backendLabel } : {},
8298
+ endpoint: ctx.endpoint,
8299
+ configured: ctx.configured,
8300
+ detected: [],
8301
+ resolved: null,
8302
+ error: err instanceof Error ? err.message : String(err),
8303
+ exitCode: ExitCode.ERROR
8304
+ };
8305
+ }
8306
+ const match = ctx.configured.find((id) => detected.includes(id)) ?? null;
8307
+ return {
8308
+ status: match !== null ? "ok" : "no-match",
8309
+ ...ctx.backendLabel !== void 0 ? { backend: ctx.backendLabel } : {},
8310
+ endpoint: ctx.endpoint,
8311
+ configured: ctx.configured,
8312
+ detected,
8313
+ resolved: match,
8314
+ exitCode: match !== null ? ExitCode.SUCCESS : ExitCode.ERROR
8315
+ };
8316
+ }
8317
+ function defaultLocalBackend(backends) {
8318
+ if (backends === void 0) return null;
8319
+ for (const [name, def] of Object.entries(backends)) {
8320
+ const t = def.type;
8321
+ if (t === "local" || t === "pi") return name;
8322
+ }
8323
+ return null;
8324
+ }
8325
+ function formatProbe(result) {
8326
+ if (result.status === "error") {
8327
+ return `error probing ${result.endpoint || "(no endpoint)"}: ${result.error}`;
8328
+ }
8329
+ const lines = [];
8330
+ lines.push(
8331
+ `endpoint: ${result.endpoint}${result.backend !== void 0 ? ` (agent.backends["${result.backend}"])` : ""}`
8332
+ );
8333
+ lines.push(`configured: [${result.configured.join(", ")}]`);
8334
+ lines.push(`detected: [${result.detected.join(", ")}]`);
8335
+ if (result.resolved !== null) {
8336
+ lines.push(`resolved: ${result.resolved}`);
8337
+ } else {
8338
+ lines.push("resolved: (no configured model is loaded)");
8339
+ lines.push(
8340
+ "hint: load one of the configured models or update agent.backends.<name>.model to include a detected id."
8341
+ );
8342
+ }
8343
+ return lines.join("\n");
8344
+ }
8345
+ function createModelsCommand() {
8346
+ const cmd = new Command64("models").description(
8347
+ "Inspect and manage local LLM backends. Currently ships `probe`; LMLM phases add status/suggest/pool/proposals."
8348
+ );
8349
+ cmd.command("probe").description(
8350
+ "Probe a local backend's /v1/models endpoint and report which configured model is loaded."
8351
+ ).option(
8352
+ "--backend <name>",
8353
+ "Name of an entry in agent.backends. Defaults to the first local/pi entry."
8354
+ ).option("--endpoint <url>", "Override the backend endpoint (bypasses harness.config.json).").option("--api-key <key>", "Override the API key.").option("--json", "Print machine-readable JSON instead of a human summary.", false).action(async (options) => {
8355
+ const result = await runModelsProbe(options);
8356
+ if (options.json) {
8357
+ console.log(JSON.stringify(result, null, 2));
8358
+ } else {
8359
+ const text = formatProbe(result);
8360
+ if (result.status === "error" || result.status === "no-match") {
8361
+ logger.error(text);
8362
+ } else {
8363
+ logger.info(text);
8364
+ }
8365
+ }
8366
+ process.exit(result.exitCode);
8367
+ });
8368
+ return cmd;
8036
8369
  }
8037
8370
 
8038
8371
  // src/commands/naming-craft.ts
8039
- import { Command as Command63 } from "commander";
8372
+ import { Command as Command65 } from "commander";
8040
8373
  function createNamingCraftCommand() {
8041
- return new Command63("naming-craft").description(
8374
+ return new Command65("naming-craft").description(
8042
8375
  "LLM-judgment critique of identifier names (variables, functions, types, files). First craft-pipeline ceiling skill; uses curated rubric catalog from Martin/Beck/Karlton."
8043
8376
  ).option("-f, --files <files...>", "Optional file/glob scope").option(
8044
8377
  "-k, --kinds <kinds...>",
@@ -8088,10 +8421,10 @@ function printResult4(result, mode, _formatter) {
8088
8421
  list.push(f);
8089
8422
  byFile.set(f.target.file, list);
8090
8423
  }
8091
- for (const [file, fs47] of byFile) {
8424
+ for (const [file, fs48] of byFile) {
8092
8425
  console.log(`
8093
8426
  ${file}`);
8094
- for (const f of fs47) {
8427
+ for (const f of fs48) {
8095
8428
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
8096
8429
  console.log(
8097
8430
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.kind} ${f.target.identifier}${line}`
@@ -8111,11 +8444,11 @@ ${file}`);
8111
8444
  }
8112
8445
 
8113
8446
  // src/commands/notifications/index.ts
8114
- import { Command as Command65 } from "commander";
8447
+ import { Command as Command67 } from "commander";
8115
8448
 
8116
8449
  // src/commands/notifications/test.ts
8117
8450
  init_dist3();
8118
- import { Command as Command64 } from "commander";
8451
+ import { Command as Command66 } from "commander";
8119
8452
  import { randomBytes } from "crypto";
8120
8453
  import { resolve as resolve28 } from "path";
8121
8454
  import { SinkRegistry, SinkConfigError, wrapAsEnvelope } from "@harness-engineering/orchestrator";
@@ -8167,7 +8500,7 @@ async function runNotificationsTest(sinkId, opts, projectRoot2 = process.cwd())
8167
8500
  return { ok: false, error: result.error };
8168
8501
  }
8169
8502
  function createNotificationsTestSubcommand() {
8170
- return new Command64("test").description("Send a synthetic notification.test event through the named sink").argument("<sink-id>", "Sink id from harness.config.json `notifications.sinks[].id`").option("--message <text>", "Override the default test message").action(async (sinkId, opts, cmd) => {
8503
+ return new Command66("test").description("Send a synthetic notification.test event through the named sink").argument("<sink-id>", "Sink id from harness.config.json `notifications.sinks[].id`").option("--message <text>", "Override the default test message").action(async (sinkId, opts, cmd) => {
8171
8504
  const globalOpts = cmd.optsWithGlobals();
8172
8505
  const projectRoot2 = typeof globalOpts["cwd"] === "string" ? resolve28(globalOpts["cwd"]) : process.cwd();
8173
8506
  const result = await runNotificationsTest(sinkId, opts, projectRoot2);
@@ -8184,7 +8517,7 @@ function createNotificationsTestSubcommand() {
8184
8517
 
8185
8518
  // src/commands/notifications/index.ts
8186
8519
  function createNotificationsCommand() {
8187
- const cmd = new Command65("notifications").description(
8520
+ const cmd = new Command67("notifications").description(
8188
8521
  "Manage notification sinks (Slack and others)"
8189
8522
  );
8190
8523
  cmd.addCommand(createNotificationsTestSubcommand());
@@ -8192,13 +8525,13 @@ function createNotificationsCommand() {
8192
8525
  }
8193
8526
 
8194
8527
  // src/commands/orchestrator.ts
8195
- import { Command as Command66 } from "commander";
8196
- import * as path44 from "path";
8528
+ import { Command as Command68 } from "commander";
8529
+ import * as path45 from "path";
8197
8530
  import { Orchestrator, WorkflowLoader as WorkflowLoader2, launchTUI } from "@harness-engineering/orchestrator";
8198
8531
  function createOrchestratorCommand() {
8199
- const orchestrator = new Command66("orchestrator");
8532
+ const orchestrator = new Command68("orchestrator");
8200
8533
  orchestrator.command("run").description("Run the orchestrator daemon").option("-w, --workflow <path>", "Path to harness.orchestrator.md", "harness.orchestrator.md").option("--headless", "Run without TUI (server-only mode for use with web dashboard)").action(async (opts) => {
8201
- const workflowPath = path44.resolve(process.cwd(), opts.workflow);
8534
+ const workflowPath = path45.resolve(process.cwd(), opts.workflow);
8202
8535
  const loader = new WorkflowLoader2();
8203
8536
  const result = await loader.loadWorkflow(workflowPath);
8204
8537
  if (!result.ok) {
@@ -8232,13 +8565,13 @@ function createOrchestratorCommand() {
8232
8565
 
8233
8566
  // src/commands/perf.ts
8234
8567
  init_dist3();
8235
- import { Command as Command67 } from "commander";
8236
- import * as path45 from "path";
8568
+ import { Command as Command69 } from "commander";
8569
+ import * as path46 from "path";
8237
8570
  function registerBenchCommand(perf) {
8238
8571
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
8239
8572
  const globalOpts = cmd.optsWithGlobals();
8240
8573
  const cwd = process.cwd();
8241
- const { BenchmarkRunner } = await import("./dist-XIJWWQ5N.js");
8574
+ const { BenchmarkRunner } = await import("./dist-JCFK263L.js");
8242
8575
  const runner = new BenchmarkRunner();
8243
8576
  const benchFiles = runner.discover(cwd, glob2);
8244
8577
  if (benchFiles.length === 0) {
@@ -8302,7 +8635,7 @@ async function runBaselinesShow(globalOpts) {
8302
8635
  }
8303
8636
  async function runBaselinesUpdate(globalOpts) {
8304
8637
  const cwd = process.cwd();
8305
- const { BenchmarkRunner } = await import("./dist-XIJWWQ5N.js");
8638
+ const { BenchmarkRunner } = await import("./dist-JCFK263L.js");
8306
8639
  const runner = new BenchmarkRunner();
8307
8640
  const manager = new BaselineManager(cwd);
8308
8641
  logger.info("Running benchmarks to update baselines...");
@@ -8343,9 +8676,9 @@ function registerReportCommand(perf) {
8343
8676
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
8344
8677
  const globalOpts = cmd.optsWithGlobals();
8345
8678
  const cwd = process.cwd();
8346
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-XIJWWQ5N.js");
8679
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-JCFK263L.js");
8347
8680
  const analyzer = new EntropyAnalyzer2({
8348
- rootDir: path45.resolve(cwd),
8681
+ rootDir: path46.resolve(cwd),
8349
8682
  analyze: { complexity: true, coupling: true }
8350
8683
  });
8351
8684
  const result = await analyzer.analyze();
@@ -8404,7 +8737,7 @@ function registerCriticalPathsCommand(perf) {
8404
8737
  });
8405
8738
  }
8406
8739
  function createPerfCommand() {
8407
- const perf = new Command67("perf").description("Performance benchmark and baseline management");
8740
+ const perf = new Command69("perf").description("Performance benchmark and baseline management");
8408
8741
  registerBenchCommand(perf);
8409
8742
  registerBaselinesCommands(perf);
8410
8743
  registerReportCommand(perf);
@@ -8413,10 +8746,10 @@ function createPerfCommand() {
8413
8746
  }
8414
8747
 
8415
8748
  // src/commands/persona/index.ts
8416
- import { Command as Command70 } from "commander";
8749
+ import { Command as Command72 } from "commander";
8417
8750
 
8418
8751
  // src/commands/persona/list.ts
8419
- import { Command as Command68 } from "commander";
8752
+ import { Command as Command70 } from "commander";
8420
8753
  function printPersonaList(personas) {
8421
8754
  if (personas.length === 0) {
8422
8755
  logger.info("No personas found.");
@@ -8430,7 +8763,7 @@ function printPersonaList(personas) {
8430
8763
  }
8431
8764
  }
8432
8765
  function createListCommand2() {
8433
- return new Command68("list").description("List available agent personas").action(async (_opts, cmd) => {
8766
+ return new Command70("list").description("List available agent personas").action(async (_opts, cmd) => {
8434
8767
  const globalOpts = cmd.optsWithGlobals();
8435
8768
  const personasDir = resolvePersonasDir();
8436
8769
  const result = listPersonas(personasDir);
@@ -8450,51 +8783,51 @@ function createListCommand2() {
8450
8783
  }
8451
8784
 
8452
8785
  // src/commands/persona/generate.ts
8453
- import { Command as Command69 } from "commander";
8454
- import * as fs28 from "fs";
8455
- import * as path46 from "path";
8786
+ import { Command as Command71 } from "commander";
8787
+ import * as fs29 from "fs";
8788
+ import * as path47 from "path";
8456
8789
  function generatePersonaArtifacts(persona, outputDir, only) {
8457
8790
  const slug = toKebabCase(persona.name);
8458
8791
  const generated = [];
8459
8792
  if (!only || only === "runtime") {
8460
8793
  const result = generateRuntime(persona);
8461
8794
  if (result.ok) {
8462
- const outPath = path46.join(outputDir, `${slug}.runtime.json`);
8463
- fs28.mkdirSync(path46.dirname(outPath), { recursive: true });
8464
- fs28.writeFileSync(outPath, result.value);
8795
+ const outPath = path47.join(outputDir, `${slug}.runtime.json`);
8796
+ fs29.mkdirSync(path47.dirname(outPath), { recursive: true });
8797
+ fs29.writeFileSync(outPath, result.value);
8465
8798
  generated.push(outPath);
8466
8799
  }
8467
8800
  }
8468
8801
  if (!only || only === "agents-md") {
8469
8802
  const result = generateAgentsMd(persona);
8470
8803
  if (result.ok) {
8471
- const outPath = path46.join(outputDir, `${slug}.agents.md`);
8472
- fs28.writeFileSync(outPath, result.value);
8804
+ const outPath = path47.join(outputDir, `${slug}.agents.md`);
8805
+ fs29.writeFileSync(outPath, result.value);
8473
8806
  generated.push(outPath);
8474
8807
  }
8475
8808
  }
8476
8809
  if (!only || only === "ci") {
8477
8810
  const result = generateCIWorkflow(persona, "github");
8478
8811
  if (result.ok) {
8479
- const outPath = path46.join(outputDir, ".github", "workflows", `${slug}.yml`);
8480
- fs28.mkdirSync(path46.dirname(outPath), { recursive: true });
8481
- fs28.writeFileSync(outPath, result.value);
8812
+ const outPath = path47.join(outputDir, ".github", "workflows", `${slug}.yml`);
8813
+ fs29.mkdirSync(path47.dirname(outPath), { recursive: true });
8814
+ fs29.writeFileSync(outPath, result.value);
8482
8815
  generated.push(outPath);
8483
8816
  }
8484
8817
  }
8485
8818
  return generated;
8486
8819
  }
8487
8820
  function createGenerateCommand3() {
8488
- return new Command69("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
8821
+ return new Command71("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
8489
8822
  const globalOpts = cmd.optsWithGlobals();
8490
- const personaResult = loadPersona(path46.join(resolvePersonasDir(), `${name}.yaml`));
8823
+ const personaResult = loadPersona(path47.join(resolvePersonasDir(), `${name}.yaml`));
8491
8824
  if (!personaResult.ok) {
8492
8825
  logger.error(personaResult.error.message);
8493
8826
  process.exit(ExitCode.ERROR);
8494
8827
  }
8495
8828
  const generated = generatePersonaArtifacts(
8496
8829
  personaResult.value,
8497
- path46.resolve(opts.outputDir),
8830
+ path47.resolve(opts.outputDir),
8498
8831
  opts.only
8499
8832
  );
8500
8833
  if (!globalOpts.quiet) {
@@ -8507,7 +8840,7 @@ function createGenerateCommand3() {
8507
8840
 
8508
8841
  // src/commands/persona/index.ts
8509
8842
  function createPersonaCommand() {
8510
- const command = new Command70("persona").description("Agent persona management commands");
8843
+ const command = new Command72("persona").description("Agent persona management commands");
8511
8844
  command.addCommand(createListCommand2());
8512
8845
  command.addCommand(createGenerateCommand3());
8513
8846
  return command;
@@ -8515,8 +8848,8 @@ function createPersonaCommand() {
8515
8848
 
8516
8849
  // src/commands/predict.ts
8517
8850
  init_dist3();
8518
- import { Command as Command71 } from "commander";
8519
- import chalk10 from "chalk";
8851
+ import { Command as Command73 } from "commander";
8852
+ import chalk11 from "chalk";
8520
8853
  var CATEGORY_ORDER = [
8521
8854
  "circular-deps",
8522
8855
  "layer-violations",
@@ -8537,11 +8870,11 @@ function crossingLabel(weeks) {
8537
8870
  function severityPrefix(severity) {
8538
8871
  switch (severity) {
8539
8872
  case "critical":
8540
- return chalk10.red("[critical]");
8873
+ return chalk11.red("[critical]");
8541
8874
  case "warning":
8542
- return chalk10.yellow("[warning]");
8875
+ return chalk11.yellow("[warning]");
8543
8876
  case "info":
8544
- return chalk10.blue("[info]");
8877
+ return chalk11.blue("[info]");
8545
8878
  }
8546
8879
  }
8547
8880
  function printCategoryTable(result) {
@@ -8621,7 +8954,7 @@ function handlePredictError(err, mode) {
8621
8954
  process.exit(ExitCode.ERROR);
8622
8955
  }
8623
8956
  function createPredictCommand() {
8624
- const command = new Command71("predict").description("Predict which architectural constraints will break and when").option("--category <name>", "Filter to a single metric category").option("--no-roadmap", "Baseline only \u2014 skip roadmap spec impact").option("--horizon <weeks>", "Forecast horizon in weeks (default: 12)", "12").action(async (opts, cmd) => {
8957
+ const command = new Command73("predict").description("Predict which architectural constraints will break and when").option("--category <name>", "Filter to a single metric category").option("--no-roadmap", "Baseline only \u2014 skip roadmap spec impact").option("--horizon <weeks>", "Forecast horizon in weeks (default: 12)", "12").action(async (opts, cmd) => {
8625
8958
  const globalOpts = cmd.optsWithGlobals();
8626
8959
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
8627
8960
  try {
@@ -8645,7 +8978,7 @@ function createPredictCommand() {
8645
8978
 
8646
8979
  // src/commands/proposals.ts
8647
8980
  init_dist3();
8648
- import { Command as Command72 } from "commander";
8981
+ import { Command as Command74 } from "commander";
8649
8982
  import { resolve as resolve32 } from "path";
8650
8983
  function projectRoot() {
8651
8984
  return resolve32(process.env["HARNESS_PROJECT_ROOT"] ?? process.cwd());
@@ -8740,7 +9073,7 @@ async function actApproveCommand(id) {
8740
9073
  }
8741
9074
  }
8742
9075
  function createProposalsCommand() {
8743
- const cmd = new Command72("proposals").description("Skill-proposal review queue (Hermes Phase 4)");
9076
+ const cmd = new Command74("proposals").description("Skill-proposal review queue");
8744
9077
  cmd.command("list").description("List skill proposals in the local queue").option(
8745
9078
  "--status <status>",
8746
9079
  `Filter by status \u2014 one of ${ALLOWED_STATUSES.join(" | ")}`,
@@ -8755,9 +9088,9 @@ function createProposalsCommand() {
8755
9088
  }
8756
9089
 
8757
9090
  // src/commands/publish-analyses.ts
8758
- import * as fs29 from "fs";
8759
- import * as path47 from "path";
8760
- import { Command as Command73 } from "commander";
9091
+ import * as fs30 from "fs";
9092
+ import * as path48 from "path";
9093
+ import { Command as Command75 } from "commander";
8761
9094
  init_dist3();
8762
9095
  import {
8763
9096
  renderAnalysisComment,
@@ -8765,7 +9098,7 @@ import {
8765
9098
  savePublishedIndex
8766
9099
  } from "@harness-engineering/orchestrator";
8767
9100
  function bootstrapTrackerCommand(opts, verb) {
8768
- const projectPath = path47.resolve(opts.dir);
9101
+ const projectPath = path48.resolve(opts.dir);
8769
9102
  const trackerConfig = loadTrackerSyncConfig(projectPath);
8770
9103
  if (!trackerConfig) {
8771
9104
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -8777,8 +9110,8 @@ function bootstrapTrackerCommand(opts, verb) {
8777
9110
  );
8778
9111
  return null;
8779
9112
  }
8780
- const projectEnvPath = path47.join(projectPath, ".env");
8781
- if (fs29.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
9113
+ const projectEnvPath = path48.join(projectPath, ".env");
9114
+ if (fs30.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
8782
9115
  __require("dotenv").config({ path: projectEnvPath });
8783
9116
  }
8784
9117
  const token = process.env.GITHUB_TOKEN;
@@ -8814,13 +9147,13 @@ async function buildNameToExternalIdMap(projectPath) {
8814
9147
  }
8815
9148
  return fileLessMap;
8816
9149
  }
8817
- const roadmapFile = path47.join(projectPath, "docs", "roadmap.md");
8818
- if (!fs29.existsSync(roadmapFile)) {
9150
+ const roadmapFile = path48.join(projectPath, "docs", "roadmap.md");
9151
+ if (!fs30.existsSync(roadmapFile)) {
8819
9152
  logger.error("No docs/roadmap.md found. Cannot map issue hashes to external IDs.");
8820
9153
  return null;
8821
9154
  }
8822
9155
  const { parseRoadmap: parseRoadmap2 } = (init_dist3(), __toCommonJS(dist_exports));
8823
- const roadmapParsed = parseRoadmap2(fs29.readFileSync(roadmapFile, "utf-8"));
9156
+ const roadmapParsed = parseRoadmap2(fs30.readFileSync(roadmapFile, "utf-8"));
8824
9157
  if (!roadmapParsed.ok) {
8825
9158
  logger.error("Failed to parse docs/roadmap.md");
8826
9159
  return null;
@@ -8870,8 +9203,8 @@ async function runPublishAnalyses(opts) {
8870
9203
  const nameToExternalId = await buildNameToExternalIdMap(projectPath);
8871
9204
  if (!nameToExternalId) return process.exit(1);
8872
9205
  const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
8873
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-XIJWWQ5N.js");
8874
- const archive = new AnalysisArchive(path47.join(projectPath, ".harness", "analyses"));
9206
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-JCFK263L.js");
9207
+ const archive = new AnalysisArchive(path48.join(projectPath, ".harness", "analyses"));
8875
9208
  const analyses = await archive.list();
8876
9209
  if (analyses.length === 0) {
8877
9210
  logger.info("No analyses found to publish.");
@@ -8893,7 +9226,7 @@ async function runPublishAnalyses(opts) {
8893
9226
  }
8894
9227
  }
8895
9228
  function createPublishAnalysesCommand() {
8896
- const command = new Command73("publish-analyses").description(
9229
+ const command = new Command75("publish-analyses").description(
8897
9230
  "Publishes locally generated intelligence analyses to the external issue tracker (e.g., GitHub)"
8898
9231
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
8899
9232
  try {
@@ -8909,18 +9242,18 @@ function createPublishAnalysesCommand() {
8909
9242
  }
8910
9243
 
8911
9244
  // src/commands/pulse/index.ts
8912
- import { Command as Command75 } from "commander";
9245
+ import { Command as Command77 } from "commander";
8913
9246
 
8914
9247
  // src/commands/pulse/run.ts
8915
9248
  init_dist3();
8916
- import { readFileSync as readFileSync18, mkdirSync as mkdirSync13, writeFileSync as writeFileSync15 } from "fs";
8917
- import { dirname as dirname17, join as join38, resolve as resolve34 } from "path";
8918
- import { Command as Command74 } from "commander";
9249
+ import { readFileSync as readFileSync19, mkdirSync as mkdirSync13, writeFileSync as writeFileSync16 } from "fs";
9250
+ import { dirname as dirname18, join as join39, resolve as resolve34 } from "path";
9251
+ import { Command as Command76 } from "commander";
8919
9252
  async function runPulseRunCommand(opts) {
8920
9253
  const startedAt = Date.now();
8921
9254
  let raw;
8922
9255
  try {
8923
- raw = JSON.parse(readFileSync18(opts.configPath, "utf-8"));
9256
+ raw = JSON.parse(readFileSync19(opts.configPath, "utf-8"));
8924
9257
  } catch (err) {
8925
9258
  return emit2(
8926
9259
  {
@@ -8946,9 +9279,9 @@ async function runPulseRunCommand(opts) {
8946
9279
  const report = assembleReport(result, productName, lookback);
8947
9280
  const now = /* @__PURE__ */ new Date();
8948
9281
  const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}-${String(now.getMinutes()).padStart(2, "0")}`;
8949
- const filePath = join38(opts.outputDir, `${ts}.md`);
8950
- mkdirSync13(dirname17(filePath), { recursive: true });
8951
- writeFileSync15(filePath, report);
9282
+ const filePath = join39(opts.outputDir, `${ts}.md`);
9283
+ mkdirSync13(dirname18(filePath), { recursive: true });
9284
+ writeFileSync16(filePath, report);
8952
9285
  const headlines = extractHeadlines(report);
8953
9286
  return emit2(
8954
9287
  {
@@ -8980,7 +9313,7 @@ function emit2(status, nonInteractive) {
8980
9313
  return status;
8981
9314
  }
8982
9315
  function createRunCommand2() {
8983
- return new Command74("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
9316
+ return new Command76("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
8984
9317
  "--lookback <window>",
8985
9318
  "Lookback window (e.g. 24h, 7d). Defaults to pulse.lookbackDefault."
8986
9319
  ).option(
@@ -9004,14 +9337,14 @@ function createRunCommand2() {
9004
9337
 
9005
9338
  // src/commands/pulse/index.ts
9006
9339
  function createPulseCommand() {
9007
- const command = new Command75("pulse").description("Pulse (read-side observability) commands");
9340
+ const command = new Command77("pulse").description("Pulse (read-side observability) commands");
9008
9341
  command.addCommand(createRunCommand2());
9009
9342
  return command;
9010
9343
  }
9011
9344
 
9012
9345
  // src/commands/recommend.ts
9013
- import { Command as Command76 } from "commander";
9014
- import chalk11 from "chalk";
9346
+ import { Command as Command78 } from "commander";
9347
+ import chalk12 from "chalk";
9015
9348
  async function resolveSnapshot(cwd, noCache) {
9016
9349
  if (!noCache) {
9017
9350
  const cached = loadCachedSnapshot(cwd);
@@ -9045,12 +9378,12 @@ async function runRecommend(options) {
9045
9378
  function formatRecommendation(rec) {
9046
9379
  const lines = [];
9047
9380
  if (rec.urgency === "critical") {
9048
- lines.push(` ${chalk11.red("[CRITICAL]")} ${rec.sequence}. ${rec.skillName}`);
9381
+ lines.push(` ${chalk12.red("[CRITICAL]")} ${rec.sequence}. ${rec.skillName}`);
9049
9382
  } else {
9050
9383
  lines.push(` ${rec.sequence}. ${rec.skillName} (${rec.score.toFixed(2)})`);
9051
9384
  }
9052
9385
  for (const reason of rec.reasons) {
9053
- lines.push(` ${chalk11.dim("\u2192")} ${reason}`);
9386
+ lines.push(` ${chalk12.dim("\u2192")} ${reason}`);
9054
9387
  }
9055
9388
  return lines.join("\n");
9056
9389
  }
@@ -9074,7 +9407,7 @@ function printRecommendations(result) {
9074
9407
  console.log("");
9075
9408
  }
9076
9409
  function createRecommendCommand() {
9077
- const command = new Command76("recommend").description("Recommend skills based on codebase health analysis").option("--no-cache", "Force fresh health snapshot").option("--top <n>", "Max recommendations (default 5)", "5").action(async (opts, cmd) => {
9410
+ const command = new Command78("recommend").description("Recommend skills based on codebase health analysis").option("--no-cache", "Force fresh health snapshot").option("--top <n>", "Max recommendations (default 5)", "5").action(async (opts, cmd) => {
9078
9411
  const globalOpts = cmd.optsWithGlobals();
9079
9412
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
9080
9413
  try {
@@ -9110,18 +9443,18 @@ function createRecommendCommand() {
9110
9443
  }
9111
9444
 
9112
9445
  // src/commands/roadmap/index.ts
9113
- import { Command as Command78 } from "commander";
9446
+ import { Command as Command80 } from "commander";
9114
9447
 
9115
9448
  // src/commands/roadmap/migrate.ts
9116
9449
  init_dist3();
9117
- import { Command as Command77 } from "commander";
9118
- import * as fs31 from "fs";
9119
- import * as path49 from "path";
9120
- import chalk12 from "chalk";
9450
+ import { Command as Command79 } from "commander";
9451
+ import * as fs32 from "fs";
9452
+ import * as path50 from "path";
9453
+ import chalk13 from "chalk";
9121
9454
 
9122
9455
  // src/commands/roadmap/migrate-lock.ts
9123
- import * as fs30 from "fs";
9124
- import * as path48 from "path";
9456
+ import * as fs31 from "fs";
9457
+ import * as path49 from "path";
9125
9458
  import * as os6 from "os";
9126
9459
  var LOCK_FILE_NAME = "migrate.lock";
9127
9460
  var STALE_LOCK_MS = 30 * 60 * 1e3;
@@ -9135,13 +9468,13 @@ function isPidAlive(pid) {
9135
9468
  }
9136
9469
  }
9137
9470
  function acquireMigrateLock(projectRoot2) {
9138
- const harnessDir = path48.join(projectRoot2, ".harness");
9139
- const lockPath = path48.join(harnessDir, LOCK_FILE_NAME);
9140
- if (!fs30.existsSync(harnessDir)) fs30.mkdirSync(harnessDir, { recursive: true });
9141
- if (fs30.existsSync(lockPath)) {
9471
+ const harnessDir = path49.join(projectRoot2, ".harness");
9472
+ const lockPath = path49.join(harnessDir, LOCK_FILE_NAME);
9473
+ if (!fs31.existsSync(harnessDir)) fs31.mkdirSync(harnessDir, { recursive: true });
9474
+ if (fs31.existsSync(lockPath)) {
9142
9475
  const existingRaw = (() => {
9143
9476
  try {
9144
- return fs30.readFileSync(lockPath, "utf-8");
9477
+ return fs31.readFileSync(lockPath, "utf-8");
9145
9478
  } catch {
9146
9479
  return null;
9147
9480
  }
@@ -9171,11 +9504,11 @@ function acquireMigrateLock(projectRoot2) {
9171
9504
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
9172
9505
  hostname: os6.hostname()
9173
9506
  };
9174
- fs30.writeFileSync(lockPath, JSON.stringify(payload, null, 2) + "\n");
9507
+ fs31.writeFileSync(lockPath, JSON.stringify(payload, null, 2) + "\n");
9175
9508
  return {
9176
9509
  release: () => {
9177
9510
  try {
9178
- fs30.unlinkSync(lockPath);
9511
+ fs31.unlinkSync(lockPath);
9179
9512
  } catch {
9180
9513
  }
9181
9514
  }
@@ -9206,7 +9539,7 @@ function reportToExitCode(report) {
9206
9539
  return MigrateExitCode.GENERIC_FAILURE;
9207
9540
  }
9208
9541
  function printPlanSummary(plan, dryRun) {
9209
- const banner = dryRun ? chalk12.cyan("DRY RUN ") : "";
9542
+ const banner = dryRun ? chalk13.cyan("DRY RUN ") : "";
9210
9543
  console.log(`${banner}Migration plan:`);
9211
9544
  console.log(` Would create: ${plan.toCreate.length}`);
9212
9545
  for (const e of plan.toCreate) console.log(` - ${e.name}`);
@@ -9335,11 +9668,11 @@ async function runRoadmapMigrate(opts) {
9335
9668
  if (!clientR.ok) return Err(new CLIError(clientR.error.message));
9336
9669
  client = clientR.value;
9337
9670
  }
9338
- const roadmapPath = path49.join(cwd, "docs", "roadmap.md");
9339
- if (!fs31.existsSync(roadmapPath)) {
9671
+ const roadmapPath = path50.join(cwd, "docs", "roadmap.md");
9672
+ if (!fs32.existsSync(roadmapPath)) {
9340
9673
  return Err(new CLIError(`docs/roadmap.md not found in ${cwd}`));
9341
9674
  }
9342
- const roadmapR = parseRoadmap(fs31.readFileSync(roadmapPath, "utf-8"));
9675
+ const roadmapR = parseRoadmap(fs32.readFileSync(roadmapPath, "utf-8"));
9343
9676
  if (!roadmapR.ok) {
9344
9677
  return Err(new CLIError(`failed to parse docs/roadmap.md: ${roadmapR.error.message}`));
9345
9678
  }
@@ -9360,10 +9693,10 @@ async function runRoadmapMigrate(opts) {
9360
9693
  if (!isJson) printPlanSummary(plan, opts.dryRun);
9361
9694
  const deps = {
9362
9695
  client,
9363
- readFile: (p) => fs31.readFileSync(p, "utf-8"),
9364
- writeFile: (p, b) => fs31.writeFileSync(p, b),
9365
- renameFile: (from, to) => fs31.renameSync(from, to),
9366
- existsFile: (p) => fs31.existsSync(p)
9696
+ readFile: (p) => fs32.readFileSync(p, "utf-8"),
9697
+ writeFile: (p, b) => fs32.writeFileSync(p, b),
9698
+ renameFile: (from, to) => fs32.renameSync(from, to),
9699
+ existsFile: (p) => fs32.existsSync(p)
9367
9700
  };
9368
9701
  const reportR = await migrate_exports.runMigrationPlan(plan, deps, {
9369
9702
  projectRoot: cwd,
@@ -9384,7 +9717,7 @@ async function runRoadmapMigrate(opts) {
9384
9717
  }
9385
9718
  }
9386
9719
  function createRoadmapMigrateCommand() {
9387
- return new Command77("migrate").description("Migrate the project roadmap to a different storage mode").requiredOption("--to <target>", 'Migration target (only "file-less" supported today)').option("--dry-run", "Print the migration plan without making any changes", false).option(
9720
+ return new Command79("migrate").description("Migrate the project roadmap to a different storage mode").requiredOption("--to <target>", 'Migration target (only "file-less" supported today)').option("--dry-run", "Print the migration plan without making any changes", false).option(
9388
9721
  "--format <fmt>",
9389
9722
  'Output format: "human" (default) or "json" (single JSON object for CI consumers)',
9390
9723
  "human"
@@ -9419,16 +9752,16 @@ function createRoadmapMigrateCommand() {
9419
9752
 
9420
9753
  // src/commands/roadmap/index.ts
9421
9754
  function createRoadmapCommand() {
9422
- const roadmap = new Command78("roadmap").description("Roadmap management");
9755
+ const roadmap = new Command80("roadmap").description("Roadmap management");
9423
9756
  roadmap.addCommand(createRoadmapMigrateCommand());
9424
9757
  return roadmap;
9425
9758
  }
9426
9759
 
9427
9760
  // src/commands/routing/index.ts
9428
- import { Command as Command82 } from "commander";
9761
+ import { Command as Command84 } from "commander";
9429
9762
 
9430
9763
  // src/commands/routing/config.ts
9431
- import { Command as Command79 } from "commander";
9764
+ import { Command as Command81 } from "commander";
9432
9765
 
9433
9766
  // src/commands/routing/http-client.ts
9434
9767
  function orchestratorBase() {
@@ -9438,9 +9771,9 @@ function authHeader() {
9438
9771
  const tok = process.env["HARNESS_API_TOKEN"];
9439
9772
  return tok ? { Authorization: `Bearer ${tok}` } : {};
9440
9773
  }
9441
- async function getJson(path71) {
9774
+ async function getJson(path72) {
9442
9775
  try {
9443
- const res = await fetch(`${orchestratorBase()}${path71}`, {
9776
+ const res = await fetch(`${orchestratorBase()}${path72}`, {
9444
9777
  headers: { ...authHeader() }
9445
9778
  });
9446
9779
  const text = await res.text();
@@ -9455,9 +9788,9 @@ async function getJson(path71) {
9455
9788
  };
9456
9789
  }
9457
9790
  }
9458
- async function postJson(path71, body) {
9791
+ async function postJson(path72, body) {
9459
9792
  try {
9460
- const res = await fetch(`${orchestratorBase()}${path71}`, {
9793
+ const res = await fetch(`${orchestratorBase()}${path72}`, {
9461
9794
  method: "POST",
9462
9795
  headers: { "Content-Type": "application/json", ...authHeader() },
9463
9796
  body: JSON.stringify(body)
@@ -9493,7 +9826,7 @@ function renderHuman(data) {
9493
9826
  }
9494
9827
  }
9495
9828
  function createConfigCommand() {
9496
- return new Command79("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
9829
+ return new Command81("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
9497
9830
  const r = await getJson("/api/v1/routing/config");
9498
9831
  if (!r.ok) {
9499
9832
  if (r.status === 0) {
@@ -9519,7 +9852,7 @@ function createConfigCommand() {
9519
9852
  }
9520
9853
 
9521
9854
  // src/commands/routing/trace.ts
9522
- import { Command as Command80 } from "commander";
9855
+ import { Command as Command82 } from "commander";
9523
9856
  function buildUseCase(opts) {
9524
9857
  if (opts.skill) {
9525
9858
  return opts.mode ? { kind: "skill", skillName: opts.skill, cognitiveMode: opts.mode } : { kind: "skill", skillName: opts.skill };
@@ -9540,7 +9873,7 @@ function renderHuman2(r) {
9540
9873
  }
9541
9874
  }
9542
9875
  function createTraceCommand() {
9543
- return new Command80("trace").description("Dry-run a routing decision without dispatching (Spec B F7)").option("--skill <name>", "Skill name to trace").option("--mode <m>", "Cognitive mode to trace (or attach to --skill per spec D12)").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
9876
+ return new Command82("trace").description("Dry-run a routing decision without dispatching (Spec B F7)").option("--skill <name>", "Skill name to trace").option("--mode <m>", "Cognitive mode to trace (or attach to --skill per spec D12)").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
9544
9877
  const useCase = buildUseCase(opts);
9545
9878
  if (!useCase) {
9546
9879
  logger.error("Either --skill <name> or --mode <m> is required");
@@ -9572,7 +9905,7 @@ function createTraceCommand() {
9572
9905
  }
9573
9906
 
9574
9907
  // src/commands/routing/decisions.ts
9575
- import { Command as Command81 } from "commander";
9908
+ import { Command as Command83 } from "commander";
9576
9909
  function summarizeUseCase(uc) {
9577
9910
  switch (uc.kind) {
9578
9911
  case "skill":
@@ -9620,7 +9953,7 @@ function buildQuery(opts) {
9620
9953
  return q ? `?${q}` : "";
9621
9954
  }
9622
9955
  function createDecisionsCommand() {
9623
- return new Command81("decisions").description("List recent routing decisions from the orchestrator ring buffer (Spec B F8)").option("--skill <name>", "Filter by useCase.skillName").option("--mode <m>", "Filter by useCase.cognitiveMode").option("--backend <name>", "Filter by chosen backendName").option("--last <N>", "Limit to the N most recent decisions").option("--json", "Emit JSON to stdout instead of human-readable text").action(
9956
+ return new Command83("decisions").description("List recent routing decisions from the orchestrator ring buffer (Spec B F8)").option("--skill <name>", "Filter by useCase.skillName").option("--mode <m>", "Filter by useCase.cognitiveMode").option("--backend <name>", "Filter by chosen backendName").option("--last <N>", "Limit to the N most recent decisions").option("--json", "Emit JSON to stdout instead of human-readable text").action(
9624
9957
  async (opts) => {
9625
9958
  const query = buildQuery(opts);
9626
9959
  const r = await getJson(`/api/v1/routing/decisions${query}`);
@@ -9650,7 +9983,7 @@ function createDecisionsCommand() {
9650
9983
 
9651
9984
  // src/commands/routing/index.ts
9652
9985
  function createRoutingCommand() {
9653
- const cmd = new Command82("routing").description(
9986
+ const cmd = new Command84("routing").description(
9654
9987
  "Inspect routing config, trace decisions, and read recent dispatches"
9655
9988
  );
9656
9989
  cmd.addCommand(createConfigCommand());
@@ -9661,9 +9994,9 @@ function createRoutingCommand() {
9661
9994
 
9662
9995
  // src/commands/scan-config.ts
9663
9996
  init_dist3();
9664
- import { Command as Command83 } from "commander";
9665
- import { existsSync as existsSync28, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "fs";
9666
- import { join as join41, relative as relative3 } from "path";
9997
+ import { Command as Command85 } from "commander";
9998
+ import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "fs";
9999
+ import { join as join42, relative as relative3 } from "path";
9667
10000
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
9668
10001
  function stripHighSeverityPatterns(content, injectionFindings) {
9669
10002
  const highLines = /* @__PURE__ */ new Set();
@@ -9689,17 +10022,17 @@ function applyFix(filePath, targetDir, content, injectionFindings) {
9689
10022
  if (!hasHighSeverity) return;
9690
10023
  const { cleaned, linesStripped } = stripHighSeverityPatterns(content, injectionFindings);
9691
10024
  if (linesStripped > 0) {
9692
- writeFileSync18(filePath, cleaned);
10025
+ writeFileSync19(filePath, cleaned);
9693
10026
  logger.info(
9694
10027
  `scan-config --fix: stripped ${linesStripped} high-severity line(s) from ${relative3(targetDir, filePath).replaceAll("\\", "/")}`
9695
10028
  );
9696
10029
  }
9697
10030
  }
9698
10031
  function scanSingleFile(filePath, targetDir, scanner, options) {
9699
- if (!existsSync28(filePath)) return null;
10032
+ if (!existsSync29(filePath)) return null;
9700
10033
  let content;
9701
10034
  try {
9702
- content = readFileSync21(filePath, "utf8");
10035
+ content = readFileSync22(filePath, "utf8");
9703
10036
  } catch {
9704
10037
  return null;
9705
10038
  }
@@ -9720,7 +10053,7 @@ async function runScanConfig(targetDir, options) {
9720
10053
  const scanner = new SecurityScanner(parseSecurityConfig({}));
9721
10054
  const results = [];
9722
10055
  for (const configFile of CONFIG_FILES) {
9723
- const result = scanSingleFile(join41(targetDir, configFile), targetDir, scanner, options);
10056
+ const result = scanSingleFile(join42(targetDir, configFile), targetDir, scanner, options);
9724
10057
  if (result) results.push(result);
9725
10058
  }
9726
10059
  return { exitCode: computeScanExitCode(results), results };
@@ -9750,7 +10083,7 @@ function formatTextOutput(result) {
9750
10083
  }
9751
10084
  }
9752
10085
  function createScanConfigCommand() {
9753
- const command = new Command83("scan-config").description(
10086
+ const command = new Command85("scan-config").description(
9754
10087
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
9755
10088
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
9756
10089
  const globalOpts = cmd.optsWithGlobals();
@@ -9768,7 +10101,7 @@ function createScanConfigCommand() {
9768
10101
 
9769
10102
  // src/commands/search.ts
9770
10103
  init_dist();
9771
- import { Command as Command84 } from "commander";
10104
+ import { Command as Command86 } from "commander";
9772
10105
  function parseFileKinds(raw) {
9773
10106
  if (!raw) return void 0;
9774
10107
  const set = /* @__PURE__ */ new Set();
@@ -9789,7 +10122,7 @@ function fmtBytes(n) {
9789
10122
  return n.toFixed(0);
9790
10123
  }
9791
10124
  function createSearchCommand() {
9792
- return new Command84("search").description("Full-text search over archived + live session content (Hermes Phase 1).").argument(
10125
+ return new Command86("search").description("Full-text search over archived + live session content.").argument(
9793
10126
  "<query>",
9794
10127
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
9795
10128
  ).option("-n, --limit <n>", "Max results", "20").option("--archived-only", "Skip live sessions, only search archived ones").option("--json", "Emit JSON to stdout instead of pretty text").option(
@@ -9849,9 +10182,9 @@ function createSearchCommand() {
9849
10182
  }
9850
10183
 
9851
10184
  // src/commands/security-craft.ts
9852
- import { Command as Command85 } from "commander";
10185
+ import { Command as Command87 } from "commander";
9853
10186
  function createSecurityCraftCommand() {
9854
- return new Command85("security-craft").description(
10187
+ return new Command87("security-craft").description(
9855
10188
  "LLM-judgment critique of security posture (TS/JS source). Sixth non-design craft-pipeline ceiling skill (the final sub-project). AST-driven signal detection fires only on files with security-relevant constructs; conservative confidence defaults manage the FP risk inherent in judgment-based security."
9856
10189
  ).option("-f, --files <files...>", "Optional file scope (overrides discovery)").option("-p, --packages <names...>", "Restrict to specific packages under packages/").option("--max-files <n>", "Cap source-file count (default: 100)").option("--max-signals-per-file <n>", "Cap per-file signal critique (default: 10)").action(async (opts, cmd) => {
9857
10190
  const globalOpts = cmd.optsWithGlobals();
@@ -9898,10 +10231,10 @@ function printResult5(result, mode, _formatter) {
9898
10231
  list.push(f);
9899
10232
  byFile.set(f.target.file, list);
9900
10233
  }
9901
- for (const [file, fs47] of byFile) {
10234
+ for (const [file, fs48] of byFile) {
9902
10235
  console.log(`
9903
10236
  ${file}`);
9904
- for (const f of fs47) {
10237
+ for (const f of fs48) {
9905
10238
  console.log(
9906
10239
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.signal}:${f.target.line}`
9907
10240
  );
@@ -9917,24 +10250,24 @@ ${file}`);
9917
10250
  }
9918
10251
 
9919
10252
  // src/commands/setup.ts
9920
- import { Command as Command86 } from "commander";
9921
- import * as fs34 from "fs";
10253
+ import { Command as Command88 } from "commander";
10254
+ import * as fs35 from "fs";
9922
10255
  import * as os8 from "os";
9923
- import * as path52 from "path";
9924
- import chalk14 from "chalk";
10256
+ import * as path53 from "path";
10257
+ import chalk15 from "chalk";
9925
10258
 
9926
10259
  // src/utils/first-run.ts
9927
- import * as fs32 from "fs";
10260
+ import * as fs33 from "fs";
9928
10261
  import * as os7 from "os";
9929
- import * as path50 from "path";
9930
- var HARNESS_DIR = path50.join(os7.homedir(), ".harness");
9931
- var MARKER_FILE = path50.join(HARNESS_DIR, ".setup-complete");
10262
+ import * as path51 from "path";
10263
+ var HARNESS_DIR = path51.join(os7.homedir(), ".harness");
10264
+ var MARKER_FILE = path51.join(HARNESS_DIR, ".setup-complete");
9932
10265
  function isFirstRun() {
9933
- return !fs32.existsSync(MARKER_FILE);
10266
+ return !fs33.existsSync(MARKER_FILE);
9934
10267
  }
9935
10268
  function markSetupComplete() {
9936
- fs32.mkdirSync(HARNESS_DIR, { recursive: true });
9937
- fs32.writeFileSync(MARKER_FILE, "", "utf-8");
10269
+ fs33.mkdirSync(HARNESS_DIR, { recursive: true });
10270
+ fs33.writeFileSync(MARKER_FILE, "", "utf-8");
9938
10271
  }
9939
10272
  function printFirstRunWelcome() {
9940
10273
  try {
@@ -9947,10 +10280,10 @@ function printFirstRunWelcome() {
9947
10280
  }
9948
10281
 
9949
10282
  // src/commands/telemetry-wizard.ts
9950
- import * as fs33 from "fs";
9951
- import * as path51 from "path";
10283
+ import * as fs34 from "fs";
10284
+ import * as path52 from "path";
9952
10285
  import readline2 from "readline";
9953
- import chalk13 from "chalk";
10286
+ import chalk14 from "chalk";
9954
10287
  function prompt2(question) {
9955
10288
  const rl = readline2.createInterface({
9956
10289
  input: process.stdin,
@@ -9979,21 +10312,21 @@ function isNo(answer) {
9979
10312
  return answer === "n" || answer === "no";
9980
10313
  }
9981
10314
  function isTelemetryConfigured(cwd) {
9982
- const configPath = path51.join(cwd, "harness.config.json");
10315
+ const configPath = path52.join(cwd, "harness.config.json");
9983
10316
  try {
9984
- const raw = JSON.parse(fs33.readFileSync(configPath, "utf-8"));
10317
+ const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
9985
10318
  return raw.telemetry !== void 0 && raw.adoption !== void 0;
9986
10319
  } catch {
9987
10320
  return false;
9988
10321
  }
9989
10322
  }
9990
10323
  function writeTelemetryConfig(cwd, result) {
9991
- const configPath = path51.join(cwd, "harness.config.json");
10324
+ const configPath = path52.join(cwd, "harness.config.json");
9992
10325
  try {
9993
- const raw = JSON.parse(fs33.readFileSync(configPath, "utf-8"));
10326
+ const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
9994
10327
  raw.telemetry = { enabled: result.telemetryEnabled };
9995
10328
  raw.adoption = { enabled: result.adoptionEnabled };
9996
- fs33.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
10329
+ fs34.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
9997
10330
  } catch (err) {
9998
10331
  console.warn(
9999
10332
  `\u26A0 Could not update ${configPath}: ${err instanceof Error ? err.message : String(err)}`
@@ -10001,15 +10334,15 @@ function writeTelemetryConfig(cwd, result) {
10001
10334
  }
10002
10335
  const hasIdentity = result.identity.project || result.identity.team || result.identity.alias;
10003
10336
  if (hasIdentity) {
10004
- const harnessDir = path51.join(cwd, ".harness");
10005
- fs33.mkdirSync(harnessDir, { recursive: true });
10006
- const telemetryFile = path51.join(harnessDir, "telemetry.json");
10007
- fs33.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
10337
+ const harnessDir = path52.join(cwd, ".harness");
10338
+ fs34.mkdirSync(harnessDir, { recursive: true });
10339
+ const telemetryFile = path52.join(harnessDir, "telemetry.json");
10340
+ fs34.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
10008
10341
  }
10009
10342
  }
10010
10343
  async function promptIdentity() {
10011
10344
  console.log(
10012
- ` ${chalk13.cyan("Identity")} (optional) \u2014 tag telemetry with project/team/alias for filtering.`
10345
+ ` ${chalk14.cyan("Identity")} (optional) \u2014 tag telemetry with project/team/alias for filtering.`
10013
10346
  );
10014
10347
  console.log(" Leave blank to keep anonymous.");
10015
10348
  const answer = await prompt2(" Set identity fields? (y/N) ");
@@ -10027,20 +10360,20 @@ async function promptIdentity() {
10027
10360
  async function runTelemetryWizard() {
10028
10361
  if (!process.stdin.isTTY) return null;
10029
10362
  console.log("");
10030
- console.log(` ${chalk13.bold("Telemetry Configuration")}`);
10363
+ console.log(` ${chalk14.bold("Telemetry Configuration")}`);
10031
10364
  console.log("");
10032
10365
  console.log(" Harness can collect anonymous usage data to help improve the tool.");
10033
10366
  console.log(" You can change these settings anytime in harness.config.json.");
10034
10367
  console.log("");
10035
10368
  console.log(
10036
- ` ${chalk13.cyan("Anonymous telemetry")} \u2014 error rates, command usage, performance metrics.`
10369
+ ` ${chalk14.cyan("Anonymous telemetry")} \u2014 error rates, command usage, performance metrics.`
10037
10370
  );
10038
10371
  console.log(" No code, file contents, or personally identifiable info is sent.");
10039
10372
  const telemetryAnswer = await prompt2(" Enable anonymous telemetry? (Y/n) ");
10040
10373
  const telemetryEnabled = !isNo(telemetryAnswer);
10041
10374
  console.log("");
10042
10375
  console.log(
10043
- ` ${chalk13.cyan("Adoption tracking")} \u2014 which skills are used, how often, and success rates.`
10376
+ ` ${chalk14.cyan("Adoption tracking")} \u2014 which skills are used, how often, and success rates.`
10044
10377
  );
10045
10378
  console.log(" Stored locally in .harness/adoption/. Never sent externally.");
10046
10379
  const adoptionAnswer = await prompt2(" Enable local adoption tracking? (Y/n) ");
@@ -10050,8 +10383,8 @@ async function runTelemetryWizard() {
10050
10383
  return { telemetryEnabled, adoptionEnabled, identity };
10051
10384
  }
10052
10385
  async function ensureTelemetryConfigured(cwd) {
10053
- const configPath = path51.join(cwd, "harness.config.json");
10054
- if (!fs33.existsSync(configPath)) {
10386
+ const configPath = path52.join(cwd, "harness.config.json");
10387
+ if (!fs34.existsSync(configPath)) {
10055
10388
  return { status: "warn", message: "Not a harness project \u2014 skipped telemetry configuration" };
10056
10389
  }
10057
10390
  if (isTelemetryConfigured(cwd)) {
@@ -10097,7 +10430,7 @@ function runSlashCommandGeneration() {
10097
10430
  }
10098
10431
  }
10099
10432
  function detectClient(dirName) {
10100
- return fs34.existsSync(path52.join(os8.homedir(), dirName));
10433
+ return fs35.existsSync(path53.join(os8.homedir(), dirName));
10101
10434
  }
10102
10435
  async function runMcpSetup(cwd) {
10103
10436
  const results = [];
@@ -10113,7 +10446,7 @@ async function runMcpSetup(cwd) {
10113
10446
  { name: "Cursor", dir: ".cursor", client: "cursor", configTarget: ".cursor/mcp.json" },
10114
10447
  {
10115
10448
  name: "OpenCode",
10116
- dir: path52.join(".config", "opencode"),
10449
+ dir: path53.join(".config", "opencode"),
10117
10450
  client: "opencode",
10118
10451
  configTarget: "opencode.json"
10119
10452
  }
@@ -10140,12 +10473,12 @@ async function runMcpSetup(cwd) {
10140
10473
  return results;
10141
10474
  }
10142
10475
  function formatStep(result) {
10143
- const icon = result.status === "pass" ? chalk14.green("\u2713") : result.status === "warn" ? chalk14.yellow("\u26A0") : chalk14.red("\u2717");
10476
+ const icon = result.status === "pass" ? chalk15.green("\u2713") : result.status === "warn" ? chalk15.yellow("\u26A0") : chalk15.red("\u2717");
10144
10477
  return ` ${icon} ${result.message}`;
10145
10478
  }
10146
10479
  function configureTier0Integrations(cwd) {
10147
10480
  try {
10148
- const mcpPath = path52.join(cwd, ".mcp.json");
10481
+ const mcpPath = path53.join(cwd, ".mcp.json");
10149
10482
  const config = readMcpConfig(mcpPath);
10150
10483
  const tier0 = INTEGRATION_REGISTRY.filter((i) => i.tier === 0);
10151
10484
  const added = [];
@@ -10154,9 +10487,9 @@ function configureTier0Integrations(cwd) {
10154
10487
  writeMcpEntry(mcpPath, integration.name, integration.mcpConfig);
10155
10488
  added.push(integration.displayName);
10156
10489
  }
10157
- const geminiDir = path52.join(cwd, ".gemini");
10158
- if (fs34.existsSync(geminiDir)) {
10159
- const geminiPath = path52.join(geminiDir, "settings.json");
10490
+ const geminiDir = path53.join(cwd, ".gemini");
10491
+ if (fs35.existsSync(geminiDir)) {
10492
+ const geminiPath = path53.join(geminiDir, "settings.json");
10160
10493
  const geminiConfig = readMcpConfig(geminiPath);
10161
10494
  for (const integration of tier0) {
10162
10495
  if (!geminiConfig.mcpServers[integration.name]) {
@@ -10164,9 +10497,9 @@ function configureTier0Integrations(cwd) {
10164
10497
  }
10165
10498
  }
10166
10499
  }
10167
- const opencodePath = path52.join(cwd, "opencode.json");
10168
- const opencodeGlobalDir = path52.join(os8.homedir(), ".config", "opencode");
10169
- if (fs34.existsSync(opencodePath) || fs34.existsSync(opencodeGlobalDir)) {
10500
+ const opencodePath = path53.join(cwd, "opencode.json");
10501
+ const opencodeGlobalDir = path53.join(os8.homedir(), ".config", "opencode");
10502
+ if (fs35.existsSync(opencodePath) || fs35.existsSync(opencodeGlobalDir)) {
10170
10503
  for (const integration of tier0) {
10171
10504
  writeOpencodeMcpEntry(opencodePath, integration.name, integration.mcpConfig);
10172
10505
  }
@@ -10184,14 +10517,14 @@ function configureTier0Integrations(cwd) {
10184
10517
  }
10185
10518
  }
10186
10519
  function ensureHooks(cwd) {
10187
- const configPath = path52.join(cwd, "harness.config.json");
10188
- if (!fs34.existsSync(configPath)) {
10520
+ const configPath = path53.join(cwd, "harness.config.json");
10521
+ if (!fs35.existsSync(configPath)) {
10189
10522
  return { status: "warn", message: "Not a harness project \u2014 skipped hook installation" };
10190
10523
  }
10191
10524
  let profile = "standard";
10192
- const profilePath = path52.join(cwd, ".harness", "hooks", "profile.json");
10525
+ const profilePath = path53.join(cwd, ".harness", "hooks", "profile.json");
10193
10526
  try {
10194
- const data = JSON.parse(fs34.readFileSync(profilePath, "utf-8"));
10527
+ const data = JSON.parse(fs35.readFileSync(profilePath, "utf-8"));
10195
10528
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
10196
10529
  profile = data.profile;
10197
10530
  }
@@ -10223,7 +10556,7 @@ async function detectLegacyLayout(cwd) {
10223
10556
  }
10224
10557
  async function runInitialGraphScan(cwd) {
10225
10558
  try {
10226
- const { runScan: runScan2 } = await import("./scan-LYKLM4EQ.js");
10559
+ const { runScan: runScan2 } = await import("./scan-P7YFKB77.js");
10227
10560
  const result = await runScan2(cwd);
10228
10561
  return {
10229
10562
  status: "pass",
@@ -10262,10 +10595,10 @@ async function runSetup(cwd) {
10262
10595
  return { steps, success };
10263
10596
  }
10264
10597
  function createSetupCommand() {
10265
- return new Command86("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
10598
+ return new Command88("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
10266
10599
  const cwd = process.cwd();
10267
10600
  console.log("");
10268
- console.log(` ${chalk14.bold("harness setup")}`);
10601
+ console.log(` ${chalk15.bold("harness setup")}`);
10269
10602
  console.log("");
10270
10603
  const { steps, success } = await runSetup(cwd);
10271
10604
  for (const step of steps) {
@@ -10285,15 +10618,15 @@ function createSetupCommand() {
10285
10618
 
10286
10619
  // src/commands/share.ts
10287
10620
  init_dist3();
10288
- import { Command as Command87 } from "commander";
10289
- import * as fs35 from "fs";
10290
- import * as path53 from "path";
10291
- import { parse as parseYaml2 } from "yaml";
10621
+ import { Command as Command89 } from "commander";
10622
+ import * as fs36 from "fs";
10623
+ import * as path54 from "path";
10624
+ import { parse as parseYaml3 } from "yaml";
10292
10625
  var MANIFEST_FILENAME = "constraints.yaml";
10293
10626
  async function runShareAction(projectPath, options) {
10294
- const rootDir = path53.resolve(projectPath);
10295
- const manifestPath = path53.join(rootDir, MANIFEST_FILENAME);
10296
- if (!fs35.existsSync(manifestPath)) {
10627
+ const rootDir = path54.resolve(projectPath);
10628
+ const manifestPath = path54.join(rootDir, MANIFEST_FILENAME);
10629
+ if (!fs36.existsSync(manifestPath)) {
10297
10630
  logger.error(
10298
10631
  `No ${MANIFEST_FILENAME} found at ${manifestPath}.
10299
10632
  Create a constraints.yaml in your project root to define what to share.`
@@ -10302,8 +10635,8 @@ Create a constraints.yaml in your project root to define what to share.`
10302
10635
  }
10303
10636
  let parsed;
10304
10637
  try {
10305
- const raw = fs35.readFileSync(manifestPath, "utf-8");
10306
- parsed = parseYaml2(raw);
10638
+ const raw = fs36.readFileSync(manifestPath, "utf-8");
10639
+ parsed = parseYaml3(raw);
10307
10640
  } catch (err) {
10308
10641
  logger.error(
10309
10642
  `Failed to read ${MANIFEST_FILENAME}: ${err instanceof Error ? err.message : String(err)}`
@@ -10316,7 +10649,7 @@ Create a constraints.yaml in your project root to define what to share.`
10316
10649
  process.exit(1);
10317
10650
  }
10318
10651
  const manifest = manifestResult.value;
10319
- const configResult = resolveConfig(path53.join(rootDir, "harness.config.json"));
10652
+ const configResult = resolveConfig(path54.join(rootDir, "harness.config.json"));
10320
10653
  if (!configResult.ok) {
10321
10654
  logger.error(configResult.error.message);
10322
10655
  process.exit(1);
@@ -10334,8 +10667,8 @@ Create a constraints.yaml in your project root to define what to share.`
10334
10667
  );
10335
10668
  process.exit(1);
10336
10669
  }
10337
- const outputDir = path53.resolve(options.output);
10338
- const outputPath = path53.join(outputDir, `${manifest.name}.harness-constraints.json`);
10670
+ const outputDir = path54.resolve(options.output);
10671
+ const outputPath = path54.join(outputDir, `${manifest.name}.harness-constraints.json`);
10339
10672
  const writeResult = await writeConfig(outputPath, bundle);
10340
10673
  if (!writeResult.ok) {
10341
10674
  logger.error(`Failed to write bundle: ${writeResult.error.message}`);
@@ -10344,28 +10677,28 @@ Create a constraints.yaml in your project root to define what to share.`
10344
10677
  logger.success(`Bundle written to ${outputPath}`);
10345
10678
  }
10346
10679
  function createShareCommand() {
10347
- return new Command87("share").description("Extract and publish a constraints bundle from constraints.yaml").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory for the bundle", ".").action(async (projectPath, options) => {
10680
+ return new Command89("share").description("Extract and publish a constraints bundle from constraints.yaml").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory for the bundle", ".").action(async (projectPath, options) => {
10348
10681
  await runShareAction(projectPath, options);
10349
10682
  });
10350
10683
  }
10351
10684
 
10352
10685
  // src/commands/skill/index.ts
10353
- import { Command as Command95 } from "commander";
10686
+ import { Command as Command97 } from "commander";
10354
10687
 
10355
10688
  // src/commands/skill/list.ts
10356
- import { Command as Command88 } from "commander";
10357
- import * as fs36 from "fs";
10358
- import * as path54 from "path";
10689
+ import { Command as Command90 } from "commander";
10690
+ import * as fs37 from "fs";
10691
+ import * as path55 from "path";
10359
10692
  import { parse } from "yaml";
10360
10693
  function scanDirectory(dirPath, source) {
10361
- if (!fs36.existsSync(dirPath)) return [];
10362
- const entries = fs36.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
10694
+ if (!fs37.existsSync(dirPath)) return [];
10695
+ const entries = fs37.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
10363
10696
  const skills = [];
10364
10697
  for (const name of entries) {
10365
- const yamlPath = path54.join(dirPath, name, "skill.yaml");
10366
- if (!fs36.existsSync(yamlPath)) continue;
10698
+ const yamlPath = path55.join(dirPath, name, "skill.yaml");
10699
+ if (!fs37.existsSync(yamlPath)) continue;
10367
10700
  try {
10368
- const raw = fs36.readFileSync(yamlPath, "utf-8");
10701
+ const raw = fs37.readFileSync(yamlPath, "utf-8");
10369
10702
  const parsed = parse(raw);
10370
10703
  const result = SkillMetadataSchema.safeParse(parsed);
10371
10704
  if (result.success) {
@@ -10383,10 +10716,10 @@ function scanDirectory(dirPath, source) {
10383
10716
  }
10384
10717
  function collectCommunitySkills(seen, allSkills) {
10385
10718
  const globalDir = resolveGlobalSkillsDir();
10386
- const skillsDir = path54.dirname(globalDir);
10387
- const communityBase = path54.join(skillsDir, "community");
10388
- const communityPlatformDir = path54.join(communityBase, "claude-code");
10389
- const lockfilePath = path54.join(communityBase, "skills-lock.json");
10719
+ const skillsDir = path55.dirname(globalDir);
10720
+ const communityBase = path55.join(skillsDir, "community");
10721
+ const communityPlatformDir = path55.join(communityBase, "claude-code");
10722
+ const lockfilePath = path55.join(communityBase, "skills-lock.json");
10390
10723
  const lockfile = readLockfile2(lockfilePath);
10391
10724
  const communitySkills = scanDirectory(communityPlatformDir, "community");
10392
10725
  for (const skill of communitySkills) {
@@ -10456,7 +10789,7 @@ function printSkillsVerbose(skills) {
10456
10789
  for (const s of skills) printSkillEntry(s);
10457
10790
  }
10458
10791
  function createListCommand3() {
10459
- return new Command88("list").description("List available skills").option("--installed", "Show only community-installed skills").option("--local", "Show only project-local skills").option("--all", "Show all skills (default)").action(async (opts, cmd) => {
10792
+ return new Command90("list").description("List available skills").option("--installed", "Show only community-installed skills").option("--local", "Show only project-local skills").option("--all", "Show all skills (default)").action(async (opts, cmd) => {
10460
10793
  const globalOpts = cmd.optsWithGlobals();
10461
10794
  const skills = collectSkills({ filter: resolveFilter(opts) });
10462
10795
  if (globalOpts.json) {
@@ -10471,9 +10804,9 @@ function createListCommand3() {
10471
10804
  }
10472
10805
 
10473
10806
  // src/commands/skill/run.ts
10474
- import { Command as Command89 } from "commander";
10475
- import * as fs37 from "fs";
10476
- import * as path55 from "path";
10807
+ import { Command as Command91 } from "commander";
10808
+ import * as fs38 from "fs";
10809
+ import * as path56 from "path";
10477
10810
  import { parse as parse2 } from "yaml";
10478
10811
 
10479
10812
  // src/skill/complexity.ts
@@ -10569,10 +10902,10 @@ ${options.principles}`);
10569
10902
 
10570
10903
  // src/commands/skill/run.ts
10571
10904
  function loadSkillMetadata(skillDir) {
10572
- const yamlPath = path55.join(skillDir, "skill.yaml");
10573
- if (!fs37.existsSync(yamlPath)) return null;
10905
+ const yamlPath = path56.join(skillDir, "skill.yaml");
10906
+ if (!fs38.existsSync(yamlPath)) return null;
10574
10907
  try {
10575
- const result = SkillMetadataSchema.safeParse(parse2(fs37.readFileSync(yamlPath, "utf-8")));
10908
+ const result = SkillMetadataSchema.safeParse(parse2(fs38.readFileSync(yamlPath, "utf-8")));
10576
10909
  return result.success ? result.data : null;
10577
10910
  } catch {
10578
10911
  return null;
@@ -10584,22 +10917,22 @@ function resolveComplexity(metadata, requested, projectPath) {
10584
10917
  return requested;
10585
10918
  }
10586
10919
  function loadPrinciples(projectPath) {
10587
- const principlesPath = path55.join(projectPath, "docs", "principles.md");
10588
- return fs37.existsSync(principlesPath) ? fs37.readFileSync(principlesPath, "utf-8") : void 0;
10920
+ const principlesPath = path56.join(projectPath, "docs", "principles.md");
10921
+ return fs38.existsSync(principlesPath) ? fs38.readFileSync(principlesPath, "utf-8") : void 0;
10589
10922
  }
10590
10923
  function readMostRecentFileInDir(dirPath) {
10591
- const files = fs37.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs37.statSync(path55.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
10592
- if (files.length > 0) return fs37.readFileSync(path55.join(dirPath, files[0].name), "utf-8");
10924
+ const files = fs38.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs38.statSync(path56.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
10925
+ if (files.length > 0) return fs38.readFileSync(path56.join(dirPath, files[0].name), "utf-8");
10593
10926
  return void 0;
10594
10927
  }
10595
10928
  function loadPriorState(metadata, projectPath) {
10596
10929
  if (!metadata?.state.persistent || metadata.state.files.length === 0) return void 0;
10597
10930
  for (const stateFilePath of metadata.state.files) {
10598
- const fullPath = path55.join(projectPath, stateFilePath);
10599
- if (!fs37.existsSync(fullPath)) continue;
10600
- const stat = fs37.statSync(fullPath);
10931
+ const fullPath = path56.join(projectPath, stateFilePath);
10932
+ if (!fs38.existsSync(fullPath)) continue;
10933
+ const stat = fs38.statSync(fullPath);
10601
10934
  if (stat.isDirectory()) return readMostRecentFileInDir(fullPath);
10602
- return fs37.readFileSync(fullPath, "utf-8");
10935
+ return fs38.readFileSync(fullPath, "utf-8");
10603
10936
  }
10604
10937
  return void 0;
10605
10938
  }
@@ -10619,9 +10952,9 @@ function resolvePhaseState(metadata, projectPath, phase) {
10619
10952
  }
10620
10953
  function appendProjectState(content, metadata, projectPath, hasPathOpt) {
10621
10954
  if (!metadata?.state.persistent || !hasPathOpt) return content;
10622
- const stateFile = path55.join(projectPath, ".harness", "state.json");
10623
- if (!fs37.existsSync(stateFile)) return content;
10624
- const stateContent = fs37.readFileSync(stateFile, "utf-8");
10955
+ const stateFile = path56.join(projectPath, ".harness", "state.json");
10956
+ if (!fs38.existsSync(stateFile)) return content;
10957
+ const stateContent = fs38.readFileSync(stateFile, "utf-8");
10625
10958
  return content + `
10626
10959
 
10627
10960
  ---
@@ -10633,14 +10966,14 @@ ${stateContent}
10633
10966
  }
10634
10967
  async function runSkill(name, opts) {
10635
10968
  const skillsDir = resolveSkillsDir();
10636
- const skillDir = path55.join(skillsDir, name);
10637
- if (!fs37.existsSync(skillDir)) {
10969
+ const skillDir = path56.join(skillsDir, name);
10970
+ if (!fs38.existsSync(skillDir)) {
10638
10971
  logger.error(`Skill not found: ${name}`);
10639
10972
  process.exit(ExitCode.ERROR);
10640
10973
  return;
10641
10974
  }
10642
10975
  const metadata = loadSkillMetadata(skillDir);
10643
- const projectPath = opts.path ? path55.resolve(opts.path) : process.cwd();
10976
+ const projectPath = opts.path ? path56.resolve(opts.path) : process.cwd();
10644
10977
  const complexity = resolveComplexity(
10645
10978
  metadata,
10646
10979
  opts.complexity ?? "standard",
@@ -10667,14 +11000,14 @@ async function runSkill(name, opts) {
10667
11000
  ...stateWarning !== void 0 && { stateWarning },
10668
11001
  ...opts.party !== void 0 && { party: opts.party }
10669
11002
  });
10670
- const skillMdPath = path55.join(skillDir, "SKILL.md");
10671
- if (!fs37.existsSync(skillMdPath)) {
11003
+ const skillMdPath = path56.join(skillDir, "SKILL.md");
11004
+ if (!fs38.existsSync(skillMdPath)) {
10672
11005
  logger.error(`SKILL.md not found for skill: ${name}`);
10673
11006
  process.exit(ExitCode.ERROR);
10674
11007
  return;
10675
11008
  }
10676
11009
  const content = appendProjectState(
10677
- fs37.readFileSync(skillMdPath, "utf-8"),
11010
+ fs38.readFileSync(skillMdPath, "utf-8"),
10678
11011
  metadata,
10679
11012
  projectPath,
10680
11013
  !!opts.path
@@ -10685,16 +11018,16 @@ async function runSkill(name, opts) {
10685
11018
  process.exit(ExitCode.SUCCESS);
10686
11019
  }
10687
11020
  function createRunCommand3() {
10688
- return new Command89("run").description("Run a skill (outputs SKILL.md content with context preamble)").argument("<name>", "Skill name (e.g., harness-tdd)").option("--path <path>", "Project root path for context injection").option("--complexity <level>", "Rigor level: fast, standard, thorough", "standard").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").option(
11021
+ return new Command91("run").description("Run a skill (outputs SKILL.md content with context preamble)").argument("<name>", "Skill name (e.g., harness-tdd)").option("--path <path>", "Project root path for context injection").option("--complexity <level>", "Rigor level: fast, standard, thorough", "standard").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").option(
10689
11022
  "--backend <name>",
10690
11023
  "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
10691
11024
  ).action(async (name, opts) => runSkill(name, opts));
10692
11025
  }
10693
11026
 
10694
11027
  // src/commands/skill/validate.ts
10695
- import { Command as Command90 } from "commander";
10696
- import * as fs38 from "fs";
10697
- import * as path56 from "path";
11028
+ import { Command as Command92 } from "commander";
11029
+ import * as fs39 from "fs";
11030
+ import * as path57 from "path";
10698
11031
  import { parse as parse3 } from "yaml";
10699
11032
  var BEHAVIORAL_REQUIRED_SECTIONS = [
10700
11033
  "## When to Use",
@@ -10706,11 +11039,11 @@ var BEHAVIORAL_REQUIRED_SECTIONS = [
10706
11039
  ];
10707
11040
  var KNOWLEDGE_REQUIRED_SECTIONS = ["## Instructions"];
10708
11041
  function validateSkillMd(name, skillMdPath, skillType, errors) {
10709
- if (!fs38.existsSync(skillMdPath)) {
11042
+ if (!fs39.existsSync(skillMdPath)) {
10710
11043
  errors.push(`${name}: missing SKILL.md`);
10711
11044
  return;
10712
11045
  }
10713
- const mdContent = fs38.readFileSync(skillMdPath, "utf-8");
11046
+ const mdContent = fs39.readFileSync(skillMdPath, "utf-8");
10714
11047
  if (!mdContent.trim().startsWith("# ")) {
10715
11048
  errors.push(`${name}/SKILL.md: must start with an h1 heading`);
10716
11049
  }
@@ -10735,20 +11068,20 @@ function validateSkillMd(name, skillMdPath, skillType, errors) {
10735
11068
  }
10736
11069
  }
10737
11070
  function validateSkillEntry(name, skillsDir, errors) {
10738
- const skillDir = path56.join(skillsDir, name);
10739
- const yamlPath = path56.join(skillDir, "skill.yaml");
10740
- if (!fs38.existsSync(yamlPath)) {
11071
+ const skillDir = path57.join(skillsDir, name);
11072
+ const yamlPath = path57.join(skillDir, "skill.yaml");
11073
+ if (!fs39.existsSync(yamlPath)) {
10741
11074
  errors.push(`${name}: missing skill.yaml`);
10742
11075
  return false;
10743
11076
  }
10744
11077
  try {
10745
- const raw = fs38.readFileSync(yamlPath, "utf-8");
11078
+ const raw = fs39.readFileSync(yamlPath, "utf-8");
10746
11079
  const result = SkillMetadataSchema.safeParse(parse3(raw));
10747
11080
  if (!result.success) {
10748
11081
  errors.push(`${name}/skill.yaml: ${result.error.message}`);
10749
11082
  return false;
10750
11083
  }
10751
- validateSkillMd(name, path56.join(skillDir, "SKILL.md"), result.data.type, errors);
11084
+ validateSkillMd(name, path57.join(skillDir, "SKILL.md"), result.data.type, errors);
10752
11085
  return true;
10753
11086
  } catch (e) {
10754
11087
  errors.push(`${name}: parse error \u2014 ${e instanceof Error ? e.message : String(e)}`);
@@ -10756,15 +11089,15 @@ function validateSkillEntry(name, skillsDir, errors) {
10756
11089
  }
10757
11090
  }
10758
11091
  function createValidateCommand2() {
10759
- return new Command90("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
11092
+ return new Command92("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
10760
11093
  const globalOpts = cmd.optsWithGlobals();
10761
11094
  const skillsDir = resolveSkillsDir();
10762
- if (!fs38.existsSync(skillsDir)) {
11095
+ if (!fs39.existsSync(skillsDir)) {
10763
11096
  logger.info("No skills directory found.");
10764
11097
  process.exit(ExitCode.SUCCESS);
10765
11098
  return;
10766
11099
  }
10767
- const entries = fs38.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
11100
+ const entries = fs39.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
10768
11101
  const errors = [];
10769
11102
  let validated = 0;
10770
11103
  for (const name of entries) {
@@ -10786,24 +11119,24 @@ function createValidateCommand2() {
10786
11119
  }
10787
11120
 
10788
11121
  // src/commands/skill/info.ts
10789
- import { Command as Command91 } from "commander";
10790
- import * as fs39 from "fs";
10791
- import * as path57 from "path";
11122
+ import { Command as Command93 } from "commander";
11123
+ import * as fs40 from "fs";
11124
+ import * as path58 from "path";
10792
11125
  import { parse as parse4 } from "yaml";
10793
11126
  function loadSkillMetadata2(name) {
10794
11127
  const skillsDir = resolveSkillsDir();
10795
- const skillDir = path57.join(skillsDir, name);
10796
- if (!fs39.existsSync(skillDir)) {
11128
+ const skillDir = path58.join(skillsDir, name);
11129
+ if (!fs40.existsSync(skillDir)) {
10797
11130
  logger.error(`Skill not found: ${name}`);
10798
11131
  return { ok: false, exitCode: ExitCode.ERROR };
10799
11132
  }
10800
- const yamlPath = path57.join(skillDir, "skill.yaml");
10801
- if (!fs39.existsSync(yamlPath)) {
11133
+ const yamlPath = path58.join(skillDir, "skill.yaml");
11134
+ if (!fs40.existsSync(yamlPath)) {
10802
11135
  logger.error(`skill.yaml not found for skill: ${name}`);
10803
11136
  return { ok: false, exitCode: ExitCode.ERROR };
10804
11137
  }
10805
11138
  try {
10806
- const raw = fs39.readFileSync(yamlPath, "utf-8");
11139
+ const raw = fs40.readFileSync(yamlPath, "utf-8");
10807
11140
  const parsed = parse4(raw);
10808
11141
  const result = SkillMetadataSchema.safeParse(parsed);
10809
11142
  if (!result.success) {
@@ -10832,7 +11165,7 @@ function printSkillInfo(skill) {
10832
11165
  console.log(`Persistent: ${skill.state.persistent}`);
10833
11166
  }
10834
11167
  function createInfoCommand() {
10835
- return new Command91("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
11168
+ return new Command93("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
10836
11169
  const globalOpts = cmd.optsWithGlobals();
10837
11170
  const loaded = loadSkillMetadata2(name);
10838
11171
  if (!loaded.ok) {
@@ -10849,7 +11182,7 @@ function createInfoCommand() {
10849
11182
  }
10850
11183
 
10851
11184
  // src/commands/skill/search.ts
10852
- import { Command as Command92 } from "commander";
11185
+ import { Command as Command94 } from "commander";
10853
11186
  async function runSearch(query, opts) {
10854
11187
  const results = await searchNpmRegistry(query, opts.registry);
10855
11188
  return results.filter((r) => {
@@ -10894,15 +11227,15 @@ async function runSearchAction(query, opts, globalOpts) {
10894
11227
  }
10895
11228
  }
10896
11229
  function createSearchCommand2() {
10897
- return new Command92("search").description("Search for community skills on the @harness-skills registry").argument("<query>", "Search query").option("--platform <platform>", "Filter by platform (e.g., claude-code)").option("--trigger <trigger>", "Filter by trigger type (e.g., manual, automatic)").option("--registry <url>", "Use a custom npm registry URL").action(async (query, opts, cmd) => {
11230
+ return new Command94("search").description("Search for community skills on the @harness-skills registry").argument("<query>", "Search query").option("--platform <platform>", "Filter by platform (e.g., claude-code)").option("--trigger <trigger>", "Filter by trigger type (e.g., manual, automatic)").option("--registry <url>", "Use a custom npm registry URL").action(async (query, opts, cmd) => {
10898
11231
  await runSearchAction(query, opts, cmd.optsWithGlobals());
10899
11232
  });
10900
11233
  }
10901
11234
 
10902
11235
  // src/commands/skill/create.ts
10903
- import { Command as Command93 } from "commander";
10904
- import * as path58 from "path";
10905
- import * as fs40 from "fs";
11236
+ import { Command as Command95 } from "commander";
11237
+ import * as path59 from "path";
11238
+ import * as fs41 from "fs";
10906
11239
  import YAML from "yaml";
10907
11240
  var KEBAB_CASE_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
10908
11241
  function buildReadme(name, description) {
@@ -10986,22 +11319,22 @@ function runCreate(name, opts) {
10986
11319
  if (!KEBAB_CASE_RE.test(name)) {
10987
11320
  throw new Error(`Invalid skill name "${name}". Must be kebab-case (e.g., my-skill).`);
10988
11321
  }
10989
- const baseDir = opts.outputDir ?? path58.join(process.cwd(), "agents", "skills", "claude-code");
10990
- const skillDir = path58.join(baseDir, name);
10991
- if (fs40.existsSync(skillDir)) {
11322
+ const baseDir = opts.outputDir ?? path59.join(process.cwd(), "agents", "skills", "claude-code");
11323
+ const skillDir = path59.join(baseDir, name);
11324
+ if (fs41.existsSync(skillDir)) {
10992
11325
  throw new Error(`Skill directory already exists: ${skillDir}`);
10993
11326
  }
10994
- fs40.mkdirSync(skillDir, { recursive: true });
11327
+ fs41.mkdirSync(skillDir, { recursive: true });
10995
11328
  const description = opts.description || `A community skill: ${name}`;
10996
11329
  const skillYaml = buildSkillYaml(name, opts);
10997
- const skillYamlPath = path58.join(skillDir, "skill.yaml");
10998
- fs40.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
11330
+ const skillYamlPath = path59.join(skillDir, "skill.yaml");
11331
+ fs41.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
10999
11332
  const skillMd = buildSkillMd(name, description);
11000
- const skillMdPath = path58.join(skillDir, "SKILL.md");
11001
- fs40.writeFileSync(skillMdPath, skillMd);
11333
+ const skillMdPath = path59.join(skillDir, "SKILL.md");
11334
+ fs41.writeFileSync(skillMdPath, skillMd);
11002
11335
  const readme = buildReadme(name, description);
11003
- const readmePath = path58.join(skillDir, "README.md");
11004
- fs40.writeFileSync(readmePath, readme);
11336
+ const readmePath = path59.join(skillDir, "README.md");
11337
+ fs41.writeFileSync(readmePath, readme);
11005
11338
  return {
11006
11339
  name,
11007
11340
  directory: skillDir,
@@ -11015,12 +11348,12 @@ function printCreateResult(name, result) {
11015
11348
  }
11016
11349
  logger.info(`
11017
11350
  Next steps:`);
11018
- logger.info(` 1. Edit ${path58.join(result.directory, "SKILL.md")} with your skill content`);
11351
+ logger.info(` 1. Edit ${path59.join(result.directory, "SKILL.md")} with your skill content`);
11019
11352
  logger.info(` 2. Run: harness skill validate ${name}`);
11020
11353
  logger.info(` 3. Run: harness skills publish`);
11021
11354
  }
11022
11355
  function createCreateCommand() {
11023
- return new Command93("create").description("Scaffold a new community skill").argument("<name>", "Skill name (kebab-case)").option("--description <desc>", "Skill description").option("--type <type>", "Skill type: rigid or flexible", "flexible").option("--platforms <platforms>", "Comma-separated platforms (default: claude-code)").option("--triggers <triggers>", "Comma-separated triggers (default: manual)").option("--output-dir <dir>", "Output directory (default: agents/skills/claude-code/)").action(async (name, opts, cmd) => {
11356
+ return new Command95("create").description("Scaffold a new community skill").argument("<name>", "Skill name (kebab-case)").option("--description <desc>", "Skill description").option("--type <type>", "Skill type: rigid or flexible", "flexible").option("--platforms <platforms>", "Comma-separated platforms (default: claude-code)").option("--triggers <triggers>", "Comma-separated triggers (default: manual)").option("--output-dir <dir>", "Output directory (default: agents/skills/claude-code/)").action(async (name, opts, cmd) => {
11024
11357
  const globalOpts = cmd.optsWithGlobals();
11025
11358
  try {
11026
11359
  const result = runCreate(name, {
@@ -11043,26 +11376,26 @@ function createCreateCommand() {
11043
11376
  }
11044
11377
 
11045
11378
  // src/commands/skill/publish.ts
11046
- import { Command as Command94 } from "commander";
11047
- import * as fs42 from "fs";
11048
- import * as path60 from "path";
11379
+ import { Command as Command96 } from "commander";
11380
+ import * as fs43 from "fs";
11381
+ import * as path61 from "path";
11049
11382
  import { execFileSync as execFileSync6 } from "child_process";
11050
11383
 
11051
11384
  // src/registry/validator.ts
11052
- import * as fs41 from "fs";
11053
- import * as path59 from "path";
11385
+ import * as fs42 from "fs";
11386
+ import * as path60 from "path";
11054
11387
  import { parse as parse5 } from "yaml";
11055
11388
  import semver4 from "semver";
11056
11389
  async function validateForPublish(skillDir, registryUrl) {
11057
11390
  const errors = [];
11058
- const skillYamlPath = path59.join(skillDir, "skill.yaml");
11059
- if (!fs41.existsSync(skillYamlPath)) {
11391
+ const skillYamlPath = path60.join(skillDir, "skill.yaml");
11392
+ if (!fs42.existsSync(skillYamlPath)) {
11060
11393
  errors.push("skill.yaml not found. Create one with: harness skill create <name>");
11061
11394
  return { valid: false, errors };
11062
11395
  }
11063
11396
  let skillMeta;
11064
11397
  try {
11065
- const raw = fs41.readFileSync(skillYamlPath, "utf-8");
11398
+ const raw = fs42.readFileSync(skillYamlPath, "utf-8");
11066
11399
  const parsed = parse5(raw);
11067
11400
  const result = SkillMetadataSchema.safeParse(parsed);
11068
11401
  if (!result.success) {
@@ -11084,11 +11417,11 @@ async function validateForPublish(skillDir, registryUrl) {
11084
11417
  if (!skillMeta.triggers || skillMeta.triggers.length === 0) {
11085
11418
  errors.push("At least one trigger is required. Add triggers to skill.yaml.");
11086
11419
  }
11087
- const skillMdPath = path59.join(skillDir, "SKILL.md");
11088
- if (!fs41.existsSync(skillMdPath)) {
11420
+ const skillMdPath = path60.join(skillDir, "SKILL.md");
11421
+ if (!fs42.existsSync(skillMdPath)) {
11089
11422
  errors.push("SKILL.md not found. Create it with content describing your skill.");
11090
11423
  } else {
11091
- const content = fs41.readFileSync(skillMdPath, "utf-8");
11424
+ const content = fs42.readFileSync(skillMdPath, "utf-8");
11092
11425
  if (!content.includes("## When to Use")) {
11093
11426
  errors.push('SKILL.md must contain a "## When to Use" section.');
11094
11427
  }
@@ -11168,11 +11501,11 @@ ${errorList}`);
11168
11501
  }
11169
11502
  const meta = validation.skillMeta;
11170
11503
  const pkg = derivePackageJson(meta);
11171
- const pkgPath = path60.join(skillDir, "package.json");
11172
- fs42.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
11173
- const readmePath = path60.join(skillDir, "README.md");
11174
- if (!fs42.existsSync(readmePath)) {
11175
- const skillMdContent = fs42.readFileSync(path60.join(skillDir, "SKILL.md"), "utf-8");
11504
+ const pkgPath = path61.join(skillDir, "package.json");
11505
+ fs43.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
11506
+ const readmePath = path61.join(skillDir, "README.md");
11507
+ if (!fs43.existsSync(readmePath)) {
11508
+ const skillMdContent = fs43.readFileSync(path61.join(skillDir, "SKILL.md"), "utf-8");
11176
11509
  const readme = `# ${pkg.name}
11177
11510
 
11178
11511
  ${meta.description}
@@ -11186,7 +11519,7 @@ harness install ${meta.name}
11186
11519
  ---
11187
11520
 
11188
11521
  ${skillMdContent}`;
11189
- fs42.writeFileSync(readmePath, readme);
11522
+ fs43.writeFileSync(readmePath, readme);
11190
11523
  }
11191
11524
  if (opts.dryRun) {
11192
11525
  return {
@@ -11212,7 +11545,7 @@ ${skillMdContent}`;
11212
11545
  };
11213
11546
  }
11214
11547
  function createPublishCommand() {
11215
- return new Command94("publish").description("Validate and publish a skill to @harness-skills on npm").option("--dry-run", "Run validation and generate package.json without publishing").option("--dir <dir>", "Skill directory (default: current directory)").option("--registry <url>", "Use a custom npm registry URL").action(async (opts, cmd) => {
11548
+ return new Command96("publish").description("Validate and publish a skill to @harness-skills on npm").option("--dry-run", "Run validation and generate package.json without publishing").option("--dir <dir>", "Skill directory (default: current directory)").option("--registry <url>", "Use a custom npm registry URL").action(async (opts, cmd) => {
11216
11549
  const globalOpts = cmd.optsWithGlobals();
11217
11550
  const skillDir = opts.dir || process.cwd();
11218
11551
  try {
@@ -11237,7 +11570,7 @@ function createPublishCommand() {
11237
11570
 
11238
11571
  // src/commands/skill/index.ts
11239
11572
  function createSkillCommand() {
11240
- const command = new Command95("skill").description("Skill management commands");
11573
+ const command = new Command97("skill").description("Skill management commands");
11241
11574
  command.addCommand(createListCommand3());
11242
11575
  command.addCommand(createRunCommand3());
11243
11576
  command.addCommand(createValidateCommand2());
@@ -11250,9 +11583,9 @@ function createSkillCommand() {
11250
11583
 
11251
11584
  // src/commands/snapshot.ts
11252
11585
  init_dist3();
11253
- import { Command as Command96 } from "commander";
11586
+ import { Command as Command98 } from "commander";
11254
11587
  import { execSync as execSync5 } from "child_process";
11255
- import chalk15 from "chalk";
11588
+ import chalk16 from "chalk";
11256
11589
  function getCommitHash3(cwd) {
11257
11590
  try {
11258
11591
  return execSync5("git rev-parse --short HEAD", { cwd, encoding: "utf-8" }).toString().trim();
@@ -11277,9 +11610,9 @@ function formatDelta(delta) {
11277
11610
  function directionSymbol(direction) {
11278
11611
  switch (direction) {
11279
11612
  case "improving":
11280
- return chalk15.green("improving");
11613
+ return chalk16.green("improving");
11281
11614
  case "declining":
11282
- return chalk15.red("declining");
11615
+ return chalk16.red("declining");
11283
11616
  case "stable":
11284
11617
  return "=";
11285
11618
  }
@@ -11432,7 +11765,7 @@ function registerListCommand(parent) {
11432
11765
  });
11433
11766
  }
11434
11767
  function createSnapshotCommand() {
11435
- const command = new Command96("snapshot").description("Architecture timeline snapshot commands");
11768
+ const command = new Command98("snapshot").description("Architecture timeline snapshot commands");
11436
11769
  registerCaptureCommand(command);
11437
11770
  registerTrendsCommand(command);
11438
11771
  registerListCommand(command);
@@ -11440,9 +11773,9 @@ function createSnapshotCommand() {
11440
11773
  }
11441
11774
 
11442
11775
  // src/commands/spec-craft.ts
11443
- import { Command as Command97 } from "commander";
11776
+ import { Command as Command99 } from "commander";
11444
11777
  function createSpecCraftCommand() {
11445
- return new Command97("spec-craft").description(
11778
+ return new Command99("spec-craft").description(
11446
11779
  "LLM-judgment critique of spec quality (proposals + ADRs). Second craft-pipeline ceiling skill; 7 seed rubrics from the spec-quality canon. Per-section critique."
11447
11780
  ).option("-f, --files <files...>", "Optional spec file/glob scope").option("-k, --kinds <kinds...>", "Restrict to proposal / adr (default: both)").option("-s, --sections <names...>", "Restrict to specific canonical section names").option("--max-files <n>", "Cap doc count (default: 50)").option("--max-sections-per-file <n>", "Cap per-doc section critique (default: 10)").action(async (opts, cmd) => {
11448
11781
  const globalOpts = cmd.optsWithGlobals();
@@ -11490,10 +11823,10 @@ function printResult6(result, mode, _formatter) {
11490
11823
  list.push(f);
11491
11824
  byFile.set(f.target.file, list);
11492
11825
  }
11493
- for (const [file, fs47] of byFile) {
11826
+ for (const [file, fs48] of byFile) {
11494
11827
  console.log(`
11495
11828
  ${file}`);
11496
- for (const f of fs47) {
11829
+ for (const f of fs48) {
11497
11830
  console.log(
11498
11831
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ## ${f.target.section}:${f.target.line}`
11499
11832
  );
@@ -11509,12 +11842,12 @@ ${file}`);
11509
11842
  }
11510
11843
 
11511
11844
  // src/commands/state/index.ts
11512
- import { Command as Command102 } from "commander";
11845
+ import { Command as Command104 } from "commander";
11513
11846
 
11514
11847
  // src/commands/state/show.ts
11515
11848
  init_dist3();
11516
- import { Command as Command98 } from "commander";
11517
- import * as path61 from "path";
11849
+ import { Command as Command100 } from "commander";
11850
+ import * as path62 from "path";
11518
11851
  function printStateText(state, stream) {
11519
11852
  if (stream) console.log(`Stream: ${stream}`);
11520
11853
  console.log(`Schema Version: ${state.schemaVersion}`);
@@ -11538,9 +11871,9 @@ function printStateProgress(progress) {
11538
11871
  }
11539
11872
  }
11540
11873
  function createShowCommand() {
11541
- return new Command98("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
11874
+ return new Command100("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
11542
11875
  const globalOpts = cmd.optsWithGlobals();
11543
- const result = await loadState(path61.resolve(opts.path), opts.stream);
11876
+ const result = await loadState(path62.resolve(opts.path), opts.stream);
11544
11877
  if (!result.ok) {
11545
11878
  logger.error(result.error.message);
11546
11879
  process.exit(ExitCode.ERROR);
@@ -11556,9 +11889,9 @@ function createShowCommand() {
11556
11889
 
11557
11890
  // src/commands/state/reset.ts
11558
11891
  init_dist3();
11559
- import { Command as Command99 } from "commander";
11560
- import * as fs43 from "fs";
11561
- import * as path62 from "path";
11892
+ import { Command as Command101 } from "commander";
11893
+ import * as fs44 from "fs";
11894
+ import * as path63 from "path";
11562
11895
  import * as readline3 from "readline";
11563
11896
  async function resolveStatePath(projectPath, stream) {
11564
11897
  if (stream) {
@@ -11567,9 +11900,9 @@ async function resolveStatePath(projectPath, stream) {
11567
11900
  logger.error(streamResult.error.message);
11568
11901
  process.exit(ExitCode.ERROR);
11569
11902
  }
11570
- return path62.join(streamResult.value, "state.json");
11903
+ return path63.join(streamResult.value, "state.json");
11571
11904
  }
11572
- return path62.join(projectPath, ".harness", "state.json");
11905
+ return path63.join(projectPath, ".harness", "state.json");
11573
11906
  }
11574
11907
  async function confirmReset() {
11575
11908
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
@@ -11580,9 +11913,9 @@ async function confirmReset() {
11580
11913
  return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
11581
11914
  }
11582
11915
  async function runReset(opts) {
11583
- const projectPath = path62.resolve(opts.path);
11916
+ const projectPath = path63.resolve(opts.path);
11584
11917
  const statePath = await resolveStatePath(projectPath, opts.stream);
11585
- if (!fs43.existsSync(statePath)) {
11918
+ if (!fs44.existsSync(statePath)) {
11586
11919
  logger.info("No state file found. Nothing to reset.");
11587
11920
  process.exit(ExitCode.SUCCESS);
11588
11921
  }
@@ -11591,7 +11924,7 @@ async function runReset(opts) {
11591
11924
  process.exit(ExitCode.SUCCESS);
11592
11925
  }
11593
11926
  try {
11594
- fs43.unlinkSync(statePath);
11927
+ fs44.unlinkSync(statePath);
11595
11928
  logger.success("Project state reset.");
11596
11929
  } catch (e) {
11597
11930
  logger.error(`Failed to reset state: ${e instanceof Error ? e.message : String(e)}`);
@@ -11600,16 +11933,16 @@ async function runReset(opts) {
11600
11933
  process.exit(ExitCode.SUCCESS);
11601
11934
  }
11602
11935
  function createResetCommand() {
11603
- return new Command99("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
11936
+ return new Command101("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
11604
11937
  }
11605
11938
 
11606
11939
  // src/commands/state/learn.ts
11607
11940
  init_dist3();
11608
- import { Command as Command100 } from "commander";
11609
- import * as path63 from "path";
11941
+ import { Command as Command102 } from "commander";
11942
+ import * as path64 from "path";
11610
11943
  function createLearnCommand() {
11611
- return new Command100("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (message, opts, _cmd) => {
11612
- const projectPath = path63.resolve(opts.path);
11944
+ return new Command102("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (message, opts, _cmd) => {
11945
+ const projectPath = path64.resolve(opts.path);
11613
11946
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
11614
11947
  if (!result.ok) {
11615
11948
  logger.error(result.error.message);
@@ -11623,10 +11956,10 @@ function createLearnCommand() {
11623
11956
 
11624
11957
  // src/commands/state/streams.ts
11625
11958
  init_dist3();
11626
- import { Command as Command101 } from "commander";
11627
- import * as path64 from "path";
11959
+ import { Command as Command103 } from "commander";
11960
+ import * as path65 from "path";
11628
11961
  async function runListStreams(opts, globalOpts) {
11629
- const projectPath = path64.resolve(opts.path);
11962
+ const projectPath = path65.resolve(opts.path);
11630
11963
  const indexResult = await loadStreamIndex(projectPath);
11631
11964
  const result = await listStreams(projectPath);
11632
11965
  if (!result.ok) {
@@ -11647,7 +11980,7 @@ async function runListStreams(opts, globalOpts) {
11647
11980
  process.exit(ExitCode.SUCCESS);
11648
11981
  }
11649
11982
  async function runCreateStream(name, opts) {
11650
- const result = await createStream(path64.resolve(opts.path), name, opts.branch);
11983
+ const result = await createStream(path65.resolve(opts.path), name, opts.branch);
11651
11984
  if (!result.ok) {
11652
11985
  logger.error(result.error.message);
11653
11986
  process.exit(ExitCode.ERROR);
@@ -11656,7 +11989,7 @@ async function runCreateStream(name, opts) {
11656
11989
  process.exit(ExitCode.SUCCESS);
11657
11990
  }
11658
11991
  async function runArchiveStream(name, opts) {
11659
- const result = await archiveStream(path64.resolve(opts.path), name);
11992
+ const result = await archiveStream(path65.resolve(opts.path), name);
11660
11993
  if (!result.ok) {
11661
11994
  logger.error(result.error.message);
11662
11995
  process.exit(ExitCode.ERROR);
@@ -11665,7 +11998,7 @@ async function runArchiveStream(name, opts) {
11665
11998
  process.exit(ExitCode.SUCCESS);
11666
11999
  }
11667
12000
  async function runActivateStream(name, opts) {
11668
- const result = await setActiveStream(path64.resolve(opts.path), name);
12001
+ const result = await setActiveStream(path65.resolve(opts.path), name);
11669
12002
  if (!result.ok) {
11670
12003
  logger.error(result.error.message);
11671
12004
  process.exit(ExitCode.ERROR);
@@ -11674,7 +12007,7 @@ async function runActivateStream(name, opts) {
11674
12007
  process.exit(ExitCode.SUCCESS);
11675
12008
  }
11676
12009
  function createStreamsCommand() {
11677
- const command = new Command101("streams").description("Manage state streams");
12010
+ const command = new Command103("streams").description("Manage state streams");
11678
12011
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
11679
12012
  command.command("create <name>").description("Create a new stream").option("--path <path>", "Project root path", ".").option("--branch <branch>", "Associate with a git branch").action(async (name, opts) => runCreateStream(name, opts));
11680
12013
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -11684,7 +12017,7 @@ function createStreamsCommand() {
11684
12017
 
11685
12018
  // src/commands/state/index.ts
11686
12019
  function createStateCommand() {
11687
- const command = new Command102("state").description("Project state management commands");
12020
+ const command = new Command104("state").description("Project state management commands");
11688
12021
  command.addCommand(createShowCommand());
11689
12022
  command.addCommand(createResetCommand());
11690
12023
  command.addCommand(createLearnCommand());
@@ -11693,9 +12026,9 @@ function createStateCommand() {
11693
12026
  }
11694
12027
 
11695
12028
  // src/commands/sync-analyses.ts
11696
- import * as fs44 from "fs";
11697
- import * as path65 from "path";
11698
- import { Command as Command103 } from "commander";
12029
+ import * as fs45 from "fs";
12030
+ import * as path66 from "path";
12031
+ import { Command as Command105 } from "commander";
11699
12032
  init_dist3();
11700
12033
  function isValidRecord(record) {
11701
12034
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -11721,7 +12054,7 @@ function extractAnalysisFromComments(comments) {
11721
12054
  return null;
11722
12055
  }
11723
12056
  function bootstrapTrackerCommand2(opts, verb) {
11724
- const projectPath = path65.resolve(opts.dir);
12057
+ const projectPath = path66.resolve(opts.dir);
11725
12058
  const trackerConfig = loadTrackerSyncConfig(projectPath);
11726
12059
  if (!trackerConfig) {
11727
12060
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -11733,8 +12066,8 @@ function bootstrapTrackerCommand2(opts, verb) {
11733
12066
  );
11734
12067
  return null;
11735
12068
  }
11736
- const projectEnvPath = path65.join(projectPath, ".env");
11737
- if (fs44.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
12069
+ const projectEnvPath = path66.join(projectPath, ".env");
12070
+ if (fs45.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
11738
12071
  __require("dotenv").config({ path: projectEnvPath });
11739
12072
  }
11740
12073
  const token = process.env.GITHUB_TOKEN;
@@ -11764,13 +12097,13 @@ async function loadRoadmapFeatures(projectPath) {
11764
12097
  }
11765
12098
  return r.value.features.filter((f) => !!f.externalId).map((f) => ({ name: f.name, externalId: f.externalId }));
11766
12099
  }
11767
- const roadmapFile = path65.join(projectPath, "docs", "roadmap.md");
11768
- if (!fs44.existsSync(roadmapFile)) {
12100
+ const roadmapFile = path66.join(projectPath, "docs", "roadmap.md");
12101
+ if (!fs45.existsSync(roadmapFile)) {
11769
12102
  logger.error("No docs/roadmap.md found. Cannot discover features with externalIds.");
11770
12103
  return null;
11771
12104
  }
11772
12105
  const { parseRoadmap: parseRoadmap2 } = (init_dist3(), __toCommonJS(dist_exports));
11773
- const roadmapParsed = parseRoadmap2(fs44.readFileSync(roadmapFile, "utf-8"));
12106
+ const roadmapParsed = parseRoadmap2(fs45.readFileSync(roadmapFile, "utf-8"));
11774
12107
  if (!roadmapParsed.ok) {
11775
12108
  logger.error("Failed to parse docs/roadmap.md");
11776
12109
  return null;
@@ -11821,9 +12154,9 @@ async function runSyncAnalyses(opts) {
11821
12154
  return;
11822
12155
  }
11823
12156
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
11824
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-XIJWWQ5N.js");
12157
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-JCFK263L.js");
11825
12158
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
11826
- const archive = new AnalysisArchive(path65.join(projectPath, ".harness", "analyses"));
12159
+ const archive = new AnalysisArchive(path66.join(projectPath, ".harness", "analyses"));
11827
12160
  const publishedIndex = loadPublishedIndex2(projectPath);
11828
12161
  const { syncedCount, skippedCount, warnCount } = await syncFeatureAnalyses(
11829
12162
  features,
@@ -11843,7 +12176,7 @@ async function runSyncAnalyses(opts) {
11843
12176
  }
11844
12177
  }
11845
12178
  function createSyncAnalysesCommand() {
11846
- const command = new Command103("sync-analyses").description(
12179
+ const command = new Command105("sync-analyses").description(
11847
12180
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
11848
12181
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
11849
12182
  try {
@@ -11857,8 +12190,8 @@ function createSyncAnalysesCommand() {
11857
12190
  }
11858
12191
 
11859
12192
  // src/commands/sync-main.ts
11860
- import { Command as Command104 } from "commander";
11861
- import * as path66 from "path";
12193
+ import { Command as Command106 } from "commander";
12194
+ import * as path67 from "path";
11862
12195
  import {
11863
12196
  syncMain as defaultSyncMain
11864
12197
  } from "@harness-engineering/orchestrator";
@@ -11888,8 +12221,8 @@ function formatHuman2(r) {
11888
12221
  }
11889
12222
  }
11890
12223
  function createSyncMainCommand() {
11891
- return new Command104("sync-main").description("Fast-forward the local default branch from origin (no-op on conflict)").option("--json", "Emit a SyncMainResult JSON object", false).option("--path <path>", "Project root path", ".").action(async (opts) => {
11892
- const cwd = path66.resolve(opts.path ?? ".");
12224
+ return new Command106("sync-main").description("Fast-forward the local default branch from origin (no-op on conflict)").option("--json", "Emit a SyncMainResult JSON object", false).option("--path <path>", "Project root path", ".").action(async (opts) => {
12225
+ const cwd = path67.resolve(opts.path ?? ".");
11893
12226
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
11894
12227
  process.exit(exitCode);
11895
12228
  });
@@ -11897,7 +12230,7 @@ function createSyncMainCommand() {
11897
12230
 
11898
12231
  // src/commands/taint.ts
11899
12232
  init_dist3();
11900
- import { Command as Command105 } from "commander";
12233
+ import { Command as Command107 } from "commander";
11901
12234
  function getProjectRoot() {
11902
12235
  return process.cwd();
11903
12236
  }
@@ -11969,28 +12302,28 @@ function registerStatusCommand(taint) {
11969
12302
  });
11970
12303
  }
11971
12304
  function createTaintCommand() {
11972
- const taint = new Command105("taint").description("Manage sentinel session taint state");
12305
+ const taint = new Command107("taint").description("Manage sentinel session taint state");
11973
12306
  registerClearCommand(taint);
11974
12307
  registerStatusCommand(taint);
11975
12308
  return taint;
11976
12309
  }
11977
12310
 
11978
12311
  // src/commands/telemetry/index.ts
11979
- import { Command as Command109 } from "commander";
12312
+ import { Command as Command111 } from "commander";
11980
12313
 
11981
12314
  // src/commands/telemetry/identify.ts
11982
12315
  init_dist3();
11983
- import { Command as Command106 } from "commander";
11984
- import * as fs45 from "fs";
11985
- import * as path67 from "path";
12316
+ import { Command as Command108 } from "commander";
12317
+ import * as fs46 from "fs";
12318
+ import * as path68 from "path";
11986
12319
  function telemetryFilePath(cwd) {
11987
- return path67.join(cwd, ".harness", "telemetry.json");
12320
+ return path68.join(cwd, ".harness", "telemetry.json");
11988
12321
  }
11989
12322
  function writeTelemetryFile(cwd, data) {
11990
12323
  const filePath = telemetryFilePath(cwd);
11991
- const dir = path67.dirname(filePath);
11992
- fs45.mkdirSync(dir, { recursive: true });
11993
- fs45.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
12324
+ const dir = path68.dirname(filePath);
12325
+ fs46.mkdirSync(dir, { recursive: true });
12326
+ fs46.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
11994
12327
  }
11995
12328
  var IDENTITY_FIELDS = ["project", "team", "alias"];
11996
12329
  function applyIdentityFields(opts, identity) {
@@ -12004,7 +12337,7 @@ function printIdentity(identity) {
12004
12337
  }
12005
12338
  }
12006
12339
  function createIdentifyCommand() {
12007
- const cmd = new Command106("identify").description("Set or clear telemetry identity fields in .harness/telemetry.json").option("--project <name>", "Project name").option("--team <name>", "Team name").option("--alias <name>", "User alias").option("--clear", "Remove all identity fields").action((opts) => {
12340
+ const cmd = new Command108("identify").description("Set or clear telemetry identity fields in .harness/telemetry.json").option("--project <name>", "Project name").option("--team <name>", "Team name").option("--alias <name>", "User alias").option("--clear", "Remove all identity fields").action((opts) => {
12008
12341
  const cwd = process.cwd();
12009
12342
  if (opts.clear) {
12010
12343
  writeTelemetryFile(cwd, { identity: {} });
@@ -12029,7 +12362,7 @@ function createIdentifyCommand() {
12029
12362
 
12030
12363
  // src/commands/telemetry/status.ts
12031
12364
  init_dist3();
12032
- import { Command as Command107 } from "commander";
12365
+ import { Command as Command109 } from "commander";
12033
12366
  function gatherEnvOverrides() {
12034
12367
  const overrides = {};
12035
12368
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -12071,7 +12404,7 @@ function printHumanStatus(result) {
12071
12404
  printEnvOverrides(result.envOverrides);
12072
12405
  }
12073
12406
  function createStatusCommand() {
12074
- const cmd = new Command107("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
12407
+ const cmd = new Command109("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
12075
12408
  const cwd = process.cwd();
12076
12409
  const envOverrides = gatherEnvOverrides();
12077
12410
  const consent = resolveConsent(cwd, void 0);
@@ -12104,11 +12437,11 @@ function createStatusCommand() {
12104
12437
 
12105
12438
  // src/commands/telemetry/test.ts
12106
12439
  init_dist3();
12107
- import { Command as Command108 } from "commander";
12440
+ import { Command as Command110 } from "commander";
12108
12441
 
12109
12442
  // src/bin/command-telemetry.ts
12110
- import { existsSync as existsSync42, readFileSync as readFileSync32, mkdirSync as mkdirSync19, appendFileSync, writeFileSync as writeFileSync24 } from "fs";
12111
- import { join as join56, parse as parsePath, resolve as resolve43 } from "path";
12443
+ import { existsSync as existsSync43, readFileSync as readFileSync33, mkdirSync as mkdirSync19, appendFileSync, writeFileSync as writeFileSync25 } from "fs";
12444
+ import { join as join57, parse as parsePath, resolve as resolve43 } from "path";
12112
12445
  import { spawn as spawn2 } from "child_process";
12113
12446
  var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
12114
12447
  var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
@@ -12116,7 +12449,7 @@ function findProjectRoot(cwd) {
12116
12449
  let dir = resolve43(cwd);
12117
12450
  const { root } = parsePath(dir);
12118
12451
  while (dir !== root) {
12119
- if (existsSync42(join56(dir, "harness.config.json"))) return dir;
12452
+ if (existsSync43(join57(dir, "harness.config.json"))) return dir;
12120
12453
  dir = resolve43(dir, "..");
12121
12454
  }
12122
12455
  return cwd;
@@ -12154,7 +12487,7 @@ function resolveCommandName(cmd) {
12154
12487
  }
12155
12488
  function writeCommandRecordSync(cwd, command, duration, outcome) {
12156
12489
  try {
12157
- const metricsDir = join56(cwd, ".harness", "metrics");
12490
+ const metricsDir = join57(cwd, ".harness", "metrics");
12158
12491
  mkdirSync19(metricsDir, { recursive: true });
12159
12492
  const record = {
12160
12493
  skill: command,
@@ -12164,16 +12497,16 @@ function writeCommandRecordSync(cwd, command, duration, outcome) {
12164
12497
  outcome,
12165
12498
  phasesReached: []
12166
12499
  };
12167
- const adoptionFile = join56(metricsDir, "adoption.jsonl");
12500
+ const adoptionFile = join57(metricsDir, "adoption.jsonl");
12168
12501
  appendFileSync(adoptionFile, JSON.stringify(record) + "\n");
12169
12502
  } catch {
12170
12503
  }
12171
12504
  }
12172
12505
  function isTelemetryDisabledByConfig(cwd) {
12173
- const configPath = join56(cwd, "harness.config.json");
12174
- if (!existsSync42(configPath)) return false;
12506
+ const configPath = join57(cwd, "harness.config.json");
12507
+ if (!existsSync43(configPath)) return false;
12175
12508
  try {
12176
- const config = JSON.parse(readFileSync32(configPath, "utf-8"));
12509
+ const config = JSON.parse(readFileSync33(configPath, "utf-8"));
12177
12510
  return config?.telemetry?.enabled === false;
12178
12511
  } catch {
12179
12512
  return false;
@@ -12185,11 +12518,11 @@ function isTelemetryOptedOut(cwd) {
12185
12518
  }
12186
12519
  function flushTelemetryBackground(cwd) {
12187
12520
  try {
12188
- const adoptionFile = join56(cwd, ".harness", "metrics", "adoption.jsonl");
12189
- if (!existsSync42(adoptionFile)) return;
12521
+ const adoptionFile = join57(cwd, ".harness", "metrics", "adoption.jsonl");
12522
+ if (!existsSync43(adoptionFile)) return;
12190
12523
  if (isTelemetryOptedOut(cwd)) return;
12191
- const reporterPath = join56(cwd, ".harness", "hooks", "telemetry-reporter.js");
12192
- if (!existsSync42(reporterPath)) return;
12524
+ const reporterPath = join57(cwd, ".harness", "hooks", "telemetry-reporter.js");
12525
+ if (!existsSync43(reporterPath)) return;
12193
12526
  const child = spawn2(process.execPath, [reporterPath], {
12194
12527
  cwd,
12195
12528
  stdio: ["pipe", "ignore", "ignore"],
@@ -12226,7 +12559,7 @@ function reportTestSuccess(status, distinctId, identity) {
12226
12559
  if (identity.team) logger.info(` team: ${identity.team}`);
12227
12560
  }
12228
12561
  function createTestCommand() {
12229
- return new Command108("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
12562
+ return new Command110("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
12230
12563
  const cwd = process.cwd();
12231
12564
  const consent = resolveConsent(cwd, void 0);
12232
12565
  if (!consent.allowed) {
@@ -12263,7 +12596,7 @@ function createTestCommand() {
12263
12596
 
12264
12597
  // src/commands/telemetry/index.ts
12265
12598
  function createTelemetryCommand() {
12266
- const command = new Command109("telemetry").description("Telemetry identity and status management");
12599
+ const command = new Command111("telemetry").description("Telemetry identity and status management");
12267
12600
  command.addCommand(createIdentifyCommand());
12268
12601
  command.addCommand(createStatusCommand());
12269
12602
  command.addCommand(createTestCommand());
@@ -12271,9 +12604,9 @@ function createTelemetryCommand() {
12271
12604
  }
12272
12605
 
12273
12606
  // src/commands/test-craft.ts
12274
- import { Command as Command110 } from "commander";
12607
+ import { Command as Command112 } from "commander";
12275
12608
  function createTestCraftCommand() {
12276
- return new Command110("test-craft").description(
12609
+ return new Command112("test-craft").description(
12277
12610
  "LLM-judgment critique of test quality across vitest/jest/mocha/playwright. Fourth craft-pipeline ceiling skill. Per-test critique with best-effort source pairing."
12278
12611
  ).option("-f, --files <files...>", "Optional test file/glob scope").option("--frameworks <names...>", "Restrict to: vitest / jest / mocha / playwright").option("--max-files <n>", "Cap test file count (default: 100)").option("--max-tests-per-file <n>", "Cap per-file test critique (default: 20)").option("--no-source-pair", "Skip source-pairing resolution").action(async (opts, cmd) => {
12279
12612
  const globalOpts = cmd.optsWithGlobals();
@@ -12321,10 +12654,10 @@ function printResult7(result, mode, _formatter) {
12321
12654
  list.push(f);
12322
12655
  byFile.set(f.target.file, list);
12323
12656
  }
12324
- for (const [file, fs47] of byFile) {
12657
+ for (const [file, fs48] of byFile) {
12325
12658
  console.log(`
12326
12659
  ${file}`);
12327
- for (const f of fs47) {
12660
+ for (const f of fs48) {
12328
12661
  const nestingStr = f.target.nesting.length > 0 ? f.target.nesting.join(" > ") + " > " : "";
12329
12662
  console.log(
12330
12663
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.framework}:${f.target.line}`
@@ -12343,8 +12676,8 @@ ${file}`);
12343
12676
  }
12344
12677
 
12345
12678
  // src/commands/traceability.ts
12346
- import { Command as Command111 } from "commander";
12347
- import chalk16 from "chalk";
12679
+ import { Command as Command113 } from "commander";
12680
+ import chalk17 from "chalk";
12348
12681
  function confidenceLabel(maxConfidence) {
12349
12682
  if (maxConfidence >= 0.8) return "explicit";
12350
12683
  if (maxConfidence > 0) return "inferred";
@@ -12353,13 +12686,13 @@ function confidenceLabel(maxConfidence) {
12353
12686
  function statusIcon(status) {
12354
12687
  switch (status) {
12355
12688
  case "full":
12356
- return chalk16.green("\u2713 full");
12689
+ return chalk17.green("\u2713 full");
12357
12690
  case "code-only":
12358
- return chalk16.yellow("\u25D0 code-only");
12691
+ return chalk17.yellow("\u25D0 code-only");
12359
12692
  case "test-only":
12360
- return chalk16.yellow("\u25D0 test-only");
12693
+ return chalk17.yellow("\u25D0 test-only");
12361
12694
  case "none":
12362
- return chalk16.red("\u2717 none");
12695
+ return chalk17.red("\u2717 none");
12363
12696
  default:
12364
12697
  return status;
12365
12698
  }
@@ -12406,14 +12739,14 @@ function handleEmptyResults(mode) {
12406
12739
  }
12407
12740
  function printResultTable(result, mode) {
12408
12741
  const specLabel = result.specPath || result.featureName || "Unknown";
12409
- console.log(` ${chalk16.cyan(specLabel)} ${chalk16.dim(`(${result.summary.total} requirements)`)}`);
12742
+ console.log(` ${chalk17.cyan(specLabel)} ${chalk17.dim(`(${result.summary.total} requirements)`)}`);
12410
12743
  console.log("");
12411
12744
  const numWidth = 4;
12412
12745
  const nameWidth = mode === OutputMode.VERBOSE ? 44 : 36;
12413
12746
  const codeWidth = 6;
12414
12747
  const testWidth = 7;
12415
12748
  const confWidth = 12;
12416
- const header = chalk16.dim(
12749
+ const header = chalk17.dim(
12417
12750
  ` ${pad("#", numWidth)}${pad("Requirement", nameWidth)}${pad("Code", codeWidth)}${pad("Tests", testWidth)}${pad("Confidence", confWidth)}Status`
12418
12751
  );
12419
12752
  console.log(header);
@@ -12442,10 +12775,10 @@ function printRequirementRows(requirements, mode, cols) {
12442
12775
  );
12443
12776
  if (mode === OutputMode.VERBOSE) {
12444
12777
  for (const f of req.codeFiles) {
12445
- console.log(chalk16.dim(` code: ${f.path} (${f.method})`));
12778
+ console.log(chalk17.dim(` code: ${f.path} (${f.method})`));
12446
12779
  }
12447
12780
  for (const f of req.testFiles) {
12448
- console.log(chalk16.dim(` test: ${f.path} (${f.method})`));
12781
+ console.log(chalk17.dim(` test: ${f.path} (${f.method})`));
12449
12782
  }
12450
12783
  }
12451
12784
  }
@@ -12456,7 +12789,7 @@ function printCoverageSummary(summary) {
12456
12789
  const codePct = s.total > 0 ? Math.round(s.withCode / s.total * 100) : 0;
12457
12790
  const testPct = s.total > 0 ? Math.round(s.withTests / s.total * 100) : 0;
12458
12791
  console.log(
12459
- ` ${chalk16.bold("Coverage:")} ${fullyPct}% fully traced (${s.fullyTraced}/${s.total}), ${codePct}% with code (${s.withCode}/${s.total}), ${testPct}% with tests (${s.withTests}/${s.total})`
12792
+ ` ${chalk17.bold("Coverage:")} ${fullyPct}% fully traced (${s.fullyTraced}/${s.total}), ${codePct}% with code (${s.withCode}/${s.total}), ${testPct}% with tests (${s.withTests}/${s.total})`
12460
12793
  );
12461
12794
  }
12462
12795
  async function runTraceability(options) {
@@ -12464,7 +12797,7 @@ async function runTraceability(options) {
12464
12797
  const projectPath = process.cwd();
12465
12798
  const store = await loadGraphStore(projectPath);
12466
12799
  if (!store) handleNoStore(mode);
12467
- const graphModule = await import("./dist-R3TOOPJ7.js");
12800
+ const graphModule = await import("./dist-OWHMNL4W.js");
12468
12801
  const filterOptions = buildFilterOptions(options);
12469
12802
  const results = graphModule.queryTraceability(store, filterOptions);
12470
12803
  if (results.length === 0) handleEmptyResults(mode);
@@ -12472,14 +12805,14 @@ async function runTraceability(options) {
12472
12805
  console.log(JSON.stringify(results, null, 2));
12473
12806
  } else {
12474
12807
  console.log("");
12475
- console.log(chalk16.bold("Spec-to-Implementation Traceability"));
12808
+ console.log(chalk17.bold("Spec-to-Implementation Traceability"));
12476
12809
  console.log("");
12477
12810
  for (const result of results) printResultTable(result, mode);
12478
12811
  }
12479
12812
  process.exit(ExitCode.SUCCESS);
12480
12813
  }
12481
12814
  function createTraceabilityCommand() {
12482
- return new Command111("traceability").description("Show spec-to-implementation traceability from the knowledge graph").option("--spec <path>", "Filter by spec file path").option("--feature <name>", "Filter by feature name").action(async (opts, cmd) => {
12815
+ return new Command113("traceability").description("Show spec-to-implementation traceability from the knowledge graph").option("--spec <path>", "Filter by spec file path").option("--feature <name>", "Filter by feature name").action(async (opts, cmd) => {
12483
12816
  const globalOpts = cmd.optsWithGlobals();
12484
12817
  await runTraceability({
12485
12818
  spec: opts.spec,
@@ -12492,15 +12825,15 @@ function createTraceabilityCommand() {
12492
12825
  }
12493
12826
 
12494
12827
  // src/commands/uninstall.ts
12495
- import * as path68 from "path";
12496
- import { Command as Command112 } from "commander";
12828
+ import * as path69 from "path";
12829
+ import { Command as Command114 } from "commander";
12497
12830
  async function runUninstall(skillName, options) {
12498
12831
  const packageName = resolvePackageName(skillName);
12499
12832
  const shortName = extractSkillName(packageName);
12500
12833
  const globalDir = resolveGlobalSkillsDir();
12501
- const skillsDir = path68.dirname(globalDir);
12502
- const communityBase = path68.join(skillsDir, "community");
12503
- const lockfilePath = path68.join(communityBase, "skills-lock.json");
12834
+ const skillsDir = path69.dirname(globalDir);
12835
+ const communityBase = path69.join(skillsDir, "community");
12836
+ const lockfilePath = path69.join(communityBase, "skills-lock.json");
12504
12837
  const lockfile = readLockfile2(lockfilePath);
12505
12838
  const entry = lockfile.skills[packageName];
12506
12839
  if (!entry) {
@@ -12530,7 +12863,7 @@ async function runUninstall(skillName, options) {
12530
12863
  return result;
12531
12864
  }
12532
12865
  function createUninstallCommand() {
12533
- const cmd = new Command112("uninstall");
12866
+ const cmd = new Command114("uninstall");
12534
12867
  cmd.description("Uninstall a community skill").argument("<skill>", "Skill name or @harness-skills/scoped package name").option("--force", "Remove even if other skills depend on this one").action(async (skill, opts) => {
12535
12868
  try {
12536
12869
  const result = await runUninstall(skill, opts);
@@ -12550,9 +12883,9 @@ function createUninstallCommand() {
12550
12883
 
12551
12884
  // src/commands/uninstall-constraints.ts
12552
12885
  init_dist3();
12553
- import * as fs46 from "fs/promises";
12554
- import * as path69 from "path";
12555
- import { Command as Command113 } from "commander";
12886
+ import * as fs47 from "fs/promises";
12887
+ import * as path70 from "path";
12888
+ import { Command as Command115 } from "commander";
12556
12889
  async function runUninstallConstraints(options) {
12557
12890
  const { packageName, configPath, lockfilePath } = options;
12558
12891
  const lockfileResult = await readLockfile(lockfilePath);
@@ -12572,7 +12905,7 @@ async function runUninstallConstraints(options) {
12572
12905
  }
12573
12906
  let localConfig;
12574
12907
  try {
12575
- const raw = await fs46.readFile(configPath, "utf-8");
12908
+ const raw = await fs47.readFile(configPath, "utf-8");
12576
12909
  localConfig = JSON.parse(raw);
12577
12910
  } catch (err) {
12578
12911
  return {
@@ -12609,11 +12942,11 @@ async function runUninstallConstraints(options) {
12609
12942
  };
12610
12943
  }
12611
12944
  function createUninstallConstraintsCommand() {
12612
- const cmd = new Command113("uninstall-constraints");
12945
+ const cmd = new Command115("uninstall-constraints");
12613
12946
  cmd.description("Remove a previously installed constraints package").argument("<name>", "Name of the constraint package to uninstall").option("-c, --config <path>", "Path to harness.config.json").action(async (name, opts) => {
12614
12947
  let configPath;
12615
12948
  if (opts.config) {
12616
- configPath = path69.resolve(opts.config);
12949
+ configPath = path70.resolve(opts.config);
12617
12950
  } else {
12618
12951
  const found = findConfigFile();
12619
12952
  if (!found.ok) {
@@ -12622,8 +12955,8 @@ function createUninstallConstraintsCommand() {
12622
12955
  }
12623
12956
  configPath = found.value;
12624
12957
  }
12625
- const projectRoot2 = path69.dirname(configPath);
12626
- const lockfilePath = path69.join(projectRoot2, ".harness", "constraints.lock.json");
12958
+ const projectRoot2 = path70.dirname(configPath);
12959
+ const lockfilePath = path70.join(projectRoot2, ".harness", "constraints.lock.json");
12627
12960
  const result = await runUninstallConstraints({
12628
12961
  packageName: name,
12629
12962
  configPath,
@@ -12649,13 +12982,13 @@ function createUninstallConstraintsCommand() {
12649
12982
 
12650
12983
  // src/commands/update.ts
12651
12984
  init_dist3();
12652
- import { Command as Command114 } from "commander";
12985
+ import { Command as Command116 } from "commander";
12653
12986
  import { execFile, execFileSync as execFileSync7 } from "child_process";
12654
- import { realpathSync, existsSync as existsSync43, readFileSync as readFileSync33 } from "fs";
12655
- import { dirname as dirname22, join as join59 } from "path";
12987
+ import { realpathSync, existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
12988
+ import { dirname as dirname23, join as join60 } from "path";
12656
12989
  import { promisify } from "util";
12657
12990
  import readline4 from "readline";
12658
- import chalk17 from "chalk";
12991
+ import chalk18 from "chalk";
12659
12992
  var CLI_PACKAGE = "@harness-engineering/cli";
12660
12993
  function detectPackageManagerFromPath(resolvedPath) {
12661
12994
  const normalizedBin = resolvedPath.replace(/\\/g, "/");
@@ -12741,16 +13074,16 @@ function prompt3(question) {
12741
13074
  });
12742
13075
  }
12743
13076
  function findPackageDir(resolvedBin) {
12744
- let dir = dirname22(resolvedBin);
13077
+ let dir = dirname23(resolvedBin);
12745
13078
  for (let i = 0; i < 6; i++) {
12746
- if (existsSync43(join59(dir, "package.json"))) {
13079
+ if (existsSync44(join60(dir, "package.json"))) {
12747
13080
  try {
12748
- const pkg = JSON.parse(readFileSync33(join59(dir, "package.json"), "utf-8"));
13081
+ const pkg = JSON.parse(readFileSync34(join60(dir, "package.json"), "utf-8"));
12749
13082
  if (pkg?.name === CLI_PACKAGE) return dir;
12750
13083
  } catch {
12751
13084
  }
12752
13085
  }
12753
- const parent = dirname22(dir);
13086
+ const parent = dirname23(dir);
12754
13087
  if (parent === dir) return null;
12755
13088
  dir = parent;
12756
13089
  }
@@ -12790,7 +13123,7 @@ function findAllInstalls() {
12790
13123
  if (!packageDir) continue;
12791
13124
  let version = null;
12792
13125
  try {
12793
- const pkg = JSON.parse(readFileSync33(join59(packageDir, "package.json"), "utf-8"));
13126
+ const pkg = JSON.parse(readFileSync34(join60(packageDir, "package.json"), "utf-8"));
12794
13127
  if (typeof pkg?.version === "string") version = pkg.version;
12795
13128
  } catch {
12796
13129
  }
@@ -12824,7 +13157,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
12824
13157
  `Found ${installs.length} harness installs on PATH. Only the active one was updated.`
12825
13158
  );
12826
13159
  for (const install of installs) {
12827
- const tag = install.packageDir === activeDir ? chalk17.green(" (active, just updated)") : chalk17.yellow(" (stale)");
13160
+ const tag = install.packageDir === activeDir ? chalk18.green(" (active, just updated)") : chalk18.yellow(" (stale)");
12828
13161
  const versionStr = install.version ? `v${install.version}` : "unknown";
12829
13162
  console.log(` ${install.binPath} -> ${versionStr}${tag}`);
12830
13163
  }
@@ -12832,7 +13165,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
12832
13165
  const commands = others.map((install) => buildUninstallCommand(install));
12833
13166
  console.log("Cleanup commands:");
12834
13167
  for (const { display } of commands) {
12835
- console.log(` ${chalk17.cyan(display)}`);
13168
+ console.log(` ${chalk18.cyan(display)}`);
12836
13169
  }
12837
13170
  console.log("");
12838
13171
  const answer = await prompt3(`Run these now to remove stale installs? (y/N) `);
@@ -12840,7 +13173,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
12840
13173
  for (const cmd of commands) {
12841
13174
  if (!cmd.runnable) {
12842
13175
  logger.warn(`Skipped ${cmd.install.binPath} (no automatic uninstall for this layout).`);
12843
- console.log(` Run manually: ${chalk17.cyan(cmd.display)}`);
13176
+ console.log(` Run manually: ${chalk18.cyan(cmd.display)}`);
12844
13177
  continue;
12845
13178
  }
12846
13179
  try {
@@ -12848,7 +13181,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
12848
13181
  execFileSync7(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
12849
13182
  } catch {
12850
13183
  logger.warn(`Uninstall failed for ${cmd.install.binPath}.`);
12851
- console.log(` Run manually: ${chalk17.cyan(cmd.display)}`);
13184
+ console.log(` Run manually: ${chalk18.cyan(cmd.display)}`);
12852
13185
  }
12853
13186
  }
12854
13187
  }
@@ -12883,12 +13216,12 @@ async function ensureTelemetryIfNeeded() {
12883
13216
  }
12884
13217
  function refreshHooks() {
12885
13218
  const cwd = process.cwd();
12886
- const configPath = join59(cwd, "harness.config.json");
12887
- if (!existsSync43(configPath)) return;
13219
+ const configPath = join60(cwd, "harness.config.json");
13220
+ if (!existsSync44(configPath)) return;
12888
13221
  let profile = "standard";
12889
- const profilePath = join59(cwd, ".harness", "hooks", "profile.json");
13222
+ const profilePath = join60(cwd, ".harness", "hooks", "profile.json");
12890
13223
  try {
12891
- const data = JSON.parse(readFileSync33(profilePath, "utf-8"));
13224
+ const data = JSON.parse(readFileSync34(profilePath, "utf-8"));
12892
13225
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
12893
13226
  profile = data.profile;
12894
13227
  }
@@ -12908,7 +13241,7 @@ function runLocalGraphScan() {
12908
13241
  execFileSync7("harness", ["graph", "scan", "."], { stdio: "inherit" });
12909
13242
  } catch {
12910
13243
  logger.warn("Graph scan failed. Run manually:");
12911
- console.log(` ${chalk17.cyan("harness graph scan .")}`);
13244
+ console.log(` ${chalk18.cyan("harness graph scan .")}`);
12912
13245
  }
12913
13246
  }
12914
13247
  async function offerRegeneration() {
@@ -12925,7 +13258,7 @@ async function offerRegeneration() {
12925
13258
  });
12926
13259
  } catch {
12927
13260
  logger.warn("Generation failed. Run manually:");
12928
- console.log(` ${chalk17.cyan(`harness generate${isGlobal ? " --global" : ""}`)}`);
13261
+ console.log(` ${chalk18.cyan(`harness generate${isGlobal ? " --global" : ""}`)}`);
12929
13262
  }
12930
13263
  if (!isGlobal) {
12931
13264
  runLocalGraphScan();
@@ -12989,8 +13322,8 @@ async function runUpdateAction(opts, globalOpts) {
12989
13322
  console.log("");
12990
13323
  for (const { pkg, current, latest } of outdated) {
12991
13324
  const shortName = pkg.replace("@harness-engineering/", "");
12992
- const currentStr = current ? chalk17.dim(`v${current}`) : chalk17.dim("not installed");
12993
- logger.info(`${shortName}: ${currentStr} \u2192 ${chalk17.green(`v${latest}`)}`);
13325
+ const currentStr = current ? chalk18.dim(`v${current}`) : chalk18.dim("not installed");
13326
+ logger.info(`${shortName}: ${currentStr} \u2192 ${chalk18.green(`v${latest}`)}`);
12994
13327
  }
12995
13328
  console.log("");
12996
13329
  }
@@ -13007,7 +13340,7 @@ async function runUpdateAction(opts, globalOpts) {
13007
13340
  } catch {
13008
13341
  console.log("");
13009
13342
  logger.error("Update failed. You can try manually:");
13010
- console.log(` ${chalk17.cyan(installCmd)}`);
13343
+ console.log(` ${chalk18.cyan(installCmd)}`);
13011
13344
  process.exit(ExitCode.ERROR);
13012
13345
  }
13013
13346
  refreshHooks();
@@ -13017,7 +13350,7 @@ async function runUpdateAction(opts, globalOpts) {
13017
13350
  process.exit(ExitCode.SUCCESS);
13018
13351
  }
13019
13352
  function createUpdateCommand() {
13020
- return new Command114("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").option("--force", "Force update even if versions match").option(
13353
+ return new Command116("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").option("--force", "Force update even if versions match").option(
13021
13354
  "--regenerate",
13022
13355
  "Only regenerate slash commands and agent definitions (skip package updates)"
13023
13356
  ).action(async (opts, cmd) => {
@@ -13027,9 +13360,9 @@ function createUpdateCommand() {
13027
13360
  }
13028
13361
 
13029
13362
  // src/commands/usage.ts
13030
- import { Command as Command115 } from "commander";
13363
+ import { Command as Command117 } from "commander";
13031
13364
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
13032
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-XIJWWQ5N.js");
13365
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-JCFK263L.js");
13033
13366
  const records = readCostRecords(cwd);
13034
13367
  if (includeClaudeSessions) {
13035
13368
  const ccRecords = parseCCRecords();
@@ -13122,7 +13455,7 @@ function registerDailyCommand(usage) {
13122
13455
  else logger.info("No usage data found. Run some harness sessions first.");
13123
13456
  return;
13124
13457
  }
13125
- const { aggregateByDay } = await import("./dist-XIJWWQ5N.js");
13458
+ const { aggregateByDay } = await import("./dist-JCFK263L.js");
13126
13459
  const limited = aggregateByDay(records).slice(0, days);
13127
13460
  if (globalOpts.json) {
13128
13461
  console.log(
@@ -13151,7 +13484,7 @@ function registerSessionsCommand(usage) {
13151
13484
  }
13152
13485
  return;
13153
13486
  }
13154
- const { aggregateBySession } = await import("./dist-XIJWWQ5N.js");
13487
+ const { aggregateBySession } = await import("./dist-JCFK263L.js");
13155
13488
  const sessionData = aggregateBySession(records);
13156
13489
  const limited = sessionData.slice(0, limit);
13157
13490
  if (globalOpts.json) {
@@ -13231,7 +13564,7 @@ function registerSessionCommand(usage) {
13231
13564
  cwd,
13232
13565
  globalOpts.includeClaudeSessions
13233
13566
  );
13234
- const { aggregateBySession } = await import("./dist-XIJWWQ5N.js");
13567
+ const { aggregateBySession } = await import("./dist-JCFK263L.js");
13235
13568
  const sessionData = aggregateBySession(records);
13236
13569
  const match = sessionData.find((s) => s.sessionId === id);
13237
13570
  if (!match) {
@@ -13266,7 +13599,7 @@ function registerLatestCommand(usage) {
13266
13599
  }
13267
13600
  return;
13268
13601
  }
13269
- const { aggregateBySession } = await import("./dist-XIJWWQ5N.js");
13602
+ const { aggregateBySession } = await import("./dist-JCFK263L.js");
13270
13603
  const sessionData = aggregateBySession(records);
13271
13604
  const latest = sessionData[0];
13272
13605
  if (!latest) {
@@ -13292,7 +13625,7 @@ function registerLatestCommand(usage) {
13292
13625
  });
13293
13626
  }
13294
13627
  function createUsageCommand() {
13295
- const usage = new Command115("usage").description("Token usage and cost tracking");
13628
+ const usage = new Command117("usage").description("Token usage and cost tracking");
13296
13629
  usage.option(
13297
13630
  "--include-claude-sessions",
13298
13631
  "Include Claude Code session data from ~/.claude/projects/"
@@ -13307,15 +13640,15 @@ function createUsageCommand() {
13307
13640
  // src/commands/validate.ts
13308
13641
  init_dist3();
13309
13642
  init_dist3();
13310
- import { Command as Command116 } from "commander";
13311
- import * as path70 from "path";
13643
+ import { Command as Command118 } from "commander";
13644
+ import * as path71 from "path";
13312
13645
  async function runValidate(options) {
13313
13646
  const configResult = resolveConfig(options.configPath);
13314
13647
  if (!configResult.ok) {
13315
13648
  return configResult;
13316
13649
  }
13317
13650
  const config = configResult.value;
13318
- const cwd = options.cwd ?? (options.configPath ? path70.dirname(path70.resolve(options.configPath)) : process.cwd());
13651
+ const cwd = options.cwd ?? (options.configPath ? path71.dirname(path71.resolve(options.configPath)) : process.cwd());
13319
13652
  const result = {
13320
13653
  valid: true,
13321
13654
  checks: {
@@ -13325,7 +13658,7 @@ async function runValidate(options) {
13325
13658
  },
13326
13659
  issues: []
13327
13660
  };
13328
- const agentsMapPath = path70.resolve(cwd, config.agentsMapPath);
13661
+ const agentsMapPath = path71.resolve(cwd, config.agentsMapPath);
13329
13662
  const agentsResult = await validateAgentsMap(agentsMapPath);
13330
13663
  if (agentsResult.ok) {
13331
13664
  result.checks.agentsMap = true;
@@ -13376,6 +13709,22 @@ async function runValidate(options) {
13376
13709
  }
13377
13710
  });
13378
13711
  }
13712
+ const strategyResult = await validateStrategy(cwd);
13713
+ if (strategyResult.ok) {
13714
+ result.checks.strategyConfig = true;
13715
+ } else {
13716
+ result.valid = false;
13717
+ result.checks.strategyConfig = false;
13718
+ result.issues.push({
13719
+ check: "strategyConfig",
13720
+ file: "STRATEGY.md",
13721
+ severity: "error",
13722
+ message: strategyResult.error.message,
13723
+ ...strategyResult.error.suggestions?.[0] !== void 0 && {
13724
+ suggestion: strategyResult.error.suggestions[0]
13725
+ }
13726
+ });
13727
+ }
13379
13728
  const solutionsResult = await validateSolutionsDir(cwd);
13380
13729
  if (solutionsResult.ok) {
13381
13730
  result.checks.solutionsDir = true;
@@ -13531,11 +13880,11 @@ function resolveValidateMode(globalOpts) {
13531
13880
  return OutputMode.TEXT;
13532
13881
  }
13533
13882
  async function printCrossCheckWarnings(mode) {
13534
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-SNE3SQOB.js");
13883
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-F7GEBRDH.js");
13535
13884
  const cwd = process.cwd();
13536
13885
  const crossResult = await runCrossCheck2({
13537
- specsDir: path70.join(cwd, "docs", "specs"),
13538
- plansDir: path70.join(cwd, "docs", "plans"),
13886
+ specsDir: path71.join(cwd, "docs", "specs"),
13887
+ plansDir: path71.join(cwd, "docs", "plans"),
13539
13888
  projectPath: cwd
13540
13889
  });
13541
13890
  if (!crossResult.ok || crossResult.value.warnings === 0) return;
@@ -13547,7 +13896,7 @@ async function printCrossCheckWarnings(mode) {
13547
13896
  ${crossResult.value.warnings} warnings`);
13548
13897
  }
13549
13898
  function createValidateCommand3() {
13550
- const command = new Command116("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
13899
+ const command = new Command118("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
13551
13900
  "--agent-configs",
13552
13901
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
13553
13902
  ).option("--strict", "Treat warnings as errors (applies to --agent-configs)").option("--agnix-bin <path>", "Override the agnix binary path discovered on PATH").action(async (opts, cmd) => runValidateAction(opts, cmd.optsWithGlobals()));
@@ -13596,7 +13945,7 @@ Agent configs checked via ${engineLabel}${note}`);
13596
13945
 
13597
13946
  // src/commands/verify.ts
13598
13947
  init_dist3();
13599
- import { Command as Command117 } from "commander";
13948
+ import { Command as Command119 } from "commander";
13600
13949
  import { execSync as execSync6 } from "child_process";
13601
13950
  function loadBranchingConfig(configPath) {
13602
13951
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -13659,7 +14008,7 @@ async function runVerify(options) {
13659
14008
  process.exit(ExitCode.VALIDATION_FAILED);
13660
14009
  }
13661
14010
  function createVerifyCommand() {
13662
- return new Command117("verify").description(
14011
+ return new Command119("verify").description(
13663
14012
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
13664
14013
  ).option(
13665
14014
  "--branch <name>",
@@ -13722,6 +14071,7 @@ var commandCreators = [
13722
14071
  createMcpCommand,
13723
14072
  createMcpGuardCommand,
13724
14073
  createMigrateCommand,
14074
+ createModelsCommand,
13725
14075
  createNamingCraftCommand,
13726
14076
  createNotificationsCommand,
13727
14077
  createOrchestratorCommand,
@@ -13762,7 +14112,7 @@ var commandCreators = [
13762
14112
 
13763
14113
  // src/index.ts
13764
14114
  function createProgram() {
13765
- const program = new Command118();
14115
+ const program = new Command120();
13766
14116
  program.name("harness").description("CLI for Harness Engineering toolkit").version(CLI_VERSION).option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--verbose", "Verbose output").option("--quiet", "Minimal output");
13767
14117
  for (const creator of commandCreators) {
13768
14118
  program.addCommand(creator());