@harness-engineering/cli 2.8.0 → 3.0.1

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 (120) hide show
  1. package/dist/agents/skills/claude-code/harness-audit-harness-strength/SKILL.md +188 -0
  2. package/dist/agents/skills/claude-code/harness-audit-harness-strength/skill.yaml +54 -0
  3. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +2 -0
  4. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +28 -14
  5. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +1 -1
  6. package/dist/agents/skills/claude-code/harness-git-workflow/SKILL.md +2 -0
  7. package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +2 -0
  8. package/dist/agents/skills/claude-code/harness-knowledge-pipeline/SKILL.md +2 -0
  9. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +62 -4
  10. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +2 -0
  11. package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +80 -2
  12. package/dist/agents/skills/claude-code/harness-test-advisor/skill.yaml +4 -1
  13. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +27 -25
  14. package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +1 -0
  15. package/dist/agents/skills/claude-code/outcome-eval/SKILL.md +97 -0
  16. package/dist/agents/skills/claude-code/outcome-eval/skill.yaml +51 -0
  17. package/dist/agents/skills/codex/harness-audit-harness-strength/SKILL.md +188 -0
  18. package/dist/agents/skills/codex/harness-audit-harness-strength/skill.yaml +54 -0
  19. package/dist/agents/skills/codex/harness-autopilot/SKILL.md +2 -0
  20. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +28 -14
  21. package/dist/agents/skills/codex/harness-execution/SKILL.md +1 -1
  22. package/dist/agents/skills/codex/harness-git-workflow/SKILL.md +2 -0
  23. package/dist/agents/skills/codex/harness-ideate/SKILL.md +2 -0
  24. package/dist/agents/skills/codex/harness-knowledge-pipeline/SKILL.md +2 -0
  25. package/dist/agents/skills/codex/harness-roadmap/SKILL.md +62 -4
  26. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +2 -0
  27. package/dist/agents/skills/codex/harness-test-advisor/SKILL.md +80 -2
  28. package/dist/agents/skills/codex/harness-test-advisor/skill.yaml +4 -1
  29. package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +27 -25
  30. package/dist/agents/skills/codex/initialize-harness-project/skill.yaml +1 -0
  31. package/dist/agents/skills/codex/outcome-eval/SKILL.md +97 -0
  32. package/dist/agents/skills/codex/outcome-eval/skill.yaml +51 -0
  33. package/dist/agents/skills/cursor/harness-audit-harness-strength/SKILL.md +188 -0
  34. package/dist/agents/skills/cursor/harness-audit-harness-strength/skill.yaml +54 -0
  35. package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +2 -0
  36. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +28 -14
  37. package/dist/agents/skills/cursor/harness-execution/SKILL.md +1 -1
  38. package/dist/agents/skills/cursor/harness-git-workflow/SKILL.md +2 -0
  39. package/dist/agents/skills/cursor/harness-ideate/SKILL.md +2 -0
  40. package/dist/agents/skills/cursor/harness-knowledge-pipeline/SKILL.md +2 -0
  41. package/dist/agents/skills/cursor/harness-roadmap/SKILL.md +62 -4
  42. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +2 -0
  43. package/dist/agents/skills/cursor/harness-test-advisor/SKILL.md +80 -2
  44. package/dist/agents/skills/cursor/harness-test-advisor/skill.yaml +4 -1
  45. package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +27 -25
  46. package/dist/agents/skills/cursor/initialize-harness-project/skill.yaml +1 -0
  47. package/dist/agents/skills/cursor/outcome-eval/SKILL.md +97 -0
  48. package/dist/agents/skills/cursor/outcome-eval/skill.yaml +51 -0
  49. package/dist/agents/skills/gemini-cli/harness-audit-harness-strength/SKILL.md +188 -0
  50. package/dist/agents/skills/gemini-cli/harness-audit-harness-strength/skill.yaml +54 -0
  51. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +2 -0
  52. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +28 -14
  53. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +1 -1
  54. package/dist/agents/skills/gemini-cli/harness-git-workflow/SKILL.md +2 -0
  55. package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +2 -0
  56. package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/SKILL.md +2 -0
  57. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +62 -4
  58. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +2 -0
  59. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +80 -2
  60. package/dist/agents/skills/gemini-cli/harness-test-advisor/skill.yaml +4 -1
  61. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +27 -25
  62. package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +1 -0
  63. package/dist/agents/skills/gemini-cli/outcome-eval/SKILL.md +97 -0
  64. package/dist/agents/skills/gemini-cli/outcome-eval/skill.yaml +51 -0
  65. package/dist/agents/skills/tests/harness-test-advisor.test.ts +94 -0
  66. package/dist/{agents-md-WMJO5HSM.js → agents-md-XOJE5ETA.js} +2 -2
  67. package/dist/{architecture-EVYVGPRZ.js → architecture-JEZPJ725.js} +3 -3
  68. package/dist/{assess-project-KZG563SO.js → assess-project-RHXOQNMM.js} +1 -1
  69. package/dist/bin/harness-mcp.js +13 -13
  70. package/dist/bin/harness.js +22 -22
  71. package/dist/{check-phase-gate-MK364VXS.js → check-phase-gate-GNDOMS35.js} +3 -3
  72. package/dist/{chunk-VBNJAKUH.js → chunk-3ISHDWO7.js} +1 -1
  73. package/dist/{chunk-UJFNIWC7.js → chunk-527G27VI.js} +2 -2
  74. package/dist/{chunk-5XL5QJ5B.js → chunk-6WQCLCBO.js} +1 -1
  75. package/dist/{chunk-UXPWSV3B.js → chunk-BYVT5LVO.js} +3 -3
  76. package/dist/{chunk-HRSE6IQD.js → chunk-DE5U6KOL.js} +1 -1
  77. package/dist/{chunk-B7KMTHN3.js → chunk-GGKRA7A7.js} +1 -1
  78. package/dist/{chunk-STESM73J.js → chunk-GSP2XIVS.js} +1 -1
  79. package/dist/{chunk-KBCPELBC.js → chunk-HEIMJJI4.js} +2 -2
  80. package/dist/{chunk-KI6PHH6Q.js → chunk-HWTUUQOW.js} +3 -3
  81. package/dist/{chunk-2SNRCAC3.js → chunk-KAJOS3BA.js} +2 -2
  82. package/dist/{chunk-C7J55C6E.js → chunk-MGUPSE6D.js} +5 -5
  83. package/dist/{chunk-GOHWCHCS.js → chunk-N24HCQA4.js} +2243 -776
  84. package/dist/{chunk-EEFRPEWT.js → chunk-NWLGL3IR.js} +1 -1
  85. package/dist/{chunk-UUO4K7NX.js → chunk-ONCPJGHY.js} +6 -6
  86. package/dist/{chunk-X4EFYVCZ.js → chunk-PC2R5RUJ.js} +1 -1
  87. package/dist/{chunk-7EQAZKJ5.js → chunk-QBC7DI4Q.js} +1 -1
  88. package/dist/{chunk-UBZQE3JN.js → chunk-UX3PQKVZ.js} +7 -2
  89. package/dist/{chunk-CAQPSFPT.js → chunk-WWEVS7RO.js} +453 -91
  90. package/dist/{chunk-4BDOSCNY.js → chunk-XFU6SB2Q.js} +1015 -648
  91. package/dist/{chunk-LADPYELQ.js → chunk-XX4OLNWQ.js} +2 -2
  92. package/dist/{chunk-FZ5MBXEG.js → chunk-YQSYCBAH.js} +6 -6
  93. package/dist/{chunk-ACOOG3UW.js → chunk-Z4AWEIBY.js} +3 -3
  94. package/dist/{ci-workflow-IW2H5DC4.js → ci-workflow-ORZ4F45F.js} +2 -2
  95. package/dist/{dist-JCFK263L.js → dist-LHINSVK4.js} +85 -1
  96. package/dist/{docs-7CP6VV42.js → docs-AU3DXFFO.js} +3 -3
  97. package/dist/{engine-MKJEBWU7.js → engine-6GPWOYQH.js} +2 -2
  98. package/dist/{entropy-6JOZJYG7.js → entropy-VLKDRMRT.js} +2 -2
  99. package/dist/{feedback-T65AEJEG.js → feedback-YXYY44ZC.js} +1 -1
  100. package/dist/{generate-agent-definitions-4VI4YTO2.js → generate-agent-definitions-XIHQPKG3.js} +3 -3
  101. package/dist/hooks/cost-tracker.js +29 -6
  102. package/dist/index.d.ts +8 -8
  103. package/dist/index.js +22 -22
  104. package/dist/{loader-AWTHHE3A.js → loader-YAN56MT3.js} +2 -2
  105. package/dist/{mcp-JBIBINO2.js → mcp-RK3SFVYB.js} +13 -13
  106. package/dist/{performance-NCOUDOMW.js → performance-64DPTLLQ.js} +3 -3
  107. package/dist/{review-pipeline-YIC6JPMY.js → review-pipeline-NENG6LW7.js} +2 -2
  108. package/dist/{runtime-5MHV4UEE.js → runtime-FFIIRT2T.js} +2 -2
  109. package/dist/{security-VZPJNIDP.js → security-3PIBN35B.js} +1 -1
  110. package/dist/templates/basic/harness.config.json.hbs +34 -0
  111. package/dist/templates/ci/README.md +86 -0
  112. package/dist/templates/ci/required-review.ruleset.json +20 -0
  113. package/dist/templates/ci/required-review.yml.hbs +57 -0
  114. package/dist/templates/ci/template.json +5 -0
  115. package/dist/templates/intermediate/harness.config.json.hbs +36 -0
  116. package/dist/templates/orchestrator/harness.orchestrator.md +9 -0
  117. package/dist/{tool-tiers-B7JC2XC3.js → tool-tiers-OKK5FE57.js} +2 -0
  118. package/dist/{validate-7BE4VTFI.js → validate-7IAF2ES3.js} +3 -3
  119. package/dist/{validate-cross-check-F7GEBRDH.js → validate-cross-check-QPSAOZKD.js} +2 -2
  120. package/package.json +7 -7
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  generateRuntime
3
- } from "./chunk-5XL5QJ5B.js";
3
+ } from "./chunk-6WQCLCBO.js";
4
4
  import {
5
5
  generateAgentsMd
6
- } from "./chunk-7EQAZKJ5.js";
6
+ } from "./chunk-QBC7DI4Q.js";
7
7
  import {
8
8
  generateCIWorkflow
9
- } from "./chunk-STESM73J.js";
9
+ } from "./chunk-GSP2XIVS.js";
10
10
  import {
11
11
  createGenerateAgentDefinitionsCommand,
12
12
  generateAgentDefinitions
13
- } from "./chunk-EEFRPEWT.js";
13
+ } from "./chunk-NWLGL3IR.js";
14
14
  import {
15
15
  toKebabCase
16
16
  } from "./chunk-KET4QQZB.js";
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-2N4OENGE.js";
21
21
  import {
22
22
  TemplateEngine
23
- } from "./chunk-UBZQE3JN.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-X4EFYVCZ.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-2SNRCAC3.js";
49
+ } from "./chunk-KAJOS3BA.js";
50
50
  import {
51
51
  appendFrameworkAgents,
52
52
  captureHealthSnapshot,
@@ -74,7 +74,7 @@ import {
74
74
  runSecurityCraft,
75
75
  runSpecCraft,
76
76
  runTestCraft
77
- } from "./chunk-CAQPSFPT.js";
77
+ } from "./chunk-WWEVS7RO.js";
78
78
  import {
79
79
  VALID_PLATFORMS
80
80
  } from "./chunk-3ISINLYT.js";
@@ -99,7 +99,7 @@ import {
99
99
  BranchingConfigSchema,
100
100
  findConfigFile,
101
101
  resolveConfig
102
- } from "./chunk-B7KMTHN3.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,
@@ -194,7 +199,7 @@ import {
194
199
  validateStrategy,
195
200
  writeConfig,
196
201
  writeLockfile
197
- } from "./chunk-GOHWCHCS.js";
202
+ } from "./chunk-N24HCQA4.js";
198
203
  import {
199
204
  CLI_VERSION
200
205
  } from "./chunk-BM3PWGXQ.js";
@@ -231,7 +236,7 @@ import {
231
236
  } from "./chunk-KFQGP6VL.js";
232
237
 
233
238
  // src/index.ts
234
- import { Command as Command120 } from "commander";
239
+ import { Command as Command122 } from "commander";
235
240
 
236
241
  // src/commands/add.ts
237
242
  init_dist3();
