@harness-engineering/cli 1.21.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +3 -0
  2. package/dist/agents/skills/claude-code/detect-doc-drift/skill.yaml +5 -0
  3. package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +13 -0
  4. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +2 -2
  5. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +1 -1
  6. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +5 -0
  7. package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +5 -0
  8. package/dist/agents/skills/claude-code/harness-debugging/skill.yaml +5 -0
  9. package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +9 -0
  10. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +1 -1
  11. package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +9 -0
  12. package/dist/agents/skills/claude-code/harness-integrity/skill.yaml +5 -0
  13. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
  14. package/dist/agents/skills/claude-code/harness-refactoring/skill.yaml +9 -0
  15. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +5 -5
  16. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +18 -14
  17. package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +3 -0
  18. package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +5 -0
  19. package/dist/agents/skills/claude-code/harness-supply-chain-audit/skill.yaml +3 -0
  20. package/dist/agents/skills/claude-code/harness-tdd/skill.yaml +3 -0
  21. package/dist/agents/skills/codex/cleanup-dead-code/skill.yaml +3 -0
  22. package/dist/agents/skills/codex/detect-doc-drift/skill.yaml +5 -0
  23. package/dist/agents/skills/codex/enforce-architecture/skill.yaml +13 -0
  24. package/dist/agents/skills/codex/harness-autopilot/SKILL.md +2 -2
  25. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +1 -1
  26. package/dist/agents/skills/codex/harness-code-review/skill.yaml +5 -0
  27. package/dist/agents/skills/codex/harness-codebase-cleanup/skill.yaml +5 -0
  28. package/dist/agents/skills/codex/harness-debugging/skill.yaml +5 -0
  29. package/dist/agents/skills/codex/harness-dependency-health/skill.yaml +9 -0
  30. package/dist/agents/skills/codex/harness-execution/SKILL.md +1 -1
  31. package/dist/agents/skills/codex/harness-hotspot-detector/skill.yaml +9 -0
  32. package/dist/agents/skills/codex/harness-integrity/skill.yaml +5 -0
  33. package/dist/agents/skills/codex/harness-perf/skill.yaml +3 -0
  34. package/dist/agents/skills/codex/harness-refactoring/skill.yaml +9 -0
  35. package/dist/agents/skills/codex/harness-roadmap/SKILL.md +5 -5
  36. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +18 -14
  37. package/dist/agents/skills/codex/harness-security-scan/skill.yaml +3 -0
  38. package/dist/agents/skills/codex/harness-soundness-review/skill.yaml +5 -0
  39. package/dist/agents/skills/codex/harness-supply-chain-audit/skill.yaml +3 -0
  40. package/dist/agents/skills/codex/harness-tdd/skill.yaml +3 -0
  41. package/dist/agents/skills/cursor/cleanup-dead-code/skill.yaml +3 -0
  42. package/dist/agents/skills/cursor/detect-doc-drift/skill.yaml +5 -0
  43. package/dist/agents/skills/cursor/enforce-architecture/skill.yaml +13 -0
  44. package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +2 -2
  45. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +1 -1
  46. package/dist/agents/skills/cursor/harness-code-review/skill.yaml +5 -0
  47. package/dist/agents/skills/cursor/harness-codebase-cleanup/skill.yaml +5 -0
  48. package/dist/agents/skills/cursor/harness-debugging/skill.yaml +5 -0
  49. package/dist/agents/skills/cursor/harness-dependency-health/skill.yaml +9 -0
  50. package/dist/agents/skills/cursor/harness-execution/SKILL.md +1 -1
  51. package/dist/agents/skills/cursor/harness-hotspot-detector/skill.yaml +9 -0
  52. package/dist/agents/skills/cursor/harness-integrity/skill.yaml +5 -0
  53. package/dist/agents/skills/cursor/harness-perf/skill.yaml +3 -0
  54. package/dist/agents/skills/cursor/harness-refactoring/skill.yaml +9 -0
  55. package/dist/agents/skills/cursor/harness-roadmap/SKILL.md +5 -5
  56. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +18 -14
  57. package/dist/agents/skills/cursor/harness-security-scan/skill.yaml +3 -0
  58. package/dist/agents/skills/cursor/harness-soundness-review/skill.yaml +5 -0
  59. package/dist/agents/skills/cursor/harness-supply-chain-audit/skill.yaml +3 -0
  60. package/dist/agents/skills/cursor/harness-tdd/skill.yaml +3 -0
  61. package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +3 -0
  62. package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +5 -0
  63. package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +13 -0
  64. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +2 -2
  65. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +1 -1
  66. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +5 -0
  67. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +5 -0
  68. package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +5 -0
  69. package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +9 -0
  70. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +1 -1
  71. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +9 -0
  72. package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +5 -0
  73. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
  74. package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +9 -0
  75. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +5 -5
  76. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +18 -14
  77. package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +3 -0
  78. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +5 -0
  79. package/dist/agents/skills/gemini-cli/harness-supply-chain-audit/skill.yaml +3 -0
  80. package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +3 -0
  81. package/dist/{agents-md-TDTLYAQU.js → agents-md-GLKJSGKT.js} +2 -1
  82. package/dist/{architecture-NANP4XPE.js → architecture-EDSBAGR4.js} +3 -2
  83. package/dist/assess-project-CEDY4JU3.js +9 -0
  84. package/dist/bin/harness-mcp.js +15 -13
  85. package/dist/bin/harness.js +21 -19
  86. package/dist/{check-phase-gate-I4NQOCSU.js → check-phase-gate-N3DTKFCZ.js} +4 -3
  87. package/dist/{chunk-UEKQ5G3V.js → chunk-26AUZBV4.js} +459 -37
  88. package/dist/chunk-2LAEDVOC.js +293 -0
  89. package/dist/{chunk-M6TIO6NF.js → chunk-2PAPHA77.js} +1 -1
  90. package/dist/{dist-U7EAO6T2.js → chunk-5SWE24IG.js} +401 -60
  91. package/dist/{chunk-7G2ZUTZA.js → chunk-A4AI3H3R.js} +26 -3
  92. package/dist/{chunk-HUDEBSR2.js → chunk-AIBAYANF.js} +3 -3
  93. package/dist/{chunk-6GEYPBDU.js → chunk-AKVG4MMZ.js} +9 -9
  94. package/dist/{chunk-SPUK5W4W.js → chunk-ENA4O4WD.js} +2 -2
  95. package/dist/{chunk-SZ5TGZMI.js → chunk-GJRUIXUK.js} +17 -2
  96. package/dist/{chunk-YF5ROTWR.js → chunk-HT4VPPB4.js} +8 -8
  97. package/dist/{chunk-L6LTNZQZ.js → chunk-LIWGCYON.js} +1 -1
  98. package/dist/{chunk-UVJFBKCX.js → chunk-QUKH6QCJ.js} +7 -7
  99. package/dist/{chunk-HKUX2X7O.js → chunk-SE4YPMLH.js} +9 -1
  100. package/dist/{chunk-TMSGI27F.js → chunk-SM22U22L.js} +982 -386
  101. package/dist/{chunk-LRG3B43J.js → chunk-T5QWCVGK.js} +1 -1
  102. package/dist/{chunk-H6LXAH66.js → chunk-TD6MQUV2.js} +1 -1
  103. package/dist/{chunk-WXI5ONCU.js → chunk-TJ6NLLAY.js} +4 -4
  104. package/dist/{chunk-CZZXE6BL.js → chunk-TLDCCPUZ.js} +1 -1
  105. package/dist/{chunk-YZYBQZVL.js → chunk-XDAIFVGC.js} +1539 -587
  106. package/dist/{ci-workflow-Z4IUJBZL.js → ci-workflow-LE3QF4FP.js} +2 -1
  107. package/dist/{create-skill-NDXQSTIK.js → create-skill-U3XCFRZN.js} +2 -2
  108. package/dist/dist-OEXTQQZC.js +92 -0
  109. package/dist/{dist-KV2ICL5X.js → dist-YIKUBJLQ.js} +56 -3
  110. package/dist/{docs-2PCZVSGB.js → docs-F5G7NAFF.js} +4 -3
  111. package/dist/{engine-EOXMI5MD.js → engine-LX5RVGXN.js} +2 -1
  112. package/dist/{entropy-VGXXBIGX.js → entropy-A5Q2USYX.js} +3 -2
  113. package/dist/{feedback-VTSPL3O7.js → feedback-2EU25RIW.js} +1 -1
  114. package/dist/{generate-agent-definitions-QICSCGXB.js → generate-agent-definitions-HNJHO5YQ.js} +2 -1
  115. package/dist/{graph-loader-KMHDQYDT.js → graph-loader-XULF5QF7.js} +1 -1
  116. package/dist/index.d.ts +66 -10
  117. package/dist/index.js +27 -23
  118. package/dist/{loader-7S4FYAPP.js → loader-GWIEW4HM.js} +2 -1
  119. package/dist/{mcp-DF25USTE.js → mcp-ID3LR6JB.js} +15 -13
  120. package/dist/{performance-RV4DUMFI.js → performance-YAY2A6A6.js} +4 -3
  121. package/dist/{review-pipeline-7KQJB4SI.js → review-pipeline-YD4WI3JM.js} +1 -1
  122. package/dist/{runtime-XKOHGGRC.js → runtime-UJ4YO4CA.js} +2 -1
  123. package/dist/{security-NLWTMK3G.js → security-IBSUKMVD.js} +1 -1
  124. package/dist/{skill-executor-XEVDGXUM.js → skill-executor-2BZQLHYN.js} +2 -2
  125. package/dist/{validate-VHFE6J6O.js → validate-NHXWKMCR.js} +3 -2
  126. package/dist/{validate-cross-check-PFRKABCS.js → validate-cross-check-R3GV2MLM.js} +2 -1
  127. package/package.json +4 -4
