@harness-engineering/cli 2.7.1 → 3.0.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 (197) hide show
  1. package/dist/agents/personas/adversarial-reviewer.yaml +43 -0
  2. package/dist/agents/personas/frontend-races-reviewer.yaml +54 -0
  3. package/dist/agents/personas/typescript-strict-reviewer.yaml +53 -0
  4. package/dist/agents/skills/CHANGELOG.md +12 -0
  5. package/dist/agents/skills/claude-code/align-design-system/SKILL.md +18 -0
  6. package/dist/agents/skills/claude-code/align-design-system/skill.yaml +3 -0
  7. package/dist/agents/skills/claude-code/harness-audit-harness-strength/SKILL.md +188 -0
  8. package/dist/agents/skills/claude-code/harness-audit-harness-strength/skill.yaml +54 -0
  9. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +2 -0
  10. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +58 -12
  11. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +107 -22
  12. package/dist/agents/skills/claude-code/harness-code-review/references/confidence-rubric.md +45 -0
  13. package/dist/agents/skills/claude-code/harness-code-review/references/risk-keywords.md +40 -0
  14. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +3 -0
  15. package/dist/agents/skills/claude-code/harness-compound/SKILL.md +7 -4
  16. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +1 -1
  17. package/dist/agents/skills/claude-code/harness-git-workflow/SKILL.md +2 -0
  18. package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +279 -0
  19. package/dist/agents/skills/claude-code/harness-ideate/references/scoring.md +88 -0
  20. package/dist/agents/skills/claude-code/harness-ideate/skill.yaml +66 -0
  21. package/dist/agents/skills/claude-code/harness-knowledge-pipeline/SKILL.md +2 -0
  22. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +14 -4
  23. package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +12 -16
  24. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +62 -4
  25. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +36 -6
  26. package/dist/agents/skills/claude-code/harness-strategy/SKILL.md +152 -0
  27. package/dist/agents/skills/claude-code/harness-strategy/references/interview.md +122 -0
  28. package/dist/agents/skills/claude-code/harness-strategy/skill.yaml +54 -0
  29. package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +80 -2
  30. package/dist/agents/skills/claude-code/harness-test-advisor/skill.yaml +4 -1
  31. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +86 -18
  32. package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +1 -0
  33. package/dist/agents/skills/claude-code/outcome-eval/SKILL.md +97 -0
  34. package/dist/agents/skills/claude-code/outcome-eval/skill.yaml +51 -0
  35. package/dist/agents/skills/codex/align-design-system/SKILL.md +18 -0
  36. package/dist/agents/skills/codex/align-design-system/skill.yaml +3 -0
  37. package/dist/agents/skills/codex/harness-audit-harness-strength/SKILL.md +188 -0
  38. package/dist/agents/skills/codex/harness-audit-harness-strength/skill.yaml +54 -0
  39. package/dist/agents/skills/codex/harness-autopilot/SKILL.md +2 -0
  40. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +58 -12
  41. package/dist/agents/skills/codex/harness-code-review/SKILL.md +107 -22
  42. package/dist/agents/skills/codex/harness-code-review/references/confidence-rubric.md +45 -0
  43. package/dist/agents/skills/codex/harness-code-review/references/risk-keywords.md +40 -0
  44. package/dist/agents/skills/codex/harness-code-review/skill.yaml +3 -0
  45. package/dist/agents/skills/codex/harness-compound/SKILL.md +7 -4
  46. package/dist/agents/skills/codex/harness-execution/SKILL.md +1 -1
  47. package/dist/agents/skills/codex/harness-git-workflow/SKILL.md +2 -0
  48. package/dist/agents/skills/codex/harness-ideate/SKILL.md +279 -0
  49. package/dist/agents/skills/codex/harness-ideate/references/scoring.md +88 -0
  50. package/dist/agents/skills/codex/harness-ideate/skill.yaml +66 -0
  51. package/dist/agents/skills/codex/harness-knowledge-pipeline/SKILL.md +2 -0
  52. package/dist/agents/skills/codex/harness-planning/SKILL.md +14 -4
  53. package/dist/agents/skills/codex/harness-pulse/SKILL.md +12 -16
  54. package/dist/agents/skills/codex/harness-roadmap/SKILL.md +62 -4
  55. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +36 -6
  56. package/dist/agents/skills/codex/harness-strategy/SKILL.md +152 -0
  57. package/dist/agents/skills/codex/harness-strategy/references/interview.md +122 -0
  58. package/dist/agents/skills/codex/harness-strategy/skill.yaml +54 -0
  59. package/dist/agents/skills/codex/harness-test-advisor/SKILL.md +80 -2
  60. package/dist/agents/skills/codex/harness-test-advisor/skill.yaml +4 -1
  61. package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +86 -18
  62. package/dist/agents/skills/codex/initialize-harness-project/skill.yaml +1 -0
  63. package/dist/agents/skills/codex/outcome-eval/SKILL.md +97 -0
  64. package/dist/agents/skills/codex/outcome-eval/skill.yaml +51 -0
  65. package/dist/agents/skills/cursor/align-design-system/SKILL.md +18 -0
  66. package/dist/agents/skills/cursor/align-design-system/skill.yaml +3 -0
  67. package/dist/agents/skills/cursor/harness-audit-harness-strength/SKILL.md +188 -0
  68. package/dist/agents/skills/cursor/harness-audit-harness-strength/skill.yaml +54 -0
  69. package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +2 -0
  70. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +58 -12
  71. package/dist/agents/skills/cursor/harness-code-review/SKILL.md +107 -22
  72. package/dist/agents/skills/cursor/harness-code-review/references/confidence-rubric.md +45 -0
  73. package/dist/agents/skills/cursor/harness-code-review/references/risk-keywords.md +40 -0
  74. package/dist/agents/skills/cursor/harness-code-review/skill.yaml +3 -0
  75. package/dist/agents/skills/cursor/harness-compound/SKILL.md +7 -4
  76. package/dist/agents/skills/cursor/harness-execution/SKILL.md +1 -1
  77. package/dist/agents/skills/cursor/harness-git-workflow/SKILL.md +2 -0
  78. package/dist/agents/skills/cursor/harness-ideate/SKILL.md +279 -0
  79. package/dist/agents/skills/cursor/harness-ideate/references/scoring.md +88 -0
  80. package/dist/agents/skills/cursor/harness-ideate/skill.yaml +66 -0
  81. package/dist/agents/skills/cursor/harness-knowledge-pipeline/SKILL.md +2 -0
  82. package/dist/agents/skills/cursor/harness-planning/SKILL.md +14 -4
  83. package/dist/agents/skills/cursor/harness-pulse/SKILL.md +12 -16
  84. package/dist/agents/skills/cursor/harness-roadmap/SKILL.md +62 -4
  85. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +36 -6
  86. package/dist/agents/skills/cursor/harness-strategy/SKILL.md +152 -0
  87. package/dist/agents/skills/cursor/harness-strategy/references/interview.md +122 -0
  88. package/dist/agents/skills/cursor/harness-strategy/skill.yaml +54 -0
  89. package/dist/agents/skills/cursor/harness-test-advisor/SKILL.md +80 -2
  90. package/dist/agents/skills/cursor/harness-test-advisor/skill.yaml +4 -1
  91. package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +86 -18
  92. package/dist/agents/skills/cursor/initialize-harness-project/skill.yaml +1 -0
  93. package/dist/agents/skills/cursor/outcome-eval/SKILL.md +97 -0
  94. package/dist/agents/skills/cursor/outcome-eval/skill.yaml +51 -0
  95. package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +18 -0
  96. package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +3 -0
  97. package/dist/agents/skills/gemini-cli/harness-audit-harness-strength/SKILL.md +188 -0
  98. package/dist/agents/skills/gemini-cli/harness-audit-harness-strength/skill.yaml +54 -0
  99. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +2 -0
  100. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +58 -12
  101. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +107 -22
  102. package/dist/agents/skills/gemini-cli/harness-code-review/references/confidence-rubric.md +45 -0
  103. package/dist/agents/skills/gemini-cli/harness-code-review/references/risk-keywords.md +40 -0
  104. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +3 -0
  105. package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +7 -4
  106. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +1 -1
  107. package/dist/agents/skills/gemini-cli/harness-git-workflow/SKILL.md +2 -0
  108. package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +279 -0
  109. package/dist/agents/skills/gemini-cli/harness-ideate/references/scoring.md +88 -0
  110. package/dist/agents/skills/gemini-cli/harness-ideate/skill.yaml +66 -0
  111. package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/SKILL.md +2 -0
  112. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +14 -4
  113. package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +12 -16
  114. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +62 -4
  115. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +36 -6
  116. package/dist/agents/skills/gemini-cli/harness-strategy/SKILL.md +152 -0
  117. package/dist/agents/skills/gemini-cli/harness-strategy/references/interview.md +122 -0
  118. package/dist/agents/skills/gemini-cli/harness-strategy/skill.yaml +54 -0
  119. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +80 -2
  120. package/dist/agents/skills/gemini-cli/harness-test-advisor/skill.yaml +4 -1
  121. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +86 -18
  122. package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +1 -0
  123. package/dist/agents/skills/gemini-cli/outcome-eval/SKILL.md +97 -0
  124. package/dist/agents/skills/gemini-cli/outcome-eval/skill.yaml +51 -0
  125. package/dist/agents/skills/package.json +1 -1
  126. package/dist/agents/skills/tests/harness-strategy.test.ts +145 -0
  127. package/dist/agents/skills/tests/harness-test-advisor.test.ts +94 -0
  128. package/dist/agents-md-XOJE5ETA.js +13 -0
  129. package/dist/analyzer-V633GUHY-MBCQWKDU.js +26 -0
  130. package/dist/{architecture-LUR2I67H.js → architecture-JEZPJ725.js} +6 -6
  131. package/dist/{assess-project-OJWECOP2.js → assess-project-RHXOQNMM.js} +1 -1
  132. package/dist/bin/harness-mcp.js +17 -17
  133. package/dist/bin/harness.js +27 -27
  134. package/dist/{check-phase-gate-HS5KYLRO.js → check-phase-gate-GNDOMS35.js} +6 -6
  135. package/dist/{chunk-6UHDQP2N.js → chunk-2N4OENGE.js} +1 -1
  136. package/dist/{chunk-O2ASYKA6.js → chunk-3ISHDWO7.js} +2 -2
  137. package/dist/{chunk-GGSNWH7P.js → chunk-527G27VI.js} +5 -5
  138. package/dist/{chunk-N5NSSLMU.js → chunk-6WQCLCBO.js} +2 -2
  139. package/dist/{chunk-OH3NXXUY.js → chunk-BDGTZRZ6.js} +11 -1
  140. package/dist/{chunk-Z3TMCCZB.js → chunk-BYVT5LVO.js} +9 -9
  141. package/dist/{chunk-TIH53QXY.js → chunk-CLI4K2CH.js} +1 -1
  142. package/dist/{chunk-VSIRUZQP.js → chunk-DE5U6KOL.js} +2 -2
  143. package/dist/{chunk-FXZI6NJ2.js → chunk-GGKRA7A7.js} +51 -4
  144. package/dist/{chunk-RJ2WEES5.js → chunk-GSP2XIVS.js} +2 -2
  145. package/dist/{chunk-CZPOPMMI.js → chunk-HEIMJJI4.js} +3 -3
  146. package/dist/{chunk-7AF6C5GE.js → chunk-HWTUUQOW.js} +3 -3
  147. package/dist/{chunk-FC4JPM6W.js → chunk-KAJOS3BA.js} +3 -3
  148. package/dist/{chunk-NIVWM7OW.js → chunk-MGUPSE6D.js} +10 -10
  149. package/dist/{chunk-WZY5U6NS.js → chunk-N24HCQA4.js} +3351 -887
  150. package/dist/{chunk-Y4T6ENKQ.js → chunk-N55WOGN3.js} +86 -17
  151. package/dist/{chunk-INBTDBV2.js → chunk-NWLGL3IR.js} +1 -1
  152. package/dist/{chunk-FEKBXX2J.js → chunk-ONCPJGHY.js} +9 -9
  153. package/dist/{chunk-PTHX545Q.js → chunk-PC2R5RUJ.js} +2 -2
  154. package/dist/{chunk-H2ZJOJ7A.js → chunk-PP6ZRL5T.js} +316 -42
  155. package/dist/{chunk-LECXPXS3.js → chunk-QBC7DI4Q.js} +2 -2
  156. package/dist/{chunk-B2VAYLYI.js → chunk-UX3PQKVZ.js} +8 -3
  157. package/dist/{chunk-7PLIWP7U.js → chunk-WWEVS7RO.js} +4409 -743
  158. package/dist/{chunk-LGYXR2KZ.js → chunk-XFU6SB2Q.js} +1122 -689
  159. package/dist/{chunk-KN3EMDZ5.js → chunk-XX4OLNWQ.js} +23 -3
  160. package/dist/{chunk-VI4IS55S.js → chunk-YQSYCBAH.js} +6 -6
  161. package/dist/{chunk-LYIPI2SJ.js → chunk-Z4AWEIBY.js} +6 -6
  162. package/dist/{ci-workflow-MDSTHJOY.js → ci-workflow-ORZ4F45F.js} +5 -5
  163. package/dist/{dist-E3SAAHCM.js → dist-ICW4QUEW.js} +5 -1
  164. package/dist/{dist-72ID44UE.js → dist-LHINSVK4.js} +136 -4
  165. package/dist/{dist-R3TOOPJ7.js → dist-OWHMNL4W.js} +1 -1
  166. package/dist/{docs-2RFOJ6XY.js → docs-AU3DXFFO.js} +6 -6
  167. package/dist/engine-6GPWOYQH.js +13 -0
  168. package/dist/{entropy-3UX6644G.js → entropy-VLKDRMRT.js} +5 -5
  169. package/dist/{feedback-CVCFYND4.js → feedback-YXYY44ZC.js} +1 -1
  170. package/dist/{generate-agent-definitions-HZ3XENWO.js → generate-agent-definitions-XIHQPKG3.js} +6 -6
  171. package/dist/{glob-helper-EX4YZKZO.js → glob-helper-GLZAURJC.js} +1 -1
  172. package/dist/{graph-loader-EIFEOUVI.js → graph-loader-HHXN5FLP.js} +1 -1
  173. package/dist/hooks/cost-tracker.js +29 -6
  174. package/dist/index.d.ts +202 -0
  175. package/dist/index.js +27 -27
  176. package/dist/{loader-6RHWU5FH.js → loader-YAN56MT3.js} +5 -5
  177. package/dist/{mcp-OYR26JDI.js → mcp-RK3SFVYB.js} +17 -17
  178. package/dist/{performance-JJMIRXCH.js → performance-64DPTLLQ.js} +6 -6
  179. package/dist/{review-pipeline-BHQZIXWZ.js → review-pipeline-NENG6LW7.js} +5 -5
  180. package/dist/{runtime-DALTAVTN.js → runtime-FFIIRT2T.js} +5 -5
  181. package/dist/{scan-LYKLM4EQ.js → scan-P7YFKB77.js} +1 -1
  182. package/dist/{security-RMLMYFPB.js → security-3PIBN35B.js} +1 -1
  183. package/dist/templates/basic/harness.config.json.hbs +34 -0
  184. package/dist/templates/ci/README.md +86 -0
  185. package/dist/templates/ci/required-review.ruleset.json +20 -0
  186. package/dist/templates/ci/required-review.yml.hbs +57 -0
  187. package/dist/templates/ci/template.json +5 -0
  188. package/dist/templates/intermediate/harness.config.json.hbs +36 -0
  189. package/dist/templates/orchestrator/harness.orchestrator.md +9 -0
  190. package/dist/{tool-tiers-B7JC2XC3.js → tool-tiers-OKK5FE57.js} +2 -0
  191. package/dist/{validate-R7DZRDFK.js → validate-7IAF2ES3.js} +6 -6
  192. package/dist/validate-cross-check-QPSAOZKD.js +13 -0
  193. package/package.json +8 -8
  194. package/dist/agents-md-FKMKH6ZF.js +0 -13
  195. package/dist/analyzer-H3AHBFSL-KPOPJYRB.js +0 -26
  196. package/dist/engine-BSFKOGPN.js +0 -13
  197. package/dist/validate-cross-check-AUUZFNVL.js +0 -13
@@ -1,26 +1,26 @@
1
1
  import {
2
2
  generateRuntime
3
- } from "./chunk-N5NSSLMU.js";
3
+ } from "./chunk-6WQCLCBO.js";
4
4
  import {
5
5
  generateAgentsMd
6
- } from "./chunk-LECXPXS3.js";
6
+ } from "./chunk-QBC7DI4Q.js";
7
7
  import {
8
8
  generateCIWorkflow
9
- } from "./chunk-RJ2WEES5.js";
9
+ } from "./chunk-GSP2XIVS.js";
10
10
  import {
11
11
  createGenerateAgentDefinitionsCommand,
12
12
  generateAgentDefinitions
13
- } from "./chunk-INBTDBV2.js";
13
+ } from "./chunk-NWLGL3IR.js";
14
14
  import {
15
15
  toKebabCase
16
16
  } from "./chunk-KET4QQZB.js";
17
17
  import {
18
18
  createScanCommand,
19
19
  loadIngestOptions
20
- } from "./chunk-6UHDQP2N.js";
20
+ } from "./chunk-2N4OENGE.js";
21
21
  import {
22
22
  TemplateEngine
23
- } from "./chunk-B2VAYLYI.js";
23
+ } from "./chunk-UX3PQKVZ.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-PTHX545Q.js";
34
+ } from "./chunk-PC2R5RUJ.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-FC4JPM6W.js";
49
+ } from "./chunk-KAJOS3BA.js";
50
50
  import {
51
51
  appendFrameworkAgents,
52
52
  captureHealthSnapshot,
@@ -74,13 +74,13 @@ import {
74
74
  runSecurityCraft,
75
75
  runSpecCraft,
76
76
  runTestCraft
77
- } from "./chunk-7PLIWP7U.js";
77
+ } from "./chunk-WWEVS7RO.js";
78
78
  import {
79
79
  VALID_PLATFORMS
80
80
  } from "./chunk-3ISINLYT.js";
81
81
  import {
82
82
  loadGraphStore
83
- } from "./chunk-TIH53QXY.js";
83
+ } from "./chunk-CLI4K2CH.js";
84
84
  import {
85
85
  loadOrRebuildIndex
86
86
  } from "./chunk-27AJKSQY.js";
@@ -99,7 +99,7 @@ import {
99
99
  BranchingConfigSchema,
100
100
  findConfigFile,
101
101
  resolveConfig
102
- } from "./chunk-FXZI6NJ2.js";
102
+ } from "./chunk-GGKRA7A7.js";
103
103
  import {
104
104
  logger
105
105
  } from "./chunk-EBJQ6N4M.js";
