@harness-engineering/cli 2.6.1 → 2.7.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 (156) hide show
  1. package/dist/agents/skills/claude-code/align-design-system/SKILL.md +174 -0
  2. package/dist/agents/skills/claude-code/align-design-system/skill.yaml +57 -0
  3. package/dist/agents/skills/claude-code/audit-brand-compliance/SKILL.md +189 -0
  4. package/dist/agents/skills/claude-code/audit-brand-compliance/skill.yaml +50 -0
  5. package/dist/agents/skills/claude-code/audit-component-anatomy/SKILL.md +181 -0
  6. package/dist/agents/skills/claude-code/audit-component-anatomy/skill.yaml +51 -0
  7. package/dist/agents/skills/claude-code/copy-craft/SKILL.md +192 -0
  8. package/dist/agents/skills/claude-code/copy-craft/skill.yaml +52 -0
  9. package/dist/agents/skills/claude-code/detect-design-drift/SKILL.md +139 -0
  10. package/dist/agents/skills/claude-code/detect-design-drift/skill.yaml +50 -0
  11. package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +10 -0
  12. package/dist/agents/skills/claude-code/harness-design-craft/SKILL.md +212 -0
  13. package/dist/agents/skills/claude-code/harness-design-craft/skill.yaml +57 -0
  14. package/dist/agents/skills/claude-code/harness-design-pipeline/SKILL.md +266 -0
  15. package/dist/agents/skills/claude-code/harness-design-pipeline/skill.yaml +70 -0
  16. package/dist/agents/skills/claude-code/knowledge-craft/SKILL.md +180 -0
  17. package/dist/agents/skills/claude-code/knowledge-craft/skill.yaml +49 -0
  18. package/dist/agents/skills/claude-code/naming-craft/SKILL.md +172 -0
  19. package/dist/agents/skills/claude-code/naming-craft/skill.yaml +51 -0
  20. package/dist/agents/skills/claude-code/security-craft/SKILL.md +205 -0
  21. package/dist/agents/skills/claude-code/security-craft/skill.yaml +58 -0
  22. package/dist/agents/skills/claude-code/spec-craft/SKILL.md +184 -0
  23. package/dist/agents/skills/claude-code/spec-craft/skill.yaml +55 -0
  24. package/dist/agents/skills/claude-code/test-craft/SKILL.md +212 -0
  25. package/dist/agents/skills/claude-code/test-craft/skill.yaml +58 -0
  26. package/dist/agents/skills/codex/align-design-system/SKILL.md +174 -0
  27. package/dist/agents/skills/codex/align-design-system/skill.yaml +57 -0
  28. package/dist/agents/skills/codex/audit-brand-compliance/SKILL.md +189 -0
  29. package/dist/agents/skills/codex/audit-brand-compliance/skill.yaml +50 -0
  30. package/dist/agents/skills/codex/audit-component-anatomy/SKILL.md +181 -0
  31. package/dist/agents/skills/codex/audit-component-anatomy/skill.yaml +51 -0
  32. package/dist/agents/skills/codex/copy-craft/SKILL.md +192 -0
  33. package/dist/agents/skills/codex/copy-craft/skill.yaml +52 -0
  34. package/dist/agents/skills/codex/detect-design-drift/SKILL.md +139 -0
  35. package/dist/agents/skills/codex/detect-design-drift/skill.yaml +50 -0
  36. package/dist/agents/skills/codex/harness-accessibility/SKILL.md +10 -0
  37. package/dist/agents/skills/codex/harness-design-craft/SKILL.md +212 -0
  38. package/dist/agents/skills/codex/harness-design-craft/skill.yaml +57 -0
  39. package/dist/agents/skills/codex/harness-design-pipeline/SKILL.md +266 -0
  40. package/dist/agents/skills/codex/harness-design-pipeline/skill.yaml +70 -0
  41. package/dist/agents/skills/codex/knowledge-craft/SKILL.md +180 -0
  42. package/dist/agents/skills/codex/knowledge-craft/skill.yaml +49 -0
  43. package/dist/agents/skills/codex/naming-craft/SKILL.md +172 -0
  44. package/dist/agents/skills/codex/naming-craft/skill.yaml +51 -0
  45. package/dist/agents/skills/codex/security-craft/SKILL.md +205 -0
  46. package/dist/agents/skills/codex/security-craft/skill.yaml +58 -0
  47. package/dist/agents/skills/codex/spec-craft/SKILL.md +184 -0
  48. package/dist/agents/skills/codex/spec-craft/skill.yaml +55 -0
  49. package/dist/agents/skills/codex/test-craft/SKILL.md +212 -0
  50. package/dist/agents/skills/codex/test-craft/skill.yaml +58 -0
  51. package/dist/agents/skills/cursor/align-design-system/SKILL.md +174 -0
  52. package/dist/agents/skills/cursor/align-design-system/skill.yaml +57 -0
  53. package/dist/agents/skills/cursor/audit-brand-compliance/SKILL.md +189 -0
  54. package/dist/agents/skills/cursor/audit-brand-compliance/skill.yaml +50 -0
  55. package/dist/agents/skills/cursor/audit-component-anatomy/SKILL.md +181 -0
  56. package/dist/agents/skills/cursor/audit-component-anatomy/skill.yaml +51 -0
  57. package/dist/agents/skills/cursor/copy-craft/SKILL.md +192 -0
  58. package/dist/agents/skills/cursor/copy-craft/skill.yaml +52 -0
  59. package/dist/agents/skills/cursor/detect-design-drift/SKILL.md +139 -0
  60. package/dist/agents/skills/cursor/detect-design-drift/skill.yaml +50 -0
  61. package/dist/agents/skills/cursor/harness-accessibility/SKILL.md +10 -0
  62. package/dist/agents/skills/cursor/harness-design-craft/SKILL.md +212 -0
  63. package/dist/agents/skills/cursor/harness-design-craft/skill.yaml +57 -0
  64. package/dist/agents/skills/cursor/harness-design-pipeline/SKILL.md +266 -0
  65. package/dist/agents/skills/cursor/harness-design-pipeline/skill.yaml +70 -0
  66. package/dist/agents/skills/cursor/knowledge-craft/SKILL.md +180 -0
  67. package/dist/agents/skills/cursor/knowledge-craft/skill.yaml +49 -0
  68. package/dist/agents/skills/cursor/naming-craft/SKILL.md +172 -0
  69. package/dist/agents/skills/cursor/naming-craft/skill.yaml +51 -0
  70. package/dist/agents/skills/cursor/security-craft/SKILL.md +205 -0
  71. package/dist/agents/skills/cursor/security-craft/skill.yaml +58 -0
  72. package/dist/agents/skills/cursor/spec-craft/SKILL.md +184 -0
  73. package/dist/agents/skills/cursor/spec-craft/skill.yaml +55 -0
  74. package/dist/agents/skills/cursor/test-craft/SKILL.md +212 -0
  75. package/dist/agents/skills/cursor/test-craft/skill.yaml +58 -0
  76. package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +174 -0
  77. package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +57 -0
  78. package/dist/agents/skills/gemini-cli/audit-brand-compliance/SKILL.md +189 -0
  79. package/dist/agents/skills/gemini-cli/audit-brand-compliance/skill.yaml +50 -0
  80. package/dist/agents/skills/gemini-cli/audit-component-anatomy/SKILL.md +181 -0
  81. package/dist/agents/skills/gemini-cli/audit-component-anatomy/skill.yaml +51 -0
  82. package/dist/agents/skills/gemini-cli/copy-craft/SKILL.md +192 -0
  83. package/dist/agents/skills/gemini-cli/copy-craft/skill.yaml +52 -0
  84. package/dist/agents/skills/gemini-cli/detect-design-drift/SKILL.md +139 -0
  85. package/dist/agents/skills/gemini-cli/detect-design-drift/skill.yaml +50 -0
  86. package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +10 -0
  87. package/dist/agents/skills/gemini-cli/harness-design-craft/SKILL.md +212 -0
  88. package/dist/agents/skills/gemini-cli/harness-design-craft/skill.yaml +57 -0
  89. package/dist/agents/skills/gemini-cli/harness-design-pipeline/SKILL.md +266 -0
  90. package/dist/agents/skills/gemini-cli/harness-design-pipeline/skill.yaml +70 -0
  91. package/dist/agents/skills/gemini-cli/knowledge-craft/SKILL.md +180 -0
  92. package/dist/agents/skills/gemini-cli/knowledge-craft/skill.yaml +49 -0
  93. package/dist/agents/skills/gemini-cli/naming-craft/SKILL.md +172 -0
  94. package/dist/agents/skills/gemini-cli/naming-craft/skill.yaml +51 -0
  95. package/dist/agents/skills/gemini-cli/security-craft/SKILL.md +205 -0
  96. package/dist/agents/skills/gemini-cli/security-craft/skill.yaml +58 -0
  97. package/dist/agents/skills/gemini-cli/spec-craft/SKILL.md +184 -0
  98. package/dist/agents/skills/gemini-cli/spec-craft/skill.yaml +55 -0
  99. package/dist/agents/skills/gemini-cli/test-craft/SKILL.md +212 -0
  100. package/dist/agents/skills/gemini-cli/test-craft/skill.yaml +58 -0
  101. package/dist/{agents-md-2JUQ4FE2.js → agents-md-267R2NUJ.js} +4 -4
  102. package/dist/{analyzer-VY6DJVOU-4AHIJLNS.js → analyzer-VY6DJVOU-WYKV3TTW.js} +2 -2
  103. package/dist/{architecture-CXAVNB5X.js → architecture-ZTEHGIHD.js} +6 -6
  104. package/dist/{assess-project-M626SSPN.js → assess-project-OKDW3YSK.js} +2 -1
  105. package/dist/bin/harness-mcp.js +17 -17
  106. package/dist/bin/harness.js +27 -27
  107. package/dist/{check-phase-gate-XMU6LLUQ.js → check-phase-gate-YJWFDW66.js} +5 -5
  108. package/dist/{chunk-372MGNTI.js → chunk-4EGPFB7V.js} +6185 -124
  109. package/dist/{chunk-HFOB2MPQ.js → chunk-67RP7MLR.js} +3 -3
  110. package/dist/{chunk-5JNSFYZU.js → chunk-6T5AYG5S.js} +6 -6
  111. package/dist/{chunk-5XLLIYYL.js → chunk-6UHDQP2N.js} +1 -1
  112. package/dist/{chunk-YP7I25SL.js → chunk-B3B64OPD.js} +1 -1
  113. package/dist/{chunk-VTTNIZJL.js → chunk-B4OLYXZ4.js} +93 -3
  114. package/dist/{chunk-6AX6R3LM.js → chunk-CXAHK5PJ.js} +9 -9
  115. package/dist/{chunk-BCFDGOMA.js → chunk-H2ZJOJ7A.js} +81 -1
  116. package/dist/{chunk-CQOMVZDC.js → chunk-HLPY3RHE.js} +1641 -292
  117. package/dist/{chunk-Q6ZR2L6Q.js → chunk-HMMSWRWR.js} +2 -2
  118. package/dist/{chunk-YYRQCQPZ.js → chunk-IY2TZLY5.js} +176 -107
  119. package/dist/{chunk-I6K43QQS.js → chunk-MQG7FHXX.js} +3 -3
  120. package/dist/{chunk-43M3RLFQ.js → chunk-OLTVDPA2.js} +2 -2
  121. package/dist/{chunk-JFZOWO7D.js → chunk-OQE6ME2Z.js} +1 -1
  122. package/dist/{chunk-GWE5LL3R.js → chunk-P7EO7USC.js} +10 -10
  123. package/dist/{chunk-24KCOJJG.js → chunk-PARV3G2F.js} +1 -1
  124. package/dist/{chunk-QOKMDDBJ.js → chunk-QUPC37UB.js} +6 -6
  125. package/dist/{chunk-EPUKTTJZ.js → chunk-RC3OI5NK.js} +5 -1
  126. package/dist/{chunk-L5BCZ5XS.js → chunk-S7GEONXL.js} +1 -1
  127. package/dist/{chunk-5FDBXUFW.js → chunk-TIH53QXY.js} +1 -1
  128. package/dist/{chunk-OA6SWTU4.js → chunk-TIZ3L6CU.js} +11 -8
  129. package/dist/{chunk-GWF2OILZ.js → chunk-VG6UK6G6.js} +1 -1
  130. package/dist/{chunk-SZEFU6XC.js → chunk-W3PDVZ4I.js} +1 -1
  131. package/dist/{chunk-VUCGB2KH.js → chunk-WOXR6I3R.js} +1 -1
  132. package/dist/{chunk-K246XQ2L.js → chunk-XTIPZUPR.js} +1 -1
  133. package/dist/{chunk-HMW3VKUF.js → chunk-Z2GUITAS.js} +10 -10
  134. package/dist/{chunk-PFZEADQM.js → chunk-ZKA3TGYS.js} +79 -2
  135. package/dist/{ci-workflow-3JNDZQYD.js → ci-workflow-YGTQTNVC.js} +4 -4
  136. package/dist/{dist-QPWXPCPL.js → dist-R3TOOPJ7.js} +1 -1
  137. package/dist/{dist-OHDQBTSO.js → dist-XIJWWQ5N.js} +3 -3
  138. package/dist/{docs-5RYMDHN3.js → docs-KCTLXK2G.js} +6 -6
  139. package/dist/{engine-GKGT5ULT.js → engine-J64WPH5K.js} +4 -4
  140. package/dist/{entropy-DQTAPSSE.js → entropy-M27JUL3V.js} +5 -5
  141. package/dist/{feedback-WH6XPQJS.js → feedback-W25QO3OL.js} +2 -2
  142. package/dist/{generate-agent-definitions-SZA4QIHN.js → generate-agent-definitions-RNMU5U5R.js} +5 -5
  143. package/dist/{glob-helper-XE2UGEOV.js → glob-helper-EX4YZKZO.js} +1 -1
  144. package/dist/{graph-loader-EQBOIHFZ.js → graph-loader-EIFEOUVI.js} +1 -1
  145. package/dist/index.d.ts +587 -6
  146. package/dist/index.js +27 -27
  147. package/dist/{loader-BNKGM23C.js → loader-HZKJ5ABV.js} +4 -4
  148. package/dist/{mcp-YKKPWUMH.js → mcp-NEAPIDTT.js} +17 -17
  149. package/dist/{performance-54TMJOEU.js → performance-3AVQUDRG.js} +6 -6
  150. package/dist/{review-pipeline-OTDDVPNY.js → review-pipeline-KA7SGUXJ.js} +4 -4
  151. package/dist/{runtime-W5THSNAL.js → runtime-IP6FVV5M.js} +4 -4
  152. package/dist/{scan-4PPP6ZXT.js → scan-LYKLM4EQ.js} +1 -1
  153. package/dist/{security-27HW7CYT.js → security-EAR4FJWI.js} +1 -1
  154. package/dist/{validate-QRVCD4GP.js → validate-EVH3UXIC.js} +5 -5
  155. package/dist/{validate-cross-check-BUAGBAPO.js → validate-cross-check-SNE3SQOB.js} +4 -4
  156. package/package.json +8 -7
@@ -1,26 +1,26 @@
1
1
  import {
2
2
  generateRuntime
3
- } from "./chunk-L5BCZ5XS.js";
3
+ } from "./chunk-S7GEONXL.js";
4
4
  import {
5
5
  generateAgentsMd
6
- } from "./chunk-JFZOWO7D.js";
6
+ } from "./chunk-OQE6ME2Z.js";
7
7
  import {
8
8
  generateCIWorkflow
9
- } from "./chunk-YP7I25SL.js";
9
+ } from "./chunk-B3B64OPD.js";
10
10
  import {
11
11
  createGenerateAgentDefinitionsCommand,
12
12
  generateAgentDefinitions
13
- } from "./chunk-PFZEADQM.js";
13
+ } from "./chunk-ZKA3TGYS.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-5XLLIYYL.js";
20
+ } from "./chunk-6UHDQP2N.js";
21
21
  import {
22
22
  TemplateEngine
23
- } from "./chunk-VUCGB2KH.js";
23
+ } from "./chunk-WOXR6I3R.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-K246XQ2L.js";
34
+ } from "./chunk-XTIPZUPR.js";
35
35
  import {
36
36
  runPersona
37
37
  } from "./chunk-GISMXMVL.js";
@@ -46,7 +46,7 @@ import {
46
46
  OutputMode,
47
47
  createCheckPhaseGateCommand,
48
48
  findFiles
49
- } from "./chunk-43M3RLFQ.js";
49
+ } from "./chunk-OLTVDPA2.js";
50
50
  import {
51
51
  appendFrameworkAgents,
52
52
  captureHealthSnapshot,
@@ -59,14 +59,26 @@ import {
59
59
  isSnapshotFresh,
60
60
  loadCachedSnapshot,
61
61
  persistToolingConfig,
62
- recommend
63
- } from "./chunk-372MGNTI.js";
62
+ recommend,
63
+ runAlignDesignSystem,
64
+ runAudit,
65
+ runAuditBrand,
66
+ runCopyCraft,
67
+ runDesignCraft,
68
+ runDesignPipeline,
69
+ runDetectDrift,
70
+ runKnowledgeCraft,
71
+ runNamingCraft,
72
+ runSecurityCraft,
73
+ runSpecCraft,
74
+ runTestCraft
75
+ } from "./chunk-4EGPFB7V.js";
64
76
  import {
65
77
  VALID_PLATFORMS
66
78
  } from "./chunk-3ISINLYT.js";
67
79
  import {
68
80
  loadGraphStore
69
- } from "./chunk-5FDBXUFW.js";
81
+ } from "./chunk-TIH53QXY.js";
70
82
  import {
71
83
  loadOrRebuildIndex
72
84
  } from "./chunk-27AJKSQY.js";
@@ -85,7 +97,7 @@ import {
85
97
  BranchingConfigSchema,
86
98
  findConfigFile,
87
99
  resolveConfig
88
- } from "./chunk-VTTNIZJL.js";
100
+ } from "./chunk-B4OLYXZ4.js";
89
101
  import {
90
102
  logger
91
103
  } from "./chunk-EBJQ6N4M.js";
@@ -179,7 +191,7 @@ import {
179
191
  validateSolutionsDir,
180
192
  writeConfig,
181
193
  writeLockfile
182
- } from "./chunk-YYRQCQPZ.js";
194
+ } from "./chunk-IY2TZLY5.js";
183
195
  import {
184
196
  CLI_VERSION
185
197
  } from "./chunk-BM3PWGXQ.js";