@@ -1,3 +1,6 @@
1
+ import {
2
+ generateAgentsMd
3
+ } from "./chunk-OD3S2NHN.js";
1
4
  import {
2
5
  generateCIWorkflow
3
6
  } from "./chunk-SD3SQOZ2.js";
@@ -6,11 +9,14 @@ import {
6
9
  OutputMode,
7
10
  createCheckPhaseGateCommand,
8
11
  findFiles
9
- } from "./chunk-7G2ZUTZA.js";
12
+ } from "./chunk-A4AI3H3R.js";
10
13
  import {
11
14
  createGenerateAgentDefinitionsCommand,
12
15
  generateAgentDefinitions
13
16
  } from "./chunk-6KWBH4EO.js";
17
+ import {
18
+ TemplateEngine
19
+ } from "./chunk-YLN34N65.js";
14
20
  import {
15
21
  listPersonas,
16
22
  loadPersona
@@ -20,13 +26,13 @@ import {
20
26
  } from "./chunk-TRAPF4IX.js";
21
27
  import {
22
28
  executeSkill
23
- } from "./chunk-M6TIO6NF.js";
29
+ } from "./chunk-2PAPHA77.js";
24
30
  import {
25
31
  ALLOWED_PERSONA_COMMANDS
26
32
  } from "./chunk-TEFCFC4H.js";