@@ -114,10 +114,13 @@ import {
114
114
  BlueprintGenerator,
115
115
  BundleSchema,
116
116
  CINotifier,
117
+ CI_ASSESSMENTS,
117
118
  CriticalPathResolver,
118
119
  GitHubIssuesSyncAdapter,
120
+ HarnessStrengthAuditor,
119
121
  PredictionEngine,
120
122
  ProjectScanner,
123
+ RUNNER_PRESETS,
121
124
  SecurityScanner,
122
125
  SecurityTimelineManager,
123
126
  SpecImpactEstimator,
@@ -128,6 +131,7 @@ import {
128
131
  assembleCandidateReport,
129
132
  assembleReport,
130
133
  checkDocCoverage,
134
+ checkRoadmapHealth,
131
135
  checkTaint,
132
136
  clearTaint,
133
137
  computeHotspots,
@@ -179,6 +183,7 @@ import {
179
183
  resolveStreamPath,
180
184
  runAll,
181
185
  runCIChecks,
186
+ runCiReview,
182
187
  runPulse,
183
188
  runReviewPipeline,
184
189
  scanForInjection,
@@ -191,9 +196,10 @@ import {
191
196
  validatePulseConfig,
192
197
  validateRoadmapMode,
193
198
  validateSolutionsDir,
199
+ validateStrategy,
194
200
  writeConfig,
195
201
  writeLockfile
196
- } from "./chunk-WZY5U6NS.js";
202
+ } from "./chunk-N24HCQA4.js";
197
203
  import {
198
204
  CLI_VERSION
199
205
  } from "./chunk-BM3PWGXQ.js";
@@ -206,20 +212,20 @@ import {
206
212
  detectDocDrift,
207
213
  generateSuggestions,
208
214
  validateDependencies
209
- } from "./chunk-Y4T6ENKQ.js";
215
+ } from "./chunk-N55WOGN3.js";
210
216
  import {
211
217
  Err,
212
218
  INDEXED_FILE_KINDS,
213
219
  INSIGHTS_KEYS,
214
220
  Ok,
215
221
  init_dist
216
- } from "./chunk-OH3NXXUY.js";
222
+ } from "./chunk-BDGTZRZ6.js";
217
223
  import {
218
224
  DEFAULT_SKIP_DIRS,
219
225
  DesignConstraintAdapter,
220
226
  GraphStore,
221
227
  init_dist as init_dist2
222
- } from "./chunk-H2ZJOJ7A.js";
228
+ } from "./chunk-PP6ZRL5T.js";
223
229
  import {
224
230
  ArchConfigSchema,
225
231
  TimelineManager
@@ -230,7 +236,7 @@ import {
230
236
  } from "./chunk-KFQGP6VL.js";
231
237
 
232
238
  // src/index.ts
233
- import { Command as Command120 } from "commander";
239
+ import { Command as Command122 } from "commander";
234
240
 
235
241
  // src/commands/add.ts
236
242
  init_dist3();
@@ -419,7 +425,7 @@ function registerSkillsCommand(adoption) {
419
425
  const globalOpts = cmd.optsWithGlobals();
420
426
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
421
427
  const cwd = process.cwd();
422
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-72ID44UE.js");
428
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-LHINSVK4.js");
423
429
  const records = readAdoptionRecords(cwd);
424
430
  if (records.length === 0) {
425
431
  if (globalOpts.json) {
@@ -455,7 +461,7 @@ function registerRecentCommand(adoption) {
455
461
  const globalOpts = cmd.optsWithGlobals();
456
462
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
457
463
  const cwd = process.cwd();
458
- const { readAdoptionRecords } = await import("./dist-72ID44UE.js");
464
+ const { readAdoptionRecords } = await import("./dist-LHINSVK4.js");
459
465
  const records = readAdoptionRecords(cwd);
460
466
  if (records.length === 0) {
461
467
  if (globalOpts.json) {
@@ -533,7 +539,7 @@ function registerSkillCommand(adoption) {
533
539
  adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
534
540
  const globalOpts = cmd.optsWithGlobals();
535
541
  const cwd = process.cwd();
536
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-72ID44UE.js");
542
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-LHINSVK4.js");
537
543
  const records = readAdoptionRecords(cwd);
538
544
  const skillRecords = records.filter((r) => r.skill === name);
539
545
  if (skillRecords.length === 0) {
@@ -848,6 +854,9 @@ function createAlignDesignSystemCommand() {
848
854
  ).option(
849
855
  "--design-strictness <level>",
850
856
  "Override design.strictness: strict | standard | permissive"
857
+ ).option(
858
+ "--revert",
859
+ "Inverse-apply the most-recent batch recorded at .harness/align/last-batch.json. Skips files edited externally since the apply."
851
860
  ).action(async (opts, cmd) => {
852
861
  const globalOpts = cmd.optsWithGlobals();
853
862
  const outputMode = resolveOutputMode(globalOpts);
@@ -858,6 +867,7 @@ function createAlignDesignSystemCommand() {
858
867
  if (opts.files !== void 0) input.files = opts.files;
859
868
  if (opts.mode !== void 0) input.mode = opts.mode;
860
869
  if (opts.designStrictness !== void 0) input.designStrictness = opts.designStrictness;
870
+ if (opts.revert === true) input.revert = true;
861
871
  let result;
862
872
  try {
863
873
  result = await runAlignDesignSystem(input);
@@ -884,7 +894,11 @@ function printAlignResult(result, mode, _formatter) {
884
894
  const verbose = mode === OutputMode.VERBOSE;
885
895
  const { summary, outcomes, meta } = result;
886
896
  if (outcomes.length === 0) {
887
- console.log("No drift findings to align.");
897
+ if (meta.revert === true) {
898
+ console.log("No batch to revert (.harness/align/last-batch.json missing or empty).");
899
+ } else {
900
+ console.log("No drift findings to align.");
901
+ }
888
902
  return;
889
903
  }
890
904
  const byFile = /* @__PURE__ */ new Map();
@@ -914,8 +928,9 @@ ${file}`);
914
928
  }
915
929
  }
916
930
  console.log("");
931
+ const action = meta.revert === true ? "reverted" : "applied";
917
932
  console.log(
918
- `Summary: ${summary.applied} applied, ${summary.suggestions} suggestions, ${summary.skipped} skipped, ${summary.failed} failed (${summary.filesModified} files modified, ${summary.durationMs}ms)`
933
+ `Summary: ${summary.applied} ${action}, ${summary.suggestions} suggestions, ${summary.skipped} skipped, ${summary.failed} failed (${summary.filesModified} files modified, ${summary.durationMs}ms)`
919
934
  );
920
935
  if (meta.dryRun) {
921
936
  console.log("(dry-run \u2014 no files written)");
@@ -1654,9 +1669,9 @@ ${name} (${count} finding${count === 1 ? "" : "s"})`);
1654
1669
  }
1655
1670
  function printAnatomyFindings(findings, verbose) {
1656
1671
  const byFile = groupByFile(findings, (f) => f.file);
1657
- for (const [file, fs48] of byFile) {
1672
+ for (const [file, fs49] of byFile) {
1658
1673
  console.log(` ${file}`);
1659
- for (const f of fs48) {
1674
+ for (const f of fs49) {
1660
1675
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1661
1676
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1662
1677
  if (verbose) {
@@ -1667,9 +1682,9 @@ function printAnatomyFindings(findings, verbose) {
1667
1682
  }
1668
1683
  function printCraftFindings(findings, verbose) {
1669
1684
  const byFile = groupByFile(findings, (f) => f.target.file);
1670
- for (const [file, fs48] of byFile) {
1685
+ for (const [file, fs49] of byFile) {
1671
1686
  console.log(` ${file}`);
1672
- for (const f of fs48) {
1687
+ for (const f of fs49) {
1673
1688
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
1674
1689
  const sev = craftTierToSeverity(f.tier);
1675
1690
  console.log(
@@ -1683,9 +1698,9 @@ function printCraftFindings(findings, verbose) {
1683
1698
  }
1684
1699
  function printDriftFindings(findings, verbose) {
1685
1700
  const byFile = groupByFile(findings, (f) => f.file);
1686
- for (const [file, fs48] of byFile) {
1701
+ for (const [file, fs49] of byFile) {
1687
1702
  console.log(` ${file}`);
1688
- for (const f of fs48) {
1703
+ for (const f of fs49) {
1689
1704
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1690
1705
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1691
1706
  if (verbose) {
@@ -1696,9 +1711,9 @@ function printDriftFindings(findings, verbose) {
1696
1711
  }
1697
1712
  function printBrandFindings(findings, verbose) {
1698
1713
  const byFile = groupByFile(findings, (f) => f.file);
1699
- for (const [file, fs48] of byFile) {
1714
+ for (const [file, fs49] of byFile) {
1700
1715
  console.log(` ${file}`);
1701
- for (const f of fs48) {
1716
+ for (const f of fs49) {
1702
1717
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1703
1718
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1704
1719
  if (verbose) {
@@ -1867,14 +1882,90 @@ function createCheckDocsCommand() {
1867
1882
  return command;
1868
1883
  }
1869
1884
 
1870
- // src/commands/check-perf.ts
1885
+ // src/commands/check-harness-strength.ts
1871
1886
  init_dist3();
1872
1887
  import { Command as Command14 } from "commander";
1873
1888
  import * as path8 from "path";
1889
+ var SEVERITY_RANK = { error: 3, warning: 2, info: 1 };
1890
+ function runCheckHarnessStrength(cwd, options) {
1891
+ const projectRoot2 = path8.resolve(cwd);
1892
+ const auditor = new HarnessStrengthAuditor();
1893
+ const result = auditor.audit(projectRoot2, options.mode ? { mode: options.mode } : {});
1894
+ if (!result.ok) return result;
1895
+ const audit = result.value;
1896
+ const threshold = options.severity ?? "warning";
1897
+ const thresholdRank = SEVERITY_RANK[threshold];
1898
+ const filtered = audit.findings.filter((f) => SEVERITY_RANK[f.severity] >= thresholdRank);
1899
+ const hasErrors = filtered.some((f) => f.severity === "error");
1900
+ return Ok({ valid: !hasErrors, audit, filtered });
1901
+ }
1902
+ async function runCheckHarnessStrengthAction(opts, globalOpts) {
1903
+ const outMode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
1904
+ const formatter = new OutputFormatter(outMode);
1905
+ const resolvedMode = opts.mode ?? (opts.toolkit ? "toolkit" : opts.adopter ? "adopter" : void 0);
1906
+ const result = runCheckHarnessStrength(process.cwd(), {
1907
+ severity: opts.severity,
1908
+ ...resolvedMode !== void 0 && { mode: resolvedMode },
1909
+ ...opts.reportOnly !== void 0 && { reportOnly: opts.reportOnly }
1910
+ });
1911
+ if (!result.ok) {
1912
+ if (outMode === OutputMode.JSON) {
1913
+ console.log(JSON.stringify({ error: result.error.message }));
1914
+ } else {
1915
+ logger.error(result.error.message);
1916
+ }
1917
+ process.exit(ExitCode.ERROR);
1918
+ }
1919
+ const { valid, audit, filtered } = result.value;
1920
+ if (outMode === OutputMode.JSON) {
1921
+ console.log(JSON.stringify(audit, null, 2));
1922
+ process.exit(opts.reportOnly || valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1923
+ }
1924
+ const issues = filtered.map((f) => ({
1925
+ file: f.line !== void 0 ? `${f.file}:${f.line}` : f.file,
1926
+ message: `[${f.id}] ${f.severity.toUpperCase()} ${f.message} -> ${f.remediation}`
1927
+ }));
1928
+ const header = formatter.formatSummary(
1929
+ `harness strength (${audit.mode})`,
1930
+ `${audit.score}/100 (${audit.tier})`,
1931
+ valid
1932
+ );
1933
+ if (header) console.log(header);
1934
+ const output = formatter.formatValidation({ valid, issues });
1935
+ if (output) console.log(output);
1936
+ const summaryLine = formatter.formatSummary(
1937
+ "findings",
1938
+ `${audit.summary.errors} error / ${audit.summary.warnings} warning / ${audit.summary.info} info`,
1939
+ valid
1940
+ );
1941
+ if (summaryLine) console.log(summaryLine);
1942
+ process.exit(opts.reportOnly || valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1943
+ }
1944
+ function createCheckHarnessStrengthCommand() {
1945
+ const command = new Command14("check-harness-strength").description("Mechanically audit this project's harness setup against the 7 strength patterns").option("--severity <level>", "Minimum severity threshold to display and gate on", "warning").option("--mode <mode>", "Audit mode: adopter | toolkit (default: auto-detect)").option("--toolkit", "Force toolkit mode").option("--adopter", "Force adopter mode").option("--report-only", "Always exit 0 regardless of findings").hook("preAction", (thisCommand) => {
1946
+ const { severity, mode } = thisCommand.opts();
1947
+ if (!["error", "warning", "info"].includes(severity)) {
1948
+ logger.error(`Invalid severity: "${severity}". Must be one of: error, warning, info`);
1949
+ process.exit(ExitCode.ERROR);
1950
+ }
1951
+ if (mode !== void 0 && !["adopter", "toolkit"].includes(mode)) {
1952
+ logger.error(`Invalid mode: "${mode}". Must be one of: adopter, toolkit`);
1953
+ process.exit(ExitCode.ERROR);
1954
+ }
1955
+ }).action(async (opts, cmd) => {
1956
+ await runCheckHarnessStrengthAction(opts, cmd.optsWithGlobals());
1957
+ });
1958
+ return command;
1959
+ }
1960
+
1961
+ // src/commands/check-perf.ts
1962
+ init_dist3();
1963
+ import { Command as Command15 } from "commander";
1964
+ import * as path9 from "path";
1874
1965
  async function runCheckPerf(cwd, options) {
1875
1966
  const runAll2 = !options.structural && !options.size && !options.coupling;
1876
1967
  const analyzer = new EntropyAnalyzer({
1877
- rootDir: path8.resolve(cwd),
1968
+ rootDir: path9.resolve(cwd),
1878
1969
  analyze: {
1879
1970
  complexity: runAll2 || !!options.structural,
1880
1971
  coupling: runAll2 || !!options.coupling,
@@ -1986,7 +2077,7 @@ async function runCheckPerfAction(opts, globalOpts) {
1986
2077
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1987
2078
  }
1988
2079
  function createCheckPerfCommand() {
1989
- 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) => {
2080
+ const command = new Command15("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) => {
1990
2081
  await runCheckPerfAction(opts, cmd.optsWithGlobals());
1991
2082
  });
1992
2083
  return command;
@@ -1994,10 +2085,10 @@ function createCheckPerfCommand() {
1994
2085
 
1995
2086
  // src/commands/check-security.ts
1996
2087
  init_dist3();
1997
- import { Command as Command15 } from "commander";
1998
- import * as path9 from "path";
2088
+ import { Command as Command16 } from "commander";
2089
+ import * as path10 from "path";
1999
2090
  import { execSync as execSync3 } from "child_process";
2000
- var SEVERITY_RANK = {
2091
+ var SEVERITY_RANK2 = {
2001
2092
  error: 3,
2002
2093
  warning: 2,
2003
2094
  info: 1
@@ -2008,19 +2099,19 @@ function getChangedFiles(cwd) {
2008
2099
  cwd,
2009
2100
  encoding: "utf-8"
2010
2101
  });
2011
- return output.trim().split("\n").filter((f) => f.length > 0).map((f) => path9.resolve(cwd, f));
2102
+ return output.trim().split("\n").filter((f) => f.length > 0).map((f) => path10.resolve(cwd, f));
2012
2103
  } catch {
2013
2104
  return [];
2014
2105
  }
2015
2106
  }
2016
2107
  async function runCheckSecurity(cwd, options) {
2017
- const projectRoot2 = path9.resolve(cwd);
2108
+ const projectRoot2 = path10.resolve(cwd);
2018
2109
  let configData = {};
2019
2110
  try {
2020
- const fs48 = await import("fs");
2021
- const configPath = path9.join(projectRoot2, "harness.config.json");
2022
- if (fs48.existsSync(configPath)) {
2023
- const raw = fs48.readFileSync(configPath, "utf-8");
2111
+ const fs49 = await import("fs");
2112
+ const configPath = path10.join(projectRoot2, "harness.config.json");
2113
+ if (fs49.existsSync(configPath)) {
2114
+ const raw = fs49.readFileSync(configPath, "utf-8");
2024
2115
  const parsed = JSON.parse(raw);
2025
2116
  configData = parsed.security ?? {};
2026
2117
  }
@@ -2055,8 +2146,8 @@ async function runCheckSecurity(cwd, options) {
2055
2146
  } catch {
2056
2147
  }
2057
2148
  const threshold = options.severity ?? "warning";
2058
- const thresholdRank = SEVERITY_RANK[threshold];
2059
- const filtered = result.findings.filter((f) => SEVERITY_RANK[f.severity] >= thresholdRank);
2149
+ const thresholdRank = SEVERITY_RANK2[threshold];
2150
+ const filtered = result.findings.filter((f) => SEVERITY_RANK2[f.severity] >= thresholdRank);
2060
2151
  const hasErrors = filtered.some((f) => f.severity === "error");
2061
2152
  return Ok({
2062
2153
  valid: !hasErrors,
@@ -2099,7 +2190,7 @@ async function runCheckSecurityAction(opts, globalOpts) {
2099
2190
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
2100
2191
  }
2101
2192
  function createCheckSecurityCommand() {
2102
- 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) => {
2193
+ const command = new Command16("check-security").description("Run lightweight security scan: secrets, injection, XSS, weak crypto").option("--severity <level>", "Minimum severity threshold", "warning").hook("preAction", (thisCommand) => {
2103
2194
  const severity = thisCommand.opts().severity;
2104
2195
  if (!["error", "warning", "info"].includes(severity)) {
2105
2196
  logger.error(`Invalid severity: "${severity}". Must be one of: error, warning, info`);
@@ -2112,11 +2203,11 @@ function createCheckSecurityCommand() {
2112
2203
  }
2113
2204
 
2114
2205
  // src/commands/ci/index.ts
2115
- import { Command as Command19 } from "commander";
2206
+ import { Command as Command20 } from "commander";
2116
2207
 
2117
2208
  // src/commands/ci/check.ts
2118
2209
  init_dist3();
2119
- import { Command as Command16 } from "commander";
2210
+ import { Command as Command17 } from "commander";
2120
2211
  var VALID_CHECKS = [
2121
2212
  "validate",
2122
2213
  "deps",
@@ -2206,16 +2297,16 @@ async function runCheckAction(opts, globalOpts) {
2206
2297
  process.exit(report.exitCode);
2207
2298
  }
2208
2299
  function createCheckCommand() {
2209
- 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) => {
2300
+ return new Command17("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) => {
2210
2301
  await runCheckAction(opts, cmd.optsWithGlobals());
2211
2302
  });
2212
2303
  }
2213
2304
 
2214
2305
  // src/commands/ci/init.ts
2215
2306
  init_dist3();
2216
- import { Command as Command17 } from "commander";
2307
+ import { Command as Command18 } from "commander";
2217
2308
  import * as fs4 from "fs";
2218
- import * as path10 from "path";
2309
+ import * as path11 from "path";
2219
2310
  var ALL_CHECKS = [
2220
2311
  "validate",
2221
2312
  "deps",
@@ -2233,8 +2324,74 @@ function buildSkipFlag(checks) {
2233
2324
  if (skipChecks.length === 0) return "";
2234
2325
  return ` --skip ${skipChecks.join(",")}`;
2235
2326
  }
2236
- function generateGitHubActions(skipFlag) {
2237
- return `name: Harness Checks
2327
+ function stepsForLanguage(language) {
2328
+ switch (language) {
2329
+ case "python":
2330
+ return {
2331
+ setup: ` - uses: actions/setup-python@v5
2332
+ with:
2333
+ python-version: '3.12'`,
2334
+ install: "pip install -e .",
2335
+ lint: "ruff check .",
2336
+ test: "pytest"
2337
+ };
2338
+ case "go":
2339
+ return {
2340
+ setup: ` - uses: actions/setup-go@v5
2341
+ with:
2342
+ go-version: 'stable'`,
2343
+ install: "go mod download",
2344
+ build: "go build ./...",
2345
+ lint: "golangci-lint run",
2346
+ test: "go test ./..."
2347
+ };
2348
+ case "rust":
2349
+ return {
2350
+ setup: ` - uses: dtolnay/rust-toolchain@stable`,
2351
+ install: "cargo fetch",
2352
+ build: "cargo build",
2353
+ lint: "cargo clippy",
2354
+ test: "cargo test"
2355
+ };
2356
+ case "java":
2357
+ return {
2358
+ setup: ` - uses: actions/setup-java@v4
2359
+ with:
2360
+ distribution: 'temurin'
2361
+ java-version: '21'`,
2362
+ install: "mvn -B -q install -DskipTests",
2363
+ test: "mvn -B verify"
2364
+ };
2365
+ case "typescript":
2366
+ default:
2367
+ return {
2368
+ setup: ` - uses: pnpm/action-setup@v4
2369
+ - uses: actions/setup-node@v4
2370
+ with:
2371
+ node-version: '22'`,
2372
+ install: "pnpm i --frozen-lockfile",
2373
+ build: "pnpm build",
2374
+ lint: "pnpm lint",
2375
+ test: "pnpm test"
2376
+ };
2377
+ }
2378
+ }
2379
+ function generateGitHubActions(skipFlag, language) {
2380
+ const steps = stepsForLanguage(language);
2381
+ const commandSteps = [];
2382
+ commandSteps.push(` - name: Install dependencies
2383
+ run: ${steps.install}`);
2384
+ if (steps.build) {
2385
+ commandSteps.push(` - name: Build
2386
+ run: ${steps.build}`);
2387
+ }
2388
+ if (steps.lint) {
2389
+ commandSteps.push(` - name: Lint
2390
+ run: ${steps.lint}`);
2391
+ }
2392
+ commandSteps.push(` - name: Test
2393
+ run: ${steps.test}`);
2394
+ return `name: CI
2238
2395
 
2239
2396
  on:
2240
2397
  push:
@@ -2247,15 +2404,15 @@ concurrency:
2247
2404
  cancel-in-progress: true
2248
2405
 
2249
2406
  jobs:
2250
- harness:
2407
+ ci:
2251
2408
  runs-on: ubuntu-latest
2252
2409
  steps:
2253
2410
  - uses: actions/checkout@v4
2254
- - uses: actions/setup-node@v4
2255
- with:
2256
- node-version: '22'
2257
- - run: npm install -g @harness-engineering/cli
2258
- - name: Run harness checks
2411
+ ${steps.setup}
2412
+ ${commandSteps.join("\n")}
2413
+ - name: Install harness CLI
2414
+ run: npm install -g @harness-engineering/cli
2415
+ - name: Harness gate
2259
2416
  run: harness ci check --json${skipFlag}
2260
2417
  `;
2261
2418
  }
@@ -2300,10 +2457,13 @@ exit $EXIT_CODE
2300
2457
  `;
2301
2458
  }
2302
2459
  function generateCIConfig(options) {
2303
- const { platform, checks } = options;
2460
+ const { platform, checks, language } = options;
2304
2461
  const skipFlag = buildSkipFlag(checks);
2305
2462
  const generators = {
2306
- github: { filename: ".github/workflows/harness.yml", generate: generateGitHubActions },
2463
+ github: {
2464
+ filename: ".github/workflows/ci.yml",
2465
+ generate: (skip) => generateGitHubActions(skip, language)
2466
+ },
2307
2467
  gitlab: { filename: ".gitlab-ci-harness.yml", generate: generateGitLabCI },
2308
2468
  generic: { filename: "harness-ci.sh", generate: generateGenericScript }
2309
2469
  };
@@ -2322,8 +2482,8 @@ function detectPlatform() {
2322
2482
  return null;
2323
2483
  }
2324
2484
  function writeGeneratedConfig(filename, content, platform) {
2325
- const targetPath = path10.resolve(filename);
2326
- const dir = path10.dirname(targetPath);
2485
+ const targetPath = path11.resolve(filename);
2486
+ const dir = path11.dirname(targetPath);
2327
2487
  fs4.mkdirSync(dir, { recursive: true });
2328
2488
  fs4.writeFileSync(targetPath, content);
2329
2489
  if (platform === "generic" && process.platform !== "win32") {
@@ -2335,6 +2495,7 @@ async function runInitAction(opts, globalOpts) {
2335
2495
  const checks = opts.checks ? opts.checks.split(",").map((s) => s.trim()) : void 0;
2336
2496
  const configOpts = { platform };
2337
2497
  if (checks) configOpts.checks = checks;
2498
+ if (opts.language) configOpts.language = opts.language;
2338
2499
  const result = generateCIConfig(configOpts);
2339
2500
  if (!result.ok) {
2340
2501
  logger.error(result.error.message);
@@ -2350,14 +2511,14 @@ async function runInitAction(opts, globalOpts) {
2350
2511
  }
2351
2512
  }
2352
2513
  function createInitCommand() {
2353
- 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) => {
2514
+ return new Command18("init").description("Generate CI configuration for harness checks").option("--platform <platform>", "CI platform: github, gitlab, or generic").option("--language <language>", "Project language for build/lint/test steps").option("--checks <list>", "Comma-separated list of checks to include").action(async (opts, cmd) => {
2354
2515
  await runInitAction(opts, cmd.optsWithGlobals());
2355
2516
  });
2356
2517
  }
2357
2518
 
2358
2519
  // src/commands/ci/notify.ts
2359
2520
  init_dist3();
2360
- import { Command as Command18 } from "commander";
2521
+ import { Command as Command19 } from "commander";
2361
2522
  import * as fs5 from "fs";
2362
2523
  function loadReport(reportPath) {
2363
2524
  try {
@@ -2454,14 +2615,14 @@ async function runNotifyAction(reportPath, opts, globalOpts) {
2454
2615
  }
2455
2616
  }
2456
2617
  function createNotifyCommand() {
2457
- 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) => {
2618
+ return new Command19("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) => {
2458
2619
  await runNotifyAction(reportPath, opts, cmd.optsWithGlobals());
2459
2620
  });
2460
2621
  }
2461
2622
 
2462
2623
  // src/commands/ci/index.ts
2463
2624
  function createCICommand() {
2464
- const command = new Command19("ci").description("CI/CD integration commands");
2625
+ const command = new Command20("ci").description("CI/CD integration commands");
2465
2626
  command.addCommand(createCheckCommand());
2466
2627
  command.addCommand(createInitCommand());
2467
2628
  command.addCommand(createNotifyCommand());
@@ -2470,8 +2631,8 @@ function createCICommand() {
2470
2631
 
2471
2632
  // src/commands/cleanup.ts
2472
2633
  init_dist3();
2473
- import { Command as Command20 } from "commander";
2474
- import * as path11 from "path";
2634
+ import { Command as Command21 } from "commander";
2635
+ import * as path12 from "path";
2475
2636
  async function runCleanup(options) {
2476
2637
  const cwd = options.cwd ?? process.cwd();
2477
2638
  const type = options.type ?? "all";
@@ -2486,12 +2647,12 @@ async function runCleanup(options) {
2486
2647
  patternViolations: [],
2487
2648
  totalIssues: 0
2488
2649
  };
2489
- const rootDir = path11.resolve(cwd, config.rootDir);
2490
- const docsDir = path11.resolve(cwd, config.docsDir);
2650
+ const rootDir = path12.resolve(cwd, config.rootDir);
2651
+ const docsDir = path12.resolve(cwd, config.docsDir);
2491
2652
  const entropyConfig = {
2492
2653
  rootDir,
2493
2654
  ...config.entropy?.entryPoints && { entryPoints: config.entropy.entryPoints },
2494
- docPaths: [path11.join(docsDir, "**/*.md")],
2655
+ docPaths: [path12.join(docsDir, "**/*.md")],
2495
2656
  analyze: {
2496
2657
  drift: type === "all" || type === "drift",
2497
2658
  deadCode: type === "all" || type === "dead-code",
@@ -2559,7 +2720,7 @@ function printCleanupResult(value, formatter) {
2559
2720
  }
2560
2721
  }
2561
2722
  function createCleanupCommand() {
2562
- 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) => {
2723
+ const command = new Command21("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) => {
2563
2724
  const globalOpts = cmd.optsWithGlobals();
2564
2725
  const mode = resolveOutputMode(globalOpts);
2565
2726
  const formatter = new OutputFormatter(mode);
@@ -2590,9 +2751,9 @@ function createCleanupCommand() {
2590
2751
 
2591
2752
  // src/commands/cleanup-sessions.ts
2592
2753
  init_dist3();
2593
- import { Command as Command21 } from "commander";
2754
+ import { Command as Command22 } from "commander";
2594
2755
  import * as fs6 from "fs";
2595
- import * as path12 from "path";
2756
+ import * as path13 from "path";
2596
2757
  var STALE_TTL_MS = 24 * 60 * 60 * 1e3;
2597
2758
  var ONE_HOUR_MS = 60 * 60 * 1e3;
2598
2759
  var ONE_DAY_MS = 24 * ONE_HOUR_MS;
@@ -2609,7 +2770,7 @@ function getMostRecentMtime(dirPath) {
2609
2770
  try {
2610
2771
  const entries = fs6.readdirSync(dirPath, { withFileTypes: true });
2611
2772
  for (const entry of entries) {
2612
- const fullPath = path12.join(dirPath, entry.name);
2773
+ const fullPath = path13.join(dirPath, entry.name);
2613
2774
  const stat = fs6.statSync(fullPath);
2614
2775
  if (stat.mtimeMs > latest) latest = stat.mtimeMs;
2615
2776
  }
@@ -2622,7 +2783,7 @@ function getMostRecentMtime(dirPath) {
2622
2783
  async function runCleanupSessions(options) {
2623
2784
  const cwd = options.cwd ?? process.cwd();
2624
2785
  const dryRun = options.dryRun ?? false;
2625
- const sessionsDir = path12.join(cwd, ".harness", "sessions");
2786
+ const sessionsDir = path13.join(cwd, ".harness", "sessions");
2626
2787
  const result = { removed: [], kept: [] };
2627
2788
  if (!fs6.existsSync(sessionsDir)) {
2628
2789
  return Ok(result);
@@ -2641,7 +2802,7 @@ async function runCleanupSessions(options) {
2641
2802
  const now = Date.now();
2642
2803
  for (const entry of entries) {
2643
2804
  if (!entry.isDirectory()) continue;
2644
- const sessionPath = path12.join(sessionsDir, entry.name);
2805
+ const sessionPath = path13.join(sessionsDir, entry.name);
2645
2806
  const mostRecent = getMostRecentMtime(sessionPath);
2646
2807
  const ageMs = now - mostRecent;
2647
2808
  if (ageMs > STALE_TTL_MS) {
@@ -2705,7 +2866,7 @@ async function runCleanupAll(opts) {
2705
2866
  const results = [];
2706
2867
  for (const target of targets) {
2707
2868
  const ttlMs = (ttlOverrides[target.name] ?? 0) > 0 ? ttlOverrides[target.name] * ONE_HOUR_MS : target.defaultTtlMs;
2708
- const dir = path12.join(cwd, ".harness", target.relativeDir);
2869
+ const dir = path13.join(cwd, ".harness", target.relativeDir);
2709
2870
  const sweepResult = await sweepDirectory(dir, ttlMs, dryRun);
2710
2871
  if (!sweepResult.ok) return Err(sweepResult.error);
2711
2872
  results.push({ target: target.name, ...sweepResult.value });
@@ -2729,7 +2890,7 @@ async function sweepDirectory(dir, ttlMs, dryRun) {
2729
2890
  }
2730
2891
  const now = Date.now();
2731
2892
  for (const entry of entries) {
2732
- const entryPath = path12.join(dir, entry.name);
2893
+ const entryPath = path13.join(dir, entry.name);
2733
2894
  const ageMs = now - mtimeOf(entryPath);
2734
2895
  if (ageMs > ttlMs) {
2735
2896
  removed.push(entry.name);
@@ -2786,14 +2947,14 @@ ${dryRun ? "Would remove" : "Removed"} ${totalRemoved} stale entry(ies) across t
2786
2947
  }
2787
2948
  }
2788
2949
  function createCleanupSessionsCommand() {
2789
- const command = new Command21("cleanup-sessions").description(
2950
+ const command = new Command22("cleanup-sessions").description(
2790
2951
  "Remove stale entries from .harness/. Default: only .harness/sessions/ (no write in 24h)."
2791
2952
  ).option("--dry-run", "List stale entries without deleting them", false).option("--path <path>", "Project root path", ".").option("--all", "Sweep every registered .harness/ target").option(
2792
2953
  "--include <list>",
2793
2954
  "Comma-separated target names (mutually-exclusive with --exclude/--all)"
2794
2955
  ).option("--exclude <list>", "Comma-separated target names to skip").action(async (opts, cmd) => {
2795
2956
  const globalOpts = cmd.optsWithGlobals();
2796
- const cwd = path12.resolve(opts.path);
2957
+ const cwd = path13.resolve(opts.path);
2797
2958
  const asJson = Boolean(globalOpts.json);
2798
2959
  if (opts.all || opts.include || opts.exclude) {
2799
2960
  await runExtendedSweep(cwd, opts, asJson);
@@ -2835,13 +2996,13 @@ async function runSessionsOnlySweep(cwd, opts, asJson) {
2835
2996
  }
2836
2997
 
2837
2998
  // src/commands/compound/index.ts
2838
- import { Command as Command23 } from "commander";
2999
+ import { Command as Command24 } from "commander";
2839
3000
 
2840
3001
  // src/commands/compound/scan-candidates.ts
2841
3002
  init_dist3();
2842
3003
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
2843
- import { dirname as dirname2, join as join8, resolve as resolve11 } from "path";
2844
- import { Command as Command22 } from "commander";
3004
+ import { dirname as dirname2, join as join8, resolve as resolve12 } from "path";
3005
+ import { Command as Command23 } from "commander";
2845
3006
  var HOTSPOT_THRESHOLD = 7;
2846
3007
  var DEFAULT_LOOKBACK = "7d";
2847
3008
  async function runCompoundScanCandidatesCommand(opts) {
@@ -2896,7 +3057,7 @@ function emit(status, nonInteractive) {
2896
3057
  return status;
2897
3058
  }
2898
3059
  function createScanCandidatesCommand() {
2899
- return new Command22("scan-candidates").description(
3060
+ return new Command23("scan-candidates").description(
2900
3061
  "Scan recent fixes and hotspots for undocumented learnings; write candidate prompts"
2901
3062
  ).option("--lookback <window>", "Lookback window (e.g. 7d, 14d).", DEFAULT_LOOKBACK).option(
2902
3063
  "--non-interactive",
@@ -2909,9 +3070,9 @@ function createScanCandidatesCommand() {
2909
3070
  const nonInteractive = options.nonInteractive === true || !process.stdout.isTTY;
2910
3071
  const status = await runCompoundScanCandidatesCommand({
2911
3072
  lookback: options.lookback,
2912
- configPath: resolve11(process.cwd(), options.config),
2913
- outputPath: options.outputPath ? resolve11(process.cwd(), options.outputPath) : void 0,
2914
- solutionsDir: resolve11(process.cwd(), options.solutionsDir),
3073
+ configPath: resolve12(process.cwd(), options.config),
3074
+ outputPath: options.outputPath ? resolve12(process.cwd(), options.outputPath) : void 0,
3075
+ solutionsDir: resolve12(process.cwd(), options.solutionsDir),
2915
3076
  nonInteractive
2916
3077
  });
2917
3078
  if (status.status === "failure") process.exitCode = 1;
@@ -2921,15 +3082,15 @@ function createScanCandidatesCommand() {
2921
3082
 
2922
3083
  // src/commands/compound/index.ts
2923
3084
  function createCompoundCommand() {
2924
- const command = new Command23("compound").description("Compound (post-mortem playbook) commands");
3085
+ const command = new Command24("compound").description("Compound (post-mortem playbook) commands");
2925
3086
  command.addCommand(createScanCandidatesCommand());
2926
3087
  return command;
2927
3088
  }
2928
3089
 
2929
3090
  // src/commands/copy-craft.ts
2930
- import { Command as Command24 } from "commander";
3091
+ import { Command as Command25 } from "commander";
2931
3092
  function createCopyCraftCommand() {
2932
- return new Command24("copy-craft").description(
3093
+ return new Command25("copy-craft").description(
2933
3094
  "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."
2934
3095
  ).option("-f, --files <files...>", "Optional source file/glob scope").option(
2935
3096
  "-s, --surfaces <surfaces...>",
@@ -2981,10 +3142,10 @@ function printResult2(result, mode, _formatter) {
2981
3142
  list.push(f);
2982
3143
  bySurface.set(f.target.surface, list);
2983
3144
  }
2984
- for (const [surface, fs48] of bySurface) {
3145
+ for (const [surface, fs49] of bySurface) {
2985
3146
  console.log(`
2986
3147
  [${surface}]`);
2987
- for (const f of fs48) {
3148
+ for (const f of fs49) {
2988
3149
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
2989
3150
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.file}${line}`);
2990
3151
  console.log(` "${truncate(f.target.snippet, 80)}"`);
@@ -3010,11 +3171,11 @@ function truncate(s, n) {
3010
3171
  }
3011
3172
 
3012
3173
  // src/commands/dashboard.ts
3013
- import { Command as Command25 } from "commander";
3174
+ import { Command as Command26 } from "commander";
3014
3175
  import { spawn } from "child_process";
3015
3176
  import { existsSync as existsSync5 } from "fs";
3016
3177
  import { createRequire } from "module";
3017
- import { dirname as dirname3, join as join9, resolve as resolve12 } from "path";
3178
+ import { dirname as dirname3, join as join9, resolve as resolve13 } from "path";
3018
3179
  import { setTimeout } from "timers";
3019
3180
  import { fileURLToPath } from "url";
3020
3181
  var __filename = fileURLToPath(import.meta.url);
@@ -3078,7 +3239,7 @@ function buildDashboardEnv(opts, clientPort, apiPort, projectPath) {
3078
3239
  function runDashboard(opts) {
3079
3240
  const clientPort = Number(opts.port ?? DEFAULT_CLIENT_PORT);
3080
3241
  const apiPort = Number(opts.apiPort ?? DEFAULT_API_PORT);
3081
- const projectPath = resolve12(opts.cwd ?? process.cwd());
3242
+ const projectPath = resolve13(opts.cwd ?? process.cwd());
3082
3243
  const url = `http://localhost:${apiPort}`;
3083
3244
  const server = resolveServerScript();
3084
3245
  if (!server) {
@@ -3094,13 +3255,13 @@ function runDashboard(opts) {
3094
3255
  }
3095
3256
  }
3096
3257
  function createDashboardCommand() {
3097
- 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));
3258
+ return new Command26("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));
3098
3259
  }
3099
3260
 
3100
3261
  // src/commands/design-pipeline.ts
3101
- import { Command as Command26 } from "commander";
3262
+ import { Command as Command27 } from "commander";
3102
3263
  function createDesignPipelineCommand() {
3103
- return new Command26("design-pipeline").description(
3264
+ return new Command27("design-pipeline").description(
3104
3265
  "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."
3105
3266
  ).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(
3106
3267
  "--design-strictness <level>",
@@ -3186,10 +3347,10 @@ function verdictBadge(verdict) {
3186
3347
  }
3187
3348
 
3188
3349
  // src/commands/doctor.ts
3189
- import { Command as Command27 } from "commander";
3350
+ import { Command as Command28 } from "commander";
3190
3351
  import * as fs8 from "fs";
3191
3352
  import * as os from "os";
3192
- import * as path14 from "path";
3353
+ import * as path15 from "path";
3193
3354
  import chalk from "chalk";
3194
3355
 
3195
3356
  // src/utils/node-version.ts
@@ -3273,7 +3434,7 @@ var INTEGRATION_REGISTRY = [
3273
3434
 
3274
3435
  // src/integrations/config.ts
3275
3436
  import * as fs7 from "fs";
3276
- import * as path13 from "path";
3437
+ import * as path14 from "path";
3277
3438
  function readJsonSafe(filePath) {
3278
3439
  if (!fs7.existsSync(filePath)) return null;
3279
3440
  try {
@@ -3283,7 +3444,7 @@ function readJsonSafe(filePath) {
3283
3444
  }
3284
3445
  }
3285
3446
  function writeJson(filePath, data) {
3286
- const dir = path13.dirname(filePath);
3447
+ const dir = path14.dirname(filePath);
3287
3448
  if (!fs7.existsSync(dir)) {
3288
3449
  fs7.mkdirSync(dir, { recursive: true });
3289
3450
  }
@@ -3367,13 +3528,13 @@ function checkSlashCommands() {
3367
3528
  const platforms = [
3368
3529
  {
3369
3530
  name: "Claude Code",
3370
- dir: path14.join(os.homedir(), ".claude", "commands", "harness"),
3531
+ dir: path15.join(os.homedir(), ".claude", "commands", "harness"),
3371
3532
  ext: ".md",
3372
3533
  client: "claude-code"
3373
3534
  },
3374
3535
  {
3375
3536
  name: "Gemini CLI",
3376
- dir: path14.join(os.homedir(), ".gemini", "commands", "harness"),
3537
+ dir: path15.join(os.homedir(), ".gemini", "commands", "harness"),
3377
3538
  ext: ".toml",
3378
3539
  client: "gemini-cli"
3379
3540
  }
@@ -3397,7 +3558,7 @@ function checkSlashCommands() {
3397
3558
  }
3398
3559
  function checkMcpConfig(cwd) {
3399
3560
  const results = [];
3400
- const claudeConfig = readMcpConfig(path14.join(cwd, ".mcp.json"));
3561
+ const claudeConfig = readMcpConfig(path15.join(cwd, ".mcp.json"));
3401
3562
  if (claudeConfig.mcpServers?.["harness"]) {
3402
3563
  results.push({
3403
3564
  name: "mcp-claude",
@@ -3412,9 +3573,9 @@ function checkMcpConfig(cwd) {
3412
3573
  fix: "Run: harness setup-mcp --client claude"
3413
3574
  });
3414
3575
  }
3415
- const geminiDir = path14.join(cwd, ".gemini");
3576
+ const geminiDir = path15.join(cwd, ".gemini");
3416
3577
  if (fs8.existsSync(geminiDir)) {
3417
- const geminiConfig = readMcpConfig(path14.join(geminiDir, "settings.json"));
3578
+ const geminiConfig = readMcpConfig(path15.join(geminiDir, "settings.json"));
3418
3579
  if (geminiConfig.mcpServers?.["harness"]) {
3419
3580
  results.push({
3420
3581
  name: "mcp-gemini",
@@ -3433,12 +3594,12 @@ function checkMcpConfig(cwd) {
3433
3594
  return results;
3434
3595
  }
3435
3596
  function loadMcpPresence(cwd) {
3436
- const mcpPath = path14.join(cwd, ".mcp.json");
3437
- const geminiDir = path14.join(cwd, ".gemini");
3597
+ const mcpPath = path15.join(cwd, ".mcp.json");
3598
+ const geminiDir = path15.join(cwd, ".gemini");
3438
3599
  const hasGemini = fs8.existsSync(geminiDir);
3439
3600
  return {
3440
3601
  mcpConfig: readMcpConfig(mcpPath),
3441
- geminiConfig: hasGemini ? readMcpConfig(path14.join(geminiDir, "settings.json")) : null,
3602
+ geminiConfig: hasGemini ? readMcpConfig(path15.join(geminiDir, "settings.json")) : null,
3442
3603
  hasGemini
3443
3604
  };
3444
3605
  }
@@ -3470,7 +3631,7 @@ function checkTier0Presence(def, presence) {
3470
3631
  function checkIntegrations(cwd) {
3471
3632
  const results = [];
3472
3633
  const presence = loadMcpPresence(cwd);
3473
- const configPath = path14.join(cwd, "harness.config.json");
3634
+ const configPath = path15.join(cwd, "harness.config.json");
3474
3635
  const integrationsConfig = readIntegrationsConfig(configPath);
3475
3636
  for (const def of INTEGRATION_REGISTRY.filter((d) => d.tier === 0)) {
3476
3637
  results.push(checkTier0Presence(def, presence));
@@ -3538,12 +3699,12 @@ function checkLivePings(env = process.env) {
3538
3699
  return results;
3539
3700
  }
3540
3701
  function listHookFiles(cwd) {
3541
- const hooksDir = path14.join(cwd, ".harness", "hooks");
3702
+ const hooksDir = path15.join(cwd, ".harness", "hooks");
3542
3703
  if (!fs8.existsSync(hooksDir)) return [];
3543
3704
  try {
3544
3705
  return fs8.readdirSync(hooksDir).filter((f) => !f.startsWith(".")).map((f) => ({
3545
- relativePath: path14.join(".harness", "hooks", f),
3546
- absolutePath: path14.join(hooksDir, f)
3706
+ relativePath: path15.join(".harness", "hooks", f),
3707
+ absolutePath: path15.join(hooksDir, f)
3547
3708
  }));
3548
3709
  } catch {
3549
3710
  return [];
@@ -3640,7 +3801,7 @@ var DAY_MS = 24 * 60 * 60 * 1e3;
3640
3801
  function checkBaselineFreshness(cwd, now = Date.now()) {
3641
3802
  const results = [];
3642
3803
  for (const def of BASELINE_FILES) {
3643
- const absolutePath = path14.join(cwd, def.relativePath);
3804
+ const absolutePath = path15.join(cwd, def.relativePath);
3644
3805
  if (!fs8.existsSync(absolutePath)) {
3645
3806
  results.push({
3646
3807
  name: `baseline-freshness-${def.relativePath}`,
@@ -3688,7 +3849,7 @@ function checkBaselineFreshness(cwd, now = Date.now()) {
3688
3849
  }
3689
3850
  var SESSIONS_SAMPLE_SIZE = 5;
3690
3851
  function listRecentSessions(cwd) {
3691
- const sessionsDir = path14.join(cwd, ".harness", "sessions");
3852
+ const sessionsDir = path15.join(cwd, ".harness", "sessions");
3692
3853
  if (!fs8.existsSync(sessionsDir)) return [];
3693
3854
  let entries;
3694
3855
  try {
@@ -3699,7 +3860,7 @@ function listRecentSessions(cwd) {
3699
3860
  const dirs = [];
3700
3861
  for (const name of entries) {
3701
3862
  if (name.startsWith(".")) continue;
3702
- const absolutePath = path14.join(sessionsDir, name);
3863
+ const absolutePath = path15.join(sessionsDir, name);
3703
3864
  try {
3704
3865
  const stat = fs8.statSync(absolutePath);
3705
3866
  if (!stat.isDirectory()) continue;
@@ -3716,7 +3877,7 @@ function scanSessionSummaries(sessions) {
3716
3877
  let missing = 0;
3717
3878
  const corrupt = [];
3718
3879
  for (const session of sessions) {
3719
- const summaryPath = path14.join(session.absolutePath, "session-summary.json");
3880
+ const summaryPath = path15.join(session.absolutePath, "session-summary.json");
3720
3881
  if (!fs8.existsSync(summaryPath)) {
3721
3882
  missing += 1;
3722
3883
  continue;
@@ -3790,7 +3951,7 @@ function formatCheck(check) {
3790
3951
  return line;
3791
3952
  }
3792
3953
  function createDoctorCommand() {
3793
- return new Command27("doctor").description(
3954
+ return new Command28("doctor").description(
3794
3955
  "Check environment health: Node, slash commands, MCP, integrations, integration credentials, hooks, baselines, sessions"
3795
3956
  ).action((_opts, cmd) => {
3796
3957
  const globalOpts = cmd.optsWithGlobals();
@@ -3818,8 +3979,8 @@ function createDoctorCommand() {
3818
3979
 
3819
3980
  // src/commands/fix-drift.ts
3820
3981
  init_dist3();
3821
- import { Command as Command28 } from "commander";
3822
- import * as path15 from "path";
3982
+ import { Command as Command29 } from "commander";
3983
+ import * as path16 from "path";
3823
3984
  async function runFixDrift(options) {
3824
3985
  const cwd = options.cwd ?? process.cwd();
3825
3986
  const dryRun = options.dryRun !== false;
@@ -3828,12 +3989,12 @@ async function runFixDrift(options) {
3828
3989
  return Err(configResult.error);
3829
3990
  }
3830
3991
  const config = configResult.value;
3831
- const rootDir = path15.resolve(cwd, config.rootDir);
3832
- const docsDir = path15.resolve(cwd, config.docsDir);
3992
+ const rootDir = path16.resolve(cwd, config.rootDir);
3993
+ const docsDir = path16.resolve(cwd, config.docsDir);
3833
3994
  const entropyConfig = {
3834
3995
  rootDir,
3835
3996
  ...config.entropy?.entryPoints && { entryPoints: config.entropy.entryPoints },
3836
- docPaths: [path15.join(docsDir, "**/*.md")],
3997
+ docPaths: [path16.join(docsDir, "**/*.md")],
3837
3998
  analyze: {
3838
3999
  drift: true,
3839
4000
  deadCode: true,
@@ -3951,7 +4112,7 @@ function printFixDriftResult(value, mode, formatter) {
3951
4112
  }
3952
4113
  }
3953
4114
  function createFixDriftCommand() {
3954
- 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) => {
4115
+ const command = new Command29("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) => {
3955
4116
  const globalOpts = cmd.optsWithGlobals();
3956
4117
  const mode = resolveOutputMode(globalOpts);
3957
4118
  const formatter = new OutputFormatter(mode);
@@ -3981,14 +4142,14 @@ function createFixDriftCommand() {
3981
4142
  }
3982
4143
 
3983
4144
  // src/commands/gateway/index.ts
3984
- import { Command as Command31 } from "commander";
4145
+ import { Command as Command32 } from "commander";
3985
4146
 
3986
4147
  // src/commands/gateway/token.ts
3987
- import { Command as Command29 } from "commander";
3988
- import { resolve as resolve14 } from "path";
4148
+ import { Command as Command30 } from "commander";
4149
+ import { resolve as resolve15 } from "path";
3989
4150
  import { TokenStore } from "@harness-engineering/orchestrator";
3990
4151
  function getStore() {
3991
- const p = process.env["HARNESS_TOKENS_PATH"] ?? resolve14(".harness", "tokens.json");
4152
+ const p = process.env["HARNESS_TOKENS_PATH"] ?? resolve15(".harness", "tokens.json");
3992
4153
  return new TokenStore(p);
3993
4154
  }
3994
4155
  async function runTokenCreate(opts) {
@@ -4005,7 +4166,7 @@ async function runTokenRevoke(id) {
4005
4166
  return store.revoke(id);
4006
4167
  }
4007
4168
  function createTokenCommand() {
4008
- const cmd = new Command29("token").description("Manage Gateway API tokens");
4169
+ const cmd = new Command30("token").description("Manage Gateway API tokens");
4009
4170
  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(
4010
4171
  async (opts) => {
4011
4172
  const scopes = opts.scopes.split(",").map((s) => s.trim());
@@ -4034,12 +4195,12 @@ function createTokenCommand() {
4034
4195
  }
4035
4196
 
4036
4197
  // src/commands/gateway/deliveries.ts
4037
- import { Command as Command30 } from "commander";
4198
+ import { Command as Command31 } from "commander";
4038
4199
  import { createInterface } from "readline";
4039
- import { resolve as resolve15 } from "path";
4200
+ import { resolve as resolve16 } from "path";
4040
4201
  import { WebhookQueue } from "@harness-engineering/orchestrator";
4041
4202
  function resolveQueuePath() {
4042
- return process.env["HARNESS_WEBHOOK_QUEUE_PATH"] ?? resolve15(".harness", "webhook-queue.sqlite");
4203
+ return process.env["HARNESS_WEBHOOK_QUEUE_PATH"] ?? resolve16(".harness", "webhook-queue.sqlite");
4043
4204
  }
4044
4205
  function getQueue() {
4045
4206
  return new WebhookQueue(resolveQueuePath());
@@ -4074,7 +4235,7 @@ function promptYesNo(message) {
4074
4235
  });
4075
4236
  }
4076
4237
  function createDeliveriesCommand() {
4077
- const cmd = new Command30("deliveries").description("Inspect and manage webhook delivery queue");
4238
+ const cmd = new Command31("deliveries").description("Inspect and manage webhook delivery queue");
4078
4239
  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) => {
4079
4240
  const queue = getQueue();
4080
4241
  try {
@@ -4134,14 +4295,14 @@ function createDeliveriesCommand() {
4134
4295
 
4135
4296
  // src/commands/gateway/index.ts
4136
4297
  function createGatewayCommand() {
4137
- const cmd = new Command31("gateway").description("Gateway API administration");
4298
+ const cmd = new Command32("gateway").description("Gateway API administration");
4138
4299
  cmd.addCommand(createTokenCommand());
4139
4300
  cmd.addCommand(createDeliveriesCommand());
4140
4301
  return cmd;
4141
4302
  }
4142
4303
 
4143
4304
  // src/commands/generate.ts
4144
- import { Command as Command32 } from "commander";
4305
+ import { Command as Command33 } from "commander";
4145
4306
  function validatePlatforms(platforms) {
4146
4307
  for (const p of platforms) {
4147
4308
  if (!VALID_PLATFORMS.includes(p)) {
@@ -4201,22 +4362,22 @@ async function runGenerateAction(opts, globalOpts) {
4201
4362
  }
4202
4363
  }
4203
4364
  function createGenerateCommand() {
4204
- 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) => {
4365
+ return new Command33("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) => {
4205
4366
  await runGenerateAction(opts, cmd.optsWithGlobals());
4206
4367
  });
4207
4368
  }
4208
4369
 
4209
4370
  // src/commands/graph/index.ts
4210
- import { Command as Command35 } from "commander";
4371
+ import { Command as Command36 } from "commander";
4211
4372
 
4212
4373
  // src/commands/graph/status.ts
4213
- import * as path16 from "path";
4374
+ import * as path17 from "path";
4214
4375
  async function readConnectorSyncStatus(graphDir) {
4215
- const fs48 = await import("fs/promises");
4376
+ const fs49 = await import("fs/promises");
4216
4377
  const result = {};
4217
4378
  try {
4218
- const syncMetaPath = path16.join(graphDir, "sync-metadata.json");
4219
- const syncMeta = JSON.parse(await fs48.readFile(syncMetaPath, "utf-8"));
4379
+ const syncMetaPath = path17.join(graphDir, "sync-metadata.json");
4380
+ const syncMeta = JSON.parse(await fs49.readFile(syncMetaPath, "utf-8"));
4220
4381
  for (const [name, data] of Object.entries(syncMeta.connectors ?? {})) {
4221
4382
  result[name] = data.lastSyncTimestamp;
4222
4383
  }
@@ -4225,8 +4386,8 @@ async function readConnectorSyncStatus(graphDir) {
4225
4386
  return result;
4226
4387
  }
4227
4388
  async function runGraphStatus(projectPath) {
4228
- const { GraphStore: GraphStore2, loadGraphMetadata } = await import("./dist-R3TOOPJ7.js");
4229
- const graphDir = path16.join(projectPath, ".harness", "graph");
4389
+ const { GraphStore: GraphStore2, loadGraphMetadata } = await import("./dist-OWHMNL4W.js");
4390
+ const graphDir = path17.join(projectPath, ".harness", "graph");
4230
4391
  const metaResult = await loadGraphMetadata(graphDir);
4231
4392
  if (metaResult.status === "not_found") {
4232
4393
  return { status: "no_graph", message: "No graph found. Run `harness scan` first." };
@@ -4275,10 +4436,10 @@ async function runGraphStatus(projectPath) {
4275
4436
  }
4276
4437
 
4277
4438
  // src/commands/graph/export.ts
4278
- import * as path17 from "path";
4439
+ import * as path18 from "path";
4279
4440
  async function runGraphExport(projectPath, format) {
4280
- const { GraphStore: GraphStore2 } = await import("./dist-R3TOOPJ7.js");
4281
- const graphDir = path17.join(projectPath, ".harness", "graph");
4441
+ const { GraphStore: GraphStore2 } = await import("./dist-OWHMNL4W.js");
4442
+ const graphDir = path18.join(projectPath, ".harness", "graph");
4282
4443
  const store = new GraphStore2();
4283
4444
  const loaded = await store.load(graphDir);
4284
4445
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
@@ -4307,15 +4468,15 @@ async function runGraphExport(projectPath, format) {
4307
4468
  }
4308
4469
 
4309
4470
  // src/commands/graph/index.ts
4310
- import * as path20 from "path";
4471
+ import * as path21 from "path";
4311
4472
 
4312
4473
  // src/commands/graph/query.ts
4313
- import { Command as Command33 } from "commander";
4314
- import * as path18 from "path";
4474
+ import { Command as Command34 } from "commander";
4475
+ import * as path19 from "path";
4315
4476
  async function runQuery(projectPath, rootNodeId, opts) {
4316
- const { GraphStore: GraphStore2, ContextQL } = await import("./dist-R3TOOPJ7.js");
4477
+ const { GraphStore: GraphStore2, ContextQL } = await import("./dist-OWHMNL4W.js");
4317
4478
  const store = new GraphStore2();
4318
- const graphDir = path18.join(projectPath, ".harness", "graph");
4479
+ const graphDir = path19.join(projectPath, ".harness", "graph");
4319
4480
  const loaded = await store.load(graphDir);
4320
4481
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
4321
4482
  const params = {
@@ -4337,7 +4498,7 @@ function printQueryResult(result) {
4337
4498
  }
4338
4499
  }
4339
4500
  async function runQueryAction(rootNodeId, opts, globalOpts) {
4340
- const projectPath = path18.resolve(globalOpts.config ? path18.dirname(globalOpts.config) : ".");
4501
+ const projectPath = path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
4341
4502
  try {
4342
4503
  const result = await runQuery(projectPath, rootNodeId, {
4343
4504
  depth: parseInt(opts.depth),
@@ -4356,25 +4517,32 @@ async function runQueryAction(rootNodeId, opts, globalOpts) {
4356
4517
  }
4357
4518
  }
4358
4519
  function createQueryCommand() {
4359
- 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) => {
4520
+ return new Command34("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) => {
4360
4521
  await runQueryAction(rootNodeId, opts, cmd.optsWithGlobals());
4361
4522
  });
4362
4523
  }
4363
4524
 
4364
4525
  // src/commands/graph/ingest.ts
4365
- import { Command as Command34 } from "commander";
4366
- import * as path19 from "path";
4526
+ import { Command as Command35 } from "commander";
4527
+ import * as path20 from "path";
4367
4528
  async function loadConnectorConfig(projectPath, source) {
4368
4529
  try {
4369
- const fs48 = await import("fs/promises");
4370
- const configPath = path19.join(projectPath, "harness.config.json");
4371
- const config = JSON.parse(await fs48.readFile(configPath, "utf-8"));
4530
+ const fs49 = await import("fs/promises");
4531
+ const configPath = path20.join(projectPath, "harness.config.json");
4532
+ const config = JSON.parse(await fs49.readFile(configPath, "utf-8"));
4372
4533
  const connector = config.graph?.connectors?.[source];
4373
4534
  return connector ?? {};
4374
4535
  } catch {
4375
4536
  return {};
4376
4537
  }
4377
4538
  }
4539
+ async function ingestBusinessKnowledge(bk, projectPath) {
4540
+ return mergeResults(
4541
+ await bk.ingest(path20.join(projectPath, "docs", "knowledge")),
4542
+ await bk.ingestSolutions(path20.join(projectPath, "docs", "solutions")),
4543
+ await bk.ingestStrategy(path20.join(projectPath, "STRATEGY.md"))
4544
+ );
4545
+ }
4378
4546
  function mergeResults(...results) {
4379
4547
  return results.reduce(
4380
4548
  (acc, r) => ({
@@ -4401,6 +4569,7 @@ async function runIngest(projectPath, source, opts) {
4401
4569
  CodeIngestor,
4402
4570
  TopologicalLinker,
4403
4571
  KnowledgeIngestor,
4572
+ BusinessKnowledgeIngestor,
4404
4573
  GitIngestor,
4405
4574
  RequirementIngestor,
4406
4575
  SyncManager,
@@ -4410,8 +4579,8 @@ async function runIngest(projectPath, source, opts) {
4410
4579
  ConfluenceConnector,
4411
4580
  FigmaConnector,
4412
4581
  MiroConnector
4413
- } = await import("./dist-R3TOOPJ7.js");
4414
- const graphDir = path19.join(projectPath, ".harness", "graph");
4582
+ } = await import("./dist-OWHMNL4W.js");
4583
+ const graphDir = path20.join(projectPath, ".harness", "graph");
4415
4584
  const store = new GraphStore2();
4416
4585
  await store.load(graphDir);
4417
4586
  const ingestOptions = loadIngestOptions(projectPath);
@@ -4420,12 +4589,14 @@ async function runIngest(projectPath, source, opts) {
4420
4589
  const codeResult = await new CodeIngestor(store, ingestOptions).ingest(projectPath);
4421
4590
  new TopologicalLinker(store).link();
4422
4591
  const knowledgeResult = await new KnowledgeIngestor(store).ingestAll(projectPath);
4592
+ const bkInst = new BusinessKnowledgeIngestor(store);
4593
+ const bkResult = await ingestBusinessKnowledge(bkInst, projectPath);
4423
4594
  const reqResult = await new RequirementIngestor(store).ingestSpecs(
4424
- path19.join(projectPath, "docs", "changes")
4595
+ path20.join(projectPath, "docs", "changes")
4425
4596
  );
4426
4597
  const gitResult = await new GitIngestor(store).ingest(projectPath);
4427
- const { createExtractionRunner } = await import("./dist-R3TOOPJ7.js");
4428
- const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
4598
+ const { createExtractionRunner } = await import("./dist-OWHMNL4W.js");
4599
+ const extractedDir = path20.join(projectPath, ".harness", "knowledge", "extracted");
4429
4600
  const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
4430
4601
  const syncManager = new SyncManager(store, graphDir);
4431
4602
  const connectorMap = {
@@ -4445,6 +4616,7 @@ async function runIngest(projectPath, source, opts) {
4445
4616
  const merged = mergeResults(
4446
4617
  codeResult,
4447
4618
  knowledgeResult,
4619
+ bkResult,
4448
4620
  reqResult,
4449
4621
  gitResult,
4450
4622
  signalsResult,
@@ -4458,20 +4630,23 @@ async function runIngest(projectPath, source, opts) {
4458
4630
  result = await new CodeIngestor(store, ingestOptions).ingest(projectPath);
4459
4631
  new TopologicalLinker(store).link();
4460
4632
  break;
4461
- case "knowledge":
4462
- result = await new KnowledgeIngestor(store).ingestAll(projectPath);
4633
+ case "knowledge": {
4634
+ const knowledge = await new KnowledgeIngestor(store).ingestAll(projectPath);
4635
+ const bk = await ingestBusinessKnowledge(new BusinessKnowledgeIngestor(store), projectPath);
4636
+ result = mergeResults(knowledge, bk);
4463
4637
  break;
4638
+ }
4464
4639
  case "git":
4465
4640
  result = await new GitIngestor(store).ingest(projectPath);
4466
4641
  break;
4467
4642
  case "requirements":
4468
4643
  result = await new RequirementIngestor(store).ingestSpecs(
4469
- path19.join(projectPath, "docs", "changes")
4644
+ path20.join(projectPath, "docs", "changes")
4470
4645
  );
4471
4646
  break;
4472
4647
  case "business-signals": {
4473
- const { createExtractionRunner } = await import("./dist-R3TOOPJ7.js");
4474
- const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
4648
+ const { createExtractionRunner } = await import("./dist-OWHMNL4W.js");
4649
+ const extractedDir = path20.join(projectPath, ".harness", "knowledge", "extracted");
4475
4650
  result = await createExtractionRunner().run(projectPath, store, extractedDir);
4476
4651
  break;
4477
4652
  }
@@ -4506,40 +4681,46 @@ async function runIngest(projectPath, source, opts) {
4506
4681
  await store.save(graphDir);
4507
4682
  return result;
4508
4683
  }
4684
+ function printIngestSummary(result, label) {
4685
+ console.log(
4686
+ `Ingested (${label}): +${result.nodesAdded} nodes, +${result.edgesAdded} edges (${result.durationMs}ms)`
4687
+ );
4688
+ if (result.errors.length === 0) return;
4689
+ console.warn(` ${result.errors.length} parse/skip warning(s):`);
4690
+ for (const err of result.errors) console.warn(` - ${err}`);
4691
+ }
4692
+ async function handleIngestAction(opts, cmd) {
4693
+ if (!opts.source && !opts.all) {
4694
+ console.error("Error: --source or --all is required");
4695
+ process.exit(1);
4696
+ }
4697
+ const globalOpts = cmd.optsWithGlobals();
4698
+ const projectPath = path20.resolve(globalOpts.config ? path20.dirname(globalOpts.config) : ".");
4699
+ try {
4700
+ const runOpts = {};
4701
+ if (opts.full !== void 0) runOpts.full = opts.full;
4702
+ if (opts.all !== void 0) runOpts.all = opts.all;
4703
+ const result = await runIngest(projectPath, opts.source ?? "", runOpts);
4704
+ if (globalOpts.json) {
4705
+ console.log(JSON.stringify(result));
4706
+ } else {
4707
+ printIngestSummary(result, opts.all ? "all" : opts.source ?? "");
4708
+ }
4709
+ } catch (err) {
4710
+ console.error("Ingest failed:", err instanceof Error ? err.message : err);
4711
+ process.exit(2);
4712
+ }
4713
+ }
4509
4714
  function createIngestCommand() {
4510
- return new Command34("ingest").description("Ingest data into the knowledge graph").option(
4715
+ return new Command35("ingest").description("Ingest data into the knowledge graph").option(
4511
4716
  "--source <name>",
4512
4717
  "Source to ingest (code, knowledge, git, requirements, business-signals, jira, slack, ci, confluence, figma, miro)"
4513
- ).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(async (opts, cmd) => {
4514
- if (!opts.source && !opts.all) {
4515
- console.error("Error: --source or --all is required");
4516
- process.exit(1);
4517
- }
4518
- const globalOpts = cmd.optsWithGlobals();
4519
- const projectPath = path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
4520
- try {
4521
- const result = await runIngest(projectPath, opts.source ?? "", {
4522
- full: opts.full,
4523
- all: opts.all
4524
- });
4525
- if (globalOpts.json) {
4526
- console.log(JSON.stringify(result));
4527
- } else {
4528
- const label = opts.all ? "all" : opts.source;
4529
- console.log(
4530
- `Ingested (${label}): +${result.nodesAdded} nodes, +${result.edgesAdded} edges (${result.durationMs}ms)`
4531
- );
4532
- }
4533
- } catch (err) {
4534
- console.error("Ingest failed:", err instanceof Error ? err.message : err);
4535
- process.exit(2);
4536
- }
4537
- });
4718
+ ).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(handleIngestAction);
4538
4719
  }
4539
4720
 
4540
4721
  // src/commands/graph/index.ts
4541
4722
  function resolveProjectPath(globalOpts) {
4542
- return path20.resolve(globalOpts.config ? path20.dirname(globalOpts.config) : ".");
4723
+ return path21.resolve(globalOpts.config ? path21.dirname(globalOpts.config) : ".");
4543
4724
  }
4544
4725
  function printGraphStatus(result) {
4545
4726
  if (result.status === "no_graph" || result.status === "schema_mismatch") {
@@ -4585,19 +4766,19 @@ async function runExportAction(opts, cmd) {
4585
4766
  }
4586
4767
  }
4587
4768
  function createGraphCommand() {
4588
- const graph = new Command35("graph").description("Knowledge graph management");
4769
+ const graph = new Command36("graph").description("Knowledge graph management");
4589
4770
  graph.command("status").description("Show graph statistics").action(runStatusAction);
4590
4771
  graph.command("export").description("Export graph").requiredOption("--format <format>", "Output format (json, mermaid)").action(runExportAction);
4591
4772
  return graph;
4592
4773
  }
4593
4774
 
4594
4775
  // src/commands/hooks/index.ts
4595
- import { Command as Command40 } from "commander";
4776
+ import { Command as Command41 } from "commander";
4596
4777
 
4597
4778
  // src/commands/hooks/init.ts
4598
- import { Command as Command36 } from "commander";
4779
+ import { Command as Command37 } from "commander";
4599
4780
  import * as fs9 from "fs";
4600
- import * as path21 from "path";
4781
+ import * as path22 from "path";
4601
4782
  import { fileURLToPath as fileURLToPath2 } from "url";
4602
4783
 
4603
4784
  // src/hooks/profiles.ts
@@ -4627,14 +4808,14 @@ var PROFILES = {
4627
4808
 
4628
4809
  // src/commands/hooks/init.ts
4629
4810
  var __filename2 = fileURLToPath2(import.meta.url);
4630
- var __dirname2 = path21.dirname(__filename2);
4811
+ var __dirname2 = path22.dirname(__filename2);
4631
4812
  var VALID_PROFILES = ["minimal", "standard", "strict"];
4632
4813
  function resolveHookSourceDir() {
4633
4814
  const candidates = [
4634
4815
  // Dev layout: src/commands/hooks/ → ../../hooks/
4635
- path21.resolve(__dirname2, "..", "..", "hooks"),
4816
+ path22.resolve(__dirname2, "..", "..", "hooks"),
4636
4817
  // Bundled layout: dist/ → ./hooks/ (copied by copy-assets.mjs)
4637
- path21.resolve(__dirname2, "hooks")
4818
+ path22.resolve(__dirname2, "hooks")
4638
4819
  ];
4639
4820
  for (const candidate of candidates) {
4640
4821
  if (fs9.existsSync(candidate)) {
@@ -4674,12 +4855,12 @@ function mergeSettings(existing, hooksConfig) {
4674
4855
  }
4675
4856
  function initHooks(options) {
4676
4857
  const { profile, projectDir } = options;
4677
- const hooksDestDir = path21.join(projectDir, ".harness", "hooks");
4858
+ const hooksDestDir = path22.join(projectDir, ".harness", "hooks");
4678
4859
  fs9.mkdirSync(hooksDestDir, { recursive: true });
4679
4860
  if (fs9.existsSync(hooksDestDir)) {
4680
4861
  for (const entry of fs9.readdirSync(hooksDestDir)) {
4681
4862
  if (entry.endsWith(".js")) {
4682
- fs9.unlinkSync(path21.join(hooksDestDir, entry));
4863
+ fs9.unlinkSync(path22.join(hooksDestDir, entry));
4683
4864
  }
4684
4865
  }
4685
4866
  }
@@ -4688,18 +4869,18 @@ function initHooks(options) {
4688
4869
  const activeNames = PROFILES[profile];
4689
4870
  const activeScripts = HOOK_SCRIPTS.filter((h) => activeNames.includes(h.name));
4690
4871
  for (const script of activeScripts) {
4691
- const srcFile = path21.join(sourceDir, `${script.name}.js`);
4692
- const destFile = path21.join(hooksDestDir, `${script.name}.js`);
4872
+ const srcFile = path22.join(sourceDir, `${script.name}.js`);
4873
+ const destFile = path22.join(hooksDestDir, `${script.name}.js`);
4693
4874
  if (fs9.existsSync(srcFile)) {
4694
4875
  fs9.copyFileSync(srcFile, destFile);
4695
4876
  copiedScripts.push(script.name);
4696
4877
  }
4697
4878
  }
4698
- const profilePath = path21.join(hooksDestDir, "profile.json");
4879
+ const profilePath = path22.join(hooksDestDir, "profile.json");
4699
4880
  fs9.writeFileSync(profilePath, JSON.stringify({ profile }, null, 2) + "\n");
4700
- const claudeDir = path21.join(projectDir, ".claude");
4881
+ const claudeDir = path22.join(projectDir, ".claude");
4701
4882
  fs9.mkdirSync(claudeDir, { recursive: true });
4702
- const settingsPath = path21.join(claudeDir, "settings.json");
4883
+ const settingsPath = path22.join(claudeDir, "settings.json");
4703
4884
  let existing = {};
4704
4885
  if (fs9.existsSync(settingsPath)) {
4705
4886
  try {
@@ -4717,7 +4898,7 @@ function initHooks(options) {
4717
4898
  return { copiedScripts, settingsPath, profilePath };
4718
4899
  }
4719
4900
  function createInitCommand2() {
4720
- 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) => {
4901
+ return new Command37("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) => {
4721
4902
  const globalOpts = cmd.optsWithGlobals();
4722
4903
  const profile = opts.profile;
4723
4904
  if (!VALID_PROFILES.includes(profile)) {
@@ -4742,7 +4923,7 @@ function createInitCommand2() {
4742
4923
  );
4743
4924
  logger.info(`Profile: ${profile}`);
4744
4925
  logger.info(
4745
- `Settings: ${path21.relative(projectDir, result.settingsPath).replaceAll("\\", "/")}`
4926
+ `Settings: ${path22.relative(projectDir, result.settingsPath).replaceAll("\\", "/")}`
4746
4927
  );
4747
4928
  logger.dim("Run 'harness hooks list' to see installed hooks");
4748
4929
  }
@@ -4755,12 +4936,12 @@ function createInitCommand2() {
4755
4936
  }
4756
4937
 
4757
4938
  // src/commands/hooks/list.ts
4758
- import { Command as Command37 } from "commander";
4939
+ import { Command as Command38 } from "commander";
4759
4940
  import * as fs10 from "fs";
4760
- import * as path22 from "path";
4941
+ import * as path23 from "path";
4761
4942
  function listHooks(projectDir) {
4762
- const hooksDir = path22.join(projectDir, ".harness", "hooks");
4763
- const profilePath = path22.join(hooksDir, "profile.json");
4943
+ const hooksDir = path23.join(projectDir, ".harness", "hooks");
4944
+ const profilePath = path23.join(hooksDir, "profile.json");
4764
4945
  if (!fs10.existsSync(profilePath)) {
4765
4946
  return { installed: false, profile: null, hooks: [] };
4766
4947
  }
@@ -4779,7 +4960,7 @@ function listHooks(projectDir) {
4779
4960
  name: h.name,
4780
4961
  event: h.event,
4781
4962
  matcher: h.matcher,
4782
- scriptPath: path22.join(".harness", "hooks", `${h.name}.js`)
4963
+ scriptPath: path23.join(".harness", "hooks", `${h.name}.js`)
4783
4964
  }));
4784
4965
  const result = { installed: true, profile, hooks };
4785
4966
  if (warning) {
@@ -4788,7 +4969,7 @@ function listHooks(projectDir) {
4788
4969
  return result;
4789
4970
  }
4790
4971
  function createListCommand() {
4791
- return new Command37("list").description("Show installed hooks and active profile").action(async (_opts, cmd) => {
4972
+ return new Command38("list").description("Show installed hooks and active profile").action(async (_opts, cmd) => {
4792
4973
  const globalOpts = cmd.optsWithGlobals();
4793
4974
  const projectDir = process.cwd();
4794
4975
  const result = listHooks(projectDir);
@@ -4809,12 +4990,12 @@ function createListCommand() {
4809
4990
  }
4810
4991
 
4811
4992
  // src/commands/hooks/remove.ts
4812
- import { Command as Command38 } from "commander";
4993
+ import { Command as Command39 } from "commander";
4813
4994
  import * as fs11 from "fs";
4814
- import * as path23 from "path";
4995
+ import * as path24 from "path";
4815
4996
  function removeHooks(projectDir) {
4816
- const hooksDir = path23.join(projectDir, ".harness", "hooks");
4817
- const settingsPath = path23.join(projectDir, ".claude", "settings.json");
4997
+ const hooksDir = path24.join(projectDir, ".harness", "hooks");
4998
+ const settingsPath = path24.join(projectDir, ".claude", "settings.json");
4818
4999
  let removed = false;
4819
5000
  let settingsCleaned = false;
4820
5001
  if (fs11.existsSync(hooksDir)) {
@@ -4839,7 +5020,7 @@ function removeHooks(projectDir) {
4839
5020
  return { removed, hooksDir, settingsCleaned };
4840
5021
  }
4841
5022
  function createRemoveCommand() {
4842
- return new Command38("remove").description("Remove harness-managed hooks from the current project").action(async (_opts, cmd) => {
5023
+ return new Command39("remove").description("Remove harness-managed hooks from the current project").action(async (_opts, cmd) => {
4843
5024
  const globalOpts = cmd.optsWithGlobals();
4844
5025
  const projectDir = process.cwd();
4845
5026
  const result = removeHooks(projectDir);
@@ -4861,16 +5042,16 @@ function createRemoveCommand() {
4861
5042
  }
4862
5043
 
4863
5044
  // src/commands/hooks/add.ts
4864
- import { Command as Command39 } from "commander";
5045
+ import { Command as Command40 } from "commander";
4865
5046
  import * as fs12 from "fs";
4866
- import * as path24 from "path";
5047
+ import * as path25 from "path";
4867
5048
  import { fileURLToPath as fileURLToPath3 } from "url";
4868
- var __dirname3 = path24.dirname(fileURLToPath3(import.meta.url));
5049
+ var __dirname3 = path25.dirname(fileURLToPath3(import.meta.url));
4869
5050
  var ALIASES = {
4870
5051
  sentinel: ["sentinel-pre", "sentinel-post"]
4871
5052
  };
4872
5053
  function hookSourceDir() {
4873
- const d = path24.resolve(__dirname3, "..", "..", "hooks");
5054
+ const d = path25.resolve(__dirname3, "..", "..", "hooks");
4874
5055
  if (fs12.existsSync(d)) return d;
4875
5056
  throw new Error(`Hook scripts not found: ${d}`);
4876
5057
  }
@@ -4888,11 +5069,11 @@ function addHooks(hookName, projectDir) {
4888
5069
  const names = ALIASES[hookName] ?? [hookName];
4889
5070
  const result = { added: [], alreadyInstalled: [], notFound: [] };
4890
5071
  const srcDir = hookSourceDir();
4891
- const destDir = path24.join(projectDir, ".harness", "hooks");
5072
+ const destDir = path25.join(projectDir, ".harness", "hooks");
4892
5073
  fs12.mkdirSync(destDir, { recursive: true });
4893
- const claudeDir = path24.join(projectDir, ".claude");
5074
+ const claudeDir = path25.join(projectDir, ".claude");
4894
5075
  fs12.mkdirSync(claudeDir, { recursive: true });
4895
- const settingsPath = path24.join(claudeDir, "settings.json");
5076
+ const settingsPath = path25.join(claudeDir, "settings.json");
4896
5077
  const settings = readJson(settingsPath);
4897
5078
  if (!settings.hooks) settings.hooks = {};
4898
5079
  for (const name of names) {
@@ -4901,8 +5082,8 @@ function addHooks(hookName, projectDir) {
4901
5082
  result.notFound.push(name);
4902
5083
  continue;
4903
5084
  }
4904
- const src = path24.join(srcDir, `${name}.js`);
4905
- const dest = path24.join(destDir, `${name}.js`);
5085
+ const src = path25.join(srcDir, `${name}.js`);
5086
+ const dest = path25.join(destDir, `${name}.js`);
4906
5087
  if (fs12.existsSync(dest)) {
4907
5088
  result.alreadyInstalled.push(name);
4908
5089
  } else if (!fs12.existsSync(src)) {
@@ -4918,7 +5099,7 @@ function addHooks(hookName, projectDir) {
4918
5099
  return result;
4919
5100
  }
4920
5101
  function createAddCommand2() {
4921
- 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) => {
5102
+ return new Command40("add").argument("<hook-name>", "Hook name or alias (e.g., sentinel)").description("Add a hook without changing the profile").action(async (hookName, _opts, cmd) => {
4922
5103
  const projectDir = process.cwd();
4923
5104
  try {
4924
5105
  const res = addHooks(hookName, projectDir);
@@ -4943,7 +5124,7 @@ function createAddCommand2() {
4943
5124
 
4944
5125
  // src/commands/hooks/index.ts
4945
5126
  function createHooksCommand() {
4946
- const command = new Command40("hooks").description("Manage Claude Code hook configurations");
5127
+ const command = new Command41("hooks").description("Manage Claude Code hook configurations");
4947
5128
  command.addCommand(createInitCommand2());
4948
5129
  command.addCommand(createListCommand());
4949
5130
  command.addCommand(createRemoveCommand());
@@ -4952,9 +5133,9 @@ function createHooksCommand() {
4952
5133
  }
4953
5134
 
4954
5135
  // src/commands/impact-preview.ts
4955
- import { Command as Command41 } from "commander";
5136
+ import { Command as Command42 } from "commander";
4956
5137
  import { execSync as execSync4 } from "child_process";
4957
- import * as path25 from "path";
5138
+ import * as path26 from "path";
4958
5139
  import * as fs13 from "fs";
4959
5140
  function getStagedFiles(cwd) {
4960
5141
  try {
@@ -4969,7 +5150,7 @@ function getStagedFiles(cwd) {
4969
5150
  }
4970
5151
  function graphExists(projectPath) {
4971
5152
  try {
4972
- return fs13.existsSync(path25.join(projectPath, ".harness", "graph", "graph.json"));
5153
+ return fs13.existsSync(path26.join(projectPath, ".harness", "graph", "graph.json"));
4973
5154
  } catch {
4974
5155
  return false;
4975
5156
  }
@@ -4978,7 +5159,7 @@ function extractNodeName(id) {
4978
5159
  const parts = id.split(":");
4979
5160
  if (parts.length > 1) {
4980
5161
  const fullPath = parts.slice(1).join(":");
4981
- return path25.basename(fullPath);
5162
+ return path26.basename(fullPath);
4982
5163
  }
4983
5164
  return id;
4984
5165
  }
@@ -5133,7 +5314,7 @@ function formatImpactOutput(stagedFiles, acc, options) {
5133
5314
  return options.detailed ? formatDetailed(stagedFiles.length, merged, acc.aggregateCounts) : formatCompact(stagedFiles.length, merged, acc.aggregateCounts);
5134
5315
  }
5135
5316
  async function runImpactPreview(options) {
5136
- const projectPath = path25.resolve(options.path ?? process.cwd());
5317
+ const projectPath = path26.resolve(options.path ?? process.cwd());
5137
5318
  const stagedFiles = getStagedFiles(projectPath);
5138
5319
  if (stagedFiles.length === 0) return "Impact Preview: no staged changes";
5139
5320
  if (!graphExists(projectPath)) {
@@ -5151,7 +5332,7 @@ async function runImpactPreview(options) {
5151
5332
  return formatImpactOutput(stagedFiles, acc, options);
5152
5333
  }
5153
5334
  function createImpactPreviewCommand() {
5154
- 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) => {
5335
+ const command = new Command42("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) => {
5155
5336
  const output = await runImpactPreview({
5156
5337
  detailed: opts.detailed,
5157
5338
  perFile: opts.perFile,
@@ -5165,24 +5346,24 @@ function createImpactPreviewCommand() {
5165
5346
 
5166
5347
  // src/commands/init.ts
5167
5348
  init_dist3();
5168
- import { Command as Command43 } from "commander";
5349
+ import { Command as Command44 } from "commander";
5169
5350
  import chalk3 from "chalk";
5170
5351
  import * as fs16 from "fs";
5171
- import * as path28 from "path";
5352
+ import * as path29 from "path";
5172
5353
 
5173
5354
  // src/commands/setup-mcp.ts
5174
- import { Command as Command42 } from "commander";
5355
+ import { Command as Command43 } from "commander";
5175
5356
  import * as fs15 from "fs";
5176
- import * as path27 from "path";
5357
+ import * as path28 from "path";
5177
5358
  import * as os2 from "os";
5178
5359
  import chalk2 from "chalk";
5179
5360
  import * as clack from "@clack/prompts";
5180
5361
 
5181
5362
  // src/integrations/toml.ts
5182
5363
  import * as fs14 from "fs";
5183
- import * as path26 from "path";
5364
+ import * as path27 from "path";
5184
5365
  function writeTomlMcpEntry(filePath, name, entry) {
5185
- const dir = path26.dirname(filePath);
5366
+ const dir = path27.dirname(filePath);
5186
5367
  if (!fs14.existsSync(dir)) {
5187
5368
  fs14.mkdirSync(dir, { recursive: true });
5188
5369
  }
@@ -5312,6 +5493,8 @@ var ALL_MCP_TOOLS = [
5312
5493
  "run_code_review",
5313
5494
  "gather_context",
5314
5495
  "assess_project",
5496
+ "canary_probe",
5497
+ "canary_recommend_framework",
5315
5498
  "review_changes",
5316
5499
  "detect_anomalies",
5317
5500
  "ask_graph",
@@ -5368,7 +5551,21 @@ var ALL_MCP_TOOLS = [
5368
5551
  // craft-pipeline #9 — knowledge-craft LLM-judgment ceiling skill (docs/knowledge/ entries)
5369
5552
  "knowledge_craft",
5370
5553
  // craft-pipeline #10 — security-craft LLM-judgment ceiling skill (AST-driven, conservative-confidence)
5371
- "security_craft"
5554
+ "security_craft",
5555
+ // outcome-eval — post-execution spec-satisfaction verdict (tiered confidence→authority)
5556
+ "outcome_eval",
5557
+ // strategic-anchor — STRATEGY.md read/validate/write so projects can call
5558
+ // these via MCP without needing @harness-engineering/core in node_modules
5559
+ "validate_strategy",
5560
+ "read_strategy",
5561
+ "write_strategy",
5562
+ // strategic-anchor — pulse config writer + STRATEGY.md seed extractor
5563
+ "write_pulse_config",
5564
+ "seed_pulse_from_strategy",
5565
+ // strategic-anchor — compound lock acquire/release (server holds the handle;
5566
+ // skill threads a token between calls)
5567
+ "acquire_compound_lock",
5568
+ "release_compound_lock"
5372
5569
  ];
5373
5570
  async function runCursorToolPicker() {
5374
5571
  try {
@@ -5405,7 +5602,7 @@ function readJsonFile(filePath) {
5405
5602
  }
5406
5603
  }
5407
5604
  function writeJsonFile(filePath, data) {
5408
- const dir = path27.dirname(filePath);
5605
+ const dir = path28.dirname(filePath);
5409
5606
  if (!fs15.existsSync(dir)) {
5410
5607
  fs15.mkdirSync(dir, { recursive: true });
5411
5608
  }
@@ -5424,7 +5621,7 @@ function configureMcpServer(configPath) {
5424
5621
  return true;
5425
5622
  }
5426
5623
  function addGeminiTrustedFolder(cwd) {
5427
- const trustedPath = path27.join(os2.homedir(), ".gemini", "trustedFolders.json");
5624
+ const trustedPath = path28.join(os2.homedir(), ".gemini", "trustedFolders.json");
5428
5625
  const folders = readJsonFile(trustedPath) ?? {};
5429
5626
  if (folders[cwd] === "TRUST_FOLDER") {
5430
5627
  return false;
@@ -5438,7 +5635,7 @@ function setupMcp(cwd, client) {
5438
5635
  const skipped = [];
5439
5636
  let trustedFolder = false;
5440
5637
  if (client === "all" || client === "claude") {
5441
- const configPath = path27.join(cwd, ".mcp.json");
5638
+ const configPath = path28.join(cwd, ".mcp.json");
5442
5639
  if (configureMcpServer(configPath)) {
5443
5640
  configured.push("Claude Code");
5444
5641
  } else {
@@ -5446,7 +5643,7 @@ function setupMcp(cwd, client) {
5446
5643
  }
5447
5644
  }
5448
5645
  if (client === "all" || client === "gemini") {
5449
- const configPath = path27.join(cwd, ".gemini", "settings.json");
5646
+ const configPath = path28.join(cwd, ".gemini", "settings.json");
5450
5647
  if (configureMcpServer(configPath)) {
5451
5648
  configured.push("Gemini CLI");
5452
5649
  } else {
@@ -5455,7 +5652,7 @@ function setupMcp(cwd, client) {
5455
5652
  trustedFolder = addGeminiTrustedFolder(cwd);
5456
5653
  }
5457
5654
  if (client === "all" || client === "codex") {
5458
- const configPath = path27.join(cwd, ".codex", "config.toml");
5655
+ const configPath = path28.join(cwd, ".codex", "config.toml");
5459
5656
  const alreadyConfigured = (() => {
5460
5657
  if (!fs15.existsSync(configPath)) return false;
5461
5658
  const content = fs15.readFileSync(configPath, "utf-8");
@@ -5473,7 +5670,7 @@ function setupMcp(cwd, client) {
5473
5670
  }
5474
5671
  }
5475
5672
  if (client === "all" || client === "cursor") {
5476
- const configPath = path27.join(cwd, ".cursor", "mcp.json");
5673
+ const configPath = path28.join(cwd, ".cursor", "mcp.json");
5477
5674
  const existing = readJsonFile(configPath);
5478
5675
  if (existing?.mcpServers?.["harness"]) {
5479
5676
  skipped.push("Cursor");
@@ -5483,7 +5680,7 @@ function setupMcp(cwd, client) {
5483
5680
  }
5484
5681
  }
5485
5682
  if (client === "all" || client === "opencode") {
5486
- const configPath = path27.join(cwd, "opencode.json");
5683
+ const configPath = path28.join(cwd, "opencode.json");
5487
5684
  const existing = readJsonFile(configPath);
5488
5685
  if (existing?.mcp?.["harness"]) {
5489
5686
  skipped.push("OpenCode");
@@ -5497,7 +5694,7 @@ function setupMcp(cwd, client) {
5497
5694
  async function resolveCursorWithPicker(cwd, pick) {
5498
5695
  const configured = [];
5499
5696
  const skipped = [];
5500
- const cursorConfigPath = path27.join(cwd, ".cursor", "mcp.json");
5697
+ const cursorConfigPath = path28.join(cwd, ".cursor", "mcp.json");
5501
5698
  const existing = readJsonFile(cursorConfigPath);
5502
5699
  if (existing?.mcpServers?.["harness"] && !pick) {
5503
5700
  skipped.push("Cursor");
@@ -5541,7 +5738,7 @@ function printMcpResult(configured, skipped, trustedFolder) {
5541
5738
  console.log("");
5542
5739
  }
5543
5740
  function createSetupMcpCommand() {
5544
- return new Command42("setup-mcp").description("Configure MCP server for AI agent integration").option(
5741
+ return new Command43("setup-mcp").description("Configure MCP server for AI agent integration").option(
5545
5742
  "--client <client>",
5546
5743
  "Client to configure (claude, gemini, codex, cursor, opencode, all)",
5547
5744
  "all"
@@ -5572,11 +5769,11 @@ function loadEngineAndTemplates(_options) {
5572
5769
  }
5573
5770
  function resolveInitDefaults(options) {
5574
5771
  const cwd = options.cwd ?? process.cwd();
5575
- return { cwd, name: options.name ?? path28.basename(cwd), force: options.force ?? false };
5772
+ return { cwd, name: options.name ?? path29.basename(cwd), force: options.force ?? false };
5576
5773
  }
5577
5774
  async function runInit(options) {
5578
5775
  const { cwd, name, force } = resolveInitDefaults(options);
5579
- const configPath = path28.join(cwd, "harness.config.json");
5776
+ const configPath = path29.join(cwd, "harness.config.json");
5580
5777
  if (!force && fs16.existsSync(configPath)) {
5581
5778
  return Err(
5582
5779
  new CLIError("Project already initialized. Use --force to overwrite.", ExitCode.ERROR)
@@ -5630,6 +5827,18 @@ function scaffoldProject(engine, ctx) {
5630
5827
  ...language !== void 0 && { language }
5631
5828
  });
5632
5829
  if (!renderResult.ok) return Err(new CLIError(renderResult.error.message, ExitCode.ERROR));
5830
+ const ciResult = generateCIConfig({
5831
+ platform: "github",
5832
+ ...language !== void 0 && { language }
5833
+ });
5834
+ if (ciResult.ok) {
5835
+ renderResult.value.files.push({
5836
+ relativePath: ciResult.value.filename,
5837
+ content: ciResult.value.content
5838
+ });
5839
+ } else {
5840
+ logger.warn(`CI workflow was not generated: ${ciResult.error.message}`);
5841
+ }
5633
5842
  const existingProject = !force && engine.isExistingProject(cwd);
5634
5843
  const writeResult = engine.write(renderResult.value, cwd, {
5635
5844
  overwrite: force,
@@ -5687,7 +5896,7 @@ async function runInitAction2(opts) {
5687
5896
  process.exit(ExitCode.SUCCESS);
5688
5897
  }
5689
5898
  function createInitCommand3() {
5690
- 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) => {
5899
+ const command = new Command44("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) => {
5691
5900
  const globalOpts = cmd.optsWithGlobals();
5692
5901
  await runInitAction2({
5693
5902
  name: opts.name,
@@ -5703,7 +5912,7 @@ function createInitCommand3() {
5703
5912
 
5704
5913
  // src/commands/insights.ts
5705
5914
  init_dist();
5706
- import { Command as Command44 } from "commander";
5915
+ import { Command as Command45 } from "commander";
5707
5916
  function parseSkip2(raw) {
5708
5917
  if (!raw) return [];
5709
5918
  const valid = new Set(INSIGHTS_KEYS);
@@ -5741,10 +5950,10 @@ function renderPretty(report) {
5741
5950
  }
5742
5951
  }
5743
5952
  function createInsightsCommand() {
5744
- return new Command44("insights").description("Composite project report \u2014 health, entropy, decay, attention, impact.").option("--json", "Emit JSON to stdout instead of pretty text").option("--skip <list>", `Comma-separated keys to skip (${INSIGHTS_KEYS.join(",")})`).action(async (opts) => {
5953
+ return new Command45("insights").description("Composite project report \u2014 health, entropy, decay, attention, impact.").option("--json", "Emit JSON to stdout instead of pretty text").option("--skip <list>", `Comma-separated keys to skip (${INSIGHTS_KEYS.join(",")})`).action(async (opts) => {
5745
5954
  const cwd = process.cwd();
5746
5955
  const skip = parseSkip2(opts.skip);
5747
- const { composeInsights } = await import("./dist-72ID44UE.js");
5956
+ const { composeInsights } = await import("./dist-LHINSVK4.js");
5748
5957
  const report = await composeInsights(cwd, { skip });
5749
5958
  if (opts.json) {
5750
5959
  console.log(JSON.stringify(report, null, 2));
@@ -5757,14 +5966,14 @@ function createInsightsCommand() {
5757
5966
  // src/commands/install.ts
5758
5967
  import * as fs21 from "fs";
5759
5968
  import * as os5 from "os";
5760
- import * as path33 from "path";
5969
+ import * as path34 from "path";
5761
5970
  import { execFileSync as execFileSync3 } from "child_process";
5762
- import { Command as Command45 } from "commander";
5971
+ import { Command as Command46 } from "commander";
5763
5972
  import { parse as yamlParse } from "yaml";
5764
5973
 
5765
5974
  // src/registry/npm-client.ts
5766
5975
  import * as fs17 from "fs";
5767
- import * as path29 from "path";
5976
+ import * as path30 from "path";
5768
5977
  import * as os3 from "os";
5769
5978
  var NPM_REGISTRY = "https://registry.npmjs.org";
5770
5979
  var FETCH_TIMEOUT_MS = 3e4;
@@ -5787,7 +5996,7 @@ function extractSkillName(packageName) {
5787
5996
  function readNpmrcToken(registryUrl) {
5788
5997
  const { hostname: hostname2, pathname } = new URL(registryUrl);
5789
5998
  const registryPath = `//${hostname2}${pathname.replace(/\/$/, "")}/:_authToken=`;
5790
- const candidates = [path29.join(process.cwd(), ".npmrc"), path29.join(os3.homedir(), ".npmrc")];
5999
+ const candidates = [path30.join(process.cwd(), ".npmrc"), path30.join(os3.homedir(), ".npmrc")];
5791
6000
  for (const npmrcPath of candidates) {
5792
6001
  try {
5793
6002
  const content = fs17.readFileSync(npmrcPath, "utf-8");
@@ -5886,12 +6095,12 @@ async function searchNpmRegistry(query, registryUrl) {
5886
6095
 
5887
6096
  // src/registry/tarball.ts
5888
6097
  import * as fs18 from "fs";
5889
- import * as path30 from "path";
6098
+ import * as path31 from "path";
5890
6099
  import * as os4 from "os";
5891
6100
  import { execFileSync as execFileSync2 } from "child_process";
5892
6101
  function extractTarball(tarballBuffer) {
5893
- const tmpDir = fs18.mkdtempSync(path30.join(os4.tmpdir(), "harness-skill-install-"));
5894
- const tarballPath = path30.join(tmpDir, "package.tgz");
6102
+ const tmpDir = fs18.mkdtempSync(path31.join(os4.tmpdir(), "harness-skill-install-"));
6103
+ const tarballPath = path31.join(tmpDir, "package.tgz");
5895
6104
  try {
5896
6105
  fs18.writeFileSync(tarballPath, tarballBuffer);
5897
6106
  execFileSync2("tar", ["-xzf", tarballPath, "-C", tmpDir], {
@@ -5910,15 +6119,15 @@ function extractTarball(tarballBuffer) {
5910
6119
  function placeSkillContent(extractedPkgDir, communityBaseDir, skillName, platforms) {
5911
6120
  const files = fs18.readdirSync(extractedPkgDir);
5912
6121
  for (const platform of platforms) {
5913
- const targetDir = path30.join(communityBaseDir, platform, skillName);
6122
+ const targetDir = path31.join(communityBaseDir, platform, skillName);
5914
6123
  if (fs18.existsSync(targetDir)) {
5915
6124
  fs18.rmSync(targetDir, { recursive: true, force: true });
5916
6125
  }
5917
6126
  fs18.mkdirSync(targetDir, { recursive: true });
5918
6127
  for (const file of files) {
5919
6128
  if (file === "package.json" || file === "node_modules") continue;
5920
- const srcPath = path30.join(extractedPkgDir, file);
5921
- const destPath = path30.join(targetDir, file);
6129
+ const srcPath = path31.join(extractedPkgDir, file);
6130
+ const destPath = path31.join(targetDir, file);
5922
6131
  const stat = fs18.statSync(srcPath);
5923
6132
  if (stat.isDirectory()) {
5924
6133
  fs18.cpSync(srcPath, destPath, { recursive: true });
@@ -5930,7 +6139,7 @@ function placeSkillContent(extractedPkgDir, communityBaseDir, skillName, platfor
5930
6139
  }
5931
6140
  function removeSkillContent(communityBaseDir, skillName, platforms) {
5932
6141
  for (const platform of platforms) {
5933
- const targetDir = path30.join(communityBaseDir, platform, skillName);
6142
+ const targetDir = path31.join(communityBaseDir, platform, skillName);
5934
6143
  if (fs18.existsSync(targetDir)) {
5935
6144
  fs18.rmSync(targetDir, { recursive: true, force: true });
5936
6145
  }
@@ -5981,7 +6190,7 @@ function findDependentsOf(lockfile, targetPackageName) {
5981
6190
 
5982
6191
  // src/registry/lockfile.ts
5983
6192
  import * as fs19 from "fs";
5984
- import * as path31 from "path";
6193
+ import * as path32 from "path";
5985
6194
  function createEmptyLockfile() {
5986
6195
  return { version: 1, skills: {} };
5987
6196
  }
@@ -6021,7 +6230,7 @@ function readLockfile2(filePath) {
6021
6230
  return parsed;
6022
6231
  }
6023
6232
  function writeLockfile2(filePath, lockfile) {
6024
- const dir = path31.dirname(filePath);
6233
+ const dir = path32.dirname(filePath);
6025
6234
  fs19.mkdirSync(dir, { recursive: true });
6026
6235
  fs19.writeFileSync(filePath, sortedStringify(lockfile) + "\n", "utf-8");
6027
6236
  }
@@ -6047,7 +6256,7 @@ function removeLockfileEntry(lockfile, name) {
6047
6256
 
6048
6257
  // src/registry/bundled-skills.ts
6049
6258
  import * as fs20 from "fs";
6050
- import * as path32 from "path";
6259
+ import * as path33 from "path";
6051
6260
  function getBundledSkillNames(bundledSkillsDir) {
6052
6261
  if (!fs20.existsSync(bundledSkillsDir)) {
6053
6262
  return /* @__PURE__ */ new Set();
@@ -6056,7 +6265,7 @@ function getBundledSkillNames(bundledSkillsDir) {
6056
6265
  const names = /* @__PURE__ */ new Set();
6057
6266
  for (const entry of entries) {
6058
6267
  try {
6059
- const stat = fs20.statSync(path32.join(bundledSkillsDir, String(entry)));
6268
+ const stat = fs20.statSync(path33.join(bundledSkillsDir, String(entry)));
6060
6269
  if (stat.isDirectory()) {
6061
6270
  names.add(String(entry));
6062
6271
  }
@@ -6084,12 +6293,12 @@ function validateSkillYaml(parsed) {
6084
6293
  function resolveCommunityBase(global) {
6085
6294
  if (global) {
6086
6295
  const communityBase2 = resolveGlobalCommunityBaseDir();
6087
- return { communityBase: communityBase2, lockfilePath: path33.join(communityBase2, "skills-lock.json") };
6296
+ return { communityBase: communityBase2, lockfilePath: path34.join(communityBase2, "skills-lock.json") };
6088
6297
  }
6089
6298
  const globalDir = resolveGlobalSkillsDir();
6090
- const skillsDir = path33.dirname(globalDir);
6091
- const communityBase = path33.join(skillsDir, "community");
6092
- return { communityBase, lockfilePath: path33.join(communityBase, "skills-lock.json") };
6299
+ const skillsDir = path34.dirname(globalDir);
6300
+ const communityBase = path34.join(skillsDir, "community");
6301
+ return { communityBase, lockfilePath: path34.join(communityBase, "skills-lock.json") };
6093
6302
  }
6094
6303
  function parseGitHubRef(from) {
6095
6304
  const ghPrefix = from.match(/^github:([^/]+)\/([^#]+?)(?:#(.+))?$/);
@@ -6105,7 +6314,7 @@ function parseGitHubRef(from) {
6105
6314
  return null;
6106
6315
  }
6107
6316
  function cloneGitHubRepo(owner, repo, ref) {
6108
- const tmpDir = fs21.mkdtempSync(path33.join(os5.tmpdir(), "harness-gh-install-"));
6317
+ const tmpDir = fs21.mkdtempSync(path34.join(os5.tmpdir(), "harness-gh-install-"));
6109
6318
  const url = `https://github.com/${owner}/${repo}.git`;
6110
6319
  try {
6111
6320
  const cloneArgs = ["clone", "--depth", "1"];
@@ -6127,7 +6336,7 @@ function discoverSkillDirs(rootDir) {
6127
6336
  function scan(dir, depth) {
6128
6337
  if (depth > 3) return;
6129
6338
  if (!fs21.existsSync(dir)) return;
6130
- if (fs21.existsSync(path33.join(dir, "skill.yaml"))) {
6339
+ if (fs21.existsSync(path34.join(dir, "skill.yaml"))) {
6131
6340
  skillDirs.push(dir);
6132
6341
  return;
6133
6342
  }
@@ -6135,14 +6344,14 @@ function discoverSkillDirs(rootDir) {
6135
6344
  for (const entry of entries) {
6136
6345
  if (!entry.isDirectory()) continue;
6137
6346
  if (entry.name.startsWith(".") || DEFAULT_SKIP_DIRS.has(entry.name)) continue;
6138
- scan(path33.join(dir, entry.name), depth + 1);
6347
+ scan(path34.join(dir, entry.name), depth + 1);
6139
6348
  }
6140
6349
  }
6141
6350
  scan(rootDir, 0);
6142
6351
  return skillDirs;
6143
6352
  }
6144
6353
  function resolveLocalPkgDir(fromPath) {
6145
- const resolvedPath = path33.resolve(fromPath);
6354
+ const resolvedPath = path34.resolve(fromPath);
6146
6355
  if (!fs21.existsSync(resolvedPath)) {
6147
6356
  throw new Error(`--from path does not exist: ${resolvedPath}`);
6148
6357
  }
@@ -6153,12 +6362,12 @@ function resolveLocalPkgDir(fromPath) {
6153
6362
  if (resolvedPath.endsWith(".tgz") || resolvedPath.endsWith(".tar.gz")) {
6154
6363
  const tarballBuffer = fs21.readFileSync(resolvedPath);
6155
6364
  const extractDir = extractTarball(tarballBuffer);
6156
- return { pkgDir: path33.join(extractDir, "package"), extractDir };
6365
+ return { pkgDir: path34.join(extractDir, "package"), extractDir };
6157
6366
  }
6158
6367
  throw new Error(`--from path must be a directory or .tgz file. Got: ${resolvedPath}`);
6159
6368
  }
6160
6369
  function installSkillDir(pkgDir, resolvedPath, options) {
6161
- const skillYamlPath = path33.join(pkgDir, "skill.yaml");
6370
+ const skillYamlPath = path34.join(pkgDir, "skill.yaml");
6162
6371
  if (!fs21.existsSync(skillYamlPath)) {
6163
6372
  throw new Error(`No skill.yaml found at ${skillYamlPath}`);
6164
6373
  }
@@ -6190,7 +6399,7 @@ function installSkillDir(pkgDir, resolvedPath, options) {
6190
6399
  async function runLocalInstall(fromPath, options) {
6191
6400
  const { pkgDir, extractDir } = resolveLocalPkgDir(fromPath);
6192
6401
  try {
6193
- return installSkillDir(pkgDir, path33.resolve(fromPath), options);
6402
+ return installSkillDir(pkgDir, path34.resolve(fromPath), options);
6194
6403
  } finally {
6195
6404
  if (extractDir) cleanupTempDir(extractDir);
6196
6405
  }
@@ -6233,8 +6442,8 @@ async function runInstall(skillName, options) {
6233
6442
  version: installed.map((r) => r.version).join(", ")
6234
6443
  };
6235
6444
  }
6236
- const resolvedFrom = path33.resolve(options.from);
6237
- if (fs21.existsSync(resolvedFrom) && fs21.statSync(resolvedFrom).isDirectory() && !fs21.existsSync(path33.join(resolvedFrom, "skill.yaml"))) {
6445
+ const resolvedFrom = path34.resolve(options.from);
6446
+ if (fs21.existsSync(resolvedFrom) && fs21.statSync(resolvedFrom).isDirectory() && !fs21.existsSync(path34.join(resolvedFrom, "skill.yaml"))) {
6238
6447
  const results = await runBulkInstall(resolvedFrom, options);
6239
6448
  const installed = results.filter((r) => r.installed);
6240
6449
  return {
@@ -6275,8 +6484,8 @@ async function runInstall(skillName, options) {
6275
6484
  const extractDir = extractTarball(tarballBuffer);
6276
6485
  let skillYaml;
6277
6486
  try {
6278
- const extractedPkgDir = path33.join(extractDir, "package");
6279
- const skillYamlPath = path33.join(extractedPkgDir, "skill.yaml");
6487
+ const extractedPkgDir = path34.join(extractDir, "package");
6488
+ const skillYamlPath = path34.join(extractedPkgDir, "skill.yaml");
6280
6489
  if (!fs21.existsSync(skillYamlPath)) {
6281
6490
  throw new Error(`contains invalid skill.yaml: file not found in package`);
6282
6491
  }
@@ -6320,7 +6529,7 @@ async function runInstall(skillName, options) {
6320
6529
  return result;
6321
6530
  }
6322
6531
  function createInstallCommand() {
6323
- const cmd = new Command45("install");
6532
+ const cmd = new Command46("install");
6324
6533
  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(
6325
6534
  "--from <source>",
6326
6535
  "Install from local path, directory, or GitHub (github:owner/repo, https://github.com/owner/repo)"
@@ -6355,8 +6564,8 @@ function createInstallCommand() {
6355
6564
  // src/commands/install-constraints.ts
6356
6565
  init_dist3();
6357
6566
  import * as fs22 from "fs/promises";
6358
- import * as path34 from "path";
6359
- import { Command as Command46 } from "commander";
6567
+ import * as path35 from "path";
6568
+ import { Command as Command47 } from "commander";
6360
6569
  import semver3 from "semver";
6361
6570
  async function runInstallConstraints(options) {
6362
6571
  const { source, configPath, lockfilePath } = options;
@@ -6553,7 +6762,7 @@ function isNodeError(err) {
6553
6762
  return err instanceof Error && "code" in err;
6554
6763
  }
6555
6764
  function resolveConfigPath(opts) {
6556
- if (opts.config) return path34.resolve(opts.config);
6765
+ if (opts.config) return path35.resolve(opts.config);
6557
6766
  const found = findConfigFile();
6558
6767
  if (!found.ok) {
6559
6768
  logger.error(found.error.message);
@@ -6588,9 +6797,9 @@ function logInstallResult(val, opts) {
6588
6797
  }
6589
6798
  async function handleInstallConstraints(source, opts) {
6590
6799
  const configPath = resolveConfigPath(opts);
6591
- const projectRoot2 = path34.dirname(configPath);
6592
- const lockfilePath = path34.join(projectRoot2, ".harness", "constraints.lock.json");
6593
- const resolvedSource = path34.resolve(source);
6800
+ const projectRoot2 = path35.dirname(configPath);
6801
+ const lockfilePath = path35.join(projectRoot2, ".harness", "constraints.lock.json");
6802
+ const resolvedSource = path35.resolve(source);
6594
6803
  if (opts.forceLocal && opts.forcePackage) {
6595
6804
  logger.error("Cannot use both --force-local and --force-package.");
6596
6805
  process.exit(1);
@@ -6610,19 +6819,19 @@ async function handleInstallConstraints(source, opts) {
6610
6819
  logInstallResult(result.value, opts);
6611
6820
  }
6612
6821
  function createInstallConstraintsCommand() {
6613
- const cmd = new Command46("install-constraints");
6822
+ const cmd = new Command47("install-constraints");
6614
6823
  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);
6615
6824
  return cmd;
6616
6825
  }
6617
6826
 
6618
6827
  // src/commands/integrations/index.ts
6619
- import { Command as Command51 } from "commander";
6828
+ import { Command as Command52 } from "commander";
6620
6829
 
6621
6830
  // src/commands/integrations/add.ts
6622
6831
  init_dist3();
6623
- import { Command as Command47 } from "commander";
6832
+ import { Command as Command48 } from "commander";
6624
6833
  import * as fs23 from "fs";
6625
- import * as path35 from "path";
6834
+ import * as path36 from "path";
6626
6835
  import chalk4 from "chalk";
6627
6836
  function buildMcpEntry(def) {
6628
6837
  const entry = { command: def.mcpConfig.command };
@@ -6631,14 +6840,14 @@ function buildMcpEntry(def) {
6631
6840
  return entry;
6632
6841
  }
6633
6842
  function writeMcpEntries(cwd, defName, mcpEntry) {
6634
- writeMcpEntry(path35.join(cwd, ".mcp.json"), defName, mcpEntry);
6635
- const geminiDir = path35.join(cwd, ".gemini");
6843
+ writeMcpEntry(path36.join(cwd, ".mcp.json"), defName, mcpEntry);
6844
+ const geminiDir = path36.join(cwd, ".gemini");
6636
6845
  if (fs23.existsSync(geminiDir)) {
6637
- writeMcpEntry(path35.join(geminiDir, "settings.json"), defName, mcpEntry);
6846
+ writeMcpEntry(path36.join(geminiDir, "settings.json"), defName, mcpEntry);
6638
6847
  }
6639
6848
  }
6640
6849
  function updateIntegrationsConfig(cwd, defName) {
6641
- const configPath = path35.join(cwd, "harness.config.json");
6850
+ const configPath = path36.join(cwd, "harness.config.json");
6642
6851
  const integConfig = readIntegrationsConfig(configPath);
6643
6852
  if (!integConfig.enabled.includes(defName)) integConfig.enabled.push(defName);
6644
6853
  integConfig.dismissed = integConfig.dismissed.filter((d) => d !== defName);
@@ -6684,7 +6893,7 @@ function printAddSuccess(value) {
6684
6893
  }
6685
6894
  }
6686
6895
  function createAddIntegrationCommand() {
6687
- return new Command47("add").description("Enable an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6896
+ return new Command48("add").description("Enable an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6688
6897
  const globalOpts = cmd.optsWithGlobals();
6689
6898
  const result = addIntegration(process.cwd(), name);
6690
6899
  if (!result.ok) {
@@ -6698,8 +6907,8 @@ function createAddIntegrationCommand() {
6698
6907
  }
6699
6908
 
6700
6909
  // src/commands/integrations/list.ts
6701
- import { Command as Command48 } from "commander";
6702
- import * as path36 from "path";
6910
+ import { Command as Command49 } from "commander";
6911
+ import * as path37 from "path";
6703
6912
  import chalk5 from "chalk";
6704
6913
  function printTier0Integrations(tier0, mcpServers) {
6705
6914
  console.log(" Tier 0 (zero-config):");
@@ -6723,8 +6932,8 @@ function printTier1Integrations(tier1, mcpServers, dismissed) {
6723
6932
  }
6724
6933
  async function runListIntegrations(globalOpts) {
6725
6934
  const cwd = process.cwd();
6726
- const mcpConfig = readMcpConfig(path36.join(cwd, ".mcp.json"));
6727
- const integConfig = readIntegrationsConfig(path36.join(cwd, "harness.config.json"));
6935
+ const mcpConfig = readMcpConfig(path37.join(cwd, ".mcp.json"));
6936
+ const integConfig = readIntegrationsConfig(path37.join(cwd, "harness.config.json"));
6728
6937
  const mcpServers = mcpConfig.mcpServers ?? {};
6729
6938
  if (globalOpts.json) {
6730
6939
  const entries = INTEGRATION_REGISTRY.map((i) => ({
@@ -6755,14 +6964,14 @@ async function runListIntegrations(globalOpts) {
6755
6964
  process.exit(ExitCode.SUCCESS);
6756
6965
  }
6757
6966
  function createListIntegrationsCommand() {
6758
- return new Command48("list").description("Show all MCP integrations with status").action(async (_opts, cmd) => runListIntegrations(cmd.optsWithGlobals()));
6967
+ return new Command49("list").description("Show all MCP integrations with status").action(async (_opts, cmd) => runListIntegrations(cmd.optsWithGlobals()));
6759
6968
  }
6760
6969
 
6761
6970
  // src/commands/integrations/remove.ts
6762
6971
  init_dist3();
6763
- import { Command as Command49 } from "commander";
6972
+ import { Command as Command50 } from "commander";
6764
6973
  import * as fs24 from "fs";
6765
- import * as path37 from "path";
6974
+ import * as path38 from "path";
6766
6975
  function removeIntegration(cwd, name) {
6767
6976
  const def = INTEGRATION_REGISTRY.find((i) => i.name === name);
6768
6977
  if (!def) {
@@ -6773,21 +6982,21 @@ function removeIntegration(cwd, name) {
6773
6982
  )
6774
6983
  );
6775
6984
  }
6776
- const mcpPath = path37.join(cwd, ".mcp.json");
6985
+ const mcpPath = path38.join(cwd, ".mcp.json");
6777
6986
  removeMcpEntry(mcpPath, def.name);
6778
- const geminiDir = path37.join(cwd, ".gemini");
6987
+ const geminiDir = path38.join(cwd, ".gemini");
6779
6988
  if (fs24.existsSync(geminiDir)) {
6780
- const geminiPath = path37.join(geminiDir, "settings.json");
6989
+ const geminiPath = path38.join(geminiDir, "settings.json");
6781
6990
  removeMcpEntry(geminiPath, def.name);
6782
6991
  }
6783
- const configPath = path37.join(cwd, "harness.config.json");
6992
+ const configPath = path38.join(cwd, "harness.config.json");
6784
6993
  const integConfig = readIntegrationsConfig(configPath);
6785
6994
  integConfig.enabled = integConfig.enabled.filter((e) => e !== def.name);
6786
6995
  writeIntegrationsConfig(configPath, integConfig);
6787
6996
  return Ok(def.displayName);
6788
6997
  }
6789
6998
  function createRemoveIntegrationCommand() {
6790
- return new Command49("remove").description("Remove an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6999
+ return new Command50("remove").description("Remove an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6791
7000
  const globalOpts = cmd.optsWithGlobals();
6792
7001
  const cwd = process.cwd();
6793
7002
  const result = removeIntegration(cwd, name);
@@ -6809,8 +7018,8 @@ function createRemoveIntegrationCommand() {
6809
7018
 
6810
7019
  // src/commands/integrations/dismiss.ts
6811
7020
  init_dist3();
6812
- import { Command as Command50 } from "commander";
6813
- import * as path38 from "path";
7021
+ import { Command as Command51 } from "commander";
7022
+ import * as path39 from "path";
6814
7023
  function dismissIntegration(cwd, name) {
6815
7024
  const def = INTEGRATION_REGISTRY.find((i) => i.name === name);
6816
7025
  if (!def) {
@@ -6821,7 +7030,7 @@ function dismissIntegration(cwd, name) {
6821
7030
  )
6822
7031
  );
6823
7032
  }
6824
- const configPath = path38.join(cwd, "harness.config.json");
7033
+ const configPath = path39.join(cwd, "harness.config.json");
6825
7034
  const integConfig = readIntegrationsConfig(configPath);
6826
7035
  if (!integConfig.dismissed.includes(def.name)) {
6827
7036
  integConfig.dismissed.push(def.name);
@@ -6831,7 +7040,7 @@ function dismissIntegration(cwd, name) {
6831
7040
  return Ok(def.displayName);
6832
7041
  }
6833
7042
  function createDismissIntegrationCommand() {
6834
- 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) => {
7043
+ return new Command51("dismiss").description("Suppress doctor recommendations for an integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
6835
7044
  const globalOpts = cmd.optsWithGlobals();
6836
7045
  const cwd = process.cwd();
6837
7046
  const result = dismissIntegration(cwd, name);
@@ -6855,7 +7064,7 @@ function createDismissIntegrationCommand() {
6855
7064
 
6856
7065
  // src/commands/integrations/index.ts
6857
7066
  function createIntegrationsCommand() {
6858
- const command = new Command51("integrations").description(
7067
+ const command = new Command52("integrations").description(
6859
7068
  "Manage MCP peer integrations (add, list, remove, dismiss)"
6860
7069
  );
6861
7070
  command.addCommand(createListIntegrationsCommand());
@@ -6866,9 +7075,9 @@ function createIntegrationsCommand() {
6866
7075
  }
6867
7076
 
6868
7077
  // src/commands/knowledge-craft.ts
6869
- import { Command as Command52 } from "commander";
7078
+ import { Command as Command53 } from "commander";
6870
7079
  function createKnowledgeCraftCommand() {
6871
- return new Command52("knowledge-craft").description(
7080
+ return new Command53("knowledge-craft").description(
6872
7081
  "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."
6873
7082
  ).option("-f, --files <files...>", "Optional file scope (overrides discovery)").option(
6874
7083
  "--exclude-dirs <dirs...>",
@@ -6916,10 +7125,10 @@ function printResult3(result, mode, _formatter) {
6916
7125
  list.push(f);
6917
7126
  byFile.set(f.target.file, list);
6918
7127
  }
6919
- for (const [file, fs48] of byFile) {
7128
+ for (const [file, fs49] of byFile) {
6920
7129
  console.log(`
6921
7130
  ${file}`);
6922
- for (const f of fs48) {
7131
+ for (const f of fs49) {
6923
7132
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.relative}`);
6924
7133
  console.log(` ${f.message}`);
6925
7134
  if (verbose) console.log(` source: ${f.cite.source}`);
@@ -6933,18 +7142,18 @@ ${file}`);
6933
7142
  }
6934
7143
 
6935
7144
  // src/commands/knowledge-pipeline.ts
6936
- import { Command as Command53 } from "commander";
6937
- import * as path39 from "path";
7145
+ import { Command as Command54 } from "commander";
7146
+ import * as path40 from "path";
6938
7147
  import chalk6 from "chalk";
6939
7148
  function createKnowledgePipelineCommand() {
6940
- 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) => {
7149
+ return new Command54("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) => {
6941
7150
  const globalOpts = cmd.optsWithGlobals();
6942
7151
  const projectDir = process.cwd();
6943
7152
  try {
6944
- const graphDir = path39.join(projectDir, ".harness", "graph");
6945
- const fs48 = await import("fs/promises");
6946
- await fs48.mkdir(graphDir, { recursive: true });
6947
- const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-R3TOOPJ7.js");
7153
+ const graphDir = path40.join(projectDir, ".harness", "graph");
7154
+ const fs49 = await import("fs/promises");
7155
+ await fs49.mkdir(graphDir, { recursive: true });
7156
+ const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-OWHMNL4W.js");
6948
7157
  const store = new GraphStore2();
6949
7158
  try {
6950
7159
  await store.load(graphDir);
@@ -7000,6 +7209,7 @@ function createKnowledgePipelineCommand() {
7000
7209
  iterations: result.iterations,
7001
7210
  findings: result.findings,
7002
7211
  extraction: result.extraction,
7212
+ errors: result.errors,
7003
7213
  gaps: {
7004
7214
  domains: result.gaps.domains.length,
7005
7215
  totalEntries: result.gaps.totalEntries,
@@ -7040,7 +7250,7 @@ function createKnowledgePipelineCommand() {
7040
7250
  ` Findings: ${result.findings.new} new, ${result.findings.stale} stale, ${result.findings.drifted} drifted, ${result.findings.contradicting} contradicting`
7041
7251
  );
7042
7252
  console.log(
7043
- ` Extraction: ${result.extraction.codeSignals} code signals, ${result.extraction.diagrams} diagrams, ${result.extraction.linkerFacts} linker facts, ${result.extraction.businessKnowledge} business knowledge, ${result.extraction.images} images`
7253
+ ` Extraction: ${result.extraction.codeSignals} code signals, ${result.extraction.diagrams} diagrams, ${result.extraction.linkerFacts} linker facts, ${result.extraction.businessKnowledge} business knowledge, ${result.extraction.decisions} decisions, ${result.extraction.images} images`
7044
7254
  );
7045
7255
  console.log(
7046
7256
  ` Gaps: ${result.gaps.domains.length} domains \u2014 ${result.gaps.totalEntries} documented / ${result.gaps.totalExtracted} extracted / ${result.gaps.totalGaps} undocumented`
@@ -7051,6 +7261,13 @@ function createKnowledgePipelineCommand() {
7051
7261
  if (result.remediations.length > 0) {
7052
7262
  console.log(` Remediations: ${result.remediations.length} applied`);
7053
7263
  }
7264
+ if (result.errors.length > 0) {
7265
+ console.warn("");
7266
+ console.warn(` ${result.errors.length} ingestion warning(s):`);
7267
+ for (const err of result.errors) {
7268
+ console.warn(` - ${err}`);
7269
+ }
7270
+ }
7054
7271
  if (result.materialization) {
7055
7272
  const mat = result.materialization;
7056
7273
  console.log(
@@ -7101,14 +7318,14 @@ function createKnowledgePipelineCommand() {
7101
7318
  }
7102
7319
 
7103
7320
  // src/commands/learnings/index.ts
7104
- import { Command as Command55 } from "commander";
7321
+ import { Command as Command56 } from "commander";
7105
7322
 
7106
7323
  // src/commands/learnings/prune.ts
7107
7324
  init_dist3();
7108
- import { Command as Command54 } from "commander";
7109
- import * as path40 from "path";
7325
+ import { Command as Command55 } from "commander";
7326
+ import * as path41 from "path";
7110
7327
  async function handlePrune(opts) {
7111
- const projectPath = path40.resolve(opts.path);
7328
+ const projectPath = path41.resolve(opts.path);
7112
7329
  const result = await pruneLearnings(projectPath, opts.stream);
7113
7330
  if (!result.ok) {
7114
7331
  logger.error(result.error.message);
@@ -7147,23 +7364,23 @@ function printPatternProposals(patterns) {
7147
7364
  );
7148
7365
  }
7149
7366
  function createPruneCommand() {
7150
- return new Command54("prune").description(
7367
+ return new Command55("prune").description(
7151
7368
  "Analyze global learnings for patterns, present improvement proposals, and archive old entries"
7152
7369
  ).option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(handlePrune);
7153
7370
  }
7154
7371
 
7155
7372
  // src/commands/learnings/index.ts
7156
7373
  function createLearningsCommand() {
7157
- const command = new Command55("learnings").description("Learnings management commands");
7374
+ const command = new Command56("learnings").description("Learnings management commands");
7158
7375
  command.addCommand(createPruneCommand());
7159
7376
  return command;
7160
7377
  }
7161
7378
 
7162
7379
  // src/commands/linter/index.ts
7163
- import { Command as Command58 } from "commander";
7380
+ import { Command as Command59 } from "commander";
7164
7381
 
7165
7382
  // src/commands/linter/generate.ts
7166
- import { Command as Command56 } from "commander";
7383
+ import { Command as Command57 } from "commander";
7167
7384
  function formatGenerateError(e) {
7168
7385
  switch (e.type) {
7169
7386
  case "parse":
@@ -7207,7 +7424,7 @@ function handleSuccess(result, useJson) {
7207
7424
  Generated ${result.rulesGenerated.length} rules to ${result.outputDir}`);
7208
7425
  }
7209
7426
  function createGenerateCommand2() {
7210
- 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) => {
7427
+ return new Command57("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) => {
7211
7428
  try {
7212
7429
  if (options.verbose) logger.info(`Parsing config: ${options.config}`);
7213
7430
  const result = await generate({
@@ -7229,9 +7446,9 @@ function createGenerateCommand2() {
7229
7446
  }
7230
7447
 
7231
7448
  // src/commands/linter/validate.ts
7232
- import { Command as Command57 } from "commander";
7449
+ import { Command as Command58 } from "commander";
7233
7450
  function createValidateCommand() {
7234
- 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) => {
7451
+ return new Command58("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) => {
7235
7452
  try {
7236
7453
  const result = await validate({ configPath: options.config });
7237
7454
  if (options.json) {
@@ -7250,7 +7467,7 @@ function createValidateCommand() {
7250
7467
 
7251
7468
  // src/commands/linter/index.ts
7252
7469
  function createLinterCommand() {
7253
- const linter = new Command58("linter").description(
7470
+ const linter = new Command59("linter").description(
7254
7471
  "Generate and validate ESLint rules from YAML config"
7255
7472
  );
7256
7473
  linter.addCommand(createGenerateCommand2());
@@ -7259,8 +7476,8 @@ function createLinterCommand() {
7259
7476
  }
7260
7477
 
7261
7478
  // src/commands/maintenance.ts
7262
- import { Command as Command59 } from "commander";
7263
- import * as path41 from "path";
7479
+ import { Command as Command60 } from "commander";
7480
+ import * as path42 from "path";
7264
7481
  import * as fs25 from "fs";
7265
7482
  import chalk7 from "chalk";
7266
7483
  import {
@@ -7269,7 +7486,7 @@ import {
7269
7486
  WorkflowLoader
7270
7487
  } from "@harness-engineering/orchestrator";
7271
7488
  async function loadMaintenanceConfig(cwd) {
7272
- const workflowPath = path41.join(cwd, "harness.orchestrator.md");
7489
+ const workflowPath = path42.join(cwd, "harness.orchestrator.md");
7273
7490
  if (!fs25.existsSync(workflowPath)) return null;
7274
7491
  const loader = new WorkflowLoader();
7275
7492
  const result = await loader.loadWorkflow(workflowPath);
@@ -7351,11 +7568,11 @@ function printListTable(rows) {
7351
7568
  }
7352
7569
  }
7353
7570
  function createMaintenanceCommand() {
7354
- const command = new Command59("maintenance").description(
7571
+ const command = new Command60("maintenance").description(
7355
7572
  "Inspect built-in + custom maintenance tasks and their persisted outputs"
7356
7573
  );
7357
7574
  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) => {
7358
- const cwd = path41.resolve(opts.path);
7575
+ const cwd = path42.resolve(opts.path);
7359
7576
  const config = await loadMaintenanceConfig(cwd);
7360
7577
  const tasks = mergeResolvedTasks(config);
7361
7578
  const rows = tasks.map((t) => ({
@@ -7382,10 +7599,10 @@ async function runShow(taskId, opts) {
7382
7599
  console.error(`Invalid task id '${taskId}' (must match ^[a-z0-9][a-z0-9-]*$).`);
7383
7600
  process.exit(ExitCode.ERROR);
7384
7601
  }
7385
- const cwd = path41.resolve(opts.path ?? ".");
7602
+ const cwd = path42.resolve(opts.path ?? ".");
7386
7603
  const limit = Math.max(1, parseInt(opts.limit ?? "5", 10) || 5);
7387
7604
  const store = new TaskOutputStore({
7388
- rootDir: path41.join(cwd, ".harness", "maintenance")
7605
+ rootDir: path42.join(cwd, ".harness", "maintenance")
7389
7606
  });
7390
7607
  const entries = await store.list(taskId, limit, 0);
7391
7608
  renderShow(taskId, entries, Boolean(opts.json));
@@ -7419,7 +7636,7 @@ function describeOrigin(origin) {
7419
7636
  }
7420
7637
 
7421
7638
  // src/commands/mcp.ts
7422
- import { Command as Command60 } from "commander";
7639
+ import { Command as Command61 } from "commander";
7423
7640
  var VALID_TIERS = /* @__PURE__ */ new Set(["core", "standard", "full"]);
7424
7641
  function parseTier(value) {
7425
7642
  const lower = value.toLowerCase();
@@ -7436,7 +7653,7 @@ function parseBudget(value) {
7436
7653
  return n;
7437
7654
  }
7438
7655
  function createMcpCommand() {
7439
- 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(
7656
+ return new Command61("mcp").description("Start the MCP (Model Context Protocol) server on stdio").option("--tools <tools...>", "Only register the specified tools (used by Cursor integration)").option(
7440
7657
  "--tier <core|standard|full>",
7441
7658
  "Load a preset tool tier instead of all tools",
7442
7659
  parseTier
@@ -7446,8 +7663,8 @@ function createMcpCommand() {
7446
7663
  parseBudget
7447
7664
  ).action(async (opts) => {
7448
7665
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
7449
- import("./mcp-OYR26JDI.js"),
7450
- import("./tool-tiers-B7JC2XC3.js")
7666
+ import("./mcp-RK3SFVYB.js"),
7667
+ import("./tool-tiers-OKK5FE57.js")
7451
7668
  ]);
7452
7669
  if (opts.tools && opts.tools.length > 0) {
7453
7670
  await startServer2(opts.tools);
@@ -7468,9 +7685,9 @@ function createMcpCommand() {
7468
7685
 
7469
7686
  // src/commands/mcp-guard.ts
7470
7687
  init_dist3();
7471
- import { Command as Command61 } from "commander";
7688
+ import { Command as Command62 } from "commander";
7472
7689
  import * as fs26 from "fs";
7473
- import * as path42 from "path";
7690
+ import * as path43 from "path";
7474
7691
  import chalk8 from "chalk";
7475
7692
  function extractNpmPackages(config) {
7476
7693
  const out = [];
@@ -7509,7 +7726,7 @@ function parseNpmSpec(spec) {
7509
7726
  }
7510
7727
  async function runMcpGuardCheck(options = {}) {
7511
7728
  const cwd = options.cwd ?? process.cwd();
7512
- const configPath = options.configPath ?? path42.join(cwd, ".mcp.json");
7729
+ const configPath = options.configPath ?? path43.join(cwd, ".mcp.json");
7513
7730
  if (!fs26.existsSync(configPath)) {
7514
7731
  return { ok: true, checked: [] };
7515
7732
  }
@@ -7520,7 +7737,7 @@ async function runMcpGuardCheck(options = {}) {
7520
7737
  return { ok: true, checked: [] };
7521
7738
  }
7522
7739
  const pkgs = extractNpmPackages(config);
7523
- const cacheDir = path42.join(cwd, ".harness", "cache", "osv");
7740
+ const cacheDir = path43.join(cwd, ".harness", "cache", "osv");
7524
7741
  const warnLogger = {
7525
7742
  warn: (m, ctx) => logger.warn(ctx ? `${m} ${JSON.stringify(ctx)}` : m)
7526
7743
  };
@@ -7576,12 +7793,12 @@ function formatHuman(result) {
7576
7793
  }
7577
7794
  }
7578
7795
  function createMcpGuardCommand() {
7579
- const command = new Command61("mcp-guard").description("Pre-launch OSV malware guard for MCP/npx packages").addHelpText(
7796
+ const command = new Command62("mcp-guard").description("Pre-launch OSV malware guard for MCP/npx packages").addHelpText(
7580
7797
  "after",
7581
7798
  '\nUse "harness mcp-guard check" before launching MCP servers to block known malicious packages.'
7582
7799
  );
7583
7800
  command.command("check").description("Check every MCP/npx package in .mcp.json against OSV.dev advisories").option("--strict", "Fail closed on network errors (default: fail-open)", false).option("--json", "Emit machine-readable JSON", false).option("--path <path>", "Project root path", ".").action(async (opts) => {
7584
- const cwd = path42.resolve(opts.path);
7801
+ const cwd = path43.resolve(opts.path);
7585
7802
  const result = await runMcpGuardCheck({ cwd, strict: opts.strict, json: opts.json });
7586
7803
  if (opts.json) {
7587
7804
  console.log(JSON.stringify(result, null, 2));
@@ -7592,8 +7809,8 @@ function createMcpGuardCommand() {
7592
7809
  process.exit(result.ok ? ExitCode.SUCCESS : 2);
7593
7810
  });
7594
7811
  command.command("cache").description("Manage the on-disk OSV advisory cache").command("clear").option("--path <path>", "Project root path", ".").action(async (opts) => {
7595
- const cwd = path42.resolve(opts.path);
7596
- const cacheDir = path42.join(cwd, ".harness", "cache", "osv");
7812
+ const cwd = path43.resolve(opts.path);
7813
+ const cacheDir = path43.join(cwd, ".harness", "cache", "osv");
7597
7814
  try {
7598
7815
  fs26.rmSync(cacheDir, { recursive: true, force: true });
7599
7816
  console.log(`Cleared ${cacheDir}`);
@@ -7607,12 +7824,12 @@ function createMcpGuardCommand() {
7607
7824
  }
7608
7825
 
7609
7826
  // src/commands/migrate.ts
7610
- import { Command as Command63 } from "commander";
7827
+ import { Command as Command64 } from "commander";
7611
7828
 
7612
7829
  // src/commands/migrate-backends.ts
7613
- import { Command as Command62 } from "commander";
7830
+ import { Command as Command63 } from "commander";
7614
7831
  import * as fs27 from "fs";
7615
- import * as path43 from "path";
7832
+ import * as path44 from "path";
7616
7833
  import chalk9 from "chalk";
7617
7834
  import { parse as parseYaml2 } from "yaml";
7618
7835
  async function runMigrateBackends(opts = {}) {
@@ -7634,7 +7851,7 @@ async function runMigrateBackends(opts = {}) {
7634
7851
  };
7635
7852
  }
7636
7853
  const routing = readRoutingFromOrchestratorMd(mdPath);
7637
- const jsonPath = path43.join(path43.dirname(mdPath), "harness.config.json");
7854
+ const jsonPath = path44.join(path44.dirname(mdPath), "harness.config.json");
7638
7855
  if (!fs27.existsSync(jsonPath)) {
7639
7856
  return {
7640
7857
  status: "error",
@@ -7727,7 +7944,7 @@ function readRoutingFromOrchestratorMd(mdPath) {
7727
7944
  return routing ?? null;
7728
7945
  }
7729
7946
  function createBackendsSubcommand() {
7730
- return new Command62("backends").description(
7947
+ return new Command63("backends").description(
7731
7948
  "Copy agent.backends (and routing) from harness.orchestrator.md into harness.config.json."
7732
7949
  ).option("--dry-run", "Show what would change without writing", false).option("--force", "Overwrite existing agent.backends in harness.config.json", false).action(async (options) => {
7733
7950
  const result = await runMigrateBackends({
@@ -7747,7 +7964,7 @@ function createBackendsSubcommand() {
7747
7964
  init_dist3();
7748
7965
  init_dist2();
7749
7966
  import * as fs28 from "fs";
7750
- import * as path44 from "path";
7967
+ import * as path45 from "path";
7751
7968
  import * as readline from "readline";
7752
7969
  import { execFileSync as execFileSync4 } from "child_process";
7753
7970
  import chalk10 from "chalk";
@@ -7779,7 +7996,7 @@ function walk(dir, predicate) {
7779
7996
  const out = [];
7780
7997
  for (const entry of fs28.readdirSync(dir, { withFileTypes: true })) {
7781
7998
  if (DEFAULT_SKIP_DIRS.has(entry.name)) continue;
7782
- const full = path44.join(dir, entry.name);
7999
+ const full = path45.join(dir, entry.name);
7783
8000
  if (entry.isDirectory()) out.push(...walk(full, predicate));
7784
8001
  else if (predicate(full)) out.push(full);
7785
8002
  }
@@ -7791,11 +8008,11 @@ function extractAutopilotTopic(state) {
7791
8008
  }
7792
8009
  function buildAutopilotMap(cwd) {
7793
8010
  const map = /* @__PURE__ */ new Map();
7794
- const sessionsDir = path44.join(cwd, ".harness", "sessions");
8011
+ const sessionsDir = path45.join(cwd, ".harness", "sessions");
7795
8012
  if (!fs28.existsSync(sessionsDir)) return map;
7796
8013
  for (const session of listDirs(sessionsDir)) {
7797
8014
  if (!session.startsWith("changes--")) continue;
7798
- const state = readJson2(path44.join(sessionsDir, session, "autopilot-state.json"));
8015
+ const state = readJson2(path45.join(sessionsDir, session, "autopilot-state.json"));
7799
8016
  if (!state) continue;
7800
8017
  const topic = extractAutopilotTopic(state);
7801
8018
  if (!topic) continue;
@@ -7833,7 +8050,7 @@ function extractTopicFromFilename(filename, proposalTopics) {
7833
8050
  return best;
7834
8051
  }
7835
8052
  function resolveDocsDir(cwd) {
7836
- const configPath = path44.join(cwd, "harness.config.json");
8053
+ const configPath = path45.join(cwd, "harness.config.json");
7837
8054
  const configResult = fs28.existsSync(configPath) ? resolveConfig(configPath) : null;
7838
8055
  let docsDir;
7839
8056
  if (configResult?.ok) {
@@ -7846,16 +8063,16 @@ function resolveDocsDir(cwd) {
7846
8063
  } else {
7847
8064
  docsDir = "./docs";
7848
8065
  }
7849
- const docsAbs = path44.resolve(cwd, docsDir);
7850
- const relRaw = path44.relative(cwd, docsAbs).replaceAll("\\", "/");
8066
+ const docsAbs = path45.resolve(cwd, docsDir);
8067
+ const relRaw = path45.relative(cwd, docsAbs).replaceAll("\\", "/");
7851
8068
  return relRaw === "" ? "docs" : relRaw;
7852
8069
  }
7853
8070
  function collectAdrMoves(cwd, docsRel) {
7854
8071
  const moves = [];
7855
- const legacyAdrDir = path44.join(cwd, ".harness", "architecture");
8072
+ const legacyAdrDir = path45.join(cwd, ".harness", "architecture");
7856
8073
  if (!fs28.existsSync(legacyAdrDir)) return moves;
7857
8074
  for (const topic of listDirs(legacyAdrDir)) {
7858
- const topicSrc = path44.join(legacyAdrDir, topic);
8075
+ const topicSrc = path45.join(legacyAdrDir, topic);
7859
8076
  for (const file of listFiles(topicSrc, (n) => n.endsWith(".md"))) {
7860
8077
  moves.push({
7861
8078
  src: `.harness/architecture/${topic}/${file}`,
@@ -7867,9 +8084,9 @@ function collectAdrMoves(cwd, docsRel) {
7867
8084
  }
7868
8085
  function collectProposalTopics(cwd) {
7869
8086
  const topics = /* @__PURE__ */ new Set();
7870
- const changesDir = path44.join(cwd, "docs", "changes");
8087
+ const changesDir = path45.join(cwd, "docs", "changes");
7871
8088
  for (const topic of listDirs(changesDir)) {
7872
- if (fs28.existsSync(path44.join(changesDir, topic, "proposal.md"))) {
8089
+ if (fs28.existsSync(path45.join(changesDir, topic, "proposal.md"))) {
7873
8090
  topics.add(topic);
7874
8091
  }
7875
8092
  }
@@ -7896,12 +8113,12 @@ async function buildPlan(opts) {
7896
8113
  orphanPlans: [],
7897
8114
  proposalTopics: collectProposalTopics(cwd)
7898
8115
  };
7899
- const legacyPlanDir = path44.join(cwd, "docs", "plans");
8116
+ const legacyPlanDir = path45.join(cwd, "docs", "plans");
7900
8117
  if (!fs28.existsSync(legacyPlanDir)) return plan;
7901
8118
  const autopilotMap = buildAutopilotMap(cwd);
7902
8119
  for (const file of listFiles(legacyPlanDir, (n) => n.endsWith(".md") && n !== "index.md")) {
7903
8120
  const planRel = `docs/plans/${file}`;
7904
- const planAbs = path44.join(legacyPlanDir, file);
8121
+ const planAbs = path45.join(legacyPlanDir, file);
7905
8122
  const subdir = file.includes("VERIFICATION") ? "verifications" : "plans";
7906
8123
  const classified = classifyPlan(planRel, planAbs, file, autopilotMap, plan.proposalTopics);
7907
8124
  if (classified) {
@@ -7919,8 +8136,8 @@ async function buildPlan(opts) {
7919
8136
  return plan;
7920
8137
  }
7921
8138
  function gitMv(cwd, src, dest, useGit) {
7922
- const destAbs = path44.join(cwd, dest);
7923
- fs28.mkdirSync(path44.dirname(destAbs), { recursive: true });
8139
+ const destAbs = path45.join(cwd, dest);
8140
+ fs28.mkdirSync(path45.dirname(destAbs), { recursive: true });
7924
8141
  if (useGit) {
7925
8142
  try {
7926
8143
  execFileSync4("git", ["mv", src, dest], { cwd, stdio: "pipe" });
@@ -7928,7 +8145,7 @@ function gitMv(cwd, src, dest, useGit) {
7928
8145
  } catch {
7929
8146
  }
7930
8147
  }
7931
- fs28.renameSync(path44.join(cwd, src), destAbs);
8148
+ fs28.renameSync(path45.join(cwd, src), destAbs);
7932
8149
  }
7933
8150
  function executeMigration(plan) {
7934
8151
  let moved = 0;
@@ -7960,8 +8177,8 @@ function updateReferences(plan) {
7960
8177
  let files = 0;
7961
8178
  let replacements = 0;
7962
8179
  const targets = [
7963
- ...walk(path44.join(plan.cwd, "docs"), (p) => p.endsWith(".md")),
7964
- ...walk(path44.join(plan.cwd, ".harness", "sessions"), (p) => p.endsWith(".json"))
8180
+ ...walk(path45.join(plan.cwd, "docs"), (p) => p.endsWith(".md")),
8181
+ ...walk(path45.join(plan.cwd, ".harness", "sessions"), (p) => p.endsWith(".json"))
7965
8182
  ];
7966
8183
  for (const target of targets) {
7967
8184
  let text;
@@ -7988,7 +8205,7 @@ function updateReferences(plan) {
7988
8205
  }
7989
8206
  async function prompt(question, def = "n") {
7990
8207
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
7991
- const answer = await new Promise((resolve46) => rl.question(question, resolve46));
8208
+ const answer = await new Promise((resolve47) => rl.question(question, resolve47));
7992
8209
  rl.close();
7993
8210
  return (answer.trim() || def).toLowerCase();
7994
8211
  }
@@ -8038,7 +8255,7 @@ async function resolveOrphans(plan, opts) {
8038
8255
  }
8039
8256
  function bucketOrphans(plan, topic) {
8040
8257
  for (const src of plan.orphanPlans) {
8041
- const file = path44.basename(src);
8258
+ const file = path45.basename(src);
8042
8259
  const isVerification = file.includes("VERIFICATION");
8043
8260
  const subdir = isVerification ? "verifications" : "plans";
8044
8261
  plan.planMoves.push({
@@ -8080,9 +8297,9 @@ function summarize(plan) {
8080
8297
  console.log("");
8081
8298
  }
8082
8299
  async function detectLegacyArtifacts(cwd) {
8083
- const adrLegacyDir = path44.join(cwd, ".harness", "architecture");
8300
+ const adrLegacyDir = path45.join(cwd, ".harness", "architecture");
8084
8301
  const adrLegacy = fs28.existsSync(adrLegacyDir) && listDirs(adrLegacyDir).length > 0;
8085
- const planLegacyDir = path44.join(cwd, "docs", "plans");
8302
+ const planLegacyDir = path45.join(cwd, "docs", "plans");
8086
8303
  const planLegacy = fs28.existsSync(planLegacyDir) && listFiles(planLegacyDir, (n) => n.endsWith(".md") && n !== "index.md").length > 0;
8087
8304
  return { adrLegacy, planLegacy };
8088
8305
  }
@@ -8151,7 +8368,7 @@ async function runMigrate(opts) {
8151
8368
  });
8152
8369
  }
8153
8370
  function createMigrateCommand() {
8154
- const cmd = new Command63("migrate").description("Migrate legacy harness artifact locations to current layout").option("--dry-run", "Show the migration plan without moving files", false).option("--yes", "Skip confirmation prompt", false).option(
8371
+ const cmd = new Command64("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(
8155
8372
  "--skip-references",
8156
8373
  "Do not update path references in docs/sessions after moves",
8157
8374
  false
@@ -8175,7 +8392,7 @@ function createMigrateCommand() {
8175
8392
  }
8176
8393
 
8177
8394
  // src/commands/models.ts
8178
- import { Command as Command64 } from "commander";
8395
+ import { Command as Command65 } from "commander";
8179
8396
  import { defaultFetchModels } from "@harness-engineering/orchestrator";
8180
8397
  function errorResult(message, partial) {
8181
8398
  return {
@@ -8293,7 +8510,7 @@ function formatProbe(result) {
8293
8510
  return lines.join("\n");
8294
8511
  }
8295
8512
  function createModelsCommand() {
8296
- const cmd = new Command64("models").description(
8513
+ const cmd = new Command65("models").description(
8297
8514
  "Inspect and manage local LLM backends. Currently ships `probe`; LMLM phases add status/suggest/pool/proposals."
8298
8515
  );
8299
8516
  cmd.command("probe").description(
@@ -8319,9 +8536,9 @@ function createModelsCommand() {
8319
8536
  }
8320
8537
 
8321
8538
  // src/commands/naming-craft.ts
8322
- import { Command as Command65 } from "commander";
8539
+ import { Command as Command66 } from "commander";
8323
8540
  function createNamingCraftCommand() {
8324
- return new Command65("naming-craft").description(
8541
+ return new Command66("naming-craft").description(
8325
8542
  "LLM-judgment critique of identifier names (variables, functions, types, files). First craft-pipeline ceiling skill; uses curated rubric catalog from Martin/Beck/Karlton."
8326
8543
  ).option("-f, --files <files...>", "Optional file/glob scope").option(
8327
8544
  "-k, --kinds <kinds...>",
@@ -8371,10 +8588,10 @@ function printResult4(result, mode, _formatter) {
8371
8588
  list.push(f);
8372
8589
  byFile.set(f.target.file, list);
8373
8590
  }
8374
- for (const [file, fs48] of byFile) {
8591
+ for (const [file, fs49] of byFile) {
8375
8592
  console.log(`
8376
8593
  ${file}`);
8377
- for (const f of fs48) {
8594
+ for (const f of fs49) {
8378
8595
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
8379
8596
  console.log(
8380
8597
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.kind} ${f.target.identifier}${line}`
@@ -8394,13 +8611,13 @@ ${file}`);
8394
8611
  }
8395
8612
 
8396
8613
  // src/commands/notifications/index.ts
8397
- import { Command as Command67 } from "commander";
8614
+ import { Command as Command68 } from "commander";
8398
8615
 
8399
8616
  // src/commands/notifications/test.ts
8400
8617
  init_dist3();
8401
- import { Command as Command66 } from "commander";
8618
+ import { Command as Command67 } from "commander";
8402
8619
  import { randomBytes } from "crypto";
8403
- import { resolve as resolve28 } from "path";
8620
+ import { resolve as resolve29 } from "path";
8404
8621
  import { SinkRegistry, SinkConfigError, wrapAsEnvelope } from "@harness-engineering/orchestrator";
8405
8622
  function makeTestEvent(message) {
8406
8623
  return {
@@ -8450,9 +8667,9 @@ async function runNotificationsTest(sinkId, opts, projectRoot2 = process.cwd())
8450
8667
  return { ok: false, error: result.error };
8451
8668
  }
8452
8669
  function createNotificationsTestSubcommand() {
8453
- return new Command66("test").description("Send a synthetic notification.test event through the named sink").argument("<sink-id>", "Sink id from harness.config.json `notifications.sinks[].id`").option("--message <text>", "Override the default test message").action(async (sinkId, opts, cmd) => {
8670
+ return new Command67("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) => {
8454
8671
  const globalOpts = cmd.optsWithGlobals();
8455
- const projectRoot2 = typeof globalOpts["cwd"] === "string" ? resolve28(globalOpts["cwd"]) : process.cwd();
8672
+ const projectRoot2 = typeof globalOpts["cwd"] === "string" ? resolve29(globalOpts["cwd"]) : process.cwd();
8456
8673
  const result = await runNotificationsTest(sinkId, opts, projectRoot2);
8457
8674
  if (globalOpts["json"]) {
8458
8675
  console.log(JSON.stringify(result, null, 2));
@@ -8467,7 +8684,7 @@ function createNotificationsTestSubcommand() {
8467
8684
 
8468
8685
  // src/commands/notifications/index.ts
8469
8686
  function createNotificationsCommand() {
8470
- const cmd = new Command67("notifications").description(
8687
+ const cmd = new Command68("notifications").description(
8471
8688
  "Manage notification sinks (Slack and others)"
8472
8689
  );
8473
8690
  cmd.addCommand(createNotificationsTestSubcommand());
@@ -8475,13 +8692,13 @@ function createNotificationsCommand() {
8475
8692
  }
8476
8693
 
8477
8694
  // src/commands/orchestrator.ts
8478
- import { Command as Command68 } from "commander";
8479
- import * as path45 from "path";
8695
+ import { Command as Command69 } from "commander";
8696
+ import * as path46 from "path";
8480
8697
  import { Orchestrator, WorkflowLoader as WorkflowLoader2, launchTUI } from "@harness-engineering/orchestrator";
8481
8698
  function createOrchestratorCommand() {
8482
- const orchestrator = new Command68("orchestrator");
8699
+ const orchestrator = new Command69("orchestrator");
8483
8700
  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) => {
8484
- const workflowPath = path45.resolve(process.cwd(), opts.workflow);
8701
+ const workflowPath = path46.resolve(process.cwd(), opts.workflow);
8485
8702
  const loader = new WorkflowLoader2();
8486
8703
  const result = await loader.loadWorkflow(workflowPath);
8487
8704
  if (!result.ok) {
@@ -8515,13 +8732,13 @@ function createOrchestratorCommand() {
8515
8732
 
8516
8733
  // src/commands/perf.ts
8517
8734
  init_dist3();
8518
- import { Command as Command69 } from "commander";
8519
- import * as path46 from "path";
8735
+ import { Command as Command70 } from "commander";
8736
+ import * as path47 from "path";
8520
8737
  function registerBenchCommand(perf) {
8521
8738
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
8522
8739
  const globalOpts = cmd.optsWithGlobals();
8523
8740
  const cwd = process.cwd();
8524
- const { BenchmarkRunner } = await import("./dist-72ID44UE.js");
8741
+ const { BenchmarkRunner } = await import("./dist-LHINSVK4.js");
8525
8742
  const runner = new BenchmarkRunner();
8526
8743
  const benchFiles = runner.discover(cwd, glob2);
8527
8744
  if (benchFiles.length === 0) {
@@ -8585,7 +8802,7 @@ async function runBaselinesShow(globalOpts) {
8585
8802
  }
8586
8803
  async function runBaselinesUpdate(globalOpts) {
8587
8804
  const cwd = process.cwd();
8588
- const { BenchmarkRunner } = await import("./dist-72ID44UE.js");
8805
+ const { BenchmarkRunner } = await import("./dist-LHINSVK4.js");
8589
8806
  const runner = new BenchmarkRunner();
8590
8807
  const manager = new BaselineManager(cwd);
8591
8808
  logger.info("Running benchmarks to update baselines...");
@@ -8626,9 +8843,9 @@ function registerReportCommand(perf) {
8626
8843
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
8627
8844
  const globalOpts = cmd.optsWithGlobals();
8628
8845
  const cwd = process.cwd();
8629
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-72ID44UE.js");
8846
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-LHINSVK4.js");
8630
8847
  const analyzer = new EntropyAnalyzer2({
8631
- rootDir: path46.resolve(cwd),
8848
+ rootDir: path47.resolve(cwd),
8632
8849
  analyze: { complexity: true, coupling: true }
8633
8850
  });
8634
8851
  const result = await analyzer.analyze();
@@ -8687,7 +8904,7 @@ function registerCriticalPathsCommand(perf) {
8687
8904
  });
8688
8905
  }
8689
8906
  function createPerfCommand() {
8690
- const perf = new Command69("perf").description("Performance benchmark and baseline management");
8907
+ const perf = new Command70("perf").description("Performance benchmark and baseline management");
8691
8908
  registerBenchCommand(perf);
8692
8909
  registerBaselinesCommands(perf);
8693
8910
  registerReportCommand(perf);
@@ -8696,10 +8913,10 @@ function createPerfCommand() {
8696
8913
  }
8697
8914
 
8698
8915
  // src/commands/persona/index.ts
8699
- import { Command as Command72 } from "commander";
8916
+ import { Command as Command73 } from "commander";
8700
8917
 
8701
8918
  // src/commands/persona/list.ts
8702
- import { Command as Command70 } from "commander";
8919
+ import { Command as Command71 } from "commander";
8703
8920
  function printPersonaList(personas) {
8704
8921
  if (personas.length === 0) {
8705
8922
  logger.info("No personas found.");
@@ -8713,7 +8930,7 @@ function printPersonaList(personas) {
8713
8930
  }
8714
8931
  }
8715
8932
  function createListCommand2() {
8716
- return new Command70("list").description("List available agent personas").action(async (_opts, cmd) => {
8933
+ return new Command71("list").description("List available agent personas").action(async (_opts, cmd) => {
8717
8934
  const globalOpts = cmd.optsWithGlobals();
8718
8935
  const personasDir = resolvePersonasDir();
8719
8936
  const result = listPersonas(personasDir);
@@ -8733,17 +8950,17 @@ function createListCommand2() {
8733
8950
  }
8734
8951
 
8735
8952
  // src/commands/persona/generate.ts
8736
- import { Command as Command71 } from "commander";
8953
+ import { Command as Command72 } from "commander";
8737
8954
  import * as fs29 from "fs";
8738
- import * as path47 from "path";
8955
+ import * as path48 from "path";
8739
8956
  function generatePersonaArtifacts(persona, outputDir, only) {
8740
8957
  const slug = toKebabCase(persona.name);
8741
8958
  const generated = [];
8742
8959
  if (!only || only === "runtime") {
8743
8960
  const result = generateRuntime(persona);
8744
8961
  if (result.ok) {
8745
- const outPath = path47.join(outputDir, `${slug}.runtime.json`);
8746
- fs29.mkdirSync(path47.dirname(outPath), { recursive: true });
8962
+ const outPath = path48.join(outputDir, `${slug}.runtime.json`);
8963
+ fs29.mkdirSync(path48.dirname(outPath), { recursive: true });
8747
8964
  fs29.writeFileSync(outPath, result.value);
8748
8965
  generated.push(outPath);
8749
8966
  }
@@ -8751,7 +8968,7 @@ function generatePersonaArtifacts(persona, outputDir, only) {
8751
8968
  if (!only || only === "agents-md") {
8752
8969
  const result = generateAgentsMd(persona);
8753
8970
  if (result.ok) {
8754
- const outPath = path47.join(outputDir, `${slug}.agents.md`);
8971
+ const outPath = path48.join(outputDir, `${slug}.agents.md`);
8755
8972
  fs29.writeFileSync(outPath, result.value);
8756
8973
  generated.push(outPath);
8757
8974
  }
@@ -8759,8 +8976,8 @@ function generatePersonaArtifacts(persona, outputDir, only) {
8759
8976
  if (!only || only === "ci") {
8760
8977
  const result = generateCIWorkflow(persona, "github");
8761
8978
  if (result.ok) {
8762
- const outPath = path47.join(outputDir, ".github", "workflows", `${slug}.yml`);
8763
- fs29.mkdirSync(path47.dirname(outPath), { recursive: true });
8979
+ const outPath = path48.join(outputDir, ".github", "workflows", `${slug}.yml`);
8980
+ fs29.mkdirSync(path48.dirname(outPath), { recursive: true });
8764
8981
  fs29.writeFileSync(outPath, result.value);
8765
8982
  generated.push(outPath);
8766
8983
  }
@@ -8768,16 +8985,16 @@ function generatePersonaArtifacts(persona, outputDir, only) {
8768
8985
  return generated;
8769
8986
  }
8770
8987
  function createGenerateCommand3() {
8771
- return new Command71("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
8988
+ return new Command72("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) => {
8772
8989
  const globalOpts = cmd.optsWithGlobals();
8773
- const personaResult = loadPersona(path47.join(resolvePersonasDir(), `${name}.yaml`));
8990
+ const personaResult = loadPersona(path48.join(resolvePersonasDir(), `${name}.yaml`));
8774
8991
  if (!personaResult.ok) {
8775
8992
  logger.error(personaResult.error.message);
8776
8993
  process.exit(ExitCode.ERROR);
8777
8994
  }
8778
8995
  const generated = generatePersonaArtifacts(
8779
8996
  personaResult.value,
8780
- path47.resolve(opts.outputDir),
8997
+ path48.resolve(opts.outputDir),
8781
8998
  opts.only
8782
8999
  );
8783
9000
  if (!globalOpts.quiet) {
@@ -8790,7 +9007,7 @@ function createGenerateCommand3() {
8790
9007
 
8791
9008
  // src/commands/persona/index.ts
8792
9009
  function createPersonaCommand() {
8793
- const command = new Command72("persona").description("Agent persona management commands");
9010
+ const command = new Command73("persona").description("Agent persona management commands");
8794
9011
  command.addCommand(createListCommand2());
8795
9012
  command.addCommand(createGenerateCommand3());
8796
9013
  return command;
@@ -8798,7 +9015,7 @@ function createPersonaCommand() {
8798
9015
 
8799
9016
  // src/commands/predict.ts
8800
9017
  init_dist3();
8801
- import { Command as Command73 } from "commander";
9018
+ import { Command as Command74 } from "commander";
8802
9019
  import chalk11 from "chalk";
8803
9020
  var CATEGORY_ORDER = [
8804
9021
  "circular-deps",
@@ -8904,7 +9121,7 @@ function handlePredictError(err, mode) {
8904
9121
  process.exit(ExitCode.ERROR);
8905
9122
  }
8906
9123
  function createPredictCommand() {
8907
- const command = new Command73("predict").description("Predict which architectural constraints will break and when").option("--category <name>", "Filter to a single metric category").option("--no-roadmap", "Baseline only \u2014 skip roadmap spec impact").option("--horizon <weeks>", "Forecast horizon in weeks (default: 12)", "12").action(async (opts, cmd) => {
9124
+ const command = new Command74("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) => {
8908
9125
  const globalOpts = cmd.optsWithGlobals();
8909
9126
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
8910
9127
  try {
@@ -8928,10 +9145,10 @@ function createPredictCommand() {
8928
9145
 
8929
9146
  // src/commands/proposals.ts
8930
9147
  init_dist3();
8931
- import { Command as Command74 } from "commander";
8932
- import { resolve as resolve32 } from "path";
9148
+ import { Command as Command75 } from "commander";
9149
+ import { resolve as resolve33 } from "path";
8933
9150
  function projectRoot() {
8934
- return resolve32(process.env["HARNESS_PROJECT_ROOT"] ?? process.cwd());
9151
+ return resolve33(process.env["HARNESS_PROJECT_ROOT"] ?? process.cwd());
8935
9152
  }
8936
9153
  function summarizeProposal(p) {
8937
9154
  return {
@@ -9023,7 +9240,7 @@ async function actApproveCommand(id) {
9023
9240
  }
9024
9241
  }
9025
9242
  function createProposalsCommand() {
9026
- const cmd = new Command74("proposals").description("Skill-proposal review queue");
9243
+ const cmd = new Command75("proposals").description("Skill-proposal review queue");
9027
9244
  cmd.command("list").description("List skill proposals in the local queue").option(
9028
9245
  "--status <status>",
9029
9246
  `Filter by status \u2014 one of ${ALLOWED_STATUSES.join(" | ")}`,
@@ -9039,8 +9256,8 @@ function createProposalsCommand() {
9039
9256
 
9040
9257
  // src/commands/publish-analyses.ts
9041
9258
  import * as fs30 from "fs";
9042
- import * as path48 from "path";
9043
- import { Command as Command75 } from "commander";
9259
+ import * as path49 from "path";
9260
+ import { Command as Command76 } from "commander";
9044
9261
  init_dist3();
9045
9262
  import {
9046
9263
  renderAnalysisComment,
@@ -9048,7 +9265,7 @@ import {
9048
9265
  savePublishedIndex
9049
9266
  } from "@harness-engineering/orchestrator";
9050
9267
  function bootstrapTrackerCommand(opts, verb) {
9051
- const projectPath = path48.resolve(opts.dir);
9268
+ const projectPath = path49.resolve(opts.dir);
9052
9269
  const trackerConfig = loadTrackerSyncConfig(projectPath);
9053
9270
  if (!trackerConfig) {
9054
9271
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -9060,7 +9277,7 @@ function bootstrapTrackerCommand(opts, verb) {
9060
9277
  );
9061
9278
  return null;
9062
9279
  }
9063
- const projectEnvPath = path48.join(projectPath, ".env");
9280
+ const projectEnvPath = path49.join(projectPath, ".env");
9064
9281
  if (fs30.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
9065
9282
  __require("dotenv").config({ path: projectEnvPath });
9066
9283
  }
@@ -9097,7 +9314,7 @@ async function buildNameToExternalIdMap(projectPath) {
9097
9314
  }
9098
9315
  return fileLessMap;
9099
9316
  }
9100
- const roadmapFile = path48.join(projectPath, "docs", "roadmap.md");
9317
+ const roadmapFile = path49.join(projectPath, "docs", "roadmap.md");
9101
9318
  if (!fs30.existsSync(roadmapFile)) {
9102
9319
  logger.error("No docs/roadmap.md found. Cannot map issue hashes to external IDs.");
9103
9320
  return null;
@@ -9153,8 +9370,8 @@ async function runPublishAnalyses(opts) {
9153
9370
  const nameToExternalId = await buildNameToExternalIdMap(projectPath);
9154
9371
  if (!nameToExternalId) return process.exit(1);
9155
9372
  const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
9156
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-72ID44UE.js");
9157
- const archive = new AnalysisArchive(path48.join(projectPath, ".harness", "analyses"));
9373
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-LHINSVK4.js");
9374
+ const archive = new AnalysisArchive(path49.join(projectPath, ".harness", "analyses"));
9158
9375
  const analyses = await archive.list();
9159
9376
  if (analyses.length === 0) {
9160
9377
  logger.info("No analyses found to publish.");
@@ -9176,7 +9393,7 @@ async function runPublishAnalyses(opts) {
9176
9393
  }
9177
9394
  }
9178
9395
  function createPublishAnalysesCommand() {
9179
- const command = new Command75("publish-analyses").description(
9396
+ const command = new Command76("publish-analyses").description(
9180
9397
  "Publishes locally generated intelligence analyses to the external issue tracker (e.g., GitHub)"
9181
9398
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
9182
9399
  try {
@@ -9192,13 +9409,13 @@ function createPublishAnalysesCommand() {
9192
9409
  }
9193
9410
 
9194
9411
  // src/commands/pulse/index.ts
9195
- import { Command as Command77 } from "commander";
9412
+ import { Command as Command78 } from "commander";
9196
9413
 
9197
9414
  // src/commands/pulse/run.ts
9198
9415
  init_dist3();
9199
9416
  import { readFileSync as readFileSync19, mkdirSync as mkdirSync13, writeFileSync as writeFileSync16 } from "fs";
9200
- import { dirname as dirname18, join as join39, resolve as resolve34 } from "path";
9201
- import { Command as Command76 } from "commander";
9417
+ import { dirname as dirname18, join as join39, resolve as resolve35 } from "path";
9418
+ import { Command as Command77 } from "commander";
9202
9419
  async function runPulseRunCommand(opts) {
9203
9420
  const startedAt = Date.now();
9204
9421
  let raw;
@@ -9263,7 +9480,7 @@ function emit2(status, nonInteractive) {
9263
9480
  return status;
9264
9481
  }
9265
9482
  function createRunCommand2() {
9266
- return new Command76("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
9483
+ return new Command77("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
9267
9484
  "--lookback <window>",
9268
9485
  "Lookback window (e.g. 24h, 7d). Defaults to pulse.lookbackDefault."
9269
9486
  ).option(
@@ -9273,8 +9490,8 @@ function createRunCommand2() {
9273
9490
  async (options) => {
9274
9491
  const nonInteractive = options.nonInteractive === true || !process.stdout.isTTY;
9275
9492
  const status = await runPulseRunCommand({
9276
- configPath: resolve34(process.cwd(), options.config),
9277
- outputDir: resolve34(process.cwd(), options.outputDir),
9493
+ configPath: resolve35(process.cwd(), options.config),
9494
+ outputDir: resolve35(process.cwd(), options.outputDir),
9278
9495
  nonInteractive,
9279
9496
  lookback: options.lookback
9280
9497
  });
@@ -9287,13 +9504,13 @@ function createRunCommand2() {
9287
9504
 
9288
9505
  // src/commands/pulse/index.ts
9289
9506
  function createPulseCommand() {
9290
- const command = new Command77("pulse").description("Pulse (read-side observability) commands");
9507
+ const command = new Command78("pulse").description("Pulse (read-side observability) commands");
9291
9508
  command.addCommand(createRunCommand2());
9292
9509
  return command;
9293
9510
  }
9294
9511
 
9295
9512
  // src/commands/recommend.ts
9296
- import { Command as Command78 } from "commander";
9513
+ import { Command as Command79 } from "commander";
9297
9514
  import chalk12 from "chalk";
9298
9515
  async function resolveSnapshot(cwd, noCache) {
9299
9516
  if (!noCache) {
@@ -9357,7 +9574,7 @@ function printRecommendations(result) {
9357
9574
  console.log("");
9358
9575
  }
9359
9576
  function createRecommendCommand() {
9360
- const command = new Command78("recommend").description("Recommend skills based on codebase health analysis").option("--no-cache", "Force fresh health snapshot").option("--top <n>", "Max recommendations (default 5)", "5").action(async (opts, cmd) => {
9577
+ const command = new Command79("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) => {
9361
9578
  const globalOpts = cmd.optsWithGlobals();
9362
9579
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
9363
9580
  try {
@@ -9392,19 +9609,197 @@ function createRecommendCommand() {
9392
9609
  return command;
9393
9610
  }
9394
9611
 
9612
+ // src/commands/review-ci.ts
9613
+ init_dist3();
9614
+ import { execFileSync as execFileSync5 } from "child_process";
9615
+ import { writeFileSync as writeFileSync17 } from "fs";
9616
+ import { Command as Command80, Option } from "commander";
9617
+
9618
+ // src/commands/review-ci-local-adapter.ts
9619
+ import { z } from "zod";
9620
+ import { OpenAICompatibleAnalysisProvider } from "@harness-engineering/intelligence";
9621
+ var FindingSchema = z.object({
9622
+ id: z.string(),
9623
+ file: z.string(),
9624
+ lineRange: z.tuple([z.number(), z.number()]),
9625
+ domain: z.enum(["compliance", "bug", "security", "architecture", "learnings"]),
9626
+ severity: z.enum(["critical", "important", "suggestion"]),
9627
+ title: z.string(),
9628
+ rationale: z.string(),
9629
+ suggestion: z.string().optional(),
9630
+ evidence: z.array(z.string())
9631
+ });
9632
+ var LocalVerdictSchema = z.object({
9633
+ assessment: z.enum(["approve", "comment", "request-changes"]),
9634
+ findings: z.array(FindingSchema)
9635
+ });
9636
+ var MAX_SURFACED_ERROR_LEN = 200;
9637
+ function sanitizeProviderError(err) {
9638
+ const raw = err instanceof Error ? err.message : String(err);
9639
+ const redacted = raw.replace(/https?:\/\/\S+/gi, "[endpoint]").replace(/\b(bearer|authorization|api[-_]?key|token)\b\s*[:=]?\s*\S+/gi, "[redacted]").replace(/\s+/g, " ").trim();
9640
+ const capped = redacted.length > MAX_SURFACED_ERROR_LEN ? redacted.slice(0, MAX_SURFACED_ERROR_LEN - 1) + "\u2026" : redacted;
9641
+ return `local runner provider error: ${capped}`;
9642
+ }
9643
+ function createLocalInvoke() {
9644
+ return async ({ endpoint, model, instruction, diff: diff2 }) => {
9645
+ if (!/^https?:\/\//i.test(endpoint)) {
9646
+ throw new Error(
9647
+ `HARNESS_LOCAL_ENDPOINT must be an http(s) URL (got '${endpoint}'); e.g. http://localhost:1234/v1`
9648
+ );
9649
+ }
9650
+ const provider = new OpenAICompatibleAnalysisProvider({
9651
+ apiKey: process.env.HARNESS_LOCAL_API_KEY ?? "local",
9652
+ baseUrl: endpoint,
9653
+ defaultModel: model
9654
+ });
9655
+ try {
9656
+ const { result } = await provider.analyze({
9657
+ prompt: `${instruction}
9658
+
9659
+ ---
9660
+ DIFF UNDER REVIEW:
9661
+ ${diff2}`,
9662
+ responseSchema: LocalVerdictSchema,
9663
+ model
9664
+ });
9665
+ return JSON.stringify(result);
9666
+ } catch (err) {
9667
+ throw new Error(sanitizeProviderError(err), { cause: err });
9668
+ }
9669
+ };
9670
+ }
9671
+
9672
+ // src/commands/review-ci.ts
9673
+ var KNOWN_RUNNERS = Object.keys(RUNNER_PRESETS);
9674
+ var BLOCK_ON_LEVELS = [...CI_ASSESSMENTS, "none"];
9675
+ function assertKnownRunner(runner) {
9676
+ if (runner === void 0) return;
9677
+ if (!KNOWN_RUNNERS.includes(runner)) {
9678
+ throw new Error(`unknown runner '${runner}' (expected: ${KNOWN_RUNNERS.join("|")})`);
9679
+ }
9680
+ }
9681
+ var defaultRunGit = (args) => execFileSync5("git", args, { encoding: "utf-8" }).toString().trim();
9682
+ function resolveDiffRange(opts) {
9683
+ if (opts.range) return opts.range;
9684
+ const runGit = opts.runGit ?? defaultRunGit;
9685
+ let base = "main";
9686
+ try {
9687
+ const ref = runGit(["symbolic-ref", "refs/remotes/origin/HEAD"]);
9688
+ const m = ref.match(/origin\/(.+)$/);
9689
+ if (m?.[1]) base = m[1];
9690
+ } catch {
9691
+ }
9692
+ return `origin/${base}...HEAD`;
9693
+ }
9694
+ function splitDiffByFile(rawDiff) {
9695
+ const sections = /* @__PURE__ */ new Map();
9696
+ const headerRe = /^diff --git a\/(.+?) b\/(.+?)$/;
9697
+ let currentPath = null;
9698
+ let buffer = [];
9699
+ const flush = () => {
9700
+ if (currentPath !== null) sections.set(currentPath, buffer.join("\n"));
9701
+ };
9702
+ for (const line of rawDiff.split("\n")) {
9703
+ const m = line.match(headerRe);
9704
+ if (m?.[2]) {
9705
+ flush();
9706
+ currentPath = m[2];
9707
+ buffer = [line];
9708
+ } else if (currentPath !== null) {
9709
+ buffer.push(line);
9710
+ }
9711
+ }
9712
+ flush();
9713
+ return sections;
9714
+ }
9715
+ function buildDiffInfo(rawDiff) {
9716
+ const parsed = parseDiff(rawDiff);
9717
+ if (!parsed.ok) throw new Error(`Failed to parse diff: ${parsed.error.message}`);
9718
+ const files = parsed.value.files;
9719
+ const perFile = splitDiffByFile(rawDiff);
9720
+ return {
9721
+ changedFiles: files.map((f) => f.path),
9722
+ newFiles: files.filter((f) => f.status === "added").map((f) => f.path),
9723
+ deletedFiles: files.filter((f) => f.status === "deleted").map((f) => f.path),
9724
+ totalDiffLines: rawDiff ? rawDiff.split("\n").length : 0,
9725
+ // On a path-key miss, fall back to '' (the file contributes no per-file diff)
9726
+ // rather than the ENTIRE raw diff — substituting the whole diff would duplicate
9727
+ // every file's content into one section, inflating the STDIN payload to the LLM
9728
+ // (and risking core's execMaxStdoutBytes). With splitDiffByFile aligned to core's
9729
+ // path extraction, ordinary paths never miss; this is the safe degenerate case.
9730
+ fileDiffs: new Map(files.map((f) => [f.path, perFile.get(f.path) ?? ""]))
9731
+ };
9732
+ }
9733
+ function defaultResolveRaw(range, _cwd, runGit) {
9734
+ return runGit(["diff", range]);
9735
+ }
9736
+ function buildCallOpts(opts, cwd, diff2) {
9737
+ const runner = opts.runner;
9738
+ return {
9739
+ projectRoot: cwd,
9740
+ diff: diff2,
9741
+ ...runner ? { runner } : {},
9742
+ ...opts.blockOn ? { blockOn: opts.blockOn } : {},
9743
+ ...runner === "local" ? { localInvoke: opts.localInvoke ?? createLocalInvoke() } : {}
9744
+ };
9745
+ }
9746
+ async function runReviewCi(opts) {
9747
+ assertKnownRunner(opts.runner);
9748
+ const cwd = opts.cwd ?? process.cwd();
9749
+ const runGit = opts.runGit ?? defaultRunGit;
9750
+ const range = resolveDiffRange({
9751
+ ...opts.diffRange ? { range: opts.diffRange } : {},
9752
+ cwd,
9753
+ runGit
9754
+ });
9755
+ const rawDiff = (opts.resolveRaw ?? defaultResolveRaw)(range, cwd, runGit);
9756
+ const diff2 = buildDiffInfo(rawDiff);
9757
+ const callOpts = buildCallOpts(opts, cwd, diff2);
9758
+ return (opts.runCiReviewImpl ?? runCiReview)(callOpts);
9759
+ }
9760
+ function emitReviewCi(result, opts, writeFile = (p, d) => writeFileSync17(p, d), log = (m) => process.stdout.write(m + "\n")) {
9761
+ log(result.terminalOutput);
9762
+ if (opts.jsonPath) writeFile(opts.jsonPath, JSON.stringify(result.verdict, null, 2));
9763
+ if (opts.comment) {
9764
+ logger.warn(
9765
+ "review-ci: --comment posting is not yet wired (no gh PR poster; Phase 3 stub). The verdict above is authoritative; use --json to capture the artifact. PR-review posting lands in a later phase."
9766
+ );
9767
+ }
9768
+ }
9769
+ function createReviewCiCommand() {
9770
+ return new Command80("review-ci").description("Run the tiered code-review gate (floor + optional LLM runner) for CI").addOption(
9771
+ new Option("--runner <runner>", `${KNOWN_RUNNERS.join(" | ")} (omit = floor-only)`).choices(
9772
+ KNOWN_RUNNERS
9773
+ )
9774
+ ).addOption(
9775
+ new Option("--block-on <level>", BLOCK_ON_LEVELS.join(" | ")).choices(BLOCK_ON_LEVELS).default("request-changes")
9776
+ ).option("--diff <range>", "git range (default: origin/<base>...HEAD)").option("--comment", "post verdict as a PR review (stubbed in this phase)").option("--json <path>", "write the verdict artifact to this path").action(async (opts) => {
9777
+ const result = await runReviewCi({
9778
+ runner: opts.runner,
9779
+ blockOn: opts.blockOn,
9780
+ diffRange: opts.diff
9781
+ });
9782
+ emitReviewCi(result, {
9783
+ jsonPath: opts.json,
9784
+ comment: opts.comment
9785
+ });
9786
+ process.exit(result.exitCode);
9787
+ });
9788
+ }
9789
+
9395
9790
  // src/commands/roadmap/index.ts
9396
- import { Command as Command80 } from "commander";
9791
+ import { Command as Command82 } from "commander";
9397
9792
 
9398
9793
  // src/commands/roadmap/migrate.ts
9399
9794
  init_dist3();
9400
- import { Command as Command79 } from "commander";
9795
+ import { Command as Command81 } from "commander";
9401
9796
  import * as fs32 from "fs";
9402
- import * as path50 from "path";
9797
+ import * as path51 from "path";
9403
9798
  import chalk13 from "chalk";
9404
9799
 
9405
9800
  // src/commands/roadmap/migrate-lock.ts
9406
9801
  import * as fs31 from "fs";
9407
- import * as path49 from "path";
9802
+ import * as path50 from "path";
9408
9803
  import * as os6 from "os";
9409
9804
  var LOCK_FILE_NAME = "migrate.lock";
9410
9805
  var STALE_LOCK_MS = 30 * 60 * 1e3;
@@ -9418,8 +9813,8 @@ function isPidAlive(pid) {
9418
9813
  }
9419
9814
  }
9420
9815
  function acquireMigrateLock(projectRoot2) {
9421
- const harnessDir = path49.join(projectRoot2, ".harness");
9422
- const lockPath = path49.join(harnessDir, LOCK_FILE_NAME);
9816
+ const harnessDir = path50.join(projectRoot2, ".harness");
9817
+ const lockPath = path50.join(harnessDir, LOCK_FILE_NAME);
9423
9818
  if (!fs31.existsSync(harnessDir)) fs31.mkdirSync(harnessDir, { recursive: true });
9424
9819
  if (fs31.existsSync(lockPath)) {
9425
9820
  const existingRaw = (() => {
@@ -9618,7 +10013,7 @@ async function runRoadmapMigrate(opts) {
9618
10013
  if (!clientR.ok) return Err(new CLIError(clientR.error.message));
9619
10014
  client = clientR.value;
9620
10015
  }
9621
- const roadmapPath = path50.join(cwd, "docs", "roadmap.md");
10016
+ const roadmapPath = path51.join(cwd, "docs", "roadmap.md");
9622
10017
  if (!fs32.existsSync(roadmapPath)) {
9623
10018
  return Err(new CLIError(`docs/roadmap.md not found in ${cwd}`));
9624
10019
  }
@@ -9667,7 +10062,7 @@ async function runRoadmapMigrate(opts) {
9667
10062
  }
9668
10063
  }
9669
10064
  function createRoadmapMigrateCommand() {
9670
- return new Command79("migrate").description("Migrate the project roadmap to a different storage mode").requiredOption("--to <target>", 'Migration target (only "file-less" supported today)').option("--dry-run", "Print the migration plan without making any changes", false).option(
10065
+ return new Command81("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(
9671
10066
  "--format <fmt>",
9672
10067
  'Output format: "human" (default) or "json" (single JSON object for CI consumers)',
9673
10068
  "human"
@@ -9702,16 +10097,16 @@ function createRoadmapMigrateCommand() {
9702
10097
 
9703
10098
  // src/commands/roadmap/index.ts
9704
10099
  function createRoadmapCommand() {
9705
- const roadmap = new Command80("roadmap").description("Roadmap management");
10100
+ const roadmap = new Command82("roadmap").description("Roadmap management");
9706
10101
  roadmap.addCommand(createRoadmapMigrateCommand());
9707
10102
  return roadmap;
9708
10103
  }
9709
10104
 
9710
10105
  // src/commands/routing/index.ts
9711
- import { Command as Command84 } from "commander";
10106
+ import { Command as Command86 } from "commander";
9712
10107
 
9713
10108
  // src/commands/routing/config.ts
9714
- import { Command as Command81 } from "commander";
10109
+ import { Command as Command83 } from "commander";
9715
10110
 
9716
10111
  // src/commands/routing/http-client.ts
9717
10112
  function orchestratorBase() {
@@ -9721,9 +10116,9 @@ function authHeader() {
9721
10116
  const tok = process.env["HARNESS_API_TOKEN"];
9722
10117
  return tok ? { Authorization: `Bearer ${tok}` } : {};
9723
10118
  }
9724
- async function getJson(path72) {
10119
+ async function getJson(path73) {
9725
10120
  try {
9726
- const res = await fetch(`${orchestratorBase()}${path72}`, {
10121
+ const res = await fetch(`${orchestratorBase()}${path73}`, {
9727
10122
  headers: { ...authHeader() }
9728
10123
  });
9729
10124
  const text = await res.text();
@@ -9738,9 +10133,9 @@ async function getJson(path72) {
9738
10133
  };
9739
10134
  }
9740
10135
  }
9741
- async function postJson(path72, body) {
10136
+ async function postJson(path73, body) {
9742
10137
  try {
9743
- const res = await fetch(`${orchestratorBase()}${path72}`, {
10138
+ const res = await fetch(`${orchestratorBase()}${path73}`, {
9744
10139
  method: "POST",
9745
10140
  headers: { "Content-Type": "application/json", ...authHeader() },
9746
10141
  body: JSON.stringify(body)
@@ -9776,7 +10171,7 @@ function renderHuman(data) {
9776
10171
  }
9777
10172
  }
9778
10173
  function createConfigCommand() {
9779
- return new Command81("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
10174
+ return new Command83("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
9780
10175
  const r = await getJson("/api/v1/routing/config");
9781
10176
  if (!r.ok) {
9782
10177
  if (r.status === 0) {
@@ -9802,7 +10197,7 @@ function createConfigCommand() {
9802
10197
  }
9803
10198
 
9804
10199
  // src/commands/routing/trace.ts
9805
- import { Command as Command82 } from "commander";
10200
+ import { Command as Command84 } from "commander";
9806
10201
  function buildUseCase(opts) {
9807
10202
  if (opts.skill) {
9808
10203
  return opts.mode ? { kind: "skill", skillName: opts.skill, cognitiveMode: opts.mode } : { kind: "skill", skillName: opts.skill };
@@ -9823,7 +10218,7 @@ function renderHuman2(r) {
9823
10218
  }
9824
10219
  }
9825
10220
  function createTraceCommand() {
9826
- return new Command82("trace").description("Dry-run a routing decision without dispatching (Spec B F7)").option("--skill <name>", "Skill name to trace").option("--mode <m>", "Cognitive mode to trace (or attach to --skill per spec D12)").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
10221
+ return new Command84("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) => {
9827
10222
  const useCase = buildUseCase(opts);
9828
10223
  if (!useCase) {
9829
10224
  logger.error("Either --skill <name> or --mode <m> is required");
@@ -9855,7 +10250,7 @@ function createTraceCommand() {
9855
10250
  }
9856
10251
 
9857
10252
  // src/commands/routing/decisions.ts
9858
- import { Command as Command83 } from "commander";
10253
+ import { Command as Command85 } from "commander";
9859
10254
  function summarizeUseCase(uc) {
9860
10255
  switch (uc.kind) {
9861
10256
  case "skill":
@@ -9903,7 +10298,7 @@ function buildQuery(opts) {
9903
10298
  return q ? `?${q}` : "";
9904
10299
  }
9905
10300
  function createDecisionsCommand() {
9906
- return new Command83("decisions").description("List recent routing decisions from the orchestrator ring buffer (Spec B F8)").option("--skill <name>", "Filter by useCase.skillName").option("--mode <m>", "Filter by useCase.cognitiveMode").option("--backend <name>", "Filter by chosen backendName").option("--last <N>", "Limit to the N most recent decisions").option("--json", "Emit JSON to stdout instead of human-readable text").action(
10301
+ return new Command85("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(
9907
10302
  async (opts) => {
9908
10303
  const query = buildQuery(opts);
9909
10304
  const r = await getJson(`/api/v1/routing/decisions${query}`);
@@ -9933,7 +10328,7 @@ function createDecisionsCommand() {
9933
10328
 
9934
10329
  // src/commands/routing/index.ts
9935
10330
  function createRoutingCommand() {
9936
- const cmd = new Command84("routing").description(
10331
+ const cmd = new Command86("routing").description(
9937
10332
  "Inspect routing config, trace decisions, and read recent dispatches"
9938
10333
  );
9939
10334
  cmd.addCommand(createConfigCommand());
@@ -9944,8 +10339,8 @@ function createRoutingCommand() {
9944
10339
 
9945
10340
  // src/commands/scan-config.ts
9946
10341
  init_dist3();
9947
- import { Command as Command85 } from "commander";
9948
- import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "fs";
10342
+ import { Command as Command87 } from "commander";
10343
+ import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync20 } from "fs";
9949
10344
  import { join as join42, relative as relative3 } from "path";
9950
10345
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
9951
10346
  function stripHighSeverityPatterns(content, injectionFindings) {
@@ -9972,7 +10367,7 @@ function applyFix(filePath, targetDir, content, injectionFindings) {
9972
10367
  if (!hasHighSeverity) return;
9973
10368
  const { cleaned, linesStripped } = stripHighSeverityPatterns(content, injectionFindings);
9974
10369
  if (linesStripped > 0) {
9975
- writeFileSync19(filePath, cleaned);
10370
+ writeFileSync20(filePath, cleaned);
9976
10371
  logger.info(
9977
10372
  `scan-config --fix: stripped ${linesStripped} high-severity line(s) from ${relative3(targetDir, filePath).replaceAll("\\", "/")}`
9978
10373
  );
@@ -10033,7 +10428,7 @@ function formatTextOutput(result) {
10033
10428
  }
10034
10429
  }
10035
10430
  function createScanConfigCommand() {
10036
- const command = new Command85("scan-config").description(
10431
+ const command = new Command87("scan-config").description(
10037
10432
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
10038
10433
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
10039
10434
  const globalOpts = cmd.optsWithGlobals();
@@ -10051,7 +10446,7 @@ function createScanConfigCommand() {
10051
10446
 
10052
10447
  // src/commands/search.ts
10053
10448
  init_dist();
10054
- import { Command as Command86 } from "commander";
10449
+ import { Command as Command88 } from "commander";
10055
10450
  function parseFileKinds(raw) {
10056
10451
  if (!raw) return void 0;
10057
10452
  const set = /* @__PURE__ */ new Set();
@@ -10072,7 +10467,7 @@ function fmtBytes(n) {
10072
10467
  return n.toFixed(0);
10073
10468
  }
10074
10469
  function createSearchCommand() {
10075
- return new Command86("search").description("Full-text search over archived + live session content.").argument(
10470
+ return new Command88("search").description("Full-text search over archived + live session content.").argument(
10076
10471
  "<query>",
10077
10472
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
10078
10473
  ).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(
@@ -10132,9 +10527,9 @@ function createSearchCommand() {
10132
10527
  }
10133
10528
 
10134
10529
  // src/commands/security-craft.ts
10135
- import { Command as Command87 } from "commander";
10530
+ import { Command as Command89 } from "commander";
10136
10531
  function createSecurityCraftCommand() {
10137
- return new Command87("security-craft").description(
10532
+ return new Command89("security-craft").description(
10138
10533
  "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."
10139
10534
  ).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) => {
10140
10535
  const globalOpts = cmd.optsWithGlobals();
@@ -10181,10 +10576,10 @@ function printResult5(result, mode, _formatter) {
10181
10576
  list.push(f);
10182
10577
  byFile.set(f.target.file, list);
10183
10578
  }
10184
- for (const [file, fs48] of byFile) {
10579
+ for (const [file, fs49] of byFile) {
10185
10580
  console.log(`
10186
10581
  ${file}`);
10187
- for (const f of fs48) {
10582
+ for (const f of fs49) {
10188
10583
  console.log(
10189
10584
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.signal}:${f.target.line}`
10190
10585
  );
@@ -10200,18 +10595,18 @@ ${file}`);
10200
10595
  }
10201
10596
 
10202
10597
  // src/commands/setup.ts
10203
- import { Command as Command88 } from "commander";
10598
+ import { Command as Command90 } from "commander";
10204
10599
  import * as fs35 from "fs";
10205
10600
  import * as os8 from "os";
10206
- import * as path53 from "path";
10601
+ import * as path54 from "path";
10207
10602
  import chalk15 from "chalk";
10208
10603
 
10209
10604
  // src/utils/first-run.ts
10210
10605
  import * as fs33 from "fs";
10211
10606
  import * as os7 from "os";
10212
- import * as path51 from "path";
10213
- var HARNESS_DIR = path51.join(os7.homedir(), ".harness");
10214
- var MARKER_FILE = path51.join(HARNESS_DIR, ".setup-complete");
10607
+ import * as path52 from "path";
10608
+ var HARNESS_DIR = path52.join(os7.homedir(), ".harness");
10609
+ var MARKER_FILE = path52.join(HARNESS_DIR, ".setup-complete");
10215
10610
  function isFirstRun() {
10216
10611
  return !fs33.existsSync(MARKER_FILE);
10217
10612
  }
@@ -10231,7 +10626,7 @@ function printFirstRunWelcome() {
10231
10626
 
10232
10627
  // src/commands/telemetry-wizard.ts
10233
10628
  import * as fs34 from "fs";
10234
- import * as path52 from "path";
10629
+ import * as path53 from "path";
10235
10630
  import readline2 from "readline";
10236
10631
  import chalk14 from "chalk";
10237
10632
  function prompt2(question) {
@@ -10239,10 +10634,10 @@ function prompt2(question) {
10239
10634
  input: process.stdin,
10240
10635
  output: process.stdout
10241
10636
  });
10242
- return new Promise((resolve46) => {
10637
+ return new Promise((resolve47) => {
10243
10638
  rl.question(question, (answer) => {
10244
10639
  rl.close();
10245
- resolve46(answer.trim().toLowerCase());
10640
+ resolve47(answer.trim().toLowerCase());
10246
10641
  });
10247
10642
  });
10248
10643
  }
@@ -10251,10 +10646,10 @@ function promptRaw(question) {
10251
10646
  input: process.stdin,
10252
10647
  output: process.stdout
10253
10648
  });
10254
- return new Promise((resolve46) => {
10649
+ return new Promise((resolve47) => {
10255
10650
  rl.question(question, (answer) => {
10256
10651
  rl.close();
10257
- resolve46(answer.trim());
10652
+ resolve47(answer.trim());
10258
10653
  });
10259
10654
  });
10260
10655
  }
@@ -10262,7 +10657,7 @@ function isNo(answer) {
10262
10657
  return answer === "n" || answer === "no";
10263
10658
  }
10264
10659
  function isTelemetryConfigured(cwd) {
10265
- const configPath = path52.join(cwd, "harness.config.json");
10660
+ const configPath = path53.join(cwd, "harness.config.json");
10266
10661
  try {
10267
10662
  const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
10268
10663
  return raw.telemetry !== void 0 && raw.adoption !== void 0;
@@ -10271,7 +10666,7 @@ function isTelemetryConfigured(cwd) {
10271
10666
  }
10272
10667
  }
10273
10668
  function writeTelemetryConfig(cwd, result) {
10274
- const configPath = path52.join(cwd, "harness.config.json");
10669
+ const configPath = path53.join(cwd, "harness.config.json");
10275
10670
  try {
10276
10671
  const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
10277
10672
  raw.telemetry = { enabled: result.telemetryEnabled };
@@ -10284,9 +10679,9 @@ function writeTelemetryConfig(cwd, result) {
10284
10679
  }
10285
10680
  const hasIdentity = result.identity.project || result.identity.team || result.identity.alias;
10286
10681
  if (hasIdentity) {
10287
- const harnessDir = path52.join(cwd, ".harness");
10682
+ const harnessDir = path53.join(cwd, ".harness");
10288
10683
  fs34.mkdirSync(harnessDir, { recursive: true });
10289
- const telemetryFile = path52.join(harnessDir, "telemetry.json");
10684
+ const telemetryFile = path53.join(harnessDir, "telemetry.json");
10290
10685
  fs34.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
10291
10686
  }
10292
10687
  }
@@ -10333,7 +10728,7 @@ async function runTelemetryWizard() {
10333
10728
  return { telemetryEnabled, adoptionEnabled, identity };
10334
10729
  }
10335
10730
  async function ensureTelemetryConfigured(cwd) {
10336
- const configPath = path52.join(cwd, "harness.config.json");
10731
+ const configPath = path53.join(cwd, "harness.config.json");
10337
10732
  if (!fs34.existsSync(configPath)) {
10338
10733
  return { status: "warn", message: "Not a harness project \u2014 skipped telemetry configuration" };
10339
10734
  }
@@ -10380,7 +10775,7 @@ function runSlashCommandGeneration() {
10380
10775
  }
10381
10776
  }
10382
10777
  function detectClient(dirName) {
10383
- return fs35.existsSync(path53.join(os8.homedir(), dirName));
10778
+ return fs35.existsSync(path54.join(os8.homedir(), dirName));
10384
10779
  }
10385
10780
  async function runMcpSetup(cwd) {
10386
10781
  const results = [];
@@ -10396,7 +10791,7 @@ async function runMcpSetup(cwd) {
10396
10791
  { name: "Cursor", dir: ".cursor", client: "cursor", configTarget: ".cursor/mcp.json" },
10397
10792
  {
10398
10793
  name: "OpenCode",
10399
- dir: path53.join(".config", "opencode"),
10794
+ dir: path54.join(".config", "opencode"),
10400
10795
  client: "opencode",
10401
10796
  configTarget: "opencode.json"
10402
10797
  }
@@ -10428,7 +10823,7 @@ function formatStep(result) {
10428
10823
  }
10429
10824
  function configureTier0Integrations(cwd) {
10430
10825
  try {
10431
- const mcpPath = path53.join(cwd, ".mcp.json");
10826
+ const mcpPath = path54.join(cwd, ".mcp.json");
10432
10827
  const config = readMcpConfig(mcpPath);
10433
10828
  const tier0 = INTEGRATION_REGISTRY.filter((i) => i.tier === 0);
10434
10829
  const added = [];
@@ -10437,9 +10832,9 @@ function configureTier0Integrations(cwd) {
10437
10832
  writeMcpEntry(mcpPath, integration.name, integration.mcpConfig);
10438
10833
  added.push(integration.displayName);
10439
10834
  }
10440
- const geminiDir = path53.join(cwd, ".gemini");
10835
+ const geminiDir = path54.join(cwd, ".gemini");
10441
10836
  if (fs35.existsSync(geminiDir)) {
10442
- const geminiPath = path53.join(geminiDir, "settings.json");
10837
+ const geminiPath = path54.join(geminiDir, "settings.json");
10443
10838
  const geminiConfig = readMcpConfig(geminiPath);
10444
10839
  for (const integration of tier0) {
10445
10840
  if (!geminiConfig.mcpServers[integration.name]) {
@@ -10447,8 +10842,8 @@ function configureTier0Integrations(cwd) {
10447
10842
  }
10448
10843
  }
10449
10844
  }
10450
- const opencodePath = path53.join(cwd, "opencode.json");
10451
- const opencodeGlobalDir = path53.join(os8.homedir(), ".config", "opencode");
10845
+ const opencodePath = path54.join(cwd, "opencode.json");
10846
+ const opencodeGlobalDir = path54.join(os8.homedir(), ".config", "opencode");
10452
10847
  if (fs35.existsSync(opencodePath) || fs35.existsSync(opencodeGlobalDir)) {
10453
10848
  for (const integration of tier0) {
10454
10849
  writeOpencodeMcpEntry(opencodePath, integration.name, integration.mcpConfig);
@@ -10467,12 +10862,12 @@ function configureTier0Integrations(cwd) {
10467
10862
  }
10468
10863
  }
10469
10864
  function ensureHooks(cwd) {
10470
- const configPath = path53.join(cwd, "harness.config.json");
10865
+ const configPath = path54.join(cwd, "harness.config.json");
10471
10866
  if (!fs35.existsSync(configPath)) {
10472
10867
  return { status: "warn", message: "Not a harness project \u2014 skipped hook installation" };
10473
10868
  }
10474
10869
  let profile = "standard";
10475
- const profilePath = path53.join(cwd, ".harness", "hooks", "profile.json");
10870
+ const profilePath = path54.join(cwd, ".harness", "hooks", "profile.json");
10476
10871
  try {
10477
10872
  const data = JSON.parse(fs35.readFileSync(profilePath, "utf-8"));
10478
10873
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
@@ -10506,7 +10901,7 @@ async function detectLegacyLayout(cwd) {
10506
10901
  }
10507
10902
  async function runInitialGraphScan(cwd) {
10508
10903
  try {
10509
- const { runScan: runScan2 } = await import("./scan-LYKLM4EQ.js");
10904
+ const { runScan: runScan2 } = await import("./scan-P7YFKB77.js");
10510
10905
  const result = await runScan2(cwd);
10511
10906
  return {
10512
10907
  status: "pass",
@@ -10545,7 +10940,7 @@ async function runSetup(cwd) {
10545
10940
  return { steps, success };
10546
10941
  }
10547
10942
  function createSetupCommand() {
10548
- return new Command88("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
10943
+ return new Command90("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
10549
10944
  const cwd = process.cwd();
10550
10945
  console.log("");
10551
10946
  console.log(` ${chalk15.bold("harness setup")}`);
@@ -10568,14 +10963,14 @@ function createSetupCommand() {
10568
10963
 
10569
10964
  // src/commands/share.ts
10570
10965
  init_dist3();
10571
- import { Command as Command89 } from "commander";
10966
+ import { Command as Command91 } from "commander";
10572
10967
  import * as fs36 from "fs";
10573
- import * as path54 from "path";
10968
+ import * as path55 from "path";
10574
10969
  import { parse as parseYaml3 } from "yaml";
10575
10970
  var MANIFEST_FILENAME = "constraints.yaml";
10576
10971
  async function runShareAction(projectPath, options) {
10577
- const rootDir = path54.resolve(projectPath);
10578
- const manifestPath = path54.join(rootDir, MANIFEST_FILENAME);
10972
+ const rootDir = path55.resolve(projectPath);
10973
+ const manifestPath = path55.join(rootDir, MANIFEST_FILENAME);
10579
10974
  if (!fs36.existsSync(manifestPath)) {
10580
10975
  logger.error(
10581
10976
  `No ${MANIFEST_FILENAME} found at ${manifestPath}.
@@ -10599,7 +10994,7 @@ Create a constraints.yaml in your project root to define what to share.`
10599
10994
  process.exit(1);
10600
10995
  }
10601
10996
  const manifest = manifestResult.value;
10602
- const configResult = resolveConfig(path54.join(rootDir, "harness.config.json"));
10997
+ const configResult = resolveConfig(path55.join(rootDir, "harness.config.json"));
10603
10998
  if (!configResult.ok) {
10604
10999
  logger.error(configResult.error.message);
10605
11000
  process.exit(1);
@@ -10617,8 +11012,8 @@ Create a constraints.yaml in your project root to define what to share.`
10617
11012
  );
10618
11013
  process.exit(1);
10619
11014
  }
10620
- const outputDir = path54.resolve(options.output);
10621
- const outputPath = path54.join(outputDir, `${manifest.name}.harness-constraints.json`);
11015
+ const outputDir = path55.resolve(options.output);
11016
+ const outputPath = path55.join(outputDir, `${manifest.name}.harness-constraints.json`);
10622
11017
  const writeResult = await writeConfig(outputPath, bundle);
10623
11018
  if (!writeResult.ok) {
10624
11019
  logger.error(`Failed to write bundle: ${writeResult.error.message}`);
@@ -10627,25 +11022,25 @@ Create a constraints.yaml in your project root to define what to share.`
10627
11022
  logger.success(`Bundle written to ${outputPath}`);
10628
11023
  }
10629
11024
  function createShareCommand() {
10630
- return new Command89("share").description("Extract and publish a constraints bundle from constraints.yaml").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory for the bundle", ".").action(async (projectPath, options) => {
11025
+ return new Command91("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) => {
10631
11026
  await runShareAction(projectPath, options);
10632
11027
  });
10633
11028
  }
10634
11029
 
10635
11030
  // src/commands/skill/index.ts
10636
- import { Command as Command97 } from "commander";
11031
+ import { Command as Command99 } from "commander";
10637
11032
 
10638
11033
  // src/commands/skill/list.ts
10639
- import { Command as Command90 } from "commander";
11034
+ import { Command as Command92 } from "commander";
10640
11035
  import * as fs37 from "fs";
10641
- import * as path55 from "path";
11036
+ import * as path56 from "path";
10642
11037
  import { parse } from "yaml";
10643
11038
  function scanDirectory(dirPath, source) {
10644
11039
  if (!fs37.existsSync(dirPath)) return [];
10645
11040
  const entries = fs37.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
10646
11041
  const skills = [];
10647
11042
  for (const name of entries) {
10648
- const yamlPath = path55.join(dirPath, name, "skill.yaml");
11043
+ const yamlPath = path56.join(dirPath, name, "skill.yaml");
10649
11044
  if (!fs37.existsSync(yamlPath)) continue;
10650
11045
  try {
10651
11046
  const raw = fs37.readFileSync(yamlPath, "utf-8");
@@ -10666,10 +11061,10 @@ function scanDirectory(dirPath, source) {
10666
11061
  }
10667
11062
  function collectCommunitySkills(seen, allSkills) {
10668
11063
  const globalDir = resolveGlobalSkillsDir();
10669
- const skillsDir = path55.dirname(globalDir);
10670
- const communityBase = path55.join(skillsDir, "community");
10671
- const communityPlatformDir = path55.join(communityBase, "claude-code");
10672
- const lockfilePath = path55.join(communityBase, "skills-lock.json");
11064
+ const skillsDir = path56.dirname(globalDir);
11065
+ const communityBase = path56.join(skillsDir, "community");
11066
+ const communityPlatformDir = path56.join(communityBase, "claude-code");
11067
+ const lockfilePath = path56.join(communityBase, "skills-lock.json");
10673
11068
  const lockfile = readLockfile2(lockfilePath);
10674
11069
  const communitySkills = scanDirectory(communityPlatformDir, "community");
10675
11070
  for (const skill of communitySkills) {
@@ -10739,7 +11134,7 @@ function printSkillsVerbose(skills) {
10739
11134
  for (const s of skills) printSkillEntry(s);
10740
11135
  }
10741
11136
  function createListCommand3() {
10742
- return new Command90("list").description("List available skills").option("--installed", "Show only community-installed skills").option("--local", "Show only project-local skills").option("--all", "Show all skills (default)").action(async (opts, cmd) => {
11137
+ return new Command92("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) => {
10743
11138
  const globalOpts = cmd.optsWithGlobals();
10744
11139
  const skills = collectSkills({ filter: resolveFilter(opts) });
10745
11140
  if (globalOpts.json) {
@@ -10754,13 +11149,13 @@ function createListCommand3() {
10754
11149
  }
10755
11150
 
10756
11151
  // src/commands/skill/run.ts
10757
- import { Command as Command91 } from "commander";
11152
+ import { Command as Command93 } from "commander";
10758
11153
  import * as fs38 from "fs";
10759
- import * as path56 from "path";
11154
+ import * as path57 from "path";
10760
11155
  import { parse as parse2 } from "yaml";
10761
11156
 
10762
11157
  // src/skill/complexity.ts
10763
- import { execFileSync as execFileSync5 } from "child_process";
11158
+ import { execFileSync as execFileSync6 } from "child_process";
10764
11159
  function evaluateSignals(signals) {
10765
11160
  if (signals.fileCount >= 3) return "thorough";
10766
11161
  if (signals.newDir) return "thorough";
@@ -10772,17 +11167,17 @@ function evaluateSignals(signals) {
10772
11167
  }
10773
11168
  function detectComplexity(projectPath) {
10774
11169
  try {
10775
- const base = execFileSync5("git", ["merge-base", "HEAD", "main"], {
11170
+ const base = execFileSync6("git", ["merge-base", "HEAD", "main"], {
10776
11171
  cwd: projectPath,
10777
11172
  encoding: "utf-8",
10778
11173
  stdio: ["pipe", "pipe", "pipe"]
10779
11174
  }).trim();
10780
- const diffFiles = execFileSync5("git", ["diff", "--name-only", base], {
11175
+ const diffFiles = execFileSync6("git", ["diff", "--name-only", base], {
10781
11176
  cwd: projectPath,
10782
11177
  encoding: "utf-8",
10783
11178
  stdio: ["pipe", "pipe", "pipe"]
10784
11179
  }).trim().split("\n").filter(Boolean);
10785
- const diffStat = execFileSync5("git", ["diff", "--stat", base], {
11180
+ const diffStat = execFileSync6("git", ["diff", "--stat", base], {
10786
11181
  cwd: projectPath,
10787
11182
  encoding: "utf-8",
10788
11183
  stdio: ["pipe", "pipe", "pipe"]
@@ -10852,7 +11247,7 @@ ${options.principles}`);
10852
11247
 
10853
11248
  // src/commands/skill/run.ts
10854
11249
  function loadSkillMetadata(skillDir) {
10855
- const yamlPath = path56.join(skillDir, "skill.yaml");
11250
+ const yamlPath = path57.join(skillDir, "skill.yaml");
10856
11251
  if (!fs38.existsSync(yamlPath)) return null;
10857
11252
  try {
10858
11253
  const result = SkillMetadataSchema.safeParse(parse2(fs38.readFileSync(yamlPath, "utf-8")));
@@ -10867,18 +11262,18 @@ function resolveComplexity(metadata, requested, projectPath) {
10867
11262
  return requested;
10868
11263
  }
10869
11264
  function loadPrinciples(projectPath) {
10870
- const principlesPath = path56.join(projectPath, "docs", "principles.md");
11265
+ const principlesPath = path57.join(projectPath, "docs", "principles.md");
10871
11266
  return fs38.existsSync(principlesPath) ? fs38.readFileSync(principlesPath, "utf-8") : void 0;
10872
11267
  }
10873
11268
  function readMostRecentFileInDir(dirPath) {
10874
- const files = fs38.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs38.statSync(path56.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
10875
- if (files.length > 0) return fs38.readFileSync(path56.join(dirPath, files[0].name), "utf-8");
11269
+ const files = fs38.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs38.statSync(path57.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
11270
+ if (files.length > 0) return fs38.readFileSync(path57.join(dirPath, files[0].name), "utf-8");
10876
11271
  return void 0;
10877
11272
  }
10878
11273
  function loadPriorState(metadata, projectPath) {
10879
11274
  if (!metadata?.state.persistent || metadata.state.files.length === 0) return void 0;
10880
11275
  for (const stateFilePath of metadata.state.files) {
10881
- const fullPath = path56.join(projectPath, stateFilePath);
11276
+ const fullPath = path57.join(projectPath, stateFilePath);
10882
11277
  if (!fs38.existsSync(fullPath)) continue;
10883
11278
  const stat = fs38.statSync(fullPath);
10884
11279
  if (stat.isDirectory()) return readMostRecentFileInDir(fullPath);
@@ -10902,7 +11297,7 @@ function resolvePhaseState(metadata, projectPath, phase) {
10902
11297
  }
10903
11298
  function appendProjectState(content, metadata, projectPath, hasPathOpt) {
10904
11299
  if (!metadata?.state.persistent || !hasPathOpt) return content;
10905
- const stateFile = path56.join(projectPath, ".harness", "state.json");
11300
+ const stateFile = path57.join(projectPath, ".harness", "state.json");
10906
11301
  if (!fs38.existsSync(stateFile)) return content;
10907
11302
  const stateContent = fs38.readFileSync(stateFile, "utf-8");
10908
11303
  return content + `
@@ -10916,14 +11311,14 @@ ${stateContent}
10916
11311
  }
10917
11312
  async function runSkill(name, opts) {
10918
11313
  const skillsDir = resolveSkillsDir();
10919
- const skillDir = path56.join(skillsDir, name);
11314
+ const skillDir = path57.join(skillsDir, name);
10920
11315
  if (!fs38.existsSync(skillDir)) {
10921
11316
  logger.error(`Skill not found: ${name}`);
10922
11317
  process.exit(ExitCode.ERROR);
10923
11318
  return;
10924
11319
  }
10925
11320
  const metadata = loadSkillMetadata(skillDir);
10926
- const projectPath = opts.path ? path56.resolve(opts.path) : process.cwd();
11321
+ const projectPath = opts.path ? path57.resolve(opts.path) : process.cwd();
10927
11322
  const complexity = resolveComplexity(
10928
11323
  metadata,
10929
11324
  opts.complexity ?? "standard",
@@ -10950,7 +11345,7 @@ async function runSkill(name, opts) {
10950
11345
  ...stateWarning !== void 0 && { stateWarning },
10951
11346
  ...opts.party !== void 0 && { party: opts.party }
10952
11347
  });
10953
- const skillMdPath = path56.join(skillDir, "SKILL.md");
11348
+ const skillMdPath = path57.join(skillDir, "SKILL.md");
10954
11349
  if (!fs38.existsSync(skillMdPath)) {
10955
11350
  logger.error(`SKILL.md not found for skill: ${name}`);
10956
11351
  process.exit(ExitCode.ERROR);
@@ -10968,16 +11363,16 @@ async function runSkill(name, opts) {
10968
11363
  process.exit(ExitCode.SUCCESS);
10969
11364
  }
10970
11365
  function createRunCommand3() {
10971
- return new Command91("run").description("Run a skill (outputs SKILL.md content with context preamble)").argument("<name>", "Skill name (e.g., harness-tdd)").option("--path <path>", "Project root path for context injection").option("--complexity <level>", "Rigor level: fast, standard, thorough", "standard").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").option(
11366
+ return new Command93("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(
10972
11367
  "--backend <name>",
10973
11368
  "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
10974
11369
  ).action(async (name, opts) => runSkill(name, opts));
10975
11370
  }
10976
11371
 
10977
11372
  // src/commands/skill/validate.ts
10978
- import { Command as Command92 } from "commander";
11373
+ import { Command as Command94 } from "commander";
10979
11374
  import * as fs39 from "fs";
10980
- import * as path57 from "path";
11375
+ import * as path58 from "path";
10981
11376
  import { parse as parse3 } from "yaml";
10982
11377
  var BEHAVIORAL_REQUIRED_SECTIONS = [
10983
11378
  "## When to Use",
@@ -11018,8 +11413,8 @@ function validateSkillMd(name, skillMdPath, skillType, errors) {
11018
11413
  }
11019
11414
  }
11020
11415
  function validateSkillEntry(name, skillsDir, errors) {
11021
- const skillDir = path57.join(skillsDir, name);
11022
- const yamlPath = path57.join(skillDir, "skill.yaml");
11416
+ const skillDir = path58.join(skillsDir, name);
11417
+ const yamlPath = path58.join(skillDir, "skill.yaml");
11023
11418
  if (!fs39.existsSync(yamlPath)) {
11024
11419
  errors.push(`${name}: missing skill.yaml`);
11025
11420
  return false;
@@ -11031,7 +11426,7 @@ function validateSkillEntry(name, skillsDir, errors) {
11031
11426
  errors.push(`${name}/skill.yaml: ${result.error.message}`);
11032
11427
  return false;
11033
11428
  }
11034
- validateSkillMd(name, path57.join(skillDir, "SKILL.md"), result.data.type, errors);
11429
+ validateSkillMd(name, path58.join(skillDir, "SKILL.md"), result.data.type, errors);
11035
11430
  return true;
11036
11431
  } catch (e) {
11037
11432
  errors.push(`${name}: parse error \u2014 ${e instanceof Error ? e.message : String(e)}`);
@@ -11039,7 +11434,7 @@ function validateSkillEntry(name, skillsDir, errors) {
11039
11434
  }
11040
11435
  }
11041
11436
  function createValidateCommand2() {
11042
- return new Command92("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
11437
+ return new Command94("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
11043
11438
  const globalOpts = cmd.optsWithGlobals();
11044
11439
  const skillsDir = resolveSkillsDir();
11045
11440
  if (!fs39.existsSync(skillsDir)) {
@@ -11069,18 +11464,18 @@ function createValidateCommand2() {
11069
11464
  }
11070
11465
 
11071
11466
  // src/commands/skill/info.ts
11072
- import { Command as Command93 } from "commander";
11467
+ import { Command as Command95 } from "commander";
11073
11468
  import * as fs40 from "fs";
11074
- import * as path58 from "path";
11469
+ import * as path59 from "path";
11075
11470
  import { parse as parse4 } from "yaml";
11076
11471
  function loadSkillMetadata2(name) {
11077
11472
  const skillsDir = resolveSkillsDir();
11078
- const skillDir = path58.join(skillsDir, name);
11473
+ const skillDir = path59.join(skillsDir, name);
11079
11474
  if (!fs40.existsSync(skillDir)) {
11080
11475
  logger.error(`Skill not found: ${name}`);
11081
11476
  return { ok: false, exitCode: ExitCode.ERROR };
11082
11477
  }
11083
- const yamlPath = path58.join(skillDir, "skill.yaml");
11478
+ const yamlPath = path59.join(skillDir, "skill.yaml");
11084
11479
  if (!fs40.existsSync(yamlPath)) {
11085
11480
  logger.error(`skill.yaml not found for skill: ${name}`);
11086
11481
  return { ok: false, exitCode: ExitCode.ERROR };
@@ -11115,7 +11510,7 @@ function printSkillInfo(skill) {
11115
11510
  console.log(`Persistent: ${skill.state.persistent}`);
11116
11511
  }
11117
11512
  function createInfoCommand() {
11118
- return new Command93("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
11513
+ return new Command95("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
11119
11514
  const globalOpts = cmd.optsWithGlobals();
11120
11515
  const loaded = loadSkillMetadata2(name);
11121
11516
  if (!loaded.ok) {
@@ -11132,7 +11527,7 @@ function createInfoCommand() {
11132
11527
  }
11133
11528
 
11134
11529
  // src/commands/skill/search.ts
11135
- import { Command as Command94 } from "commander";
11530
+ import { Command as Command96 } from "commander";
11136
11531
  async function runSearch(query, opts) {
11137
11532
  const results = await searchNpmRegistry(query, opts.registry);
11138
11533
  return results.filter((r) => {
@@ -11177,14 +11572,14 @@ async function runSearchAction(query, opts, globalOpts) {
11177
11572
  }
11178
11573
  }
11179
11574
  function createSearchCommand2() {
11180
- return new Command94("search").description("Search for community skills on the @harness-skills registry").argument("<query>", "Search query").option("--platform <platform>", "Filter by platform (e.g., claude-code)").option("--trigger <trigger>", "Filter by trigger type (e.g., manual, automatic)").option("--registry <url>", "Use a custom npm registry URL").action(async (query, opts, cmd) => {
11575
+ return new Command96("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) => {
11181
11576
  await runSearchAction(query, opts, cmd.optsWithGlobals());
11182
11577
  });
11183
11578
  }
11184
11579
 
11185
11580
  // src/commands/skill/create.ts
11186
- import { Command as Command95 } from "commander";
11187
- import * as path59 from "path";
11581
+ import { Command as Command97 } from "commander";
11582
+ import * as path60 from "path";
11188
11583
  import * as fs41 from "fs";
11189
11584
  import YAML from "yaml";
11190
11585
  var KEBAB_CASE_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
@@ -11269,21 +11664,21 @@ function runCreate(name, opts) {
11269
11664
  if (!KEBAB_CASE_RE.test(name)) {
11270
11665
  throw new Error(`Invalid skill name "${name}". Must be kebab-case (e.g., my-skill).`);
11271
11666
  }
11272
- const baseDir = opts.outputDir ?? path59.join(process.cwd(), "agents", "skills", "claude-code");
11273
- const skillDir = path59.join(baseDir, name);
11667
+ const baseDir = opts.outputDir ?? path60.join(process.cwd(), "agents", "skills", "claude-code");
11668
+ const skillDir = path60.join(baseDir, name);
11274
11669
  if (fs41.existsSync(skillDir)) {
11275
11670
  throw new Error(`Skill directory already exists: ${skillDir}`);
11276
11671
  }
11277
11672
  fs41.mkdirSync(skillDir, { recursive: true });
11278
11673
  const description = opts.description || `A community skill: ${name}`;
11279
11674
  const skillYaml = buildSkillYaml(name, opts);
11280
- const skillYamlPath = path59.join(skillDir, "skill.yaml");
11675
+ const skillYamlPath = path60.join(skillDir, "skill.yaml");
11281
11676
  fs41.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
11282
11677
  const skillMd = buildSkillMd(name, description);
11283
- const skillMdPath = path59.join(skillDir, "SKILL.md");
11678
+ const skillMdPath = path60.join(skillDir, "SKILL.md");
11284
11679
  fs41.writeFileSync(skillMdPath, skillMd);
11285
11680
  const readme = buildReadme(name, description);
11286
- const readmePath = path59.join(skillDir, "README.md");
11681
+ const readmePath = path60.join(skillDir, "README.md");
11287
11682
  fs41.writeFileSync(readmePath, readme);
11288
11683
  return {
11289
11684
  name,
@@ -11298,12 +11693,12 @@ function printCreateResult(name, result) {
11298
11693
  }
11299
11694
  logger.info(`
11300
11695
  Next steps:`);
11301
- logger.info(` 1. Edit ${path59.join(result.directory, "SKILL.md")} with your skill content`);
11696
+ logger.info(` 1. Edit ${path60.join(result.directory, "SKILL.md")} with your skill content`);
11302
11697
  logger.info(` 2. Run: harness skill validate ${name}`);
11303
11698
  logger.info(` 3. Run: harness skills publish`);
11304
11699
  }
11305
11700
  function createCreateCommand() {
11306
- return new Command95("create").description("Scaffold a new community skill").argument("<name>", "Skill name (kebab-case)").option("--description <desc>", "Skill description").option("--type <type>", "Skill type: rigid or flexible", "flexible").option("--platforms <platforms>", "Comma-separated platforms (default: claude-code)").option("--triggers <triggers>", "Comma-separated triggers (default: manual)").option("--output-dir <dir>", "Output directory (default: agents/skills/claude-code/)").action(async (name, opts, cmd) => {
11701
+ return new Command97("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) => {
11307
11702
  const globalOpts = cmd.optsWithGlobals();
11308
11703
  try {
11309
11704
  const result = runCreate(name, {
@@ -11326,19 +11721,19 @@ function createCreateCommand() {
11326
11721
  }
11327
11722
 
11328
11723
  // src/commands/skill/publish.ts
11329
- import { Command as Command96 } from "commander";
11724
+ import { Command as Command98 } from "commander";
11330
11725
  import * as fs43 from "fs";
11331
- import * as path61 from "path";
11332
- import { execFileSync as execFileSync6 } from "child_process";
11726
+ import * as path62 from "path";
11727
+ import { execFileSync as execFileSync7 } from "child_process";
11333
11728
 
11334
11729
  // src/registry/validator.ts
11335
11730
  import * as fs42 from "fs";
11336
- import * as path60 from "path";
11731
+ import * as path61 from "path";
11337
11732
  import { parse as parse5 } from "yaml";
11338
11733
  import semver4 from "semver";
11339
11734
  async function validateForPublish(skillDir, registryUrl) {
11340
11735
  const errors = [];
11341
- const skillYamlPath = path60.join(skillDir, "skill.yaml");
11736
+ const skillYamlPath = path61.join(skillDir, "skill.yaml");
11342
11737
  if (!fs42.existsSync(skillYamlPath)) {
11343
11738
  errors.push("skill.yaml not found. Create one with: harness skill create <name>");
11344
11739
  return { valid: false, errors };
@@ -11367,7 +11762,7 @@ async function validateForPublish(skillDir, registryUrl) {
11367
11762
  if (!skillMeta.triggers || skillMeta.triggers.length === 0) {
11368
11763
  errors.push("At least one trigger is required. Add triggers to skill.yaml.");
11369
11764
  }
11370
- const skillMdPath = path60.join(skillDir, "SKILL.md");
11765
+ const skillMdPath = path61.join(skillDir, "SKILL.md");
11371
11766
  if (!fs42.existsSync(skillMdPath)) {
11372
11767
  errors.push("SKILL.md not found. Create it with content describing your skill.");
11373
11768
  } else {
@@ -11451,11 +11846,11 @@ ${errorList}`);
11451
11846
  }
11452
11847
  const meta = validation.skillMeta;
11453
11848
  const pkg = derivePackageJson(meta);
11454
- const pkgPath = path61.join(skillDir, "package.json");
11849
+ const pkgPath = path62.join(skillDir, "package.json");
11455
11850
  fs43.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
11456
- const readmePath = path61.join(skillDir, "README.md");
11851
+ const readmePath = path62.join(skillDir, "README.md");
11457
11852
  if (!fs43.existsSync(readmePath)) {
11458
- const skillMdContent = fs43.readFileSync(path61.join(skillDir, "SKILL.md"), "utf-8");
11853
+ const skillMdContent = fs43.readFileSync(path62.join(skillDir, "SKILL.md"), "utf-8");
11459
11854
  const readme = `# ${pkg.name}
11460
11855
 
11461
11856
  ${meta.description}
@@ -11483,7 +11878,7 @@ ${skillMdContent}`;
11483
11878
  if (opts.registry) {
11484
11879
  publishArgs.push("--registry", opts.registry);
11485
11880
  }
11486
- execFileSync6("npm", publishArgs, {
11881
+ execFileSync7("npm", publishArgs, {
11487
11882
  cwd: skillDir,
11488
11883
  stdio: "pipe",
11489
11884
  timeout: 6e4
@@ -11495,7 +11890,7 @@ ${skillMdContent}`;
11495
11890
  };
11496
11891
  }
11497
11892
  function createPublishCommand() {
11498
- return new Command96("publish").description("Validate and publish a skill to @harness-skills on npm").option("--dry-run", "Run validation and generate package.json without publishing").option("--dir <dir>", "Skill directory (default: current directory)").option("--registry <url>", "Use a custom npm registry URL").action(async (opts, cmd) => {
11893
+ return new Command98("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) => {
11499
11894
  const globalOpts = cmd.optsWithGlobals();
11500
11895
  const skillDir = opts.dir || process.cwd();
11501
11896
  try {
@@ -11520,7 +11915,7 @@ function createPublishCommand() {
11520
11915
 
11521
11916
  // src/commands/skill/index.ts
11522
11917
  function createSkillCommand() {
11523
- const command = new Command97("skill").description("Skill management commands");
11918
+ const command = new Command99("skill").description("Skill management commands");
11524
11919
  command.addCommand(createListCommand3());
11525
11920
  command.addCommand(createRunCommand3());
11526
11921
  command.addCommand(createValidateCommand2());
@@ -11533,7 +11928,7 @@ function createSkillCommand() {
11533
11928
 
11534
11929
  // src/commands/snapshot.ts
11535
11930
  init_dist3();
11536
- import { Command as Command98 } from "commander";
11931
+ import { Command as Command100 } from "commander";
11537
11932
  import { execSync as execSync5 } from "child_process";
11538
11933
  import chalk16 from "chalk";
11539
11934
  function getCommitHash3(cwd) {
@@ -11715,7 +12110,7 @@ function registerListCommand(parent) {
11715
12110
  });
11716
12111
  }
11717
12112
  function createSnapshotCommand() {
11718
- const command = new Command98("snapshot").description("Architecture timeline snapshot commands");
12113
+ const command = new Command100("snapshot").description("Architecture timeline snapshot commands");
11719
12114
  registerCaptureCommand(command);
11720
12115
  registerTrendsCommand(command);
11721
12116
  registerListCommand(command);
@@ -11723,9 +12118,9 @@ function createSnapshotCommand() {
11723
12118
  }
11724
12119
 
11725
12120
  // src/commands/spec-craft.ts
11726
- import { Command as Command99 } from "commander";
12121
+ import { Command as Command101 } from "commander";
11727
12122
  function createSpecCraftCommand() {
11728
- return new Command99("spec-craft").description(
12123
+ return new Command101("spec-craft").description(
11729
12124
  "LLM-judgment critique of spec quality (proposals + ADRs). Second craft-pipeline ceiling skill; 7 seed rubrics from the spec-quality canon. Per-section critique."
11730
12125
  ).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) => {
11731
12126
  const globalOpts = cmd.optsWithGlobals();
@@ -11773,10 +12168,10 @@ function printResult6(result, mode, _formatter) {
11773
12168
  list.push(f);
11774
12169
  byFile.set(f.target.file, list);
11775
12170
  }
11776
- for (const [file, fs48] of byFile) {
12171
+ for (const [file, fs49] of byFile) {
11777
12172
  console.log(`
11778
12173
  ${file}`);
11779
- for (const f of fs48) {
12174
+ for (const f of fs49) {
11780
12175
  console.log(
11781
12176
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ## ${f.target.section}:${f.target.line}`
11782
12177
  );
@@ -11792,12 +12187,12 @@ ${file}`);
11792
12187
  }
11793
12188
 
11794
12189
  // src/commands/state/index.ts
11795
- import { Command as Command104 } from "commander";
12190
+ import { Command as Command106 } from "commander";
11796
12191
 
11797
12192
  // src/commands/state/show.ts
11798
12193
  init_dist3();
11799
- import { Command as Command100 } from "commander";
11800
- import * as path62 from "path";
12194
+ import { Command as Command102 } from "commander";
12195
+ import * as path63 from "path";
11801
12196
  function printStateText(state, stream) {
11802
12197
  if (stream) console.log(`Stream: ${stream}`);
11803
12198
  console.log(`Schema Version: ${state.schemaVersion}`);
@@ -11821,9 +12216,9 @@ function printStateProgress(progress) {
11821
12216
  }
11822
12217
  }
11823
12218
  function createShowCommand() {
11824
- return new Command100("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
12219
+ return new Command102("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
11825
12220
  const globalOpts = cmd.optsWithGlobals();
11826
- const result = await loadState(path62.resolve(opts.path), opts.stream);
12221
+ const result = await loadState(path63.resolve(opts.path), opts.stream);
11827
12222
  if (!result.ok) {
11828
12223
  logger.error(result.error.message);
11829
12224
  process.exit(ExitCode.ERROR);
@@ -11839,9 +12234,9 @@ function createShowCommand() {
11839
12234
 
11840
12235
  // src/commands/state/reset.ts
11841
12236
  init_dist3();
11842
- import { Command as Command101 } from "commander";
12237
+ import { Command as Command103 } from "commander";
11843
12238
  import * as fs44 from "fs";
11844
- import * as path63 from "path";
12239
+ import * as path64 from "path";
11845
12240
  import * as readline3 from "readline";
11846
12241
  async function resolveStatePath(projectPath, stream) {
11847
12242
  if (stream) {
@@ -11850,20 +12245,20 @@ async function resolveStatePath(projectPath, stream) {
11850
12245
  logger.error(streamResult.error.message);
11851
12246
  process.exit(ExitCode.ERROR);
11852
12247
  }
11853
- return path63.join(streamResult.value, "state.json");
12248
+ return path64.join(streamResult.value, "state.json");
11854
12249
  }
11855
- return path63.join(projectPath, ".harness", "state.json");
12250
+ return path64.join(projectPath, ".harness", "state.json");
11856
12251
  }
11857
12252
  async function confirmReset() {
11858
12253
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
11859
- const answer = await new Promise((resolve46) => {
11860
- rl.question("Reset project state? This cannot be undone. [y/N] ", resolve46);
12254
+ const answer = await new Promise((resolve47) => {
12255
+ rl.question("Reset project state? This cannot be undone. [y/N] ", resolve47);
11861
12256
  });
11862
12257
  rl.close();
11863
12258
  return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
11864
12259
  }
11865
12260
  async function runReset(opts) {
11866
- const projectPath = path63.resolve(opts.path);
12261
+ const projectPath = path64.resolve(opts.path);
11867
12262
  const statePath = await resolveStatePath(projectPath, opts.stream);
11868
12263
  if (!fs44.existsSync(statePath)) {
11869
12264
  logger.info("No state file found. Nothing to reset.");
@@ -11883,16 +12278,16 @@ async function runReset(opts) {
11883
12278
  process.exit(ExitCode.SUCCESS);
11884
12279
  }
11885
12280
  function createResetCommand() {
11886
- return new Command101("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
12281
+ return new Command103("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));
11887
12282
  }
11888
12283
 
11889
12284
  // src/commands/state/learn.ts
11890
12285
  init_dist3();
11891
- import { Command as Command102 } from "commander";
11892
- import * as path64 from "path";
12286
+ import { Command as Command104 } from "commander";
12287
+ import * as path65 from "path";
11893
12288
  function createLearnCommand() {
11894
- return new Command102("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (message, opts, _cmd) => {
11895
- const projectPath = path64.resolve(opts.path);
12289
+ return new Command104("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) => {
12290
+ const projectPath = path65.resolve(opts.path);
11896
12291
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
11897
12292
  if (!result.ok) {
11898
12293
  logger.error(result.error.message);
@@ -11906,10 +12301,10 @@ function createLearnCommand() {
11906
12301
 
11907
12302
  // src/commands/state/streams.ts
11908
12303
  init_dist3();
11909
- import { Command as Command103 } from "commander";
11910
- import * as path65 from "path";
12304
+ import { Command as Command105 } from "commander";
12305
+ import * as path66 from "path";
11911
12306
  async function runListStreams(opts, globalOpts) {
11912
- const projectPath = path65.resolve(opts.path);
12307
+ const projectPath = path66.resolve(opts.path);
11913
12308
  const indexResult = await loadStreamIndex(projectPath);
11914
12309
  const result = await listStreams(projectPath);
11915
12310
  if (!result.ok) {
@@ -11930,7 +12325,7 @@ async function runListStreams(opts, globalOpts) {
11930
12325
  process.exit(ExitCode.SUCCESS);
11931
12326
  }
11932
12327
  async function runCreateStream(name, opts) {
11933
- const result = await createStream(path65.resolve(opts.path), name, opts.branch);
12328
+ const result = await createStream(path66.resolve(opts.path), name, opts.branch);
11934
12329
  if (!result.ok) {
11935
12330
  logger.error(result.error.message);
11936
12331
  process.exit(ExitCode.ERROR);
@@ -11939,7 +12334,7 @@ async function runCreateStream(name, opts) {
11939
12334
  process.exit(ExitCode.SUCCESS);
11940
12335
  }
11941
12336
  async function runArchiveStream(name, opts) {
11942
- const result = await archiveStream(path65.resolve(opts.path), name);
12337
+ const result = await archiveStream(path66.resolve(opts.path), name);
11943
12338
  if (!result.ok) {
11944
12339
  logger.error(result.error.message);
11945
12340
  process.exit(ExitCode.ERROR);
@@ -11948,7 +12343,7 @@ async function runArchiveStream(name, opts) {
11948
12343
  process.exit(ExitCode.SUCCESS);
11949
12344
  }
11950
12345
  async function runActivateStream(name, opts) {
11951
- const result = await setActiveStream(path65.resolve(opts.path), name);
12346
+ const result = await setActiveStream(path66.resolve(opts.path), name);
11952
12347
  if (!result.ok) {
11953
12348
  logger.error(result.error.message);
11954
12349
  process.exit(ExitCode.ERROR);
@@ -11957,7 +12352,7 @@ async function runActivateStream(name, opts) {
11957
12352
  process.exit(ExitCode.SUCCESS);
11958
12353
  }
11959
12354
  function createStreamsCommand() {
11960
- const command = new Command103("streams").description("Manage state streams");
12355
+ const command = new Command105("streams").description("Manage state streams");
11961
12356
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
11962
12357
  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));
11963
12358
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -11967,7 +12362,7 @@ function createStreamsCommand() {
11967
12362
 
11968
12363
  // src/commands/state/index.ts
11969
12364
  function createStateCommand() {
11970
- const command = new Command104("state").description("Project state management commands");
12365
+ const command = new Command106("state").description("Project state management commands");
11971
12366
  command.addCommand(createShowCommand());
11972
12367
  command.addCommand(createResetCommand());
11973
12368
  command.addCommand(createLearnCommand());
@@ -11977,8 +12372,8 @@ function createStateCommand() {
11977
12372
 
11978
12373
  // src/commands/sync-analyses.ts
11979
12374
  import * as fs45 from "fs";
11980
- import * as path66 from "path";
11981
- import { Command as Command105 } from "commander";
12375
+ import * as path67 from "path";
12376
+ import { Command as Command107 } from "commander";
11982
12377
  init_dist3();
11983
12378
  function isValidRecord(record) {
11984
12379
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -12004,7 +12399,7 @@ function extractAnalysisFromComments(comments) {
12004
12399
  return null;
12005
12400
  }
12006
12401
  function bootstrapTrackerCommand2(opts, verb) {
12007
- const projectPath = path66.resolve(opts.dir);
12402
+ const projectPath = path67.resolve(opts.dir);
12008
12403
  const trackerConfig = loadTrackerSyncConfig(projectPath);
12009
12404
  if (!trackerConfig) {
12010
12405
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -12016,7 +12411,7 @@ function bootstrapTrackerCommand2(opts, verb) {
12016
12411
  );
12017
12412
  return null;
12018
12413
  }
12019
- const projectEnvPath = path66.join(projectPath, ".env");
12414
+ const projectEnvPath = path67.join(projectPath, ".env");
12020
12415
  if (fs45.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
12021
12416
  __require("dotenv").config({ path: projectEnvPath });
12022
12417
  }
@@ -12047,7 +12442,7 @@ async function loadRoadmapFeatures(projectPath) {
12047
12442
  }
12048
12443
  return r.value.features.filter((f) => !!f.externalId).map((f) => ({ name: f.name, externalId: f.externalId }));
12049
12444
  }
12050
- const roadmapFile = path66.join(projectPath, "docs", "roadmap.md");
12445
+ const roadmapFile = path67.join(projectPath, "docs", "roadmap.md");
12051
12446
  if (!fs45.existsSync(roadmapFile)) {
12052
12447
  logger.error("No docs/roadmap.md found. Cannot discover features with externalIds.");
12053
12448
  return null;
@@ -12104,9 +12499,9 @@ async function runSyncAnalyses(opts) {
12104
12499
  return;
12105
12500
  }
12106
12501
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
12107
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-72ID44UE.js");
12502
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-LHINSVK4.js");
12108
12503
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
12109
- const archive = new AnalysisArchive(path66.join(projectPath, ".harness", "analyses"));
12504
+ const archive = new AnalysisArchive(path67.join(projectPath, ".harness", "analyses"));
12110
12505
  const publishedIndex = loadPublishedIndex2(projectPath);
12111
12506
  const { syncedCount, skippedCount, warnCount } = await syncFeatureAnalyses(
12112
12507
  features,
@@ -12126,7 +12521,7 @@ async function runSyncAnalyses(opts) {
12126
12521
  }
12127
12522
  }
12128
12523
  function createSyncAnalysesCommand() {
12129
- const command = new Command105("sync-analyses").description(
12524
+ const command = new Command107("sync-analyses").description(
12130
12525
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
12131
12526
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
12132
12527
  try {
@@ -12140,8 +12535,8 @@ function createSyncAnalysesCommand() {
12140
12535
  }
12141
12536
 
12142
12537
  // src/commands/sync-main.ts
12143
- import { Command as Command106 } from "commander";
12144
- import * as path67 from "path";
12538
+ import { Command as Command108 } from "commander";
12539
+ import * as path68 from "path";
12145
12540
  import {
12146
12541
  syncMain as defaultSyncMain
12147
12542
  } from "@harness-engineering/orchestrator";
@@ -12171,8 +12566,8 @@ function formatHuman2(r) {
12171
12566
  }
12172
12567
  }
12173
12568
  function createSyncMainCommand() {
12174
- return new Command106("sync-main").description("Fast-forward the local default branch from origin (no-op on conflict)").option("--json", "Emit a SyncMainResult JSON object", false).option("--path <path>", "Project root path", ".").action(async (opts) => {
12175
- const cwd = path67.resolve(opts.path ?? ".");
12569
+ return new Command108("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) => {
12570
+ const cwd = path68.resolve(opts.path ?? ".");
12176
12571
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
12177
12572
  process.exit(exitCode);
12178
12573
  });
@@ -12180,7 +12575,7 @@ function createSyncMainCommand() {
12180
12575
 
12181
12576
  // src/commands/taint.ts
12182
12577
  init_dist3();
12183
- import { Command as Command107 } from "commander";
12578
+ import { Command as Command109 } from "commander";
12184
12579
  function getProjectRoot() {
12185
12580
  return process.cwd();
12186
12581
  }
@@ -12252,26 +12647,26 @@ function registerStatusCommand(taint) {
12252
12647
  });
12253
12648
  }
12254
12649
  function createTaintCommand() {
12255
- const taint = new Command107("taint").description("Manage sentinel session taint state");
12650
+ const taint = new Command109("taint").description("Manage sentinel session taint state");
12256
12651
  registerClearCommand(taint);
12257
12652
  registerStatusCommand(taint);
12258
12653
  return taint;
12259
12654
  }
12260
12655
 
12261
12656
  // src/commands/telemetry/index.ts
12262
- import { Command as Command111 } from "commander";
12657
+ import { Command as Command113 } from "commander";
12263
12658
 
12264
12659
  // src/commands/telemetry/identify.ts
12265
12660
  init_dist3();
12266
- import { Command as Command108 } from "commander";
12661
+ import { Command as Command110 } from "commander";
12267
12662
  import * as fs46 from "fs";
12268
- import * as path68 from "path";
12663
+ import * as path69 from "path";
12269
12664
  function telemetryFilePath(cwd) {
12270
- return path68.join(cwd, ".harness", "telemetry.json");
12665
+ return path69.join(cwd, ".harness", "telemetry.json");
12271
12666
  }
12272
12667
  function writeTelemetryFile(cwd, data) {
12273
12668
  const filePath = telemetryFilePath(cwd);
12274
- const dir = path68.dirname(filePath);
12669
+ const dir = path69.dirname(filePath);
12275
12670
  fs46.mkdirSync(dir, { recursive: true });
12276
12671
  fs46.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
12277
12672
  }
@@ -12287,7 +12682,7 @@ function printIdentity(identity) {
12287
12682
  }
12288
12683
  }
12289
12684
  function createIdentifyCommand() {
12290
- const cmd = new Command108("identify").description("Set or clear telemetry identity fields in .harness/telemetry.json").option("--project <name>", "Project name").option("--team <name>", "Team name").option("--alias <name>", "User alias").option("--clear", "Remove all identity fields").action((opts) => {
12685
+ const cmd = new Command110("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) => {
12291
12686
  const cwd = process.cwd();
12292
12687
  if (opts.clear) {
12293
12688
  writeTelemetryFile(cwd, { identity: {} });
@@ -12312,7 +12707,7 @@ function createIdentifyCommand() {
12312
12707
 
12313
12708
  // src/commands/telemetry/status.ts
12314
12709
  init_dist3();
12315
- import { Command as Command109 } from "commander";
12710
+ import { Command as Command111 } from "commander";
12316
12711
  function gatherEnvOverrides() {
12317
12712
  const overrides = {};
12318
12713
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -12354,7 +12749,7 @@ function printHumanStatus(result) {
12354
12749
  printEnvOverrides(result.envOverrides);
12355
12750
  }
12356
12751
  function createStatusCommand() {
12357
- const cmd = new Command109("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
12752
+ const cmd = new Command111("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
12358
12753
  const cwd = process.cwd();
12359
12754
  const envOverrides = gatherEnvOverrides();
12360
12755
  const consent = resolveConsent(cwd, void 0);
@@ -12387,20 +12782,20 @@ function createStatusCommand() {
12387
12782
 
12388
12783
  // src/commands/telemetry/test.ts
12389
12784
  init_dist3();
12390
- import { Command as Command110 } from "commander";
12785
+ import { Command as Command112 } from "commander";
12391
12786
 
12392
12787
  // src/bin/command-telemetry.ts
12393
- import { existsSync as existsSync43, readFileSync as readFileSync33, mkdirSync as mkdirSync19, appendFileSync, writeFileSync as writeFileSync25 } from "fs";
12394
- import { join as join57, parse as parsePath, resolve as resolve43 } from "path";
12788
+ import { existsSync as existsSync43, readFileSync as readFileSync33, mkdirSync as mkdirSync19, appendFileSync, writeFileSync as writeFileSync26 } from "fs";
12789
+ import { join as join57, parse as parsePath, resolve as resolve44 } from "path";
12395
12790
  import { spawn as spawn2 } from "child_process";
12396
12791
  var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
12397
12792
  var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
12398
12793
  function findProjectRoot(cwd) {
12399
- let dir = resolve43(cwd);
12794
+ let dir = resolve44(cwd);
12400
12795
  const { root } = parsePath(dir);
12401
12796
  while (dir !== root) {
12402
12797
  if (existsSync43(join57(dir, "harness.config.json"))) return dir;
12403
- dir = resolve43(dir, "..");
12798
+ dir = resolve44(dir, "..");
12404
12799
  }
12405
12800
  return cwd;
12406
12801
  }
@@ -12509,7 +12904,7 @@ function reportTestSuccess(status, distinctId, identity) {
12509
12904
  if (identity.team) logger.info(` team: ${identity.team}`);
12510
12905
  }
12511
12906
  function createTestCommand() {
12512
- return new Command110("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
12907
+ return new Command112("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
12513
12908
  const cwd = process.cwd();
12514
12909
  const consent = resolveConsent(cwd, void 0);
12515
12910
  if (!consent.allowed) {
@@ -12546,7 +12941,7 @@ function createTestCommand() {
12546
12941
 
12547
12942
  // src/commands/telemetry/index.ts
12548
12943
  function createTelemetryCommand() {
12549
- const command = new Command111("telemetry").description("Telemetry identity and status management");
12944
+ const command = new Command113("telemetry").description("Telemetry identity and status management");
12550
12945
  command.addCommand(createIdentifyCommand());
12551
12946
  command.addCommand(createStatusCommand());
12552
12947
  command.addCommand(createTestCommand());
@@ -12554,9 +12949,9 @@ function createTelemetryCommand() {
12554
12949
  }
12555
12950
 
12556
12951
  // src/commands/test-craft.ts
12557
- import { Command as Command112 } from "commander";
12952
+ import { Command as Command114 } from "commander";
12558
12953
  function createTestCraftCommand() {
12559
- return new Command112("test-craft").description(
12954
+ return new Command114("test-craft").description(
12560
12955
  "LLM-judgment critique of test quality across vitest/jest/mocha/playwright. Fourth craft-pipeline ceiling skill. Per-test critique with best-effort source pairing."
12561
12956
  ).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) => {
12562
12957
  const globalOpts = cmd.optsWithGlobals();
@@ -12604,10 +12999,10 @@ function printResult7(result, mode, _formatter) {
12604
12999
  list.push(f);
12605
13000
  byFile.set(f.target.file, list);
12606
13001
  }
12607
- for (const [file, fs48] of byFile) {
13002
+ for (const [file, fs49] of byFile) {
12608
13003
  console.log(`
12609
13004
  ${file}`);
12610
- for (const f of fs48) {
13005
+ for (const f of fs49) {
12611
13006
  const nestingStr = f.target.nesting.length > 0 ? f.target.nesting.join(" > ") + " > " : "";
12612
13007
  console.log(
12613
13008
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.framework}:${f.target.line}`
@@ -12626,7 +13021,7 @@ ${file}`);
12626
13021
  }
12627
13022
 
12628
13023
  // src/commands/traceability.ts
12629
- import { Command as Command113 } from "commander";
13024
+ import { Command as Command115 } from "commander";
12630
13025
  import chalk17 from "chalk";
12631
13026
  function confidenceLabel(maxConfidence) {
12632
13027
  if (maxConfidence >= 0.8) return "explicit";
@@ -12747,7 +13142,7 @@ async function runTraceability(options) {
12747
13142
  const projectPath = process.cwd();
12748
13143
  const store = await loadGraphStore(projectPath);
12749
13144
  if (!store) handleNoStore(mode);
12750
- const graphModule = await import("./dist-R3TOOPJ7.js");
13145
+ const graphModule = await import("./dist-OWHMNL4W.js");
12751
13146
  const filterOptions = buildFilterOptions(options);
12752
13147
  const results = graphModule.queryTraceability(store, filterOptions);
12753
13148
  if (results.length === 0) handleEmptyResults(mode);
@@ -12762,7 +13157,7 @@ async function runTraceability(options) {
12762
13157
  process.exit(ExitCode.SUCCESS);
12763
13158
  }
12764
13159
  function createTraceabilityCommand() {
12765
- return new Command113("traceability").description("Show spec-to-implementation traceability from the knowledge graph").option("--spec <path>", "Filter by spec file path").option("--feature <name>", "Filter by feature name").action(async (opts, cmd) => {
13160
+ return new Command115("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) => {
12766
13161
  const globalOpts = cmd.optsWithGlobals();
12767
13162
  await runTraceability({
12768
13163
  spec: opts.spec,
@@ -12775,15 +13170,15 @@ function createTraceabilityCommand() {
12775
13170
  }
12776
13171
 
12777
13172
  // src/commands/uninstall.ts
12778
- import * as path69 from "path";
12779
- import { Command as Command114 } from "commander";
13173
+ import * as path70 from "path";
13174
+ import { Command as Command116 } from "commander";
12780
13175
  async function runUninstall(skillName, options) {
12781
13176
  const packageName = resolvePackageName(skillName);
12782
13177
  const shortName = extractSkillName(packageName);
12783
13178
  const globalDir = resolveGlobalSkillsDir();
12784
- const skillsDir = path69.dirname(globalDir);
12785
- const communityBase = path69.join(skillsDir, "community");
12786
- const lockfilePath = path69.join(communityBase, "skills-lock.json");
13179
+ const skillsDir = path70.dirname(globalDir);
13180
+ const communityBase = path70.join(skillsDir, "community");
13181
+ const lockfilePath = path70.join(communityBase, "skills-lock.json");
12787
13182
  const lockfile = readLockfile2(lockfilePath);
12788
13183
  const entry = lockfile.skills[packageName];
12789
13184
  if (!entry) {
@@ -12813,7 +13208,7 @@ async function runUninstall(skillName, options) {
12813
13208
  return result;
12814
13209
  }
12815
13210
  function createUninstallCommand() {
12816
- const cmd = new Command114("uninstall");
13211
+ const cmd = new Command116("uninstall");
12817
13212
  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) => {
12818
13213
  try {
12819
13214
  const result = await runUninstall(skill, opts);
@@ -12834,8 +13229,8 @@ function createUninstallCommand() {
12834
13229
  // src/commands/uninstall-constraints.ts
12835
13230
  init_dist3();
12836
13231
  import * as fs47 from "fs/promises";
12837
- import * as path70 from "path";
12838
- import { Command as Command115 } from "commander";
13232
+ import * as path71 from "path";
13233
+ import { Command as Command117 } from "commander";
12839
13234
  async function runUninstallConstraints(options) {
12840
13235
  const { packageName, configPath, lockfilePath } = options;
12841
13236
  const lockfileResult = await readLockfile(lockfilePath);
@@ -12892,11 +13287,11 @@ async function runUninstallConstraints(options) {
12892
13287
  };
12893
13288
  }
12894
13289
  function createUninstallConstraintsCommand() {
12895
- const cmd = new Command115("uninstall-constraints");
13290
+ const cmd = new Command117("uninstall-constraints");
12896
13291
  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) => {
12897
13292
  let configPath;
12898
13293
  if (opts.config) {
12899
- configPath = path70.resolve(opts.config);
13294
+ configPath = path71.resolve(opts.config);
12900
13295
  } else {
12901
13296
  const found = findConfigFile();
12902
13297
  if (!found.ok) {
@@ -12905,8 +13300,8 @@ function createUninstallConstraintsCommand() {
12905
13300
  }
12906
13301
  configPath = found.value;
12907
13302
  }
12908
- const projectRoot2 = path70.dirname(configPath);
12909
- const lockfilePath = path70.join(projectRoot2, ".harness", "constraints.lock.json");
13303
+ const projectRoot2 = path71.dirname(configPath);
13304
+ const lockfilePath = path71.join(projectRoot2, ".harness", "constraints.lock.json");
12910
13305
  const result = await runUninstallConstraints({
12911
13306
  packageName: name,
12912
13307
  configPath,
@@ -12932,8 +13327,8 @@ function createUninstallConstraintsCommand() {
12932
13327
 
12933
13328
  // src/commands/update.ts
12934
13329
  init_dist3();
12935
- import { Command as Command116 } from "commander";
12936
- import { execFile, execFileSync as execFileSync7 } from "child_process";
13330
+ import { Command as Command118 } from "commander";
13331
+ import { execFile, execFileSync as execFileSync8 } from "child_process";
12937
13332
  import { realpathSync, existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
12938
13333
  import { dirname as dirname23, join as join60 } from "path";
12939
13334
  import { promisify } from "util";
@@ -12975,7 +13370,7 @@ async function getLatestVersionAsync(pkg) {
12975
13370
  function getInstalledVersions(pm, packages) {
12976
13371
  const versions = {};
12977
13372
  try {
12978
- const output = execFileSync7(pm, ["list", "-g", "--json"], {
13373
+ const output = execFileSync8(pm, ["list", "-g", "--json"], {
12979
13374
  encoding: "utf-8",
12980
13375
  timeout: 15e3
12981
13376
  });
@@ -12996,7 +13391,7 @@ function getInstalledVersions(pm, packages) {
12996
13391
  }
12997
13392
  function getInstalledPackages(pm) {
12998
13393
  try {
12999
- const output = execFileSync7(pm, ["list", "-g", "--json"], {
13394
+ const output = execFileSync8(pm, ["list", "-g", "--json"], {
13000
13395
  encoding: "utf-8",
13001
13396
  timeout: 15e3
13002
13397
  });
@@ -13016,10 +13411,10 @@ function prompt3(question) {
13016
13411
  input: process.stdin,
13017
13412
  output: process.stdout
13018
13413
  });
13019
- return new Promise((resolve46) => {
13414
+ return new Promise((resolve47) => {
13020
13415
  rl.question(question, (answer) => {
13021
13416
  rl.close();
13022
- resolve46(answer.trim().toLowerCase());
13417
+ resolve47(answer.trim().toLowerCase());
13023
13418
  });
13024
13419
  });
13025
13420
  }
@@ -13051,7 +13446,7 @@ function findAllInstalls() {
13051
13446
  const args = isWindows ? ["harness"] : ["-a", "harness"];
13052
13447
  let output;
13053
13448
  try {
13054
- const raw = execFileSync7(cmd, args, { encoding: "utf-8", timeout: 5e3 });
13449
+ const raw = execFileSync8(cmd, args, { encoding: "utf-8", timeout: 5e3 });
13055
13450
  if (typeof raw !== "string") return [];
13056
13451
  output = raw;
13057
13452
  } catch {
@@ -13128,7 +13523,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
13128
13523
  }
13129
13524
  try {
13130
13525
  logger.info(`Uninstalling: ${cmd.display}`);
13131
- execFileSync7(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
13526
+ execFileSync8(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
13132
13527
  } catch {
13133
13528
  logger.warn(`Uninstall failed for ${cmd.install.binPath}.`);
13134
13529
  console.log(` Run manually: ${chalk18.cyan(cmd.display)}`);
@@ -13188,7 +13583,7 @@ function refreshHooks() {
13188
13583
  function runLocalGraphScan() {
13189
13584
  try {
13190
13585
  logger.info("Scanning codebase to rebuild knowledge graph...");
13191
- execFileSync7("harness", ["graph", "scan", "."], { stdio: "inherit" });
13586
+ execFileSync8("harness", ["graph", "scan", "."], { stdio: "inherit" });
13192
13587
  } catch {
13193
13588
  logger.warn("Graph scan failed. Run manually:");
13194
13589
  console.log(` ${chalk18.cyan("harness graph scan .")}`);
@@ -13203,7 +13598,7 @@ async function offerRegeneration() {
13203
13598
  const scopeAnswer = await prompt3("Generate for (G)lobal or (l)ocal project? (G/l) ");
13204
13599
  const isGlobal = scopeAnswer !== "l" && scopeAnswer !== "local";
13205
13600
  try {
13206
- execFileSync7("harness", ["generate", ...isGlobal ? ["--global"] : []], {
13601
+ execFileSync8("harness", ["generate", ...isGlobal ? ["--global"] : []], {
13207
13602
  stdio: "inherit"
13208
13603
  });
13209
13604
  } catch {
@@ -13283,7 +13678,7 @@ async function runUpdateAction(opts, globalOpts) {
13283
13678
  }
13284
13679
  try {
13285
13680
  logger.info("Updating packages...");
13286
- execFileSync7(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
13681
+ execFileSync8(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
13287
13682
  console.log("");
13288
13683
  logger.success("Update complete");
13289
13684
  invalidateCheckState();
@@ -13300,7 +13695,7 @@ async function runUpdateAction(opts, globalOpts) {
13300
13695
  process.exit(ExitCode.SUCCESS);
13301
13696
  }
13302
13697
  function createUpdateCommand() {
13303
- return new Command116("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").option("--force", "Force update even if versions match").option(
13698
+ return new Command118("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(
13304
13699
  "--regenerate",
13305
13700
  "Only regenerate slash commands and agent definitions (skip package updates)"
13306
13701
  ).action(async (opts, cmd) => {
@@ -13310,9 +13705,9 @@ function createUpdateCommand() {
13310
13705
  }
13311
13706
 
13312
13707
  // src/commands/usage.ts
13313
- import { Command as Command117 } from "commander";
13708
+ import { Command as Command119 } from "commander";
13314
13709
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
13315
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-72ID44UE.js");
13710
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-LHINSVK4.js");
13316
13711
  const records = readCostRecords(cwd);
13317
13712
  if (includeClaudeSessions) {
13318
13713
  const ccRecords = parseCCRecords();
@@ -13405,7 +13800,7 @@ function registerDailyCommand(usage) {
13405
13800
  else logger.info("No usage data found. Run some harness sessions first.");
13406
13801
  return;
13407
13802
  }
13408
- const { aggregateByDay } = await import("./dist-72ID44UE.js");
13803
+ const { aggregateByDay } = await import("./dist-LHINSVK4.js");
13409
13804
  const limited = aggregateByDay(records).slice(0, days);
13410
13805
  if (globalOpts.json) {
13411
13806
  console.log(
@@ -13434,7 +13829,7 @@ function registerSessionsCommand(usage) {
13434
13829
  }
13435
13830
  return;
13436
13831
  }
13437
- const { aggregateBySession } = await import("./dist-72ID44UE.js");
13832
+ const { aggregateBySession } = await import("./dist-LHINSVK4.js");
13438
13833
  const sessionData = aggregateBySession(records);
13439
13834
  const limited = sessionData.slice(0, limit);
13440
13835
  if (globalOpts.json) {
@@ -13514,7 +13909,7 @@ function registerSessionCommand(usage) {
13514
13909
  cwd,
13515
13910
  globalOpts.includeClaudeSessions
13516
13911
  );
13517
- const { aggregateBySession } = await import("./dist-72ID44UE.js");
13912
+ const { aggregateBySession } = await import("./dist-LHINSVK4.js");
13518
13913
  const sessionData = aggregateBySession(records);
13519
13914
  const match = sessionData.find((s) => s.sessionId === id);
13520
13915
  if (!match) {
@@ -13549,7 +13944,7 @@ function registerLatestCommand(usage) {
13549
13944
  }
13550
13945
  return;
13551
13946
  }
13552
- const { aggregateBySession } = await import("./dist-72ID44UE.js");
13947
+ const { aggregateBySession } = await import("./dist-LHINSVK4.js");
13553
13948
  const sessionData = aggregateBySession(records);
13554
13949
  const latest = sessionData[0];
13555
13950
  if (!latest) {
@@ -13575,7 +13970,7 @@ function registerLatestCommand(usage) {
13575
13970
  });
13576
13971
  }
13577
13972
  function createUsageCommand() {
13578
- const usage = new Command117("usage").description("Token usage and cost tracking");
13973
+ const usage = new Command119("usage").description("Token usage and cost tracking");
13579
13974
  usage.option(
13580
13975
  "--include-claude-sessions",
13581
13976
  "Include Claude Code session data from ~/.claude/projects/"
@@ -13590,15 +13985,16 @@ function createUsageCommand() {
13590
13985
  // src/commands/validate.ts
13591
13986
  init_dist3();
13592
13987
  init_dist3();
13593
- import { Command as Command118 } from "commander";
13594
- import * as path71 from "path";
13988
+ import { Command as Command120 } from "commander";
13989
+ import * as fs48 from "fs";
13990
+ import * as path72 from "path";
13595
13991
  async function runValidate(options) {
13596
13992
  const configResult = resolveConfig(options.configPath);
13597
13993
  if (!configResult.ok) {
13598
13994
  return configResult;
13599
13995
  }
13600
13996
  const config = configResult.value;
13601
- const cwd = options.cwd ?? (options.configPath ? path71.dirname(path71.resolve(options.configPath)) : process.cwd());
13997
+ const cwd = options.cwd ?? (options.configPath ? path72.dirname(path72.resolve(options.configPath)) : process.cwd());
13602
13998
  const result = {
13603
13999
  valid: true,
13604
14000
  checks: {
@@ -13608,7 +14004,7 @@ async function runValidate(options) {
13608
14004
  },
13609
14005
  issues: []
13610
14006
  };
13611
- const agentsMapPath = path71.resolve(cwd, config.agentsMapPath);
14007
+ const agentsMapPath = path72.resolve(cwd, config.agentsMapPath);
13612
14008
  const agentsResult = await validateAgentsMap(agentsMapPath);
13613
14009
  if (agentsResult.ok) {
13614
14010
  result.checks.agentsMap = true;
@@ -13659,6 +14055,22 @@ async function runValidate(options) {
13659
14055
  }
13660
14056
  });
13661
14057
  }
14058
+ const strategyResult = await validateStrategy(cwd);
14059
+ if (strategyResult.ok) {
14060
+ result.checks.strategyConfig = true;
14061
+ } else {
14062
+ result.valid = false;
14063
+ result.checks.strategyConfig = false;
14064
+ result.issues.push({
14065
+ check: "strategyConfig",
14066
+ file: "STRATEGY.md",
14067
+ severity: "error",
14068
+ message: strategyResult.error.message,
14069
+ ...strategyResult.error.suggestions?.[0] !== void 0 && {
14070
+ suggestion: strategyResult.error.suggestions[0]
14071
+ }
14072
+ });
14073
+ }
13662
14074
  const solutionsResult = await validateSolutionsDir(cwd);
13663
14075
  if (solutionsResult.ok) {
13664
14076
  result.checks.solutionsDir = true;
@@ -13689,6 +14101,25 @@ async function runValidate(options) {
13689
14101
  }
13690
14102
  });
13691
14103
  }
14104
+ const roadmapPath = path72.join(cwd, "docs", "roadmap.md");
14105
+ if (fs48.existsSync(roadmapPath)) {
14106
+ const parsed = parseRoadmap(fs48.readFileSync(roadmapPath, "utf-8"));
14107
+ if (parsed.ok) {
14108
+ const findings = checkRoadmapHealth(parsed.value);
14109
+ result.checks.roadmapHealth = !findings.some((f) => f.severity === "error");
14110
+ if (!result.checks.roadmapHealth) result.valid = false;
14111
+ for (const finding of findings) {
14112
+ result.issues.push({
14113
+ check: "roadmapHealth",
14114
+ file: "docs/roadmap.md",
14115
+ ruleId: finding.ruleId,
14116
+ severity: finding.severity === "error" ? "error" : "warning",
14117
+ message: finding.feature ? `${finding.feature} (${finding.milestone}): ${finding.message}` : finding.message,
14118
+ ...finding.suggestion !== void 0 && { suggestion: finding.suggestion }
14119
+ });
14120
+ }
14121
+ }
14122
+ }
13692
14123
  const anatomyEnabled = config.design?.audit?.componentAnatomy?.enabled !== false;
13693
14124
  if (anatomyEnabled) {
13694
14125
  try {
@@ -13814,11 +14245,11 @@ function resolveValidateMode(globalOpts) {
13814
14245
  return OutputMode.TEXT;
13815
14246
  }
13816
14247
  async function printCrossCheckWarnings(mode) {
13817
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-AUUZFNVL.js");
14248
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-QPSAOZKD.js");
13818
14249
  const cwd = process.cwd();
13819
14250
  const crossResult = await runCrossCheck2({
13820
- specsDir: path71.join(cwd, "docs", "specs"),
13821
- plansDir: path71.join(cwd, "docs", "plans"),
14251
+ specsDir: path72.join(cwd, "docs", "specs"),
14252
+ plansDir: path72.join(cwd, "docs", "plans"),
13822
14253
  projectPath: cwd
13823
14254
  });
13824
14255
  if (!crossResult.ok || crossResult.value.warnings === 0) return;
@@ -13830,7 +14261,7 @@ async function printCrossCheckWarnings(mode) {
13830
14261
  ${crossResult.value.warnings} warnings`);
13831
14262
  }
13832
14263
  function createValidateCommand3() {
13833
- const command = new Command118("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
14264
+ const command = new Command120("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
13834
14265
  "--agent-configs",
13835
14266
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
13836
14267
  ).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()));
@@ -13879,7 +14310,7 @@ Agent configs checked via ${engineLabel}${note}`);
13879
14310
 
13880
14311
  // src/commands/verify.ts
13881
14312
  init_dist3();
13882
- import { Command as Command119 } from "commander";
14313
+ import { Command as Command121 } from "commander";
13883
14314
  import { execSync as execSync6 } from "child_process";
13884
14315
  function loadBranchingConfig(configPath) {
13885
14316
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -13942,7 +14373,7 @@ async function runVerify(options) {
13942
14373
  process.exit(ExitCode.VALIDATION_FAILED);
13943
14374
  }
13944
14375
  function createVerifyCommand() {
13945
- return new Command119("verify").description(
14376
+ return new Command121("verify").description(
13946
14377
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
13947
14378
  ).option(
13948
14379
  "--branch <name>",
@@ -13971,6 +14402,7 @@ var commandCreators = [
13971
14402
  createCheckDepsCommand,
13972
14403
  createCheckDesignCommand,
13973
14404
  createCheckDocsCommand,
14405
+ createCheckHarnessStrengthCommand,
13974
14406
  createCheckPerfCommand,
13975
14407
  createCheckPhaseGateCommand,
13976
14408
  createCheckSecurityCommand,
@@ -14017,6 +14449,7 @@ var commandCreators = [
14017
14449
  createPulseCommand,
14018
14450
  createQueryCommand,
14019
14451
  createRecommendCommand,
14452
+ createReviewCiCommand,
14020
14453
  createRoadmapCommand,
14021
14454
  createRoutingCommand,
14022
14455
  createScanCommand,
@@ -14046,7 +14479,7 @@ var commandCreators = [
14046
14479
 
14047
14480
  // src/index.ts
14048
14481
  function createProgram() {
14049
- const program = new Command120();
14482
+ const program = new Command122();
14050
14483
  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");
14051
14484
  for (const creator of commandCreators) {
14052
14485
  program.addCommand(creator());