@@ -192,7 +204,7 @@ import {
192
204
  detectDocDrift,
193
205
  generateSuggestions,
194
206
  validateDependencies
195
- } from "./chunk-SZEFU6XC.js";
207
+ } from "./chunk-W3PDVZ4I.js";
196
208
  import {
197
209
  Err,
198
210
  INDEXED_FILE_KINDS,
@@ -202,8 +214,10 @@ import {
202
214
  } from "./chunk-OH3NXXUY.js";
203
215
  import {
204
216
  DEFAULT_SKIP_DIRS,
217
+ DesignConstraintAdapter,
218
+ GraphStore,
205
219
  init_dist as init_dist2
206
- } from "./chunk-BCFDGOMA.js";
220
+ } from "./chunk-H2ZJOJ7A.js";
207
221
  import {
208
222
  ArchConfigSchema,
209
223
  TimelineManager
@@ -214,7 +228,7 @@ import {
214
228
  } from "./chunk-KFQGP6VL.js";
215
229
 
216
230
  // src/index.ts
217
- import { Command as Command105 } from "commander";
231
+ import { Command as Command118 } from "commander";
218
232
 
219
233
  // src/commands/add.ts
220
234
  init_dist3();
@@ -403,7 +417,7 @@ function registerSkillsCommand(adoption) {
403
417
  const globalOpts = cmd.optsWithGlobals();
404
418
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
405
419
  const cwd = process.cwd();
406
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-OHDQBTSO.js");
420
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-XIJWWQ5N.js");
407
421
  const records = readAdoptionRecords(cwd);
408
422
  if (records.length === 0) {
409
423
  if (globalOpts.json) {
@@ -439,7 +453,7 @@ function registerRecentCommand(adoption) {
439
453
  const globalOpts = cmd.optsWithGlobals();
440
454
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
441
455
  const cwd = process.cwd();
442
- const { readAdoptionRecords } = await import("./dist-OHDQBTSO.js");
456
+ const { readAdoptionRecords } = await import("./dist-XIJWWQ5N.js");
443
457
  const records = readAdoptionRecords(cwd);
444
458
  if (records.length === 0) {
445
459
  if (globalOpts.json) {
@@ -517,7 +531,7 @@ function registerSkillCommand(adoption) {
517
531
  adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
518
532
  const globalOpts = cmd.optsWithGlobals();
519
533
  const cwd = process.cwd();
520
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-OHDQBTSO.js");
534
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-XIJWWQ5N.js");
521
535
  const records = readAdoptionRecords(cwd);
522
536
  const skillRecords = records.filter((r) => r.skill === name);
523
537
  if (skillRecords.length === 0) {
@@ -807,11 +821,8 @@ function createAgentCommand() {
807
821
  return command;
808
822
  }
809
823
 
810
- // src/commands/audit-protected.ts
811
- init_dist3();
824
+ // src/commands/align-design-system.ts
812
825
  import { Command as Command6 } from "commander";
813
- import * as path3 from "path";
814
- import * as fs2 from "fs";
815
826
 
816
827
  // src/utils/output.ts
817
828
  function resolveOutputMode(globalOpts) {
@@ -821,7 +832,115 @@ function resolveOutputMode(globalOpts) {
821
832
  return OutputMode.TEXT;
822
833
  }
823
834
 
835
+ // src/commands/align-design-system.ts
836
+ function createAlignDesignSystemCommand() {
837
+ return new Command6("align-design-system").description(
838
+ "Apply codemods for safe DRIFT-T001/T002/T003 findings and emit suggestions for DRIFT-T004 + all DRIFT-P*. Runs standalone (invokes detect-design-drift internally) or pipeline (reads pipeline.driftFindings from .harness/handoff.json)."
839
+ ).option("--dry-run", "Compute diffs without writing files. Default: write.").option(
840
+ "-f, --files <files...>",
841
+ "Optional file/glob scope (standalone mode only \u2014 passed to detect-design-drift)."
842
+ ).option(
843
+ "--mode <mode>",
844
+ "standalone (default) or pipeline (read findings from handoff.json)",
845
+ "standalone"
846
+ ).option(
847
+ "--design-strictness <level>",
848
+ "Override design.strictness: strict | standard | permissive"
849
+ ).action(async (opts, cmd) => {
850
+ const globalOpts = cmd.optsWithGlobals();
851
+ const outputMode = resolveOutputMode(globalOpts);
852
+ const formatter = new OutputFormatter(outputMode);
853
+ const cwd = globalOpts.cwd ?? process.cwd();
854
+ const input = { path: cwd };
855
+ if (opts.dryRun === true) input.dryRun = true;
856
+ if (opts.files !== void 0) input.files = opts.files;
857
+ if (opts.mode !== void 0) input.mode = opts.mode;
858
+ if (opts.designStrictness !== void 0) input.designStrictness = opts.designStrictness;
859
+ let result;
860
+ try {
861
+ result = await runAlignDesignSystem(input);
862
+ } catch (err) {
863
+ const message = err instanceof Error ? err.message : String(err);
864
+ if (outputMode === OutputMode.JSON) {
865
+ console.log(JSON.stringify({ error: message }));
866
+ } else {
867
+ logger.error(`align-design-system failed: ${message}`);
868
+ }
869
+ process.exit(ExitCode.ERROR);
870
+ return;
871
+ }
872
+ if (outputMode === OutputMode.JSON) {
873
+ console.log(JSON.stringify(result, null, 2));
874
+ } else {
875
+ printAlignResult(result, outputMode, formatter);
876
+ }
877
+ if (result.summary.failed > 0) process.exit(ExitCode.ERROR);
878
+ process.exit(ExitCode.SUCCESS);
879
+ });
880
+ }
881
+ function printAlignResult(result, mode, _formatter) {
882
+ const verbose = mode === OutputMode.VERBOSE;
883
+ const { summary, outcomes, meta } = result;
884
+ if (outcomes.length === 0) {
885
+ console.log("No drift findings to align.");
886
+ return;
887
+ }
888
+ const byFile = /* @__PURE__ */ new Map();
889
+ for (const o of outcomes) {
890
+ const file = outcomeFile(o);
891
+ const list = byFile.get(file) ?? [];
892
+ list.push(o);
893
+ byFile.set(file, list);
894
+ }
895
+ for (const [file, fixes] of byFile) {
896
+ console.log(`
897
+ ${file}`);
898
+ for (const o of fixes) {
899
+ const icon = outcomeIcon(o.kind);
900
+ const line = o.finding.line !== null && o.finding.line !== void 0 ? `:${o.finding.line}` : "";
901
+ console.log(` ${icon} ${o.finding.code}${line} \u2014 ${o.finding.message}`);
902
+ if (o.kind === "applied") {
903
+ console.log(` before: ${o.diff.before.trim()}`);
904
+ console.log(` after: ${o.diff.after.trim()}`);
905
+ } else if (o.kind === "suggestion" && verbose) {
906
+ console.log(` suggest: ${o.suggestion.description}`);
907
+ } else if (o.kind === "skipped-unsafe" && verbose) {
908
+ console.log(` skipped: ${o.reason}`);
909
+ } else if (o.kind === "failed") {
910
+ console.log(` error: ${o.error}`);
911
+ }
912
+ }
913
+ }
914
+ console.log("");
915
+ console.log(
916
+ `Summary: ${summary.applied} applied, ${summary.suggestions} suggestions, ${summary.skipped} skipped, ${summary.failed} failed (${summary.filesModified} files modified, ${summary.durationMs}ms)`
917
+ );
918
+ if (meta.dryRun) {
919
+ console.log("(dry-run \u2014 no files written)");
920
+ }
921
+ }
922
+ function outcomeFile(o) {
923
+ if (o.kind === "applied") return o.diff.file;
924
+ return o.finding.file;
925
+ }
926
+ function outcomeIcon(kind) {
927
+ switch (kind) {
928
+ case "applied":
929
+ return "\u2713";
930
+ case "suggestion":
931
+ return "?";
932
+ case "skipped-unsafe":
933
+ return "\xB7";
934
+ case "failed":
935
+ return "\u2717";
936
+ }
937
+ }
938
+
824
939
  // src/commands/audit-protected.ts
940
+ init_dist3();
941
+ import { Command as Command7 } from "commander";
942
+ import * as path3 from "path";
943
+ import * as fs2 from "fs";
825
944
  import { glob } from "glob";
826
945
  async function runAuditProtected(options) {
827
946
  const cwd = options.cwd ?? process.cwd();
@@ -890,7 +1009,7 @@ Issues (${result.issues.length}):`);
890
1009
  }
891
1010
  }
892
1011
  function createAuditProtectedCommand() {
893
- const command = new Command6("audit-protected").description("Report all harness-ignore protected code regions").action(async (_opts, cmd) => {
1012
+ const command = new Command7("audit-protected").description("Report all harness-ignore protected code regions").action(async (_opts, cmd) => {
894
1013
  const globalOpts = cmd.optsWithGlobals();
895
1014
  const mode = resolveOutputMode(globalOpts);
896
1015
  const formatter = new OutputFormatter(mode);
@@ -916,7 +1035,7 @@ function createAuditProtectedCommand() {
916
1035
  }
917
1036
 
918
1037
  // src/commands/backfill-skill-provenance.ts
919
- import { Command as Command7 } from "commander";
1038
+ import { Command as Command8 } from "commander";
920
1039
  import * as fs3 from "fs";
921
1040
  import * as path4 from "path";
922
1041
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
@@ -1004,7 +1123,7 @@ function runBackfillSkillProvenance(projectRoot2) {
1004
1123
  return result;
1005
1124
  }
1006
1125
  function createBackfillSkillProvenanceCommand() {
1007
- const cmd = new Command7("backfill-skill-provenance").description(
1126
+ const cmd = new Command8("backfill-skill-provenance").description(
1008
1127
  "Stamp `provenance: user-authored` on every catalog skill missing the field (Hermes Phase 4 one-shot)"
1009
1128
  ).option("--root <path>", "Project root containing agents/skills/", process.cwd()).action((opts) => {
1010
1129
  const result = runBackfillSkillProvenance(opts.root);
@@ -1016,10 +1135,10 @@ function createBackfillSkillProvenanceCommand() {
1016
1135
 
1017
1136
  // src/commands/blueprint.ts
1018
1137
  init_dist3();
1019
- import { Command as Command8 } from "commander";
1138
+ import { Command as Command9 } from "commander";
1020
1139
  import * as path5 from "path";
1021
1140
  function createBlueprintCommand() {
1022
- return new Command8("blueprint").description("Generate a self-contained, interactive blueprint of the codebase").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory", "docs/blueprint").action(async (projectPath, options) => {
1141
+ return new Command9("blueprint").description("Generate a self-contained, interactive blueprint of the codebase").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory", "docs/blueprint").action(async (projectPath, options) => {
1023
1142
  try {
1024
1143
  const rootDir = path5.resolve(projectPath);
1025
1144
  const outputDir = path5.resolve(options.output);
@@ -1041,7 +1160,7 @@ function createBlueprintCommand() {
1041
1160
 
1042
1161
  // src/commands/check-arch.ts
1043
1162
  init_dist3();
1044
- import { Command as Command9 } from "commander";
1163
+ import { Command as Command10 } from "commander";
1045
1164
  import { execSync as execSync2 } from "child_process";
1046
1165
  function getCommitHash(cwd) {
1047
1166
  try {
@@ -1170,7 +1289,7 @@ function printArchResult(value, mode, formatter) {
1170
1289
  if (output) console.log(output);
1171
1290
  }
1172
1291
  function createCheckArchCommand() {
1173
- const command = new Command9("check-arch").description("Check architecture assertions against baseline and thresholds").option("--update-baseline", "Capture current state as new baseline").option("--module <path>", "Check a single module").action(async (opts, cmd) => {
1292
+ const command = new Command10("check-arch").description("Check architecture assertions against baseline and thresholds").option("--update-baseline", "Capture current state as new baseline").option("--module <path>", "Check a single module").action(async (opts, cmd) => {
1174
1293
  const globalOpts = cmd.optsWithGlobals();
1175
1294
  const mode = resolveOutputMode2(globalOpts);
1176
1295
  const formatter = new OutputFormatter(mode);
@@ -1202,7 +1321,7 @@ function createCheckArchCommand() {
1202
1321
  // src/commands/check-deps.ts
1203
1322
  init_dist3();
1204
1323
  init_dist3();
1205
- import { Command as Command10 } from "commander";
1324
+ import { Command as Command11 } from "commander";
1206
1325
  import * as path6 from "path";
1207
1326
  async function runCheckDeps(options) {
1208
1327
  const cwd = options.cwd ?? process.cwd();
@@ -1294,16 +1413,352 @@ async function runCheckDepsAction(globalOpts) {
1294
1413
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1295
1414
  }
1296
1415
  function createCheckDepsCommand() {
1297
- const command = new Command10("check-deps").description("Validate dependency layers and detect circular dependencies").action(async (_opts, cmd) => {
1416
+ const command = new Command11("check-deps").description("Validate dependency layers and detect circular dependencies").action(async (_opts, cmd) => {
1298
1417
  await runCheckDepsAction(cmd.optsWithGlobals());
1299
1418
  });
1300
1419
  return command;
1301
1420
  }
1302
1421
 
1422
+ // src/commands/check-design.ts
1423
+ init_dist3();
1424
+ init_dist2();
1425
+ import { Command as Command12 } from "commander";
1426
+ async function runCheckDesign(options) {
1427
+ const startedAt = Date.now();
1428
+ const cwd = options.cwd ?? process.cwd();
1429
+ const mode = options.mode ?? "full";
1430
+ const configResult = resolveConfig(options.configPath);
1431
+ if (!configResult.ok) {
1432
+ return configResult;
1433
+ }
1434
+ const verifiersRun = [];
1435
+ const verifiersFailed = [];
1436
+ const anatomyFindings = [];
1437
+ const craftFindings = [];
1438
+ const driftFindings = [];
1439
+ const brandFindings = [];
1440
+ try {
1441
+ const anatomyOut = await runAudit({
1442
+ path: cwd,
1443
+ mode,
1444
+ ...options.files !== void 0 && { files: options.files }
1445
+ });
1446
+ anatomyFindings.push(...anatomyOut.findings);
1447
+ verifiersRun.push("audit-anatomy");
1448
+ } catch (err) {
1449
+ const message = err instanceof Error ? err.message : String(err);
1450
+ verifiersFailed.push({ name: "audit-anatomy", error: message });
1451
+ logger.warn(`audit-anatomy verifier failed: ${message}`);
1452
+ }
1453
+ try {
1454
+ const craftResult = await runDesignCraft({
1455
+ path: cwd,
1456
+ mode: mode === "fast" ? "fast" : "fast",
1457
+ // deep mode not in MVP per design-craft spec
1458
+ phases: ["critique"],
1459
+ ...options.files !== void 0 && { files: options.files }
1460
+ });
1461
+ if (craftResult.ok) {
1462
+ craftFindings.push(...craftResult.value.findings);
1463
+ verifiersRun.push("design-craft-critique");
1464
+ } else {
1465
+ verifiersFailed.push({
1466
+ name: "design-craft-critique",
1467
+ error: craftResult.error.message
1468
+ });
1469
+ logger.warn(`design-craft verifier failed: ${craftResult.error.message}`);
1470
+ }
1471
+ } catch (err) {
1472
+ const message = err instanceof Error ? err.message : String(err);
1473
+ verifiersFailed.push({ name: "design-craft-critique", error: message });
1474
+ logger.warn(`design-craft verifier failed: ${message}`);
1475
+ }
1476
+ try {
1477
+ const driftOut = await runDetectDrift({
1478
+ path: cwd,
1479
+ mode,
1480
+ ...options.files !== void 0 && { files: options.files }
1481
+ });
1482
+ driftFindings.push(...driftOut.findings);
1483
+ verifiersRun.push("detect-drift");
1484
+ } catch (err) {
1485
+ const message = err instanceof Error ? err.message : String(err);
1486
+ verifiersFailed.push({ name: "detect-drift", error: message });
1487
+ logger.warn(`detect-drift verifier failed: ${message}`);
1488
+ }
1489
+ try {
1490
+ const brandOut = await runAuditBrand({
1491
+ path: cwd,
1492
+ mode,
1493
+ ...options.files !== void 0 && { files: options.files }
1494
+ });
1495
+ brandFindings.push(...brandOut.findings);
1496
+ verifiersRun.push("audit-brand");
1497
+ } catch (err) {
1498
+ const message = err instanceof Error ? err.message : String(err);
1499
+ verifiersFailed.push({ name: "audit-brand", error: message });
1500
+ logger.warn(`audit-brand verifier failed: ${message}`);
1501
+ }
1502
+ const bySeverity = {
1503
+ error: 0,
1504
+ warn: 0,
1505
+ info: 0
1506
+ };
1507
+ const byCode = {};
1508
+ for (const f of anatomyFindings) {
1509
+ bySeverity[f.severity] = (bySeverity[f.severity] ?? 0) + 1;
1510
+ byCode[f.code] = (byCode[f.code] ?? 0) + 1;
1511
+ }
1512
+ for (const f of craftFindings) {
1513
+ const sev = craftTierToSeverity(f.tier);
1514
+ bySeverity[sev] = (bySeverity[sev] ?? 0) + 1;
1515
+ byCode[f.code] = (byCode[f.code] ?? 0) + 1;
1516
+ }
1517
+ for (const f of driftFindings) {
1518
+ bySeverity[f.severity] = (bySeverity[f.severity] ?? 0) + 1;
1519
+ byCode[f.code] = (byCode[f.code] ?? 0) + 1;
1520
+ }
1521
+ for (const f of brandFindings) {
1522
+ bySeverity[f.severity] = (bySeverity[f.severity] ?? 0) + 1;
1523
+ byCode[f.code] = (byCode[f.code] ?? 0) + 1;
1524
+ }
1525
+ const totalFindings = anatomyFindings.length + craftFindings.length + driftFindings.length + brandFindings.length;
1526
+ const graphPersisted = await persistFindings(
1527
+ anatomyFindings,
1528
+ craftFindings,
1529
+ driftFindings,
1530
+ brandFindings
1531
+ );
1532
+ const durationMs = Date.now() - startedAt;
1533
+ const result = {
1534
+ // valid is false if any error-severity finding OR any verifier failed
1535
+ valid: bySeverity.error === 0 && verifiersFailed.length === 0,
1536
+ findingsByVerifier: {
1537
+ anatomy: anatomyFindings,
1538
+ craft: craftFindings,
1539
+ drift: driftFindings,
1540
+ brand: brandFindings
1541
+ },
1542
+ summary: {
1543
+ totalFindings,
1544
+ bySeverity,
1545
+ byCode,
1546
+ verifiersRun,
1547
+ verifiersFailed,
1548
+ durationMs
1549
+ },
1550
+ graphPersisted
1551
+ };
1552
+ return Ok(result);
1553
+ }
1554
+ function craftTierToSeverity(tier) {
1555
+ switch (tier) {
1556
+ case "foundational":
1557
+ return "error";
1558
+ case "polish":
1559
+ return "warn";
1560
+ case "aspirational":
1561
+ return "info";
1562
+ }
1563
+ }
1564
+ async function persistFindings(anatomyFindings, craftFindings, driftFindings, brandFindings) {
1565
+ const store = new GraphStore();
1566
+ const adapter = new DesignConstraintAdapter(store);
1567
+ const records = [
1568
+ ...anatomyFindings.map(
1569
+ (f) => ({
1570
+ code: f.code,
1571
+ file: f.file,
1572
+ ...f.line !== null && f.line !== void 0 && { line: f.line },
1573
+ message: f.message,
1574
+ severity: f.severity,
1575
+ evidence: f.evidence?.snippet
1576
+ })
1577
+ ),
1578
+ ...craftFindings.map(
1579
+ (f) => ({
1580
+ code: f.code,
1581
+ file: f.target.file,
1582
+ ...f.target.line !== void 0 && { line: f.target.line },
1583
+ message: f.message,
1584
+ severity: craftTierToSeverity(f.tier)
1585
+ })
1586
+ ),
1587
+ ...driftFindings.map(
1588
+ (f) => ({
1589
+ code: f.code,
1590
+ file: f.file,
1591
+ ...f.line !== null && f.line !== void 0 && { line: f.line },
1592
+ message: f.message,
1593
+ severity: f.severity,
1594
+ evidence: f.evidence?.snippet
1595
+ })
1596
+ ),
1597
+ ...brandFindings.map(
1598
+ (f) => ({
1599
+ code: f.code,
1600
+ file: f.file,
1601
+ ...f.line !== null && f.line !== void 0 && { line: f.line },
1602
+ message: f.message,
1603
+ severity: f.severity,
1604
+ evidence: f.evidence?.snippet
1605
+ })
1606
+ )
1607
+ ];
1608
+ return adapter.recordFindings(records);
1609
+ }
1610
+ function printCheckDesignResult(value, mode, formatter) {
1611
+ const summaryLine = `${value.summary.totalFindings} finding${value.summary.totalFindings === 1 ? "" : "s"}`;
1612
+ console.log(formatter.formatSummary("check-design", summaryLine, value.valid));
1613
+ if (mode === OutputMode.QUIET) return;
1614
+ printVerifierSection(
1615
+ "audit-anatomy",
1616
+ value.findingsByVerifier.anatomy.length,
1617
+ () => printAnatomyFindings(value.findingsByVerifier.anatomy, mode === OutputMode.VERBOSE)
1618
+ );
1619
+ printVerifierSection(
1620
+ "design-craft critique",
1621
+ value.findingsByVerifier.craft.length,
1622
+ () => printCraftFindings(value.findingsByVerifier.craft, mode === OutputMode.VERBOSE)
1623
+ );
1624
+ printVerifierSection(
1625
+ "detect-drift",
1626
+ value.findingsByVerifier.drift.length,
1627
+ () => printDriftFindings(value.findingsByVerifier.drift, mode === OutputMode.VERBOSE)
1628
+ );
1629
+ printVerifierSection(
1630
+ "audit-brand",
1631
+ value.findingsByVerifier.brand.length,
1632
+ () => printBrandFindings(value.findingsByVerifier.brand, mode === OutputMode.VERBOSE)
1633
+ );
1634
+ if (value.summary.verifiersFailed.length > 0) {
1635
+ console.log("\nVerifiers that failed:");
1636
+ for (const failed of value.summary.verifiersFailed) {
1637
+ console.log(` - ${failed.name}: ${failed.error}`);
1638
+ }
1639
+ }
1640
+ console.log(
1641
+ `
1642
+ ${value.summary.bySeverity.error} error, ${value.summary.bySeverity.warn} warn, ${value.summary.bySeverity.info} info`
1643
+ );
1644
+ console.log(
1645
+ `Graph: +${value.graphPersisted.constraintsAdded} constraint(s), +${value.graphPersisted.edgesAdded} edge(s)`
1646
+ );
1647
+ }
1648
+ function printVerifierSection(name, count, printer) {
1649
+ console.log(`
1650
+ ${name} (${count} finding${count === 1 ? "" : "s"})`);
1651
+ if (count > 0) printer();
1652
+ }
1653
+ function printAnatomyFindings(findings, verbose) {
1654
+ const byFile = groupByFile(findings, (f) => f.file);
1655
+ for (const [file, fs47] of byFile) {
1656
+ console.log(` ${file}`);
1657
+ for (const f of fs47) {
1658
+ const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1659
+ console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1660
+ if (verbose) {
1661
+ console.log(` fix: ${f.fix.description}`);
1662
+ }
1663
+ }
1664
+ }
1665
+ }
1666
+ function printCraftFindings(findings, verbose) {
1667
+ const byFile = groupByFile(findings, (f) => f.target.file);
1668
+ for (const [file, fs47] of byFile) {
1669
+ console.log(` ${file}`);
1670
+ for (const f of fs47) {
1671
+ const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
1672
+ const sev = craftTierToSeverity(f.tier);
1673
+ console.log(
1674
+ ` ${f.code} [${sev} / tier:${f.tier} / impact:${f.impact} / conf:${f.confidence}] line${line}: ${f.message}`
1675
+ );
1676
+ if (verbose && f.after !== void 0) {
1677
+ console.log(` after: ${f.after}`);
1678
+ }
1679
+ }
1680
+ }
1681
+ }
1682
+ function printDriftFindings(findings, verbose) {
1683
+ const byFile = groupByFile(findings, (f) => f.file);
1684
+ for (const [file, fs47] of byFile) {
1685
+ console.log(` ${file}`);
1686
+ for (const f of fs47) {
1687
+ const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1688
+ console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1689
+ if (verbose) {
1690
+ console.log(` fix: ${f.fix.description}`);
1691
+ }
1692
+ }
1693
+ }
1694
+ }
1695
+ function printBrandFindings(findings, verbose) {
1696
+ const byFile = groupByFile(findings, (f) => f.file);
1697
+ for (const [file, fs47] of byFile) {
1698
+ console.log(` ${file}`);
1699
+ for (const f of fs47) {
1700
+ const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1701
+ console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1702
+ if (verbose) {
1703
+ console.log(` fix: ${f.fix.description}`);
1704
+ }
1705
+ }
1706
+ }
1707
+ }
1708
+ function groupByFile(items, getFile) {
1709
+ const map = /* @__PURE__ */ new Map();
1710
+ for (const item of items) {
1711
+ const f = getFile(item);
1712
+ const list = map.get(f) ?? [];
1713
+ list.push(item);
1714
+ map.set(f, list);
1715
+ }
1716
+ return map;
1717
+ }
1718
+ function createCheckDesignCommand() {
1719
+ const command = new Command12("check-design").description(
1720
+ "Run the design verifier suite (component-anatomy + design-craft critique). Mirrors `harness check-docs`. Single-pass; the convergence fix loop lives in the design-pipeline orchestrator (sub-project #5)."
1721
+ ).option("-m, --mode <mode>", "Audit mode: fast | full", "full").option(
1722
+ "-f, --files <files...>",
1723
+ "Optional file/glob scoping. Defaults to all project source files."
1724
+ ).action(async (opts, cmd) => {
1725
+ const globalOpts = cmd.optsWithGlobals();
1726
+ const mode = resolveOutputMode(globalOpts);
1727
+ const formatter = new OutputFormatter(mode);
1728
+ const result = await runCheckDesign({
1729
+ configPath: globalOpts.config,
1730
+ json: globalOpts.json,
1731
+ verbose: globalOpts.verbose,
1732
+ quiet: globalOpts.quiet,
1733
+ ...opts.files !== void 0 && { files: opts.files },
1734
+ ...opts.mode !== void 0 && { mode: opts.mode }
1735
+ });
1736
+ if (!result.ok) {
1737
+ if (mode === OutputMode.JSON) {
1738
+ console.log(JSON.stringify({ error: result.error.message }));
1739
+ } else {
1740
+ logger.error(result.error.message);
1741
+ }
1742
+ process.exit(result.error.exitCode);
1743
+ }
1744
+ if (mode === OutputMode.JSON) {
1745
+ console.log(JSON.stringify(result.value, null, 2));
1746
+ } else {
1747
+ printCheckDesignResult(result.value, mode, formatter);
1748
+ }
1749
+ const hasErrors = result.value.summary.bySeverity.error > 0;
1750
+ const degraded = result.value.summary.verifiersFailed.length > 0;
1751
+ process.exit(
1752
+ hasErrors ? ExitCode.VALIDATION_FAILED : degraded ? ExitCode.ERROR : ExitCode.SUCCESS
1753
+ );
1754
+ });
1755
+ return command;
1756
+ }
1757
+
1303
1758
  // src/commands/check-docs.ts
1304
1759
  init_dist3();
1305
1760
  init_dist3();
1306
- import { Command as Command11 } from "commander";
1761
+ import { Command as Command13 } from "commander";
1307
1762
  import * as path7 from "path";
1308
1763
  async function runCheckDocs(options) {
1309
1764
  const cwd = options.cwd ?? process.cwd();
@@ -1381,7 +1836,7 @@ function printCheckDocsResult(value, mode, formatter) {
1381
1836
  }
1382
1837
  }
1383
1838
  function createCheckDocsCommand() {
1384
- const command = new Command11("check-docs").description("Check documentation coverage").option("--min-coverage <percent>", "Minimum coverage percentage", "80").action(async (opts, cmd) => {
1839
+ const command = new Command13("check-docs").description("Check documentation coverage").option("--min-coverage <percent>", "Minimum coverage percentage", "80").action(async (opts, cmd) => {
1385
1840
  const globalOpts = cmd.optsWithGlobals();
1386
1841
  const mode = resolveOutputMode(globalOpts);
1387
1842
  const formatter = new OutputFormatter(mode);
@@ -1412,7 +1867,7 @@ function createCheckDocsCommand() {
1412
1867
 
1413
1868
  // src/commands/check-perf.ts
1414
1869
  init_dist3();
1415
- import { Command as Command12 } from "commander";
1870
+ import { Command as Command14 } from "commander";
1416
1871
  import * as path8 from "path";
1417
1872
  async function runCheckPerf(cwd, options) {
1418
1873
  const runAll2 = !options.structural && !options.size && !options.coupling;
@@ -1529,7 +1984,7 @@ async function runCheckPerfAction(opts, globalOpts) {
1529
1984
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1530
1985
  }
1531
1986
  function createCheckPerfCommand() {
1532
- const command = new Command12("check-perf").description("Run performance checks: structural complexity, coupling, and size budgets").option("--structural", "Run structural complexity checks only").option("--coupling", "Run coupling metric checks only").option("--size", "Run size budget checks only").action(async (opts, cmd) => {
1987
+ const command = new Command14("check-perf").description("Run performance checks: structural complexity, coupling, and size budgets").option("--structural", "Run structural complexity checks only").option("--coupling", "Run coupling metric checks only").option("--size", "Run size budget checks only").action(async (opts, cmd) => {
1533
1988
  await runCheckPerfAction(opts, cmd.optsWithGlobals());
1534
1989
  });
1535
1990
  return command;
@@ -1537,7 +1992,7 @@ function createCheckPerfCommand() {
1537
1992
 
1538
1993
  // src/commands/check-security.ts
1539
1994
  init_dist3();
1540
- import { Command as Command13 } from "commander";
1995
+ import { Command as Command15 } from "commander";
1541
1996
  import * as path9 from "path";
1542
1997
  import { execSync as execSync3 } from "child_process";
1543
1998
  var SEVERITY_RANK = {
@@ -1642,7 +2097,7 @@ async function runCheckSecurityAction(opts, globalOpts) {
1642
2097
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1643
2098
  }
1644
2099
  function createCheckSecurityCommand() {
1645
- const command = new Command13("check-security").description("Run lightweight security scan: secrets, injection, XSS, weak crypto").option("--severity <level>", "Minimum severity threshold", "warning").hook("preAction", (thisCommand) => {
2100
+ const command = new Command15("check-security").description("Run lightweight security scan: secrets, injection, XSS, weak crypto").option("--severity <level>", "Minimum severity threshold", "warning").hook("preAction", (thisCommand) => {
1646
2101
  const severity = thisCommand.opts().severity;
1647
2102
  if (!["error", "warning", "info"].includes(severity)) {
1648
2103
  logger.error(`Invalid severity: "${severity}". Must be one of: error, warning, info`);
@@ -1655,11 +2110,11 @@ function createCheckSecurityCommand() {
1655
2110
  }
1656
2111
 
1657
2112
  // src/commands/ci/index.ts
1658
- import { Command as Command17 } from "commander";
2113
+ import { Command as Command19 } from "commander";
1659
2114
 
1660
2115
  // src/commands/ci/check.ts
1661
2116
  init_dist3();
1662
- import { Command as Command14 } from "commander";
2117
+ import { Command as Command16 } from "commander";
1663
2118
  var VALID_CHECKS = [
1664
2119
  "validate",
1665
2120
  "deps",
@@ -1749,14 +2204,14 @@ async function runCheckAction(opts, globalOpts) {
1749
2204
  process.exit(report.exitCode);
1750
2205
  }
1751
2206
  function createCheckCommand() {
1752
- return new Command14("check").description("Run all harness checks for CI (validate, deps, docs, entropy, phase-gate, arch)").option("--skip <checks>", "Comma-separated checks to skip (e.g., entropy,docs)").option("--fail-on <severity>", "Fail on severity level: error (default) or warning", "error").action(async (opts, cmd) => {
2207
+ return new Command16("check").description("Run all harness checks for CI (validate, deps, docs, entropy, phase-gate, arch)").option("--skip <checks>", "Comma-separated checks to skip (e.g., entropy,docs)").option("--fail-on <severity>", "Fail on severity level: error (default) or warning", "error").action(async (opts, cmd) => {
1753
2208
  await runCheckAction(opts, cmd.optsWithGlobals());
1754
2209
  });
1755
2210
  }
1756
2211
 
1757
2212
  // src/commands/ci/init.ts
1758
2213
  init_dist3();
1759
- import { Command as Command15 } from "commander";
2214
+ import { Command as Command17 } from "commander";
1760
2215
  import * as fs4 from "fs";
1761
2216
  import * as path10 from "path";
1762
2217
  var ALL_CHECKS = [
@@ -1893,14 +2348,14 @@ async function runInitAction(opts, globalOpts) {
1893
2348
  }
1894
2349
  }
1895
2350
  function createInitCommand() {
1896
- return new Command15("init").description("Generate CI configuration for harness checks").option("--platform <platform>", "CI platform: github, gitlab, or generic").option("--checks <list>", "Comma-separated list of checks to include").action(async (opts, cmd) => {
2351
+ return new Command17("init").description("Generate CI configuration for harness checks").option("--platform <platform>", "CI platform: github, gitlab, or generic").option("--checks <list>", "Comma-separated list of checks to include").action(async (opts, cmd) => {
1897
2352
  await runInitAction(opts, cmd.optsWithGlobals());
1898
2353
  });
1899
2354
  }
1900
2355
 
1901
2356
  // src/commands/ci/notify.ts
1902
2357
  init_dist3();
1903
- import { Command as Command16 } from "commander";
2358
+ import { Command as Command18 } from "commander";
1904
2359
  import * as fs5 from "fs";
1905
2360
  function loadReport(reportPath) {
1906
2361
  try {
@@ -1997,14 +2452,14 @@ async function runNotifyAction(reportPath, opts, globalOpts) {
1997
2452
  }
1998
2453
  }
1999
2454
  function createNotifyCommand() {
2000
- return new Command16("notify").description("Post CI check results to GitHub (PR comment or issue)").argument("<report>", "Path to CI check report JSON file (from harness ci check --json)").requiredOption("--target <target>", "Notification target: pr-comment or issue").option("--pr <number>", "PR number (required for pr-comment target)").option("--title <title>", "Custom issue title (for issue target)").option("--labels <labels>", "Comma-separated labels for created issues").action(async (reportPath, opts, cmd) => {
2455
+ return new Command18("notify").description("Post CI check results to GitHub (PR comment or issue)").argument("<report>", "Path to CI check report JSON file (from harness ci check --json)").requiredOption("--target <target>", "Notification target: pr-comment or issue").option("--pr <number>", "PR number (required for pr-comment target)").option("--title <title>", "Custom issue title (for issue target)").option("--labels <labels>", "Comma-separated labels for created issues").action(async (reportPath, opts, cmd) => {
2001
2456
  await runNotifyAction(reportPath, opts, cmd.optsWithGlobals());
2002
2457
  });
2003
2458
  }
2004
2459
 
2005
2460
  // src/commands/ci/index.ts
2006
2461
  function createCICommand() {
2007
- const command = new Command17("ci").description("CI/CD integration commands");
2462
+ const command = new Command19("ci").description("CI/CD integration commands");
2008
2463
  command.addCommand(createCheckCommand());
2009
2464
  command.addCommand(createInitCommand());
2010
2465
  command.addCommand(createNotifyCommand());
@@ -2013,7 +2468,7 @@ function createCICommand() {
2013
2468
 
2014
2469
  // src/commands/cleanup.ts
2015
2470
  init_dist3();
2016
- import { Command as Command18 } from "commander";
2471
+ import { Command as Command20 } from "commander";
2017
2472
  import * as path11 from "path";
2018
2473
  async function runCleanup(options) {
2019
2474
  const cwd = options.cwd ?? process.cwd();
@@ -2102,7 +2557,7 @@ function printCleanupResult(value, formatter) {
2102
2557
  }
2103
2558
  }
2104
2559
  function createCleanupCommand() {
2105
- const command = new Command18("cleanup").description("Detect entropy issues (doc drift, dead code, patterns)").option("-t, --type <type>", "Issue type: drift, dead-code, patterns, all", "all").action(async (opts, cmd) => {
2560
+ const command = new Command20("cleanup").description("Detect entropy issues (doc drift, dead code, patterns)").option("-t, --type <type>", "Issue type: drift, dead-code, patterns, all", "all").action(async (opts, cmd) => {
2106
2561
  const globalOpts = cmd.optsWithGlobals();
2107
2562
  const mode = resolveOutputMode(globalOpts);
2108
2563
  const formatter = new OutputFormatter(mode);
@@ -2133,7 +2588,7 @@ function createCleanupCommand() {
2133
2588
 
2134
2589
  // src/commands/cleanup-sessions.ts
2135
2590
  init_dist3();
2136
- import { Command as Command19 } from "commander";
2591
+ import { Command as Command21 } from "commander";
2137
2592
  import * as fs6 from "fs";
2138
2593
  import * as path12 from "path";
2139
2594
  var STALE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -2329,7 +2784,7 @@ ${dryRun ? "Would remove" : "Removed"} ${totalRemoved} stale entry(ies) across t
2329
2784
  }
2330
2785
  }
2331
2786
  function createCleanupSessionsCommand() {
2332
- const command = new Command19("cleanup-sessions").description(
2787
+ const command = new Command21("cleanup-sessions").description(
2333
2788
  "Remove stale entries from .harness/. Default: only .harness/sessions/ (no write in 24h)."
2334
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(
2335
2790
  "--include <list>",
@@ -2378,13 +2833,13 @@ async function runSessionsOnlySweep(cwd, opts, asJson) {
2378
2833
  }
2379
2834
 
2380
2835
  // src/commands/compound/index.ts
2381
- import { Command as Command21 } from "commander";
2836
+ import { Command as Command23 } from "commander";
2382
2837
 
2383
2838
  // src/commands/compound/scan-candidates.ts
2384
2839
  init_dist3();
2385
2840
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
2386
2841
  import { dirname as dirname2, join as join8, resolve as resolve11 } from "path";
2387
- import { Command as Command20 } from "commander";
2842
+ import { Command as Command22 } from "commander";
2388
2843
  var HOTSPOT_THRESHOLD = 7;
2389
2844
  var DEFAULT_LOOKBACK = "7d";
2390
2845
  async function runCompoundScanCandidatesCommand(opts) {
@@ -2439,7 +2894,7 @@ function emit(status, nonInteractive) {
2439
2894
  return status;
2440
2895
  }
2441
2896
  function createScanCandidatesCommand() {
2442
- return new Command20("scan-candidates").description(
2897
+ return new Command22("scan-candidates").description(
2443
2898
  "Scan recent fixes and hotspots for undocumented learnings; write candidate prompts"
2444
2899
  ).option("--lookback <window>", "Lookback window (e.g. 7d, 14d).", DEFAULT_LOOKBACK).option(
2445
2900
  "--non-interactive",
@@ -2464,13 +2919,96 @@ function createScanCandidatesCommand() {
2464
2919
 
2465
2920
  // src/commands/compound/index.ts
2466
2921
  function createCompoundCommand() {
2467
- const command = new Command21("compound").description("Compound (post-mortem playbook) commands");
2922
+ const command = new Command23("compound").description("Compound (post-mortem playbook) commands");
2468
2923
  command.addCommand(createScanCandidatesCommand());
2469
2924
  return command;
2470
2925
  }
2471
2926
 
2927
+ // src/commands/copy-craft.ts
2928
+ import { Command as Command24 } from "commander";
2929
+ function createCopyCraftCommand() {
2930
+ return new Command24("copy-craft").description(
2931
+ "LLM-judgment critique of prose-in-code across six surfaces: error messages, log lines, CLI output, commit subjects, PR descriptions, code comments. Third craft-pipeline ceiling skill. Graceful degradation when git/gh prereqs absent."
2932
+ ).option("-f, --files <files...>", "Optional source file/glob scope").option(
2933
+ "-s, --surfaces <surfaces...>",
2934
+ "Restrict to: error / log / cli-output / commit / pr-description / comment"
2935
+ ).option("--max-files <n>", "Cap source file count (default: 100)").option("--max-items-per-file <n>", "Cap per-file item sampling (default: 20)").option("--commits-since <when>", "Commit window (default: '1 month ago')").option("--pr-limit <n>", "PR count cap (default: 20)").action(async (opts, cmd) => {
2936
+ const globalOpts = cmd.optsWithGlobals();
2937
+ const outputMode = resolveOutputMode(globalOpts);
2938
+ const formatter = new OutputFormatter(outputMode);
2939
+ const cwd = globalOpts.cwd ?? process.cwd();
2940
+ const input = { path: cwd };
2941
+ if (opts.files !== void 0) input.files = opts.files;
2942
+ if (opts.surfaces !== void 0) input.surfaces = opts.surfaces;
2943
+ if (opts.maxFiles !== void 0) input.maxFiles = parseInt(opts.maxFiles, 10);
2944
+ if (opts.maxItemsPerFile !== void 0)
2945
+ input.maxItemsPerFile = parseInt(opts.maxItemsPerFile, 10);
2946
+ if (opts.commitsSince !== void 0) input.commitsSince = opts.commitsSince;
2947
+ if (opts.prLimit !== void 0) input.prLimit = parseInt(opts.prLimit, 10);
2948
+ let result;
2949
+ try {
2950
+ result = await runCopyCraft(input);
2951
+ } catch (err) {
2952
+ const message = err instanceof Error ? err.message : String(err);
2953
+ if (outputMode === OutputMode.JSON) {
2954
+ console.log(JSON.stringify({ error: message }));
2955
+ } else {
2956
+ logger.error(`copy-craft failed: ${message}`);
2957
+ }
2958
+ process.exit(ExitCode.ERROR);
2959
+ return;
2960
+ }
2961
+ if (outputMode === OutputMode.JSON) {
2962
+ console.log(JSON.stringify(result, null, 2));
2963
+ } else {
2964
+ printResult2(result, outputMode, formatter);
2965
+ }
2966
+ const hasFoundational = result.findings.some((f) => f.tier === "foundational");
2967
+ process.exit(hasFoundational ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS);
2968
+ });
2969
+ }
2970
+ function printResult2(result, mode, _formatter) {
2971
+ const verbose = mode === OutputMode.VERBOSE;
2972
+ const { findings, summary } = result;
2973
+ if (findings.length === 0) {
2974
+ console.log("No copy findings.");
2975
+ } else {
2976
+ const bySurface = /* @__PURE__ */ new Map();
2977
+ for (const f of findings) {
2978
+ const list = bySurface.get(f.target.surface) ?? [];
2979
+ list.push(f);
2980
+ bySurface.set(f.target.surface, list);
2981
+ }
2982
+ for (const [surface, fs47] of bySurface) {
2983
+ console.log(`
2984
+ [${surface}]`);
2985
+ for (const f of fs47) {
2986
+ const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
2987
+ console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.file}${line}`);
2988
+ console.log(` "${truncate(f.target.snippet, 80)}"`);
2989
+ console.log(` ${f.message}`);
2990
+ if (verbose) console.log(` source: ${f.cite.source}`);
2991
+ }
2992
+ }
2993
+ }
2994
+ console.log("");
2995
+ const surfaceCounts = Object.entries(summary.counts).filter(([, n]) => n > 0).map(([s, n]) => `${s}=${n}`).join(", ");
2996
+ console.log(
2997
+ `Summary: ${findings.length} findings across ${surfaceCounts || "no items"} (${summary.catalog.rubricsApplied.length} rubrics, ${summary.llmCalls.count} LLM calls, $${summary.llmCalls.costUsd.toFixed(4)}, ${summary.durationMs}ms)`
2998
+ );
2999
+ if (summary.skippedSurfaces.length > 0) {
3000
+ console.log(`Skipped surfaces:`);
3001
+ for (const s of summary.skippedSurfaces) {
3002
+ console.log(` - ${s.surface}: ${s.reason}`);
3003
+ }
3004
+ }
3005
+ }
3006
+ function truncate(s, n) {
3007
+ return s.length > n ? s.slice(0, n) + "\u2026" : s;
3008
+ }
3009
+
2472
3010
  // src/commands/dashboard.ts
2473
- import { Command as Command22 } from "commander";
3011
+ import { Command as Command25 } from "commander";
2474
3012
  import { spawn } from "child_process";
2475
3013
  import { existsSync as existsSync5 } from "fs";
2476
3014
  import { createRequire } from "module";
@@ -2554,11 +3092,99 @@ function runDashboard(opts) {
2554
3092
  }
2555
3093
  }
2556
3094
  function createDashboardCommand() {
2557
- return new Command22("dashboard").description("Start the Harness local web dashboard").option("--port <port>", "Client dev server port", String(DEFAULT_CLIENT_PORT)).option("--api-port <port>", "API server port", String(DEFAULT_API_PORT)).option("--orchestrator-url <url>", "Orchestrator URL (default: http://localhost:8080)").option("--no-open", "Do not automatically open browser").option("--cwd <path>", "Project directory (defaults to cwd)").action((opts) => runDashboard(opts));
3095
+ return new Command25("dashboard").description("Start the Harness local web dashboard").option("--port <port>", "Client dev server port", String(DEFAULT_CLIENT_PORT)).option("--api-port <port>", "API server port", String(DEFAULT_API_PORT)).option("--orchestrator-url <url>", "Orchestrator URL (default: http://localhost:8080)").option("--no-open", "Do not automatically open browser").option("--cwd <path>", "Project directory (defaults to cwd)").action((opts) => runDashboard(opts));
3096
+ }
3097
+
3098
+ // src/commands/design-pipeline.ts
3099
+ import { Command as Command26 } from "commander";
3100
+ function createDesignPipelineCommand() {
3101
+ return new Command26("design-pipeline").description(
3102
+ "Run the design-pipeline orchestrator: FRESHEN \u2192 DETECT \u2192 FIX \u2192 AUDIT \u2192 FILL \u2192 REPORT. Composes detect-design-drift, align-design-system, audit-component-anatomy, audit-brand-compliance, and design-craft-elevator into a single sequential pipeline with convergence-based remediation."
3103
+ ).option("--fix", "Enable convergence-based remediation (default: detect + report only)").option("--no-freshen", "Skip the FRESHEN phase").option("--no-fill", "Skip the FILL phase (input bootstrap + craft polish)").option("--ci", "Non-interactive: safe fixes only, no prompts").option("-f, --files <files...>", "Optional file/glob scope passed to each verifier").option("-m, --mode <mode>", "Verifier mode: fast | full", "fast").option(
3104
+ "--design-strictness <level>",
3105
+ "Override design.strictness: strict | standard | permissive"
3106
+ ).action(async (opts, cmd) => {
3107
+ const globalOpts = cmd.optsWithGlobals();
3108
+ const outputMode = resolveOutputMode(globalOpts);
3109
+ const formatter = new OutputFormatter(outputMode);
3110
+ const cwd = globalOpts.cwd ?? process.cwd();
3111
+ const input = { path: cwd };
3112
+ if (opts.fix === true) input.fix = true;
3113
+ if (opts.noFreshen === true) input.noFreshen = true;
3114
+ if (opts.noFill === true) input.noFill = true;
3115
+ if (opts.ci === true) input.ci = true;
3116
+ if (opts.files !== void 0) input.files = opts.files;
3117
+ if (opts.mode !== void 0) input.mode = opts.mode;
3118
+ if (opts.designStrictness !== void 0) input.designStrictness = opts.designStrictness;
3119
+ let result;
3120
+ try {
3121
+ result = await runDesignPipeline(input);
3122
+ } catch (err) {
3123
+ const message = err instanceof Error ? err.message : String(err);
3124
+ if (outputMode === OutputMode.JSON) {
3125
+ console.log(JSON.stringify({ error: message }));
3126
+ } else {
3127
+ logger.error(`design-pipeline failed: ${message}`);
3128
+ }
3129
+ process.exit(ExitCode.ERROR);
3130
+ return;
3131
+ }
3132
+ if (outputMode === OutputMode.JSON) {
3133
+ const serializable = { ...result, exclusions: [...result.exclusions] };
3134
+ console.log(JSON.stringify(serializable, null, 2));
3135
+ } else {
3136
+ printPipelineResult(result, outputMode, formatter);
3137
+ }
3138
+ const code = result.verdict === "fail" ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS;
3139
+ process.exit(code);
3140
+ });
3141
+ }
3142
+ function printPipelineResult(result, _mode, _formatter) {
3143
+ console.log("");
3144
+ console.log(`Verdict: ${verdictBadge(result.verdict)}`);
3145
+ console.log("");
3146
+ console.log("Phases:");
3147
+ console.log(
3148
+ ` FRESHEN inputs: DESIGN.md=${result.inputs.designMdExists ? "yes" : "no"} tokens.json=${result.inputs.tokensJsonExists ? "yes" : "no"} registry=${result.inputs.componentRegistryExists ? "yes" : "no"} brand=${result.inputs.brandRulesExist ? "yes" : "no"}`
3149
+ );
3150
+ console.log(` DETECT drift findings: ${result.driftFindings.length}`);
3151
+ console.log(
3152
+ ` FIX iterations: ${result.summary.iterationsRun}, fixes applied: ${result.summary.fixesApplied}`
3153
+ );
3154
+ console.log(
3155
+ ` AUDIT anatomy: ${result.auditFindings.anatomy.length}, brand: ${result.auditFindings.brand.length}`
3156
+ );
3157
+ const bootstrapped = Object.entries(result.bootstrapped).filter(([, v]) => v).map(([k]) => k);
3158
+ console.log(
3159
+ ` FILL bootstrapped: ${bootstrapped.length > 0 ? bootstrapped.join(", ") : "none"}, craft suggestions: ${result.craftSuggestions}`
3160
+ );
3161
+ console.log("");
3162
+ console.log(
3163
+ `Summary: ${result.summary.totalFindings} total findings (${result.summary.bySeverity.error} error, ${result.summary.bySeverity.warn} warn, ${result.summary.bySeverity.info} info) in ${result.summary.durationMs}ms`
3164
+ );
3165
+ if (result.verifiersRun.length > 0) {
3166
+ console.log(`Verifiers run: ${result.verifiersRun.join(", ")}`);
3167
+ }
3168
+ if (result.verifiersFailed.length > 0) {
3169
+ console.log("Verifiers failed (degraded):");
3170
+ for (const f of result.verifiersFailed) {
3171
+ console.log(` - ${f.name}: ${f.error}`);
3172
+ }
3173
+ }
3174
+ }
3175
+ function verdictBadge(verdict) {
3176
+ switch (verdict) {
3177
+ case "pass":
3178
+ return "\u2713 pass";
3179
+ case "warn":
3180
+ return "\u26A0 warn";
3181
+ case "fail":
3182
+ return "\u2717 fail";
3183
+ }
2558
3184
  }
2559
3185
 
2560
3186
  // src/commands/doctor.ts
2561
- import { Command as Command23 } from "commander";
3187
+ import { Command as Command27 } from "commander";
2562
3188
  import * as fs8 from "fs";
2563
3189
  import * as os from "os";
2564
3190
  import * as path14 from "path";
@@ -3162,7 +3788,7 @@ function formatCheck(check) {
3162
3788
  return line;
3163
3789
  }
3164
3790
  function createDoctorCommand() {
3165
- return new Command23("doctor").description(
3791
+ return new Command27("doctor").description(
3166
3792
  "Check environment health: Node, slash commands, MCP, integrations, integration credentials, hooks, baselines, sessions"
3167
3793
  ).action((_opts, cmd) => {
3168
3794
  const globalOpts = cmd.optsWithGlobals();
@@ -3190,7 +3816,7 @@ function createDoctorCommand() {
3190
3816
 
3191
3817
  // src/commands/fix-drift.ts
3192
3818
  init_dist3();
3193
- import { Command as Command24 } from "commander";
3819
+ import { Command as Command28 } from "commander";
3194
3820
  import * as path15 from "path";
3195
3821
  async function runFixDrift(options) {
3196
3822
  const cwd = options.cwd ?? process.cwd();
@@ -3323,7 +3949,7 @@ function printFixDriftResult(value, mode, formatter) {
3323
3949
  }
3324
3950
  }
3325
3951
  function createFixDriftCommand() {
3326
- const command = new Command24("fix-drift").description("Auto-fix entropy issues (doc drift, dead code)").option("--no-dry-run", "Actually apply fixes (default is dry-run mode)").action(async (opts, cmd) => {
3952
+ const command = new Command28("fix-drift").description("Auto-fix entropy issues (doc drift, dead code)").option("--no-dry-run", "Actually apply fixes (default is dry-run mode)").action(async (opts, cmd) => {
3327
3953
  const globalOpts = cmd.optsWithGlobals();
3328
3954
  const mode = resolveOutputMode(globalOpts);
3329
3955
  const formatter = new OutputFormatter(mode);
@@ -3353,10 +3979,10 @@ function createFixDriftCommand() {
3353
3979
  }
3354
3980
 
3355
3981
  // src/commands/gateway/index.ts
3356
- import { Command as Command27 } from "commander";
3982
+ import { Command as Command31 } from "commander";
3357
3983
 
3358
3984
  // src/commands/gateway/token.ts
3359
- import { Command as Command25 } from "commander";
3985
+ import { Command as Command29 } from "commander";
3360
3986
  import { resolve as resolve14 } from "path";
3361
3987
  import { TokenStore } from "@harness-engineering/orchestrator";
3362
3988
  function getStore() {
@@ -3377,7 +4003,7 @@ async function runTokenRevoke(id) {
3377
4003
  return store.revoke(id);
3378
4004
  }
3379
4005
  function createTokenCommand() {
3380
- const cmd = new Command25("token").description("Manage Gateway API tokens");
4006
+ const cmd = new Command29("token").description("Manage Gateway API tokens");
3381
4007
  cmd.command("create").description("Create a new auth token. Secret is shown ONCE.").requiredOption("--name <name>", "Human label").requiredOption("--scopes <scopes>", "Comma-separated scopes").option("--bridge <kind>", "slack | discord | github-app | custom").option("--tenant <id>", "Tenant identifier").option("--expires <iso>", "Expiry ISO-8601").action(
3382
4008
  async (opts) => {
3383
4009
  const scopes = opts.scopes.split(",").map((s) => s.trim());
@@ -3406,7 +4032,7 @@ function createTokenCommand() {
3406
4032
  }
3407
4033
 
3408
4034
  // src/commands/gateway/deliveries.ts
3409
- import { Command as Command26 } from "commander";
4035
+ import { Command as Command30 } from "commander";
3410
4036
  import { createInterface } from "readline";
3411
4037
  import { resolve as resolve15 } from "path";
3412
4038
  import { WebhookQueue } from "@harness-engineering/orchestrator";
@@ -3446,7 +4072,7 @@ function promptYesNo(message) {
3446
4072
  });
3447
4073
  }
3448
4074
  function createDeliveriesCommand() {
3449
- const cmd = new Command26("deliveries").description("Inspect and manage webhook delivery queue");
4075
+ const cmd = new Command30("deliveries").description("Inspect and manage webhook delivery queue");
3450
4076
  cmd.command("list").description("List delivery queue entries (newest first; capped at 200 rows)").option("--status <status>", "Filter by status: pending|failed|delivered|dead").option("--subscription <id>", "Filter by subscription ID").action((opts) => {
3451
4077
  const queue = getQueue();
3452
4078
  try {
@@ -3506,14 +4132,14 @@ function createDeliveriesCommand() {
3506
4132
 
3507
4133
  // src/commands/gateway/index.ts
3508
4134
  function createGatewayCommand() {
3509
- const cmd = new Command27("gateway").description("Gateway API administration");
4135
+ const cmd = new Command31("gateway").description("Gateway API administration");
3510
4136
  cmd.addCommand(createTokenCommand());
3511
4137
  cmd.addCommand(createDeliveriesCommand());
3512
4138
  return cmd;
3513
4139
  }
3514
4140
 
3515
4141
  // src/commands/generate.ts
3516
- import { Command as Command28 } from "commander";
4142
+ import { Command as Command32 } from "commander";
3517
4143
  function validatePlatforms(platforms) {
3518
4144
  for (const p of platforms) {
3519
4145
  if (!VALID_PLATFORMS.includes(p)) {
@@ -3573,13 +4199,13 @@ async function runGenerateAction(opts, globalOpts) {
3573
4199
  }
3574
4200
  }
3575
4201
  function createGenerateCommand() {
3576
- return new Command28("generate").description("Generate all platform integrations (slash commands + agent definitions)").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global directories", false).option("--include-global", "Include built-in global skills", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).option("--yes", "Skip deletion confirmation prompts", false).action(async (opts, cmd) => {
4202
+ return new Command32("generate").description("Generate all platform integrations (slash commands + agent definitions)").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global directories", false).option("--include-global", "Include built-in global skills", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).option("--yes", "Skip deletion confirmation prompts", false).action(async (opts, cmd) => {
3577
4203
  await runGenerateAction(opts, cmd.optsWithGlobals());
3578
4204
  });
3579
4205
  }
3580
4206
 
3581
4207
  // src/commands/graph/index.ts
3582
- import { Command as Command31 } from "commander";
4208
+ import { Command as Command35 } from "commander";
3583
4209
 
3584
4210
  // src/commands/graph/status.ts
3585
4211
  import * as path16 from "path";
@@ -3597,7 +4223,7 @@ async function readConnectorSyncStatus(graphDir) {
3597
4223
  return result;
3598
4224
  }
3599
4225
  async function runGraphStatus(projectPath) {
3600
- const { GraphStore, loadGraphMetadata } = await import("./dist-QPWXPCPL.js");
4226
+ const { GraphStore: GraphStore2, loadGraphMetadata } = await import("./dist-R3TOOPJ7.js");
3601
4227
  const graphDir = path16.join(projectPath, ".harness", "graph");
3602
4228
  const metaResult = await loadGraphMetadata(graphDir);
3603
4229
  if (metaResult.status === "not_found") {
@@ -3621,7 +4247,7 @@ async function runGraphStatus(projectPath) {
3621
4247
  ...Object.keys(connectorSyncStatus).length > 0 ? { connectorSyncStatus } : {}
3622
4248
  };
3623
4249
  }
3624
- const store = new GraphStore();
4250
+ const store = new GraphStore2();
3625
4251
  const loaded = await store.load(graphDir);
3626
4252
  if (!loaded) {
3627
4253
  return {
@@ -3649,9 +4275,9 @@ async function runGraphStatus(projectPath) {
3649
4275
  // src/commands/graph/export.ts
3650
4276
  import * as path17 from "path";
3651
4277
  async function runGraphExport(projectPath, format) {
3652
- const { GraphStore } = await import("./dist-QPWXPCPL.js");
4278
+ const { GraphStore: GraphStore2 } = await import("./dist-R3TOOPJ7.js");
3653
4279
  const graphDir = path17.join(projectPath, ".harness", "graph");
3654
- const store = new GraphStore();
4280
+ const store = new GraphStore2();
3655
4281
  const loaded = await store.load(graphDir);
3656
4282
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
3657
4283
  if (format === "json") {
@@ -3682,11 +4308,11 @@ async function runGraphExport(projectPath, format) {
3682
4308
  import * as path20 from "path";
3683
4309
 
3684
4310
  // src/commands/graph/query.ts
3685
- import { Command as Command29 } from "commander";
4311
+ import { Command as Command33 } from "commander";
3686
4312
  import * as path18 from "path";
3687
4313
  async function runQuery(projectPath, rootNodeId, opts) {
3688
- const { GraphStore, ContextQL } = await import("./dist-QPWXPCPL.js");
3689
- const store = new GraphStore();
4314
+ const { GraphStore: GraphStore2, ContextQL } = await import("./dist-R3TOOPJ7.js");
4315
+ const store = new GraphStore2();
3690
4316
  const graphDir = path18.join(projectPath, ".harness", "graph");
3691
4317
  const loaded = await store.load(graphDir);
3692
4318
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
@@ -3728,13 +4354,13 @@ async function runQueryAction(rootNodeId, opts, globalOpts) {
3728
4354
  }
3729
4355
  }
3730
4356
  function createQueryCommand() {
3731
- return new Command29("query").description("Query the knowledge graph").argument("<rootNodeId>", "Starting node ID").option("--depth <n>", "Max traversal depth", "3").option("--types <types>", "Comma-separated node types to include").option("--edges <edges>", "Comma-separated edge types to include").option("--bidirectional", "Traverse both directions").action(async (rootNodeId, opts, cmd) => {
4357
+ return new Command33("query").description("Query the knowledge graph").argument("<rootNodeId>", "Starting node ID").option("--depth <n>", "Max traversal depth", "3").option("--types <types>", "Comma-separated node types to include").option("--edges <edges>", "Comma-separated edge types to include").option("--bidirectional", "Traverse both directions").action(async (rootNodeId, opts, cmd) => {
3732
4358
  await runQueryAction(rootNodeId, opts, cmd.optsWithGlobals());
3733
4359
  });
3734
4360
  }
3735
4361
 
3736
4362
  // src/commands/graph/ingest.ts
3737
- import { Command as Command30 } from "commander";
4363
+ import { Command as Command34 } from "commander";
3738
4364
  import * as path19 from "path";
3739
4365
  async function loadConnectorConfig(projectPath, source) {
3740
4366
  try {
@@ -3769,7 +4395,7 @@ function mergeResults(...results) {
3769
4395
  }
3770
4396
  async function runIngest(projectPath, source, opts) {
3771
4397
  const {
3772
- GraphStore,
4398
+ GraphStore: GraphStore2,
3773
4399
  CodeIngestor,
3774
4400
  TopologicalLinker,
3775
4401
  KnowledgeIngestor,
@@ -3782,9 +4408,9 @@ async function runIngest(projectPath, source, opts) {
3782
4408
  ConfluenceConnector,
3783
4409
  FigmaConnector,
3784
4410
  MiroConnector
3785
- } = await import("./dist-QPWXPCPL.js");
4411
+ } = await import("./dist-R3TOOPJ7.js");
3786
4412
  const graphDir = path19.join(projectPath, ".harness", "graph");
3787
- const store = new GraphStore();
4413
+ const store = new GraphStore2();
3788
4414
  await store.load(graphDir);
3789
4415
  const ingestOptions = loadIngestOptions(projectPath);
3790
4416
  if (opts?.all) {
@@ -3796,7 +4422,7 @@ async function runIngest(projectPath, source, opts) {
3796
4422
  path19.join(projectPath, "docs", "changes")
3797
4423
  );
3798
4424
  const gitResult = await new GitIngestor(store).ingest(projectPath);
3799
- const { createExtractionRunner } = await import("./dist-QPWXPCPL.js");
4425
+ const { createExtractionRunner } = await import("./dist-R3TOOPJ7.js");
3800
4426
  const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
3801
4427
  const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
3802
4428
  const syncManager = new SyncManager(store, graphDir);
@@ -3842,7 +4468,7 @@ async function runIngest(projectPath, source, opts) {
3842
4468
  );
3843
4469
  break;
3844
4470
  case "business-signals": {
3845
- const { createExtractionRunner } = await import("./dist-QPWXPCPL.js");
4471
+ const { createExtractionRunner } = await import("./dist-R3TOOPJ7.js");
3846
4472
  const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
3847
4473
  result = await createExtractionRunner().run(projectPath, store, extractedDir);
3848
4474
  break;
@@ -3879,7 +4505,7 @@ async function runIngest(projectPath, source, opts) {
3879
4505
  return result;
3880
4506
  }
3881
4507
  function createIngestCommand() {
3882
- return new Command30("ingest").description("Ingest data into the knowledge graph").option(
4508
+ return new Command34("ingest").description("Ingest data into the knowledge graph").option(
3883
4509
  "--source <name>",
3884
4510
  "Source to ingest (code, knowledge, git, requirements, business-signals, jira, slack, ci, confluence, figma, miro)"
3885
4511
  ).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(async (opts, cmd) => {
@@ -3957,17 +4583,17 @@ async function runExportAction(opts, cmd) {
3957
4583
  }
3958
4584
  }
3959
4585
  function createGraphCommand() {
3960
- const graph = new Command31("graph").description("Knowledge graph management");
4586
+ const graph = new Command35("graph").description("Knowledge graph management");
3961
4587
  graph.command("status").description("Show graph statistics").action(runStatusAction);
3962
4588
  graph.command("export").description("Export graph").requiredOption("--format <format>", "Output format (json, mermaid)").action(runExportAction);
3963
4589
  return graph;
3964
4590
  }
3965
4591
 
3966
4592
  // src/commands/hooks/index.ts
3967
- import { Command as Command36 } from "commander";
4593
+ import { Command as Command40 } from "commander";
3968
4594
 
3969
4595
  // src/commands/hooks/init.ts
3970
- import { Command as Command32 } from "commander";
4596
+ import { Command as Command36 } from "commander";
3971
4597
  import * as fs9 from "fs";
3972
4598
  import * as path21 from "path";
3973
4599
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -4089,7 +4715,7 @@ function initHooks(options) {
4089
4715
  return { copiedScripts, settingsPath, profilePath };
4090
4716
  }
4091
4717
  function createInitCommand2() {
4092
- return new Command32("init").description("Install Claude Code hook configurations into the current project").option("--profile <profile>", "Hook profile: minimal, standard, or strict", "standard").action(async (opts, cmd) => {
4718
+ return new Command36("init").description("Install Claude Code hook configurations into the current project").option("--profile <profile>", "Hook profile: minimal, standard, or strict", "standard").action(async (opts, cmd) => {
4093
4719
  const globalOpts = cmd.optsWithGlobals();
4094
4720
  const profile = opts.profile;
4095
4721
  if (!VALID_PROFILES.includes(profile)) {
@@ -4127,7 +4753,7 @@ function createInitCommand2() {
4127
4753
  }
4128
4754
 
4129
4755
  // src/commands/hooks/list.ts
4130
- import { Command as Command33 } from "commander";
4756
+ import { Command as Command37 } from "commander";
4131
4757
  import * as fs10 from "fs";
4132
4758
  import * as path22 from "path";
4133
4759
  function listHooks(projectDir) {
@@ -4160,7 +4786,7 @@ function listHooks(projectDir) {
4160
4786
  return result;
4161
4787
  }
4162
4788
  function createListCommand() {
4163
- return new Command33("list").description("Show installed hooks and active profile").action(async (_opts, cmd) => {
4789
+ return new Command37("list").description("Show installed hooks and active profile").action(async (_opts, cmd) => {
4164
4790
  const globalOpts = cmd.optsWithGlobals();
4165
4791
  const projectDir = process.cwd();
4166
4792
  const result = listHooks(projectDir);
@@ -4181,7 +4807,7 @@ function createListCommand() {
4181
4807
  }
4182
4808
 
4183
4809
  // src/commands/hooks/remove.ts
4184
- import { Command as Command34 } from "commander";
4810
+ import { Command as Command38 } from "commander";
4185
4811
  import * as fs11 from "fs";
4186
4812
  import * as path23 from "path";
4187
4813
  function removeHooks(projectDir) {
@@ -4211,7 +4837,7 @@ function removeHooks(projectDir) {
4211
4837
  return { removed, hooksDir, settingsCleaned };
4212
4838
  }
4213
4839
  function createRemoveCommand() {
4214
- return new Command34("remove").description("Remove harness-managed hooks from the current project").action(async (_opts, cmd) => {
4840
+ return new Command38("remove").description("Remove harness-managed hooks from the current project").action(async (_opts, cmd) => {
4215
4841
  const globalOpts = cmd.optsWithGlobals();
4216
4842
  const projectDir = process.cwd();
4217
4843
  const result = removeHooks(projectDir);
@@ -4233,7 +4859,7 @@ function createRemoveCommand() {
4233
4859
  }
4234
4860
 
4235
4861
  // src/commands/hooks/add.ts
4236
- import { Command as Command35 } from "commander";
4862
+ import { Command as Command39 } from "commander";
4237
4863
  import * as fs12 from "fs";
4238
4864
  import * as path24 from "path";
4239
4865
  import { fileURLToPath as fileURLToPath3 } from "url";
@@ -4290,7 +4916,7 @@ function addHooks(hookName, projectDir) {
4290
4916
  return result;
4291
4917
  }
4292
4918
  function createAddCommand2() {
4293
- return new Command35("add").argument("<hook-name>", "Hook name or alias (e.g., sentinel)").description("Add a hook without changing the profile").action(async (hookName, _opts, cmd) => {
4919
+ return new Command39("add").argument("<hook-name>", "Hook name or alias (e.g., sentinel)").description("Add a hook without changing the profile").action(async (hookName, _opts, cmd) => {
4294
4920
  const projectDir = process.cwd();
4295
4921
  try {
4296
4922
  const res = addHooks(hookName, projectDir);
@@ -4315,7 +4941,7 @@ function createAddCommand2() {
4315
4941
 
4316
4942
  // src/commands/hooks/index.ts
4317
4943
  function createHooksCommand() {
4318
- const command = new Command36("hooks").description("Manage Claude Code hook configurations");
4944
+ const command = new Command40("hooks").description("Manage Claude Code hook configurations");
4319
4945
  command.addCommand(createInitCommand2());
4320
4946
  command.addCommand(createListCommand());
4321
4947
  command.addCommand(createRemoveCommand());
@@ -4324,7 +4950,7 @@ function createHooksCommand() {
4324
4950
  }
4325
4951
 
4326
4952
  // src/commands/impact-preview.ts
4327
- import { Command as Command37 } from "commander";
4953
+ import { Command as Command41 } from "commander";
4328
4954
  import { execSync as execSync4 } from "child_process";
4329
4955
  import * as path25 from "path";
4330
4956
  import * as fs13 from "fs";
@@ -4523,7 +5149,7 @@ async function runImpactPreview(options) {
4523
5149
  return formatImpactOutput(stagedFiles, acc, options);
4524
5150
  }
4525
5151
  function createImpactPreviewCommand() {
4526
- const command = new Command37("impact-preview").description("Show blast radius of staged changes using the knowledge graph").option("--detailed", "Show all affected files instead of top items").option("--per-file", "Show impact per staged file instead of aggregate").option("--path <dir>", "Project root (default: cwd)").action(async (opts) => {
5152
+ const command = new Command41("impact-preview").description("Show blast radius of staged changes using the knowledge graph").option("--detailed", "Show all affected files instead of top items").option("--per-file", "Show impact per staged file instead of aggregate").option("--path <dir>", "Project root (default: cwd)").action(async (opts) => {
4527
5153
  const output = await runImpactPreview({
4528
5154
  detailed: opts.detailed,
4529
5155
  perFile: opts.perFile,
@@ -4537,13 +5163,13 @@ function createImpactPreviewCommand() {
4537
5163
 
4538
5164
  // src/commands/init.ts
4539
5165
  init_dist3();
4540
- import { Command as Command39 } from "commander";
5166
+ import { Command as Command43 } from "commander";
4541
5167
  import chalk3 from "chalk";
4542
5168
  import * as fs16 from "fs";
4543
5169
  import * as path28 from "path";
4544
5170
 
4545
5171
  // src/commands/setup-mcp.ts
4546
- import { Command as Command38 } from "commander";
5172
+ import { Command as Command42 } from "commander";
4547
5173
  import * as fs15 from "fs";
4548
5174
  import * as path27 from "path";
4549
5175
  import * as os2 from "os";
@@ -4715,7 +5341,31 @@ var ALL_MCP_TOOLS = [
4715
5341
  "summarize_session",
4716
5342
  "insights_summary",
4717
5343
  // Hermes Phase 4 — agent-emitted skill proposals
4718
- "emit_skill_proposal"
5344
+ "emit_skill_proposal",
5345
+ // design-pipeline #2 — component-anatomy audit (ANAT-D* findings)
5346
+ "audit_anatomy",
5347
+ // design-pipeline #6 — design-craft LLM-judgment skill (CRITIQUE / POLISH / BENCHMARK)
5348
+ "design_craft",
5349
+ // design-pipeline #1 (detect half) — design-system drift detection
5350
+ "detect_drift",
5351
+ // design-pipeline #1 (align half) — apply codemods + emit suggestions
5352
+ "align_design_system",
5353
+ // design-pipeline #3 — brand-semantics audit (BRAND-T* + BRAND-V001)
5354
+ "audit_brand",
5355
+ // design-pipeline #5 — orchestrator composing all design verifiers
5356
+ "run_design_pipeline",
5357
+ // craft-pipeline #1 — naming-craft LLM-judgment ceiling skill
5358
+ "naming_craft",
5359
+ // craft-pipeline #6 — spec-craft LLM-judgment ceiling skill
5360
+ "spec_craft",
5361
+ // craft-pipeline #5 — copy-craft LLM-judgment ceiling skill (6 surfaces)
5362
+ "copy_craft",
5363
+ // craft-pipeline #3 — test-craft LLM-judgment ceiling skill (vitest/jest/mocha/playwright)
5364
+ "test_craft",
5365
+ // craft-pipeline #9 — knowledge-craft LLM-judgment ceiling skill (docs/knowledge/ entries)
5366
+ "knowledge_craft",
5367
+ // craft-pipeline #10 — security-craft LLM-judgment ceiling skill (AST-driven, conservative-confidence)
5368
+ "security_craft"
4719
5369
  ];
4720
5370
  async function runCursorToolPicker() {
4721
5371
  try {
@@ -4888,7 +5538,7 @@ function printMcpResult(configured, skipped, trustedFolder) {
4888
5538
  console.log("");
4889
5539
  }
4890
5540
  function createSetupMcpCommand() {
4891
- return new Command38("setup-mcp").description("Configure MCP server for AI agent integration").option(
5541
+ return new Command42("setup-mcp").description("Configure MCP server for AI agent integration").option(
4892
5542
  "--client <client>",
4893
5543
  "Client to configure (claude, gemini, codex, cursor, opencode, all)",
4894
5544
  "all"
@@ -5034,7 +5684,7 @@ async function runInitAction2(opts) {
5034
5684
  process.exit(ExitCode.SUCCESS);
5035
5685
  }
5036
5686
  function createInitCommand3() {
5037
- const command = new Command39("init").description("Initialize a new harness-engineering project").option("-n, --name <name>", "Project name").option("-l, --level <level>", "Adoption level (basic, intermediate, advanced)", "basic").option("-t, --template <template>", "Specific template name (e.g. orchestrator)").option("--framework <framework>", "Framework overlay (nextjs)").option("--language <language>", "Target language (typescript, python, go, rust, java)").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use defaults without prompting").action(async (opts, cmd) => {
5687
+ const command = new Command43("init").description("Initialize a new harness-engineering project").option("-n, --name <name>", "Project name").option("-l, --level <level>", "Adoption level (basic, intermediate, advanced)", "basic").option("-t, --template <template>", "Specific template name (e.g. orchestrator)").option("--framework <framework>", "Framework overlay (nextjs)").option("--language <language>", "Target language (typescript, python, go, rust, java)").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use defaults without prompting").action(async (opts, cmd) => {
5038
5688
  const globalOpts = cmd.optsWithGlobals();
5039
5689
  await runInitAction2({
5040
5690
  name: opts.name,
@@ -5050,7 +5700,7 @@ function createInitCommand3() {
5050
5700
 
5051
5701
  // src/commands/insights.ts
5052
5702
  init_dist();
5053
- import { Command as Command40 } from "commander";
5703
+ import { Command as Command44 } from "commander";
5054
5704
  function parseSkip2(raw) {
5055
5705
  if (!raw) return [];
5056
5706
  const valid = new Set(INSIGHTS_KEYS);
@@ -5088,12 +5738,12 @@ function renderPretty(report) {
5088
5738
  }
5089
5739
  }
5090
5740
  function createInsightsCommand() {
5091
- return new Command40("insights").description(
5741
+ return new Command44("insights").description(
5092
5742
  "Composite project report \u2014 health, entropy, decay, attention, impact (Hermes Phase 1)."
5093
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) => {
5094
5744
  const cwd = process.cwd();
5095
5745
  const skip = parseSkip2(opts.skip);
5096
- const { composeInsights } = await import("./dist-OHDQBTSO.js");
5746
+ const { composeInsights } = await import("./dist-XIJWWQ5N.js");
5097
5747
  const report = await composeInsights(cwd, { skip });
5098
5748
  if (opts.json) {
5099
5749
  console.log(JSON.stringify(report, null, 2));
@@ -5108,7 +5758,7 @@ import * as fs21 from "fs";
5108
5758
  import * as os5 from "os";
5109
5759
  import * as path33 from "path";
5110
5760
  import { execFileSync as execFileSync3 } from "child_process";
5111
- import { Command as Command41 } from "commander";
5761
+ import { Command as Command45 } from "commander";
5112
5762
  import { parse as yamlParse } from "yaml";
5113
5763
 
5114
5764
  // src/registry/npm-client.ts
@@ -5669,7 +6319,7 @@ async function runInstall(skillName, options) {
5669
6319
  return result;
5670
6320
  }
5671
6321
  function createInstallCommand() {
5672
- const cmd = new Command41("install");
6322
+ const cmd = new Command45("install");
5673
6323
  cmd.description("Install skills from npm registry, local directory, or GitHub repository").argument("<skill>", 'Skill name, @harness-skills/scoped package, or "." for bulk install').option("--version <range>", "Semver range or exact version to install").option("--force", "Force reinstall even if same version is already installed").option(
5674
6324
  "--from <source>",
5675
6325
  "Install from local path, directory, or GitHub (github:owner/repo, https://github.com/owner/repo)"
@@ -5705,7 +6355,7 @@ function createInstallCommand() {
5705
6355
  init_dist3();
5706
6356
  import * as fs22 from "fs/promises";
5707
6357
  import * as path34 from "path";
5708
- import { Command as Command42 } from "commander";
6358
+ import { Command as Command46 } from "commander";
5709
6359
  import semver3 from "semver";
5710
6360
  async function runInstallConstraints(options) {
5711
6361
  const { source, configPath, lockfilePath } = options;
@@ -5959,17 +6609,17 @@ async function handleInstallConstraints(source, opts) {
5959
6609
  logInstallResult(result.value, opts);
5960
6610
  }
5961
6611
  function createInstallConstraintsCommand() {
5962
- const cmd = new Command42("install-constraints");
6612
+ const cmd = new Command46("install-constraints");
5963
6613
  cmd.description("Install a constraints bundle into the local harness config").argument("<source>", "Path to a .harness-constraints.json bundle file").option("--force-local", "Resolve all conflicts by keeping local values").option("--force-package", "Resolve all conflicts by using package values").option("--dry-run", "Show what would change without writing files").option("-c, --config <path>", "Path to harness.config.json").action(handleInstallConstraints);
5964
6614
  return cmd;
5965
6615
  }
5966
6616
 
5967
6617
  // src/commands/integrations/index.ts
5968
- import { Command as Command47 } from "commander";
6618
+ import { Command as Command51 } from "commander";
5969
6619
 
5970
6620
  // src/commands/integrations/add.ts
5971
6621
  init_dist3();
5972
- import { Command as Command43 } from "commander";
6622
+ import { Command as Command47 } from "commander";
5973
6623
  import * as fs23 from "fs";
5974
6624
  import * as path35 from "path";
5975
6625
  import chalk4 from "chalk";
@@ -6033,7 +6683,7 @@ function printAddSuccess(value) {
6033
6683
  }
6034
6684
  }
6035
6685
  function createAddIntegrationCommand() {
6036
- return new Command43("add").description("Enable an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6686
+ return new Command47("add").description("Enable an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6037
6687
  const globalOpts = cmd.optsWithGlobals();
6038
6688
  const result = addIntegration(process.cwd(), name);
6039
6689
  if (!result.ok) {
@@ -6047,7 +6697,7 @@ function createAddIntegrationCommand() {
6047
6697
  }
6048
6698
 
6049
6699
  // src/commands/integrations/list.ts
6050
- import { Command as Command44 } from "commander";
6700
+ import { Command as Command48 } from "commander";
6051
6701
  import * as path36 from "path";
6052
6702
  import chalk5 from "chalk";
6053
6703
  function printTier0Integrations(tier0, mcpServers) {
@@ -6104,12 +6754,12 @@ async function runListIntegrations(globalOpts) {
6104
6754
  process.exit(ExitCode.SUCCESS);
6105
6755
  }
6106
6756
  function createListIntegrationsCommand() {
6107
- return new Command44("list").description("Show all MCP integrations with status").action(async (_opts, cmd) => runListIntegrations(cmd.optsWithGlobals()));
6757
+ return new Command48("list").description("Show all MCP integrations with status").action(async (_opts, cmd) => runListIntegrations(cmd.optsWithGlobals()));
6108
6758
  }
6109
6759
 
6110
6760
  // src/commands/integrations/remove.ts
6111
6761
  init_dist3();
6112
- import { Command as Command45 } from "commander";
6762
+ import { Command as Command49 } from "commander";
6113
6763
  import * as fs24 from "fs";
6114
6764
  import * as path37 from "path";
6115
6765
  function removeIntegration(cwd, name) {
@@ -6136,7 +6786,7 @@ function removeIntegration(cwd, name) {
6136
6786
  return Ok(def.displayName);
6137
6787
  }
6138
6788
  function createRemoveIntegrationCommand() {
6139
- return new Command45("remove").description("Remove an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6789
+ return new Command49("remove").description("Remove an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6140
6790
  const globalOpts = cmd.optsWithGlobals();
6141
6791
  const cwd = process.cwd();
6142
6792
  const result = removeIntegration(cwd, name);
@@ -6158,7 +6808,7 @@ function createRemoveIntegrationCommand() {
6158
6808
 
6159
6809
  // src/commands/integrations/dismiss.ts
6160
6810
  init_dist3();
6161
- import { Command as Command46 } from "commander";
6811
+ import { Command as Command50 } from "commander";
6162
6812
  import * as path38 from "path";
6163
6813
  function dismissIntegration(cwd, name) {
6164
6814
  const def = INTEGRATION_REGISTRY.find((i) => i.name === name);
@@ -6180,7 +6830,7 @@ function dismissIntegration(cwd, name) {
6180
6830
  return Ok(def.displayName);
6181
6831
  }
6182
6832
  function createDismissIntegrationCommand() {
6183
- return new Command46("dismiss").description("Suppress doctor recommendations for an integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6833
+ return new Command50("dismiss").description("Suppress doctor recommendations for an integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6184
6834
  const globalOpts = cmd.optsWithGlobals();
6185
6835
  const cwd = process.cwd();
6186
6836
  const result = dismissIntegration(cwd, name);
@@ -6204,7 +6854,7 @@ function createDismissIntegrationCommand() {
6204
6854
 
6205
6855
  // src/commands/integrations/index.ts
6206
6856
  function createIntegrationsCommand() {
6207
- const command = new Command47("integrations").description(
6857
+ const command = new Command51("integrations").description(
6208
6858
  "Manage MCP peer integrations (add, list, remove, dismiss)"
6209
6859
  );
6210
6860
  command.addCommand(createListIntegrationsCommand());
@@ -6214,20 +6864,87 @@ function createIntegrationsCommand() {
6214
6864
  return command;
6215
6865
  }
6216
6866
 
6867
+ // src/commands/knowledge-craft.ts
6868
+ import { Command as Command52 } from "commander";
6869
+ function createKnowledgeCraftCommand() {
6870
+ return new Command52("knowledge-craft").description(
6871
+ "LLM-judgment critique of knowledge-entry quality (docs/knowledge/, excluding decisions/). Fifth non-design craft-pipeline ceiling skill; 7 seed rubrics (load-bearing-fact, earns-graph-place, carries-forward-decision, \u2026). Per-file critique."
6872
+ ).option("-f, --files <files...>", "Optional file scope (overrides discovery)").option(
6873
+ "--exclude-dirs <dirs...>",
6874
+ "Additional subdir names to skip (decisions is always excluded)"
6875
+ ).option("--max-files <n>", "Cap entry count (default: 50)").action(async (opts, cmd) => {
6876
+ const globalOpts = cmd.optsWithGlobals();
6877
+ const outputMode = resolveOutputMode(globalOpts);
6878
+ const formatter = new OutputFormatter(outputMode);
6879
+ const cwd = globalOpts.cwd ?? process.cwd();
6880
+ const input = { path: cwd };
6881
+ if (opts.files !== void 0) input.files = opts.files;
6882
+ if (opts.excludeDirs !== void 0) input.excludeDirs = opts.excludeDirs;
6883
+ if (opts.maxFiles !== void 0) input.maxFiles = parseInt(opts.maxFiles, 10);
6884
+ let result;
6885
+ try {
6886
+ result = await runKnowledgeCraft(input);
6887
+ } catch (err) {
6888
+ const message = err instanceof Error ? err.message : String(err);
6889
+ if (outputMode === OutputMode.JSON) {
6890
+ console.log(JSON.stringify({ error: message }));
6891
+ } else {
6892
+ logger.error(`knowledge-craft failed: ${message}`);
6893
+ }
6894
+ process.exit(ExitCode.ERROR);
6895
+ return;
6896
+ }
6897
+ if (outputMode === OutputMode.JSON) {
6898
+ console.log(JSON.stringify(result, null, 2));
6899
+ } else {
6900
+ printResult3(result, outputMode, formatter);
6901
+ }
6902
+ const hasFoundational = result.findings.some((f) => f.tier === "foundational");
6903
+ process.exit(hasFoundational ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS);
6904
+ });
6905
+ }
6906
+ function printResult3(result, mode, _formatter) {
6907
+ const verbose = mode === OutputMode.VERBOSE;
6908
+ const { findings, summary } = result;
6909
+ if (findings.length === 0) {
6910
+ console.log("No knowledge-entry findings.");
6911
+ } else {
6912
+ const byFile = /* @__PURE__ */ new Map();
6913
+ for (const f of findings) {
6914
+ const list = byFile.get(f.target.file) ?? [];
6915
+ list.push(f);
6916
+ byFile.set(f.target.file, list);
6917
+ }
6918
+ for (const [file, fs47] of byFile) {
6919
+ console.log(`
6920
+ ${file}`);
6921
+ for (const f of fs47) {
6922
+ console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.relative}`);
6923
+ console.log(` ${f.message}`);
6924
+ if (verbose) console.log(` source: ${f.cite.source}`);
6925
+ }
6926
+ }
6927
+ }
6928
+ console.log("");
6929
+ console.log(
6930
+ `Summary: ${findings.length} findings across ${summary.counts.filesScanned} entries (${summary.counts.filesSkipped} skipped, ${summary.catalog.rubricsApplied.length} rubrics, ${summary.llmCalls.count} LLM calls, $${summary.llmCalls.costUsd.toFixed(4)}, ${summary.durationMs}ms)`
6931
+ );
6932
+ }
6933
+
6217
6934
  // src/commands/knowledge-pipeline.ts
6218
- import { Command as Command48 } from "commander";
6935
+ import { Command as Command53 } from "commander";
6219
6936
  import * as path39 from "path";
6220
6937
  import chalk6 from "chalk";
6221
6938
  function createKnowledgePipelineCommand() {
6222
- return new Command48("knowledge-pipeline").description("Run knowledge extraction, drift detection, and gap analysis").option("--fix", "Enable convergence-based auto-remediation (default: detect-only)").option("--ci", "Non-interactive mode \u2014 apply safe fixes only, report everything else").option("--domain <name>", "Limit pipeline to a specific knowledge domain").option("--drift-check", "Exit 1 if unresolved drift exists (CI gate mode)").option("--analyze-images", "Enable vision model analysis of image files").option("--image-paths <paths>", "Comma-separated image file paths for analysis").option("--coverage", "Display per-domain coverage report").option("--check-contradictions", "Display cross-source contradiction report").action(async (opts, cmd) => {
6939
+ return new Command53("knowledge-pipeline").description("Run knowledge extraction, drift detection, and gap analysis").option("--fix", "Enable convergence-based auto-remediation (default: detect-only)").option("--ci", "Non-interactive mode \u2014 apply safe fixes only, report everything else").option("--domain <name>", "Limit pipeline to a specific knowledge domain").option("--drift-check", "Exit 1 if unresolved drift exists (CI gate mode)").option("--analyze-images", "Enable vision model analysis of image files").option("--image-paths <paths>", "Comma-separated image file paths for analysis").option("--coverage", "Display per-domain coverage report").option("--check-contradictions", "Display cross-source contradiction report").action(async (opts, cmd) => {
6223
6940
  const globalOpts = cmd.optsWithGlobals();
6224
6941
  const projectDir = process.cwd();
6225
6942
  try {
6226
6943
  const graphDir = path39.join(projectDir, ".harness", "graph");
6227
6944
  const fs47 = await import("fs/promises");
6228
6945
  await fs47.mkdir(graphDir, { recursive: true });
6229
- const { GraphStore, KnowledgePipelineRunner } = await import("./dist-QPWXPCPL.js");
6230
- const store = new GraphStore();
6946
+ const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-R3TOOPJ7.js");
6947
+ const store = new GraphStore2();
6231
6948
  try {
6232
6949
  await store.load(graphDir);
6233
6950
  } catch {
@@ -6383,11 +7100,11 @@ function createKnowledgePipelineCommand() {
6383
7100
  }
6384
7101
 
6385
7102
  // src/commands/learnings/index.ts
6386
- import { Command as Command50 } from "commander";
7103
+ import { Command as Command55 } from "commander";
6387
7104
 
6388
7105
  // src/commands/learnings/prune.ts
6389
7106
  init_dist3();
6390
- import { Command as Command49 } from "commander";
7107
+ import { Command as Command54 } from "commander";
6391
7108
  import * as path40 from "path";
6392
7109
  async function handlePrune(opts) {
6393
7110
  const projectPath = path40.resolve(opts.path);
@@ -6429,23 +7146,23 @@ function printPatternProposals(patterns) {
6429
7146
  );
6430
7147
  }
6431
7148
  function createPruneCommand() {
6432
- return new Command49("prune").description(
7149
+ return new Command54("prune").description(
6433
7150
  "Analyze global learnings for patterns, present improvement proposals, and archive old entries"
6434
7151
  ).option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(handlePrune);
6435
7152
  }
6436
7153
 
6437
7154
  // src/commands/learnings/index.ts
6438
7155
  function createLearningsCommand() {
6439
- const command = new Command50("learnings").description("Learnings management commands");
7156
+ const command = new Command55("learnings").description("Learnings management commands");
6440
7157
  command.addCommand(createPruneCommand());
6441
7158
  return command;
6442
7159
  }
6443
7160
 
6444
7161
  // src/commands/linter/index.ts
6445
- import { Command as Command53 } from "commander";
7162
+ import { Command as Command58 } from "commander";
6446
7163
 
6447
7164
  // src/commands/linter/generate.ts
6448
- import { Command as Command51 } from "commander";
7165
+ import { Command as Command56 } from "commander";
6449
7166
  function formatGenerateError(e) {
6450
7167
  switch (e.type) {
6451
7168
  case "parse":
@@ -6489,7 +7206,7 @@ function handleSuccess(result, useJson) {
6489
7206
  Generated ${result.rulesGenerated.length} rules to ${result.outputDir}`);
6490
7207
  }
6491
7208
  function createGenerateCommand2() {
6492
- return new Command51("generate").description("Generate ESLint rules from harness-linter.yml").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("-o, --output <dir>", "Override output directory").option("--clean", "Remove existing files before generating").option("--dry-run", "Preview without writing files").option("--json", "Output as JSON").option("--verbose", "Show detailed output").action(async (options) => {
7209
+ return new Command56("generate").description("Generate ESLint rules from harness-linter.yml").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("-o, --output <dir>", "Override output directory").option("--clean", "Remove existing files before generating").option("--dry-run", "Preview without writing files").option("--json", "Output as JSON").option("--verbose", "Show detailed output").action(async (options) => {
6493
7210
  try {
6494
7211
  if (options.verbose) logger.info(`Parsing config: ${options.config}`);
6495
7212
  const result = await generate({
@@ -6511,9 +7228,9 @@ function createGenerateCommand2() {
6511
7228
  }
6512
7229
 
6513
7230
  // src/commands/linter/validate.ts
6514
- import { Command as Command52 } from "commander";
7231
+ import { Command as Command57 } from "commander";
6515
7232
  function createValidateCommand() {
6516
- return new Command52("validate").description("Validate harness-linter.yml config").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("--json", "Output as JSON").action(async (options) => {
7233
+ return new Command57("validate").description("Validate harness-linter.yml config").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("--json", "Output as JSON").action(async (options) => {
6517
7234
  try {
6518
7235
  const result = await validate({ configPath: options.config });
6519
7236
  if (options.json) {
@@ -6532,7 +7249,7 @@ function createValidateCommand() {
6532
7249
 
6533
7250
  // src/commands/linter/index.ts
6534
7251
  function createLinterCommand() {
6535
- const linter = new Command53("linter").description(
7252
+ const linter = new Command58("linter").description(
6536
7253
  "Generate and validate ESLint rules from YAML config"
6537
7254
  );
6538
7255
  linter.addCommand(createGenerateCommand2());
@@ -6541,7 +7258,7 @@ function createLinterCommand() {
6541
7258
  }
6542
7259
 
6543
7260
  // src/commands/maintenance.ts
6544
- import { Command as Command54 } from "commander";
7261
+ import { Command as Command59 } from "commander";
6545
7262
  import * as path41 from "path";
6546
7263
  import * as fs25 from "fs";
6547
7264
  import chalk7 from "chalk";
@@ -6556,6 +7273,7 @@ async function loadMaintenanceConfig(cwd) {
6556
7273
  const loader = new WorkflowLoader();
6557
7274
  const result = await loader.loadWorkflow(workflowPath);
6558
7275
  if (!result.ok) return null;
7276
+ for (const w of result.value.warnings) logger.warn(w);
6559
7277
  return result.value.config.maintenance ?? null;
6560
7278
  }
6561
7279
  function mergeResolvedTasks(config) {
@@ -6632,7 +7350,7 @@ function printListTable(rows) {
6632
7350
  }
6633
7351
  }
6634
7352
  function createMaintenanceCommand() {
6635
- const command = new Command54("maintenance").description(
7353
+ const command = new Command59("maintenance").description(
6636
7354
  "Hermes Phase 2 \u2014 inspect built-in + custom maintenance tasks and their persisted outputs"
6637
7355
  );
6638
7356
  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) => {
@@ -6700,7 +7418,7 @@ function describeOrigin(origin) {
6700
7418
  }
6701
7419
 
6702
7420
  // src/commands/mcp.ts
6703
- import { Command as Command55 } from "commander";
7421
+ import { Command as Command60 } from "commander";
6704
7422
  var VALID_TIERS = /* @__PURE__ */ new Set(["core", "standard", "full"]);
6705
7423
  function parseTier(value) {
6706
7424
  const lower = value.toLowerCase();
@@ -6717,7 +7435,7 @@ function parseBudget(value) {
6717
7435
  return n;
6718
7436
  }
6719
7437
  function createMcpCommand() {
6720
- return new Command55("mcp").description("Start the MCP (Model Context Protocol) server on stdio").option("--tools <tools...>", "Only register the specified tools (used by Cursor integration)").option(
7438
+ return new Command60("mcp").description("Start the MCP (Model Context Protocol) server on stdio").option("--tools <tools...>", "Only register the specified tools (used by Cursor integration)").option(
6721
7439
  "--tier <core|standard|full>",
6722
7440
  "Load a preset tool tier instead of all tools",
6723
7441
  parseTier
@@ -6727,7 +7445,7 @@ function createMcpCommand() {
6727
7445
  parseBudget
6728
7446
  ).action(async (opts) => {
6729
7447
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
6730
- import("./mcp-YKKPWUMH.js"),
7448
+ import("./mcp-NEAPIDTT.js"),
6731
7449
  import("./tool-tiers-B7JC2XC3.js")
6732
7450
  ]);
6733
7451
  if (opts.tools && opts.tools.length > 0) {
@@ -6749,7 +7467,7 @@ function createMcpCommand() {
6749
7467
 
6750
7468
  // src/commands/mcp-guard.ts
6751
7469
  init_dist3();
6752
- import { Command as Command56 } from "commander";
7470
+ import { Command as Command61 } from "commander";
6753
7471
  import * as fs26 from "fs";
6754
7472
  import * as path42 from "path";
6755
7473
  import chalk8 from "chalk";
@@ -6857,7 +7575,7 @@ function formatHuman(result) {
6857
7575
  }
6858
7576
  }
6859
7577
  function createMcpGuardCommand() {
6860
- const command = new Command56("mcp-guard").description("Pre-launch OSV malware guard for MCP/npx packages").addHelpText(
7578
+ const command = new Command61("mcp-guard").description("Pre-launch OSV malware guard for MCP/npx packages").addHelpText(
6861
7579
  "after",
6862
7580
  '\nUse "harness mcp-guard check" before launching MCP servers to block known malicious packages.'
6863
7581
  );
@@ -6890,7 +7608,7 @@ function createMcpGuardCommand() {
6890
7608
  // src/commands/migrate.ts
6891
7609
  init_dist3();
6892
7610
  init_dist2();
6893
- import { Command as Command57 } from "commander";
7611
+ import { Command as Command62 } from "commander";
6894
7612
  import * as fs27 from "fs";
6895
7613
  import * as path43 from "path";
6896
7614
  import * as readline from "readline";
@@ -7296,7 +8014,7 @@ async function runMigrate(opts) {
7296
8014
  });
7297
8015
  }
7298
8016
  function createMigrateCommand() {
7299
- return new Command57("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(
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(
7300
8018
  "--skip-references",
7301
8019
  "Do not update path references in docs/sessions after moves",
7302
8020
  false
@@ -7317,12 +8035,87 @@ function createMigrateCommand() {
7317
8035
  });
7318
8036
  }
7319
8037
 
8038
+ // src/commands/naming-craft.ts
8039
+ import { Command as Command63 } from "commander";
8040
+ function createNamingCraftCommand() {
8041
+ return new Command63("naming-craft").description(
8042
+ "LLM-judgment critique of identifier names (variables, functions, types, files). First craft-pipeline ceiling skill; uses curated rubric catalog from Martin/Beck/Karlton."
8043
+ ).option("-f, --files <files...>", "Optional file/glob scope").option(
8044
+ "-k, --kinds <kinds...>",
8045
+ "Restrict to variable / function / type / file (default: all)"
8046
+ ).option("--max-files <n>", "Cap file count (default: 100)").option("--max-identifiers-per-file <n>", "Cap per-file identifier sampling (default: 15)").action(async (opts, cmd) => {
8047
+ const globalOpts = cmd.optsWithGlobals();
8048
+ const outputMode = resolveOutputMode(globalOpts);
8049
+ const formatter = new OutputFormatter(outputMode);
8050
+ const cwd = globalOpts.cwd ?? process.cwd();
8051
+ const input = { path: cwd };
8052
+ if (opts.files !== void 0) input.files = opts.files;
8053
+ if (opts.kinds !== void 0) input.kinds = opts.kinds;
8054
+ if (opts.maxFiles !== void 0) input.maxFiles = parseInt(opts.maxFiles, 10);
8055
+ if (opts.maxIdentifiersPerFile !== void 0)
8056
+ input.maxIdentifiersPerFile = parseInt(opts.maxIdentifiersPerFile, 10);
8057
+ let result;
8058
+ try {
8059
+ result = await runNamingCraft(input);
8060
+ } catch (err) {
8061
+ const message = err instanceof Error ? err.message : String(err);
8062
+ if (outputMode === OutputMode.JSON) {
8063
+ console.log(JSON.stringify({ error: message }));
8064
+ } else {
8065
+ logger.error(`naming-craft failed: ${message}`);
8066
+ }
8067
+ process.exit(ExitCode.ERROR);
8068
+ return;
8069
+ }
8070
+ if (outputMode === OutputMode.JSON) {
8071
+ console.log(JSON.stringify(result, null, 2));
8072
+ } else {
8073
+ printResult4(result, outputMode, formatter);
8074
+ }
8075
+ const hasError = result.findings.some((f) => f.tier === "foundational");
8076
+ process.exit(hasError ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS);
8077
+ });
8078
+ }
8079
+ function printResult4(result, mode, _formatter) {
8080
+ const verbose = mode === OutputMode.VERBOSE;
8081
+ const { findings, summary } = result;
8082
+ if (findings.length === 0) {
8083
+ console.log("No naming findings.");
8084
+ } else {
8085
+ const byFile = /* @__PURE__ */ new Map();
8086
+ for (const f of findings) {
8087
+ const list = byFile.get(f.target.file) ?? [];
8088
+ list.push(f);
8089
+ byFile.set(f.target.file, list);
8090
+ }
8091
+ for (const [file, fs47] of byFile) {
8092
+ console.log(`
8093
+ ${file}`);
8094
+ for (const f of fs47) {
8095
+ const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
8096
+ console.log(
8097
+ ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.kind} ${f.target.identifier}${line}`
8098
+ );
8099
+ console.log(` ${f.message}`);
8100
+ if (verbose) console.log(` source: ${f.cite.source}`);
8101
+ }
8102
+ }
8103
+ }
8104
+ console.log("");
8105
+ console.log(
8106
+ `Summary: ${findings.length} findings (rubrics: ${summary.catalog.rubricsApplied.length}, LLM calls: ${summary.llmCalls.count}, cost: $${summary.llmCalls.costUsd.toFixed(4)}, ${summary.durationMs}ms)`
8107
+ );
8108
+ console.log(
8109
+ `Convention: vars=${summary.convention.variables ?? "?"}, funcs=${summary.convention.functions ?? "?"}, types=${summary.convention.types ?? "?"}, files=${summary.convention.files ?? "?"}`
8110
+ );
8111
+ }
8112
+
7320
8113
  // src/commands/notifications/index.ts
7321
- import { Command as Command59 } from "commander";
8114
+ import { Command as Command65 } from "commander";
7322
8115
 
7323
8116
  // src/commands/notifications/test.ts
7324
8117
  init_dist3();
7325
- import { Command as Command58 } from "commander";
8118
+ import { Command as Command64 } from "commander";
7326
8119
  import { randomBytes } from "crypto";
7327
8120
  import { resolve as resolve28 } from "path";
7328
8121
  import { SinkRegistry, SinkConfigError, wrapAsEnvelope } from "@harness-engineering/orchestrator";
@@ -7374,7 +8167,7 @@ async function runNotificationsTest(sinkId, opts, projectRoot2 = process.cwd())
7374
8167
  return { ok: false, error: result.error };
7375
8168
  }
7376
8169
  function createNotificationsTestSubcommand() {
7377
- return new Command58("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) => {
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) => {
7378
8171
  const globalOpts = cmd.optsWithGlobals();
7379
8172
  const projectRoot2 = typeof globalOpts["cwd"] === "string" ? resolve28(globalOpts["cwd"]) : process.cwd();
7380
8173
  const result = await runNotificationsTest(sinkId, opts, projectRoot2);
@@ -7391,7 +8184,7 @@ function createNotificationsTestSubcommand() {
7391
8184
 
7392
8185
  // src/commands/notifications/index.ts
7393
8186
  function createNotificationsCommand() {
7394
- const cmd = new Command59("notifications").description(
8187
+ const cmd = new Command65("notifications").description(
7395
8188
  "Manage notification sinks (Slack and others)"
7396
8189
  );
7397
8190
  cmd.addCommand(createNotificationsTestSubcommand());
@@ -7399,11 +8192,11 @@ function createNotificationsCommand() {
7399
8192
  }
7400
8193
 
7401
8194
  // src/commands/orchestrator.ts
7402
- import { Command as Command60 } from "commander";
8195
+ import { Command as Command66 } from "commander";
7403
8196
  import * as path44 from "path";
7404
8197
  import { Orchestrator, WorkflowLoader as WorkflowLoader2, launchTUI } from "@harness-engineering/orchestrator";
7405
8198
  function createOrchestratorCommand() {
7406
- const orchestrator = new Command60("orchestrator");
8199
+ const orchestrator = new Command66("orchestrator");
7407
8200
  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) => {
7408
8201
  const workflowPath = path44.resolve(process.cwd(), opts.workflow);
7409
8202
  const loader = new WorkflowLoader2();
@@ -7412,7 +8205,8 @@ function createOrchestratorCommand() {
7412
8205
  logger.error(`Failed to load workflow: ${result.error.message}`);
7413
8206
  process.exit(ExitCode.ERROR);
7414
8207
  }
7415
- const { config, promptTemplate } = result.value;
8208
+ const { config, promptTemplate, warnings } = result.value;
8209
+ for (const w of warnings) logger.warn(w);
7416
8210
  const daemon = new Orchestrator(config, promptTemplate);
7417
8211
  const shutdown = () => {
7418
8212
  daemon.stop();
@@ -7438,13 +8232,13 @@ function createOrchestratorCommand() {
7438
8232
 
7439
8233
  // src/commands/perf.ts
7440
8234
  init_dist3();
7441
- import { Command as Command61 } from "commander";
8235
+ import { Command as Command67 } from "commander";
7442
8236
  import * as path45 from "path";
7443
8237
  function registerBenchCommand(perf) {
7444
8238
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
7445
8239
  const globalOpts = cmd.optsWithGlobals();
7446
8240
  const cwd = process.cwd();
7447
- const { BenchmarkRunner } = await import("./dist-OHDQBTSO.js");
8241
+ const { BenchmarkRunner } = await import("./dist-XIJWWQ5N.js");
7448
8242
  const runner = new BenchmarkRunner();
7449
8243
  const benchFiles = runner.discover(cwd, glob2);
7450
8244
  if (benchFiles.length === 0) {
@@ -7508,7 +8302,7 @@ async function runBaselinesShow(globalOpts) {
7508
8302
  }
7509
8303
  async function runBaselinesUpdate(globalOpts) {
7510
8304
  const cwd = process.cwd();
7511
- const { BenchmarkRunner } = await import("./dist-OHDQBTSO.js");
8305
+ const { BenchmarkRunner } = await import("./dist-XIJWWQ5N.js");
7512
8306
  const runner = new BenchmarkRunner();
7513
8307
  const manager = new BaselineManager(cwd);
7514
8308
  logger.info("Running benchmarks to update baselines...");
@@ -7549,7 +8343,7 @@ function registerReportCommand(perf) {
7549
8343
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
7550
8344
  const globalOpts = cmd.optsWithGlobals();
7551
8345
  const cwd = process.cwd();
7552
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-OHDQBTSO.js");
8346
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-XIJWWQ5N.js");
7553
8347
  const analyzer = new EntropyAnalyzer2({
7554
8348
  rootDir: path45.resolve(cwd),
7555
8349
  analyze: { complexity: true, coupling: true }
@@ -7610,7 +8404,7 @@ function registerCriticalPathsCommand(perf) {
7610
8404
  });
7611
8405
  }
7612
8406
  function createPerfCommand() {
7613
- const perf = new Command61("perf").description("Performance benchmark and baseline management");
8407
+ const perf = new Command67("perf").description("Performance benchmark and baseline management");
7614
8408
  registerBenchCommand(perf);
7615
8409
  registerBaselinesCommands(perf);
7616
8410
  registerReportCommand(perf);
@@ -7619,10 +8413,10 @@ function createPerfCommand() {
7619
8413
  }
7620
8414
 
7621
8415
  // src/commands/persona/index.ts
7622
- import { Command as Command64 } from "commander";
8416
+ import { Command as Command70 } from "commander";
7623
8417
 
7624
8418
  // src/commands/persona/list.ts
7625
- import { Command as Command62 } from "commander";
8419
+ import { Command as Command68 } from "commander";
7626
8420
  function printPersonaList(personas) {
7627
8421
  if (personas.length === 0) {
7628
8422
  logger.info("No personas found.");
@@ -7636,7 +8430,7 @@ function printPersonaList(personas) {
7636
8430
  }
7637
8431
  }
7638
8432
  function createListCommand2() {
7639
- return new Command62("list").description("List available agent personas").action(async (_opts, cmd) => {
8433
+ return new Command68("list").description("List available agent personas").action(async (_opts, cmd) => {
7640
8434
  const globalOpts = cmd.optsWithGlobals();
7641
8435
  const personasDir = resolvePersonasDir();
7642
8436
  const result = listPersonas(personasDir);
@@ -7656,7 +8450,7 @@ function createListCommand2() {
7656
8450
  }
7657
8451
 
7658
8452
  // src/commands/persona/generate.ts
7659
- import { Command as Command63 } from "commander";
8453
+ import { Command as Command69 } from "commander";
7660
8454
  import * as fs28 from "fs";
7661
8455
  import * as path46 from "path";
7662
8456
  function generatePersonaArtifacts(persona, outputDir, only) {
@@ -7691,7 +8485,7 @@ function generatePersonaArtifacts(persona, outputDir, only) {
7691
8485
  return generated;
7692
8486
  }
7693
8487
  function createGenerateCommand3() {
7694
- return new Command63("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) => {
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) => {
7695
8489
  const globalOpts = cmd.optsWithGlobals();
7696
8490
  const personaResult = loadPersona(path46.join(resolvePersonasDir(), `${name}.yaml`));
7697
8491
  if (!personaResult.ok) {
@@ -7713,7 +8507,7 @@ function createGenerateCommand3() {
7713
8507
 
7714
8508
  // src/commands/persona/index.ts
7715
8509
  function createPersonaCommand() {
7716
- const command = new Command64("persona").description("Agent persona management commands");
8510
+ const command = new Command70("persona").description("Agent persona management commands");
7717
8511
  command.addCommand(createListCommand2());
7718
8512
  command.addCommand(createGenerateCommand3());
7719
8513
  return command;
@@ -7721,7 +8515,7 @@ function createPersonaCommand() {
7721
8515
 
7722
8516
  // src/commands/predict.ts
7723
8517
  init_dist3();
7724
- import { Command as Command65 } from "commander";
8518
+ import { Command as Command71 } from "commander";
7725
8519
  import chalk10 from "chalk";
7726
8520
  var CATEGORY_ORDER = [
7727
8521
  "circular-deps",
@@ -7827,7 +8621,7 @@ function handlePredictError(err, mode) {
7827
8621
  process.exit(ExitCode.ERROR);
7828
8622
  }
7829
8623
  function createPredictCommand() {
7830
- const command = new Command65("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) => {
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) => {
7831
8625
  const globalOpts = cmd.optsWithGlobals();
7832
8626
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
7833
8627
  try {
@@ -7851,7 +8645,7 @@ function createPredictCommand() {
7851
8645
 
7852
8646
  // src/commands/proposals.ts
7853
8647
  init_dist3();
7854
- import { Command as Command66 } from "commander";
8648
+ import { Command as Command72 } from "commander";
7855
8649
  import { resolve as resolve32 } from "path";
7856
8650
  function projectRoot() {
7857
8651
  return resolve32(process.env["HARNESS_PROJECT_ROOT"] ?? process.cwd());
@@ -7946,7 +8740,7 @@ async function actApproveCommand(id) {
7946
8740
  }
7947
8741
  }
7948
8742
  function createProposalsCommand() {
7949
- const cmd = new Command66("proposals").description("Skill-proposal review queue (Hermes Phase 4)");
8743
+ const cmd = new Command72("proposals").description("Skill-proposal review queue (Hermes Phase 4)");
7950
8744
  cmd.command("list").description("List skill proposals in the local queue").option(
7951
8745
  "--status <status>",
7952
8746
  `Filter by status \u2014 one of ${ALLOWED_STATUSES.join(" | ")}`,
@@ -7963,7 +8757,7 @@ function createProposalsCommand() {
7963
8757
  // src/commands/publish-analyses.ts
7964
8758
  import * as fs29 from "fs";
7965
8759
  import * as path47 from "path";
7966
- import { Command as Command67 } from "commander";
8760
+ import { Command as Command73 } from "commander";
7967
8761
  init_dist3();
7968
8762
  import {
7969
8763
  renderAnalysisComment,
@@ -8076,7 +8870,7 @@ async function runPublishAnalyses(opts) {
8076
8870
  const nameToExternalId = await buildNameToExternalIdMap(projectPath);
8077
8871
  if (!nameToExternalId) return process.exit(1);
8078
8872
  const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
8079
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-OHDQBTSO.js");
8873
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-XIJWWQ5N.js");
8080
8874
  const archive = new AnalysisArchive(path47.join(projectPath, ".harness", "analyses"));
8081
8875
  const analyses = await archive.list();
8082
8876
  if (analyses.length === 0) {
@@ -8099,7 +8893,7 @@ async function runPublishAnalyses(opts) {
8099
8893
  }
8100
8894
  }
8101
8895
  function createPublishAnalysesCommand() {
8102
- const command = new Command67("publish-analyses").description(
8896
+ const command = new Command73("publish-analyses").description(
8103
8897
  "Publishes locally generated intelligence analyses to the external issue tracker (e.g., GitHub)"
8104
8898
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
8105
8899
  try {
@@ -8115,13 +8909,13 @@ function createPublishAnalysesCommand() {
8115
8909
  }
8116
8910
 
8117
8911
  // src/commands/pulse/index.ts
8118
- import { Command as Command69 } from "commander";
8912
+ import { Command as Command75 } from "commander";
8119
8913
 
8120
8914
  // src/commands/pulse/run.ts
8121
8915
  init_dist3();
8122
8916
  import { readFileSync as readFileSync18, mkdirSync as mkdirSync13, writeFileSync as writeFileSync15 } from "fs";
8123
8917
  import { dirname as dirname17, join as join38, resolve as resolve34 } from "path";
8124
- import { Command as Command68 } from "commander";
8918
+ import { Command as Command74 } from "commander";
8125
8919
  async function runPulseRunCommand(opts) {
8126
8920
  const startedAt = Date.now();
8127
8921
  let raw;
@@ -8186,7 +8980,7 @@ function emit2(status, nonInteractive) {
8186
8980
  return status;
8187
8981
  }
8188
8982
  function createRunCommand2() {
8189
- return new Command68("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
8983
+ return new Command74("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
8190
8984
  "--lookback <window>",
8191
8985
  "Lookback window (e.g. 24h, 7d). Defaults to pulse.lookbackDefault."
8192
8986
  ).option(
@@ -8210,13 +9004,13 @@ function createRunCommand2() {
8210
9004
 
8211
9005
  // src/commands/pulse/index.ts
8212
9006
  function createPulseCommand() {
8213
- const command = new Command69("pulse").description("Pulse (read-side observability) commands");
9007
+ const command = new Command75("pulse").description("Pulse (read-side observability) commands");
8214
9008
  command.addCommand(createRunCommand2());
8215
9009
  return command;
8216
9010
  }
8217
9011
 
8218
9012
  // src/commands/recommend.ts
8219
- import { Command as Command70 } from "commander";
9013
+ import { Command as Command76 } from "commander";
8220
9014
  import chalk11 from "chalk";
8221
9015
  async function resolveSnapshot(cwd, noCache) {
8222
9016
  if (!noCache) {
@@ -8280,7 +9074,7 @@ function printRecommendations(result) {
8280
9074
  console.log("");
8281
9075
  }
8282
9076
  function createRecommendCommand() {
8283
- const command = new Command70("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) => {
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) => {
8284
9078
  const globalOpts = cmd.optsWithGlobals();
8285
9079
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
8286
9080
  try {
@@ -8316,11 +9110,11 @@ function createRecommendCommand() {
8316
9110
  }
8317
9111
 
8318
9112
  // src/commands/roadmap/index.ts
8319
- import { Command as Command72 } from "commander";
9113
+ import { Command as Command78 } from "commander";
8320
9114
 
8321
9115
  // src/commands/roadmap/migrate.ts
8322
9116
  init_dist3();
8323
- import { Command as Command71 } from "commander";
9117
+ import { Command as Command77 } from "commander";
8324
9118
  import * as fs31 from "fs";
8325
9119
  import * as path49 from "path";
8326
9120
  import chalk12 from "chalk";
@@ -8578,61 +9372,296 @@ async function runRoadmapMigrate(opts) {
8578
9372
  if (!reportR.ok) {
8579
9373
  return Err(new CLIError(`migration failed: ${reportR.error.message}`));
8580
9374
  }
8581
- if (isJson) {
8582
- const exitCode = reportToExitCode(reportR.value);
8583
- console.log(JSON.stringify(buildJsonOutput(plan, reportR.value, void 0, exitCode)));
8584
- } else {
8585
- printReport(reportR.value);
9375
+ if (isJson) {
9376
+ const exitCode = reportToExitCode(reportR.value);
9377
+ console.log(JSON.stringify(buildJsonOutput(plan, reportR.value, void 0, exitCode)));
9378
+ } else {
9379
+ printReport(reportR.value);
9380
+ }
9381
+ return Ok(reportR.value);
9382
+ } finally {
9383
+ lockResult.release();
9384
+ }
9385
+ }
9386
+ 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(
9388
+ "--format <fmt>",
9389
+ 'Output format: "human" (default) or "json" (single JSON object for CI consumers)',
9390
+ "human"
9391
+ ).action(async (options) => {
9392
+ const format = options.format === "json" ? "json" : "human";
9393
+ const result = await runRoadmapMigrate({
9394
+ to: options.to,
9395
+ dryRun: Boolean(options.dryRun),
9396
+ format
9397
+ });
9398
+ if (!result.ok) {
9399
+ if (format === "json") {
9400
+ console.log(
9401
+ JSON.stringify(
9402
+ buildJsonOutput(
9403
+ void 0,
9404
+ void 0,
9405
+ result.error.message,
9406
+ MigrateExitCode.CONFIG_ERROR
9407
+ )
9408
+ )
9409
+ );
9410
+ } else {
9411
+ logger.error(result.error.message);
9412
+ }
9413
+ process.exit(format === "json" ? MigrateExitCode.CONFIG_ERROR : result.error.exitCode);
9414
+ }
9415
+ const exitCode = reportToExitCode(result.value);
9416
+ process.exit(exitCode);
9417
+ });
9418
+ }
9419
+
9420
+ // src/commands/roadmap/index.ts
9421
+ function createRoadmapCommand() {
9422
+ const roadmap = new Command78("roadmap").description("Roadmap management");
9423
+ roadmap.addCommand(createRoadmapMigrateCommand());
9424
+ return roadmap;
9425
+ }
9426
+
9427
+ // src/commands/routing/index.ts
9428
+ import { Command as Command82 } from "commander";
9429
+
9430
+ // src/commands/routing/config.ts
9431
+ import { Command as Command79 } from "commander";
9432
+
9433
+ // src/commands/routing/http-client.ts
9434
+ function orchestratorBase() {
9435
+ return process.env["HARNESS_ORCHESTRATOR_URL"] ?? "http://127.0.0.1:8080";
9436
+ }
9437
+ function authHeader() {
9438
+ const tok = process.env["HARNESS_API_TOKEN"];
9439
+ return tok ? { Authorization: `Bearer ${tok}` } : {};
9440
+ }
9441
+ async function getJson(path71) {
9442
+ try {
9443
+ const res = await fetch(`${orchestratorBase()}${path71}`, {
9444
+ headers: { ...authHeader() }
9445
+ });
9446
+ const text = await res.text();
9447
+ if (!res.ok) return { ok: false, status: res.status, body: null, error: text };
9448
+ return { ok: true, status: res.status, body: text ? JSON.parse(text) : null };
9449
+ } catch (err) {
9450
+ return {
9451
+ ok: false,
9452
+ status: 0,
9453
+ body: null,
9454
+ error: err instanceof Error ? err.message : String(err)
9455
+ };
9456
+ }
9457
+ }
9458
+ async function postJson(path71, body) {
9459
+ try {
9460
+ const res = await fetch(`${orchestratorBase()}${path71}`, {
9461
+ method: "POST",
9462
+ headers: { "Content-Type": "application/json", ...authHeader() },
9463
+ body: JSON.stringify(body)
9464
+ });
9465
+ const text = await res.text();
9466
+ if (!res.ok) return { ok: false, status: res.status, body: null, error: text };
9467
+ return { ok: true, status: res.status, body: text ? JSON.parse(text) : null };
9468
+ } catch (err) {
9469
+ return {
9470
+ ok: false,
9471
+ status: 0,
9472
+ body: null,
9473
+ error: err instanceof Error ? err.message : String(err)
9474
+ };
9475
+ }
9476
+ }
9477
+
9478
+ // src/commands/routing/config.ts
9479
+ function renderHuman(data) {
9480
+ console.log("Backends:");
9481
+ for (const b of data.backends) console.log(` - ${b}`);
9482
+ console.log("");
9483
+ console.log("Resolved Chains:");
9484
+ const keys = Object.keys(data.resolvedChains);
9485
+ if (keys.length === 0) {
9486
+ console.log(" (none)");
9487
+ return;
9488
+ }
9489
+ for (const key of keys) {
9490
+ const chain = data.resolvedChains[key] ?? [];
9491
+ const rendered = chain.map((c) => c.exists ? c.candidate : `${c.candidate}(MISSING)`).join(" -> ");
9492
+ console.log(` ${key}: ${rendered}`);
9493
+ }
9494
+ }
9495
+ 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) => {
9497
+ const r = await getJson("/api/v1/routing/config");
9498
+ if (!r.ok) {
9499
+ if (r.status === 0) {
9500
+ logger.error(
9501
+ `Failed to reach orchestrator at ${orchestratorBase()}: ${r.error ?? "unknown error"}`
9502
+ );
9503
+ } else if (r.status === 503) {
9504
+ logger.error(
9505
+ "Routing observability not available \u2014 orchestrator has no BackendRouter (legacy single-backend config)"
9506
+ );
9507
+ } else {
9508
+ logger.error(`Request failed (${r.status}): ${r.error ?? ""}`);
9509
+ }
9510
+ process.exit(ExitCode.ERROR);
9511
+ return;
9512
+ }
9513
+ if (opts.json) {
9514
+ console.log(JSON.stringify(r.body, null, 2));
9515
+ return;
8586
9516
  }
8587
- return Ok(reportR.value);
8588
- } finally {
8589
- lockResult.release();
9517
+ if (r.body) renderHuman(r.body);
9518
+ });
9519
+ }
9520
+
9521
+ // src/commands/routing/trace.ts
9522
+ import { Command as Command80 } from "commander";
9523
+ function buildUseCase(opts) {
9524
+ if (opts.skill) {
9525
+ return opts.mode ? { kind: "skill", skillName: opts.skill, cognitiveMode: opts.mode } : { kind: "skill", skillName: opts.skill };
8590
9526
  }
9527
+ if (opts.mode) return { kind: "mode", cognitiveMode: opts.mode };
9528
+ return null;
8591
9529
  }
8592
- function createRoadmapMigrateCommand() {
8593
- return new Command71("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(
8594
- "--format <fmt>",
8595
- 'Output format: "human" (default) or "json" (single JSON object for CI consumers)',
8596
- "human"
8597
- ).action(async (options) => {
8598
- const format = options.format === "json" ? "json" : "human";
8599
- const result = await runRoadmapMigrate({
8600
- to: options.to,
8601
- dryRun: Boolean(options.dryRun),
8602
- format
8603
- });
8604
- if (!result.ok) {
8605
- if (format === "json") {
8606
- console.log(
8607
- JSON.stringify(
8608
- buildJsonOutput(
8609
- void 0,
8610
- void 0,
8611
- result.error.message,
8612
- MigrateExitCode.CONFIG_ERROR
8613
- )
8614
- )
9530
+ function renderHuman2(r) {
9531
+ console.log(`Backend: ${r.decision.backendName} (type: ${r.def.type})`);
9532
+ console.log(`Duration: ${r.decision.durationMs.toFixed(2)} ms`);
9533
+ console.log("Resolution path:");
9534
+ if (r.decision.resolutionPath.length === 0) {
9535
+ console.log(" (empty)");
9536
+ return;
9537
+ }
9538
+ for (const step of r.decision.resolutionPath) {
9539
+ console.log(` ${step.source}:${step.candidate} -> ${step.outcome}`);
9540
+ }
9541
+ }
9542
+ 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) => {
9544
+ const useCase = buildUseCase(opts);
9545
+ if (!useCase) {
9546
+ logger.error("Either --skill <name> or --mode <m> is required");
9547
+ process.exit(ExitCode.ERROR);
9548
+ return;
9549
+ }
9550
+ const r = await postJson("/api/v1/routing/trace", { useCase });
9551
+ if (!r.ok) {
9552
+ if (r.status === 0) {
9553
+ logger.error(
9554
+ `Failed to reach orchestrator at ${orchestratorBase()}: ${r.error ?? "unknown error"}`
9555
+ );
9556
+ } else if (r.status === 503) {
9557
+ logger.error(
9558
+ "Routing observability not available \u2014 orchestrator has no BackendRouter (legacy single-backend config)"
8615
9559
  );
8616
9560
  } else {
8617
- logger.error(result.error.message);
9561
+ logger.error(`Trace failed (${r.status}): ${r.error ?? ""}`);
8618
9562
  }
8619
- process.exit(format === "json" ? MigrateExitCode.CONFIG_ERROR : result.error.exitCode);
9563
+ process.exit(ExitCode.ERROR);
9564
+ return;
8620
9565
  }
8621
- const exitCode = reportToExitCode(result.value);
8622
- process.exit(exitCode);
9566
+ if (opts.json) {
9567
+ console.log(JSON.stringify(r.body, null, 2));
9568
+ return;
9569
+ }
9570
+ if (r.body) renderHuman2(r.body);
8623
9571
  });
8624
9572
  }
8625
9573
 
8626
- // src/commands/roadmap/index.ts
8627
- function createRoadmapCommand() {
8628
- const roadmap = new Command72("roadmap").description("Roadmap management");
8629
- roadmap.addCommand(createRoadmapMigrateCommand());
8630
- return roadmap;
9574
+ // src/commands/routing/decisions.ts
9575
+ import { Command as Command81 } from "commander";
9576
+ function summarizeUseCase(uc) {
9577
+ switch (uc.kind) {
9578
+ case "skill":
9579
+ return uc.cognitiveMode ? `skill:${uc.skillName}/${uc.cognitiveMode}` : `skill:${uc.skillName}`;
9580
+ case "mode":
9581
+ return `mode:${uc.cognitiveMode}`;
9582
+ case "tier":
9583
+ return `tier:${uc.tier}`;
9584
+ case "intelligence":
9585
+ return `intelligence:${uc.layer}`;
9586
+ case "isolation":
9587
+ return `isolation:${uc.tier}`;
9588
+ case "maintenance":
9589
+ return "maintenance";
9590
+ case "chat":
9591
+ return "chat";
9592
+ }
9593
+ }
9594
+ function shortIso(iso) {
9595
+ const parts = iso.split("T");
9596
+ const tail = parts[1] ?? iso;
9597
+ return tail.replace("Z", "");
9598
+ }
9599
+ function renderHuman3(data) {
9600
+ if (data.decisions.length === 0) {
9601
+ console.log("(no decisions in buffer)");
9602
+ return;
9603
+ }
9604
+ console.log("TIMESTAMP USE-CASE BACKEND DURATION");
9605
+ for (const d of data.decisions) {
9606
+ const ts = shortIso(d.timestamp).padEnd(13);
9607
+ const uc = summarizeUseCase(d.useCase).padEnd(38);
9608
+ const be = d.backendName.padEnd(14);
9609
+ const dur = `${d.durationMs.toFixed(2)} ms`;
9610
+ console.log(`${ts} ${uc} ${be} ${dur}`);
9611
+ }
9612
+ }
9613
+ function buildQuery(opts) {
9614
+ const p = new URLSearchParams();
9615
+ if (opts.skill) p.set("skill", opts.skill);
9616
+ if (opts.mode) p.set("mode", opts.mode);
9617
+ if (opts.backend) p.set("backend", opts.backend);
9618
+ if (opts.last) p.set("limit", opts.last);
9619
+ const q = p.toString();
9620
+ return q ? `?${q}` : "";
9621
+ }
9622
+ 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(
9624
+ async (opts) => {
9625
+ const query = buildQuery(opts);
9626
+ const r = await getJson(`/api/v1/routing/decisions${query}`);
9627
+ if (!r.ok) {
9628
+ if (r.status === 0) {
9629
+ logger.error(
9630
+ `Failed to reach orchestrator at ${orchestratorBase()}: ${r.error ?? "unknown error"}`
9631
+ );
9632
+ } else if (r.status === 503) {
9633
+ logger.error(
9634
+ "Routing observability not available \u2014 orchestrator has no BackendRouter (legacy single-backend config)"
9635
+ );
9636
+ } else {
9637
+ logger.error(`Request failed (${r.status}): ${r.error ?? ""}`);
9638
+ }
9639
+ process.exit(ExitCode.ERROR);
9640
+ return;
9641
+ }
9642
+ if (opts.json) {
9643
+ console.log(JSON.stringify(r.body, null, 2));
9644
+ return;
9645
+ }
9646
+ if (r.body) renderHuman3(r.body);
9647
+ }
9648
+ );
9649
+ }
9650
+
9651
+ // src/commands/routing/index.ts
9652
+ function createRoutingCommand() {
9653
+ const cmd = new Command82("routing").description(
9654
+ "Inspect routing config, trace decisions, and read recent dispatches"
9655
+ );
9656
+ cmd.addCommand(createConfigCommand());
9657
+ cmd.addCommand(createTraceCommand());
9658
+ cmd.addCommand(createDecisionsCommand());
9659
+ return cmd;
8631
9660
  }
8632
9661
 
8633
9662
  // src/commands/scan-config.ts
8634
9663
  init_dist3();
8635
- import { Command as Command73 } from "commander";
9664
+ import { Command as Command83 } from "commander";
8636
9665
  import { existsSync as existsSync28, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "fs";
8637
9666
  import { join as join41, relative as relative3 } from "path";
8638
9667
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
@@ -8721,7 +9750,7 @@ function formatTextOutput(result) {
8721
9750
  }
8722
9751
  }
8723
9752
  function createScanConfigCommand() {
8724
- const command = new Command73("scan-config").description(
9753
+ const command = new Command83("scan-config").description(
8725
9754
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
8726
9755
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
8727
9756
  const globalOpts = cmd.optsWithGlobals();
@@ -8739,7 +9768,7 @@ function createScanConfigCommand() {
8739
9768
 
8740
9769
  // src/commands/search.ts
8741
9770
  init_dist();
8742
- import { Command as Command74 } from "commander";
9771
+ import { Command as Command84 } from "commander";
8743
9772
  function parseFileKinds(raw) {
8744
9773
  if (!raw) return void 0;
8745
9774
  const set = /* @__PURE__ */ new Set();
@@ -8760,7 +9789,7 @@ function fmtBytes(n) {
8760
9789
  return n.toFixed(0);
8761
9790
  }
8762
9791
  function createSearchCommand() {
8763
- return new Command74("search").description("Full-text search over archived + live session content (Hermes Phase 1).").argument(
9792
+ return new Command84("search").description("Full-text search over archived + live session content (Hermes Phase 1).").argument(
8764
9793
  "<query>",
8765
9794
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
8766
9795
  ).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(
@@ -8819,8 +9848,76 @@ function createSearchCommand() {
8819
9848
  });
8820
9849
  }
8821
9850
 
9851
+ // src/commands/security-craft.ts
9852
+ import { Command as Command85 } from "commander";
9853
+ function createSecurityCraftCommand() {
9854
+ return new Command85("security-craft").description(
9855
+ "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
+ ).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
+ const globalOpts = cmd.optsWithGlobals();
9858
+ const outputMode = resolveOutputMode(globalOpts);
9859
+ const formatter = new OutputFormatter(outputMode);
9860
+ const cwd = globalOpts.cwd ?? process.cwd();
9861
+ const input = { path: cwd };
9862
+ if (opts.files !== void 0) input.files = opts.files;
9863
+ if (opts.packages !== void 0) input.packages = opts.packages;
9864
+ if (opts.maxFiles !== void 0) input.maxFiles = parseInt(opts.maxFiles, 10);
9865
+ if (opts.maxSignalsPerFile !== void 0)
9866
+ input.maxSignalsPerFile = parseInt(opts.maxSignalsPerFile, 10);
9867
+ let result;
9868
+ try {
9869
+ result = await runSecurityCraft(input);
9870
+ } catch (err) {
9871
+ const message = err instanceof Error ? err.message : String(err);
9872
+ if (outputMode === OutputMode.JSON) {
9873
+ console.log(JSON.stringify({ error: message }));
9874
+ } else {
9875
+ logger.error(`security-craft failed: ${message}`);
9876
+ }
9877
+ process.exit(ExitCode.ERROR);
9878
+ return;
9879
+ }
9880
+ if (outputMode === OutputMode.JSON) {
9881
+ console.log(JSON.stringify(result, null, 2));
9882
+ } else {
9883
+ printResult5(result, outputMode, formatter);
9884
+ }
9885
+ const hasFoundational = result.findings.some((f) => f.tier === "foundational");
9886
+ process.exit(hasFoundational ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS);
9887
+ });
9888
+ }
9889
+ function printResult5(result, mode, _formatter) {
9890
+ const verbose = mode === OutputMode.VERBOSE;
9891
+ const { findings, summary } = result;
9892
+ if (findings.length === 0) {
9893
+ console.log("No security findings.");
9894
+ } else {
9895
+ const byFile = /* @__PURE__ */ new Map();
9896
+ for (const f of findings) {
9897
+ const list = byFile.get(f.target.file) ?? [];
9898
+ list.push(f);
9899
+ byFile.set(f.target.file, list);
9900
+ }
9901
+ for (const [file, fs47] of byFile) {
9902
+ console.log(`
9903
+ ${file}`);
9904
+ for (const f of fs47) {
9905
+ console.log(
9906
+ ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.signal}:${f.target.line}`
9907
+ );
9908
+ console.log(` ${f.message}`);
9909
+ if (verbose) console.log(` source: ${f.cite.source}`);
9910
+ }
9911
+ }
9912
+ }
9913
+ console.log("");
9914
+ console.log(
9915
+ `Summary: ${findings.length} findings across ${summary.counts.filesScanned} files (${summary.counts.filesSkippedNoSignal} skipped, ${summary.counts.signalsDetected} signals, ${summary.catalog.rubricsApplied.length} rubrics, ${summary.llmCalls.count} LLM calls, $${summary.llmCalls.costUsd.toFixed(4)}, ${summary.durationMs}ms)`
9916
+ );
9917
+ }
9918
+
8822
9919
  // src/commands/setup.ts
8823
- import { Command as Command75 } from "commander";
9920
+ import { Command as Command86 } from "commander";
8824
9921
  import * as fs34 from "fs";
8825
9922
  import * as os8 from "os";
8826
9923
  import * as path52 from "path";
@@ -9126,7 +10223,7 @@ async function detectLegacyLayout(cwd) {
9126
10223
  }
9127
10224
  async function runInitialGraphScan(cwd) {
9128
10225
  try {
9129
- const { runScan: runScan2 } = await import("./scan-4PPP6ZXT.js");
10226
+ const { runScan: runScan2 } = await import("./scan-LYKLM4EQ.js");
9130
10227
  const result = await runScan2(cwd);
9131
10228
  return {
9132
10229
  status: "pass",
@@ -9165,7 +10262,7 @@ async function runSetup(cwd) {
9165
10262
  return { steps, success };
9166
10263
  }
9167
10264
  function createSetupCommand() {
9168
- return new Command75("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
10265
+ return new Command86("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
9169
10266
  const cwd = process.cwd();
9170
10267
  console.log("");
9171
10268
  console.log(` ${chalk14.bold("harness setup")}`);
@@ -9188,7 +10285,7 @@ function createSetupCommand() {
9188
10285
 
9189
10286
  // src/commands/share.ts
9190
10287
  init_dist3();
9191
- import { Command as Command76 } from "commander";
10288
+ import { Command as Command87 } from "commander";
9192
10289
  import * as fs35 from "fs";
9193
10290
  import * as path53 from "path";
9194
10291
  import { parse as parseYaml2 } from "yaml";
@@ -9247,16 +10344,16 @@ Create a constraints.yaml in your project root to define what to share.`
9247
10344
  logger.success(`Bundle written to ${outputPath}`);
9248
10345
  }
9249
10346
  function createShareCommand() {
9250
- return new Command76("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) => {
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) => {
9251
10348
  await runShareAction(projectPath, options);
9252
10349
  });
9253
10350
  }
9254
10351
 
9255
10352
  // src/commands/skill/index.ts
9256
- import { Command as Command84 } from "commander";
10353
+ import { Command as Command95 } from "commander";
9257
10354
 
9258
10355
  // src/commands/skill/list.ts
9259
- import { Command as Command77 } from "commander";
10356
+ import { Command as Command88 } from "commander";
9260
10357
  import * as fs36 from "fs";
9261
10358
  import * as path54 from "path";
9262
10359
  import { parse } from "yaml";
@@ -9359,7 +10456,7 @@ function printSkillsVerbose(skills) {
9359
10456
  for (const s of skills) printSkillEntry(s);
9360
10457
  }
9361
10458
  function createListCommand3() {
9362
- return new Command77("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) => {
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) => {
9363
10460
  const globalOpts = cmd.optsWithGlobals();
9364
10461
  const skills = collectSkills({ filter: resolveFilter(opts) });
9365
10462
  if (globalOpts.json) {
@@ -9374,7 +10471,7 @@ function createListCommand3() {
9374
10471
  }
9375
10472
 
9376
10473
  // src/commands/skill/run.ts
9377
- import { Command as Command78 } from "commander";
10474
+ import { Command as Command89 } from "commander";
9378
10475
  import * as fs37 from "fs";
9379
10476
  import * as path55 from "path";
9380
10477
  import { parse as parse2 } from "yaml";
@@ -9582,15 +10679,20 @@ async function runSkill(name, opts) {
9582
10679
  projectPath,
9583
10680
  !!opts.path
9584
10681
  );
9585
- process.stdout.write(preamble + content);
10682
+ const overrideHint = opts.backend ? `<!-- HARNESS_BACKEND_OVERRIDE=${opts.backend} -->
10683
+ ` : "";
10684
+ process.stdout.write(overrideHint + preamble + content);
9586
10685
  process.exit(ExitCode.SUCCESS);
9587
10686
  }
9588
10687
  function createRunCommand3() {
9589
- return new Command78("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").action(async (name, opts) => runSkill(name, opts));
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(
10689
+ "--backend <name>",
10690
+ "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
10691
+ ).action(async (name, opts) => runSkill(name, opts));
9590
10692
  }
9591
10693
 
9592
10694
  // src/commands/skill/validate.ts
9593
- import { Command as Command79 } from "commander";
10695
+ import { Command as Command90 } from "commander";
9594
10696
  import * as fs38 from "fs";
9595
10697
  import * as path56 from "path";
9596
10698
  import { parse as parse3 } from "yaml";
@@ -9654,7 +10756,7 @@ function validateSkillEntry(name, skillsDir, errors) {
9654
10756
  }
9655
10757
  }
9656
10758
  function createValidateCommand2() {
9657
- return new Command79("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
10759
+ return new Command90("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
9658
10760
  const globalOpts = cmd.optsWithGlobals();
9659
10761
  const skillsDir = resolveSkillsDir();
9660
10762
  if (!fs38.existsSync(skillsDir)) {
@@ -9684,7 +10786,7 @@ function createValidateCommand2() {
9684
10786
  }
9685
10787
 
9686
10788
  // src/commands/skill/info.ts
9687
- import { Command as Command80 } from "commander";
10789
+ import { Command as Command91 } from "commander";
9688
10790
  import * as fs39 from "fs";
9689
10791
  import * as path57 from "path";
9690
10792
  import { parse as parse4 } from "yaml";
@@ -9730,7 +10832,7 @@ function printSkillInfo(skill) {
9730
10832
  console.log(`Persistent: ${skill.state.persistent}`);
9731
10833
  }
9732
10834
  function createInfoCommand() {
9733
- return new Command80("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
10835
+ return new Command91("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
9734
10836
  const globalOpts = cmd.optsWithGlobals();
9735
10837
  const loaded = loadSkillMetadata2(name);
9736
10838
  if (!loaded.ok) {
@@ -9747,7 +10849,7 @@ function createInfoCommand() {
9747
10849
  }
9748
10850
 
9749
10851
  // src/commands/skill/search.ts
9750
- import { Command as Command81 } from "commander";
10852
+ import { Command as Command92 } from "commander";
9751
10853
  async function runSearch(query, opts) {
9752
10854
  const results = await searchNpmRegistry(query, opts.registry);
9753
10855
  return results.filter((r) => {
@@ -9792,13 +10894,13 @@ async function runSearchAction(query, opts, globalOpts) {
9792
10894
  }
9793
10895
  }
9794
10896
  function createSearchCommand2() {
9795
- return new Command81("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) => {
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) => {
9796
10898
  await runSearchAction(query, opts, cmd.optsWithGlobals());
9797
10899
  });
9798
10900
  }
9799
10901
 
9800
10902
  // src/commands/skill/create.ts
9801
- import { Command as Command82 } from "commander";
10903
+ import { Command as Command93 } from "commander";
9802
10904
  import * as path58 from "path";
9803
10905
  import * as fs40 from "fs";
9804
10906
  import YAML from "yaml";
@@ -9918,7 +11020,7 @@ Next steps:`);
9918
11020
  logger.info(` 3. Run: harness skills publish`);
9919
11021
  }
9920
11022
  function createCreateCommand() {
9921
- return new Command82("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) => {
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) => {
9922
11024
  const globalOpts = cmd.optsWithGlobals();
9923
11025
  try {
9924
11026
  const result = runCreate(name, {
@@ -9941,7 +11043,7 @@ function createCreateCommand() {
9941
11043
  }
9942
11044
 
9943
11045
  // src/commands/skill/publish.ts
9944
- import { Command as Command83 } from "commander";
11046
+ import { Command as Command94 } from "commander";
9945
11047
  import * as fs42 from "fs";
9946
11048
  import * as path60 from "path";
9947
11049
  import { execFileSync as execFileSync6 } from "child_process";
@@ -10110,7 +11212,7 @@ ${skillMdContent}`;
10110
11212
  };
10111
11213
  }
10112
11214
  function createPublishCommand() {
10113
- return new Command83("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) => {
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) => {
10114
11216
  const globalOpts = cmd.optsWithGlobals();
10115
11217
  const skillDir = opts.dir || process.cwd();
10116
11218
  try {
@@ -10135,7 +11237,7 @@ function createPublishCommand() {
10135
11237
 
10136
11238
  // src/commands/skill/index.ts
10137
11239
  function createSkillCommand() {
10138
- const command = new Command84("skill").description("Skill management commands");
11240
+ const command = new Command95("skill").description("Skill management commands");
10139
11241
  command.addCommand(createListCommand3());
10140
11242
  command.addCommand(createRunCommand3());
10141
11243
  command.addCommand(createValidateCommand2());
@@ -10148,7 +11250,7 @@ function createSkillCommand() {
10148
11250
 
10149
11251
  // src/commands/snapshot.ts
10150
11252
  init_dist3();
10151
- import { Command as Command85 } from "commander";
11253
+ import { Command as Command96 } from "commander";
10152
11254
  import { execSync as execSync5 } from "child_process";
10153
11255
  import chalk15 from "chalk";
10154
11256
  function getCommitHash3(cwd) {
@@ -10330,19 +11432,88 @@ function registerListCommand(parent) {
10330
11432
  });
10331
11433
  }
10332
11434
  function createSnapshotCommand() {
10333
- const command = new Command85("snapshot").description("Architecture timeline snapshot commands");
11435
+ const command = new Command96("snapshot").description("Architecture timeline snapshot commands");
10334
11436
  registerCaptureCommand(command);
10335
11437
  registerTrendsCommand(command);
10336
11438
  registerListCommand(command);
10337
11439
  return command;
10338
11440
  }
10339
11441
 
11442
+ // src/commands/spec-craft.ts
11443
+ import { Command as Command97 } from "commander";
11444
+ function createSpecCraftCommand() {
11445
+ return new Command97("spec-craft").description(
11446
+ "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
+ ).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
+ const globalOpts = cmd.optsWithGlobals();
11449
+ const outputMode = resolveOutputMode(globalOpts);
11450
+ const formatter = new OutputFormatter(outputMode);
11451
+ const cwd = globalOpts.cwd ?? process.cwd();
11452
+ const input = { path: cwd };
11453
+ if (opts.files !== void 0) input.files = opts.files;
11454
+ if (opts.kinds !== void 0) input.kinds = opts.kinds;
11455
+ if (opts.sections !== void 0) input.sections = opts.sections;
11456
+ if (opts.maxFiles !== void 0) input.maxFiles = parseInt(opts.maxFiles, 10);
11457
+ if (opts.maxSectionsPerFile !== void 0)
11458
+ input.maxSectionsPerFile = parseInt(opts.maxSectionsPerFile, 10);
11459
+ let result;
11460
+ try {
11461
+ result = await runSpecCraft(input);
11462
+ } catch (err) {
11463
+ const message = err instanceof Error ? err.message : String(err);
11464
+ if (outputMode === OutputMode.JSON) {
11465
+ console.log(JSON.stringify({ error: message }));
11466
+ } else {
11467
+ logger.error(`spec-craft failed: ${message}`);
11468
+ }
11469
+ process.exit(ExitCode.ERROR);
11470
+ return;
11471
+ }
11472
+ if (outputMode === OutputMode.JSON) {
11473
+ console.log(JSON.stringify(result, null, 2));
11474
+ } else {
11475
+ printResult6(result, outputMode, formatter);
11476
+ }
11477
+ const hasFoundational = result.findings.some((f) => f.tier === "foundational");
11478
+ process.exit(hasFoundational ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS);
11479
+ });
11480
+ }
11481
+ function printResult6(result, mode, _formatter) {
11482
+ const verbose = mode === OutputMode.VERBOSE;
11483
+ const { findings, summary } = result;
11484
+ if (findings.length === 0) {
11485
+ console.log("No spec findings.");
11486
+ } else {
11487
+ const byFile = /* @__PURE__ */ new Map();
11488
+ for (const f of findings) {
11489
+ const list = byFile.get(f.target.file) ?? [];
11490
+ list.push(f);
11491
+ byFile.set(f.target.file, list);
11492
+ }
11493
+ for (const [file, fs47] of byFile) {
11494
+ console.log(`
11495
+ ${file}`);
11496
+ for (const f of fs47) {
11497
+ console.log(
11498
+ ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ## ${f.target.section}:${f.target.line}`
11499
+ );
11500
+ console.log(` ${f.message}`);
11501
+ if (verbose) console.log(` source: ${f.cite.source}`);
11502
+ }
11503
+ }
11504
+ }
11505
+ console.log("");
11506
+ console.log(
11507
+ `Summary: ${findings.length} findings across ${summary.docsScanned} docs (${summary.sectionsScanned} sections, ${summary.catalog.rubricsApplied.length} rubrics, ${summary.llmCalls.count} LLM calls, $${summary.llmCalls.costUsd.toFixed(4)}, ${summary.durationMs}ms)`
11508
+ );
11509
+ }
11510
+
10340
11511
  // src/commands/state/index.ts
10341
- import { Command as Command90 } from "commander";
11512
+ import { Command as Command102 } from "commander";
10342
11513
 
10343
11514
  // src/commands/state/show.ts
10344
11515
  init_dist3();
10345
- import { Command as Command86 } from "commander";
11516
+ import { Command as Command98 } from "commander";
10346
11517
  import * as path61 from "path";
10347
11518
  function printStateText(state, stream) {
10348
11519
  if (stream) console.log(`Stream: ${stream}`);
@@ -10367,7 +11538,7 @@ function printStateProgress(progress) {
10367
11538
  }
10368
11539
  }
10369
11540
  function createShowCommand() {
10370
- return new Command86("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
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) => {
10371
11542
  const globalOpts = cmd.optsWithGlobals();
10372
11543
  const result = await loadState(path61.resolve(opts.path), opts.stream);
10373
11544
  if (!result.ok) {
@@ -10385,7 +11556,7 @@ function createShowCommand() {
10385
11556
 
10386
11557
  // src/commands/state/reset.ts
10387
11558
  init_dist3();
10388
- import { Command as Command87 } from "commander";
11559
+ import { Command as Command99 } from "commander";
10389
11560
  import * as fs43 from "fs";
10390
11561
  import * as path62 from "path";
10391
11562
  import * as readline3 from "readline";
@@ -10429,15 +11600,15 @@ async function runReset(opts) {
10429
11600
  process.exit(ExitCode.SUCCESS);
10430
11601
  }
10431
11602
  function createResetCommand() {
10432
- return new Command87("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));
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));
10433
11604
  }
10434
11605
 
10435
11606
  // src/commands/state/learn.ts
10436
11607
  init_dist3();
10437
- import { Command as Command88 } from "commander";
11608
+ import { Command as Command100 } from "commander";
10438
11609
  import * as path63 from "path";
10439
11610
  function createLearnCommand() {
10440
- return new Command88("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) => {
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) => {
10441
11612
  const projectPath = path63.resolve(opts.path);
10442
11613
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
10443
11614
  if (!result.ok) {
@@ -10452,7 +11623,7 @@ function createLearnCommand() {
10452
11623
 
10453
11624
  // src/commands/state/streams.ts
10454
11625
  init_dist3();
10455
- import { Command as Command89 } from "commander";
11626
+ import { Command as Command101 } from "commander";
10456
11627
  import * as path64 from "path";
10457
11628
  async function runListStreams(opts, globalOpts) {
10458
11629
  const projectPath = path64.resolve(opts.path);
@@ -10503,7 +11674,7 @@ async function runActivateStream(name, opts) {
10503
11674
  process.exit(ExitCode.SUCCESS);
10504
11675
  }
10505
11676
  function createStreamsCommand() {
10506
- const command = new Command89("streams").description("Manage state streams");
11677
+ const command = new Command101("streams").description("Manage state streams");
10507
11678
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
10508
11679
  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));
10509
11680
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -10513,7 +11684,7 @@ function createStreamsCommand() {
10513
11684
 
10514
11685
  // src/commands/state/index.ts
10515
11686
  function createStateCommand() {
10516
- const command = new Command90("state").description("Project state management commands");
11687
+ const command = new Command102("state").description("Project state management commands");
10517
11688
  command.addCommand(createShowCommand());
10518
11689
  command.addCommand(createResetCommand());
10519
11690
  command.addCommand(createLearnCommand());
@@ -10524,7 +11695,7 @@ function createStateCommand() {
10524
11695
  // src/commands/sync-analyses.ts
10525
11696
  import * as fs44 from "fs";
10526
11697
  import * as path65 from "path";
10527
- import { Command as Command91 } from "commander";
11698
+ import { Command as Command103 } from "commander";
10528
11699
  init_dist3();
10529
11700
  function isValidRecord(record) {
10530
11701
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -10650,7 +11821,7 @@ async function runSyncAnalyses(opts) {
10650
11821
  return;
10651
11822
  }
10652
11823
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
10653
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-OHDQBTSO.js");
11824
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-XIJWWQ5N.js");
10654
11825
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
10655
11826
  const archive = new AnalysisArchive(path65.join(projectPath, ".harness", "analyses"));
10656
11827
  const publishedIndex = loadPublishedIndex2(projectPath);
@@ -10672,7 +11843,7 @@ async function runSyncAnalyses(opts) {
10672
11843
  }
10673
11844
  }
10674
11845
  function createSyncAnalysesCommand() {
10675
- const command = new Command91("sync-analyses").description(
11846
+ const command = new Command103("sync-analyses").description(
10676
11847
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
10677
11848
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
10678
11849
  try {
@@ -10686,7 +11857,7 @@ function createSyncAnalysesCommand() {
10686
11857
  }
10687
11858
 
10688
11859
  // src/commands/sync-main.ts
10689
- import { Command as Command92 } from "commander";
11860
+ import { Command as Command104 } from "commander";
10690
11861
  import * as path66 from "path";
10691
11862
  import {
10692
11863
  syncMain as defaultSyncMain
@@ -10717,7 +11888,7 @@ function formatHuman2(r) {
10717
11888
  }
10718
11889
  }
10719
11890
  function createSyncMainCommand() {
10720
- return new Command92("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) => {
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) => {
10721
11892
  const cwd = path66.resolve(opts.path ?? ".");
10722
11893
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
10723
11894
  process.exit(exitCode);
@@ -10726,7 +11897,7 @@ function createSyncMainCommand() {
10726
11897
 
10727
11898
  // src/commands/taint.ts
10728
11899
  init_dist3();
10729
- import { Command as Command93 } from "commander";
11900
+ import { Command as Command105 } from "commander";
10730
11901
  function getProjectRoot() {
10731
11902
  return process.cwd();
10732
11903
  }
@@ -10798,18 +11969,18 @@ function registerStatusCommand(taint) {
10798
11969
  });
10799
11970
  }
10800
11971
  function createTaintCommand() {
10801
- const taint = new Command93("taint").description("Manage sentinel session taint state");
11972
+ const taint = new Command105("taint").description("Manage sentinel session taint state");
10802
11973
  registerClearCommand(taint);
10803
11974
  registerStatusCommand(taint);
10804
11975
  return taint;
10805
11976
  }
10806
11977
 
10807
11978
  // src/commands/telemetry/index.ts
10808
- import { Command as Command97 } from "commander";
11979
+ import { Command as Command109 } from "commander";
10809
11980
 
10810
11981
  // src/commands/telemetry/identify.ts
10811
11982
  init_dist3();
10812
- import { Command as Command94 } from "commander";
11983
+ import { Command as Command106 } from "commander";
10813
11984
  import * as fs45 from "fs";
10814
11985
  import * as path67 from "path";
10815
11986
  function telemetryFilePath(cwd) {
@@ -10833,7 +12004,7 @@ function printIdentity(identity) {
10833
12004
  }
10834
12005
  }
10835
12006
  function createIdentifyCommand() {
10836
- const cmd = new Command94("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) => {
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) => {
10837
12008
  const cwd = process.cwd();
10838
12009
  if (opts.clear) {
10839
12010
  writeTelemetryFile(cwd, { identity: {} });
@@ -10858,7 +12029,7 @@ function createIdentifyCommand() {
10858
12029
 
10859
12030
  // src/commands/telemetry/status.ts
10860
12031
  init_dist3();
10861
- import { Command as Command95 } from "commander";
12032
+ import { Command as Command107 } from "commander";
10862
12033
  function gatherEnvOverrides() {
10863
12034
  const overrides = {};
10864
12035
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -10900,7 +12071,7 @@ function printHumanStatus(result) {
10900
12071
  printEnvOverrides(result.envOverrides);
10901
12072
  }
10902
12073
  function createStatusCommand() {
10903
- const cmd = new Command95("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
12074
+ const cmd = new Command107("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
10904
12075
  const cwd = process.cwd();
10905
12076
  const envOverrides = gatherEnvOverrides();
10906
12077
  const consent = resolveConsent(cwd, void 0);
@@ -10933,7 +12104,7 @@ function createStatusCommand() {
10933
12104
 
10934
12105
  // src/commands/telemetry/test.ts
10935
12106
  init_dist3();
10936
- import { Command as Command96 } from "commander";
12107
+ import { Command as Command108 } from "commander";
10937
12108
 
10938
12109
  // src/bin/command-telemetry.ts
10939
12110
  import { existsSync as existsSync42, readFileSync as readFileSync32, mkdirSync as mkdirSync19, appendFileSync, writeFileSync as writeFileSync24 } from "fs";
@@ -11055,7 +12226,7 @@ function reportTestSuccess(status, distinctId, identity) {
11055
12226
  if (identity.team) logger.info(` team: ${identity.team}`);
11056
12227
  }
11057
12228
  function createTestCommand() {
11058
- return new Command96("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
12229
+ return new Command108("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
11059
12230
  const cwd = process.cwd();
11060
12231
  const consent = resolveConsent(cwd, void 0);
11061
12232
  if (!consent.allowed) {
@@ -11092,15 +12263,87 @@ function createTestCommand() {
11092
12263
 
11093
12264
  // src/commands/telemetry/index.ts
11094
12265
  function createTelemetryCommand() {
11095
- const command = new Command97("telemetry").description("Telemetry identity and status management");
12266
+ const command = new Command109("telemetry").description("Telemetry identity and status management");
11096
12267
  command.addCommand(createIdentifyCommand());
11097
12268
  command.addCommand(createStatusCommand());
11098
12269
  command.addCommand(createTestCommand());
11099
12270
  return command;
11100
12271
  }
11101
12272
 
12273
+ // src/commands/test-craft.ts
12274
+ import { Command as Command110 } from "commander";
12275
+ function createTestCraftCommand() {
12276
+ return new Command110("test-craft").description(
12277
+ "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
+ ).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
+ const globalOpts = cmd.optsWithGlobals();
12280
+ const outputMode = resolveOutputMode(globalOpts);
12281
+ const formatter = new OutputFormatter(outputMode);
12282
+ const cwd = globalOpts.cwd ?? process.cwd();
12283
+ const input = { path: cwd };
12284
+ if (opts.files !== void 0) input.files = opts.files;
12285
+ if (opts.frameworks !== void 0) input.frameworks = opts.frameworks;
12286
+ if (opts.maxFiles !== void 0) input.maxFiles = parseInt(opts.maxFiles, 10);
12287
+ if (opts.maxTestsPerFile !== void 0)
12288
+ input.maxTestsPerFile = parseInt(opts.maxTestsPerFile, 10);
12289
+ if (opts.noSourcePair === true) input.sourcePair = false;
12290
+ let result;
12291
+ try {
12292
+ result = await runTestCraft(input);
12293
+ } catch (err) {
12294
+ const message = err instanceof Error ? err.message : String(err);
12295
+ if (outputMode === OutputMode.JSON) {
12296
+ console.log(JSON.stringify({ error: message }));
12297
+ } else {
12298
+ logger.error(`test-craft failed: ${message}`);
12299
+ }
12300
+ process.exit(ExitCode.ERROR);
12301
+ return;
12302
+ }
12303
+ if (outputMode === OutputMode.JSON) {
12304
+ console.log(JSON.stringify(result, null, 2));
12305
+ } else {
12306
+ printResult7(result, outputMode, formatter);
12307
+ }
12308
+ const hasFoundational = result.findings.some((f) => f.tier === "foundational");
12309
+ process.exit(hasFoundational ? ExitCode.VALIDATION_FAILED : ExitCode.SUCCESS);
12310
+ });
12311
+ }
12312
+ function printResult7(result, mode, _formatter) {
12313
+ const verbose = mode === OutputMode.VERBOSE;
12314
+ const { findings, summary } = result;
12315
+ if (findings.length === 0) {
12316
+ console.log("No test findings.");
12317
+ } else {
12318
+ const byFile = /* @__PURE__ */ new Map();
12319
+ for (const f of findings) {
12320
+ const list = byFile.get(f.target.file) ?? [];
12321
+ list.push(f);
12322
+ byFile.set(f.target.file, list);
12323
+ }
12324
+ for (const [file, fs47] of byFile) {
12325
+ console.log(`
12326
+ ${file}`);
12327
+ for (const f of fs47) {
12328
+ const nestingStr = f.target.nesting.length > 0 ? f.target.nesting.join(" > ") + " > " : "";
12329
+ console.log(
12330
+ ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.framework}:${f.target.line}`
12331
+ );
12332
+ console.log(` ${nestingStr}${f.target.testName}`);
12333
+ console.log(` ${f.message}`);
12334
+ if (verbose) console.log(` source: ${f.cite.source}`);
12335
+ }
12336
+ }
12337
+ }
12338
+ console.log("");
12339
+ const frameworksStr = Object.entries(summary.frameworksDetected).filter(([, n]) => n > 0).map(([k, n]) => `${k}=${n}`).join(", ");
12340
+ console.log(
12341
+ `Summary: ${findings.length} findings across ${summary.counts.testsExtracted} tests (${summary.counts.filesScanned} files, frameworks: ${frameworksStr || "none"}, paired: ${summary.counts.sourcePaired}, ${summary.llmCalls.count} LLM calls, $${summary.llmCalls.costUsd.toFixed(4)}, ${summary.durationMs}ms)`
12342
+ );
12343
+ }
12344
+
11102
12345
  // src/commands/traceability.ts
11103
- import { Command as Command98 } from "commander";
12346
+ import { Command as Command111 } from "commander";
11104
12347
  import chalk16 from "chalk";
11105
12348
  function confidenceLabel(maxConfidence) {
11106
12349
  if (maxConfidence >= 0.8) return "explicit";
@@ -11121,7 +12364,7 @@ function statusIcon(status) {
11121
12364
  return status;
11122
12365
  }
11123
12366
  }
11124
- function truncate(str, max) {
12367
+ function truncate2(str, max) {
11125
12368
  if (str.length <= max) return str;
11126
12369
  return str.slice(0, max - 3) + "...";
11127
12370
  }
@@ -11189,7 +12432,7 @@ function printRequirementRows(requirements, mode, cols) {
11189
12432
  const { numWidth, nameWidth, codeWidth, testWidth, confWidth } = cols;
11190
12433
  for (const req of requirements) {
11191
12434
  const num = `${req.index}.`;
11192
- const name = truncate(req.requirementName, nameWidth - 2);
12435
+ const name = truncate2(req.requirementName, nameWidth - 2);
11193
12436
  const code = String(req.codeFiles.length);
11194
12437
  const tests = String(req.testFiles.length);
11195
12438
  const conf = confidenceLabel(req.maxConfidence);
@@ -11221,7 +12464,7 @@ async function runTraceability(options) {
11221
12464
  const projectPath = process.cwd();
11222
12465
  const store = await loadGraphStore(projectPath);
11223
12466
  if (!store) handleNoStore(mode);
11224
- const graphModule = await import("./dist-QPWXPCPL.js");
12467
+ const graphModule = await import("./dist-R3TOOPJ7.js");
11225
12468
  const filterOptions = buildFilterOptions(options);
11226
12469
  const results = graphModule.queryTraceability(store, filterOptions);
11227
12470
  if (results.length === 0) handleEmptyResults(mode);
@@ -11236,7 +12479,7 @@ async function runTraceability(options) {
11236
12479
  process.exit(ExitCode.SUCCESS);
11237
12480
  }
11238
12481
  function createTraceabilityCommand() {
11239
- return new Command98("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) => {
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) => {
11240
12483
  const globalOpts = cmd.optsWithGlobals();
11241
12484
  await runTraceability({
11242
12485
  spec: opts.spec,
@@ -11250,7 +12493,7 @@ function createTraceabilityCommand() {
11250
12493
 
11251
12494
  // src/commands/uninstall.ts
11252
12495
  import * as path68 from "path";
11253
- import { Command as Command99 } from "commander";
12496
+ import { Command as Command112 } from "commander";
11254
12497
  async function runUninstall(skillName, options) {
11255
12498
  const packageName = resolvePackageName(skillName);
11256
12499
  const shortName = extractSkillName(packageName);
@@ -11287,7 +12530,7 @@ async function runUninstall(skillName, options) {
11287
12530
  return result;
11288
12531
  }
11289
12532
  function createUninstallCommand() {
11290
- const cmd = new Command99("uninstall");
12533
+ const cmd = new Command112("uninstall");
11291
12534
  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) => {
11292
12535
  try {
11293
12536
  const result = await runUninstall(skill, opts);
@@ -11309,7 +12552,7 @@ function createUninstallCommand() {
11309
12552
  init_dist3();
11310
12553
  import * as fs46 from "fs/promises";
11311
12554
  import * as path69 from "path";
11312
- import { Command as Command100 } from "commander";
12555
+ import { Command as Command113 } from "commander";
11313
12556
  async function runUninstallConstraints(options) {
11314
12557
  const { packageName, configPath, lockfilePath } = options;
11315
12558
  const lockfileResult = await readLockfile(lockfilePath);
@@ -11366,7 +12609,7 @@ async function runUninstallConstraints(options) {
11366
12609
  };
11367
12610
  }
11368
12611
  function createUninstallConstraintsCommand() {
11369
- const cmd = new Command100("uninstall-constraints");
12612
+ const cmd = new Command113("uninstall-constraints");
11370
12613
  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) => {
11371
12614
  let configPath;
11372
12615
  if (opts.config) {
@@ -11406,7 +12649,7 @@ function createUninstallConstraintsCommand() {
11406
12649
 
11407
12650
  // src/commands/update.ts
11408
12651
  init_dist3();
11409
- import { Command as Command101 } from "commander";
12652
+ import { Command as Command114 } from "commander";
11410
12653
  import { execFile, execFileSync as execFileSync7 } from "child_process";
11411
12654
  import { realpathSync, existsSync as existsSync43, readFileSync as readFileSync33 } from "fs";
11412
12655
  import { dirname as dirname22, join as join59 } from "path";
@@ -11774,7 +13017,7 @@ async function runUpdateAction(opts, globalOpts) {
11774
13017
  process.exit(ExitCode.SUCCESS);
11775
13018
  }
11776
13019
  function createUpdateCommand() {
11777
- return new Command101("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(
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(
11778
13021
  "--regenerate",
11779
13022
  "Only regenerate slash commands and agent definitions (skip package updates)"
11780
13023
  ).action(async (opts, cmd) => {
@@ -11784,9 +13027,9 @@ function createUpdateCommand() {
11784
13027
  }
11785
13028
 
11786
13029
  // src/commands/usage.ts
11787
- import { Command as Command102 } from "commander";
13030
+ import { Command as Command115 } from "commander";
11788
13031
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
11789
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-OHDQBTSO.js");
13032
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-XIJWWQ5N.js");
11790
13033
  const records = readCostRecords(cwd);
11791
13034
  if (includeClaudeSessions) {
11792
13035
  const ccRecords = parseCCRecords();
@@ -11879,7 +13122,7 @@ function registerDailyCommand(usage) {
11879
13122
  else logger.info("No usage data found. Run some harness sessions first.");
11880
13123
  return;
11881
13124
  }
11882
- const { aggregateByDay } = await import("./dist-OHDQBTSO.js");
13125
+ const { aggregateByDay } = await import("./dist-XIJWWQ5N.js");
11883
13126
  const limited = aggregateByDay(records).slice(0, days);
11884
13127
  if (globalOpts.json) {
11885
13128
  console.log(
@@ -11908,7 +13151,7 @@ function registerSessionsCommand(usage) {
11908
13151
  }
11909
13152
  return;
11910
13153
  }
11911
- const { aggregateBySession } = await import("./dist-OHDQBTSO.js");
13154
+ const { aggregateBySession } = await import("./dist-XIJWWQ5N.js");
11912
13155
  const sessionData = aggregateBySession(records);
11913
13156
  const limited = sessionData.slice(0, limit);
11914
13157
  if (globalOpts.json) {
@@ -11988,7 +13231,7 @@ function registerSessionCommand(usage) {
11988
13231
  cwd,
11989
13232
  globalOpts.includeClaudeSessions
11990
13233
  );
11991
- const { aggregateBySession } = await import("./dist-OHDQBTSO.js");
13234
+ const { aggregateBySession } = await import("./dist-XIJWWQ5N.js");
11992
13235
  const sessionData = aggregateBySession(records);
11993
13236
  const match = sessionData.find((s) => s.sessionId === id);
11994
13237
  if (!match) {
@@ -12023,7 +13266,7 @@ function registerLatestCommand(usage) {
12023
13266
  }
12024
13267
  return;
12025
13268
  }
12026
- const { aggregateBySession } = await import("./dist-OHDQBTSO.js");
13269
+ const { aggregateBySession } = await import("./dist-XIJWWQ5N.js");
12027
13270
  const sessionData = aggregateBySession(records);
12028
13271
  const latest = sessionData[0];
12029
13272
  if (!latest) {
@@ -12049,7 +13292,7 @@ function registerLatestCommand(usage) {
12049
13292
  });
12050
13293
  }
12051
13294
  function createUsageCommand() {
12052
- const usage = new Command102("usage").description("Token usage and cost tracking");
13295
+ const usage = new Command115("usage").description("Token usage and cost tracking");
12053
13296
  usage.option(
12054
13297
  "--include-claude-sessions",
12055
13298
  "Include Claude Code session data from ~/.claude/projects/"
@@ -12064,7 +13307,7 @@ function createUsageCommand() {
12064
13307
  // src/commands/validate.ts
12065
13308
  init_dist3();
12066
13309
  init_dist3();
12067
- import { Command as Command103 } from "commander";
13310
+ import { Command as Command116 } from "commander";
12068
13311
  import * as path70 from "path";
12069
13312
  async function runValidate(options) {
12070
13313
  const configResult = resolveConfig(options.configPath);
@@ -12163,6 +13406,102 @@ async function runValidate(options) {
12163
13406
  }
12164
13407
  });
12165
13408
  }
13409
+ const anatomyEnabled = config.design?.audit?.componentAnatomy?.enabled !== false;
13410
+ if (anatomyEnabled) {
13411
+ try {
13412
+ const strictness = config.design?.strictness ?? "standard";
13413
+ const auditOutput = await runAudit({
13414
+ path: cwd,
13415
+ mode: "fast",
13416
+ designStrictness: strictness
13417
+ });
13418
+ result.checks.componentAnatomy = true;
13419
+ for (const finding of auditOutput.findings) {
13420
+ const severity = finding.severity === "warn" ? "warning" : finding.severity;
13421
+ if (severity === "error") result.valid = false;
13422
+ result.issues.push({
13423
+ check: "componentAnatomy",
13424
+ file: finding.file,
13425
+ ...finding.line !== null && finding.line !== void 0 && { line: finding.line },
13426
+ ruleId: finding.code,
13427
+ severity,
13428
+ message: finding.message,
13429
+ suggestion: finding.fix.description
13430
+ });
13431
+ }
13432
+ } catch (err) {
13433
+ result.checks.componentAnatomy = false;
13434
+ result.issues.push({
13435
+ check: "componentAnatomy",
13436
+ severity: "warning",
13437
+ message: `Component-anatomy audit skipped: ${err.message}`
13438
+ });
13439
+ }
13440
+ }
13441
+ const driftEnabled = config.design?.audit?.driftDetection?.enabled !== false;
13442
+ if (driftEnabled) {
13443
+ try {
13444
+ const strictness = config.design?.strictness ?? "standard";
13445
+ const driftOutput = await runDetectDrift({
13446
+ path: cwd,
13447
+ mode: "fast",
13448
+ designStrictness: strictness
13449
+ });
13450
+ result.checks.driftDetection = true;
13451
+ for (const finding of driftOutput.findings) {
13452
+ const severity = finding.severity === "warn" ? "warning" : finding.severity;
13453
+ if (severity === "error") result.valid = false;
13454
+ result.issues.push({
13455
+ check: "driftDetection",
13456
+ file: finding.file,
13457
+ ...finding.line !== null && finding.line !== void 0 && { line: finding.line },
13458
+ ruleId: finding.code,
13459
+ severity,
13460
+ message: finding.message,
13461
+ suggestion: finding.fix.description
13462
+ });
13463
+ }
13464
+ } catch (err) {
13465
+ result.checks.driftDetection = false;
13466
+ result.issues.push({
13467
+ check: "driftDetection",
13468
+ severity: "warning",
13469
+ message: `Drift detection skipped: ${err.message}`
13470
+ });
13471
+ }
13472
+ }
13473
+ const brandEnabled = config.design?.audit?.brandCompliance?.enabled !== false;
13474
+ if (brandEnabled) {
13475
+ try {
13476
+ const strictness = config.design?.strictness ?? "standard";
13477
+ const brandOutput = await runAuditBrand({
13478
+ path: cwd,
13479
+ mode: "fast",
13480
+ designStrictness: strictness
13481
+ });
13482
+ result.checks.brandCompliance = true;
13483
+ for (const finding of brandOutput.findings) {
13484
+ const severity = finding.severity === "warn" ? "warning" : finding.severity;
13485
+ if (severity === "error") result.valid = false;
13486
+ result.issues.push({
13487
+ check: "brandCompliance",
13488
+ file: finding.file,
13489
+ ...finding.line !== null && finding.line !== void 0 && { line: finding.line },
13490
+ ruleId: finding.code,
13491
+ severity,
13492
+ message: finding.message,
13493
+ suggestion: finding.fix.description
13494
+ });
13495
+ }
13496
+ } catch (err) {
13497
+ result.checks.brandCompliance = false;
13498
+ result.issues.push({
13499
+ check: "brandCompliance",
13500
+ severity: "warning",
13501
+ message: `Brand compliance audit skipped: ${err.message}`
13502
+ });
13503
+ }
13504
+ }
12166
13505
  if (options.agentConfigs) {
12167
13506
  const agentCfg = await validateAgentConfigs(cwd, {
12168
13507
  strict: options.strict === true,
@@ -12192,7 +13531,7 @@ function resolveValidateMode(globalOpts) {
12192
13531
  return OutputMode.TEXT;
12193
13532
  }
12194
13533
  async function printCrossCheckWarnings(mode) {
12195
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-BUAGBAPO.js");
13534
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-SNE3SQOB.js");
12196
13535
  const cwd = process.cwd();
12197
13536
  const crossResult = await runCrossCheck2({
12198
13537
  specsDir: path70.join(cwd, "docs", "specs"),
@@ -12208,7 +13547,7 @@ async function printCrossCheckWarnings(mode) {
12208
13547
  ${crossResult.value.warnings} warnings`);
12209
13548
  }
12210
13549
  function createValidateCommand3() {
12211
- const command = new Command103("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
13550
+ const command = new Command116("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
12212
13551
  "--agent-configs",
12213
13552
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
12214
13553
  ).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()));
@@ -12257,7 +13596,7 @@ Agent configs checked via ${engineLabel}${note}`);
12257
13596
 
12258
13597
  // src/commands/verify.ts
12259
13598
  init_dist3();
12260
- import { Command as Command104 } from "commander";
13599
+ import { Command as Command117 } from "commander";
12261
13600
  import { execSync as execSync6 } from "child_process";
12262
13601
  function loadBranchingConfig(configPath) {
12263
13602
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -12320,7 +13659,7 @@ async function runVerify(options) {
12320
13659
  process.exit(ExitCode.VALIDATION_FAILED);
12321
13660
  }
12322
13661
  function createVerifyCommand() {
12323
- return new Command104("verify").description(
13662
+ return new Command117("verify").description(
12324
13663
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
12325
13664
  ).option(
12326
13665
  "--branch <name>",
@@ -12341,11 +13680,13 @@ var commandCreators = [
12341
13680
  createAdoptionCommand,
12342
13681
  createAdviseSkillsCommand,
12343
13682
  createAgentCommand,
13683
+ createAlignDesignSystemCommand,
12344
13684
  createAuditProtectedCommand,
12345
13685
  createBackfillSkillProvenanceCommand,
12346
13686
  createBlueprintCommand,
12347
13687
  createCheckArchCommand,
12348
13688
  createCheckDepsCommand,
13689
+ createCheckDesignCommand,
12349
13690
  createCheckDocsCommand,
12350
13691
  createCheckPerfCommand,
12351
13692
  createCheckPhaseGateCommand,
@@ -12354,8 +13695,10 @@ var commandCreators = [
12354
13695
  createCleanupCommand,
12355
13696
  createCleanupSessionsCommand,
12356
13697
  createCompoundCommand,
13698
+ createCopyCraftCommand,
12357
13699
  createCreateSkillCommand,
12358
13700
  createDashboardCommand,
13701
+ createDesignPipelineCommand,
12359
13702
  createDoctorCommand,
12360
13703
  createFixDriftCommand,
12361
13704
  createGatewayCommand,
@@ -12371,6 +13714,7 @@ var commandCreators = [
12371
13714
  createInstallCommand,
12372
13715
  createInstallConstraintsCommand,
12373
13716
  createIntegrationsCommand,
13717
+ createKnowledgeCraftCommand,
12374
13718
  createKnowledgePipelineCommand,
12375
13719
  createLearningsCommand,
12376
13720
  createLinterCommand,
@@ -12378,6 +13722,7 @@ var commandCreators = [
12378
13722
  createMcpCommand,
12379
13723
  createMcpGuardCommand,
12380
13724
  createMigrateCommand,
13725
+ createNamingCraftCommand,
12381
13726
  createNotificationsCommand,
12382
13727
  createOrchestratorCommand,
12383
13728
  createPerfCommand,
@@ -12389,19 +13734,23 @@ var commandCreators = [
12389
13734
  createQueryCommand,
12390
13735
  createRecommendCommand,
12391
13736
  createRoadmapCommand,
13737
+ createRoutingCommand,
12392
13738
  createScanCommand,
12393
13739
  createScanConfigCommand,
12394
13740
  createSearchCommand,
13741
+ createSecurityCraftCommand,
12395
13742
  createSetupCommand,
12396
13743
  createSetupMcpCommand,
12397
13744
  createShareCommand,
12398
13745
  createSkillCommand,
12399
13746
  createSnapshotCommand,
13747
+ createSpecCraftCommand,
12400
13748
  createStateCommand,
12401
13749
  createSyncAnalysesCommand,
12402
13750
  createSyncMainCommand,
12403
13751
  createTaintCommand,
12404
13752
  createTelemetryCommand,
13753
+ createTestCraftCommand,
12405
13754
  createTraceabilityCommand,
12406
13755
  createUninstallCommand,
12407
13756
  createUninstallConstraintsCommand,
@@ -12413,7 +13762,7 @@ var commandCreators = [
12413
13762
 
12414
13763
  // src/index.ts
12415
13764
  function createProgram() {
12416
- const program = new Command105();
13765
+ const program = new Command118();
12417
13766
  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");
12418
13767
  for (const creator of commandCreators) {
12419
13768
  program.addCommand(creator());