27
33
  import {
28
34
  createCreateSkillCommand
29
- } from "./chunk-LRG3B43J.js";
35
+ } from "./chunk-T5QWCVGK.js";
30
36
  import {
31
37
  logger
32
38
  } from "./chunk-EBJQ6N4M.js";
@@ -40,24 +46,26 @@ import {
40
46
  import {
41
47
  toKebabCase
42
48
  } from "./chunk-KET4QQZB.js";
43
- import {
44
- generateAgentsMd
45
- } from "./chunk-OD3S2NHN.js";
46
49
  import {
47
50
  appendFrameworkAgents,
51
+ captureHealthSnapshot,
48
52
  createGenerateSlashCommandsCommand,
49
53
  generateSlashCommands,
50
54
  handleGetImpact,
51
55
  handleOrphanDeletion,
52
- persistToolingConfig
53
- } from "./chunk-TMSGI27F.js";
56
+ isSnapshotFresh,
57
+ loadCachedSnapshot,
58
+ loadOrRebuildIndex,
59
+ persistToolingConfig,
60
+ recommend
61
+ } from "./chunk-SM22U22L.js";
54
62
  import {
55
63
  VALID_PLATFORMS
56
64
  } from "./chunk-CJDVBBPB.js";
57
65
  import {
58
66
  findConfigFile,
59
67
  resolveConfig
60
- } from "./chunk-SZ5TGZMI.js";
68
+ } from "./chunk-GJRUIXUK.js";
61
69
  import {
62
70
  resolveGlobalSkillsDir,
63
71
  resolvePersonasDir,
@@ -72,13 +80,10 @@ import {
72
80
  } from "./chunk-3WGJMBKH.js";
73
81
  import {
74
82
  SkillMetadataSchema
75
- } from "./chunk-HKUX2X7O.js";
83
+ } from "./chunk-SE4YPMLH.js";
76
84
  import {
77
85
  CLI_VERSION
78
86
  } from "./chunk-BM3PWGXQ.js";