@@ -420,7 +425,7 @@ function registerSkillsCommand(adoption) {
420
425
  const globalOpts = cmd.optsWithGlobals();
421
426
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
422
427
  const cwd = process.cwd();
423
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-JCFK263L.js");
428
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-LHINSVK4.js");
424
429
  const records = readAdoptionRecords(cwd);
425
430
  if (records.length === 0) {
426
431
  if (globalOpts.json) {
@@ -456,7 +461,7 @@ function registerRecentCommand(adoption) {
456
461
  const globalOpts = cmd.optsWithGlobals();
457
462
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
458
463
  const cwd = process.cwd();
459
- const { readAdoptionRecords } = await import("./dist-JCFK263L.js");
464
+ const { readAdoptionRecords } = await import("./dist-LHINSVK4.js");
460
465
  const records = readAdoptionRecords(cwd);
461
466
  if (records.length === 0) {
462
467
  if (globalOpts.json) {
@@ -534,7 +539,7 @@ function registerSkillCommand(adoption) {
534
539
  adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
535
540
  const globalOpts = cmd.optsWithGlobals();
536
541
  const cwd = process.cwd();
537
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-JCFK263L.js");
542
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-LHINSVK4.js");
538
543
  const records = readAdoptionRecords(cwd);
539
544
  const skillRecords = records.filter((r) => r.skill === name);
540
545
  if (skillRecords.length === 0) {
@@ -1664,9 +1669,9 @@ ${name} (${count} finding${count === 1 ? "" : "s"})`);
1664
1669
  }
1665
1670
  function printAnatomyFindings(findings, verbose) {
1666
1671
  const byFile = groupByFile(findings, (f) => f.file);
1667
- for (const [file, fs48] of byFile) {
1672
+ for (const [file, fs49] of byFile) {
1668
1673
  console.log(` ${file}`);
1669
- for (const f of fs48) {
1674
+ for (const f of fs49) {
1670
1675
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1671
1676
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1672
1677
  if (verbose) {
@@ -1677,9 +1682,9 @@ function printAnatomyFindings(findings, verbose) {
1677
1682
  }
1678
1683
  function printCraftFindings(findings, verbose) {
1679
1684
  const byFile = groupByFile(findings, (f) => f.target.file);
1680
- for (const [file, fs48] of byFile) {
1685
+ for (const [file, fs49] of byFile) {
1681
1686
  console.log(` ${file}`);
1682
- for (const f of fs48) {
1687
+ for (const f of fs49) {
1683
1688
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
1684
1689
  const sev = craftTierToSeverity(f.tier);
1685
1690
  console.log(
@@ -1693,9 +1698,9 @@ function printCraftFindings(findings, verbose) {
1693
1698
  }
1694
1699
  function printDriftFindings(findings, verbose) {
1695
1700
  const byFile = groupByFile(findings, (f) => f.file);
1696
- for (const [file, fs48] of byFile) {
1701
+ for (const [file, fs49] of byFile) {
1697
1702
  console.log(` ${file}`);
1698
- for (const f of fs48) {
1703
+ for (const f of fs49) {
1699
1704
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1700
1705
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1701
1706
  if (verbose) {
@@ -1706,9 +1711,9 @@ function printDriftFindings(findings, verbose) {
1706
1711
  }
1707
1712
  function printBrandFindings(findings, verbose) {
1708
1713
  const byFile = groupByFile(findings, (f) => f.file);
1709
- for (const [file, fs48] of byFile) {
1714
+ for (const [file, fs49] of byFile) {
1710
1715
  console.log(` ${file}`);
1711
- for (const f of fs48) {
1716
+ for (const f of fs49) {
1712
1717
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1713
1718
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1714
1719
  if (verbose) {
@@ -1877,14 +1882,90 @@ function createCheckDocsCommand() {
1877
1882
  return command;
1878
1883
  }
1879
1884
 
1880
- // src/commands/check-perf.ts
1885
+ // src/commands/check-harness-strength.ts
1881
1886
  init_dist3();
1882
1887
  import { Command as Command14 } from "commander";
1883
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";
1884
1965
  async function runCheckPerf(cwd, options) {
1885
1966
  const runAll2 = !options.structural && !options.size && !options.coupling;
1886
1967
  const analyzer = new EntropyAnalyzer({
1887
- rootDir: path8.resolve(cwd),
1968
+ rootDir: path9.resolve(cwd),
1888
1969
  analyze: {
1889
1970
  complexity: runAll2 || !!options.structural,
1890
1971
  coupling: runAll2 || !!options.coupling,
@@ -1996,7 +2077,7 @@ async function runCheckPerfAction(opts, globalOpts) {
1996
2077
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
1997
2078
  }
1998
2079
  function createCheckPerfCommand() {
1999
- 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) => {
2000
2081
  await runCheckPerfAction(opts, cmd.optsWithGlobals());
2001
2082
  });
2002
2083
  return command;
@@ -2004,10 +2085,10 @@ function createCheckPerfCommand() {
2004
2085
 
2005
2086
  // src/commands/check-security.ts
2006
2087
  init_dist3();
2007
- import { Command as Command15 } from "commander";
2008
- import * as path9 from "path";
2088
+ import { Command as Command16 } from "commander";
2089
+ import * as path10 from "path";
2009
2090
  import { execSync as execSync3 } from "child_process";
2010
- var SEVERITY_RANK = {
2091
+ var SEVERITY_RANK2 = {
2011
2092
  error: 3,
2012
2093
  warning: 2,
2013
2094
  info: 1
@@ -2018,19 +2099,19 @@ function getChangedFiles(cwd) {
2018
2099
  cwd,
2019
2100
  encoding: "utf-8"
2020
2101
  });
2021
- 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));
2022
2103
  } catch {
2023
2104
  return [];
2024
2105
  }
2025
2106
  }
2026
2107
  async function runCheckSecurity(cwd, options) {
2027
- const projectRoot2 = path9.resolve(cwd);
2108
+ const projectRoot2 = path10.resolve(cwd);
2028
2109
  let configData = {};
2029
2110
  try {
2030
- const fs48 = await import("fs");
2031
- const configPath = path9.join(projectRoot2, "harness.config.json");
2032
- if (fs48.existsSync(configPath)) {
2033
- 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");
2034
2115
  const parsed = JSON.parse(raw);
2035
2116
  configData = parsed.security ?? {};
2036
2117
  }
@@ -2065,8 +2146,8 @@ async function runCheckSecurity(cwd, options) {
2065
2146
  } catch {
2066
2147
  }
2067
2148
  const threshold = options.severity ?? "warning";
2068
- const thresholdRank = SEVERITY_RANK[threshold];
2069
- 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);
2070
2151
  const hasErrors = filtered.some((f) => f.severity === "error");
2071
2152
  return Ok({
2072
2153
  valid: !hasErrors,
@@ -2109,7 +2190,7 @@ async function runCheckSecurityAction(opts, globalOpts) {
2109
2190
  process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
2110
2191
  }
2111
2192
  function createCheckSecurityCommand() {
2112
- 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) => {
2113
2194
  const severity = thisCommand.opts().severity;
2114
2195
  if (!["error", "warning", "info"].includes(severity)) {
2115
2196
  logger.error(`Invalid severity: "${severity}". Must be one of: error, warning, info`);
@@ -2122,11 +2203,11 @@ function createCheckSecurityCommand() {
2122
2203
  }
2123
2204
 
2124
2205
  // src/commands/ci/index.ts
2125
- import { Command as Command19 } from "commander";
2206
+ import { Command as Command20 } from "commander";
2126
2207
 
2127
2208
  // src/commands/ci/check.ts
2128
2209
  init_dist3();
2129
- import { Command as Command16 } from "commander";
2210
+ import { Command as Command17 } from "commander";
2130
2211
  var VALID_CHECKS = [
2131
2212
  "validate",
2132
2213
  "deps",
@@ -2216,16 +2297,16 @@ async function runCheckAction(opts, globalOpts) {
2216
2297
  process.exit(report.exitCode);
2217
2298
  }
2218
2299
  function createCheckCommand() {
2219
- 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) => {
2220
2301
  await runCheckAction(opts, cmd.optsWithGlobals());
2221
2302
  });
2222
2303
  }
2223
2304
 
2224
2305
  // src/commands/ci/init.ts
2225
2306
  init_dist3();
2226
- import { Command as Command17 } from "commander";
2307
+ import { Command as Command18 } from "commander";
2227
2308
  import * as fs4 from "fs";
2228
- import * as path10 from "path";
2309
+ import * as path11 from "path";
2229
2310
  var ALL_CHECKS = [
2230
2311
  "validate",
2231
2312
  "deps",
@@ -2243,8 +2324,74 @@ function buildSkipFlag(checks) {
2243
2324
  if (skipChecks.length === 0) return "";
2244
2325
  return ` --skip ${skipChecks.join(",")}`;
2245
2326
  }
2246
- function generateGitHubActions(skipFlag) {
2247
- 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
2248
2395
 
2249
2396
  on:
2250
2397
  push:
@@ -2257,15 +2404,15 @@ concurrency:
2257
2404
  cancel-in-progress: true
2258
2405
 
2259
2406
  jobs:
2260
- harness:
2407
+ ci:
2261
2408
  runs-on: ubuntu-latest
2262
2409
  steps:
2263
2410
  - uses: actions/checkout@v4
2264
- - uses: actions/setup-node@v4
2265
- with:
2266
- node-version: '22'
2267
- - run: npm install -g @harness-engineering/cli
2268
- - 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
2269
2416
  run: harness ci check --json${skipFlag}
2270
2417
  `;
2271
2418
  }
@@ -2310,10 +2457,13 @@ exit $EXIT_CODE
2310
2457
  `;
2311
2458
  }
2312
2459
  function generateCIConfig(options) {
2313
- const { platform, checks } = options;
2460
+ const { platform, checks, language } = options;
2314
2461
  const skipFlag = buildSkipFlag(checks);
2315
2462
  const generators = {
2316
- github: { filename: ".github/workflows/harness.yml", generate: generateGitHubActions },
2463
+ github: {
2464
+ filename: ".github/workflows/ci.yml",
2465
+ generate: (skip) => generateGitHubActions(skip, language)
2466
+ },
2317
2467
  gitlab: { filename: ".gitlab-ci-harness.yml", generate: generateGitLabCI },
2318
2468
  generic: { filename: "harness-ci.sh", generate: generateGenericScript }
2319
2469
  };
@@ -2332,8 +2482,8 @@ function detectPlatform() {
2332
2482
  return null;
2333
2483
  }
2334
2484
  function writeGeneratedConfig(filename, content, platform) {
2335
- const targetPath = path10.resolve(filename);
2336
- const dir = path10.dirname(targetPath);
2485
+ const targetPath = path11.resolve(filename);
2486
+ const dir = path11.dirname(targetPath);
2337
2487
  fs4.mkdirSync(dir, { recursive: true });
2338
2488
  fs4.writeFileSync(targetPath, content);
2339
2489
  if (platform === "generic" && process.platform !== "win32") {
@@ -2345,6 +2495,7 @@ async function runInitAction(opts, globalOpts) {
2345
2495
  const checks = opts.checks ? opts.checks.split(",").map((s) => s.trim()) : void 0;
2346
2496
  const configOpts = { platform };
2347
2497
  if (checks) configOpts.checks = checks;
2498
+ if (opts.language) configOpts.language = opts.language;
2348
2499
  const result = generateCIConfig(configOpts);
2349
2500
  if (!result.ok) {
2350
2501
  logger.error(result.error.message);
@@ -2360,14 +2511,14 @@ async function runInitAction(opts, globalOpts) {
2360
2511
  }
2361
2512
  }
2362
2513
  function createInitCommand() {
2363
- 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) => {
2364
2515
  await runInitAction(opts, cmd.optsWithGlobals());
2365
2516
  });
2366
2517
  }
2367
2518
 
2368
2519
  // src/commands/ci/notify.ts
2369
2520
  init_dist3();
2370
- import { Command as Command18 } from "commander";
2521
+ import { Command as Command19 } from "commander";
2371
2522
  import * as fs5 from "fs";
2372
2523
  function loadReport(reportPath) {
2373
2524
  try {
@@ -2464,14 +2615,14 @@ async function runNotifyAction(reportPath, opts, globalOpts) {
2464
2615
  }
2465
2616
  }
2466
2617
  function createNotifyCommand() {
2467
- 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) => {
2468
2619
  await runNotifyAction(reportPath, opts, cmd.optsWithGlobals());
2469
2620
  });
2470
2621
  }
2471
2622
 
2472
2623
  // src/commands/ci/index.ts
2473
2624
  function createCICommand() {
2474
- const command = new Command19("ci").description("CI/CD integration commands");
2625
+ const command = new Command20("ci").description("CI/CD integration commands");
2475
2626
  command.addCommand(createCheckCommand());
2476
2627
  command.addCommand(createInitCommand());
2477
2628
  command.addCommand(createNotifyCommand());
@@ -2480,8 +2631,8 @@ function createCICommand() {
2480
2631
 
2481
2632
  // src/commands/cleanup.ts
2482
2633
  init_dist3();
2483
- import { Command as Command20 } from "commander";
2484
- import * as path11 from "path";
2634
+ import { Command as Command21 } from "commander";
2635
+ import * as path12 from "path";
2485
2636
  async function runCleanup(options) {
2486
2637
  const cwd = options.cwd ?? process.cwd();
2487
2638
  const type = options.type ?? "all";
@@ -2496,12 +2647,12 @@ async function runCleanup(options) {
2496
2647
  patternViolations: [],
2497
2648
  totalIssues: 0
2498
2649
  };
2499
- const rootDir = path11.resolve(cwd, config.rootDir);
2500
- const docsDir = path11.resolve(cwd, config.docsDir);
2650
+ const rootDir = path12.resolve(cwd, config.rootDir);
2651
+ const docsDir = path12.resolve(cwd, config.docsDir);
2501
2652
  const entropyConfig = {
2502
2653
  rootDir,
2503
2654
  ...config.entropy?.entryPoints && { entryPoints: config.entropy.entryPoints },
2504
- docPaths: [path11.join(docsDir, "**/*.md")],
2655
+ docPaths: [path12.join(docsDir, "**/*.md")],
2505
2656
  analyze: {
2506
2657
  drift: type === "all" || type === "drift",
2507
2658
  deadCode: type === "all" || type === "dead-code",
@@ -2569,7 +2720,7 @@ function printCleanupResult(value, formatter) {
2569
2720
  }
2570
2721
  }
2571
2722
  function createCleanupCommand() {
2572
- 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) => {
2573
2724
  const globalOpts = cmd.optsWithGlobals();
2574
2725
  const mode = resolveOutputMode(globalOpts);
2575
2726
  const formatter = new OutputFormatter(mode);
@@ -2600,9 +2751,9 @@ function createCleanupCommand() {
2600
2751
 
2601
2752
  // src/commands/cleanup-sessions.ts
2602
2753
  init_dist3();
2603
- import { Command as Command21 } from "commander";
2754
+ import { Command as Command22 } from "commander";
2604
2755
  import * as fs6 from "fs";
2605
- import * as path12 from "path";
2756
+ import * as path13 from "path";
2606
2757
  var STALE_TTL_MS = 24 * 60 * 60 * 1e3;
2607
2758
  var ONE_HOUR_MS = 60 * 60 * 1e3;
2608
2759
  var ONE_DAY_MS = 24 * ONE_HOUR_MS;
@@ -2619,7 +2770,7 @@ function getMostRecentMtime(dirPath) {
2619
2770
  try {
2620
2771
  const entries = fs6.readdirSync(dirPath, { withFileTypes: true });
2621
2772
  for (const entry of entries) {
2622
- const fullPath = path12.join(dirPath, entry.name);
2773
+ const fullPath = path13.join(dirPath, entry.name);
2623
2774
  const stat = fs6.statSync(fullPath);
2624
2775
  if (stat.mtimeMs > latest) latest = stat.mtimeMs;
2625
2776
  }
@@ -2632,7 +2783,7 @@ function getMostRecentMtime(dirPath) {
2632
2783
  async function runCleanupSessions(options) {
2633
2784
  const cwd = options.cwd ?? process.cwd();
2634
2785
  const dryRun = options.dryRun ?? false;
2635
- const sessionsDir = path12.join(cwd, ".harness", "sessions");
2786
+ const sessionsDir = path13.join(cwd, ".harness", "sessions");
2636
2787
  const result = { removed: [], kept: [] };
2637
2788
  if (!fs6.existsSync(sessionsDir)) {
2638
2789
  return Ok(result);
@@ -2651,7 +2802,7 @@ async function runCleanupSessions(options) {
2651
2802
  const now = Date.now();
2652
2803
  for (const entry of entries) {
2653
2804
  if (!entry.isDirectory()) continue;
2654
- const sessionPath = path12.join(sessionsDir, entry.name);
2805
+ const sessionPath = path13.join(sessionsDir, entry.name);
2655
2806
  const mostRecent = getMostRecentMtime(sessionPath);
2656
2807
  const ageMs = now - mostRecent;
2657
2808
  if (ageMs > STALE_TTL_MS) {
@@ -2715,7 +2866,7 @@ async function runCleanupAll(opts) {
2715
2866
  const results = [];
2716
2867
  for (const target of targets) {
2717
2868
  const ttlMs = (ttlOverrides[target.name] ?? 0) > 0 ? ttlOverrides[target.name] * ONE_HOUR_MS : target.defaultTtlMs;
2718
- const dir = path12.join(cwd, ".harness", target.relativeDir);
2869
+ const dir = path13.join(cwd, ".harness", target.relativeDir);
2719
2870
  const sweepResult = await sweepDirectory(dir, ttlMs, dryRun);
2720
2871
  if (!sweepResult.ok) return Err(sweepResult.error);
2721
2872
  results.push({ target: target.name, ...sweepResult.value });
@@ -2739,7 +2890,7 @@ async function sweepDirectory(dir, ttlMs, dryRun) {
2739
2890
  }
2740
2891
  const now = Date.now();
2741
2892
  for (const entry of entries) {
2742
- const entryPath = path12.join(dir, entry.name);
2893
+ const entryPath = path13.join(dir, entry.name);
2743
2894
  const ageMs = now - mtimeOf(entryPath);
2744
2895
  if (ageMs > ttlMs) {
2745
2896
  removed.push(entry.name);
@@ -2796,14 +2947,14 @@ ${dryRun ? "Would remove" : "Removed"} ${totalRemoved} stale entry(ies) across t
2796
2947
  }
2797
2948
  }
2798
2949
  function createCleanupSessionsCommand() {
2799
- const command = new Command21("cleanup-sessions").description(
2950
+ const command = new Command22("cleanup-sessions").description(
2800
2951
  "Remove stale entries from .harness/. Default: only .harness/sessions/ (no write in 24h)."
2801
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(
2802
2953
  "--include <list>",
2803
2954
  "Comma-separated target names (mutually-exclusive with --exclude/--all)"
2804
2955
  ).option("--exclude <list>", "Comma-separated target names to skip").action(async (opts, cmd) => {
2805
2956
  const globalOpts = cmd.optsWithGlobals();
2806
- const cwd = path12.resolve(opts.path);
2957
+ const cwd = path13.resolve(opts.path);
2807
2958
  const asJson = Boolean(globalOpts.json);
2808
2959
  if (opts.all || opts.include || opts.exclude) {
2809
2960
  await runExtendedSweep(cwd, opts, asJson);
@@ -2845,13 +2996,13 @@ async function runSessionsOnlySweep(cwd, opts, asJson) {
2845
2996
  }
2846
2997
 
2847
2998
  // src/commands/compound/index.ts
2848
- import { Command as Command23 } from "commander";
2999
+ import { Command as Command24 } from "commander";
2849
3000
 
2850
3001
  // src/commands/compound/scan-candidates.ts
2851
3002
  init_dist3();
2852
3003
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
2853
- import { dirname as dirname2, join as join8, resolve as resolve11 } from "path";
2854
- 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";
2855
3006
  var HOTSPOT_THRESHOLD = 7;
2856
3007
  var DEFAULT_LOOKBACK = "7d";
2857
3008
  async function runCompoundScanCandidatesCommand(opts) {
@@ -2906,7 +3057,7 @@ function emit(status, nonInteractive) {
2906
3057
  return status;
2907
3058
  }
2908
3059
  function createScanCandidatesCommand() {
2909
- return new Command22("scan-candidates").description(
3060
+ return new Command23("scan-candidates").description(
2910
3061
  "Scan recent fixes and hotspots for undocumented learnings; write candidate prompts"
2911
3062
  ).option("--lookback <window>", "Lookback window (e.g. 7d, 14d).", DEFAULT_LOOKBACK).option(
2912
3063
  "--non-interactive",
@@ -2919,9 +3070,9 @@ function createScanCandidatesCommand() {
2919
3070
  const nonInteractive = options.nonInteractive === true || !process.stdout.isTTY;
2920
3071
  const status = await runCompoundScanCandidatesCommand({
2921
3072
  lookback: options.lookback,
2922
- configPath: resolve11(process.cwd(), options.config),
2923
- outputPath: options.outputPath ? resolve11(process.cwd(), options.outputPath) : void 0,
2924
- 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),
2925
3076
  nonInteractive
2926
3077
  });
2927
3078
  if (status.status === "failure") process.exitCode = 1;
@@ -2931,15 +3082,15 @@ function createScanCandidatesCommand() {
2931
3082
 
2932
3083
  // src/commands/compound/index.ts
2933
3084
  function createCompoundCommand() {
2934
- const command = new Command23("compound").description("Compound (post-mortem playbook) commands");
3085
+ const command = new Command24("compound").description("Compound (post-mortem playbook) commands");
2935
3086
  command.addCommand(createScanCandidatesCommand());
2936
3087
  return command;
2937
3088
  }
2938
3089
 
2939
3090
  // src/commands/copy-craft.ts
2940
- import { Command as Command24 } from "commander";
3091
+ import { Command as Command25 } from "commander";
2941
3092
  function createCopyCraftCommand() {
2942
- return new Command24("copy-craft").description(
3093
+ return new Command25("copy-craft").description(
2943
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."
2944
3095
  ).option("-f, --files <files...>", "Optional source file/glob scope").option(
2945
3096
  "-s, --surfaces <surfaces...>",
@@ -2991,10 +3142,10 @@ function printResult2(result, mode, _formatter) {
2991
3142
  list.push(f);
2992
3143
  bySurface.set(f.target.surface, list);
2993
3144
  }
2994
- for (const [surface, fs48] of bySurface) {
3145
+ for (const [surface, fs49] of bySurface) {
2995
3146
  console.log(`
2996
3147
  [${surface}]`);
2997
- for (const f of fs48) {
3148
+ for (const f of fs49) {
2998
3149
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
2999
3150
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.file}${line}`);
3000
3151
  console.log(` "${truncate(f.target.snippet, 80)}"`);
@@ -3020,11 +3171,11 @@ function truncate(s, n) {
3020
3171
  }
3021
3172
 
3022
3173
  // src/commands/dashboard.ts
3023
- import { Command as Command25 } from "commander";
3174
+ import { Command as Command26 } from "commander";
3024
3175
  import { spawn } from "child_process";
3025
3176
  import { existsSync as existsSync5 } from "fs";
3026
3177
  import { createRequire } from "module";
3027
- 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";
3028
3179
  import { setTimeout } from "timers";
3029
3180
  import { fileURLToPath } from "url";
3030
3181
  var __filename = fileURLToPath(import.meta.url);
@@ -3088,7 +3239,7 @@ function buildDashboardEnv(opts, clientPort, apiPort, projectPath) {
3088
3239
  function runDashboard(opts) {
3089
3240
  const clientPort = Number(opts.port ?? DEFAULT_CLIENT_PORT);
3090
3241
  const apiPort = Number(opts.apiPort ?? DEFAULT_API_PORT);
3091
- const projectPath = resolve12(opts.cwd ?? process.cwd());
3242
+ const projectPath = resolve13(opts.cwd ?? process.cwd());
3092
3243
  const url = `http://localhost:${apiPort}`;
3093
3244
  const server = resolveServerScript();
3094
3245
  if (!server) {
@@ -3104,13 +3255,13 @@ function runDashboard(opts) {
3104
3255
  }
3105
3256
  }
3106
3257
  function createDashboardCommand() {
3107
- 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));
3108
3259
  }
3109
3260
 
3110
3261
  // src/commands/design-pipeline.ts
3111
- import { Command as Command26 } from "commander";
3262
+ import { Command as Command27 } from "commander";
3112
3263
  function createDesignPipelineCommand() {
3113
- return new Command26("design-pipeline").description(
3264
+ return new Command27("design-pipeline").description(
3114
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."
3115
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(
3116
3267
  "--design-strictness <level>",
@@ -3196,10 +3347,10 @@ function verdictBadge(verdict) {
3196
3347
  }
3197
3348
 
3198
3349
  // src/commands/doctor.ts
3199
- import { Command as Command27 } from "commander";
3350
+ import { Command as Command28 } from "commander";
3200
3351
  import * as fs8 from "fs";
3201
3352
  import * as os from "os";
3202
- import * as path14 from "path";
3353
+ import * as path15 from "path";
3203
3354
  import chalk from "chalk";
3204
3355
 
3205
3356
  // src/utils/node-version.ts
@@ -3283,7 +3434,7 @@ var INTEGRATION_REGISTRY = [
3283
3434
 
3284
3435
  // src/integrations/config.ts
3285
3436
  import * as fs7 from "fs";
3286
- import * as path13 from "path";
3437
+ import * as path14 from "path";
3287
3438
  function readJsonSafe(filePath) {
3288
3439
  if (!fs7.existsSync(filePath)) return null;
3289
3440
  try {
@@ -3293,7 +3444,7 @@ function readJsonSafe(filePath) {
3293
3444
  }
3294
3445
  }
3295
3446
  function writeJson(filePath, data) {
3296
- const dir = path13.dirname(filePath);
3447
+ const dir = path14.dirname(filePath);
3297
3448
  if (!fs7.existsSync(dir)) {
3298
3449
  fs7.mkdirSync(dir, { recursive: true });
3299
3450
  }
@@ -3377,13 +3528,13 @@ function checkSlashCommands() {
3377
3528
  const platforms = [
3378
3529
  {
3379
3530
  name: "Claude Code",
3380
- dir: path14.join(os.homedir(), ".claude", "commands", "harness"),
3531
+ dir: path15.join(os.homedir(), ".claude", "commands", "harness"),
3381
3532
  ext: ".md",
3382
3533
  client: "claude-code"
3383
3534
  },
3384
3535
  {
3385
3536
  name: "Gemini CLI",
3386
- dir: path14.join(os.homedir(), ".gemini", "commands", "harness"),
3537
+ dir: path15.join(os.homedir(), ".gemini", "commands", "harness"),
3387
3538
  ext: ".toml",
3388
3539
  client: "gemini-cli"
3389
3540
  }
@@ -3407,7 +3558,7 @@ function checkSlashCommands() {
3407
3558
  }
3408
3559
  function checkMcpConfig(cwd) {
3409
3560
  const results = [];
3410
- const claudeConfig = readMcpConfig(path14.join(cwd, ".mcp.json"));
3561
+ const claudeConfig = readMcpConfig(path15.join(cwd, ".mcp.json"));
3411
3562
  if (claudeConfig.mcpServers?.["harness"]) {
3412
3563
  results.push({
3413
3564
  name: "mcp-claude",
@@ -3422,9 +3573,9 @@ function checkMcpConfig(cwd) {
3422
3573
  fix: "Run: harness setup-mcp --client claude"
3423
3574
  });
3424
3575
  }
3425
- const geminiDir = path14.join(cwd, ".gemini");
3576
+ const geminiDir = path15.join(cwd, ".gemini");
3426
3577
  if (fs8.existsSync(geminiDir)) {
3427
- const geminiConfig = readMcpConfig(path14.join(geminiDir, "settings.json"));
3578
+ const geminiConfig = readMcpConfig(path15.join(geminiDir, "settings.json"));
3428
3579
  if (geminiConfig.mcpServers?.["harness"]) {
3429
3580
  results.push({
3430
3581
  name: "mcp-gemini",
@@ -3443,12 +3594,12 @@ function checkMcpConfig(cwd) {
3443
3594
  return results;
3444
3595
  }
3445
3596
  function loadMcpPresence(cwd) {
3446
- const mcpPath = path14.join(cwd, ".mcp.json");
3447
- const geminiDir = path14.join(cwd, ".gemini");
3597
+ const mcpPath = path15.join(cwd, ".mcp.json");
3598
+ const geminiDir = path15.join(cwd, ".gemini");
3448
3599
  const hasGemini = fs8.existsSync(geminiDir);
3449
3600
  return {
3450
3601
  mcpConfig: readMcpConfig(mcpPath),
3451
- geminiConfig: hasGemini ? readMcpConfig(path14.join(geminiDir, "settings.json")) : null,
3602
+ geminiConfig: hasGemini ? readMcpConfig(path15.join(geminiDir, "settings.json")) : null,
3452
3603
  hasGemini
3453
3604
  };
3454
3605
  }
@@ -3480,7 +3631,7 @@ function checkTier0Presence(def, presence) {
3480
3631
  function checkIntegrations(cwd) {
3481
3632
  const results = [];
3482
3633
  const presence = loadMcpPresence(cwd);
3483
- const configPath = path14.join(cwd, "harness.config.json");
3634
+ const configPath = path15.join(cwd, "harness.config.json");
3484
3635
  const integrationsConfig = readIntegrationsConfig(configPath);
3485
3636
  for (const def of INTEGRATION_REGISTRY.filter((d) => d.tier === 0)) {
3486
3637
  results.push(checkTier0Presence(def, presence));
@@ -3548,12 +3699,12 @@ function checkLivePings(env = process.env) {
3548
3699
  return results;
3549
3700
  }
3550
3701
  function listHookFiles(cwd) {
3551
- const hooksDir = path14.join(cwd, ".harness", "hooks");
3702
+ const hooksDir = path15.join(cwd, ".harness", "hooks");
3552
3703
  if (!fs8.existsSync(hooksDir)) return [];
3553
3704
  try {
3554
3705
  return fs8.readdirSync(hooksDir).filter((f) => !f.startsWith(".")).map((f) => ({
3555
- relativePath: path14.join(".harness", "hooks", f),
3556
- absolutePath: path14.join(hooksDir, f)
3706
+ relativePath: path15.join(".harness", "hooks", f),
3707
+ absolutePath: path15.join(hooksDir, f)
3557
3708
  }));
3558
3709
  } catch {
3559
3710
  return [];
@@ -3650,7 +3801,7 @@ var DAY_MS = 24 * 60 * 60 * 1e3;
3650
3801
  function checkBaselineFreshness(cwd, now = Date.now()) {
3651
3802
  const results = [];
3652
3803
  for (const def of BASELINE_FILES) {
3653
- const absolutePath = path14.join(cwd, def.relativePath);
3804
+ const absolutePath = path15.join(cwd, def.relativePath);
3654
3805
  if (!fs8.existsSync(absolutePath)) {
3655
3806
  results.push({
3656
3807
  name: `baseline-freshness-${def.relativePath}`,
@@ -3698,7 +3849,7 @@ function checkBaselineFreshness(cwd, now = Date.now()) {
3698
3849
  }
3699
3850
  var SESSIONS_SAMPLE_SIZE = 5;
3700
3851
  function listRecentSessions(cwd) {
3701
- const sessionsDir = path14.join(cwd, ".harness", "sessions");
3852
+ const sessionsDir = path15.join(cwd, ".harness", "sessions");
3702
3853
  if (!fs8.existsSync(sessionsDir)) return [];
3703
3854
  let entries;
3704
3855
  try {
@@ -3709,7 +3860,7 @@ function listRecentSessions(cwd) {
3709
3860
  const dirs = [];
3710
3861
  for (const name of entries) {
3711
3862
  if (name.startsWith(".")) continue;
3712
- const absolutePath = path14.join(sessionsDir, name);
3863
+ const absolutePath = path15.join(sessionsDir, name);
3713
3864
  try {
3714
3865
  const stat = fs8.statSync(absolutePath);
3715
3866
  if (!stat.isDirectory()) continue;
@@ -3726,7 +3877,7 @@ function scanSessionSummaries(sessions) {
3726
3877
  let missing = 0;
3727
3878
  const corrupt = [];
3728
3879
  for (const session of sessions) {
3729
- const summaryPath = path14.join(session.absolutePath, "session-summary.json");
3880
+ const summaryPath = path15.join(session.absolutePath, "session-summary.json");
3730
3881
  if (!fs8.existsSync(summaryPath)) {
3731
3882
  missing += 1;
3732
3883
  continue;
@@ -3800,7 +3951,7 @@ function formatCheck(check) {
3800
3951
  return line;
3801
3952
  }
3802
3953
  function createDoctorCommand() {
3803
- return new Command27("doctor").description(
3954
+ return new Command28("doctor").description(
3804
3955
  "Check environment health: Node, slash commands, MCP, integrations, integration credentials, hooks, baselines, sessions"
3805
3956
  ).action((_opts, cmd) => {
3806
3957
  const globalOpts = cmd.optsWithGlobals();
@@ -3828,8 +3979,8 @@ function createDoctorCommand() {
3828
3979
 
3829
3980
  // src/commands/fix-drift.ts
3830
3981
  init_dist3();
3831
- import { Command as Command28 } from "commander";
3832
- import * as path15 from "path";
3982
+ import { Command as Command29 } from "commander";
3983
+ import * as path16 from "path";
3833
3984
  async function runFixDrift(options) {
3834
3985
  const cwd = options.cwd ?? process.cwd();
3835
3986
  const dryRun = options.dryRun !== false;
@@ -3838,12 +3989,12 @@ async function runFixDrift(options) {
3838
3989
  return Err(configResult.error);
3839
3990
  }
3840
3991
  const config = configResult.value;
3841
- const rootDir = path15.resolve(cwd, config.rootDir);
3842
- const docsDir = path15.resolve(cwd, config.docsDir);
3992
+ const rootDir = path16.resolve(cwd, config.rootDir);
3993
+ const docsDir = path16.resolve(cwd, config.docsDir);
3843
3994
  const entropyConfig = {
3844
3995
  rootDir,
3845
3996
  ...config.entropy?.entryPoints && { entryPoints: config.entropy.entryPoints },
3846
- docPaths: [path15.join(docsDir, "**/*.md")],
3997
+ docPaths: [path16.join(docsDir, "**/*.md")],
3847
3998
  analyze: {
3848
3999
  drift: true,
3849
4000
  deadCode: true,
@@ -3961,7 +4112,7 @@ function printFixDriftResult(value, mode, formatter) {
3961
4112
  }
3962
4113
  }
3963
4114
  function createFixDriftCommand() {
3964
- 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) => {
3965
4116
  const globalOpts = cmd.optsWithGlobals();
3966
4117
  const mode = resolveOutputMode(globalOpts);
3967
4118
  const formatter = new OutputFormatter(mode);
@@ -3991,14 +4142,14 @@ function createFixDriftCommand() {
3991
4142
  }
3992
4143
 
3993
4144
  // src/commands/gateway/index.ts
3994
- import { Command as Command31 } from "commander";
4145
+ import { Command as Command32 } from "commander";
3995
4146
 
3996
4147
  // src/commands/gateway/token.ts
3997
- import { Command as Command29 } from "commander";
3998
- import { resolve as resolve14 } from "path";
4148
+ import { Command as Command30 } from "commander";
4149
+ import { resolve as resolve15 } from "path";
3999
4150
  import { TokenStore } from "@harness-engineering/orchestrator";
4000
4151
  function getStore() {
4001
- const p = process.env["HARNESS_TOKENS_PATH"] ?? resolve14(".harness", "tokens.json");
4152
+ const p = process.env["HARNESS_TOKENS_PATH"] ?? resolve15(".harness", "tokens.json");
4002
4153
  return new TokenStore(p);
4003
4154
  }
4004
4155
  async function runTokenCreate(opts) {
@@ -4015,7 +4166,7 @@ async function runTokenRevoke(id) {
4015
4166
  return store.revoke(id);
4016
4167
  }
4017
4168
  function createTokenCommand() {
4018
- const cmd = new Command29("token").description("Manage Gateway API tokens");
4169
+ const cmd = new Command30("token").description("Manage Gateway API tokens");
4019
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(
4020
4171
  async (opts) => {
4021
4172
  const scopes = opts.scopes.split(",").map((s) => s.trim());
@@ -4044,12 +4195,12 @@ function createTokenCommand() {
4044
4195
  }
4045
4196
 
4046
4197
  // src/commands/gateway/deliveries.ts
4047
- import { Command as Command30 } from "commander";
4198
+ import { Command as Command31 } from "commander";
4048
4199
  import { createInterface } from "readline";
4049
- import { resolve as resolve15 } from "path";
4200
+ import { resolve as resolve16 } from "path";
4050
4201
  import { WebhookQueue } from "@harness-engineering/orchestrator";
4051
4202
  function resolveQueuePath() {
4052
- 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");
4053
4204
  }
4054
4205
  function getQueue() {
4055
4206
  return new WebhookQueue(resolveQueuePath());
@@ -4084,7 +4235,7 @@ function promptYesNo(message) {
4084
4235
  });
4085
4236
  }
4086
4237
  function createDeliveriesCommand() {
4087
- 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");
4088
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) => {
4089
4240
  const queue = getQueue();
4090
4241
  try {
@@ -4144,14 +4295,14 @@ function createDeliveriesCommand() {
4144
4295
 
4145
4296
  // src/commands/gateway/index.ts
4146
4297
  function createGatewayCommand() {
4147
- const cmd = new Command31("gateway").description("Gateway API administration");
4298
+ const cmd = new Command32("gateway").description("Gateway API administration");
4148
4299
  cmd.addCommand(createTokenCommand());
4149
4300
  cmd.addCommand(createDeliveriesCommand());
4150
4301
  return cmd;
4151
4302
  }
4152
4303
 
4153
4304
  // src/commands/generate.ts
4154
- import { Command as Command32 } from "commander";
4305
+ import { Command as Command33 } from "commander";
4155
4306
  function validatePlatforms(platforms) {
4156
4307
  for (const p of platforms) {
4157
4308
  if (!VALID_PLATFORMS.includes(p)) {
@@ -4211,22 +4362,22 @@ async function runGenerateAction(opts, globalOpts) {
4211
4362
  }
4212
4363
  }
4213
4364
  function createGenerateCommand() {
4214
- 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) => {
4215
4366
  await runGenerateAction(opts, cmd.optsWithGlobals());
4216
4367
  });
4217
4368
  }
4218
4369
 
4219
4370
  // src/commands/graph/index.ts
4220
- import { Command as Command35 } from "commander";
4371
+ import { Command as Command36 } from "commander";
4221
4372
 
4222
4373
  // src/commands/graph/status.ts
4223
- import * as path16 from "path";
4374
+ import * as path17 from "path";
4224
4375
  async function readConnectorSyncStatus(graphDir) {
4225
- const fs48 = await import("fs/promises");
4376
+ const fs49 = await import("fs/promises");
4226
4377
  const result = {};
4227
4378
  try {
4228
- const syncMetaPath = path16.join(graphDir, "sync-metadata.json");
4229
- 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"));
4230
4381
  for (const [name, data] of Object.entries(syncMeta.connectors ?? {})) {
4231
4382
  result[name] = data.lastSyncTimestamp;
4232
4383
  }
@@ -4236,7 +4387,7 @@ async function readConnectorSyncStatus(graphDir) {
4236
4387
  }
4237
4388
  async function runGraphStatus(projectPath) {
4238
4389
  const { GraphStore: GraphStore2, loadGraphMetadata } = await import("./dist-OWHMNL4W.js");
4239
- const graphDir = path16.join(projectPath, ".harness", "graph");
4390
+ const graphDir = path17.join(projectPath, ".harness", "graph");
4240
4391
  const metaResult = await loadGraphMetadata(graphDir);
4241
4392
  if (metaResult.status === "not_found") {
4242
4393
  return { status: "no_graph", message: "No graph found. Run `harness scan` first." };
@@ -4285,10 +4436,10 @@ async function runGraphStatus(projectPath) {
4285
4436
  }
4286
4437
 
4287
4438
  // src/commands/graph/export.ts
4288
- import * as path17 from "path";
4439
+ import * as path18 from "path";
4289
4440
  async function runGraphExport(projectPath, format) {
4290
4441
  const { GraphStore: GraphStore2 } = await import("./dist-OWHMNL4W.js");
4291
- const graphDir = path17.join(projectPath, ".harness", "graph");
4442
+ const graphDir = path18.join(projectPath, ".harness", "graph");
4292
4443
  const store = new GraphStore2();
4293
4444
  const loaded = await store.load(graphDir);
4294
4445
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
@@ -4317,15 +4468,15 @@ async function runGraphExport(projectPath, format) {
4317
4468
  }
4318
4469
 
4319
4470
  // src/commands/graph/index.ts
4320
- import * as path20 from "path";
4471
+ import * as path21 from "path";
4321
4472
 
4322
4473
  // src/commands/graph/query.ts
4323
- import { Command as Command33 } from "commander";
4324
- import * as path18 from "path";
4474
+ import { Command as Command34 } from "commander";
4475
+ import * as path19 from "path";
4325
4476
  async function runQuery(projectPath, rootNodeId, opts) {
4326
4477
  const { GraphStore: GraphStore2, ContextQL } = await import("./dist-OWHMNL4W.js");
4327
4478
  const store = new GraphStore2();
4328
- const graphDir = path18.join(projectPath, ".harness", "graph");
4479
+ const graphDir = path19.join(projectPath, ".harness", "graph");
4329
4480
  const loaded = await store.load(graphDir);
4330
4481
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
4331
4482
  const params = {
@@ -4347,7 +4498,7 @@ function printQueryResult(result) {
4347
4498
  }
4348
4499
  }
4349
4500
  async function runQueryAction(rootNodeId, opts, globalOpts) {
4350
- const projectPath = path18.resolve(globalOpts.config ? path18.dirname(globalOpts.config) : ".");
4501
+ const projectPath = path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
4351
4502
  try {
4352
4503
  const result = await runQuery(projectPath, rootNodeId, {
4353
4504
  depth: parseInt(opts.depth),
@@ -4366,19 +4517,19 @@ async function runQueryAction(rootNodeId, opts, globalOpts) {
4366
4517
  }
4367
4518
  }
4368
4519
  function createQueryCommand() {
4369
- 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) => {
4370
4521
  await runQueryAction(rootNodeId, opts, cmd.optsWithGlobals());
4371
4522
  });
4372
4523
  }
4373
4524
 
4374
4525
  // src/commands/graph/ingest.ts
4375
- import { Command as Command34 } from "commander";
4376
- import * as path19 from "path";
4526
+ import { Command as Command35 } from "commander";
4527
+ import * as path20 from "path";
4377
4528
  async function loadConnectorConfig(projectPath, source) {
4378
4529
  try {
4379
- const fs48 = await import("fs/promises");
4380
- const configPath = path19.join(projectPath, "harness.config.json");
4381
- 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"));
4382
4533
  const connector = config.graph?.connectors?.[source];
4383
4534
  return connector ?? {};
4384
4535
  } catch {
@@ -4387,9 +4538,9 @@ async function loadConnectorConfig(projectPath, source) {
4387
4538
  }
4388
4539
  async function ingestBusinessKnowledge(bk, projectPath) {
4389
4540
  return mergeResults(
4390
- await bk.ingest(path19.join(projectPath, "docs", "knowledge")),
4391
- await bk.ingestSolutions(path19.join(projectPath, "docs", "solutions")),
4392
- await bk.ingestStrategy(path19.join(projectPath, "STRATEGY.md"))
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"))
4393
4544
  );
4394
4545
  }
4395
4546
  function mergeResults(...results) {
@@ -4429,7 +4580,7 @@ async function runIngest(projectPath, source, opts) {
4429
4580
  FigmaConnector,
4430
4581
  MiroConnector
4431
4582
  } = await import("./dist-OWHMNL4W.js");
4432
- const graphDir = path19.join(projectPath, ".harness", "graph");
4583
+ const graphDir = path20.join(projectPath, ".harness", "graph");
4433
4584
  const store = new GraphStore2();
4434
4585
  await store.load(graphDir);
4435
4586
  const ingestOptions = loadIngestOptions(projectPath);
@@ -4441,11 +4592,11 @@ async function runIngest(projectPath, source, opts) {
4441
4592
  const bkInst = new BusinessKnowledgeIngestor(store);
4442
4593
  const bkResult = await ingestBusinessKnowledge(bkInst, projectPath);
4443
4594
  const reqResult = await new RequirementIngestor(store).ingestSpecs(
4444
- path19.join(projectPath, "docs", "changes")
4595
+ path20.join(projectPath, "docs", "changes")
4445
4596
  );
4446
4597
  const gitResult = await new GitIngestor(store).ingest(projectPath);
4447
4598
  const { createExtractionRunner } = await import("./dist-OWHMNL4W.js");
4448
- const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
4599
+ const extractedDir = path20.join(projectPath, ".harness", "knowledge", "extracted");
4449
4600
  const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
4450
4601
  const syncManager = new SyncManager(store, graphDir);
4451
4602
  const connectorMap = {
@@ -4490,12 +4641,12 @@ async function runIngest(projectPath, source, opts) {
4490
4641
  break;
4491
4642
  case "requirements":
4492
4643
  result = await new RequirementIngestor(store).ingestSpecs(
4493
- path19.join(projectPath, "docs", "changes")
4644
+ path20.join(projectPath, "docs", "changes")
4494
4645
  );
4495
4646
  break;
4496
4647
  case "business-signals": {
4497
4648
  const { createExtractionRunner } = await import("./dist-OWHMNL4W.js");
4498
- const extractedDir = path19.join(projectPath, ".harness", "knowledge", "extracted");
4649
+ const extractedDir = path20.join(projectPath, ".harness", "knowledge", "extracted");
4499
4650
  result = await createExtractionRunner().run(projectPath, store, extractedDir);
4500
4651
  break;
4501
4652
  }
@@ -4544,7 +4695,7 @@ async function handleIngestAction(opts, cmd) {
4544
4695
  process.exit(1);
4545
4696
  }
4546
4697
  const globalOpts = cmd.optsWithGlobals();
4547
- const projectPath = path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
4698
+ const projectPath = path20.resolve(globalOpts.config ? path20.dirname(globalOpts.config) : ".");
4548
4699
  try {
4549
4700
  const runOpts = {};
4550
4701
  if (opts.full !== void 0) runOpts.full = opts.full;
@@ -4561,7 +4712,7 @@ async function handleIngestAction(opts, cmd) {
4561
4712
  }
4562
4713
  }
4563
4714
  function createIngestCommand() {
4564
- 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(
4565
4716
  "--source <name>",
4566
4717
  "Source to ingest (code, knowledge, git, requirements, business-signals, jira, slack, ci, confluence, figma, miro)"
4567
4718
  ).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(handleIngestAction);
@@ -4569,7 +4720,7 @@ function createIngestCommand() {
4569
4720
 
4570
4721
  // src/commands/graph/index.ts
4571
4722
  function resolveProjectPath(globalOpts) {
4572
- return path20.resolve(globalOpts.config ? path20.dirname(globalOpts.config) : ".");
4723
+ return path21.resolve(globalOpts.config ? path21.dirname(globalOpts.config) : ".");
4573
4724
  }
4574
4725
  function printGraphStatus(result) {
4575
4726
  if (result.status === "no_graph" || result.status === "schema_mismatch") {
@@ -4615,19 +4766,19 @@ async function runExportAction(opts, cmd) {
4615
4766
  }
4616
4767
  }
4617
4768
  function createGraphCommand() {
4618
- const graph = new Command35("graph").description("Knowledge graph management");
4769
+ const graph = new Command36("graph").description("Knowledge graph management");
4619
4770
  graph.command("status").description("Show graph statistics").action(runStatusAction);
4620
4771
  graph.command("export").description("Export graph").requiredOption("--format <format>", "Output format (json, mermaid)").action(runExportAction);
4621
4772
  return graph;
4622
4773
  }
4623
4774
 
4624
4775
  // src/commands/hooks/index.ts
4625
- import { Command as Command40 } from "commander";
4776
+ import { Command as Command41 } from "commander";
4626
4777
 
4627
4778
  // src/commands/hooks/init.ts
4628
- import { Command as Command36 } from "commander";
4779
+ import { Command as Command37 } from "commander";
4629
4780
  import * as fs9 from "fs";
4630
- import * as path21 from "path";
4781
+ import * as path22 from "path";
4631
4782
  import { fileURLToPath as fileURLToPath2 } from "url";
4632
4783
 
4633
4784
  // src/hooks/profiles.ts
@@ -4657,14 +4808,14 @@ var PROFILES = {
4657
4808
 
4658
4809
  // src/commands/hooks/init.ts
4659
4810
  var __filename2 = fileURLToPath2(import.meta.url);
4660
- var __dirname2 = path21.dirname(__filename2);
4811
+ var __dirname2 = path22.dirname(__filename2);
4661
4812
  var VALID_PROFILES = ["minimal", "standard", "strict"];
4662
4813
  function resolveHookSourceDir() {
4663
4814
  const candidates = [
4664
4815
  // Dev layout: src/commands/hooks/ → ../../hooks/
4665
- path21.resolve(__dirname2, "..", "..", "hooks"),
4816
+ path22.resolve(__dirname2, "..", "..", "hooks"),
4666
4817
  // Bundled layout: dist/ → ./hooks/ (copied by copy-assets.mjs)
4667
- path21.resolve(__dirname2, "hooks")
4818
+ path22.resolve(__dirname2, "hooks")
4668
4819
  ];
4669
4820
  for (const candidate of candidates) {
4670
4821
  if (fs9.existsSync(candidate)) {
@@ -4704,12 +4855,12 @@ function mergeSettings(existing, hooksConfig) {
4704
4855
  }
4705
4856
  function initHooks(options) {
4706
4857
  const { profile, projectDir } = options;
4707
- const hooksDestDir = path21.join(projectDir, ".harness", "hooks");
4858
+ const hooksDestDir = path22.join(projectDir, ".harness", "hooks");
4708
4859
  fs9.mkdirSync(hooksDestDir, { recursive: true });
4709
4860
  if (fs9.existsSync(hooksDestDir)) {
4710
4861
  for (const entry of fs9.readdirSync(hooksDestDir)) {
4711
4862
  if (entry.endsWith(".js")) {
4712
- fs9.unlinkSync(path21.join(hooksDestDir, entry));
4863
+ fs9.unlinkSync(path22.join(hooksDestDir, entry));
4713
4864
  }
4714
4865
  }
4715
4866
  }
@@ -4718,18 +4869,18 @@ function initHooks(options) {
4718
4869
  const activeNames = PROFILES[profile];
4719
4870
  const activeScripts = HOOK_SCRIPTS.filter((h) => activeNames.includes(h.name));
4720
4871
  for (const script of activeScripts) {
4721
- const srcFile = path21.join(sourceDir, `${script.name}.js`);
4722
- 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`);
4723
4874
  if (fs9.existsSync(srcFile)) {
4724
4875
  fs9.copyFileSync(srcFile, destFile);
4725
4876
  copiedScripts.push(script.name);
4726
4877
  }
4727
4878
  }
4728
- const profilePath = path21.join(hooksDestDir, "profile.json");
4879
+ const profilePath = path22.join(hooksDestDir, "profile.json");
4729
4880
  fs9.writeFileSync(profilePath, JSON.stringify({ profile }, null, 2) + "\n");
4730
- const claudeDir = path21.join(projectDir, ".claude");
4881
+ const claudeDir = path22.join(projectDir, ".claude");
4731
4882
  fs9.mkdirSync(claudeDir, { recursive: true });
4732
- const settingsPath = path21.join(claudeDir, "settings.json");
4883
+ const settingsPath = path22.join(claudeDir, "settings.json");
4733
4884
  let existing = {};
4734
4885
  if (fs9.existsSync(settingsPath)) {
4735
4886
  try {
@@ -4747,7 +4898,7 @@ function initHooks(options) {
4747
4898
  return { copiedScripts, settingsPath, profilePath };
4748
4899
  }
4749
4900
  function createInitCommand2() {
4750
- 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) => {
4751
4902
  const globalOpts = cmd.optsWithGlobals();
4752
4903
  const profile = opts.profile;
4753
4904
  if (!VALID_PROFILES.includes(profile)) {
@@ -4772,7 +4923,7 @@ function createInitCommand2() {
4772
4923
  );
4773
4924
  logger.info(`Profile: ${profile}`);
4774
4925
  logger.info(
4775
- `Settings: ${path21.relative(projectDir, result.settingsPath).replaceAll("\\", "/")}`
4926
+ `Settings: ${path22.relative(projectDir, result.settingsPath).replaceAll("\\", "/")}`
4776
4927
  );
4777
4928
  logger.dim("Run 'harness hooks list' to see installed hooks");
4778
4929
  }
@@ -4785,12 +4936,12 @@ function createInitCommand2() {
4785
4936
  }
4786
4937
 
4787
4938
  // src/commands/hooks/list.ts
4788
- import { Command as Command37 } from "commander";
4939
+ import { Command as Command38 } from "commander";
4789
4940
  import * as fs10 from "fs";
4790
- import * as path22 from "path";
4941
+ import * as path23 from "path";
4791
4942
  function listHooks(projectDir) {
4792
- const hooksDir = path22.join(projectDir, ".harness", "hooks");
4793
- const profilePath = path22.join(hooksDir, "profile.json");
4943
+ const hooksDir = path23.join(projectDir, ".harness", "hooks");
4944
+ const profilePath = path23.join(hooksDir, "profile.json");
4794
4945
  if (!fs10.existsSync(profilePath)) {
4795
4946
  return { installed: false, profile: null, hooks: [] };
4796
4947
  }
@@ -4809,7 +4960,7 @@ function listHooks(projectDir) {
4809
4960
  name: h.name,
4810
4961
  event: h.event,
4811
4962
  matcher: h.matcher,
4812
- scriptPath: path22.join(".harness", "hooks", `${h.name}.js`)
4963
+ scriptPath: path23.join(".harness", "hooks", `${h.name}.js`)
4813
4964
  }));
4814
4965
  const result = { installed: true, profile, hooks };
4815
4966
  if (warning) {
@@ -4818,7 +4969,7 @@ function listHooks(projectDir) {
4818
4969
  return result;
4819
4970
  }
4820
4971
  function createListCommand() {
4821
- 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) => {
4822
4973
  const globalOpts = cmd.optsWithGlobals();
4823
4974
  const projectDir = process.cwd();
4824
4975
  const result = listHooks(projectDir);
@@ -4839,12 +4990,12 @@ function createListCommand() {
4839
4990
  }
4840
4991
 
4841
4992
  // src/commands/hooks/remove.ts
4842
- import { Command as Command38 } from "commander";
4993
+ import { Command as Command39 } from "commander";
4843
4994
  import * as fs11 from "fs";
4844
- import * as path23 from "path";
4995
+ import * as path24 from "path";
4845
4996
  function removeHooks(projectDir) {
4846
- const hooksDir = path23.join(projectDir, ".harness", "hooks");
4847
- 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");
4848
4999
  let removed = false;
4849
5000
  let settingsCleaned = false;
4850
5001
  if (fs11.existsSync(hooksDir)) {
@@ -4869,7 +5020,7 @@ function removeHooks(projectDir) {
4869
5020
  return { removed, hooksDir, settingsCleaned };
4870
5021
  }
4871
5022
  function createRemoveCommand() {
4872
- 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) => {
4873
5024
  const globalOpts = cmd.optsWithGlobals();
4874
5025
  const projectDir = process.cwd();
4875
5026
  const result = removeHooks(projectDir);
@@ -4891,16 +5042,16 @@ function createRemoveCommand() {
4891
5042
  }
4892
5043
 
4893
5044
  // src/commands/hooks/add.ts
4894
- import { Command as Command39 } from "commander";
5045
+ import { Command as Command40 } from "commander";
4895
5046
  import * as fs12 from "fs";
4896
- import * as path24 from "path";
5047
+ import * as path25 from "path";
4897
5048
  import { fileURLToPath as fileURLToPath3 } from "url";
4898
- var __dirname3 = path24.dirname(fileURLToPath3(import.meta.url));
5049
+ var __dirname3 = path25.dirname(fileURLToPath3(import.meta.url));
4899
5050
  var ALIASES = {
4900
5051
  sentinel: ["sentinel-pre", "sentinel-post"]
4901
5052
  };
4902
5053
  function hookSourceDir() {
4903
- const d = path24.resolve(__dirname3, "..", "..", "hooks");
5054
+ const d = path25.resolve(__dirname3, "..", "..", "hooks");
4904
5055
  if (fs12.existsSync(d)) return d;
4905
5056
  throw new Error(`Hook scripts not found: ${d}`);
4906
5057
  }
@@ -4918,11 +5069,11 @@ function addHooks(hookName, projectDir) {
4918
5069
  const names = ALIASES[hookName] ?? [hookName];
4919
5070
  const result = { added: [], alreadyInstalled: [], notFound: [] };
4920
5071
  const srcDir = hookSourceDir();
4921
- const destDir = path24.join(projectDir, ".harness", "hooks");
5072
+ const destDir = path25.join(projectDir, ".harness", "hooks");
4922
5073
  fs12.mkdirSync(destDir, { recursive: true });
4923
- const claudeDir = path24.join(projectDir, ".claude");
5074
+ const claudeDir = path25.join(projectDir, ".claude");
4924
5075
  fs12.mkdirSync(claudeDir, { recursive: true });
4925
- const settingsPath = path24.join(claudeDir, "settings.json");
5076
+ const settingsPath = path25.join(claudeDir, "settings.json");
4926
5077
  const settings = readJson(settingsPath);
4927
5078
  if (!settings.hooks) settings.hooks = {};
4928
5079
  for (const name of names) {
@@ -4931,8 +5082,8 @@ function addHooks(hookName, projectDir) {
4931
5082
  result.notFound.push(name);
4932
5083
  continue;
4933
5084
  }
4934
- const src = path24.join(srcDir, `${name}.js`);
4935
- const dest = path24.join(destDir, `${name}.js`);
5085
+ const src = path25.join(srcDir, `${name}.js`);
5086
+ const dest = path25.join(destDir, `${name}.js`);
4936
5087
  if (fs12.existsSync(dest)) {
4937
5088
  result.alreadyInstalled.push(name);
4938
5089
  } else if (!fs12.existsSync(src)) {
@@ -4948,7 +5099,7 @@ function addHooks(hookName, projectDir) {
4948
5099
  return result;
4949
5100
  }
4950
5101
  function createAddCommand2() {
4951
- 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) => {
4952
5103
  const projectDir = process.cwd();
4953
5104
  try {
4954
5105
  const res = addHooks(hookName, projectDir);
@@ -4973,7 +5124,7 @@ function createAddCommand2() {
4973
5124
 
4974
5125
  // src/commands/hooks/index.ts
4975
5126
  function createHooksCommand() {
4976
- const command = new Command40("hooks").description("Manage Claude Code hook configurations");
5127
+ const command = new Command41("hooks").description("Manage Claude Code hook configurations");
4977
5128
  command.addCommand(createInitCommand2());
4978
5129
  command.addCommand(createListCommand());
4979
5130
  command.addCommand(createRemoveCommand());
@@ -4982,9 +5133,9 @@ function createHooksCommand() {
4982
5133
  }
4983
5134
 
4984
5135
  // src/commands/impact-preview.ts
4985
- import { Command as Command41 } from "commander";
5136
+ import { Command as Command42 } from "commander";
4986
5137
  import { execSync as execSync4 } from "child_process";
4987
- import * as path25 from "path";
5138
+ import * as path26 from "path";
4988
5139
  import * as fs13 from "fs";
4989
5140
  function getStagedFiles(cwd) {
4990
5141
  try {
@@ -4999,7 +5150,7 @@ function getStagedFiles(cwd) {
4999
5150
  }
5000
5151
  function graphExists(projectPath) {
5001
5152
  try {
5002
- return fs13.existsSync(path25.join(projectPath, ".harness", "graph", "graph.json"));
5153
+ return fs13.existsSync(path26.join(projectPath, ".harness", "graph", "graph.json"));
5003
5154
  } catch {
5004
5155
  return false;
5005
5156
  }
@@ -5008,7 +5159,7 @@ function extractNodeName(id) {
5008
5159
  const parts = id.split(":");
5009
5160
  if (parts.length > 1) {
5010
5161
  const fullPath = parts.slice(1).join(":");
5011
- return path25.basename(fullPath);
5162
+ return path26.basename(fullPath);
5012
5163
  }
5013
5164
  return id;
5014
5165
  }
@@ -5163,7 +5314,7 @@ function formatImpactOutput(stagedFiles, acc, options) {
5163
5314
  return options.detailed ? formatDetailed(stagedFiles.length, merged, acc.aggregateCounts) : formatCompact(stagedFiles.length, merged, acc.aggregateCounts);
5164
5315
  }
5165
5316
  async function runImpactPreview(options) {
5166
- const projectPath = path25.resolve(options.path ?? process.cwd());
5317
+ const projectPath = path26.resolve(options.path ?? process.cwd());
5167
5318
  const stagedFiles = getStagedFiles(projectPath);
5168
5319
  if (stagedFiles.length === 0) return "Impact Preview: no staged changes";
5169
5320
  if (!graphExists(projectPath)) {
@@ -5181,7 +5332,7 @@ async function runImpactPreview(options) {
5181
5332
  return formatImpactOutput(stagedFiles, acc, options);
5182
5333
  }
5183
5334
  function createImpactPreviewCommand() {
5184
- 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) => {
5185
5336
  const output = await runImpactPreview({
5186
5337
  detailed: opts.detailed,
5187
5338
  perFile: opts.perFile,
@@ -5195,24 +5346,24 @@ function createImpactPreviewCommand() {
5195
5346
 
5196
5347
  // src/commands/init.ts
5197
5348
  init_dist3();
5198
- import { Command as Command43 } from "commander";
5349
+ import { Command as Command44 } from "commander";
5199
5350
  import chalk3 from "chalk";
5200
5351
  import * as fs16 from "fs";
5201
- import * as path28 from "path";
5352
+ import * as path29 from "path";
5202
5353
 
5203
5354
  // src/commands/setup-mcp.ts
5204
- import { Command as Command42 } from "commander";
5355
+ import { Command as Command43 } from "commander";
5205
5356
  import * as fs15 from "fs";
5206
- import * as path27 from "path";
5357
+ import * as path28 from "path";
5207
5358
  import * as os2 from "os";
5208
5359
  import chalk2 from "chalk";
5209
5360
  import * as clack from "@clack/prompts";
5210
5361
 
5211
5362
  // src/integrations/toml.ts
5212
5363
  import * as fs14 from "fs";
5213
- import * as path26 from "path";
5364
+ import * as path27 from "path";
5214
5365
  function writeTomlMcpEntry(filePath, name, entry) {
5215
- const dir = path26.dirname(filePath);
5366
+ const dir = path27.dirname(filePath);
5216
5367
  if (!fs14.existsSync(dir)) {
5217
5368
  fs14.mkdirSync(dir, { recursive: true });
5218
5369
  }
@@ -5342,6 +5493,8 @@ var ALL_MCP_TOOLS = [
5342
5493
  "run_code_review",
5343
5494
  "gather_context",
5344
5495
  "assess_project",
5496
+ "canary_probe",
5497
+ "canary_recommend_framework",
5345
5498
  "review_changes",
5346
5499
  "detect_anomalies",
5347
5500
  "ask_graph",
@@ -5399,6 +5552,8 @@ var ALL_MCP_TOOLS = [
5399
5552
  "knowledge_craft",
5400
5553
  // craft-pipeline #10 — security-craft LLM-judgment ceiling skill (AST-driven, conservative-confidence)
5401
5554
  "security_craft",
5555
+ // outcome-eval — post-execution spec-satisfaction verdict (tiered confidence→authority)
5556
+ "outcome_eval",
5402
5557
  // strategic-anchor — STRATEGY.md read/validate/write so projects can call
5403
5558
  // these via MCP without needing @harness-engineering/core in node_modules
5404
5559
  "validate_strategy",
@@ -5447,7 +5602,7 @@ function readJsonFile(filePath) {
5447
5602
  }
5448
5603
  }
5449
5604
  function writeJsonFile(filePath, data) {
5450
- const dir = path27.dirname(filePath);
5605
+ const dir = path28.dirname(filePath);
5451
5606
  if (!fs15.existsSync(dir)) {
5452
5607
  fs15.mkdirSync(dir, { recursive: true });
5453
5608
  }
@@ -5466,7 +5621,7 @@ function configureMcpServer(configPath) {
5466
5621
  return true;
5467
5622
  }
5468
5623
  function addGeminiTrustedFolder(cwd) {
5469
- const trustedPath = path27.join(os2.homedir(), ".gemini", "trustedFolders.json");
5624
+ const trustedPath = path28.join(os2.homedir(), ".gemini", "trustedFolders.json");
5470
5625
  const folders = readJsonFile(trustedPath) ?? {};
5471
5626
  if (folders[cwd] === "TRUST_FOLDER") {
5472
5627
  return false;
@@ -5480,7 +5635,7 @@ function setupMcp(cwd, client) {
5480
5635
  const skipped = [];
5481
5636
  let trustedFolder = false;
5482
5637
  if (client === "all" || client === "claude") {
5483
- const configPath = path27.join(cwd, ".mcp.json");
5638
+ const configPath = path28.join(cwd, ".mcp.json");
5484
5639
  if (configureMcpServer(configPath)) {
5485
5640
  configured.push("Claude Code");
5486
5641
  } else {
@@ -5488,7 +5643,7 @@ function setupMcp(cwd, client) {
5488
5643
  }
5489
5644
  }
5490
5645
  if (client === "all" || client === "gemini") {
5491
- const configPath = path27.join(cwd, ".gemini", "settings.json");
5646
+ const configPath = path28.join(cwd, ".gemini", "settings.json");
5492
5647
  if (configureMcpServer(configPath)) {
5493
5648
  configured.push("Gemini CLI");
5494
5649
  } else {
@@ -5497,7 +5652,7 @@ function setupMcp(cwd, client) {
5497
5652
  trustedFolder = addGeminiTrustedFolder(cwd);
5498
5653
  }
5499
5654
  if (client === "all" || client === "codex") {
5500
- const configPath = path27.join(cwd, ".codex", "config.toml");
5655
+ const configPath = path28.join(cwd, ".codex", "config.toml");
5501
5656
  const alreadyConfigured = (() => {
5502
5657
  if (!fs15.existsSync(configPath)) return false;
5503
5658
  const content = fs15.readFileSync(configPath, "utf-8");
@@ -5515,7 +5670,7 @@ function setupMcp(cwd, client) {
5515
5670
  }
5516
5671
  }
5517
5672
  if (client === "all" || client === "cursor") {
5518
- const configPath = path27.join(cwd, ".cursor", "mcp.json");
5673
+ const configPath = path28.join(cwd, ".cursor", "mcp.json");
5519
5674
  const existing = readJsonFile(configPath);
5520
5675
  if (existing?.mcpServers?.["harness"]) {
5521
5676
  skipped.push("Cursor");
@@ -5525,7 +5680,7 @@ function setupMcp(cwd, client) {
5525
5680
  }
5526
5681
  }
5527
5682
  if (client === "all" || client === "opencode") {
5528
- const configPath = path27.join(cwd, "opencode.json");
5683
+ const configPath = path28.join(cwd, "opencode.json");
5529
5684
  const existing = readJsonFile(configPath);
5530
5685
  if (existing?.mcp?.["harness"]) {
5531
5686
  skipped.push("OpenCode");
@@ -5539,7 +5694,7 @@ function setupMcp(cwd, client) {
5539
5694
  async function resolveCursorWithPicker(cwd, pick) {
5540
5695
  const configured = [];
5541
5696
  const skipped = [];
5542
- const cursorConfigPath = path27.join(cwd, ".cursor", "mcp.json");
5697
+ const cursorConfigPath = path28.join(cwd, ".cursor", "mcp.json");
5543
5698
  const existing = readJsonFile(cursorConfigPath);
5544
5699
  if (existing?.mcpServers?.["harness"] && !pick) {
5545
5700
  skipped.push("Cursor");
@@ -5583,7 +5738,7 @@ function printMcpResult(configured, skipped, trustedFolder) {
5583
5738
  console.log("");
5584
5739
  }
5585
5740
  function createSetupMcpCommand() {
5586
- 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(
5587
5742
  "--client <client>",
5588
5743
  "Client to configure (claude, gemini, codex, cursor, opencode, all)",
5589
5744
  "all"
@@ -5614,11 +5769,11 @@ function loadEngineAndTemplates(_options) {
5614
5769
  }
5615
5770
  function resolveInitDefaults(options) {
5616
5771
  const cwd = options.cwd ?? process.cwd();
5617
- 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 };
5618
5773
  }
5619
5774
  async function runInit(options) {
5620
5775
  const { cwd, name, force } = resolveInitDefaults(options);
5621
- const configPath = path28.join(cwd, "harness.config.json");
5776
+ const configPath = path29.join(cwd, "harness.config.json");
5622
5777
  if (!force && fs16.existsSync(configPath)) {
5623
5778
  return Err(
5624
5779
  new CLIError("Project already initialized. Use --force to overwrite.", ExitCode.ERROR)
@@ -5672,6 +5827,18 @@ function scaffoldProject(engine, ctx) {
5672
5827
  ...language !== void 0 && { language }
5673
5828
  });
5674
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
+ }
5675
5842
  const existingProject = !force && engine.isExistingProject(cwd);
5676
5843
  const writeResult = engine.write(renderResult.value, cwd, {
5677
5844
  overwrite: force,
@@ -5729,7 +5896,7 @@ async function runInitAction2(opts) {
5729
5896
  process.exit(ExitCode.SUCCESS);
5730
5897
  }
5731
5898
  function createInitCommand3() {
5732
- 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) => {
5733
5900
  const globalOpts = cmd.optsWithGlobals();
5734
5901
  await runInitAction2({
5735
5902
  name: opts.name,
@@ -5745,7 +5912,7 @@ function createInitCommand3() {
5745
5912
 
5746
5913
  // src/commands/insights.ts
5747
5914
  init_dist();
5748
- import { Command as Command44 } from "commander";
5915
+ import { Command as Command45 } from "commander";
5749
5916
  function parseSkip2(raw) {
5750
5917
  if (!raw) return [];
5751
5918
  const valid = new Set(INSIGHTS_KEYS);
@@ -5783,10 +5950,10 @@ function renderPretty(report) {
5783
5950
  }
5784
5951
  }
5785
5952
  function createInsightsCommand() {
5786
- return new Command44("insights").description("Composite project report \u2014 health, entropy, decay, attention, impact.").option("--json", "Emit JSON to stdout instead of pretty text").option("--skip <list>", `Comma-separated keys to skip (${INSIGHTS_KEYS.join(",")})`).action(async (opts) => {
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) => {
5787
5954
  const cwd = process.cwd();
5788
5955
  const skip = parseSkip2(opts.skip);
5789
- const { composeInsights } = await import("./dist-JCFK263L.js");
5956
+ const { composeInsights } = await import("./dist-LHINSVK4.js");
5790
5957
  const report = await composeInsights(cwd, { skip });
5791
5958
  if (opts.json) {
5792
5959
  console.log(JSON.stringify(report, null, 2));
@@ -5799,14 +5966,14 @@ function createInsightsCommand() {
5799
5966
  // src/commands/install.ts
5800
5967
  import * as fs21 from "fs";
5801
5968
  import * as os5 from "os";
5802
- import * as path33 from "path";
5969
+ import * as path34 from "path";
5803
5970
  import { execFileSync as execFileSync3 } from "child_process";
5804
- import { Command as Command45 } from "commander";
5971
+ import { Command as Command46 } from "commander";
5805
5972
  import { parse as yamlParse } from "yaml";
5806
5973
 
5807
5974
  // src/registry/npm-client.ts
5808
5975
  import * as fs17 from "fs";
5809
- import * as path29 from "path";
5976
+ import * as path30 from "path";
5810
5977
  import * as os3 from "os";
5811
5978
  var NPM_REGISTRY = "https://registry.npmjs.org";
5812
5979
  var FETCH_TIMEOUT_MS = 3e4;
@@ -5829,7 +5996,7 @@ function extractSkillName(packageName) {
5829
5996
  function readNpmrcToken(registryUrl) {
5830
5997
  const { hostname: hostname2, pathname } = new URL(registryUrl);
5831
5998
  const registryPath = `//${hostname2}${pathname.replace(/\/$/, "")}/:_authToken=`;
5832
- 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")];
5833
6000
  for (const npmrcPath of candidates) {
5834
6001
  try {
5835
6002
  const content = fs17.readFileSync(npmrcPath, "utf-8");
@@ -5928,12 +6095,12 @@ async function searchNpmRegistry(query, registryUrl) {
5928
6095
 
5929
6096
  // src/registry/tarball.ts
5930
6097
  import * as fs18 from "fs";
5931
- import * as path30 from "path";
6098
+ import * as path31 from "path";
5932
6099
  import * as os4 from "os";
5933
6100
  import { execFileSync as execFileSync2 } from "child_process";
5934
6101
  function extractTarball(tarballBuffer) {
5935
- const tmpDir = fs18.mkdtempSync(path30.join(os4.tmpdir(), "harness-skill-install-"));
5936
- 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");
5937
6104
  try {
5938
6105
  fs18.writeFileSync(tarballPath, tarballBuffer);
5939
6106
  execFileSync2("tar", ["-xzf", tarballPath, "-C", tmpDir], {
@@ -5952,15 +6119,15 @@ function extractTarball(tarballBuffer) {
5952
6119
  function placeSkillContent(extractedPkgDir, communityBaseDir, skillName, platforms) {
5953
6120
  const files = fs18.readdirSync(extractedPkgDir);
5954
6121
  for (const platform of platforms) {
5955
- const targetDir = path30.join(communityBaseDir, platform, skillName);
6122
+ const targetDir = path31.join(communityBaseDir, platform, skillName);
5956
6123
  if (fs18.existsSync(targetDir)) {
5957
6124
  fs18.rmSync(targetDir, { recursive: true, force: true });
5958
6125
  }
5959
6126
  fs18.mkdirSync(targetDir, { recursive: true });
5960
6127
  for (const file of files) {
5961
6128
  if (file === "package.json" || file === "node_modules") continue;
5962
- const srcPath = path30.join(extractedPkgDir, file);
5963
- const destPath = path30.join(targetDir, file);
6129
+ const srcPath = path31.join(extractedPkgDir, file);
6130
+ const destPath = path31.join(targetDir, file);
5964
6131
  const stat = fs18.statSync(srcPath);
5965
6132
  if (stat.isDirectory()) {
5966
6133
  fs18.cpSync(srcPath, destPath, { recursive: true });
@@ -5972,7 +6139,7 @@ function placeSkillContent(extractedPkgDir, communityBaseDir, skillName, platfor
5972
6139
  }
5973
6140
  function removeSkillContent(communityBaseDir, skillName, platforms) {
5974
6141
  for (const platform of platforms) {
5975
- const targetDir = path30.join(communityBaseDir, platform, skillName);
6142
+ const targetDir = path31.join(communityBaseDir, platform, skillName);
5976
6143
  if (fs18.existsSync(targetDir)) {
5977
6144
  fs18.rmSync(targetDir, { recursive: true, force: true });
5978
6145
  }
@@ -6023,7 +6190,7 @@ function findDependentsOf(lockfile, targetPackageName) {
6023
6190
 
6024
6191
  // src/registry/lockfile.ts
6025
6192
  import * as fs19 from "fs";
6026
- import * as path31 from "path";
6193
+ import * as path32 from "path";
6027
6194
  function createEmptyLockfile() {
6028
6195
  return { version: 1, skills: {} };
6029
6196
  }
@@ -6063,7 +6230,7 @@ function readLockfile2(filePath) {
6063
6230
  return parsed;
6064
6231
  }
6065
6232
  function writeLockfile2(filePath, lockfile) {
6066
- const dir = path31.dirname(filePath);
6233
+ const dir = path32.dirname(filePath);
6067
6234
  fs19.mkdirSync(dir, { recursive: true });
6068
6235
  fs19.writeFileSync(filePath, sortedStringify(lockfile) + "\n", "utf-8");
6069
6236
  }
@@ -6089,7 +6256,7 @@ function removeLockfileEntry(lockfile, name) {
6089
6256
 
6090
6257
  // src/registry/bundled-skills.ts
6091
6258
  import * as fs20 from "fs";
6092
- import * as path32 from "path";
6259
+ import * as path33 from "path";
6093
6260
  function getBundledSkillNames(bundledSkillsDir) {
6094
6261
  if (!fs20.existsSync(bundledSkillsDir)) {
6095
6262
  return /* @__PURE__ */ new Set();
@@ -6098,7 +6265,7 @@ function getBundledSkillNames(bundledSkillsDir) {
6098
6265
  const names = /* @__PURE__ */ new Set();
6099
6266
  for (const entry of entries) {
6100
6267
  try {
6101
- const stat = fs20.statSync(path32.join(bundledSkillsDir, String(entry)));
6268
+ const stat = fs20.statSync(path33.join(bundledSkillsDir, String(entry)));
6102
6269
  if (stat.isDirectory()) {
6103
6270
  names.add(String(entry));
6104
6271
  }
@@ -6126,12 +6293,12 @@ function validateSkillYaml(parsed) {
6126
6293
  function resolveCommunityBase(global) {
6127
6294
  if (global) {
6128
6295
  const communityBase2 = resolveGlobalCommunityBaseDir();
6129
- return { communityBase: communityBase2, lockfilePath: path33.join(communityBase2, "skills-lock.json") };
6296
+ return { communityBase: communityBase2, lockfilePath: path34.join(communityBase2, "skills-lock.json") };
6130
6297
  }
6131
6298
  const globalDir = resolveGlobalSkillsDir();
6132
- const skillsDir = path33.dirname(globalDir);
6133
- const communityBase = path33.join(skillsDir, "community");
6134
- 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") };
6135
6302
  }
6136
6303
  function parseGitHubRef(from) {
6137
6304
  const ghPrefix = from.match(/^github:([^/]+)\/([^#]+?)(?:#(.+))?$/);
@@ -6147,7 +6314,7 @@ function parseGitHubRef(from) {
6147
6314
  return null;
6148
6315
  }
6149
6316
  function cloneGitHubRepo(owner, repo, ref) {
6150
- const tmpDir = fs21.mkdtempSync(path33.join(os5.tmpdir(), "harness-gh-install-"));
6317
+ const tmpDir = fs21.mkdtempSync(path34.join(os5.tmpdir(), "harness-gh-install-"));
6151
6318
  const url = `https://github.com/${owner}/${repo}.git`;
6152
6319
  try {
6153
6320
  const cloneArgs = ["clone", "--depth", "1"];
@@ -6169,7 +6336,7 @@ function discoverSkillDirs(rootDir) {
6169
6336
  function scan(dir, depth) {
6170
6337
  if (depth > 3) return;
6171
6338
  if (!fs21.existsSync(dir)) return;
6172
- if (fs21.existsSync(path33.join(dir, "skill.yaml"))) {
6339
+ if (fs21.existsSync(path34.join(dir, "skill.yaml"))) {
6173
6340
  skillDirs.push(dir);
6174
6341
  return;
6175
6342
  }
@@ -6177,14 +6344,14 @@ function discoverSkillDirs(rootDir) {
6177
6344
  for (const entry of entries) {
6178
6345
  if (!entry.isDirectory()) continue;
6179
6346
  if (entry.name.startsWith(".") || DEFAULT_SKIP_DIRS.has(entry.name)) continue;
6180
- scan(path33.join(dir, entry.name), depth + 1);
6347
+ scan(path34.join(dir, entry.name), depth + 1);
6181
6348
  }
6182
6349
  }
6183
6350
  scan(rootDir, 0);
6184
6351
  return skillDirs;
6185
6352
  }
6186
6353
  function resolveLocalPkgDir(fromPath) {
6187
- const resolvedPath = path33.resolve(fromPath);
6354
+ const resolvedPath = path34.resolve(fromPath);
6188
6355
  if (!fs21.existsSync(resolvedPath)) {
6189
6356
  throw new Error(`--from path does not exist: ${resolvedPath}`);
6190
6357
  }
@@ -6195,12 +6362,12 @@ function resolveLocalPkgDir(fromPath) {
6195
6362
  if (resolvedPath.endsWith(".tgz") || resolvedPath.endsWith(".tar.gz")) {
6196
6363
  const tarballBuffer = fs21.readFileSync(resolvedPath);
6197
6364
  const extractDir = extractTarball(tarballBuffer);
6198
- return { pkgDir: path33.join(extractDir, "package"), extractDir };
6365
+ return { pkgDir: path34.join(extractDir, "package"), extractDir };
6199
6366
  }
6200
6367
  throw new Error(`--from path must be a directory or .tgz file. Got: ${resolvedPath}`);
6201
6368
  }
6202
6369
  function installSkillDir(pkgDir, resolvedPath, options) {
6203
- const skillYamlPath = path33.join(pkgDir, "skill.yaml");
6370
+ const skillYamlPath = path34.join(pkgDir, "skill.yaml");
6204
6371
  if (!fs21.existsSync(skillYamlPath)) {
6205
6372
  throw new Error(`No skill.yaml found at ${skillYamlPath}`);
6206
6373
  }
@@ -6232,7 +6399,7 @@ function installSkillDir(pkgDir, resolvedPath, options) {
6232
6399
  async function runLocalInstall(fromPath, options) {
6233
6400
  const { pkgDir, extractDir } = resolveLocalPkgDir(fromPath);
6234
6401
  try {
6235
- return installSkillDir(pkgDir, path33.resolve(fromPath), options);
6402
+ return installSkillDir(pkgDir, path34.resolve(fromPath), options);
6236
6403
  } finally {
6237
6404
  if (extractDir) cleanupTempDir(extractDir);
6238
6405
  }
@@ -6275,8 +6442,8 @@ async function runInstall(skillName, options) {
6275
6442
  version: installed.map((r) => r.version).join(", ")
6276
6443
  };
6277
6444
  }
6278
- const resolvedFrom = path33.resolve(options.from);
6279
- 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"))) {
6280
6447
  const results = await runBulkInstall(resolvedFrom, options);
6281
6448
  const installed = results.filter((r) => r.installed);
6282
6449
  return {
@@ -6317,8 +6484,8 @@ async function runInstall(skillName, options) {
6317
6484
  const extractDir = extractTarball(tarballBuffer);
6318
6485
  let skillYaml;
6319
6486
  try {
6320
- const extractedPkgDir = path33.join(extractDir, "package");
6321
- const skillYamlPath = path33.join(extractedPkgDir, "skill.yaml");
6487
+ const extractedPkgDir = path34.join(extractDir, "package");
6488
+ const skillYamlPath = path34.join(extractedPkgDir, "skill.yaml");
6322
6489
  if (!fs21.existsSync(skillYamlPath)) {
6323
6490
  throw new Error(`contains invalid skill.yaml: file not found in package`);
6324
6491
  }
@@ -6362,7 +6529,7 @@ async function runInstall(skillName, options) {
6362
6529
  return result;
6363
6530
  }
6364
6531
  function createInstallCommand() {
6365
- const cmd = new Command45("install");
6532
+ const cmd = new Command46("install");
6366
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(
6367
6534
  "--from <source>",
6368
6535
  "Install from local path, directory, or GitHub (github:owner/repo, https://github.com/owner/repo)"
@@ -6397,8 +6564,8 @@ function createInstallCommand() {
6397
6564
  // src/commands/install-constraints.ts
6398
6565
  init_dist3();
6399
6566
  import * as fs22 from "fs/promises";
6400
- import * as path34 from "path";
6401
- import { Command as Command46 } from "commander";
6567
+ import * as path35 from "path";
6568
+ import { Command as Command47 } from "commander";
6402
6569
  import semver3 from "semver";
6403
6570
  async function runInstallConstraints(options) {
6404
6571
  const { source, configPath, lockfilePath } = options;
@@ -6595,7 +6762,7 @@ function isNodeError(err) {
6595
6762
  return err instanceof Error && "code" in err;
6596
6763
  }
6597
6764
  function resolveConfigPath(opts) {
6598
- if (opts.config) return path34.resolve(opts.config);
6765
+ if (opts.config) return path35.resolve(opts.config);
6599
6766
  const found = findConfigFile();
6600
6767
  if (!found.ok) {
6601
6768
  logger.error(found.error.message);
@@ -6630,9 +6797,9 @@ function logInstallResult(val, opts) {
6630
6797
  }
6631
6798
  async function handleInstallConstraints(source, opts) {
6632
6799
  const configPath = resolveConfigPath(opts);
6633
- const projectRoot2 = path34.dirname(configPath);
6634
- const lockfilePath = path34.join(projectRoot2, ".harness", "constraints.lock.json");
6635
- 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);
6636
6803
  if (opts.forceLocal && opts.forcePackage) {
6637
6804
  logger.error("Cannot use both --force-local and --force-package.");
6638
6805
  process.exit(1);
@@ -6652,19 +6819,19 @@ async function handleInstallConstraints(source, opts) {
6652
6819
  logInstallResult(result.value, opts);
6653
6820
  }
6654
6821
  function createInstallConstraintsCommand() {
6655
- const cmd = new Command46("install-constraints");
6822
+ const cmd = new Command47("install-constraints");
6656
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);
6657
6824
  return cmd;
6658
6825
  }
6659
6826
 
6660
6827
  // src/commands/integrations/index.ts
6661
- import { Command as Command51 } from "commander";
6828
+ import { Command as Command52 } from "commander";
6662
6829
 
6663
6830
  // src/commands/integrations/add.ts
6664
6831
  init_dist3();
6665
- import { Command as Command47 } from "commander";
6832
+ import { Command as Command48 } from "commander";
6666
6833
  import * as fs23 from "fs";
6667
- import * as path35 from "path";
6834
+ import * as path36 from "path";
6668
6835
  import chalk4 from "chalk";
6669
6836
  function buildMcpEntry(def) {
6670
6837
  const entry = { command: def.mcpConfig.command };
@@ -6673,14 +6840,14 @@ function buildMcpEntry(def) {
6673
6840
  return entry;
6674
6841
  }
6675
6842
  function writeMcpEntries(cwd, defName, mcpEntry) {
6676
- writeMcpEntry(path35.join(cwd, ".mcp.json"), defName, mcpEntry);
6677
- const geminiDir = path35.join(cwd, ".gemini");
6843
+ writeMcpEntry(path36.join(cwd, ".mcp.json"), defName, mcpEntry);
6844
+ const geminiDir = path36.join(cwd, ".gemini");
6678
6845
  if (fs23.existsSync(geminiDir)) {
6679
- writeMcpEntry(path35.join(geminiDir, "settings.json"), defName, mcpEntry);
6846
+ writeMcpEntry(path36.join(geminiDir, "settings.json"), defName, mcpEntry);
6680
6847
  }
6681
6848
  }
6682
6849
  function updateIntegrationsConfig(cwd, defName) {
6683
- const configPath = path35.join(cwd, "harness.config.json");
6850
+ const configPath = path36.join(cwd, "harness.config.json");
6684
6851
  const integConfig = readIntegrationsConfig(configPath);
6685
6852
  if (!integConfig.enabled.includes(defName)) integConfig.enabled.push(defName);
6686
6853
  integConfig.dismissed = integConfig.dismissed.filter((d) => d !== defName);
@@ -6726,7 +6893,7 @@ function printAddSuccess(value) {
6726
6893
  }
6727
6894
  }
6728
6895
  function createAddIntegrationCommand() {
6729
- 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) => {
6730
6897
  const globalOpts = cmd.optsWithGlobals();
6731
6898
  const result = addIntegration(process.cwd(), name);
6732
6899
  if (!result.ok) {
@@ -6740,8 +6907,8 @@ function createAddIntegrationCommand() {
6740
6907
  }
6741
6908
 
6742
6909
  // src/commands/integrations/list.ts
6743
- import { Command as Command48 } from "commander";
6744
- import * as path36 from "path";
6910
+ import { Command as Command49 } from "commander";
6911
+ import * as path37 from "path";
6745
6912
  import chalk5 from "chalk";
6746
6913
  function printTier0Integrations(tier0, mcpServers) {
6747
6914
  console.log(" Tier 0 (zero-config):");
@@ -6765,8 +6932,8 @@ function printTier1Integrations(tier1, mcpServers, dismissed) {
6765
6932
  }
6766
6933
  async function runListIntegrations(globalOpts) {
6767
6934
  const cwd = process.cwd();
6768
- const mcpConfig = readMcpConfig(path36.join(cwd, ".mcp.json"));
6769
- 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"));
6770
6937
  const mcpServers = mcpConfig.mcpServers ?? {};
6771
6938
  if (globalOpts.json) {
6772
6939
  const entries = INTEGRATION_REGISTRY.map((i) => ({
@@ -6797,14 +6964,14 @@ async function runListIntegrations(globalOpts) {
6797
6964
  process.exit(ExitCode.SUCCESS);
6798
6965
  }
6799
6966
  function createListIntegrationsCommand() {
6800
- 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()));
6801
6968
  }
6802
6969
 
6803
6970
  // src/commands/integrations/remove.ts
6804
6971
  init_dist3();
6805
- import { Command as Command49 } from "commander";
6972
+ import { Command as Command50 } from "commander";
6806
6973
  import * as fs24 from "fs";
6807
- import * as path37 from "path";
6974
+ import * as path38 from "path";
6808
6975
  function removeIntegration(cwd, name) {
6809
6976
  const def = INTEGRATION_REGISTRY.find((i) => i.name === name);
6810
6977
  if (!def) {
@@ -6815,21 +6982,21 @@ function removeIntegration(cwd, name) {
6815
6982
  )
6816
6983
  );
6817
6984
  }
6818
- const mcpPath = path37.join(cwd, ".mcp.json");
6985
+ const mcpPath = path38.join(cwd, ".mcp.json");
6819
6986
  removeMcpEntry(mcpPath, def.name);
6820
- const geminiDir = path37.join(cwd, ".gemini");
6987
+ const geminiDir = path38.join(cwd, ".gemini");
6821
6988
  if (fs24.existsSync(geminiDir)) {
6822
- const geminiPath = path37.join(geminiDir, "settings.json");
6989
+ const geminiPath = path38.join(geminiDir, "settings.json");
6823
6990
  removeMcpEntry(geminiPath, def.name);
6824
6991
  }
6825
- const configPath = path37.join(cwd, "harness.config.json");
6992
+ const configPath = path38.join(cwd, "harness.config.json");
6826
6993
  const integConfig = readIntegrationsConfig(configPath);
6827
6994
  integConfig.enabled = integConfig.enabled.filter((e) => e !== def.name);
6828
6995
  writeIntegrationsConfig(configPath, integConfig);
6829
6996
  return Ok(def.displayName);
6830
6997
  }
6831
6998
  function createRemoveIntegrationCommand() {
6832
- 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) => {
6833
7000
  const globalOpts = cmd.optsWithGlobals();
6834
7001
  const cwd = process.cwd();
6835
7002
  const result = removeIntegration(cwd, name);
@@ -6851,8 +7018,8 @@ function createRemoveIntegrationCommand() {
6851
7018
 
6852
7019
  // src/commands/integrations/dismiss.ts
6853
7020
  init_dist3();
6854
- import { Command as Command50 } from "commander";
6855
- import * as path38 from "path";
7021
+ import { Command as Command51 } from "commander";
7022
+ import * as path39 from "path";
6856
7023
  function dismissIntegration(cwd, name) {
6857
7024
  const def = INTEGRATION_REGISTRY.find((i) => i.name === name);
6858
7025
  if (!def) {
@@ -6863,7 +7030,7 @@ function dismissIntegration(cwd, name) {
6863
7030
  )
6864
7031
  );
6865
7032
  }
6866
- const configPath = path38.join(cwd, "harness.config.json");
7033
+ const configPath = path39.join(cwd, "harness.config.json");
6867
7034
  const integConfig = readIntegrationsConfig(configPath);
6868
7035
  if (!integConfig.dismissed.includes(def.name)) {
6869
7036
  integConfig.dismissed.push(def.name);
@@ -6873,7 +7040,7 @@ function dismissIntegration(cwd, name) {
6873
7040
  return Ok(def.displayName);
6874
7041
  }
6875
7042
  function createDismissIntegrationCommand() {
6876
- 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) => {
6877
7044
  const globalOpts = cmd.optsWithGlobals();
6878
7045
  const cwd = process.cwd();
6879
7046
  const result = dismissIntegration(cwd, name);
@@ -6897,7 +7064,7 @@ function createDismissIntegrationCommand() {
6897
7064
 
6898
7065
  // src/commands/integrations/index.ts
6899
7066
  function createIntegrationsCommand() {
6900
- const command = new Command51("integrations").description(
7067
+ const command = new Command52("integrations").description(
6901
7068
  "Manage MCP peer integrations (add, list, remove, dismiss)"
6902
7069
  );
6903
7070
  command.addCommand(createListIntegrationsCommand());
@@ -6908,9 +7075,9 @@ function createIntegrationsCommand() {
6908
7075
  }
6909
7076
 
6910
7077
  // src/commands/knowledge-craft.ts
6911
- import { Command as Command52 } from "commander";
7078
+ import { Command as Command53 } from "commander";
6912
7079
  function createKnowledgeCraftCommand() {
6913
- return new Command52("knowledge-craft").description(
7080
+ return new Command53("knowledge-craft").description(
6914
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."
6915
7082
  ).option("-f, --files <files...>", "Optional file scope (overrides discovery)").option(
6916
7083
  "--exclude-dirs <dirs...>",
@@ -6958,10 +7125,10 @@ function printResult3(result, mode, _formatter) {
6958
7125
  list.push(f);
6959
7126
  byFile.set(f.target.file, list);
6960
7127
  }
6961
- for (const [file, fs48] of byFile) {
7128
+ for (const [file, fs49] of byFile) {
6962
7129
  console.log(`
6963
7130
  ${file}`);
6964
- for (const f of fs48) {
7131
+ for (const f of fs49) {
6965
7132
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.relative}`);
6966
7133
  console.log(` ${f.message}`);
6967
7134
  if (verbose) console.log(` source: ${f.cite.source}`);
@@ -6975,17 +7142,17 @@ ${file}`);
6975
7142
  }
6976
7143
 
6977
7144
  // src/commands/knowledge-pipeline.ts
6978
- import { Command as Command53 } from "commander";
6979
- import * as path39 from "path";
7145
+ import { Command as Command54 } from "commander";
7146
+ import * as path40 from "path";
6980
7147
  import chalk6 from "chalk";
6981
7148
  function createKnowledgePipelineCommand() {
6982
- 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) => {
6983
7150
  const globalOpts = cmd.optsWithGlobals();
6984
7151
  const projectDir = process.cwd();
6985
7152
  try {
6986
- const graphDir = path39.join(projectDir, ".harness", "graph");
6987
- const fs48 = await import("fs/promises");
6988
- await fs48.mkdir(graphDir, { recursive: true });
7153
+ const graphDir = path40.join(projectDir, ".harness", "graph");
7154
+ const fs49 = await import("fs/promises");
7155
+ await fs49.mkdir(graphDir, { recursive: true });
6989
7156
  const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-OWHMNL4W.js");
6990
7157
  const store = new GraphStore2();
6991
7158
  try {
@@ -7151,14 +7318,14 @@ function createKnowledgePipelineCommand() {
7151
7318
  }
7152
7319
 
7153
7320
  // src/commands/learnings/index.ts
7154
- import { Command as Command55 } from "commander";
7321
+ import { Command as Command56 } from "commander";
7155
7322
 
7156
7323
  // src/commands/learnings/prune.ts
7157
7324
  init_dist3();
7158
- import { Command as Command54 } from "commander";
7159
- import * as path40 from "path";
7325
+ import { Command as Command55 } from "commander";
7326
+ import * as path41 from "path";
7160
7327
  async function handlePrune(opts) {
7161
- const projectPath = path40.resolve(opts.path);
7328
+ const projectPath = path41.resolve(opts.path);
7162
7329
  const result = await pruneLearnings(projectPath, opts.stream);
7163
7330
  if (!result.ok) {
7164
7331
  logger.error(result.error.message);
@@ -7197,23 +7364,23 @@ function printPatternProposals(patterns) {
7197
7364
  );
7198
7365
  }
7199
7366
  function createPruneCommand() {
7200
- return new Command54("prune").description(
7367
+ return new Command55("prune").description(
7201
7368
  "Analyze global learnings for patterns, present improvement proposals, and archive old entries"
7202
7369
  ).option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(handlePrune);
7203
7370
  }
7204
7371
 
7205
7372
  // src/commands/learnings/index.ts
7206
7373
  function createLearningsCommand() {
7207
- const command = new Command55("learnings").description("Learnings management commands");
7374
+ const command = new Command56("learnings").description("Learnings management commands");
7208
7375
  command.addCommand(createPruneCommand());
7209
7376
  return command;
7210
7377
  }
7211
7378
 
7212
7379
  // src/commands/linter/index.ts
7213
- import { Command as Command58 } from "commander";
7380
+ import { Command as Command59 } from "commander";
7214
7381
 
7215
7382
  // src/commands/linter/generate.ts
7216
- import { Command as Command56 } from "commander";
7383
+ import { Command as Command57 } from "commander";
7217
7384
  function formatGenerateError(e) {
7218
7385
  switch (e.type) {
7219
7386
  case "parse":
@@ -7257,7 +7424,7 @@ function handleSuccess(result, useJson) {
7257
7424
  Generated ${result.rulesGenerated.length} rules to ${result.outputDir}`);
7258
7425
  }
7259
7426
  function createGenerateCommand2() {
7260
- 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) => {
7261
7428
  try {
7262
7429
  if (options.verbose) logger.info(`Parsing config: ${options.config}`);
7263
7430
  const result = await generate({
@@ -7279,9 +7446,9 @@ function createGenerateCommand2() {
7279
7446
  }
7280
7447
 
7281
7448
  // src/commands/linter/validate.ts
7282
- import { Command as Command57 } from "commander";
7449
+ import { Command as Command58 } from "commander";
7283
7450
  function createValidateCommand() {
7284
- 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) => {
7285
7452
  try {
7286
7453
  const result = await validate({ configPath: options.config });
7287
7454
  if (options.json) {
@@ -7300,7 +7467,7 @@ function createValidateCommand() {
7300
7467
 
7301
7468
  // src/commands/linter/index.ts
7302
7469
  function createLinterCommand() {
7303
- const linter = new Command58("linter").description(
7470
+ const linter = new Command59("linter").description(
7304
7471
  "Generate and validate ESLint rules from YAML config"
7305
7472
  );
7306
7473
  linter.addCommand(createGenerateCommand2());
@@ -7309,8 +7476,8 @@ function createLinterCommand() {
7309
7476
  }
7310
7477
 
7311
7478
  // src/commands/maintenance.ts
7312
- import { Command as Command59 } from "commander";
7313
- import * as path41 from "path";
7479
+ import { Command as Command60 } from "commander";
7480
+ import * as path42 from "path";
7314
7481
  import * as fs25 from "fs";
7315
7482
  import chalk7 from "chalk";
7316
7483
  import {
@@ -7319,7 +7486,7 @@ import {
7319
7486
  WorkflowLoader
7320
7487
  } from "@harness-engineering/orchestrator";
7321
7488
  async function loadMaintenanceConfig(cwd) {
7322
- const workflowPath = path41.join(cwd, "harness.orchestrator.md");
7489
+ const workflowPath = path42.join(cwd, "harness.orchestrator.md");
7323
7490
  if (!fs25.existsSync(workflowPath)) return null;
7324
7491
  const loader = new WorkflowLoader();
7325
7492
  const result = await loader.loadWorkflow(workflowPath);
@@ -7401,11 +7568,11 @@ function printListTable(rows) {
7401
7568
  }
7402
7569
  }
7403
7570
  function createMaintenanceCommand() {
7404
- const command = new Command59("maintenance").description(
7571
+ const command = new Command60("maintenance").description(
7405
7572
  "Inspect built-in + custom maintenance tasks and their persisted outputs"
7406
7573
  );
7407
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) => {
7408
- const cwd = path41.resolve(opts.path);
7575
+ const cwd = path42.resolve(opts.path);
7409
7576
  const config = await loadMaintenanceConfig(cwd);
7410
7577
  const tasks = mergeResolvedTasks(config);
7411
7578
  const rows = tasks.map((t) => ({
@@ -7432,10 +7599,10 @@ async function runShow(taskId, opts) {
7432
7599
  console.error(`Invalid task id '${taskId}' (must match ^[a-z0-9][a-z0-9-]*$).`);
7433
7600
  process.exit(ExitCode.ERROR);
7434
7601
  }
7435
- const cwd = path41.resolve(opts.path ?? ".");
7602
+ const cwd = path42.resolve(opts.path ?? ".");
7436
7603
  const limit = Math.max(1, parseInt(opts.limit ?? "5", 10) || 5);
7437
7604
  const store = new TaskOutputStore({
7438
- rootDir: path41.join(cwd, ".harness", "maintenance")
7605
+ rootDir: path42.join(cwd, ".harness", "maintenance")
7439
7606
  });
7440
7607
  const entries = await store.list(taskId, limit, 0);
7441
7608
  renderShow(taskId, entries, Boolean(opts.json));
@@ -7469,7 +7636,7 @@ function describeOrigin(origin) {
7469
7636
  }
7470
7637
 
7471
7638
  // src/commands/mcp.ts
7472
- import { Command as Command60 } from "commander";
7639
+ import { Command as Command61 } from "commander";
7473
7640
  var VALID_TIERS = /* @__PURE__ */ new Set(["core", "standard", "full"]);
7474
7641
  function parseTier(value) {
7475
7642
  const lower = value.toLowerCase();
@@ -7486,7 +7653,7 @@ function parseBudget(value) {
7486
7653
  return n;
7487
7654
  }
7488
7655
  function createMcpCommand() {
7489
- 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(
7490
7657
  "--tier <core|standard|full>",
7491
7658
  "Load a preset tool tier instead of all tools",
7492
7659
  parseTier
@@ -7496,8 +7663,8 @@ function createMcpCommand() {
7496
7663
  parseBudget
7497
7664
  ).action(async (opts) => {
7498
7665
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
7499
- import("./mcp-JBIBINO2.js"),
7500
- import("./tool-tiers-B7JC2XC3.js")
7666
+ import("./mcp-RK3SFVYB.js"),
7667
+ import("./tool-tiers-OKK5FE57.js")
7501
7668
  ]);
7502
7669
  if (opts.tools && opts.tools.length > 0) {
7503
7670
  await startServer2(opts.tools);
@@ -7518,9 +7685,9 @@ function createMcpCommand() {
7518
7685
 
7519
7686
  // src/commands/mcp-guard.ts
7520
7687
  init_dist3();
7521
- import { Command as Command61 } from "commander";
7688
+ import { Command as Command62 } from "commander";
7522
7689
  import * as fs26 from "fs";
7523
- import * as path42 from "path";
7690
+ import * as path43 from "path";
7524
7691
  import chalk8 from "chalk";
7525
7692
  function extractNpmPackages(config) {
7526
7693
  const out = [];
@@ -7559,7 +7726,7 @@ function parseNpmSpec(spec) {
7559
7726
  }
7560
7727
  async function runMcpGuardCheck(options = {}) {
7561
7728
  const cwd = options.cwd ?? process.cwd();
7562
- const configPath = options.configPath ?? path42.join(cwd, ".mcp.json");
7729
+ const configPath = options.configPath ?? path43.join(cwd, ".mcp.json");
7563
7730
  if (!fs26.existsSync(configPath)) {
7564
7731
  return { ok: true, checked: [] };
7565
7732
  }
@@ -7570,7 +7737,7 @@ async function runMcpGuardCheck(options = {}) {
7570
7737
  return { ok: true, checked: [] };
7571
7738
  }
7572
7739
  const pkgs = extractNpmPackages(config);
7573
- const cacheDir = path42.join(cwd, ".harness", "cache", "osv");
7740
+ const cacheDir = path43.join(cwd, ".harness", "cache", "osv");
7574
7741
  const warnLogger = {
7575
7742
  warn: (m, ctx) => logger.warn(ctx ? `${m} ${JSON.stringify(ctx)}` : m)
7576
7743
  };
@@ -7626,12 +7793,12 @@ function formatHuman(result) {
7626
7793
  }
7627
7794
  }
7628
7795
  function createMcpGuardCommand() {
7629
- 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(
7630
7797
  "after",
7631
7798
  '\nUse "harness mcp-guard check" before launching MCP servers to block known malicious packages.'
7632
7799
  );
7633
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) => {
7634
- const cwd = path42.resolve(opts.path);
7801
+ const cwd = path43.resolve(opts.path);
7635
7802
  const result = await runMcpGuardCheck({ cwd, strict: opts.strict, json: opts.json });
7636
7803
  if (opts.json) {
7637
7804
  console.log(JSON.stringify(result, null, 2));
@@ -7642,8 +7809,8 @@ function createMcpGuardCommand() {
7642
7809
  process.exit(result.ok ? ExitCode.SUCCESS : 2);
7643
7810
  });
7644
7811
  command.command("cache").description("Manage the on-disk OSV advisory cache").command("clear").option("--path <path>", "Project root path", ".").action(async (opts) => {
7645
- const cwd = path42.resolve(opts.path);
7646
- const cacheDir = path42.join(cwd, ".harness", "cache", "osv");
7812
+ const cwd = path43.resolve(opts.path);
7813
+ const cacheDir = path43.join(cwd, ".harness", "cache", "osv");
7647
7814
  try {
7648
7815
  fs26.rmSync(cacheDir, { recursive: true, force: true });
7649
7816
  console.log(`Cleared ${cacheDir}`);
@@ -7657,12 +7824,12 @@ function createMcpGuardCommand() {
7657
7824
  }
7658
7825
 
7659
7826
  // src/commands/migrate.ts
7660
- import { Command as Command63 } from "commander";
7827
+ import { Command as Command64 } from "commander";
7661
7828
 
7662
7829
  // src/commands/migrate-backends.ts
7663
- import { Command as Command62 } from "commander";
7830
+ import { Command as Command63 } from "commander";
7664
7831
  import * as fs27 from "fs";
7665
- import * as path43 from "path";
7832
+ import * as path44 from "path";
7666
7833
  import chalk9 from "chalk";
7667
7834
  import { parse as parseYaml2 } from "yaml";
7668
7835
  async function runMigrateBackends(opts = {}) {
@@ -7684,7 +7851,7 @@ async function runMigrateBackends(opts = {}) {
7684
7851
  };
7685
7852
  }
7686
7853
  const routing = readRoutingFromOrchestratorMd(mdPath);
7687
- const jsonPath = path43.join(path43.dirname(mdPath), "harness.config.json");
7854
+ const jsonPath = path44.join(path44.dirname(mdPath), "harness.config.json");
7688
7855
  if (!fs27.existsSync(jsonPath)) {
7689
7856
  return {
7690
7857
  status: "error",
@@ -7777,7 +7944,7 @@ function readRoutingFromOrchestratorMd(mdPath) {
7777
7944
  return routing ?? null;
7778
7945
  }
7779
7946
  function createBackendsSubcommand() {
7780
- return new Command62("backends").description(
7947
+ return new Command63("backends").description(
7781
7948
  "Copy agent.backends (and routing) from harness.orchestrator.md into harness.config.json."
7782
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) => {
7783
7950
  const result = await runMigrateBackends({
@@ -7797,7 +7964,7 @@ function createBackendsSubcommand() {
7797
7964
  init_dist3();
7798
7965
  init_dist2();
7799
7966
  import * as fs28 from "fs";
7800
- import * as path44 from "path";
7967
+ import * as path45 from "path";
7801
7968
  import * as readline from "readline";
7802
7969
  import { execFileSync as execFileSync4 } from "child_process";
7803
7970
  import chalk10 from "chalk";
@@ -7829,7 +7996,7 @@ function walk(dir, predicate) {
7829
7996
  const out = [];
7830
7997
  for (const entry of fs28.readdirSync(dir, { withFileTypes: true })) {
7831
7998
  if (DEFAULT_SKIP_DIRS.has(entry.name)) continue;
7832
- const full = path44.join(dir, entry.name);
7999
+ const full = path45.join(dir, entry.name);
7833
8000
  if (entry.isDirectory()) out.push(...walk(full, predicate));
7834
8001
  else if (predicate(full)) out.push(full);
7835
8002
  }
@@ -7841,11 +8008,11 @@ function extractAutopilotTopic(state) {
7841
8008
  }
7842
8009
  function buildAutopilotMap(cwd) {
7843
8010
  const map = /* @__PURE__ */ new Map();
7844
- const sessionsDir = path44.join(cwd, ".harness", "sessions");
8011
+ const sessionsDir = path45.join(cwd, ".harness", "sessions");
7845
8012
  if (!fs28.existsSync(sessionsDir)) return map;
7846
8013
  for (const session of listDirs(sessionsDir)) {
7847
8014
  if (!session.startsWith("changes--")) continue;
7848
- const state = readJson2(path44.join(sessionsDir, session, "autopilot-state.json"));
8015
+ const state = readJson2(path45.join(sessionsDir, session, "autopilot-state.json"));
7849
8016
  if (!state) continue;
7850
8017
  const topic = extractAutopilotTopic(state);
7851
8018
  if (!topic) continue;
@@ -7883,7 +8050,7 @@ function extractTopicFromFilename(filename, proposalTopics) {
7883
8050
  return best;
7884
8051
  }
7885
8052
  function resolveDocsDir(cwd) {
7886
- const configPath = path44.join(cwd, "harness.config.json");
8053
+ const configPath = path45.join(cwd, "harness.config.json");
7887
8054
  const configResult = fs28.existsSync(configPath) ? resolveConfig(configPath) : null;
7888
8055
  let docsDir;
7889
8056
  if (configResult?.ok) {
@@ -7896,16 +8063,16 @@ function resolveDocsDir(cwd) {
7896
8063
  } else {
7897
8064
  docsDir = "./docs";
7898
8065
  }
7899
- const docsAbs = path44.resolve(cwd, docsDir);
7900
- const relRaw = path44.relative(cwd, docsAbs).replaceAll("\\", "/");
8066
+ const docsAbs = path45.resolve(cwd, docsDir);
8067
+ const relRaw = path45.relative(cwd, docsAbs).replaceAll("\\", "/");
7901
8068
  return relRaw === "" ? "docs" : relRaw;
7902
8069
  }
7903
8070
  function collectAdrMoves(cwd, docsRel) {
7904
8071
  const moves = [];
7905
- const legacyAdrDir = path44.join(cwd, ".harness", "architecture");
8072
+ const legacyAdrDir = path45.join(cwd, ".harness", "architecture");
7906
8073
  if (!fs28.existsSync(legacyAdrDir)) return moves;
7907
8074
  for (const topic of listDirs(legacyAdrDir)) {
7908
- const topicSrc = path44.join(legacyAdrDir, topic);
8075
+ const topicSrc = path45.join(legacyAdrDir, topic);
7909
8076
  for (const file of listFiles(topicSrc, (n) => n.endsWith(".md"))) {
7910
8077
  moves.push({
7911
8078
  src: `.harness/architecture/${topic}/${file}`,
@@ -7917,9 +8084,9 @@ function collectAdrMoves(cwd, docsRel) {
7917
8084
  }
7918
8085
  function collectProposalTopics(cwd) {
7919
8086
  const topics = /* @__PURE__ */ new Set();
7920
- const changesDir = path44.join(cwd, "docs", "changes");
8087
+ const changesDir = path45.join(cwd, "docs", "changes");
7921
8088
  for (const topic of listDirs(changesDir)) {
7922
- if (fs28.existsSync(path44.join(changesDir, topic, "proposal.md"))) {
8089
+ if (fs28.existsSync(path45.join(changesDir, topic, "proposal.md"))) {
7923
8090
  topics.add(topic);
7924
8091
  }
7925
8092
  }
@@ -7946,12 +8113,12 @@ async function buildPlan(opts) {
7946
8113
  orphanPlans: [],
7947
8114
  proposalTopics: collectProposalTopics(cwd)
7948
8115
  };
7949
- const legacyPlanDir = path44.join(cwd, "docs", "plans");
8116
+ const legacyPlanDir = path45.join(cwd, "docs", "plans");
7950
8117
  if (!fs28.existsSync(legacyPlanDir)) return plan;
7951
8118
  const autopilotMap = buildAutopilotMap(cwd);
7952
8119
  for (const file of listFiles(legacyPlanDir, (n) => n.endsWith(".md") && n !== "index.md")) {
7953
8120
  const planRel = `docs/plans/${file}`;
7954
- const planAbs = path44.join(legacyPlanDir, file);
8121
+ const planAbs = path45.join(legacyPlanDir, file);
7955
8122
  const subdir = file.includes("VERIFICATION") ? "verifications" : "plans";
7956
8123
  const classified = classifyPlan(planRel, planAbs, file, autopilotMap, plan.proposalTopics);
7957
8124
  if (classified) {
@@ -7969,8 +8136,8 @@ async function buildPlan(opts) {
7969
8136
  return plan;
7970
8137
  }
7971
8138
  function gitMv(cwd, src, dest, useGit) {
7972
- const destAbs = path44.join(cwd, dest);
7973
- fs28.mkdirSync(path44.dirname(destAbs), { recursive: true });
8139
+ const destAbs = path45.join(cwd, dest);
8140
+ fs28.mkdirSync(path45.dirname(destAbs), { recursive: true });
7974
8141
  if (useGit) {
7975
8142
  try {
7976
8143
  execFileSync4("git", ["mv", src, dest], { cwd, stdio: "pipe" });
@@ -7978,7 +8145,7 @@ function gitMv(cwd, src, dest, useGit) {
7978
8145
  } catch {
7979
8146
  }
7980
8147
  }
7981
- fs28.renameSync(path44.join(cwd, src), destAbs);
8148
+ fs28.renameSync(path45.join(cwd, src), destAbs);
7982
8149
  }
7983
8150
  function executeMigration(plan) {
7984
8151
  let moved = 0;
@@ -8010,8 +8177,8 @@ function updateReferences(plan) {
8010
8177
  let files = 0;
8011
8178
  let replacements = 0;
8012
8179
  const targets = [
8013
- ...walk(path44.join(plan.cwd, "docs"), (p) => p.endsWith(".md")),
8014
- ...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"))
8015
8182
  ];
8016
8183
  for (const target of targets) {
8017
8184
  let text;
@@ -8038,7 +8205,7 @@ function updateReferences(plan) {
8038
8205
  }
8039
8206
  async function prompt(question, def = "n") {
8040
8207
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8041
- const answer = await new Promise((resolve46) => rl.question(question, resolve46));
8208
+ const answer = await new Promise((resolve47) => rl.question(question, resolve47));
8042
8209
  rl.close();
8043
8210
  return (answer.trim() || def).toLowerCase();
8044
8211
  }
@@ -8088,7 +8255,7 @@ async function resolveOrphans(plan, opts) {
8088
8255
  }
8089
8256
  function bucketOrphans(plan, topic) {
8090
8257
  for (const src of plan.orphanPlans) {
8091
- const file = path44.basename(src);
8258
+ const file = path45.basename(src);
8092
8259
  const isVerification = file.includes("VERIFICATION");
8093
8260
  const subdir = isVerification ? "verifications" : "plans";
8094
8261
  plan.planMoves.push({
@@ -8130,9 +8297,9 @@ function summarize(plan) {
8130
8297
  console.log("");
8131
8298
  }
8132
8299
  async function detectLegacyArtifacts(cwd) {
8133
- const adrLegacyDir = path44.join(cwd, ".harness", "architecture");
8300
+ const adrLegacyDir = path45.join(cwd, ".harness", "architecture");
8134
8301
  const adrLegacy = fs28.existsSync(adrLegacyDir) && listDirs(adrLegacyDir).length > 0;
8135
- const planLegacyDir = path44.join(cwd, "docs", "plans");
8302
+ const planLegacyDir = path45.join(cwd, "docs", "plans");
8136
8303
  const planLegacy = fs28.existsSync(planLegacyDir) && listFiles(planLegacyDir, (n) => n.endsWith(".md") && n !== "index.md").length > 0;
8137
8304
  return { adrLegacy, planLegacy };
8138
8305
  }
@@ -8201,7 +8368,7 @@ async function runMigrate(opts) {
8201
8368
  });
8202
8369
  }
8203
8370
  function createMigrateCommand() {
8204
- const cmd = new Command63("migrate").description("Migrate legacy harness artifact locations to current layout").option("--dry-run", "Show the migration plan without moving files", false).option("--yes", "Skip confirmation prompt", false).option(
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(
8205
8372
  "--skip-references",
8206
8373
  "Do not update path references in docs/sessions after moves",
8207
8374
  false
@@ -8225,7 +8392,7 @@ function createMigrateCommand() {
8225
8392
  }
8226
8393
 
8227
8394
  // src/commands/models.ts
8228
- import { Command as Command64 } from "commander";
8395
+ import { Command as Command65 } from "commander";
8229
8396
  import { defaultFetchModels } from "@harness-engineering/orchestrator";
8230
8397
  function errorResult(message, partial) {
8231
8398
  return {
@@ -8343,7 +8510,7 @@ function formatProbe(result) {
8343
8510
  return lines.join("\n");
8344
8511
  }
8345
8512
  function createModelsCommand() {
8346
- const cmd = new Command64("models").description(
8513
+ const cmd = new Command65("models").description(
8347
8514
  "Inspect and manage local LLM backends. Currently ships `probe`; LMLM phases add status/suggest/pool/proposals."
8348
8515
  );
8349
8516
  cmd.command("probe").description(
@@ -8369,9 +8536,9 @@ function createModelsCommand() {
8369
8536
  }
8370
8537
 
8371
8538
  // src/commands/naming-craft.ts
8372
- import { Command as Command65 } from "commander";
8539
+ import { Command as Command66 } from "commander";
8373
8540
  function createNamingCraftCommand() {
8374
- return new Command65("naming-craft").description(
8541
+ return new Command66("naming-craft").description(
8375
8542
  "LLM-judgment critique of identifier names (variables, functions, types, files). First craft-pipeline ceiling skill; uses curated rubric catalog from Martin/Beck/Karlton."
8376
8543
  ).option("-f, --files <files...>", "Optional file/glob scope").option(
8377
8544
  "-k, --kinds <kinds...>",
@@ -8421,10 +8588,10 @@ function printResult4(result, mode, _formatter) {
8421
8588
  list.push(f);
8422
8589
  byFile.set(f.target.file, list);
8423
8590
  }
8424
- for (const [file, fs48] of byFile) {
8591
+ for (const [file, fs49] of byFile) {
8425
8592
  console.log(`
8426
8593
  ${file}`);
8427
- for (const f of fs48) {
8594
+ for (const f of fs49) {
8428
8595
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
8429
8596
  console.log(
8430
8597
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.kind} ${f.target.identifier}${line}`
@@ -8444,13 +8611,13 @@ ${file}`);
8444
8611
  }
8445
8612
 
8446
8613
  // src/commands/notifications/index.ts
8447
- import { Command as Command67 } from "commander";
8614
+ import { Command as Command68 } from "commander";
8448
8615
 
8449
8616
  // src/commands/notifications/test.ts
8450
8617
  init_dist3();
8451
- import { Command as Command66 } from "commander";
8618
+ import { Command as Command67 } from "commander";
8452
8619
  import { randomBytes } from "crypto";
8453
- import { resolve as resolve28 } from "path";
8620
+ import { resolve as resolve29 } from "path";
8454
8621
  import { SinkRegistry, SinkConfigError, wrapAsEnvelope } from "@harness-engineering/orchestrator";
8455
8622
  function makeTestEvent(message) {
8456
8623
  return {
@@ -8500,9 +8667,9 @@ async function runNotificationsTest(sinkId, opts, projectRoot2 = process.cwd())
8500
8667
  return { ok: false, error: result.error };
8501
8668
  }
8502
8669
  function createNotificationsTestSubcommand() {
8503
- return new Command66("test").description("Send a synthetic notification.test event through the named sink").argument("<sink-id>", "Sink id from harness.config.json `notifications.sinks[].id`").option("--message <text>", "Override the default test message").action(async (sinkId, opts, cmd) => {
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) => {
8504
8671
  const globalOpts = cmd.optsWithGlobals();
8505
- const projectRoot2 = typeof globalOpts["cwd"] === "string" ? resolve28(globalOpts["cwd"]) : process.cwd();
8672
+ const projectRoot2 = typeof globalOpts["cwd"] === "string" ? resolve29(globalOpts["cwd"]) : process.cwd();
8506
8673
  const result = await runNotificationsTest(sinkId, opts, projectRoot2);
8507
8674
  if (globalOpts["json"]) {
8508
8675
  console.log(JSON.stringify(result, null, 2));
@@ -8517,7 +8684,7 @@ function createNotificationsTestSubcommand() {
8517
8684
 
8518
8685
  // src/commands/notifications/index.ts
8519
8686
  function createNotificationsCommand() {
8520
- const cmd = new Command67("notifications").description(
8687
+ const cmd = new Command68("notifications").description(
8521
8688
  "Manage notification sinks (Slack and others)"
8522
8689
  );
8523
8690
  cmd.addCommand(createNotificationsTestSubcommand());
@@ -8525,13 +8692,13 @@ function createNotificationsCommand() {
8525
8692
  }
8526
8693
 
8527
8694
  // src/commands/orchestrator.ts
8528
- import { Command as Command68 } from "commander";
8529
- import * as path45 from "path";
8695
+ import { Command as Command69 } from "commander";
8696
+ import * as path46 from "path";
8530
8697
  import { Orchestrator, WorkflowLoader as WorkflowLoader2, launchTUI } from "@harness-engineering/orchestrator";
8531
8698
  function createOrchestratorCommand() {
8532
- const orchestrator = new Command68("orchestrator");
8699
+ const orchestrator = new Command69("orchestrator");
8533
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) => {
8534
- const workflowPath = path45.resolve(process.cwd(), opts.workflow);
8701
+ const workflowPath = path46.resolve(process.cwd(), opts.workflow);
8535
8702
  const loader = new WorkflowLoader2();
8536
8703
  const result = await loader.loadWorkflow(workflowPath);
8537
8704
  if (!result.ok) {
@@ -8565,13 +8732,13 @@ function createOrchestratorCommand() {
8565
8732
 
8566
8733
  // src/commands/perf.ts
8567
8734
  init_dist3();
8568
- import { Command as Command69 } from "commander";
8569
- import * as path46 from "path";
8735
+ import { Command as Command70 } from "commander";
8736
+ import * as path47 from "path";
8570
8737
  function registerBenchCommand(perf) {
8571
8738
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
8572
8739
  const globalOpts = cmd.optsWithGlobals();
8573
8740
  const cwd = process.cwd();
8574
- const { BenchmarkRunner } = await import("./dist-JCFK263L.js");
8741
+ const { BenchmarkRunner } = await import("./dist-LHINSVK4.js");
8575
8742
  const runner = new BenchmarkRunner();
8576
8743
  const benchFiles = runner.discover(cwd, glob2);
8577
8744
  if (benchFiles.length === 0) {
@@ -8635,7 +8802,7 @@ async function runBaselinesShow(globalOpts) {
8635
8802
  }
8636
8803
  async function runBaselinesUpdate(globalOpts) {
8637
8804
  const cwd = process.cwd();
8638
- const { BenchmarkRunner } = await import("./dist-JCFK263L.js");
8805
+ const { BenchmarkRunner } = await import("./dist-LHINSVK4.js");
8639
8806
  const runner = new BenchmarkRunner();
8640
8807
  const manager = new BaselineManager(cwd);
8641
8808
  logger.info("Running benchmarks to update baselines...");
@@ -8676,9 +8843,9 @@ function registerReportCommand(perf) {
8676
8843
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
8677
8844
  const globalOpts = cmd.optsWithGlobals();
8678
8845
  const cwd = process.cwd();
8679
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-JCFK263L.js");
8846
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-LHINSVK4.js");
8680
8847
  const analyzer = new EntropyAnalyzer2({
8681
- rootDir: path46.resolve(cwd),
8848
+ rootDir: path47.resolve(cwd),
8682
8849
  analyze: { complexity: true, coupling: true }
8683
8850
  });
8684
8851
  const result = await analyzer.analyze();
@@ -8737,7 +8904,7 @@ function registerCriticalPathsCommand(perf) {
8737
8904
  });
8738
8905
  }
8739
8906
  function createPerfCommand() {
8740
- const perf = new Command69("perf").description("Performance benchmark and baseline management");
8907
+ const perf = new Command70("perf").description("Performance benchmark and baseline management");
8741
8908
  registerBenchCommand(perf);
8742
8909
  registerBaselinesCommands(perf);
8743
8910
  registerReportCommand(perf);
@@ -8746,10 +8913,10 @@ function createPerfCommand() {
8746
8913
  }
8747
8914
 
8748
8915
  // src/commands/persona/index.ts
8749
- import { Command as Command72 } from "commander";
8916
+ import { Command as Command73 } from "commander";
8750
8917
 
8751
8918
  // src/commands/persona/list.ts
8752
- import { Command as Command70 } from "commander";
8919
+ import { Command as Command71 } from "commander";
8753
8920
  function printPersonaList(personas) {
8754
8921
  if (personas.length === 0) {
8755
8922
  logger.info("No personas found.");
@@ -8763,7 +8930,7 @@ function printPersonaList(personas) {
8763
8930
  }
8764
8931
  }
8765
8932
  function createListCommand2() {
8766
- 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) => {
8767
8934
  const globalOpts = cmd.optsWithGlobals();
8768
8935
  const personasDir = resolvePersonasDir();
8769
8936
  const result = listPersonas(personasDir);
@@ -8783,17 +8950,17 @@ function createListCommand2() {
8783
8950
  }
8784
8951
 
8785
8952
  // src/commands/persona/generate.ts
8786
- import { Command as Command71 } from "commander";
8953
+ import { Command as Command72 } from "commander";
8787
8954
  import * as fs29 from "fs";
8788
- import * as path47 from "path";
8955
+ import * as path48 from "path";
8789
8956
  function generatePersonaArtifacts(persona, outputDir, only) {
8790
8957
  const slug = toKebabCase(persona.name);
8791
8958
  const generated = [];
8792
8959
  if (!only || only === "runtime") {
8793
8960
  const result = generateRuntime(persona);
8794
8961
  if (result.ok) {
8795
- const outPath = path47.join(outputDir, `${slug}.runtime.json`);
8796
- fs29.mkdirSync(path47.dirname(outPath), { recursive: true });
8962
+ const outPath = path48.join(outputDir, `${slug}.runtime.json`);
8963
+ fs29.mkdirSync(path48.dirname(outPath), { recursive: true });
8797
8964
  fs29.writeFileSync(outPath, result.value);
8798
8965
  generated.push(outPath);
8799
8966
  }
@@ -8801,7 +8968,7 @@ function generatePersonaArtifacts(persona, outputDir, only) {
8801
8968
  if (!only || only === "agents-md") {
8802
8969
  const result = generateAgentsMd(persona);
8803
8970
  if (result.ok) {
8804
- const outPath = path47.join(outputDir, `${slug}.agents.md`);
8971
+ const outPath = path48.join(outputDir, `${slug}.agents.md`);
8805
8972
  fs29.writeFileSync(outPath, result.value);
8806
8973
  generated.push(outPath);
8807
8974
  }
@@ -8809,8 +8976,8 @@ function generatePersonaArtifacts(persona, outputDir, only) {
8809
8976
  if (!only || only === "ci") {
8810
8977
  const result = generateCIWorkflow(persona, "github");
8811
8978
  if (result.ok) {
8812
- const outPath = path47.join(outputDir, ".github", "workflows", `${slug}.yml`);
8813
- 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 });
8814
8981
  fs29.writeFileSync(outPath, result.value);
8815
8982
  generated.push(outPath);
8816
8983
  }
@@ -8818,16 +8985,16 @@ function generatePersonaArtifacts(persona, outputDir, only) {
8818
8985
  return generated;
8819
8986
  }
8820
8987
  function createGenerateCommand3() {
8821
- return new Command71("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
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) => {
8822
8989
  const globalOpts = cmd.optsWithGlobals();
8823
- const personaResult = loadPersona(path47.join(resolvePersonasDir(), `${name}.yaml`));
8990
+ const personaResult = loadPersona(path48.join(resolvePersonasDir(), `${name}.yaml`));
8824
8991
  if (!personaResult.ok) {
8825
8992
  logger.error(personaResult.error.message);
8826
8993
  process.exit(ExitCode.ERROR);
8827
8994
  }
8828
8995
  const generated = generatePersonaArtifacts(
8829
8996
  personaResult.value,
8830
- path47.resolve(opts.outputDir),
8997
+ path48.resolve(opts.outputDir),
8831
8998
  opts.only
8832
8999
  );
8833
9000
  if (!globalOpts.quiet) {
@@ -8840,7 +9007,7 @@ function createGenerateCommand3() {
8840
9007
 
8841
9008
  // src/commands/persona/index.ts
8842
9009
  function createPersonaCommand() {
8843
- const command = new Command72("persona").description("Agent persona management commands");
9010
+ const command = new Command73("persona").description("Agent persona management commands");
8844
9011
  command.addCommand(createListCommand2());
8845
9012
  command.addCommand(createGenerateCommand3());
8846
9013
  return command;
@@ -8848,7 +9015,7 @@ function createPersonaCommand() {
8848
9015
 
8849
9016
  // src/commands/predict.ts
8850
9017
  init_dist3();
8851
- import { Command as Command73 } from "commander";
9018
+ import { Command as Command74 } from "commander";
8852
9019
  import chalk11 from "chalk";
8853
9020
  var CATEGORY_ORDER = [
8854
9021
  "circular-deps",
@@ -8954,7 +9121,7 @@ function handlePredictError(err, mode) {
8954
9121
  process.exit(ExitCode.ERROR);
8955
9122
  }
8956
9123
  function createPredictCommand() {
8957
- const command = new Command73("predict").description("Predict which architectural constraints will break and when").option("--category <name>", "Filter to a single metric category").option("--no-roadmap", "Baseline only \u2014 skip roadmap spec impact").option("--horizon <weeks>", "Forecast horizon in weeks (default: 12)", "12").action(async (opts, cmd) => {
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) => {
8958
9125
  const globalOpts = cmd.optsWithGlobals();
8959
9126
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
8960
9127
  try {
@@ -8978,10 +9145,10 @@ function createPredictCommand() {
8978
9145
 
8979
9146
  // src/commands/proposals.ts
8980
9147
  init_dist3();
8981
- import { Command as Command74 } from "commander";
8982
- import { resolve as resolve32 } from "path";
9148
+ import { Command as Command75 } from "commander";
9149
+ import { resolve as resolve33 } from "path";
8983
9150
  function projectRoot() {
8984
- return resolve32(process.env["HARNESS_PROJECT_ROOT"] ?? process.cwd());
9151
+ return resolve33(process.env["HARNESS_PROJECT_ROOT"] ?? process.cwd());
8985
9152
  }
8986
9153
  function summarizeProposal(p) {
8987
9154
  return {
@@ -9073,7 +9240,7 @@ async function actApproveCommand(id) {
9073
9240
  }
9074
9241
  }
9075
9242
  function createProposalsCommand() {
9076
- const cmd = new Command74("proposals").description("Skill-proposal review queue");
9243
+ const cmd = new Command75("proposals").description("Skill-proposal review queue");
9077
9244
  cmd.command("list").description("List skill proposals in the local queue").option(
9078
9245
  "--status <status>",
9079
9246
  `Filter by status \u2014 one of ${ALLOWED_STATUSES.join(" | ")}`,
@@ -9089,8 +9256,8 @@ function createProposalsCommand() {
9089
9256
 
9090
9257
  // src/commands/publish-analyses.ts
9091
9258
  import * as fs30 from "fs";
9092
- import * as path48 from "path";
9093
- import { Command as Command75 } from "commander";
9259
+ import * as path49 from "path";
9260
+ import { Command as Command76 } from "commander";
9094
9261
  init_dist3();
9095
9262
  import {
9096
9263
  renderAnalysisComment,
@@ -9098,7 +9265,7 @@ import {
9098
9265
  savePublishedIndex
9099
9266
  } from "@harness-engineering/orchestrator";
9100
9267
  function bootstrapTrackerCommand(opts, verb) {
9101
- const projectPath = path48.resolve(opts.dir);
9268
+ const projectPath = path49.resolve(opts.dir);
9102
9269
  const trackerConfig = loadTrackerSyncConfig(projectPath);
9103
9270
  if (!trackerConfig) {
9104
9271
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -9110,7 +9277,7 @@ function bootstrapTrackerCommand(opts, verb) {
9110
9277
  );
9111
9278
  return null;
9112
9279
  }
9113
- const projectEnvPath = path48.join(projectPath, ".env");
9280
+ const projectEnvPath = path49.join(projectPath, ".env");
9114
9281
  if (fs30.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
9115
9282
  __require("dotenv").config({ path: projectEnvPath });
9116
9283
  }
@@ -9147,7 +9314,7 @@ async function buildNameToExternalIdMap(projectPath) {
9147
9314
  }
9148
9315
  return fileLessMap;
9149
9316
  }
9150
- const roadmapFile = path48.join(projectPath, "docs", "roadmap.md");
9317
+ const roadmapFile = path49.join(projectPath, "docs", "roadmap.md");
9151
9318
  if (!fs30.existsSync(roadmapFile)) {
9152
9319
  logger.error("No docs/roadmap.md found. Cannot map issue hashes to external IDs.");
9153
9320
  return null;
@@ -9203,8 +9370,8 @@ async function runPublishAnalyses(opts) {
9203
9370
  const nameToExternalId = await buildNameToExternalIdMap(projectPath);
9204
9371
  if (!nameToExternalId) return process.exit(1);
9205
9372
  const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
9206
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-JCFK263L.js");
9207
- 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"));
9208
9375
  const analyses = await archive.list();
9209
9376
  if (analyses.length === 0) {
9210
9377
  logger.info("No analyses found to publish.");
@@ -9226,7 +9393,7 @@ async function runPublishAnalyses(opts) {
9226
9393
  }
9227
9394
  }
9228
9395
  function createPublishAnalysesCommand() {
9229
- const command = new Command75("publish-analyses").description(
9396
+ const command = new Command76("publish-analyses").description(
9230
9397
  "Publishes locally generated intelligence analyses to the external issue tracker (e.g., GitHub)"
9231
9398
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
9232
9399
  try {
@@ -9242,13 +9409,13 @@ function createPublishAnalysesCommand() {
9242
9409
  }
9243
9410
 
9244
9411
  // src/commands/pulse/index.ts
9245
- import { Command as Command77 } from "commander";
9412
+ import { Command as Command78 } from "commander";
9246
9413
 
9247
9414
  // src/commands/pulse/run.ts
9248
9415
  init_dist3();
9249
9416
  import { readFileSync as readFileSync19, mkdirSync as mkdirSync13, writeFileSync as writeFileSync16 } from "fs";
9250
- import { dirname as dirname18, join as join39, resolve as resolve34 } from "path";
9251
- import { Command as Command76 } from "commander";
9417
+ import { dirname as dirname18, join as join39, resolve as resolve35 } from "path";
9418
+ import { Command as Command77 } from "commander";
9252
9419
  async function runPulseRunCommand(opts) {
9253
9420
  const startedAt = Date.now();
9254
9421
  let raw;
@@ -9313,7 +9480,7 @@ function emit2(status, nonInteractive) {
9313
9480
  return status;
9314
9481
  }
9315
9482
  function createRunCommand2() {
9316
- 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(
9317
9484
  "--lookback <window>",
9318
9485
  "Lookback window (e.g. 24h, 7d). Defaults to pulse.lookbackDefault."
9319
9486
  ).option(
@@ -9323,8 +9490,8 @@ function createRunCommand2() {
9323
9490
  async (options) => {
9324
9491
  const nonInteractive = options.nonInteractive === true || !process.stdout.isTTY;
9325
9492
  const status = await runPulseRunCommand({
9326
- configPath: resolve34(process.cwd(), options.config),
9327
- outputDir: resolve34(process.cwd(), options.outputDir),
9493
+ configPath: resolve35(process.cwd(), options.config),
9494
+ outputDir: resolve35(process.cwd(), options.outputDir),
9328
9495
  nonInteractive,
9329
9496
  lookback: options.lookback
9330
9497
  });
@@ -9337,13 +9504,13 @@ function createRunCommand2() {
9337
9504
 
9338
9505
  // src/commands/pulse/index.ts
9339
9506
  function createPulseCommand() {
9340
- const command = new Command77("pulse").description("Pulse (read-side observability) commands");
9507
+ const command = new Command78("pulse").description("Pulse (read-side observability) commands");
9341
9508
  command.addCommand(createRunCommand2());
9342
9509
  return command;
9343
9510
  }
9344
9511
 
9345
9512
  // src/commands/recommend.ts
9346
- import { Command as Command78 } from "commander";
9513
+ import { Command as Command79 } from "commander";
9347
9514
  import chalk12 from "chalk";
9348
9515
  async function resolveSnapshot(cwd, noCache) {
9349
9516
  if (!noCache) {
@@ -9407,7 +9574,7 @@ function printRecommendations(result) {
9407
9574
  console.log("");
9408
9575
  }
9409
9576
  function createRecommendCommand() {
9410
- const command = new Command78("recommend").description("Recommend skills based on codebase health analysis").option("--no-cache", "Force fresh health snapshot").option("--top <n>", "Max recommendations (default 5)", "5").action(async (opts, cmd) => {
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) => {
9411
9578
  const globalOpts = cmd.optsWithGlobals();
9412
9579
  const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
9413
9580
  try {
@@ -9442,19 +9609,197 @@ function createRecommendCommand() {
9442
9609
  return command;
9443
9610
  }
9444
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
+
9445
9790
  // src/commands/roadmap/index.ts
9446
- import { Command as Command80 } from "commander";
9791
+ import { Command as Command82 } from "commander";
9447
9792
 
9448
9793
  // src/commands/roadmap/migrate.ts
9449
9794
  init_dist3();
9450
- import { Command as Command79 } from "commander";
9795
+ import { Command as Command81 } from "commander";
9451
9796
  import * as fs32 from "fs";
9452
- import * as path50 from "path";
9797
+ import * as path51 from "path";
9453
9798
  import chalk13 from "chalk";
9454
9799
 
9455
9800
  // src/commands/roadmap/migrate-lock.ts
9456
9801
  import * as fs31 from "fs";
9457
- import * as path49 from "path";
9802
+ import * as path50 from "path";
9458
9803
  import * as os6 from "os";
9459
9804
  var LOCK_FILE_NAME = "migrate.lock";
9460
9805
  var STALE_LOCK_MS = 30 * 60 * 1e3;
@@ -9468,8 +9813,8 @@ function isPidAlive(pid) {
9468
9813
  }
9469
9814
  }
9470
9815
  function acquireMigrateLock(projectRoot2) {
9471
- const harnessDir = path49.join(projectRoot2, ".harness");
9472
- const lockPath = path49.join(harnessDir, LOCK_FILE_NAME);
9816
+ const harnessDir = path50.join(projectRoot2, ".harness");
9817
+ const lockPath = path50.join(harnessDir, LOCK_FILE_NAME);
9473
9818
  if (!fs31.existsSync(harnessDir)) fs31.mkdirSync(harnessDir, { recursive: true });
9474
9819
  if (fs31.existsSync(lockPath)) {
9475
9820
  const existingRaw = (() => {
@@ -9668,7 +10013,7 @@ async function runRoadmapMigrate(opts) {
9668
10013
  if (!clientR.ok) return Err(new CLIError(clientR.error.message));
9669
10014
  client = clientR.value;
9670
10015
  }
9671
- const roadmapPath = path50.join(cwd, "docs", "roadmap.md");
10016
+ const roadmapPath = path51.join(cwd, "docs", "roadmap.md");
9672
10017
  if (!fs32.existsSync(roadmapPath)) {
9673
10018
  return Err(new CLIError(`docs/roadmap.md not found in ${cwd}`));
9674
10019
  }
@@ -9717,7 +10062,7 @@ async function runRoadmapMigrate(opts) {
9717
10062
  }
9718
10063
  }
9719
10064
  function createRoadmapMigrateCommand() {
9720
- return new Command79("migrate").description("Migrate the project roadmap to a different storage mode").requiredOption("--to <target>", 'Migration target (only "file-less" supported today)').option("--dry-run", "Print the migration plan without making any changes", false).option(
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(
9721
10066
  "--format <fmt>",
9722
10067
  'Output format: "human" (default) or "json" (single JSON object for CI consumers)',
9723
10068
  "human"
@@ -9752,16 +10097,16 @@ function createRoadmapMigrateCommand() {
9752
10097
 
9753
10098
  // src/commands/roadmap/index.ts
9754
10099
  function createRoadmapCommand() {
9755
- const roadmap = new Command80("roadmap").description("Roadmap management");
10100
+ const roadmap = new Command82("roadmap").description("Roadmap management");
9756
10101
  roadmap.addCommand(createRoadmapMigrateCommand());
9757
10102
  return roadmap;
9758
10103
  }
9759
10104
 
9760
10105
  // src/commands/routing/index.ts
9761
- import { Command as Command84 } from "commander";
10106
+ import { Command as Command86 } from "commander";
9762
10107
 
9763
10108
  // src/commands/routing/config.ts
9764
- import { Command as Command81 } from "commander";
10109
+ import { Command as Command83 } from "commander";
9765
10110
 
9766
10111
  // src/commands/routing/http-client.ts
9767
10112
  function orchestratorBase() {
@@ -9771,9 +10116,9 @@ function authHeader() {
9771
10116
  const tok = process.env["HARNESS_API_TOKEN"];
9772
10117
  return tok ? { Authorization: `Bearer ${tok}` } : {};
9773
10118
  }
9774
- async function getJson(path72) {
10119
+ async function getJson(path73) {
9775
10120
  try {
9776
- const res = await fetch(`${orchestratorBase()}${path72}`, {
10121
+ const res = await fetch(`${orchestratorBase()}${path73}`, {
9777
10122
  headers: { ...authHeader() }
9778
10123
  });
9779
10124
  const text = await res.text();
@@ -9788,9 +10133,9 @@ async function getJson(path72) {
9788
10133
  };
9789
10134
  }
9790
10135
  }
9791
- async function postJson(path72, body) {
10136
+ async function postJson(path73, body) {
9792
10137
  try {
9793
- const res = await fetch(`${orchestratorBase()}${path72}`, {
10138
+ const res = await fetch(`${orchestratorBase()}${path73}`, {
9794
10139
  method: "POST",
9795
10140
  headers: { "Content-Type": "application/json", ...authHeader() },
9796
10141
  body: JSON.stringify(body)
@@ -9826,7 +10171,7 @@ function renderHuman(data) {
9826
10171
  }
9827
10172
  }
9828
10173
  function createConfigCommand() {
9829
- return new Command81("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
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) => {
9830
10175
  const r = await getJson("/api/v1/routing/config");
9831
10176
  if (!r.ok) {
9832
10177
  if (r.status === 0) {
@@ -9852,7 +10197,7 @@ function createConfigCommand() {
9852
10197
  }
9853
10198
 
9854
10199
  // src/commands/routing/trace.ts
9855
- import { Command as Command82 } from "commander";
10200
+ import { Command as Command84 } from "commander";
9856
10201
  function buildUseCase(opts) {
9857
10202
  if (opts.skill) {
9858
10203
  return opts.mode ? { kind: "skill", skillName: opts.skill, cognitiveMode: opts.mode } : { kind: "skill", skillName: opts.skill };
@@ -9873,7 +10218,7 @@ function renderHuman2(r) {
9873
10218
  }
9874
10219
  }
9875
10220
  function createTraceCommand() {
9876
- return new Command82("trace").description("Dry-run a routing decision without dispatching (Spec B F7)").option("--skill <name>", "Skill name to trace").option("--mode <m>", "Cognitive mode to trace (or attach to --skill per spec D12)").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
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) => {
9877
10222
  const useCase = buildUseCase(opts);
9878
10223
  if (!useCase) {
9879
10224
  logger.error("Either --skill <name> or --mode <m> is required");
@@ -9905,7 +10250,7 @@ function createTraceCommand() {
9905
10250
  }
9906
10251
 
9907
10252
  // src/commands/routing/decisions.ts
9908
- import { Command as Command83 } from "commander";
10253
+ import { Command as Command85 } from "commander";
9909
10254
  function summarizeUseCase(uc) {
9910
10255
  switch (uc.kind) {
9911
10256
  case "skill":
@@ -9953,7 +10298,7 @@ function buildQuery(opts) {
9953
10298
  return q ? `?${q}` : "";
9954
10299
  }
9955
10300
  function createDecisionsCommand() {
9956
- return new Command83("decisions").description("List recent routing decisions from the orchestrator ring buffer (Spec B F8)").option("--skill <name>", "Filter by useCase.skillName").option("--mode <m>", "Filter by useCase.cognitiveMode").option("--backend <name>", "Filter by chosen backendName").option("--last <N>", "Limit to the N most recent decisions").option("--json", "Emit JSON to stdout instead of human-readable text").action(
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(
9957
10302
  async (opts) => {
9958
10303
  const query = buildQuery(opts);
9959
10304
  const r = await getJson(`/api/v1/routing/decisions${query}`);
@@ -9983,7 +10328,7 @@ function createDecisionsCommand() {
9983
10328
 
9984
10329
  // src/commands/routing/index.ts
9985
10330
  function createRoutingCommand() {
9986
- const cmd = new Command84("routing").description(
10331
+ const cmd = new Command86("routing").description(
9987
10332
  "Inspect routing config, trace decisions, and read recent dispatches"
9988
10333
  );
9989
10334
  cmd.addCommand(createConfigCommand());
@@ -9994,8 +10339,8 @@ function createRoutingCommand() {
9994
10339
 
9995
10340
  // src/commands/scan-config.ts
9996
10341
  init_dist3();
9997
- import { Command as Command85 } from "commander";
9998
- 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";
9999
10344
  import { join as join42, relative as relative3 } from "path";
10000
10345
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
10001
10346
  function stripHighSeverityPatterns(content, injectionFindings) {
@@ -10022,7 +10367,7 @@ function applyFix(filePath, targetDir, content, injectionFindings) {
10022
10367
  if (!hasHighSeverity) return;
10023
10368
  const { cleaned, linesStripped } = stripHighSeverityPatterns(content, injectionFindings);
10024
10369
  if (linesStripped > 0) {
10025
- writeFileSync19(filePath, cleaned);
10370
+ writeFileSync20(filePath, cleaned);
10026
10371
  logger.info(
10027
10372
  `scan-config --fix: stripped ${linesStripped} high-severity line(s) from ${relative3(targetDir, filePath).replaceAll("\\", "/")}`
10028
10373
  );
@@ -10083,7 +10428,7 @@ function formatTextOutput(result) {
10083
10428
  }
10084
10429
  }
10085
10430
  function createScanConfigCommand() {
10086
- const command = new Command85("scan-config").description(
10431
+ const command = new Command87("scan-config").description(
10087
10432
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
10088
10433
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
10089
10434
  const globalOpts = cmd.optsWithGlobals();
@@ -10101,7 +10446,7 @@ function createScanConfigCommand() {
10101
10446
 
10102
10447
  // src/commands/search.ts
10103
10448
  init_dist();
10104
- import { Command as Command86 } from "commander";
10449
+ import { Command as Command88 } from "commander";
10105
10450
  function parseFileKinds(raw) {
10106
10451
  if (!raw) return void 0;
10107
10452
  const set = /* @__PURE__ */ new Set();
@@ -10122,7 +10467,7 @@ function fmtBytes(n) {
10122
10467
  return n.toFixed(0);
10123
10468
  }
10124
10469
  function createSearchCommand() {
10125
- 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(
10126
10471
  "<query>",
10127
10472
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
10128
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(
@@ -10182,9 +10527,9 @@ function createSearchCommand() {
10182
10527
  }
10183
10528
 
10184
10529
  // src/commands/security-craft.ts
10185
- import { Command as Command87 } from "commander";
10530
+ import { Command as Command89 } from "commander";
10186
10531
  function createSecurityCraftCommand() {
10187
- return new Command87("security-craft").description(
10532
+ return new Command89("security-craft").description(
10188
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."
10189
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) => {
10190
10535
  const globalOpts = cmd.optsWithGlobals();
@@ -10231,10 +10576,10 @@ function printResult5(result, mode, _formatter) {
10231
10576
  list.push(f);
10232
10577
  byFile.set(f.target.file, list);
10233
10578
  }
10234
- for (const [file, fs48] of byFile) {
10579
+ for (const [file, fs49] of byFile) {
10235
10580
  console.log(`
10236
10581
  ${file}`);
10237
- for (const f of fs48) {
10582
+ for (const f of fs49) {
10238
10583
  console.log(
10239
10584
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.signal}:${f.target.line}`
10240
10585
  );
@@ -10250,18 +10595,18 @@ ${file}`);
10250
10595
  }
10251
10596
 
10252
10597
  // src/commands/setup.ts
10253
- import { Command as Command88 } from "commander";
10598
+ import { Command as Command90 } from "commander";
10254
10599
  import * as fs35 from "fs";
10255
10600
  import * as os8 from "os";
10256
- import * as path53 from "path";
10601
+ import * as path54 from "path";
10257
10602
  import chalk15 from "chalk";
10258
10603
 
10259
10604
  // src/utils/first-run.ts
10260
10605
  import * as fs33 from "fs";
10261
10606
  import * as os7 from "os";
10262
- import * as path51 from "path";
10263
- var HARNESS_DIR = path51.join(os7.homedir(), ".harness");
10264
- var MARKER_FILE = path51.join(HARNESS_DIR, ".setup-complete");
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");
10265
10610
  function isFirstRun() {
10266
10611
  return !fs33.existsSync(MARKER_FILE);
10267
10612
  }
@@ -10281,7 +10626,7 @@ function printFirstRunWelcome() {
10281
10626
 
10282
10627
  // src/commands/telemetry-wizard.ts
10283
10628
  import * as fs34 from "fs";
10284
- import * as path52 from "path";
10629
+ import * as path53 from "path";
10285
10630
  import readline2 from "readline";
10286
10631
  import chalk14 from "chalk";
10287
10632
  function prompt2(question) {
@@ -10289,10 +10634,10 @@ function prompt2(question) {
10289
10634
  input: process.stdin,
10290
10635
  output: process.stdout
10291
10636
  });
10292
- return new Promise((resolve46) => {
10637
+ return new Promise((resolve47) => {
10293
10638
  rl.question(question, (answer) => {
10294
10639
  rl.close();
10295
- resolve46(answer.trim().toLowerCase());
10640
+ resolve47(answer.trim().toLowerCase());
10296
10641
  });
10297
10642
  });
10298
10643
  }
@@ -10301,10 +10646,10 @@ function promptRaw(question) {
10301
10646
  input: process.stdin,
10302
10647
  output: process.stdout
10303
10648
  });
10304
- return new Promise((resolve46) => {
10649
+ return new Promise((resolve47) => {
10305
10650
  rl.question(question, (answer) => {
10306
10651
  rl.close();
10307
- resolve46(answer.trim());
10652
+ resolve47(answer.trim());
10308
10653
  });
10309
10654
  });
10310
10655
  }
@@ -10312,7 +10657,7 @@ function isNo(answer) {
10312
10657
  return answer === "n" || answer === "no";
10313
10658
  }
10314
10659
  function isTelemetryConfigured(cwd) {
10315
- const configPath = path52.join(cwd, "harness.config.json");
10660
+ const configPath = path53.join(cwd, "harness.config.json");
10316
10661
  try {
10317
10662
  const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
10318
10663
  return raw.telemetry !== void 0 && raw.adoption !== void 0;
@@ -10321,7 +10666,7 @@ function isTelemetryConfigured(cwd) {
10321
10666
  }
10322
10667
  }
10323
10668
  function writeTelemetryConfig(cwd, result) {
10324
- const configPath = path52.join(cwd, "harness.config.json");
10669
+ const configPath = path53.join(cwd, "harness.config.json");
10325
10670
  try {
10326
10671
  const raw = JSON.parse(fs34.readFileSync(configPath, "utf-8"));
10327
10672
  raw.telemetry = { enabled: result.telemetryEnabled };
@@ -10334,9 +10679,9 @@ function writeTelemetryConfig(cwd, result) {
10334
10679
  }
10335
10680
  const hasIdentity = result.identity.project || result.identity.team || result.identity.alias;
10336
10681
  if (hasIdentity) {
10337
- const harnessDir = path52.join(cwd, ".harness");
10682
+ const harnessDir = path53.join(cwd, ".harness");
10338
10683
  fs34.mkdirSync(harnessDir, { recursive: true });
10339
- const telemetryFile = path52.join(harnessDir, "telemetry.json");
10684
+ const telemetryFile = path53.join(harnessDir, "telemetry.json");
10340
10685
  fs34.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
10341
10686
  }
10342
10687
  }
@@ -10383,7 +10728,7 @@ async function runTelemetryWizard() {
10383
10728
  return { telemetryEnabled, adoptionEnabled, identity };
10384
10729
  }
10385
10730
  async function ensureTelemetryConfigured(cwd) {
10386
- const configPath = path52.join(cwd, "harness.config.json");
10731
+ const configPath = path53.join(cwd, "harness.config.json");
10387
10732
  if (!fs34.existsSync(configPath)) {
10388
10733
  return { status: "warn", message: "Not a harness project \u2014 skipped telemetry configuration" };
10389
10734
  }
@@ -10430,7 +10775,7 @@ function runSlashCommandGeneration() {
10430
10775
  }
10431
10776
  }
10432
10777
  function detectClient(dirName) {
10433
- return fs35.existsSync(path53.join(os8.homedir(), dirName));
10778
+ return fs35.existsSync(path54.join(os8.homedir(), dirName));
10434
10779
  }
10435
10780
  async function runMcpSetup(cwd) {
10436
10781
  const results = [];
@@ -10446,7 +10791,7 @@ async function runMcpSetup(cwd) {
10446
10791
  { name: "Cursor", dir: ".cursor", client: "cursor", configTarget: ".cursor/mcp.json" },
10447
10792
  {
10448
10793
  name: "OpenCode",
10449
- dir: path53.join(".config", "opencode"),
10794
+ dir: path54.join(".config", "opencode"),
10450
10795
  client: "opencode",
10451
10796
  configTarget: "opencode.json"
10452
10797
  }
@@ -10478,7 +10823,7 @@ function formatStep(result) {
10478
10823
  }
10479
10824
  function configureTier0Integrations(cwd) {
10480
10825
  try {
10481
- const mcpPath = path53.join(cwd, ".mcp.json");
10826
+ const mcpPath = path54.join(cwd, ".mcp.json");
10482
10827
  const config = readMcpConfig(mcpPath);
10483
10828
  const tier0 = INTEGRATION_REGISTRY.filter((i) => i.tier === 0);
10484
10829
  const added = [];
@@ -10487,9 +10832,9 @@ function configureTier0Integrations(cwd) {
10487
10832
  writeMcpEntry(mcpPath, integration.name, integration.mcpConfig);
10488
10833
  added.push(integration.displayName);
10489
10834
  }
10490
- const geminiDir = path53.join(cwd, ".gemini");
10835
+ const geminiDir = path54.join(cwd, ".gemini");
10491
10836
  if (fs35.existsSync(geminiDir)) {
10492
- const geminiPath = path53.join(geminiDir, "settings.json");
10837
+ const geminiPath = path54.join(geminiDir, "settings.json");
10493
10838
  const geminiConfig = readMcpConfig(geminiPath);
10494
10839
  for (const integration of tier0) {
10495
10840
  if (!geminiConfig.mcpServers[integration.name]) {
@@ -10497,8 +10842,8 @@ function configureTier0Integrations(cwd) {
10497
10842
  }
10498
10843
  }
10499
10844
  }
10500
- const opencodePath = path53.join(cwd, "opencode.json");
10501
- 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");
10502
10847
  if (fs35.existsSync(opencodePath) || fs35.existsSync(opencodeGlobalDir)) {
10503
10848
  for (const integration of tier0) {
10504
10849
  writeOpencodeMcpEntry(opencodePath, integration.name, integration.mcpConfig);
@@ -10517,12 +10862,12 @@ function configureTier0Integrations(cwd) {
10517
10862
  }
10518
10863
  }
10519
10864
  function ensureHooks(cwd) {
10520
- const configPath = path53.join(cwd, "harness.config.json");
10865
+ const configPath = path54.join(cwd, "harness.config.json");
10521
10866
  if (!fs35.existsSync(configPath)) {
10522
10867
  return { status: "warn", message: "Not a harness project \u2014 skipped hook installation" };
10523
10868
  }
10524
10869
  let profile = "standard";
10525
- const profilePath = path53.join(cwd, ".harness", "hooks", "profile.json");
10870
+ const profilePath = path54.join(cwd, ".harness", "hooks", "profile.json");
10526
10871
  try {
10527
10872
  const data = JSON.parse(fs35.readFileSync(profilePath, "utf-8"));
10528
10873
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
@@ -10595,7 +10940,7 @@ async function runSetup(cwd) {
10595
10940
  return { steps, success };
10596
10941
  }
10597
10942
  function createSetupCommand() {
10598
- 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 () => {
10599
10944
  const cwd = process.cwd();
10600
10945
  console.log("");
10601
10946
  console.log(` ${chalk15.bold("harness setup")}`);
@@ -10618,14 +10963,14 @@ function createSetupCommand() {
10618
10963
 
10619
10964
  // src/commands/share.ts
10620
10965
  init_dist3();
10621
- import { Command as Command89 } from "commander";
10966
+ import { Command as Command91 } from "commander";
10622
10967
  import * as fs36 from "fs";
10623
- import * as path54 from "path";
10968
+ import * as path55 from "path";
10624
10969
  import { parse as parseYaml3 } from "yaml";
10625
10970
  var MANIFEST_FILENAME = "constraints.yaml";
10626
10971
  async function runShareAction(projectPath, options) {
10627
- const rootDir = path54.resolve(projectPath);
10628
- const manifestPath = path54.join(rootDir, MANIFEST_FILENAME);
10972
+ const rootDir = path55.resolve(projectPath);
10973
+ const manifestPath = path55.join(rootDir, MANIFEST_FILENAME);
10629
10974
  if (!fs36.existsSync(manifestPath)) {
10630
10975
  logger.error(
10631
10976
  `No ${MANIFEST_FILENAME} found at ${manifestPath}.
@@ -10649,7 +10994,7 @@ Create a constraints.yaml in your project root to define what to share.`
10649
10994
  process.exit(1);
10650
10995
  }
10651
10996
  const manifest = manifestResult.value;
10652
- const configResult = resolveConfig(path54.join(rootDir, "harness.config.json"));
10997
+ const configResult = resolveConfig(path55.join(rootDir, "harness.config.json"));
10653
10998
  if (!configResult.ok) {
10654
10999
  logger.error(configResult.error.message);
10655
11000
  process.exit(1);
@@ -10667,8 +11012,8 @@ Create a constraints.yaml in your project root to define what to share.`
10667
11012
  );
10668
11013
  process.exit(1);
10669
11014
  }
10670
- const outputDir = path54.resolve(options.output);
10671
- 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`);
10672
11017
  const writeResult = await writeConfig(outputPath, bundle);
10673
11018
  if (!writeResult.ok) {
10674
11019
  logger.error(`Failed to write bundle: ${writeResult.error.message}`);
@@ -10677,25 +11022,25 @@ Create a constraints.yaml in your project root to define what to share.`
10677
11022
  logger.success(`Bundle written to ${outputPath}`);
10678
11023
  }
10679
11024
  function createShareCommand() {
10680
- return new Command89("share").description("Extract and publish a constraints bundle from constraints.yaml").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory for the bundle", ".").action(async (projectPath, options) => {
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) => {
10681
11026
  await runShareAction(projectPath, options);
10682
11027
  });
10683
11028
  }
10684
11029
 
10685
11030
  // src/commands/skill/index.ts
10686
- import { Command as Command97 } from "commander";
11031
+ import { Command as Command99 } from "commander";
10687
11032
 
10688
11033
  // src/commands/skill/list.ts
10689
- import { Command as Command90 } from "commander";
11034
+ import { Command as Command92 } from "commander";
10690
11035
  import * as fs37 from "fs";
10691
- import * as path55 from "path";
11036
+ import * as path56 from "path";
10692
11037
  import { parse } from "yaml";
10693
11038
  function scanDirectory(dirPath, source) {
10694
11039
  if (!fs37.existsSync(dirPath)) return [];
10695
11040
  const entries = fs37.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
10696
11041
  const skills = [];
10697
11042
  for (const name of entries) {
10698
- const yamlPath = path55.join(dirPath, name, "skill.yaml");
11043
+ const yamlPath = path56.join(dirPath, name, "skill.yaml");
10699
11044
  if (!fs37.existsSync(yamlPath)) continue;
10700
11045
  try {
10701
11046
  const raw = fs37.readFileSync(yamlPath, "utf-8");
@@ -10716,10 +11061,10 @@ function scanDirectory(dirPath, source) {
10716
11061
  }
10717
11062
  function collectCommunitySkills(seen, allSkills) {
10718
11063
  const globalDir = resolveGlobalSkillsDir();
10719
- const skillsDir = path55.dirname(globalDir);
10720
- const communityBase = path55.join(skillsDir, "community");
10721
- const communityPlatformDir = path55.join(communityBase, "claude-code");
10722
- const lockfilePath = path55.join(communityBase, "skills-lock.json");
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");
10723
11068
  const lockfile = readLockfile2(lockfilePath);
10724
11069
  const communitySkills = scanDirectory(communityPlatformDir, "community");
10725
11070
  for (const skill of communitySkills) {
@@ -10789,7 +11134,7 @@ function printSkillsVerbose(skills) {
10789
11134
  for (const s of skills) printSkillEntry(s);
10790
11135
  }
10791
11136
  function createListCommand3() {
10792
- return new Command90("list").description("List available skills").option("--installed", "Show only community-installed skills").option("--local", "Show only project-local skills").option("--all", "Show all skills (default)").action(async (opts, cmd) => {
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) => {
10793
11138
  const globalOpts = cmd.optsWithGlobals();
10794
11139
  const skills = collectSkills({ filter: resolveFilter(opts) });
10795
11140
  if (globalOpts.json) {
@@ -10804,13 +11149,13 @@ function createListCommand3() {
10804
11149
  }
10805
11150
 
10806
11151
  // src/commands/skill/run.ts
10807
- import { Command as Command91 } from "commander";
11152
+ import { Command as Command93 } from "commander";
10808
11153
  import * as fs38 from "fs";
10809
- import * as path56 from "path";
11154
+ import * as path57 from "path";
10810
11155
  import { parse as parse2 } from "yaml";
10811
11156
 
10812
11157
  // src/skill/complexity.ts
10813
- import { execFileSync as execFileSync5 } from "child_process";
11158
+ import { execFileSync as execFileSync6 } from "child_process";
10814
11159
  function evaluateSignals(signals) {
10815
11160
  if (signals.fileCount >= 3) return "thorough";
10816
11161
  if (signals.newDir) return "thorough";
@@ -10822,17 +11167,17 @@ function evaluateSignals(signals) {
10822
11167
  }
10823
11168
  function detectComplexity(projectPath) {
10824
11169
  try {
10825
- const base = execFileSync5("git", ["merge-base", "HEAD", "main"], {
11170
+ const base = execFileSync6("git", ["merge-base", "HEAD", "main"], {
10826
11171
  cwd: projectPath,
10827
11172
  encoding: "utf-8",
10828
11173
  stdio: ["pipe", "pipe", "pipe"]
10829
11174
  }).trim();
10830
- const diffFiles = execFileSync5("git", ["diff", "--name-only", base], {
11175
+ const diffFiles = execFileSync6("git", ["diff", "--name-only", base], {
10831
11176
  cwd: projectPath,
10832
11177
  encoding: "utf-8",
10833
11178
  stdio: ["pipe", "pipe", "pipe"]
10834
11179
  }).trim().split("\n").filter(Boolean);
10835
- const diffStat = execFileSync5("git", ["diff", "--stat", base], {
11180
+ const diffStat = execFileSync6("git", ["diff", "--stat", base], {
10836
11181
  cwd: projectPath,
10837
11182
  encoding: "utf-8",
10838
11183
  stdio: ["pipe", "pipe", "pipe"]
@@ -10902,7 +11247,7 @@ ${options.principles}`);
10902
11247
 
10903
11248
  // src/commands/skill/run.ts
10904
11249
  function loadSkillMetadata(skillDir) {
10905
- const yamlPath = path56.join(skillDir, "skill.yaml");
11250
+ const yamlPath = path57.join(skillDir, "skill.yaml");
10906
11251
  if (!fs38.existsSync(yamlPath)) return null;
10907
11252
  try {
10908
11253
  const result = SkillMetadataSchema.safeParse(parse2(fs38.readFileSync(yamlPath, "utf-8")));
@@ -10917,18 +11262,18 @@ function resolveComplexity(metadata, requested, projectPath) {
10917
11262
  return requested;
10918
11263
  }
10919
11264
  function loadPrinciples(projectPath) {
10920
- const principlesPath = path56.join(projectPath, "docs", "principles.md");
11265
+ const principlesPath = path57.join(projectPath, "docs", "principles.md");
10921
11266
  return fs38.existsSync(principlesPath) ? fs38.readFileSync(principlesPath, "utf-8") : void 0;
10922
11267
  }
10923
11268
  function readMostRecentFileInDir(dirPath) {
10924
- const files = fs38.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs38.statSync(path56.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
10925
- if (files.length > 0) return fs38.readFileSync(path56.join(dirPath, files[0].name), "utf-8");
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");
10926
11271
  return void 0;
10927
11272
  }
10928
11273
  function loadPriorState(metadata, projectPath) {
10929
11274
  if (!metadata?.state.persistent || metadata.state.files.length === 0) return void 0;
10930
11275
  for (const stateFilePath of metadata.state.files) {
10931
- const fullPath = path56.join(projectPath, stateFilePath);
11276
+ const fullPath = path57.join(projectPath, stateFilePath);
10932
11277
  if (!fs38.existsSync(fullPath)) continue;
10933
11278
  const stat = fs38.statSync(fullPath);
10934
11279
  if (stat.isDirectory()) return readMostRecentFileInDir(fullPath);
@@ -10952,7 +11297,7 @@ function resolvePhaseState(metadata, projectPath, phase) {
10952
11297
  }
10953
11298
  function appendProjectState(content, metadata, projectPath, hasPathOpt) {
10954
11299
  if (!metadata?.state.persistent || !hasPathOpt) return content;
10955
- const stateFile = path56.join(projectPath, ".harness", "state.json");
11300
+ const stateFile = path57.join(projectPath, ".harness", "state.json");
10956
11301
  if (!fs38.existsSync(stateFile)) return content;
10957
11302
  const stateContent = fs38.readFileSync(stateFile, "utf-8");
10958
11303
  return content + `
@@ -10966,14 +11311,14 @@ ${stateContent}
10966
11311
  }
10967
11312
  async function runSkill(name, opts) {
10968
11313
  const skillsDir = resolveSkillsDir();
10969
- const skillDir = path56.join(skillsDir, name);
11314
+ const skillDir = path57.join(skillsDir, name);
10970
11315
  if (!fs38.existsSync(skillDir)) {
10971
11316
  logger.error(`Skill not found: ${name}`);
10972
11317
  process.exit(ExitCode.ERROR);
10973
11318
  return;
10974
11319
  }
10975
11320
  const metadata = loadSkillMetadata(skillDir);
10976
- const projectPath = opts.path ? path56.resolve(opts.path) : process.cwd();
11321
+ const projectPath = opts.path ? path57.resolve(opts.path) : process.cwd();
10977
11322
  const complexity = resolveComplexity(
10978
11323
  metadata,
10979
11324
  opts.complexity ?? "standard",
@@ -11000,7 +11345,7 @@ async function runSkill(name, opts) {
11000
11345
  ...stateWarning !== void 0 && { stateWarning },
11001
11346
  ...opts.party !== void 0 && { party: opts.party }
11002
11347
  });
11003
- const skillMdPath = path56.join(skillDir, "SKILL.md");
11348
+ const skillMdPath = path57.join(skillDir, "SKILL.md");
11004
11349
  if (!fs38.existsSync(skillMdPath)) {
11005
11350
  logger.error(`SKILL.md not found for skill: ${name}`);
11006
11351
  process.exit(ExitCode.ERROR);
@@ -11018,16 +11363,16 @@ async function runSkill(name, opts) {
11018
11363
  process.exit(ExitCode.SUCCESS);
11019
11364
  }
11020
11365
  function createRunCommand3() {
11021
- return new Command91("run").description("Run a skill (outputs SKILL.md content with context preamble)").argument("<name>", "Skill name (e.g., harness-tdd)").option("--path <path>", "Project root path for context injection").option("--complexity <level>", "Rigor level: fast, standard, thorough", "standard").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").option(
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(
11022
11367
  "--backend <name>",
11023
11368
  "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
11024
11369
  ).action(async (name, opts) => runSkill(name, opts));
11025
11370
  }
11026
11371
 
11027
11372
  // src/commands/skill/validate.ts
11028
- import { Command as Command92 } from "commander";
11373
+ import { Command as Command94 } from "commander";
11029
11374
  import * as fs39 from "fs";
11030
- import * as path57 from "path";
11375
+ import * as path58 from "path";
11031
11376
  import { parse as parse3 } from "yaml";
11032
11377
  var BEHAVIORAL_REQUIRED_SECTIONS = [
11033
11378
  "## When to Use",
@@ -11068,8 +11413,8 @@ function validateSkillMd(name, skillMdPath, skillType, errors) {
11068
11413
  }
11069
11414
  }
11070
11415
  function validateSkillEntry(name, skillsDir, errors) {
11071
- const skillDir = path57.join(skillsDir, name);
11072
- const yamlPath = path57.join(skillDir, "skill.yaml");
11416
+ const skillDir = path58.join(skillsDir, name);
11417
+ const yamlPath = path58.join(skillDir, "skill.yaml");
11073
11418
  if (!fs39.existsSync(yamlPath)) {
11074
11419
  errors.push(`${name}: missing skill.yaml`);
11075
11420
  return false;
@@ -11081,7 +11426,7 @@ function validateSkillEntry(name, skillsDir, errors) {
11081
11426
  errors.push(`${name}/skill.yaml: ${result.error.message}`);
11082
11427
  return false;
11083
11428
  }
11084
- validateSkillMd(name, path57.join(skillDir, "SKILL.md"), result.data.type, errors);
11429
+ validateSkillMd(name, path58.join(skillDir, "SKILL.md"), result.data.type, errors);
11085
11430
  return true;
11086
11431
  } catch (e) {
11087
11432
  errors.push(`${name}: parse error \u2014 ${e instanceof Error ? e.message : String(e)}`);
@@ -11089,7 +11434,7 @@ function validateSkillEntry(name, skillsDir, errors) {
11089
11434
  }
11090
11435
  }
11091
11436
  function createValidateCommand2() {
11092
- 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) => {
11093
11438
  const globalOpts = cmd.optsWithGlobals();
11094
11439
  const skillsDir = resolveSkillsDir();
11095
11440
  if (!fs39.existsSync(skillsDir)) {
@@ -11119,18 +11464,18 @@ function createValidateCommand2() {
11119
11464
  }
11120
11465
 
11121
11466
  // src/commands/skill/info.ts
11122
- import { Command as Command93 } from "commander";
11467
+ import { Command as Command95 } from "commander";
11123
11468
  import * as fs40 from "fs";
11124
- import * as path58 from "path";
11469
+ import * as path59 from "path";
11125
11470
  import { parse as parse4 } from "yaml";
11126
11471
  function loadSkillMetadata2(name) {
11127
11472
  const skillsDir = resolveSkillsDir();
11128
- const skillDir = path58.join(skillsDir, name);
11473
+ const skillDir = path59.join(skillsDir, name);
11129
11474
  if (!fs40.existsSync(skillDir)) {
11130
11475
  logger.error(`Skill not found: ${name}`);
11131
11476
  return { ok: false, exitCode: ExitCode.ERROR };
11132
11477
  }
11133
- const yamlPath = path58.join(skillDir, "skill.yaml");
11478
+ const yamlPath = path59.join(skillDir, "skill.yaml");
11134
11479
  if (!fs40.existsSync(yamlPath)) {
11135
11480
  logger.error(`skill.yaml not found for skill: ${name}`);
11136
11481
  return { ok: false, exitCode: ExitCode.ERROR };
@@ -11165,7 +11510,7 @@ function printSkillInfo(skill) {
11165
11510
  console.log(`Persistent: ${skill.state.persistent}`);
11166
11511
  }
11167
11512
  function createInfoCommand() {
11168
- 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) => {
11169
11514
  const globalOpts = cmd.optsWithGlobals();
11170
11515
  const loaded = loadSkillMetadata2(name);
11171
11516
  if (!loaded.ok) {
@@ -11182,7 +11527,7 @@ function createInfoCommand() {
11182
11527
  }
11183
11528
 
11184
11529
  // src/commands/skill/search.ts
11185
- import { Command as Command94 } from "commander";
11530
+ import { Command as Command96 } from "commander";
11186
11531
  async function runSearch(query, opts) {
11187
11532
  const results = await searchNpmRegistry(query, opts.registry);
11188
11533
  return results.filter((r) => {
@@ -11227,14 +11572,14 @@ async function runSearchAction(query, opts, globalOpts) {
11227
11572
  }
11228
11573
  }
11229
11574
  function createSearchCommand2() {
11230
- return new Command94("search").description("Search for community skills on the @harness-skills registry").argument("<query>", "Search query").option("--platform <platform>", "Filter by platform (e.g., claude-code)").option("--trigger <trigger>", "Filter by trigger type (e.g., manual, automatic)").option("--registry <url>", "Use a custom npm registry URL").action(async (query, opts, cmd) => {
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) => {
11231
11576
  await runSearchAction(query, opts, cmd.optsWithGlobals());
11232
11577
  });
11233
11578
  }
11234
11579
 
11235
11580
  // src/commands/skill/create.ts
11236
- import { Command as Command95 } from "commander";
11237
- import * as path59 from "path";
11581
+ import { Command as Command97 } from "commander";
11582
+ import * as path60 from "path";
11238
11583
  import * as fs41 from "fs";
11239
11584
  import YAML from "yaml";
11240
11585
  var KEBAB_CASE_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
@@ -11319,21 +11664,21 @@ function runCreate(name, opts) {
11319
11664
  if (!KEBAB_CASE_RE.test(name)) {
11320
11665
  throw new Error(`Invalid skill name "${name}". Must be kebab-case (e.g., my-skill).`);
11321
11666
  }
11322
- const baseDir = opts.outputDir ?? path59.join(process.cwd(), "agents", "skills", "claude-code");
11323
- 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);
11324
11669
  if (fs41.existsSync(skillDir)) {
11325
11670
  throw new Error(`Skill directory already exists: ${skillDir}`);
11326
11671
  }
11327
11672
  fs41.mkdirSync(skillDir, { recursive: true });
11328
11673
  const description = opts.description || `A community skill: ${name}`;
11329
11674
  const skillYaml = buildSkillYaml(name, opts);
11330
- const skillYamlPath = path59.join(skillDir, "skill.yaml");
11675
+ const skillYamlPath = path60.join(skillDir, "skill.yaml");
11331
11676
  fs41.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
11332
11677
  const skillMd = buildSkillMd(name, description);
11333
- const skillMdPath = path59.join(skillDir, "SKILL.md");
11678
+ const skillMdPath = path60.join(skillDir, "SKILL.md");
11334
11679
  fs41.writeFileSync(skillMdPath, skillMd);
11335
11680
  const readme = buildReadme(name, description);
11336
- const readmePath = path59.join(skillDir, "README.md");
11681
+ const readmePath = path60.join(skillDir, "README.md");
11337
11682
  fs41.writeFileSync(readmePath, readme);
11338
11683
  return {
11339
11684
  name,
@@ -11348,12 +11693,12 @@ function printCreateResult(name, result) {
11348
11693
  }
11349
11694
  logger.info(`
11350
11695
  Next steps:`);
11351
- 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`);
11352
11697
  logger.info(` 2. Run: harness skill validate ${name}`);
11353
11698
  logger.info(` 3. Run: harness skills publish`);
11354
11699
  }
11355
11700
  function createCreateCommand() {
11356
- return new Command95("create").description("Scaffold a new community skill").argument("<name>", "Skill name (kebab-case)").option("--description <desc>", "Skill description").option("--type <type>", "Skill type: rigid or flexible", "flexible").option("--platforms <platforms>", "Comma-separated platforms (default: claude-code)").option("--triggers <triggers>", "Comma-separated triggers (default: manual)").option("--output-dir <dir>", "Output directory (default: agents/skills/claude-code/)").action(async (name, opts, cmd) => {
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) => {
11357
11702
  const globalOpts = cmd.optsWithGlobals();
11358
11703
  try {
11359
11704
  const result = runCreate(name, {
@@ -11376,19 +11721,19 @@ function createCreateCommand() {
11376
11721
  }
11377
11722
 
11378
11723
  // src/commands/skill/publish.ts
11379
- import { Command as Command96 } from "commander";
11724
+ import { Command as Command98 } from "commander";
11380
11725
  import * as fs43 from "fs";
11381
- import * as path61 from "path";
11382
- import { execFileSync as execFileSync6 } from "child_process";
11726
+ import * as path62 from "path";
11727
+ import { execFileSync as execFileSync7 } from "child_process";
11383
11728
 
11384
11729
  // src/registry/validator.ts
11385
11730
  import * as fs42 from "fs";
11386
- import * as path60 from "path";
11731
+ import * as path61 from "path";
11387
11732
  import { parse as parse5 } from "yaml";
11388
11733
  import semver4 from "semver";
11389
11734
  async function validateForPublish(skillDir, registryUrl) {
11390
11735
  const errors = [];
11391
- const skillYamlPath = path60.join(skillDir, "skill.yaml");
11736
+ const skillYamlPath = path61.join(skillDir, "skill.yaml");
11392
11737
  if (!fs42.existsSync(skillYamlPath)) {
11393
11738
  errors.push("skill.yaml not found. Create one with: harness skill create <name>");
11394
11739
  return { valid: false, errors };
@@ -11417,7 +11762,7 @@ async function validateForPublish(skillDir, registryUrl) {
11417
11762
  if (!skillMeta.triggers || skillMeta.triggers.length === 0) {
11418
11763
  errors.push("At least one trigger is required. Add triggers to skill.yaml.");
11419
11764
  }
11420
- const skillMdPath = path60.join(skillDir, "SKILL.md");
11765
+ const skillMdPath = path61.join(skillDir, "SKILL.md");
11421
11766
  if (!fs42.existsSync(skillMdPath)) {
11422
11767
  errors.push("SKILL.md not found. Create it with content describing your skill.");
11423
11768
  } else {
@@ -11501,11 +11846,11 @@ ${errorList}`);
11501
11846
  }
11502
11847
  const meta = validation.skillMeta;
11503
11848
  const pkg = derivePackageJson(meta);
11504
- const pkgPath = path61.join(skillDir, "package.json");
11849
+ const pkgPath = path62.join(skillDir, "package.json");
11505
11850
  fs43.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
11506
- const readmePath = path61.join(skillDir, "README.md");
11851
+ const readmePath = path62.join(skillDir, "README.md");
11507
11852
  if (!fs43.existsSync(readmePath)) {
11508
- const skillMdContent = fs43.readFileSync(path61.join(skillDir, "SKILL.md"), "utf-8");
11853
+ const skillMdContent = fs43.readFileSync(path62.join(skillDir, "SKILL.md"), "utf-8");
11509
11854
  const readme = `# ${pkg.name}
11510
11855
 
11511
11856
  ${meta.description}
@@ -11533,7 +11878,7 @@ ${skillMdContent}`;
11533
11878
  if (opts.registry) {
11534
11879
  publishArgs.push("--registry", opts.registry);
11535
11880
  }
11536
- execFileSync6("npm", publishArgs, {
11881
+ execFileSync7("npm", publishArgs, {
11537
11882
  cwd: skillDir,
11538
11883
  stdio: "pipe",
11539
11884
  timeout: 6e4
@@ -11545,7 +11890,7 @@ ${skillMdContent}`;
11545
11890
  };
11546
11891
  }
11547
11892
  function createPublishCommand() {
11548
- return new Command96("publish").description("Validate and publish a skill to @harness-skills on npm").option("--dry-run", "Run validation and generate package.json without publishing").option("--dir <dir>", "Skill directory (default: current directory)").option("--registry <url>", "Use a custom npm registry URL").action(async (opts, cmd) => {
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) => {
11549
11894
  const globalOpts = cmd.optsWithGlobals();
11550
11895
  const skillDir = opts.dir || process.cwd();
11551
11896
  try {
@@ -11570,7 +11915,7 @@ function createPublishCommand() {
11570
11915
 
11571
11916
  // src/commands/skill/index.ts
11572
11917
  function createSkillCommand() {
11573
- const command = new Command97("skill").description("Skill management commands");
11918
+ const command = new Command99("skill").description("Skill management commands");
11574
11919
  command.addCommand(createListCommand3());
11575
11920
  command.addCommand(createRunCommand3());
11576
11921
  command.addCommand(createValidateCommand2());
@@ -11583,7 +11928,7 @@ function createSkillCommand() {
11583
11928
 
11584
11929
  // src/commands/snapshot.ts
11585
11930
  init_dist3();
11586
- import { Command as Command98 } from "commander";
11931
+ import { Command as Command100 } from "commander";
11587
11932
  import { execSync as execSync5 } from "child_process";
11588
11933
  import chalk16 from "chalk";
11589
11934
  function getCommitHash3(cwd) {
@@ -11765,7 +12110,7 @@ function registerListCommand(parent) {
11765
12110
  });
11766
12111
  }
11767
12112
  function createSnapshotCommand() {
11768
- const command = new Command98("snapshot").description("Architecture timeline snapshot commands");
12113
+ const command = new Command100("snapshot").description("Architecture timeline snapshot commands");
11769
12114
  registerCaptureCommand(command);
11770
12115
  registerTrendsCommand(command);
11771
12116
  registerListCommand(command);
@@ -11773,9 +12118,9 @@ function createSnapshotCommand() {
11773
12118
  }
11774
12119
 
11775
12120
  // src/commands/spec-craft.ts
11776
- import { Command as Command99 } from "commander";
12121
+ import { Command as Command101 } from "commander";
11777
12122
  function createSpecCraftCommand() {
11778
- return new Command99("spec-craft").description(
12123
+ return new Command101("spec-craft").description(
11779
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."
11780
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) => {
11781
12126
  const globalOpts = cmd.optsWithGlobals();
@@ -11823,10 +12168,10 @@ function printResult6(result, mode, _formatter) {
11823
12168
  list.push(f);
11824
12169
  byFile.set(f.target.file, list);
11825
12170
  }
11826
- for (const [file, fs48] of byFile) {
12171
+ for (const [file, fs49] of byFile) {
11827
12172
  console.log(`
11828
12173
  ${file}`);
11829
- for (const f of fs48) {
12174
+ for (const f of fs49) {
11830
12175
  console.log(
11831
12176
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ## ${f.target.section}:${f.target.line}`
11832
12177
  );
@@ -11842,12 +12187,12 @@ ${file}`);
11842
12187
  }
11843
12188
 
11844
12189
  // src/commands/state/index.ts
11845
- import { Command as Command104 } from "commander";
12190
+ import { Command as Command106 } from "commander";
11846
12191
 
11847
12192
  // src/commands/state/show.ts
11848
12193
  init_dist3();
11849
- import { Command as Command100 } from "commander";
11850
- import * as path62 from "path";
12194
+ import { Command as Command102 } from "commander";
12195
+ import * as path63 from "path";
11851
12196
  function printStateText(state, stream) {
11852
12197
  if (stream) console.log(`Stream: ${stream}`);
11853
12198
  console.log(`Schema Version: ${state.schemaVersion}`);
@@ -11871,9 +12216,9 @@ function printStateProgress(progress) {
11871
12216
  }
11872
12217
  }
11873
12218
  function createShowCommand() {
11874
- return new Command100("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
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) => {
11875
12220
  const globalOpts = cmd.optsWithGlobals();
11876
- const result = await loadState(path62.resolve(opts.path), opts.stream);
12221
+ const result = await loadState(path63.resolve(opts.path), opts.stream);
11877
12222
  if (!result.ok) {
11878
12223
  logger.error(result.error.message);
11879
12224
  process.exit(ExitCode.ERROR);
@@ -11889,9 +12234,9 @@ function createShowCommand() {
11889
12234
 
11890
12235
  // src/commands/state/reset.ts
11891
12236
  init_dist3();
11892
- import { Command as Command101 } from "commander";
12237
+ import { Command as Command103 } from "commander";
11893
12238
  import * as fs44 from "fs";
11894
- import * as path63 from "path";
12239
+ import * as path64 from "path";
11895
12240
  import * as readline3 from "readline";
11896
12241
  async function resolveStatePath(projectPath, stream) {
11897
12242
  if (stream) {
@@ -11900,20 +12245,20 @@ async function resolveStatePath(projectPath, stream) {
11900
12245
  logger.error(streamResult.error.message);
11901
12246
  process.exit(ExitCode.ERROR);
11902
12247
  }
11903
- return path63.join(streamResult.value, "state.json");
12248
+ return path64.join(streamResult.value, "state.json");
11904
12249
  }
11905
- return path63.join(projectPath, ".harness", "state.json");
12250
+ return path64.join(projectPath, ".harness", "state.json");
11906
12251
  }
11907
12252
  async function confirmReset() {
11908
12253
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
11909
- const answer = await new Promise((resolve46) => {
11910
- 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);
11911
12256
  });
11912
12257
  rl.close();
11913
12258
  return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
11914
12259
  }
11915
12260
  async function runReset(opts) {
11916
- const projectPath = path63.resolve(opts.path);
12261
+ const projectPath = path64.resolve(opts.path);
11917
12262
  const statePath = await resolveStatePath(projectPath, opts.stream);
11918
12263
  if (!fs44.existsSync(statePath)) {
11919
12264
  logger.info("No state file found. Nothing to reset.");
@@ -11933,16 +12278,16 @@ async function runReset(opts) {
11933
12278
  process.exit(ExitCode.SUCCESS);
11934
12279
  }
11935
12280
  function createResetCommand() {
11936
- return new Command101("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
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));
11937
12282
  }
11938
12283
 
11939
12284
  // src/commands/state/learn.ts
11940
12285
  init_dist3();
11941
- import { Command as Command102 } from "commander";
11942
- import * as path64 from "path";
12286
+ import { Command as Command104 } from "commander";
12287
+ import * as path65 from "path";
11943
12288
  function createLearnCommand() {
11944
- return new Command102("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (message, opts, _cmd) => {
11945
- const projectPath = path64.resolve(opts.path);
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);
11946
12291
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
11947
12292
  if (!result.ok) {
11948
12293
  logger.error(result.error.message);
@@ -11956,10 +12301,10 @@ function createLearnCommand() {
11956
12301
 
11957
12302
  // src/commands/state/streams.ts
11958
12303
  init_dist3();
11959
- import { Command as Command103 } from "commander";
11960
- import * as path65 from "path";
12304
+ import { Command as Command105 } from "commander";
12305
+ import * as path66 from "path";
11961
12306
  async function runListStreams(opts, globalOpts) {
11962
- const projectPath = path65.resolve(opts.path);
12307
+ const projectPath = path66.resolve(opts.path);
11963
12308
  const indexResult = await loadStreamIndex(projectPath);
11964
12309
  const result = await listStreams(projectPath);
11965
12310
  if (!result.ok) {
@@ -11980,7 +12325,7 @@ async function runListStreams(opts, globalOpts) {
11980
12325
  process.exit(ExitCode.SUCCESS);
11981
12326
  }
11982
12327
  async function runCreateStream(name, opts) {
11983
- const result = await createStream(path65.resolve(opts.path), name, opts.branch);
12328
+ const result = await createStream(path66.resolve(opts.path), name, opts.branch);
11984
12329
  if (!result.ok) {
11985
12330
  logger.error(result.error.message);
11986
12331
  process.exit(ExitCode.ERROR);
@@ -11989,7 +12334,7 @@ async function runCreateStream(name, opts) {
11989
12334
  process.exit(ExitCode.SUCCESS);
11990
12335
  }
11991
12336
  async function runArchiveStream(name, opts) {
11992
- const result = await archiveStream(path65.resolve(opts.path), name);
12337
+ const result = await archiveStream(path66.resolve(opts.path), name);
11993
12338
  if (!result.ok) {
11994
12339
  logger.error(result.error.message);
11995
12340
  process.exit(ExitCode.ERROR);
@@ -11998,7 +12343,7 @@ async function runArchiveStream(name, opts) {
11998
12343
  process.exit(ExitCode.SUCCESS);
11999
12344
  }
12000
12345
  async function runActivateStream(name, opts) {
12001
- const result = await setActiveStream(path65.resolve(opts.path), name);
12346
+ const result = await setActiveStream(path66.resolve(opts.path), name);
12002
12347
  if (!result.ok) {
12003
12348
  logger.error(result.error.message);
12004
12349
  process.exit(ExitCode.ERROR);
@@ -12007,7 +12352,7 @@ async function runActivateStream(name, opts) {
12007
12352
  process.exit(ExitCode.SUCCESS);
12008
12353
  }
12009
12354
  function createStreamsCommand() {
12010
- const command = new Command103("streams").description("Manage state streams");
12355
+ const command = new Command105("streams").description("Manage state streams");
12011
12356
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
12012
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));
12013
12358
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -12017,7 +12362,7 @@ function createStreamsCommand() {
12017
12362
 
12018
12363
  // src/commands/state/index.ts
12019
12364
  function createStateCommand() {
12020
- const command = new Command104("state").description("Project state management commands");
12365
+ const command = new Command106("state").description("Project state management commands");
12021
12366
  command.addCommand(createShowCommand());
12022
12367
  command.addCommand(createResetCommand());
12023
12368
  command.addCommand(createLearnCommand());
@@ -12027,8 +12372,8 @@ function createStateCommand() {
12027
12372
 
12028
12373
  // src/commands/sync-analyses.ts
12029
12374
  import * as fs45 from "fs";
12030
- import * as path66 from "path";
12031
- import { Command as Command105 } from "commander";
12375
+ import * as path67 from "path";
12376
+ import { Command as Command107 } from "commander";
12032
12377
  init_dist3();
12033
12378
  function isValidRecord(record) {
12034
12379
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -12054,7 +12399,7 @@ function extractAnalysisFromComments(comments) {
12054
12399
  return null;
12055
12400
  }
12056
12401
  function bootstrapTrackerCommand2(opts, verb) {
12057
- const projectPath = path66.resolve(opts.dir);
12402
+ const projectPath = path67.resolve(opts.dir);
12058
12403
  const trackerConfig = loadTrackerSyncConfig(projectPath);
12059
12404
  if (!trackerConfig) {
12060
12405
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -12066,7 +12411,7 @@ function bootstrapTrackerCommand2(opts, verb) {
12066
12411
  );
12067
12412
  return null;
12068
12413
  }
12069
- const projectEnvPath = path66.join(projectPath, ".env");
12414
+ const projectEnvPath = path67.join(projectPath, ".env");
12070
12415
  if (fs45.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
12071
12416
  __require("dotenv").config({ path: projectEnvPath });
12072
12417
  }
@@ -12097,7 +12442,7 @@ async function loadRoadmapFeatures(projectPath) {
12097
12442
  }
12098
12443
  return r.value.features.filter((f) => !!f.externalId).map((f) => ({ name: f.name, externalId: f.externalId }));
12099
12444
  }
12100
- const roadmapFile = path66.join(projectPath, "docs", "roadmap.md");
12445
+ const roadmapFile = path67.join(projectPath, "docs", "roadmap.md");
12101
12446
  if (!fs45.existsSync(roadmapFile)) {
12102
12447
  logger.error("No docs/roadmap.md found. Cannot discover features with externalIds.");
12103
12448
  return null;
@@ -12154,9 +12499,9 @@ async function runSyncAnalyses(opts) {
12154
12499
  return;
12155
12500
  }
12156
12501
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
12157
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-JCFK263L.js");
12502
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-LHINSVK4.js");
12158
12503
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
12159
- const archive = new AnalysisArchive(path66.join(projectPath, ".harness", "analyses"));
12504
+ const archive = new AnalysisArchive(path67.join(projectPath, ".harness", "analyses"));
12160
12505
  const publishedIndex = loadPublishedIndex2(projectPath);
12161
12506
  const { syncedCount, skippedCount, warnCount } = await syncFeatureAnalyses(
12162
12507
  features,
@@ -12176,7 +12521,7 @@ async function runSyncAnalyses(opts) {
12176
12521
  }
12177
12522
  }
12178
12523
  function createSyncAnalysesCommand() {
12179
- const command = new Command105("sync-analyses").description(
12524
+ const command = new Command107("sync-analyses").description(
12180
12525
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
12181
12526
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
12182
12527
  try {
@@ -12190,8 +12535,8 @@ function createSyncAnalysesCommand() {
12190
12535
  }
12191
12536
 
12192
12537
  // src/commands/sync-main.ts
12193
- import { Command as Command106 } from "commander";
12194
- import * as path67 from "path";
12538
+ import { Command as Command108 } from "commander";
12539
+ import * as path68 from "path";
12195
12540
  import {
12196
12541
  syncMain as defaultSyncMain
12197
12542
  } from "@harness-engineering/orchestrator";
@@ -12221,8 +12566,8 @@ function formatHuman2(r) {
12221
12566
  }
12222
12567
  }
12223
12568
  function createSyncMainCommand() {
12224
- return new Command106("sync-main").description("Fast-forward the local default branch from origin (no-op on conflict)").option("--json", "Emit a SyncMainResult JSON object", false).option("--path <path>", "Project root path", ".").action(async (opts) => {
12225
- const cwd = path67.resolve(opts.path ?? ".");
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 ?? ".");
12226
12571
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
12227
12572
  process.exit(exitCode);
12228
12573
  });
@@ -12230,7 +12575,7 @@ function createSyncMainCommand() {
12230
12575
 
12231
12576
  // src/commands/taint.ts
12232
12577
  init_dist3();
12233
- import { Command as Command107 } from "commander";
12578
+ import { Command as Command109 } from "commander";
12234
12579
  function getProjectRoot() {
12235
12580
  return process.cwd();
12236
12581
  }
@@ -12302,26 +12647,26 @@ function registerStatusCommand(taint) {
12302
12647
  });
12303
12648
  }
12304
12649
  function createTaintCommand() {
12305
- const taint = new Command107("taint").description("Manage sentinel session taint state");
12650
+ const taint = new Command109("taint").description("Manage sentinel session taint state");
12306
12651
  registerClearCommand(taint);
12307
12652
  registerStatusCommand(taint);
12308
12653
  return taint;
12309
12654
  }
12310
12655
 
12311
12656
  // src/commands/telemetry/index.ts
12312
- import { Command as Command111 } from "commander";
12657
+ import { Command as Command113 } from "commander";
12313
12658
 
12314
12659
  // src/commands/telemetry/identify.ts
12315
12660
  init_dist3();
12316
- import { Command as Command108 } from "commander";
12661
+ import { Command as Command110 } from "commander";
12317
12662
  import * as fs46 from "fs";
12318
- import * as path68 from "path";
12663
+ import * as path69 from "path";
12319
12664
  function telemetryFilePath(cwd) {
12320
- return path68.join(cwd, ".harness", "telemetry.json");
12665
+ return path69.join(cwd, ".harness", "telemetry.json");
12321
12666
  }
12322
12667
  function writeTelemetryFile(cwd, data) {
12323
12668
  const filePath = telemetryFilePath(cwd);
12324
- const dir = path68.dirname(filePath);
12669
+ const dir = path69.dirname(filePath);
12325
12670
  fs46.mkdirSync(dir, { recursive: true });
12326
12671
  fs46.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
12327
12672
  }
@@ -12337,7 +12682,7 @@ function printIdentity(identity) {
12337
12682
  }
12338
12683
  }
12339
12684
  function createIdentifyCommand() {
12340
- const cmd = new Command108("identify").description("Set or clear telemetry identity fields in .harness/telemetry.json").option("--project <name>", "Project name").option("--team <name>", "Team name").option("--alias <name>", "User alias").option("--clear", "Remove all identity fields").action((opts) => {
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) => {
12341
12686
  const cwd = process.cwd();
12342
12687
  if (opts.clear) {
12343
12688
  writeTelemetryFile(cwd, { identity: {} });
@@ -12362,7 +12707,7 @@ function createIdentifyCommand() {
12362
12707
 
12363
12708
  // src/commands/telemetry/status.ts
12364
12709
  init_dist3();
12365
- import { Command as Command109 } from "commander";
12710
+ import { Command as Command111 } from "commander";
12366
12711
  function gatherEnvOverrides() {
12367
12712
  const overrides = {};
12368
12713
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -12404,7 +12749,7 @@ function printHumanStatus(result) {
12404
12749
  printEnvOverrides(result.envOverrides);
12405
12750
  }
12406
12751
  function createStatusCommand() {
12407
- 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) => {
12408
12753
  const cwd = process.cwd();
12409
12754
  const envOverrides = gatherEnvOverrides();
12410
12755
  const consent = resolveConsent(cwd, void 0);
@@ -12437,20 +12782,20 @@ function createStatusCommand() {
12437
12782
 
12438
12783
  // src/commands/telemetry/test.ts
12439
12784
  init_dist3();
12440
- import { Command as Command110 } from "commander";
12785
+ import { Command as Command112 } from "commander";
12441
12786
 
12442
12787
  // src/bin/command-telemetry.ts
12443
- import { existsSync as existsSync43, readFileSync as readFileSync33, mkdirSync as mkdirSync19, appendFileSync, writeFileSync as writeFileSync25 } from "fs";
12444
- import { join as join57, parse as parsePath, resolve as resolve43 } from "path";
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";
12445
12790
  import { spawn as spawn2 } from "child_process";
12446
12791
  var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
12447
12792
  var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
12448
12793
  function findProjectRoot(cwd) {
12449
- let dir = resolve43(cwd);
12794
+ let dir = resolve44(cwd);
12450
12795
  const { root } = parsePath(dir);
12451
12796
  while (dir !== root) {
12452
12797
  if (existsSync43(join57(dir, "harness.config.json"))) return dir;
12453
- dir = resolve43(dir, "..");
12798
+ dir = resolve44(dir, "..");
12454
12799
  }
12455
12800
  return cwd;
12456
12801
  }
@@ -12559,7 +12904,7 @@ function reportTestSuccess(status, distinctId, identity) {
12559
12904
  if (identity.team) logger.info(` team: ${identity.team}`);
12560
12905
  }
12561
12906
  function createTestCommand() {
12562
- 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 () => {
12563
12908
  const cwd = process.cwd();
12564
12909
  const consent = resolveConsent(cwd, void 0);
12565
12910
  if (!consent.allowed) {
@@ -12596,7 +12941,7 @@ function createTestCommand() {
12596
12941
 
12597
12942
  // src/commands/telemetry/index.ts
12598
12943
  function createTelemetryCommand() {
12599
- const command = new Command111("telemetry").description("Telemetry identity and status management");
12944
+ const command = new Command113("telemetry").description("Telemetry identity and status management");
12600
12945
  command.addCommand(createIdentifyCommand());
12601
12946
  command.addCommand(createStatusCommand());
12602
12947
  command.addCommand(createTestCommand());
@@ -12604,9 +12949,9 @@ function createTelemetryCommand() {
12604
12949
  }
12605
12950
 
12606
12951
  // src/commands/test-craft.ts
12607
- import { Command as Command112 } from "commander";
12952
+ import { Command as Command114 } from "commander";
12608
12953
  function createTestCraftCommand() {
12609
- return new Command112("test-craft").description(
12954
+ return new Command114("test-craft").description(
12610
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."
12611
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) => {
12612
12957
  const globalOpts = cmd.optsWithGlobals();
@@ -12654,10 +12999,10 @@ function printResult7(result, mode, _formatter) {
12654
12999
  list.push(f);
12655
13000
  byFile.set(f.target.file, list);
12656
13001
  }
12657
- for (const [file, fs48] of byFile) {
13002
+ for (const [file, fs49] of byFile) {
12658
13003
  console.log(`
12659
13004
  ${file}`);
12660
- for (const f of fs48) {
13005
+ for (const f of fs49) {
12661
13006
  const nestingStr = f.target.nesting.length > 0 ? f.target.nesting.join(" > ") + " > " : "";
12662
13007
  console.log(
12663
13008
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.framework}:${f.target.line}`
@@ -12676,7 +13021,7 @@ ${file}`);
12676
13021
  }
12677
13022
 
12678
13023
  // src/commands/traceability.ts
12679
- import { Command as Command113 } from "commander";
13024
+ import { Command as Command115 } from "commander";
12680
13025
  import chalk17 from "chalk";
12681
13026
  function confidenceLabel(maxConfidence) {
12682
13027
  if (maxConfidence >= 0.8) return "explicit";
@@ -12812,7 +13157,7 @@ async function runTraceability(options) {
12812
13157
  process.exit(ExitCode.SUCCESS);
12813
13158
  }
12814
13159
  function createTraceabilityCommand() {
12815
- return new Command113("traceability").description("Show spec-to-implementation traceability from the knowledge graph").option("--spec <path>", "Filter by spec file path").option("--feature <name>", "Filter by feature name").action(async (opts, cmd) => {
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) => {
12816
13161
  const globalOpts = cmd.optsWithGlobals();
12817
13162
  await runTraceability({
12818
13163
  spec: opts.spec,
@@ -12825,15 +13170,15 @@ function createTraceabilityCommand() {
12825
13170
  }
12826
13171
 
12827
13172
  // src/commands/uninstall.ts
12828
- import * as path69 from "path";
12829
- import { Command as Command114 } from "commander";
13173
+ import * as path70 from "path";
13174
+ import { Command as Command116 } from "commander";
12830
13175
  async function runUninstall(skillName, options) {
12831
13176
  const packageName = resolvePackageName(skillName);
12832
13177
  const shortName = extractSkillName(packageName);
12833
13178
  const globalDir = resolveGlobalSkillsDir();
12834
- const skillsDir = path69.dirname(globalDir);
12835
- const communityBase = path69.join(skillsDir, "community");
12836
- 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");
12837
13182
  const lockfile = readLockfile2(lockfilePath);
12838
13183
  const entry = lockfile.skills[packageName];
12839
13184
  if (!entry) {
@@ -12863,7 +13208,7 @@ async function runUninstall(skillName, options) {
12863
13208
  return result;
12864
13209
  }
12865
13210
  function createUninstallCommand() {
12866
- const cmd = new Command114("uninstall");
13211
+ const cmd = new Command116("uninstall");
12867
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) => {
12868
13213
  try {
12869
13214
  const result = await runUninstall(skill, opts);
@@ -12884,8 +13229,8 @@ function createUninstallCommand() {
12884
13229
  // src/commands/uninstall-constraints.ts
12885
13230
  init_dist3();
12886
13231
  import * as fs47 from "fs/promises";
12887
- import * as path70 from "path";
12888
- import { Command as Command115 } from "commander";
13232
+ import * as path71 from "path";
13233
+ import { Command as Command117 } from "commander";
12889
13234
  async function runUninstallConstraints(options) {
12890
13235
  const { packageName, configPath, lockfilePath } = options;
12891
13236
  const lockfileResult = await readLockfile(lockfilePath);
@@ -12942,11 +13287,11 @@ async function runUninstallConstraints(options) {
12942
13287
  };
12943
13288
  }
12944
13289
  function createUninstallConstraintsCommand() {
12945
- const cmd = new Command115("uninstall-constraints");
13290
+ const cmd = new Command117("uninstall-constraints");
12946
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) => {
12947
13292
  let configPath;
12948
13293
  if (opts.config) {
12949
- configPath = path70.resolve(opts.config);
13294
+ configPath = path71.resolve(opts.config);
12950
13295
  } else {
12951
13296
  const found = findConfigFile();
12952
13297
  if (!found.ok) {
@@ -12955,8 +13300,8 @@ function createUninstallConstraintsCommand() {
12955
13300
  }
12956
13301
  configPath = found.value;
12957
13302
  }
12958
- const projectRoot2 = path70.dirname(configPath);
12959
- 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");
12960
13305
  const result = await runUninstallConstraints({
12961
13306
  packageName: name,
12962
13307
  configPath,
@@ -12982,8 +13327,8 @@ function createUninstallConstraintsCommand() {
12982
13327
 
12983
13328
  // src/commands/update.ts
12984
13329
  init_dist3();
12985
- import { Command as Command116 } from "commander";
12986
- import { execFile, execFileSync as execFileSync7 } from "child_process";
13330
+ import { Command as Command118 } from "commander";
13331
+ import { execFile, execFileSync as execFileSync8 } from "child_process";
12987
13332
  import { realpathSync, existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
12988
13333
  import { dirname as dirname23, join as join60 } from "path";
12989
13334
  import { promisify } from "util";
@@ -13025,7 +13370,7 @@ async function getLatestVersionAsync(pkg) {
13025
13370
  function getInstalledVersions(pm, packages) {
13026
13371
  const versions = {};
13027
13372
  try {
13028
- const output = execFileSync7(pm, ["list", "-g", "--json"], {
13373
+ const output = execFileSync8(pm, ["list", "-g", "--json"], {
13029
13374
  encoding: "utf-8",
13030
13375
  timeout: 15e3
13031
13376
  });
@@ -13046,7 +13391,7 @@ function getInstalledVersions(pm, packages) {
13046
13391
  }
13047
13392
  function getInstalledPackages(pm) {
13048
13393
  try {
13049
- const output = execFileSync7(pm, ["list", "-g", "--json"], {
13394
+ const output = execFileSync8(pm, ["list", "-g", "--json"], {
13050
13395
  encoding: "utf-8",
13051
13396
  timeout: 15e3
13052
13397
  });
@@ -13066,10 +13411,10 @@ function prompt3(question) {
13066
13411
  input: process.stdin,
13067
13412
  output: process.stdout
13068
13413
  });
13069
- return new Promise((resolve46) => {
13414
+ return new Promise((resolve47) => {
13070
13415
  rl.question(question, (answer) => {
13071
13416
  rl.close();
13072
- resolve46(answer.trim().toLowerCase());
13417
+ resolve47(answer.trim().toLowerCase());
13073
13418
  });
13074
13419
  });
13075
13420
  }
@@ -13101,7 +13446,7 @@ function findAllInstalls() {
13101
13446
  const args = isWindows ? ["harness"] : ["-a", "harness"];
13102
13447
  let output;
13103
13448
  try {
13104
- const raw = execFileSync7(cmd, args, { encoding: "utf-8", timeout: 5e3 });
13449
+ const raw = execFileSync8(cmd, args, { encoding: "utf-8", timeout: 5e3 });
13105
13450
  if (typeof raw !== "string") return [];
13106
13451
  output = raw;
13107
13452
  } catch {
@@ -13178,7 +13523,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
13178
13523
  }
13179
13524
  try {
13180
13525
  logger.info(`Uninstalling: ${cmd.display}`);
13181
- execFileSync7(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
13526
+ execFileSync8(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
13182
13527
  } catch {
13183
13528
  logger.warn(`Uninstall failed for ${cmd.install.binPath}.`);
13184
13529
  console.log(` Run manually: ${chalk18.cyan(cmd.display)}`);
@@ -13238,7 +13583,7 @@ function refreshHooks() {
13238
13583
  function runLocalGraphScan() {
13239
13584
  try {
13240
13585
  logger.info("Scanning codebase to rebuild knowledge graph...");
13241
- execFileSync7("harness", ["graph", "scan", "."], { stdio: "inherit" });
13586
+ execFileSync8("harness", ["graph", "scan", "."], { stdio: "inherit" });
13242
13587
  } catch {
13243
13588
  logger.warn("Graph scan failed. Run manually:");
13244
13589
  console.log(` ${chalk18.cyan("harness graph scan .")}`);
@@ -13253,7 +13598,7 @@ async function offerRegeneration() {
13253
13598
  const scopeAnswer = await prompt3("Generate for (G)lobal or (l)ocal project? (G/l) ");
13254
13599
  const isGlobal = scopeAnswer !== "l" && scopeAnswer !== "local";
13255
13600
  try {
13256
- execFileSync7("harness", ["generate", ...isGlobal ? ["--global"] : []], {
13601
+ execFileSync8("harness", ["generate", ...isGlobal ? ["--global"] : []], {
13257
13602
  stdio: "inherit"
13258
13603
  });
13259
13604
  } catch {
@@ -13333,7 +13678,7 @@ async function runUpdateAction(opts, globalOpts) {
13333
13678
  }
13334
13679
  try {
13335
13680
  logger.info("Updating packages...");
13336
- execFileSync7(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
13681
+ execFileSync8(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
13337
13682
  console.log("");
13338
13683
  logger.success("Update complete");
13339
13684
  invalidateCheckState();
@@ -13350,7 +13695,7 @@ async function runUpdateAction(opts, globalOpts) {
13350
13695
  process.exit(ExitCode.SUCCESS);
13351
13696
  }
13352
13697
  function createUpdateCommand() {
13353
- return new Command116("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").option("--force", "Force update even if versions match").option(
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(
13354
13699
  "--regenerate",
13355
13700
  "Only regenerate slash commands and agent definitions (skip package updates)"
13356
13701
  ).action(async (opts, cmd) => {
@@ -13360,9 +13705,9 @@ function createUpdateCommand() {
13360
13705
  }
13361
13706
 
13362
13707
  // src/commands/usage.ts
13363
- import { Command as Command117 } from "commander";
13708
+ import { Command as Command119 } from "commander";
13364
13709
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
13365
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-JCFK263L.js");
13710
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-LHINSVK4.js");
13366
13711
  const records = readCostRecords(cwd);
13367
13712
  if (includeClaudeSessions) {
13368
13713
  const ccRecords = parseCCRecords();
@@ -13455,7 +13800,7 @@ function registerDailyCommand(usage) {
13455
13800
  else logger.info("No usage data found. Run some harness sessions first.");
13456
13801
  return;
13457
13802
  }
13458
- const { aggregateByDay } = await import("./dist-JCFK263L.js");
13803
+ const { aggregateByDay } = await import("./dist-LHINSVK4.js");
13459
13804
  const limited = aggregateByDay(records).slice(0, days);
13460
13805
  if (globalOpts.json) {
13461
13806
  console.log(
@@ -13484,7 +13829,7 @@ function registerSessionsCommand(usage) {
13484
13829
  }
13485
13830
  return;
13486
13831
  }
13487
- const { aggregateBySession } = await import("./dist-JCFK263L.js");
13832
+ const { aggregateBySession } = await import("./dist-LHINSVK4.js");
13488
13833
  const sessionData = aggregateBySession(records);
13489
13834
  const limited = sessionData.slice(0, limit);
13490
13835
  if (globalOpts.json) {
@@ -13564,7 +13909,7 @@ function registerSessionCommand(usage) {
13564
13909
  cwd,
13565
13910
  globalOpts.includeClaudeSessions
13566
13911
  );
13567
- const { aggregateBySession } = await import("./dist-JCFK263L.js");
13912
+ const { aggregateBySession } = await import("./dist-LHINSVK4.js");
13568
13913
  const sessionData = aggregateBySession(records);
13569
13914
  const match = sessionData.find((s) => s.sessionId === id);
13570
13915
  if (!match) {
@@ -13599,7 +13944,7 @@ function registerLatestCommand(usage) {
13599
13944
  }
13600
13945
  return;
13601
13946
  }
13602
- const { aggregateBySession } = await import("./dist-JCFK263L.js");
13947
+ const { aggregateBySession } = await import("./dist-LHINSVK4.js");
13603
13948
  const sessionData = aggregateBySession(records);
13604
13949
  const latest = sessionData[0];
13605
13950
  if (!latest) {
@@ -13625,7 +13970,7 @@ function registerLatestCommand(usage) {
13625
13970
  });
13626
13971
  }
13627
13972
  function createUsageCommand() {
13628
- const usage = new Command117("usage").description("Token usage and cost tracking");
13973
+ const usage = new Command119("usage").description("Token usage and cost tracking");
13629
13974
  usage.option(
13630
13975
  "--include-claude-sessions",
13631
13976
  "Include Claude Code session data from ~/.claude/projects/"
@@ -13640,15 +13985,16 @@ function createUsageCommand() {
13640
13985
  // src/commands/validate.ts
13641
13986
  init_dist3();
13642
13987
  init_dist3();
13643
- import { Command as Command118 } from "commander";
13644
- import * as path71 from "path";
13988
+ import { Command as Command120 } from "commander";
13989
+ import * as fs48 from "fs";
13990
+ import * as path72 from "path";
13645
13991
  async function runValidate(options) {
13646
13992
  const configResult = resolveConfig(options.configPath);
13647
13993
  if (!configResult.ok) {
13648
13994
  return configResult;
13649
13995
  }
13650
13996
  const config = configResult.value;
13651
- 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());
13652
13998
  const result = {
13653
13999
  valid: true,
13654
14000
  checks: {
@@ -13658,7 +14004,7 @@ async function runValidate(options) {
13658
14004
  },
13659
14005
  issues: []
13660
14006
  };
13661
- const agentsMapPath = path71.resolve(cwd, config.agentsMapPath);
14007
+ const agentsMapPath = path72.resolve(cwd, config.agentsMapPath);
13662
14008
  const agentsResult = await validateAgentsMap(agentsMapPath);
13663
14009
  if (agentsResult.ok) {
13664
14010
  result.checks.agentsMap = true;
@@ -13755,6 +14101,25 @@ async function runValidate(options) {
13755
14101
  }
13756
14102
  });
13757
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
+ }
13758
14123
  const anatomyEnabled = config.design?.audit?.componentAnatomy?.enabled !== false;
13759
14124
  if (anatomyEnabled) {
13760
14125
  try {
@@ -13880,11 +14245,11 @@ function resolveValidateMode(globalOpts) {
13880
14245
  return OutputMode.TEXT;
13881
14246
  }
13882
14247
  async function printCrossCheckWarnings(mode) {
13883
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-F7GEBRDH.js");
14248
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-QPSAOZKD.js");
13884
14249
  const cwd = process.cwd();
13885
14250
  const crossResult = await runCrossCheck2({
13886
- specsDir: path71.join(cwd, "docs", "specs"),
13887
- plansDir: path71.join(cwd, "docs", "plans"),
14251
+ specsDir: path72.join(cwd, "docs", "specs"),
14252
+ plansDir: path72.join(cwd, "docs", "plans"),
13888
14253
  projectPath: cwd
13889
14254
  });
13890
14255
  if (!crossResult.ok || crossResult.value.warnings === 0) return;
@@ -13896,7 +14261,7 @@ async function printCrossCheckWarnings(mode) {
13896
14261
  ${crossResult.value.warnings} warnings`);
13897
14262
  }
13898
14263
  function createValidateCommand3() {
13899
- 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(
13900
14265
  "--agent-configs",
13901
14266
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
13902
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()));
@@ -13945,7 +14310,7 @@ Agent configs checked via ${engineLabel}${note}`);
13945
14310
 
13946
14311
  // src/commands/verify.ts
13947
14312
  init_dist3();
13948
- import { Command as Command119 } from "commander";
14313
+ import { Command as Command121 } from "commander";
13949
14314
  import { execSync as execSync6 } from "child_process";
13950
14315
  function loadBranchingConfig(configPath) {
13951
14316
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -14008,7 +14373,7 @@ async function runVerify(options) {
14008
14373
  process.exit(ExitCode.VALIDATION_FAILED);
14009
14374
  }
14010
14375
  function createVerifyCommand() {
14011
- return new Command119("verify").description(
14376
+ return new Command121("verify").description(
14012
14377
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
14013
14378
  ).option(
14014
14379
  "--branch <name>",
@@ -14037,6 +14402,7 @@ var commandCreators = [
14037
14402
  createCheckDepsCommand,
14038
14403
  createCheckDesignCommand,
14039
14404
  createCheckDocsCommand,
14405
+ createCheckHarnessStrengthCommand,
14040
14406
  createCheckPerfCommand,
14041
14407
  createCheckPhaseGateCommand,
14042
14408
  createCheckSecurityCommand,
@@ -14083,6 +14449,7 @@ var commandCreators = [
14083
14449
  createPulseCommand,
14084
14450
  createQueryCommand,
14085
14451
  createRecommendCommand,
14452
+ createReviewCiCommand,
14086
14453
  createRoadmapCommand,
14087
14454
  createRoutingCommand,
14088
14455
  createScanCommand,
@@ -14112,7 +14479,7 @@ var commandCreators = [
14112
14479
 
14113
14480
  // src/index.ts
14114
14481
  function createProgram() {
14115
- const program = new Command120();
14482
+ const program = new Command122();
14116
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");
14117
14484
  for (const creator of commandCreators) {
14118
14485
  program.addCommand(creator());