79
- import {
80
- TemplateEngine
81
- } from "./chunk-YLN34N65.js";
82
87
  import {
83
88
  ArchBaselineManager,
84
89
  ArchConfigSchema,
@@ -87,8 +92,11 @@ import {
87
92
  BundleSchema,
88
93
  CriticalPathResolver,
89
94
  EntropyAnalyzer,
95
+ PredictionEngine,
90
96
  ProjectScanner,
91
97
  SecurityScanner,
98
+ SpecImpactEstimator,
99
+ TimelineManager,
92
100
  TypeScriptParser,
93
101
  addProvenance,
94
102
  appendLearning,
@@ -135,14 +143,14 @@ import {
135
143
  validateKnowledgeMap,
136
144
  writeConfig,
137
145
  writeLockfile
138
- } from "./chunk-YZYBQZVL.js";
146
+ } from "./chunk-XDAIFVGC.js";
139
147
  import {
140
148
  Err,
141
149
  Ok
142
150
  } from "./chunk-ERS5EVUZ.js";
143
151
 
144
152
  // src/index.ts
145
- import { Command as Command70 } from "commander";
153
+ import { Command as Command73 } from "commander";
146
154
 
147
155
  // src/commands/validate.ts
148
156
  import { Command } from "commander";
@@ -221,7 +229,7 @@ function createValidateCommand() {
221
229
  process.exit(result.error.exitCode);
222
230
  }
223
231
  if (opts.crossCheck) {
224
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-PFRKABCS.js");
232
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-R3GV2MLM.js");
225
233
  const cwd = process.cwd();
226
234
  const specsDir = path.join(cwd, "docs", "specs");
227
235
  const plansDir = path.join(cwd, "docs", "plans");
@@ -578,7 +586,7 @@ function registerBenchCommand(perf) {
578
586
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob, _opts, cmd) => {
579
587
  const globalOpts = cmd.optsWithGlobals();
580
588
  const cwd = process.cwd();
581
- const { BenchmarkRunner } = await import("./dist-KV2ICL5X.js");
589
+ const { BenchmarkRunner } = await import("./dist-YIKUBJLQ.js");
582
590
  const runner = new BenchmarkRunner();
583
591
  const benchFiles = runner.discover(cwd, glob);
584
592
  if (benchFiles.length === 0) {
@@ -646,7 +654,7 @@ function registerBaselinesCommands(perf) {
646
654
  baselines.command("update").description("Update baselines from latest benchmark run").action(async (_opts, cmd) => {
647
655
  const globalOpts = cmd.optsWithGlobals();
648
656
  const cwd = process.cwd();
649
- const { BenchmarkRunner } = await import("./dist-KV2ICL5X.js");
657
+ const { BenchmarkRunner } = await import("./dist-YIKUBJLQ.js");
650
658
  const runner = new BenchmarkRunner();
651
659
  const manager = new BaselineManager(cwd);
652
660
  logger.info("Running benchmarks to update baselines...");
@@ -669,8 +677,8 @@ function registerBaselinesCommands(perf) {
669
677
  }
670
678
  async function getCommitHash(cwd) {
671
679
  try {
672
- const { execSync: execSync5 } = await import("child_process");
673
- return execSync5("git rev-parse --short HEAD", { cwd, encoding: "utf-8" }).trim();
680
+ const { execSync: execSync6 } = await import("child_process");
681
+ return execSync6("git rev-parse --short HEAD", { cwd, encoding: "utf-8" }).trim();
674
682
  } catch {
675
683
  return "unknown";
676
684
  }
@@ -679,7 +687,7 @@ function registerReportCommand(perf) {
679
687
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
680
688
  const globalOpts = cmd.optsWithGlobals();
681
689
  const cwd = process.cwd();
682
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-KV2ICL5X.js");
690
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-YIKUBJLQ.js");
683
691
  const analyzer = new EntropyAnalyzer2({
684
692
  rootDir: path5.resolve(cwd),
685
693
  analyze: { complexity: true, coupling: true }
@@ -1060,7 +1068,11 @@ var ALL_MCP_TOOLS = [
1060
1068
  "search_skills",
1061
1069
  "code_outline",
1062
1070
  "code_search",
1063
- "code_unfold"
1071
+ "code_unfold",
1072
+ "get_decay_trends",
1073
+ "check_traceability",
1074
+ "predict_failures",
1075
+ "recommend_skills"
1064
1076
  ];
1065
1077
  async function runCursorToolPicker() {
1066
1078
  try {
@@ -1975,7 +1987,7 @@ async function runAdd(componentType, name, options) {
1975
1987
  break;
1976
1988
  }
1977
1989
  case "skill": {
1978
- const { generateSkillFiles: generateSkillFiles2 } = await import("./create-skill-NDXQSTIK.js");
1990
+ const { generateSkillFiles: generateSkillFiles2 } = await import("./create-skill-U3XCFRZN.js");
1979
1991
  generateSkillFiles2({
1980
1992
  name,
1981
1993
  description: `${name} skill`,
@@ -3987,7 +3999,8 @@ var VALID_CHECKS = [
3987
3999
  "security",
3988
4000
  "perf",
3989
4001
  "phase-gate",
3990
- "arch"
4002
+ "arch",
4003
+ "traceability"
3991
4004
  ];
3992
4005
  async function runCICheck(options) {
3993
4006
  const configResult = resolveConfig(options.configPath);
@@ -4073,7 +4086,8 @@ var ALL_CHECKS = [
4073
4086
  "security",
4074
4087
  "perf",
4075
4088
  "phase-gate",
4076
- "arch"
4089
+ "arch",
4090
+ "traceability"
4077
4091
  ];
4078
4092
  function buildSkipFlag(checks) {
4079
4093
  if (!checks) return "";
@@ -4753,7 +4767,7 @@ function createGenerateCommand3() {
4753
4767
  import { Command as Command46 } from "commander";
4754
4768
  import * as path38 from "path";
4755
4769
  async function runScan(projectPath) {
4756
- const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-U7EAO6T2.js");
4770
+ const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-OEXTQQZC.js");
4757
4771
  const store = new GraphStore();
4758
4772
  const start = Date.now();
4759
4773
  await new CodeIngestor(store).ingest(projectPath);
@@ -4834,7 +4848,7 @@ async function runIngest(projectPath, source, opts) {
4834
4848
  SyncManager,
4835
4849
  JiraConnector,
4836
4850
  SlackConnector
4837
- } = await import("./dist-U7EAO6T2.js");
4851
+ } = await import("./dist-OEXTQQZC.js");
4838
4852
  const graphDir = path39.join(projectPath, ".harness", "graph");
4839
4853
  const store = new GraphStore();
4840
4854
  await store.load(graphDir);
@@ -4927,7 +4941,7 @@ function createIngestCommand() {
4927
4941
  import { Command as Command48 } from "commander";
4928
4942
  import * as path40 from "path";
4929
4943
  async function runQuery(projectPath, rootNodeId, opts) {
4930
- const { GraphStore, ContextQL } = await import("./dist-U7EAO6T2.js");
4944
+ const { GraphStore, ContextQL } = await import("./dist-OEXTQQZC.js");
4931
4945
  const store = new GraphStore();
4932
4946
  const graphDir = path40.join(projectPath, ".harness", "graph");
4933
4947
  const loaded = await store.load(graphDir);
@@ -4976,7 +4990,7 @@ import { Command as Command49 } from "commander";
4976
4990
  // src/commands/graph/status.ts
4977
4991
  import * as path41 from "path";
4978
4992
  async function runGraphStatus(projectPath) {
4979
- const { GraphStore } = await import("./dist-U7EAO6T2.js");
4993
+ const { GraphStore } = await import("./dist-OEXTQQZC.js");
4980
4994
  const graphDir = path41.join(projectPath, ".harness", "graph");
4981
4995
  const store = new GraphStore();
4982
4996
  const loaded = await store.load(graphDir);
@@ -5016,7 +5030,7 @@ async function runGraphStatus(projectPath) {
5016
5030
  // src/commands/graph/export.ts
5017
5031
  import * as path42 from "path";
5018
5032
  async function runGraphExport(projectPath, format) {
5019
- const { GraphStore } = await import("./dist-U7EAO6T2.js");
5033
+ const { GraphStore } = await import("./dist-OEXTQQZC.js");
5020
5034
  const graphDir = path42.join(projectPath, ".harness", "graph");
5021
5035
  const store = new GraphStore();
5022
5036
  const loaded = await store.load(graphDir);
@@ -5095,7 +5109,7 @@ function createGraphCommand() {
5095
5109
  import { Command as Command50 } from "commander";
5096
5110
  function createMcpCommand() {
5097
5111
  return new Command50("mcp").description("Start the MCP (Model Context Protocol) server on stdio").option("--tools <tools...>", "Only register the specified tools (used by Cursor integration)").action(async (opts) => {
5098
- const { startServer: startServer2 } = await import("./mcp-DF25USTE.js");
5112
+ const { startServer: startServer2 } = await import("./mcp-ID3LR6JB.js");
5099
5113
  await startServer2(opts.tools);
5100
5114
  });
5101
5115
  }
@@ -6594,7 +6608,7 @@ function createIntegrationsCommand() {
6594
6608
  // src/commands/usage.ts
6595
6609
  import { Command as Command67 } from "commander";
6596
6610
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
6597
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-KV2ICL5X.js");
6611
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-YIKUBJLQ.js");
6598
6612
  const records = readCostRecords(cwd);
6599
6613
  if (includeClaudeSessions) {
6600
6614
  const ccRecords = parseCCRecords();
@@ -6638,7 +6652,7 @@ function registerDailyCommand(usage) {
6638
6652
  }
6639
6653
  return;
6640
6654
  }
6641
- const { aggregateByDay } = await import("./dist-KV2ICL5X.js");
6655
+ const { aggregateByDay } = await import("./dist-YIKUBJLQ.js");
6642
6656
  const dailyData = aggregateByDay(records);
6643
6657
  const limited = dailyData.slice(0, days);
6644
6658
  if (globalOpts.json) {
@@ -6674,7 +6688,7 @@ function registerSessionsCommand(usage) {
6674
6688
  }
6675
6689
  return;
6676
6690
  }
6677
- const { aggregateBySession } = await import("./dist-KV2ICL5X.js");
6691
+ const { aggregateBySession } = await import("./dist-YIKUBJLQ.js");
6678
6692
  const sessionData = aggregateBySession(records);
6679
6693
  const limited = sessionData.slice(0, limit);
6680
6694
  if (globalOpts.json) {
@@ -6703,7 +6717,7 @@ function registerSessionCommand(usage) {
6703
6717
  const globalOpts = cmd.optsWithGlobals();
6704
6718
  const cwd = process.cwd();
6705
6719
  const records = await loadAndPriceRecords(cwd, globalOpts.includeClaudeSessions);
6706
- const { aggregateBySession } = await import("./dist-KV2ICL5X.js");
6720
+ const { aggregateBySession } = await import("./dist-YIKUBJLQ.js");
6707
6721
  const sessionData = aggregateBySession(records);
6708
6722
  const match = sessionData.find((s) => s.sessionId === id);
6709
6723
  if (!match) {
@@ -6769,7 +6783,7 @@ function registerLatestCommand(usage) {
6769
6783
  }
6770
6784
  return;
6771
6785
  }
6772
- const { aggregateBySession } = await import("./dist-KV2ICL5X.js");
6786
+ const { aggregateBySession } = await import("./dist-YIKUBJLQ.js");
6773
6787
  const sessionData = aggregateBySession(records);
6774
6788
  const latest = sessionData[0];
6775
6789
  if (!latest) {
@@ -6986,9 +7000,413 @@ function createScanConfigCommand() {
6986
7000
  return command;
6987
7001
  }
6988
7002
 
7003
+ // src/commands/snapshot.ts
7004
+ import { Command as Command70 } from "commander";
7005
+ import { execSync as execSync5 } from "child_process";
7006
+ import chalk8 from "chalk";
7007
+ function getCommitHash3(cwd) {
7008
+ try {
7009
+ return execSync5("git rev-parse --short HEAD", { cwd, encoding: "utf-8" }).toString().trim();
7010
+ } catch {
7011
+ return "unknown";
7012
+ }
7013
+ }
7014
+ function resolveArchConfig(configPath) {
7015
+ const configResult = resolveConfig(configPath);
7016
+ if (!configResult.ok) {
7017
+ return { error: configResult.error };
7018
+ }
7019
+ const archConfig = configResult.value.architecture ?? ArchConfigSchema.parse({});
7020
+ return { archConfig };
7021
+ }
7022
+ function formatDelta(delta) {
7023
+ if (delta === 0) return "0";
7024
+ const sign = delta > 0 ? "+" : "";
7025
+ const formatted = Number.isInteger(delta) ? String(delta) : delta.toFixed(2).replace(/\.?0+$/, "");
7026
+ return `${sign}${formatted}`;
7027
+ }
7028
+ function directionSymbol(direction) {
7029
+ switch (direction) {
7030
+ case "improving":
7031
+ return chalk8.green("improving");
7032
+ case "declining":
7033
+ return chalk8.red("declining");
7034
+ case "stable":
7035
+ return "=";
7036
+ }
7037
+ }
7038
+ var CATEGORY_ORDER = [
7039
+ "circular-deps",
7040
+ "layer-violations",
7041
+ "complexity",
7042
+ "coupling",
7043
+ "forbidden-imports",
7044
+ "module-size",
7045
+ "dependency-depth"
7046
+ ];
7047
+ async function runSnapshotCapture(options) {
7048
+ const cwd = options.cwd ?? process.cwd();
7049
+ const resolved = resolveArchConfig(options.configPath);
7050
+ if (resolved.error) {
7051
+ throw resolved.error;
7052
+ }
7053
+ const manager = new TimelineManager(cwd);
7054
+ const timelineBefore = manager.load();
7055
+ const previous = timelineBefore.snapshots.length > 0 ? timelineBefore.snapshots[timelineBefore.snapshots.length - 1] : void 0;
7056
+ const results = await runAll(resolved.archConfig, cwd);
7057
+ const commitHash = getCommitHash3(cwd);
7058
+ const snapshot = manager.capture(results, commitHash);
7059
+ return { snapshot, previous };
7060
+ }
7061
+ function printCaptureSummary(snapshot, previous) {
7062
+ const date = snapshot.capturedAt.slice(0, 10);
7063
+ const commit = snapshot.commitHash.slice(0, 7);
7064
+ console.log("");
7065
+ console.log(`Architecture Snapshot captured (${date}, ${commit})`);
7066
+ console.log("");
7067
+ const stabilityDelta = previous ? ` (${formatDelta(snapshot.stabilityScore - previous.stabilityScore)} from last)` : "";
7068
+ console.log(` Stability: ${snapshot.stabilityScore}/100${stabilityDelta}`);
7069
+ console.log("");
7070
+ const header = " Category".padEnd(22) + "Value".padStart(7) + "Delta".padStart(8) + " Trend";
7071
+ console.log(header);
7072
+ for (const category of CATEGORY_ORDER) {
7073
+ const current = snapshot.metrics[category];
7074
+ const prev = previous?.metrics[category];
7075
+ const value = current?.value ?? 0;
7076
+ const delta = prev ? value - prev.value : 0;
7077
+ const valueFmt = Number.isInteger(value) ? String(value) : value.toFixed(2);
7078
+ const deltaFmt = formatDelta(delta);
7079
+ const direction = Math.abs(delta) < 2 ? "stable" : delta < 0 ? "improving" : "declining";
7080
+ const line = ` ${category.padEnd(20)}${valueFmt.padStart(7)}${deltaFmt.padStart(8)} ${directionSymbol(direction)}`;
7081
+ console.log(line);
7082
+ }
7083
+ console.log("");
7084
+ }
7085
+ function printTrendsSummary(trends) {
7086
+ if (trends.snapshotCount === 0) {
7087
+ logger.warn("No snapshots found. Run `harness snapshot capture` first.");
7088
+ return;
7089
+ }
7090
+ const fromDate = trends.from.slice(0, 10);
7091
+ const toDate = trends.to.slice(0, 10);
7092
+ console.log("");
7093
+ console.log(`Architecture Trends (${trends.snapshotCount} snapshots, ${fromDate} to ${toDate})`);
7094
+ console.log("");
7095
+ const stabilityDelta = formatDelta(trends.stability.delta);
7096
+ console.log(
7097
+ ` Stability: ${trends.stability.current}/100 (was ${trends.stability.previous} on ${fromDate}, ${stabilityDelta})`
7098
+ );
7099
+ console.log("");
7100
+ const header = " Category".padEnd(22) + "Current".padStart(9) + "Start".padStart(9) + "Delta".padStart(9) + " Trend";
7101
+ console.log(header);
7102
+ for (const category of CATEGORY_ORDER) {
7103
+ const trend = trends.categories[category];
7104
+ if (!trend) continue;
7105
+ const currentFmt = Number.isInteger(trend.current) ? String(trend.current) : trend.current.toFixed(2);
7106
+ const prevFmt = Number.isInteger(trend.previous) ? String(trend.previous) : trend.previous.toFixed(2);
7107
+ const deltaFmt = formatDelta(trend.delta);
7108
+ const line = ` ${category.padEnd(20)}${currentFmt.padStart(9)}${prevFmt.padStart(9)}${deltaFmt.padStart(9)} ${directionSymbol(trend.direction)}`;
7109
+ console.log(line);
7110
+ }
7111
+ console.log("");
7112
+ }
7113
+ function printSnapshotList(manager) {
7114
+ const timeline = manager.load();
7115
+ if (timeline.snapshots.length === 0) {
7116
+ logger.warn("No snapshots found. Run `harness snapshot capture` first.");
7117
+ return;
7118
+ }
7119
+ console.log("");
7120
+ console.log(`Architecture Snapshots (${timeline.snapshots.length} total)`);
7121
+ console.log("");
7122
+ const header = " #".padEnd(6) + "Date".padEnd(14) + "Commit".padEnd(12) + "Stability";
7123
+ console.log(header);
7124
+ timeline.snapshots.forEach((snap, idx) => {
7125
+ const date = snap.capturedAt.slice(0, 10);
7126
+ const commit = snap.commitHash.slice(0, 7);
7127
+ const num = String(idx + 1);
7128
+ const line = ` ${num.padEnd(4)}${date.padEnd(14)}${commit.padEnd(12)}${snap.stabilityScore}/100`;
7129
+ console.log(line);
7130
+ });
7131
+ console.log("");
7132
+ }
7133
+ function createSnapshotCommand() {
7134
+ const command = new Command70("snapshot").description("Architecture timeline snapshot commands");
7135
+ command.command("capture").description("Capture current architecture metrics as a timeline snapshot").action(async (_opts, cmd) => {
7136
+ const globalOpts = cmd.optsWithGlobals();
7137
+ const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
7138
+ try {
7139
+ const { snapshot, previous } = await runSnapshotCapture({
7140
+ configPath: globalOpts.config
7141
+ });
7142
+ if (mode === OutputMode.JSON) {
7143
+ console.log(JSON.stringify({ snapshot, previous: previous ?? null }, null, 2));
7144
+ } else {
7145
+ printCaptureSummary(snapshot, previous);
7146
+ }
7147
+ } catch (err) {
7148
+ if (err instanceof CLIError) {
7149
+ if (mode === OutputMode.JSON) {
7150
+ console.log(JSON.stringify({ error: err.message }));
7151
+ } else {
7152
+ logger.error(err.message);
7153
+ }
7154
+ process.exit(err.exitCode);
7155
+ }
7156
+ throw err;
7157
+ }
7158
+ });
7159
+ command.command("trends").description("Show architecture metric trends over time").option("--last <n>", "Number of recent snapshots to analyze", "10").option("--since <date>", "Show trends since ISO date").action(async (opts, cmd) => {
7160
+ const globalOpts = cmd.optsWithGlobals();
7161
+ const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
7162
+ const cwd = process.cwd();
7163
+ const manager = new TimelineManager(cwd);
7164
+ const trends = manager.trends({
7165
+ last: parseInt(opts.last, 10),
7166
+ since: opts.since
7167
+ });
7168
+ if (mode === OutputMode.JSON) {
7169
+ console.log(JSON.stringify(trends, null, 2));
7170
+ } else {
7171
+ printTrendsSummary(trends);
7172
+ }
7173
+ });
7174
+ command.command("list").description("List all captured architecture snapshots").action(async (_opts, cmd) => {
7175
+ const globalOpts = cmd.optsWithGlobals();
7176
+ const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
7177
+ const cwd = process.cwd();
7178
+ const manager = new TimelineManager(cwd);
7179
+ if (mode === OutputMode.JSON) {
7180
+ const timeline = manager.load();
7181
+ console.log(JSON.stringify(timeline, null, 2));
7182
+ } else {
7183
+ printSnapshotList(manager);
7184
+ }
7185
+ });
7186
+ return command;
7187
+ }
7188
+
7189
+ // src/commands/predict.ts
7190
+ import { Command as Command71 } from "commander";
7191
+ import chalk9 from "chalk";
7192
+ var CATEGORY_ORDER2 = [
7193
+ "circular-deps",
7194
+ "layer-violations",
7195
+ "complexity",
7196
+ "coupling",
7197
+ "forbidden-imports",
7198
+ "module-size",
7199
+ "dependency-depth"
7200
+ ];
7201
+ function formatValue(value) {
7202
+ if (Number.isInteger(value)) return String(value);
7203
+ return value.toFixed(2);
7204
+ }
7205
+ function crossingLabel(weeks) {
7206
+ if (weeks === null || weeks <= 0) return "--";
7207
+ return `~${Math.round(weeks)} weeks`;
7208
+ }
7209
+ function severityPrefix(severity) {
7210
+ switch (severity) {
7211
+ case "critical":
7212
+ return chalk9.red("[critical]");
7213
+ case "warning":
7214
+ return chalk9.yellow("[warning]");
7215
+ case "info":
7216
+ return chalk9.blue("[info]");
7217
+ }
7218
+ }
7219
+ function printPredictionReport(result) {
7220
+ const sf = result.stabilityForecast;
7221
+ const horizonWeeks = 12;
7222
+ console.log("");
7223
+ console.log(
7224
+ `Architecture Prediction (${horizonWeeks}-week horizon, ${result.snapshotsUsed} snapshots)`
7225
+ );
7226
+ console.log("");
7227
+ console.log(
7228
+ ` Stability: ${sf.current}/100 -> projected ${sf.projected12w}/100 in 12w (${sf.confidence} confidence)`
7229
+ );
7230
+ console.log("");
7231
+ const header = " " + "Category".padEnd(20) + "Current".padStart(9) + "Threshold".padStart(11) + "4w".padStart(7) + "8w".padStart(7) + "12w".padStart(7) + " Crossing".padEnd(16) + "Confidence";
7232
+ console.log(header);
7233
+ for (const category of CATEGORY_ORDER2) {
7234
+ const af = result.categories[category];
7235
+ if (!af) continue;
7236
+ const f = af.adjusted;
7237
+ const line = " " + category.padEnd(20) + formatValue(f.current).padStart(9) + formatValue(f.threshold).padStart(11) + formatValue(f.projectedValue4w).padStart(7) + formatValue(f.projectedValue8w).padStart(7) + formatValue(f.projectedValue12w).padStart(7) + (" " + crossingLabel(f.thresholdCrossingWeeks)).padEnd(16) + f.confidence;
7238
+ console.log(line);
7239
+ }
7240
+ if (result.warnings.length > 0) {
7241
+ console.log("");
7242
+ console.log(" Warnings:");
7243
+ for (const w of result.warnings) {
7244
+ console.log(` ${severityPrefix(w.severity)} ${w.message}`);
7245
+ if (w.contributingFeatures.length > 0) {
7246
+ console.log(` Accelerated by: ${w.contributingFeatures.join(", ")}`);
7247
+ }
7248
+ }
7249
+ }
7250
+ console.log("");
7251
+ }
7252
+ function runPredict(options) {
7253
+ const cwd = options.cwd ?? process.cwd();
7254
+ const configResult = resolveConfig(options.configPath);
7255
+ if (!configResult.ok) {
7256
+ throw configResult.error;
7257
+ }
7258
+ const manager = new TimelineManager(cwd);
7259
+ const estimator = options.noRoadmap === true ? null : new SpecImpactEstimator(cwd);
7260
+ const engine = new PredictionEngine(cwd, manager, estimator);
7261
+ const categories = options.category ? [options.category] : void 0;
7262
+ return engine.predict({
7263
+ ...options.horizon !== void 0 ? { horizon: options.horizon } : {},
7264
+ includeRoadmap: options.noRoadmap !== true,
7265
+ categories
7266
+ });
7267
+ }
7268
+ function createPredictCommand() {
7269
+ const command = new Command71("predict").description("Predict which architectural constraints will break and when").option("--category <name>", "Filter to a single metric category").option("--no-roadmap", "Baseline only \u2014 skip roadmap spec impact").option("--horizon <weeks>", "Forecast horizon in weeks (default: 12)", "12").action(async (opts, cmd) => {
7270
+ const globalOpts = cmd.optsWithGlobals();
7271
+ const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
7272
+ try {
7273
+ const result = runPredict({
7274
+ configPath: globalOpts.config,
7275
+ category: opts.category,
7276
+ noRoadmap: opts.roadmap === false,
7277
+ horizon: (() => {
7278
+ const h = parseInt(opts.horizon, 10);
7279
+ if (isNaN(h) || h < 1) throw new Error("--horizon must be a positive integer");
7280
+ return h;
7281
+ })()
7282
+ });
7283
+ if (mode === OutputMode.JSON) {
7284
+ console.log(JSON.stringify(result, null, 2));
7285
+ } else {
7286
+ printPredictionReport(result);
7287
+ }
7288
+ } catch (err) {
7289
+ const message = err instanceof Error ? err.message : String(err);
7290
+ if (err instanceof CLIError) {
7291
+ if (mode === OutputMode.JSON) {
7292
+ console.log(JSON.stringify({ error: message }));
7293
+ } else {
7294
+ logger.error(message);
7295
+ }
7296
+ process.exit(err.exitCode);
7297
+ }
7298
+ if (mode === OutputMode.JSON) {
7299
+ console.log(JSON.stringify({ error: message }));
7300
+ } else {
7301
+ logger.error(message);
7302
+ }
7303
+ process.exit(ExitCode.ERROR);
7304
+ }
7305
+ });
7306
+ return command;
7307
+ }
7308
+
7309
+ // src/commands/recommend.ts
7310
+ import { Command as Command72 } from "commander";
7311
+ import chalk10 from "chalk";
7312
+ async function runRecommend(options) {
7313
+ const cwd = options.cwd ?? process.cwd();
7314
+ const top = options.top ?? 5;
7315
+ let snapshot = null;
7316
+ let usedCache = false;
7317
+ if (!options.noCache) {
7318
+ const cached = loadCachedSnapshot(cwd);
7319
+ if (cached && isSnapshotFresh(cached, cwd)) {
7320
+ snapshot = cached;
7321
+ usedCache = true;
7322
+ }
7323
+ }
7324
+ if (!snapshot) {
7325
+ snapshot = await captureHealthSnapshot(cwd);
7326
+ }
7327
+ const configResult = resolveConfig();
7328
+ const tierOverrides = configResult.ok ? configResult.value.skills?.tierOverrides : void 0;
7329
+ const index = loadOrRebuildIndex("claude-code", cwd, tierOverrides);
7330
+ const skills = {};
7331
+ for (const [name, entry] of Object.entries(index.skills)) {
7332
+ skills[name] = { addresses: entry.addresses, dependsOn: entry.dependsOn };
7333
+ }
7334
+ const result = recommend(snapshot, skills, { top });
7335
+ return {
7336
+ ...result,
7337
+ snapshotAge: usedCache ? "cached" : "fresh"
7338
+ };
7339
+ }
7340
+ function formatRecommendation(rec) {
7341
+ const lines = [];
7342
+ if (rec.urgency === "critical") {
7343
+ lines.push(` ${chalk10.red("[CRITICAL]")} ${rec.sequence}. ${rec.skillName}`);
7344
+ } else {
7345
+ lines.push(` ${rec.sequence}. ${rec.skillName} (${rec.score.toFixed(2)})`);
7346
+ }
7347
+ for (const reason of rec.reasons) {
7348
+ lines.push(` ${chalk10.dim("\u2192")} ${reason}`);
7349
+ }
7350
+ return lines.join("\n");
7351
+ }
7352
+ function printRecommendations(result) {
7353
+ if (result.recommendations.length === 0) {
7354
+ console.log("");
7355
+ console.log("No recommendations. Codebase health looks good!");
7356
+ console.log("");
7357
+ return;
7358
+ }
7359
+ console.log("");
7360
+ console.log(
7361
+ `Recommended workflow (${result.recommendations.length} skill${result.recommendations.length === 1 ? "" : "s"}):`
7362
+ );
7363
+ console.log("");
7364
+ for (const rec of result.recommendations) {
7365
+ console.log(formatRecommendation(rec));
7366
+ console.log("");
7367
+ }
7368
+ console.log(`Sequence reasoning: ${result.sequenceReasoning}`);
7369
+ console.log("");
7370
+ }
7371
+ function createRecommendCommand() {
7372
+ const command = new Command72("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) => {
7373
+ const globalOpts = cmd.optsWithGlobals();
7374
+ const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
7375
+ try {
7376
+ const top = parseInt(opts.top, 10);
7377
+ if (isNaN(top) || top < 1) {
7378
+ logger.error("--top must be a positive integer");
7379
+ process.exit(1);
7380
+ }
7381
+ if (mode === OutputMode.TEXT) {
7382
+ console.log("");
7383
+ console.log("Analyzing codebase health...");
7384
+ }
7385
+ const result = await runRecommend({
7386
+ noCache: opts.cache === false,
7387
+ top
7388
+ });
7389
+ if (mode === OutputMode.JSON) {
7390
+ console.log(JSON.stringify(result, null, 2));
7391
+ } else {
7392
+ printRecommendations(result);
7393
+ }
7394
+ } catch (err) {
7395
+ const message = err instanceof Error ? err.message : String(err);
7396
+ if (mode === OutputMode.JSON) {
7397
+ console.log(JSON.stringify({ error: message }));
7398
+ } else {
7399
+ logger.error(message);
7400
+ }
7401
+ process.exit(1);
7402
+ }
7403
+ });
7404
+ return command;
7405
+ }
7406
+
6989
7407
  // src/index.ts
6990
7408
  function createProgram() {
6991
- const program = new Command70();
7409
+ const program = new Command73();
6992
7410
  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");
6993
7411
  program.addCommand(createValidateCommand());
6994
7412
  program.addCommand(createCheckDepsCommand());
@@ -7035,6 +7453,9 @@ function createProgram() {
7035
7453
  program.addCommand(createUsageCommand());
7036
7454
  program.addCommand(createTaintCommand());
7037
7455
  program.addCommand(createScanConfigCommand());
7456
+ program.addCommand(createSnapshotCommand());
7457
+ program.addCommand(createPredictCommand());
7458
+ program.addCommand(createRecommendCommand());
7038
7459
  return program;
7039
7460
  }
7040
7461
 
@@ -7052,5 +7473,6 @@ export {
7052
7473
  runInstallConstraints,
7053
7474
  runUninstallConstraints,
7054
7475
  runUninstall,
7476
+ runSnapshotCapture,
7055
7477
  createProgram
7056
7478
  };