@harness-engineering/cli 6.0.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/{agents-md-OTKZE5HH.js → agents-md-XBJ6YOSW.js} +2 -2
  2. package/dist/{architecture-3VYDN7MQ.js → architecture-D7PWJDXA.js} +3 -3
  3. package/dist/{assess-project-27X2FSZZ.js → assess-project-ENSWO4AX.js} +1 -1
  4. package/dist/bin/harness-mcp.js +13 -13
  5. package/dist/bin/harness.js +23 -23
  6. package/dist/{check-phase-gate-IXLFZ6YH.js → check-phase-gate-GTYAJ2YL.js} +3 -3
  7. package/dist/{chunk-QHFXVVUY.js → chunk-54RE35Q7.js} +2 -2
  8. package/dist/{chunk-XNHKXELN.js → chunk-5VP4ZQ3F.js} +1 -1
  9. package/dist/{chunk-CTMHHMHQ.js → chunk-6SP665CR.js} +89 -2
  10. package/dist/{chunk-VRA64HYI.js → chunk-7IVIRKHD.js} +1 -1
  11. package/dist/{chunk-3H7JA24B.js → chunk-CAGNARCD.js} +6 -6
  12. package/dist/{chunk-BMNHLKBA.js → chunk-GUL75WAM.js} +2 -2
  13. package/dist/{chunk-IXGYIQSR.js → chunk-HQUQA5D7.js} +1 -1
  14. package/dist/{chunk-354MCPT3.js → chunk-I6YMJ7ZD.js} +3 -3
  15. package/dist/{chunk-IOJGLIEQ.js → chunk-ILKL5I4J.js} +17 -2
  16. package/dist/{chunk-D7QXGI6E.js → chunk-INT5MUQX.js} +1 -1
  17. package/dist/{chunk-6Y6M3AZA.js → chunk-N3S6JTRS.js} +2 -2
  18. package/dist/{chunk-VGDZAWCJ.js → chunk-N4VEUBJ5.js} +934 -377
  19. package/dist/{chunk-L5UKNGC5.js → chunk-NXTNLNIP.js} +2 -2
  20. package/dist/{chunk-EFWRZHZ7.js → chunk-P7DXQAKU.js} +82 -82
  21. package/dist/{chunk-MEIUXTFY.js → chunk-PQBSP5AO.js} +1 -1
  22. package/dist/{chunk-TM4KFUWP.js → chunk-PYDUECJ3.js} +1 -1
  23. package/dist/{chunk-LISEPDVT.js → chunk-QB67FMZZ.js} +4 -4
  24. package/dist/{chunk-WAFTJFT3.js → chunk-TNR4BUWB.js} +3 -3
  25. package/dist/{chunk-KPBGAB35.js → chunk-UFZ6FMFC.js} +1 -1
  26. package/dist/{chunk-S2ETJDQJ.js → chunk-XRPHOCKU.js} +6 -6
  27. package/dist/{chunk-XF6RE3JQ.js → chunk-XYP5CIEN.js} +1 -1
  28. package/dist/{chunk-JJLOWMGC.js → chunk-YQK3GRW7.js} +1 -1
  29. package/dist/{chunk-3MKQKNY3.js → chunk-ZGK3JT4S.js} +5 -5
  30. package/dist/{ci-workflow-Y5GBKNZP.js → ci-workflow-ZODLVH62.js} +2 -2
  31. package/dist/{dist-4CZLCE33.js → dist-DTXVNQAY.js} +1 -1
  32. package/dist/{docs-3MWDPK4S.js → docs-ZU2HJCKW.js} +3 -3
  33. package/dist/{engine-RJXQ5DHK.js → engine-2DAJGPFZ.js} +2 -2
  34. package/dist/{entropy-OX5LSM4S.js → entropy-6JK3TCWY.js} +3 -3
  35. package/dist/{feedback-OODAP2G2.js → feedback-GEVH6CY3.js} +1 -1
  36. package/dist/{generate-agent-definitions-CCREQZEA.js → generate-agent-definitions-4DULEX3H.js} +3 -3
  37. package/dist/index.d.ts +90 -0
  38. package/dist/index.js +23 -23
  39. package/dist/{loader-ZICOJBVX.js → loader-K3A4YKWA.js} +2 -2
  40. package/dist/{mcp-XX6EIBLL.js → mcp-5MEIUQLV.js} +13 -13
  41. package/dist/{performance-OLZVGMAY.js → performance-HUXOQW7Q.js} +3 -3
  42. package/dist/{review-pipeline-3QPHMWPC.js → review-pipeline-QEYZXEMW.js} +2 -2
  43. package/dist/{runtime-ZFFIH76Z.js → runtime-45A4EGZD.js} +2 -2
  44. package/dist/{security-7YW3UK2C.js → security-CLZZRKND.js} +1 -1
  45. package/dist/{state-events-PTWAEGJ2.js → state-events-YLQEYOLI.js} +2 -2
  46. package/dist/{validate-H5SB7X3Z.js → validate-35GZKAOF.js} +3 -3
  47. package/dist/{validate-cross-check-YYVYMSPA.js → validate-cross-check-QJGCDWRO.js} +2 -2
  48. package/package.json +8 -8
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  generateRuntime
3
- } from "./chunk-TM4KFUWP.js";
3
+ } from "./chunk-PYDUECJ3.js";
4
4
  import {
5
5
  generateAgentsMd
6
- } from "./chunk-VRA64HYI.js";
6
+ } from "./chunk-7IVIRKHD.js";
7
7
  import {
8
8
  generateCIWorkflow
9
- } from "./chunk-XF6RE3JQ.js";
9
+ } from "./chunk-XYP5CIEN.js";
10
10
  import {
11
11
  readHarnessState
12
- } from "./chunk-MEIUXTFY.js";
12
+ } from "./chunk-PQBSP5AO.js";
13
13
  import {
14
14
  runCrossCheck
15
- } from "./chunk-D7QXGI6E.js";
15
+ } from "./chunk-INT5MUQX.js";
16
16
  import {
17
17
  createGenerateAgentDefinitionsCommand,
18
18
  generateAgentDefinitions
19
- } from "./chunk-IXGYIQSR.js";
19
+ } from "./chunk-HQUQA5D7.js";
20
20
  import {
21
21
  toKebabCase
22
22
  } from "./chunk-KET4QQZB.js";
@@ -26,7 +26,7 @@ import {
26
26
  } from "./chunk-YYFSFSB3.js";
27
27
  import {
28
28
  TemplateEngine
29
- } from "./chunk-JJLOWMGC.js";
29
+ } from "./chunk-YQK3GRW7.js";
30
30
  import {
31
31
  generate,
32
32
  validate
@@ -37,7 +37,7 @@ import {
37
37
  import {
38
38
  listPersonas,
39
39
  loadPersona
40
- } from "./chunk-KPBGAB35.js";
40
+ } from "./chunk-UFZ6FMFC.js";
41
41
  import {
42
42
  runPersona
43
43
  } from "./chunk-GISMXMVL.js";
@@ -51,7 +51,7 @@ import {
51
51
  OutputFormatter,
52
52
  OutputMode,
53
53
  createCheckPhaseGateCommand
54
- } from "./chunk-6Y6M3AZA.js";
54
+ } from "./chunk-N3S6JTRS.js";
55
55
  import {
56
56
  appendFrameworkAgents,
57
57
  captureHealthSnapshot,
@@ -79,7 +79,7 @@ import {
79
79
  runSecurityCraft,
80
80
  runSpecCraft,
81
81
  runTestCraft
82
- } from "./chunk-EFWRZHZ7.js";
82
+ } from "./chunk-P7DXQAKU.js";
83
83
  import {
84
84
  VALID_PLATFORMS
85
85
  } from "./chunk-3ISINLYT.js";
@@ -108,7 +108,7 @@ import {
108
108
  BranchingConfigSchema,
109
109
  findConfigFile,
110
110
  resolveConfig
111
- } from "./chunk-IOJGLIEQ.js";
111
+ } from "./chunk-ILKL5I4J.js";
112
112
  import {
113
113
  logger
114
114
  } from "./chunk-EBJQ6N4M.js";
@@ -202,6 +202,7 @@ import {
202
202
  requestPeerReview,
203
203
  resolveConsent,
204
204
  resolveRoadmapStore,
205
+ resolveRoadmapStoreForFile,
205
206
  roadmapSourceExists,
206
207
  roadmapToShards,
207
208
  runAll,
@@ -226,7 +227,7 @@ import {
226
227
  writeConfig,
227
228
  writeLockfile,
228
229
  writeRegeneratedRoadmap
229
- } from "./chunk-CTMHHMHQ.js";
230
+ } from "./chunk-6SP665CR.js";
230
231
  import {
231
232
  CLI_VERSION
232
233
  } from "./chunk-BM3PWGXQ.js";
@@ -263,7 +264,7 @@ import {
263
264
  } from "./chunk-KFQGP6VL.js";
264
265
 
265
266
  // src/index.ts
266
- import { Command as Command133 } from "commander";
267
+ import { Command as Command134 } from "commander";
267
268
 
268
269
  // src/commands/add.ts
269
270
  init_dist3();
@@ -454,7 +455,7 @@ function registerSkillsCommand(adoption) {
454
455
  const globalOpts = cmd.optsWithGlobals();
455
456
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
456
457
  const cwd = process.cwd();
457
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-4CZLCE33.js");
458
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-DTXVNQAY.js");
458
459
  const records = readAdoptionRecords(cwd);
459
460
  if (records.length === 0) {
460
461
  if (globalOpts.json) {
@@ -490,7 +491,7 @@ function registerRecentCommand(adoption) {
490
491
  const globalOpts = cmd.optsWithGlobals();
491
492
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
492
493
  const cwd = process.cwd();
493
- const { readAdoptionRecords } = await import("./dist-4CZLCE33.js");
494
+ const { readAdoptionRecords } = await import("./dist-DTXVNQAY.js");
494
495
  const records = readAdoptionRecords(cwd);
495
496
  if (records.length === 0) {
496
497
  if (globalOpts.json) {
@@ -568,7 +569,7 @@ function registerSkillCommand(adoption) {
568
569
  adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
569
570
  const globalOpts = cmd.optsWithGlobals();
570
571
  const cwd = process.cwd();
571
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-4CZLCE33.js");
572
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-DTXVNQAY.js");
572
573
  const records = readAdoptionRecords(cwd);
573
574
  const skillRecords = records.filter((r) => r.skill === name);
574
575
  if (skillRecords.length === 0) {
@@ -602,7 +603,7 @@ function registerRetrospectiveCommand(adoption) {
602
603
  adoption.command("retrospective").description("Generate a catalog retrospective from adoption telemetry").option("--inactive-days <n>", "Inactivity threshold in days (default: 90)", "90").option("--top <n>", "Rows per ranked section (default: 10)", "10").option("--out <path>", "Output file path (default: docs/retrospectives/YYYY-MM-DD.md)").option("--no-write", "Print the report to stdout instead of writing a file").action(async (opts, cmd) => {
603
604
  const globalOpts = cmd.optsWithGlobals();
604
605
  const cwd = process.cwd();
605
- const { readAdoptionRecords, getCatalogRetrospectiveReport, renderRetrospectiveMarkdown } = await import("./dist-4CZLCE33.js");
606
+ const { readAdoptionRecords, getCatalogRetrospectiveReport, renderRetrospectiveMarkdown } = await import("./dist-DTXVNQAY.js");
606
607
  const records = readAdoptionRecords(cwd);
607
608
  const catalogSkills = discoverCatalogSkills(cwd);
608
609
  const report = getCatalogRetrospectiveReport(records, {
@@ -1750,9 +1751,9 @@ ${name} (${count} finding${count === 1 ? "" : "s"})`);
1750
1751
  }
1751
1752
  function printAnatomyFindings(findings, verbose) {
1752
1753
  const byFile = groupByFile(findings, (f) => f.file);
1753
- for (const [file, fs51] of byFile) {
1754
+ for (const [file, fs52] of byFile) {
1754
1755
  console.log(` ${file}`);
1755
- for (const f of fs51) {
1756
+ for (const f of fs52) {
1756
1757
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1757
1758
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1758
1759
  if (verbose) {
@@ -1763,9 +1764,9 @@ function printAnatomyFindings(findings, verbose) {
1763
1764
  }
1764
1765
  function printCraftFindings(findings, verbose) {
1765
1766
  const byFile = groupByFile(findings, (f) => f.target.file);
1766
- for (const [file, fs51] of byFile) {
1767
+ for (const [file, fs52] of byFile) {
1767
1768
  console.log(` ${file}`);
1768
- for (const f of fs51) {
1769
+ for (const f of fs52) {
1769
1770
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
1770
1771
  const sev = craftTierToSeverity(f.tier);
1771
1772
  console.log(
@@ -1779,9 +1780,9 @@ function printCraftFindings(findings, verbose) {
1779
1780
  }
1780
1781
  function printDriftFindings(findings, verbose) {
1781
1782
  const byFile = groupByFile(findings, (f) => f.file);
1782
- for (const [file, fs51] of byFile) {
1783
+ for (const [file, fs52] of byFile) {
1783
1784
  console.log(` ${file}`);
1784
- for (const f of fs51) {
1785
+ for (const f of fs52) {
1785
1786
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1786
1787
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1787
1788
  if (verbose) {
@@ -1792,9 +1793,9 @@ function printDriftFindings(findings, verbose) {
1792
1793
  }
1793
1794
  function printBrandFindings(findings, verbose) {
1794
1795
  const byFile = groupByFile(findings, (f) => f.file);
1795
- for (const [file, fs51] of byFile) {
1796
+ for (const [file, fs52] of byFile) {
1796
1797
  console.log(` ${file}`);
1797
- for (const f of fs51) {
1798
+ for (const f of fs52) {
1798
1799
  const line = f.line !== null && f.line !== void 0 ? `:${f.line}` : "";
1799
1800
  console.log(` ${f.code} [${f.severity}] line${line}: ${f.message}`);
1800
1801
  if (verbose) {
@@ -2203,10 +2204,10 @@ async function runCheckSecurity(cwd, options) {
2203
2204
  const projectRoot3 = path11.resolve(cwd);
2204
2205
  let configData = {};
2205
2206
  try {
2206
- const fs51 = await import("fs");
2207
+ const fs52 = await import("fs");
2207
2208
  const configPath = path11.join(projectRoot3, "harness.config.json");
2208
- if (fs51.existsSync(configPath)) {
2209
- const raw = fs51.readFileSync(configPath, "utf-8");
2209
+ if (fs52.existsSync(configPath)) {
2210
+ const raw = fs52.readFileSync(configPath, "utf-8");
2210
2211
  const parsed = JSON.parse(raw);
2211
2212
  configData = parsed.security ?? {};
2212
2213
  }
@@ -3239,10 +3240,10 @@ function printResult2(result, mode, _formatter) {
3239
3240
  list.push(f);
3240
3241
  bySurface.set(f.target.surface, list);
3241
3242
  }
3242
- for (const [surface, fs51] of bySurface) {
3243
+ for (const [surface, fs52] of bySurface) {
3243
3244
  console.log(`
3244
3245
  [${surface}]`);
3245
- for (const f of fs51) {
3246
+ for (const f of fs52) {
3246
3247
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
3247
3248
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.file}${line}`);
3248
3249
  console.log(` "${truncate(f.target.snippet, 80)}"`);
@@ -4548,11 +4549,11 @@ import { Command as Command37 } from "commander";
4548
4549
  // src/commands/graph/status.ts
4549
4550
  import * as path19 from "path";
4550
4551
  async function readConnectorSyncStatus(graphDir) {
4551
- const fs51 = await import("fs/promises");
4552
+ const fs52 = await import("fs/promises");
4552
4553
  const result = {};
4553
4554
  try {
4554
4555
  const syncMetaPath = path19.join(graphDir, "sync-metadata.json");
4555
- const syncMeta = JSON.parse(await fs51.readFile(syncMetaPath, "utf-8"));
4556
+ const syncMeta = JSON.parse(await fs52.readFile(syncMetaPath, "utf-8"));
4556
4557
  for (const [name, data] of Object.entries(syncMeta.connectors ?? {})) {
4557
4558
  result[name] = data.lastSyncTimestamp;
4558
4559
  }
@@ -4699,9 +4700,9 @@ import { Command as Command36 } from "commander";
4699
4700
  import * as path22 from "path";
4700
4701
  async function loadConnectorConfig(projectPath, source) {
4701
4702
  try {
4702
- const fs51 = await import("fs/promises");
4703
+ const fs52 = await import("fs/promises");
4703
4704
  const configPath = path22.join(projectPath, "harness.config.json");
4704
- const config = JSON.parse(await fs51.readFile(configPath, "utf-8"));
4705
+ const config = JSON.parse(await fs52.readFile(configPath, "utf-8"));
4705
4706
  const connector = config.graph?.connectors?.[source];
4706
4707
  return connector ?? {};
4707
4708
  } catch {
@@ -6203,7 +6204,7 @@ function createInsightsCommand() {
6203
6204
  return new Command46("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) => {
6204
6205
  const cwd = process.cwd();
6205
6206
  const skip = parseSkip2(opts.skip);
6206
- const { composeInsights } = await import("./dist-4CZLCE33.js");
6207
+ const { composeInsights } = await import("./dist-DTXVNQAY.js");
6207
6208
  const report = await composeInsights(cwd, { skip });
6208
6209
  if (opts.json) {
6209
6210
  console.log(JSON.stringify(report, null, 2));
@@ -7375,10 +7376,10 @@ function printResult3(result, mode, _formatter) {
7375
7376
  list.push(f);
7376
7377
  byFile.set(f.target.file, list);
7377
7378
  }
7378
- for (const [file, fs51] of byFile) {
7379
+ for (const [file, fs52] of byFile) {
7379
7380
  console.log(`
7380
7381
  ${file}`);
7381
- for (const f of fs51) {
7382
+ for (const f of fs52) {
7382
7383
  console.log(` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.relative}`);
7383
7384
  console.log(` ${f.message}`);
7384
7385
  if (verbose) console.log(` source: ${f.cite.source}`);
@@ -7561,8 +7562,8 @@ function createKnowledgePipelineCommand() {
7561
7562
  const projectDir = process.cwd();
7562
7563
  try {
7563
7564
  const graphDir = path42.join(projectDir, ".harness", "graph");
7564
- const fs51 = await import("fs/promises");
7565
- await fs51.mkdir(graphDir, { recursive: true });
7565
+ const fs52 = await import("fs/promises");
7566
+ await fs52.mkdir(graphDir, { recursive: true });
7566
7567
  const { GraphStore: GraphStore2, KnowledgePipelineRunner } = await import("./dist-DWBTZXR5.js");
7567
7568
  const store = new GraphStore2();
7568
7569
  try {
@@ -8314,7 +8315,7 @@ function createMcpCommand() {
8314
8315
  parseBudget
8315
8316
  ).action(async (opts) => {
8316
8317
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
8317
- import("./mcp-XX6EIBLL.js"),
8318
+ import("./mcp-5MEIUQLV.js"),
8318
8319
  import("./tool-tiers-OKK5FE57.js")
8319
8320
  ]);
8320
8321
  if (opts.tools && opts.tools.length > 0) {
@@ -9395,10 +9396,10 @@ function printResult4(result, mode, _formatter) {
9395
9396
  list.push(f);
9396
9397
  byFile.set(f.target.file, list);
9397
9398
  }
9398
- for (const [file, fs51] of byFile) {
9399
+ for (const [file, fs52] of byFile) {
9399
9400
  console.log(`
9400
9401
  ${file}`);
9401
- for (const f of fs51) {
9402
+ for (const f of fs52) {
9402
9403
  const line = f.target.line !== void 0 ? `:${f.target.line}` : "";
9403
9404
  console.log(
9404
9405
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.kind} ${f.target.identifier}${line}`
@@ -9550,7 +9551,7 @@ function registerBenchCommand(perf) {
9550
9551
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
9551
9552
  const globalOpts = cmd.optsWithGlobals();
9552
9553
  const cwd = process.cwd();
9553
- const { BenchmarkRunner } = await import("./dist-4CZLCE33.js");
9554
+ const { BenchmarkRunner } = await import("./dist-DTXVNQAY.js");
9554
9555
  const runner = new BenchmarkRunner();
9555
9556
  const benchFiles = runner.discover(cwd, glob2);
9556
9557
  if (benchFiles.length === 0) {
@@ -9614,7 +9615,7 @@ async function runBaselinesShow(globalOpts) {
9614
9615
  }
9615
9616
  async function runBaselinesUpdate(globalOpts) {
9616
9617
  const cwd = process.cwd();
9617
- const { BenchmarkRunner } = await import("./dist-4CZLCE33.js");
9618
+ const { BenchmarkRunner } = await import("./dist-DTXVNQAY.js");
9618
9619
  const runner = new BenchmarkRunner();
9619
9620
  const manager = new BaselineManager(cwd);
9620
9621
  logger.info("Running benchmarks to update baselines...");
@@ -9655,7 +9656,7 @@ function registerReportCommand(perf) {
9655
9656
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
9656
9657
  const globalOpts = cmd.optsWithGlobals();
9657
9658
  const cwd = process.cwd();
9658
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-4CZLCE33.js");
9659
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-DTXVNQAY.js");
9659
9660
  const analyzer = new EntropyAnalyzer2({
9660
9661
  rootDir: path51.resolve(cwd),
9661
9662
  analyze: { complexity: true, coupling: true }
@@ -10323,11 +10324,11 @@ var defaultPostBrief = (body) => {
10323
10324
  }
10324
10325
  );
10325
10326
  };
10326
- var defaultReadFile = (path81) => readFileSync18(path81, "utf-8");
10327
- function readReview(path81, readFile4 = defaultReadFile) {
10328
- if (!path81) return void 0;
10327
+ var defaultReadFile = (path82) => readFileSync18(path82, "utf-8");
10328
+ function readReview(path82, readFile4 = defaultReadFile) {
10329
+ if (!path82) return void 0;
10329
10330
  try {
10330
- const parsed = JSON.parse(readFile4(path81));
10331
+ const parsed = JSON.parse(readFile4(path82));
10331
10332
  return parsed?.verdict && typeof parsed.verdict === "object" ? parsed.verdict : void 0;
10332
10333
  } catch {
10333
10334
  return void 0;
@@ -10678,7 +10679,7 @@ async function runPublishAnalyses(opts) {
10678
10679
  const nameToExternalId = await buildNameToExternalIdMap(projectPath);
10679
10680
  if (!nameToExternalId) return process.exit(1);
10680
10681
  const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
10681
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-4CZLCE33.js");
10682
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-DTXVNQAY.js");
10682
10683
  const archive = new AnalysisArchive(path53.join(projectPath, ".harness", "analyses"));
10683
10684
  const analyses = await archive.list();
10684
10685
  if (analyses.length === 0) {
@@ -10918,7 +10919,7 @@ function createRecommendCommand() {
10918
10919
  }
10919
10920
 
10920
10921
  // src/commands/roadmap/index.ts
10921
- import { Command as Command89 } from "commander";
10922
+ import { Command as Command90 } from "commander";
10922
10923
 
10923
10924
  // src/commands/roadmap/migrate.ts
10924
10925
  init_dist3();
@@ -11374,17 +11375,17 @@ import * as path56 from "path";
11374
11375
  import * as fsp from "fs/promises";
11375
11376
  function createNodeShardIO() {
11376
11377
  return {
11377
- readFile: (path81) => fsp.readFile(path81, "utf-8"),
11378
- writeFile: (path81, data) => fsp.writeFile(path81, data, "utf-8"),
11378
+ readFile: (path82) => fsp.readFile(path82, "utf-8"),
11379
+ writeFile: (path82, data) => fsp.writeFile(path82, data, "utf-8"),
11379
11380
  listDir: (dir) => fsp.readdir(dir),
11380
- deleteFile: (path81) => fsp.rm(path81),
11381
+ deleteFile: (path82) => fsp.rm(path82),
11381
11382
  mkdirp: async (dir) => {
11382
11383
  await fsp.mkdir(dir, { recursive: true });
11383
11384
  },
11384
- rmrf: (path81) => fsp.rm(path81, { recursive: true, force: true }),
11385
- exists: async (path81) => {
11385
+ rmrf: (path82) => fsp.rm(path82, { recursive: true, force: true }),
11386
+ exists: async (path82) => {
11386
11387
  try {
11387
- await fsp.access(path81);
11388
+ await fsp.access(path82);
11388
11389
  return true;
11389
11390
  } catch {
11390
11391
  return false;
@@ -11769,22 +11770,570 @@ function createRoadmapReferencedIssuesCommand() {
11769
11770
  });
11770
11771
  }
11771
11772
 
11773
+ // src/commands/roadmap/triage.ts
11774
+ init_dist3();
11775
+ import { Command as Command89 } from "commander";
11776
+ import * as fs36 from "fs";
11777
+ import * as path60 from "path";
11778
+ import {
11779
+ triageIssue,
11780
+ rankTriageCandidates,
11781
+ runBrainstormForIssue,
11782
+ markApprovedForDispatch,
11783
+ precedentLookupFromStored
11784
+ } from "@harness-engineering/orchestrator";
11785
+
11786
+ // src/commands/roadmap/triage-provider.ts
11787
+ import {
11788
+ AnthropicAnalysisProvider,
11789
+ OpenAICompatibleAnalysisProvider as OpenAICompatibleAnalysisProvider2
11790
+ } from "@harness-engineering/intelligence";
11791
+ function firstModel(model) {
11792
+ if (Array.isArray(model)) return model[0];
11793
+ return model;
11794
+ }
11795
+ function resolveTriageProvider(config, modelOverride) {
11796
+ const explicit = config?.intelligence?.provider;
11797
+ if (explicit) {
11798
+ if (explicit.kind === "anthropic") {
11799
+ const apiKey = explicit.apiKey ?? process.env.ANTHROPIC_API_KEY;
11800
+ if (!apiKey) return null;
11801
+ const model2 = modelOverride ?? explicit.model;
11802
+ return new AnthropicAnalysisProvider(
11803
+ model2 !== void 0 ? { apiKey, defaultModel: model2 } : { apiKey }
11804
+ );
11805
+ }
11806
+ const baseUrl = explicit.baseUrl ?? "http://localhost:11434/v1";
11807
+ const model = modelOverride ?? explicit.model;
11808
+ return new OpenAICompatibleAnalysisProvider2({
11809
+ apiKey: explicit.apiKey ?? "ollama",
11810
+ baseUrl,
11811
+ ...model !== void 0 && { defaultModel: model }
11812
+ });
11813
+ }
11814
+ const backends = config?.agent?.backends;
11815
+ if (!backends) return null;
11816
+ const local = pickBackend(backends, ["local", "pi"]);
11817
+ if (local && local.endpoint) {
11818
+ const model = modelOverride ?? firstModel(local.model);
11819
+ return new OpenAICompatibleAnalysisProvider2({
11820
+ apiKey: local.apiKey ?? "ollama",
11821
+ baseUrl: local.endpoint,
11822
+ ...model !== void 0 && { defaultModel: model },
11823
+ ...local.timeoutMs !== void 0 && { timeoutMs: local.timeoutMs }
11824
+ });
11825
+ }
11826
+ const anthropic = pickBackend(backends, ["anthropic"]);
11827
+ if (anthropic) {
11828
+ const apiKey = anthropic.apiKey ?? process.env.ANTHROPIC_API_KEY;
11829
+ if (!apiKey) return null;
11830
+ const model = modelOverride ?? firstModel(anthropic.model);
11831
+ return new AnthropicAnalysisProvider(
11832
+ model !== void 0 ? { apiKey, defaultModel: model } : { apiKey }
11833
+ );
11834
+ }
11835
+ return null;
11836
+ }
11837
+ function pickBackend(backends, types) {
11838
+ for (const def of Object.values(backends)) {
11839
+ if (def.type !== void 0 && types.includes(def.type)) return def;
11840
+ }
11841
+ return null;
11842
+ }
11843
+
11844
+ // src/commands/roadmap/triage-approve.ts
11845
+ import {
11846
+ detectScopeTier,
11847
+ artifactPresenceFromIssue
11848
+ } from "@harness-engineering/orchestrator";
11849
+ import {
11850
+ resolveGoNoGoStaged,
11851
+ resolveStage,
11852
+ dispatchableShapeKey,
11853
+ V1_MAX_STAGE
11854
+ } from "@harness-engineering/intelligence";
11855
+
11856
+ // src/commands/roadmap/triage-feature.ts
11857
+ function isActionable(feature) {
11858
+ return feature.status === "planned" || feature.status === "backlog";
11859
+ }
11860
+ function featureToIssue(feature) {
11861
+ return {
11862
+ id: feature.name,
11863
+ identifier: feature.name,
11864
+ title: feature.name,
11865
+ description: feature.summary,
11866
+ priority: null,
11867
+ state: feature.status,
11868
+ branchName: null,
11869
+ url: null,
11870
+ labels: [],
11871
+ blockedBy: feature.blockedBy.map((b) => ({ id: b, identifier: b, state: null })),
11872
+ spec: feature.spec,
11873
+ plans: feature.plans,
11874
+ createdAt: null,
11875
+ updatedAt: feature.updatedAt ?? null,
11876
+ externalId: feature.externalId ?? null,
11877
+ assignee: feature.assignee ?? null
11878
+ };
11879
+ }
11880
+
11881
+ // src/commands/roadmap/triage-approve.ts
11882
+ function deriveReadyCandidates(rows, roadmap) {
11883
+ const featureByExternalId = new Map(
11884
+ roadmap.milestones.flatMap((m) => m.features).filter((f) => f.externalId != null).map((f) => [f.externalId, f])
11885
+ );
11886
+ const ready = [];
11887
+ for (const row of rows) {
11888
+ if (row.result.outcome.kind !== "completed") continue;
11889
+ if (!row.result.specPath) continue;
11890
+ const rescore = row.result.rescore;
11891
+ if (!rescore || !rescore.dispatchable) continue;
11892
+ const feature = featureByExternalId.get(row.externalId);
11893
+ if (!feature || !isActionable(feature)) continue;
11894
+ const issue = featureToIssue({ ...feature, spec: row.result.specPath });
11895
+ const category = detectScopeTier(issue, artifactPresenceFromIssue(issue));
11896
+ const v = rescore.verdict;
11897
+ ready.push({
11898
+ externalId: row.externalId,
11899
+ featureName: feature.name,
11900
+ specPath: row.result.specPath,
11901
+ category,
11902
+ level: v.level,
11903
+ confidence: v.confidence,
11904
+ signals: v.signals,
11905
+ source: v.source,
11906
+ // scopeEstimate: the resolved-entity blast radius from the scope lever, when present.
11907
+ scopeEstimate: scopeEstimateOf(rescore),
11908
+ // Roadmap features carry no labels today, so this is always `[]`. The shapeKey
11909
+ // buckets on empty labels for now (Phase-4 calibration note): if/when labels land,
11910
+ // this is the single place to feed them into the precedent/ratchet bucket.
11911
+ labels: []
11912
+ });
11913
+ }
11914
+ return ready;
11915
+ }
11916
+ function scopeEstimateOf(rescore) {
11917
+ const scope = rescore?.levers.scope.value;
11918
+ if (scope && scope !== "unknown") return scope.blastRadius;
11919
+ return 0;
11920
+ }
11921
+ function shapeKeyForCandidate(r) {
11922
+ return dispatchableShapeKey(r.labels, r.level);
11923
+ }
11924
+ function resolveEffectiveStage(history, ceiling) {
11925
+ const earned = resolveStage(history);
11926
+ return Math.min(earned, ceiling, V1_MAX_STAGE);
11927
+ }
11928
+ function buildApprovalPlan(ready, opts) {
11929
+ const historyForShape = opts.historyForShape ?? (() => []);
11930
+ const candidates = ready.map((r) => ({
11931
+ externalId: r.externalId,
11932
+ category: r.category,
11933
+ humanApproved: opts.approveAll === true || opts.approvedIds.has(r.externalId),
11934
+ // Per-shape evidence-derived stage, ceilinged by config + hard-capped at 2 (SC6).
11935
+ effectiveStage: resolveEffectiveStage(historyForShape(shapeKeyForCandidate(r)), opts.stage)
11936
+ }));
11937
+ const decision = resolveGoNoGoStaged(candidates);
11938
+ const byId = new Map(ready.map((r) => [r.externalId, r]));
11939
+ const toMark = decision.approved.map((c) => {
11940
+ const r = byId.get(c.externalId);
11941
+ return {
11942
+ candidate: c,
11943
+ featureName: r.featureName,
11944
+ specPath: r.specPath,
11945
+ labels: r.labels,
11946
+ verdict: { level: r.level, confidence: r.confidence, signals: r.signals, source: r.source },
11947
+ scopeEstimate: r.scopeEstimate,
11948
+ // The per-shape earned stage the marker stamps onto the prediction (SC6).
11949
+ effectiveStage: c.effectiveStage
11950
+ };
11951
+ });
11952
+ const held = decision.held.map((h) => ({ externalId: h.externalId, reason: h.reason }));
11953
+ return { toMark, held };
11954
+ }
11955
+
11956
+ // src/commands/roadmap/triage.ts
11957
+ var CONFIDENCE_SCORE = { low: 1, medium: 2, high: 3 };
11958
+ var EFFORT_BY_LEVEL = { trivial: 1, simple: 2, moderate: 3, complex: 4 };
11959
+ var IMPACT_BY_PRIORITY = { P0: 4, P1: 3, P2: 2, P3: 1 };
11960
+ function rankingInputs(feature, verdict) {
11961
+ return {
11962
+ impact: feature.priority ? IMPACT_BY_PRIORITY[feature.priority] ?? 2 : 2,
11963
+ confidence: CONFIDENCE_SCORE[verdict.verdict.confidence],
11964
+ effort: EFFORT_BY_LEVEL[verdict.verdict.level] ?? 3
11965
+ };
11966
+ }
11967
+ async function buildPrecedentLookup(cwd) {
11968
+ const loaded = await event_sourcing_exports.loadTriageRecords(cwd);
11969
+ if (!loaded.ok) return void 0;
11970
+ return precedentLookupFromStored(
11971
+ loaded.value.map((r) => ({
11972
+ shapeKey: r.shapeKey,
11973
+ ...r.outcome ? { outcome: { matched: r.outcome.matched } } : {}
11974
+ }))
11975
+ );
11976
+ }
11977
+ async function buildShapeHistory(cwd) {
11978
+ const loaded = await event_sourcing_exports.loadTriageRecords(cwd);
11979
+ const byShape = /* @__PURE__ */ new Map();
11980
+ if (loaded.ok) {
11981
+ for (const rec of loaded.value) {
11982
+ if (!rec.outcome) continue;
11983
+ const list = byShape.get(rec.shapeKey) ?? [];
11984
+ list.push({ matched: rec.outcome.matched, ts: rec.ts });
11985
+ byShape.set(rec.shapeKey, list);
11986
+ }
11987
+ }
11988
+ return (shapeKey) => byShape.get(shapeKey) ?? [];
11989
+ }
11990
+ async function runTriageReport(roadmap, deps = {}) {
11991
+ const features = roadmap.milestones.flatMap((m) => m.features).filter(isActionable);
11992
+ const rows = [];
11993
+ for (const feature of features) {
11994
+ const verdict = await triageIssue(featureToIssue(feature), {
11995
+ ...deps.graphStore ? { graphStore: deps.graphStore } : {},
11996
+ ...deps.precedent ? { precedent: deps.precedent } : {},
11997
+ ...deps.config ? { config: deps.config } : {}
11998
+ });
11999
+ rows.push({
12000
+ externalId: verdict.externalId,
12001
+ name: feature.name,
12002
+ status: feature.status,
12003
+ ...rankingInputs(feature, verdict),
12004
+ verdict
12005
+ });
12006
+ }
12007
+ return rankTriageCandidates(rows);
12008
+ }
12009
+ function renderHuman(rows) {
12010
+ if (rows.length === 0) return "No actionable roadmap items to triage.";
12011
+ const lines = [];
12012
+ lines.push(`Triaged ${rows.length} actionable item(s):
12013
+ `);
12014
+ for (const row of rows) {
12015
+ const v = row.verdict;
12016
+ const badge = v.dispatchable ? "\u2713 DISPATCHABLE" : `\u2717 HELD (${v.holdReason})`;
12017
+ lines.push(`${badge} ${row.name}`);
12018
+ lines.push(
12019
+ ` level=${v.verdict.level} confidence=${v.verdict.confidence} impact=${row.impact} effort=${row.effort}`
12020
+ );
12021
+ lines.push(` ${v.rationale}`);
12022
+ lines.push("");
12023
+ }
12024
+ const dispatchable = rows.filter((r) => r.verdict.dispatchable).length;
12025
+ lines.push(
12026
+ `${dispatchable}/${rows.length} dispatchable; ${rows.length - dispatchable} to human.`
12027
+ );
12028
+ return lines.join("\n");
12029
+ }
12030
+ function renderJson(rows) {
12031
+ return JSON.stringify(
12032
+ {
12033
+ count: rows.length,
12034
+ dispatchable: rows.filter((r) => r.verdict.dispatchable).length,
12035
+ items: rows.map((r) => ({
12036
+ externalId: r.externalId,
12037
+ name: r.name,
12038
+ status: r.status,
12039
+ dispatchable: r.verdict.dispatchable,
12040
+ holdReason: r.verdict.holdReason ?? null,
12041
+ level: r.verdict.verdict.level,
12042
+ confidence: r.verdict.verdict.confidence,
12043
+ impact: r.impact,
12044
+ effort: r.effort,
12045
+ pilotInputs: { impact: r.impact, confidence: r.confidence, effort: r.effort },
12046
+ levers: r.verdict.levers,
12047
+ rationale: r.verdict.rationale
12048
+ }))
12049
+ },
12050
+ null,
12051
+ 2
12052
+ );
12053
+ }
12054
+ async function runBrainstormReport(roadmap, deps = {}) {
12055
+ const features = roadmap.milestones.flatMap((m) => m.features).filter(isActionable);
12056
+ const rows = [];
12057
+ for (const feature of features) {
12058
+ const issue = featureToIssue(feature);
12059
+ const verdict = await triageIssue(issue, {
12060
+ ...deps.graphStore ? { graphStore: deps.graphStore } : {},
12061
+ ...deps.provider ? { provider: deps.provider } : {},
12062
+ ...deps.precedent ? { precedent: deps.precedent } : {},
12063
+ ...deps.config ? { config: deps.config } : {}
12064
+ });
12065
+ const level = verdict.verdict.level;
12066
+ const wiringDeps = {
12067
+ ...deps.generator ? { generator: deps.generator } : {},
12068
+ ...deps.provider ? { provider: deps.provider } : {},
12069
+ ...deps.generatorOptions ? { generatorOptions: deps.generatorOptions } : {},
12070
+ ...deps.docsRoot ? { docsRoot: deps.docsRoot } : {},
12071
+ // Re-score the enriched item on completion (SC4), reusing the same seams — the
12072
+ // precedent lever included so the RE-SCORE (the prediction the marker records) is
12073
+ // graded against real base-rates too (SC5).
12074
+ rescore: {
12075
+ ...deps.graphStore ? { graphStore: deps.graphStore } : {},
12076
+ ...deps.provider ? { provider: deps.provider } : {},
12077
+ ...deps.precedent ? { precedent: deps.precedent } : {},
12078
+ ...deps.config ? { config: deps.config } : {}
12079
+ }
12080
+ };
12081
+ const result = await runBrainstormForIssue(issue, level, wiringDeps);
12082
+ rows.push({
12083
+ externalId: verdict.externalId,
12084
+ name: feature.name,
12085
+ status: feature.status,
12086
+ level,
12087
+ result
12088
+ });
12089
+ }
12090
+ return rows;
12091
+ }
12092
+ function renderBrainstormHuman(rows) {
12093
+ if (rows.length === 0) return "No actionable roadmap items to brainstorm.";
12094
+ const lines = [];
12095
+ lines.push(`Brainstormed ${rows.length} actionable item(s):
12096
+ `);
12097
+ for (const row of rows) {
12098
+ const o = row.result.outcome;
12099
+ if (o.kind === "completed") {
12100
+ const where = row.result.specPath ? ` \u2192 ${row.result.specPath}` : " (dry run \u2014 no docs root)";
12101
+ lines.push(`\u2713 SPEC DRAFTED ${row.name} [${row.level}]${where}`);
12102
+ lines.push(` ${o.spec.decisions.length} fork(s) resolved at high confidence`);
12103
+ if (row.result.rescore) {
12104
+ const rv = row.result.rescore;
12105
+ lines.push(
12106
+ ` re-score: ${rv.dispatchable ? "DISPATCHABLE" : `held (${rv.holdReason})`} \u2014 ${rv.verdict.level}/${rv.verdict.confidence}`
12107
+ );
12108
+ }
12109
+ } else {
12110
+ lines.push(`\u2717 HALTED \u2192 HUMAN ${row.name} [${row.level}] (${o.reason})`);
12111
+ lines.push(` fork: ${o.fork.question || o.fork.id}`);
12112
+ lines.push(` ${o.detail}`);
12113
+ }
12114
+ lines.push("");
12115
+ }
12116
+ const completed = rows.filter((r) => r.result.outcome.kind === "completed").length;
12117
+ lines.push(
12118
+ `${completed}/${rows.length} spec(s) drafted; ${rows.length - completed} halted to human.`
12119
+ );
12120
+ return lines.join("\n");
12121
+ }
12122
+ function renderBrainstormJson(rows) {
12123
+ return JSON.stringify(
12124
+ {
12125
+ count: rows.length,
12126
+ drafted: rows.filter((r) => r.result.outcome.kind === "completed").length,
12127
+ items: rows.map((r) => {
12128
+ const o = r.result.outcome;
12129
+ return {
12130
+ externalId: r.externalId,
12131
+ name: r.name,
12132
+ status: r.status,
12133
+ level: r.level,
12134
+ outcome: o.kind,
12135
+ ...o.kind === "completed" ? {
12136
+ specPath: r.result.specPath ?? null,
12137
+ forks: o.spec.decisions.map((d) => ({
12138
+ id: d.fork.id,
12139
+ question: d.fork.question,
12140
+ recommendation: d.recommendation,
12141
+ confidence: d.confidence
12142
+ })),
12143
+ rescore: r.result.rescore ? {
12144
+ dispatchable: r.result.rescore.dispatchable,
12145
+ holdReason: r.result.rescore.holdReason ?? null,
12146
+ level: r.result.rescore.verdict.level,
12147
+ confidence: r.result.rescore.verdict.confidence
12148
+ } : null
12149
+ } : {
12150
+ halt: {
12151
+ reason: o.reason,
12152
+ fork: { id: o.fork.id, question: o.fork.question },
12153
+ detail: o.detail
12154
+ }
12155
+ }
12156
+ };
12157
+ })
12158
+ },
12159
+ null,
12160
+ 2
12161
+ );
12162
+ }
12163
+ function resolveBrainstormProvider(configPath, model) {
12164
+ const configResult = resolveConfig(configPath);
12165
+ if (!configResult.ok) return null;
12166
+ return resolveTriageProvider(configResult.value, model);
12167
+ }
12168
+ async function runApproveCommand(cwd, opts) {
12169
+ const configResult = resolveConfig(opts.config);
12170
+ const cfg = configResult.ok ? configResult.value : void 0;
12171
+ const autoTriage = cfg?.roadmap?.autoTriage;
12172
+ if (!autoTriage || autoTriage.enabled !== true) {
12173
+ return { marked: [], held: [], note: "disabled" };
12174
+ }
12175
+ const stage = autoTriage.ratchetStage ?? 1;
12176
+ const roadmapPath = path60.join(cwd, "docs", "roadmap.md");
12177
+ if (!fs36.existsSync(roadmapPath)) {
12178
+ return { marked: [], held: [], note: "no-roadmap" };
12179
+ }
12180
+ const parsed = parseRoadmap(fs36.readFileSync(roadmapPath, "utf-8"));
12181
+ if (!parsed.ok) return { marked: [], held: [], note: "roadmap-parse-error" };
12182
+ const graphStore = await loadGraphStore(cwd);
12183
+ const provider = resolveBrainstormProvider(opts.config);
12184
+ const precedent = await buildPrecedentLookup(cwd);
12185
+ const rows = await runBrainstormReport(parsed.value, {
12186
+ ...graphStore ? { graphStore } : {},
12187
+ ...provider ? { provider } : {},
12188
+ ...precedent ? { precedent } : {},
12189
+ docsRoot: path60.join(cwd, "docs")
12190
+ });
12191
+ const ready = deriveReadyCandidates(rows, parsed.value);
12192
+ const approvedIds = new Set(
12193
+ (opts.approve ?? "").split(",").map((s) => s.trim()).filter((s) => s.length > 0)
12194
+ );
12195
+ const historyForShape = await buildShapeHistory(cwd);
12196
+ const plan = buildApprovalPlan(ready, {
12197
+ approvedIds,
12198
+ ...opts.approveAll ? { approveAll: true } : {},
12199
+ stage,
12200
+ historyForShape
12201
+ });
12202
+ const store = resolveRoadmapStoreForFile({ roadmapPath });
12203
+ const recordPrediction = (payload) => event_sourcing_exports.recordTriagePrediction(cwd, payload);
12204
+ const result = await markApprovedForDispatch(plan.toMark, {
12205
+ store,
12206
+ config: { enabled: true, ratchetStage: stage },
12207
+ recordPrediction
12208
+ });
12209
+ if (!result.ok) {
12210
+ return { marked: [], held: plan.held, note: `mark-failed: ${result.error.message}` };
12211
+ }
12212
+ return { marked: result.value.marked, held: plan.held };
12213
+ }
12214
+ function renderApproveHuman(res) {
12215
+ if (res.note === "disabled") {
12216
+ return "Roadmap auto-triage is disabled (roadmap.autoTriage.enabled is not true). Enable it to use `triage approve`. No changes made.";
12217
+ }
12218
+ if (res.note === "no-roadmap") return "No roadmap aggregate at docs/roadmap.md. No changes made.";
12219
+ if (res.note === "roadmap-parse-error") return "Failed to parse roadmap. No changes made.";
12220
+ const lines = [];
12221
+ if (res.marked.length > 0) {
12222
+ lines.push(`Marked ${res.marked.length} item(s) eligible for orchestrator pickup:`);
12223
+ for (const id of res.marked) lines.push(` \u2713 ${id}`);
12224
+ } else {
12225
+ lines.push("No items marked.");
12226
+ }
12227
+ if (res.held.length > 0) {
12228
+ lines.push(`
12229
+ Held to human (${res.held.length}):`);
12230
+ for (const h of res.held) lines.push(` \u2717 ${h.externalId} \u2014 ${h.reason}`);
12231
+ }
12232
+ if (res.note && res.note.startsWith("mark-failed")) lines.push(`
12233
+ ERROR: ${res.note}`);
12234
+ lines.push(
12235
+ "\nApproved items are NOT dispatched here \u2014 the existing orchestrator pickup loop dispatches them through its normal gating on its next tick."
12236
+ );
12237
+ return lines.join("\n");
12238
+ }
12239
+ function createTriageApproveCommand() {
12240
+ return new Command89("approve").description(
12241
+ "Batched human go/no-go (autonomy ratchet stage 1): review READY candidates (Phase-2 spec-bearing, re-score dispatchable) and approve a subset. Approved + auto-executable items are MARKED eligible for the EXISTING orchestrator pickup \u2014 nothing is dispatched here, and nothing is marked without an explicit approval. Gated behind roadmap.autoTriage.enabled (default off)."
12242
+ ).option(
12243
+ "--approve <ids>",
12244
+ "Comma-separated externalIds to approve (the explicit human go). Omit to mark nothing."
12245
+ ).option("--approve-all", "Approve every READY candidate (still subject to the category gate).").action(async (opts, cmd) => {
12246
+ const cwd = process.cwd();
12247
+ const globalOpts = cmd.optsWithGlobals();
12248
+ const res = await runApproveCommand(cwd, {
12249
+ ...opts,
12250
+ ...globalOpts.config !== void 0 ? { config: globalOpts.config } : {}
12251
+ });
12252
+ if (globalOpts.json) {
12253
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
12254
+ } else {
12255
+ logger.info(renderApproveHuman(res));
12256
+ }
12257
+ });
12258
+ }
12259
+ function createRoadmapTriageCommand() {
12260
+ return new Command89("triage").description(
12261
+ "Read-only triage report: score every actionable roadmap item with the four-lever scoping probe and rank dispatchability. Gated behind roadmap.autoTriage.enabled (default off); never writes. Offline by default (holds to human without a live model). With --brainstorm, additionally run the autonomous brainstorm per candidate, emitting a drafted spec (docs only) or a halt handoff (fork + reason) \u2014 still no dispatch."
12262
+ ).option(
12263
+ "--brainstorm",
12264
+ "Run the autonomous brainstorm per candidate: draft a spec (docs only) or halt to a human at the first fork it can not confidently recommend. No dispatch, no execution."
12265
+ ).action(async (opts, cmd) => {
12266
+ const cwd = process.cwd();
12267
+ const globalOpts = cmd.optsWithGlobals();
12268
+ const configResult = resolveConfig(globalOpts.config);
12269
+ const enabled = configResult.ok && configResult.value.roadmap?.autoTriage?.enabled === true;
12270
+ if (!enabled) {
12271
+ logger.info(
12272
+ "Roadmap auto-triage is disabled (roadmap.autoTriage.enabled is not true). Enable it in harness.config.json to run the read-only triage report. No changes made."
12273
+ );
12274
+ return;
12275
+ }
12276
+ const roadmapPath = path60.join(cwd, "docs", "roadmap.md");
12277
+ if (!fs36.existsSync(roadmapPath)) {
12278
+ logger.error(
12279
+ `No roadmap aggregate at ${roadmapPath}. If your roadmap is sharded, run \`harness roadmap regen\` first, then re-run triage.`
12280
+ );
12281
+ process.exitCode = 1;
12282
+ return;
12283
+ }
12284
+ const parsed = parseRoadmap(fs36.readFileSync(roadmapPath, "utf-8"));
12285
+ if (!parsed.ok) {
12286
+ logger.error(`Failed to parse roadmap: ${parsed.error.message}`);
12287
+ process.exitCode = 1;
12288
+ return;
12289
+ }
12290
+ const graphStore = await loadGraphStore(cwd);
12291
+ const precedent = await buildPrecedentLookup(cwd);
12292
+ if (opts.brainstorm) {
12293
+ const provider = resolveBrainstormProvider(globalOpts.config);
12294
+ const rows2 = await runBrainstormReport(parsed.value, {
12295
+ ...graphStore ? { graphStore } : {},
12296
+ ...provider ? { provider } : {},
12297
+ ...precedent ? { precedent } : {},
12298
+ // Specs are written under docs/changes/<slug>/proposal.md (docs only, no dispatch).
12299
+ docsRoot: path60.join(cwd, "docs")
12300
+ });
12301
+ if (globalOpts.json) {
12302
+ process.stdout.write(renderBrainstormJson(rows2) + "\n");
12303
+ } else {
12304
+ logger.info(renderBrainstormHuman(rows2));
12305
+ }
12306
+ return;
12307
+ }
12308
+ const rows = await runTriageReport(parsed.value, {
12309
+ ...graphStore ? { graphStore } : {},
12310
+ ...precedent ? { precedent } : {}
12311
+ });
12312
+ if (globalOpts.json) {
12313
+ process.stdout.write(renderJson(rows) + "\n");
12314
+ } else {
12315
+ logger.info(renderHuman(rows));
12316
+ }
12317
+ }).addCommand(createTriageApproveCommand());
12318
+ }
12319
+
11772
12320
  // src/commands/roadmap/index.ts
11773
12321
  function createRoadmapCommand() {
11774
- const roadmap = new Command89("roadmap").description("Roadmap management");
12322
+ const roadmap = new Command90("roadmap").description("Roadmap management");
11775
12323
  roadmap.addCommand(createRoadmapMigrateCommand());
11776
12324
  roadmap.addCommand(createRoadmapShardCommand());
11777
12325
  roadmap.addCommand(createRoadmapUnshardCommand());
11778
12326
  roadmap.addCommand(createRoadmapRegenCommand());
11779
12327
  roadmap.addCommand(createRoadmapReconcileCommand());
11780
12328
  roadmap.addCommand(createRoadmapReferencedIssuesCommand());
12329
+ roadmap.addCommand(createRoadmapTriageCommand());
11781
12330
  return roadmap;
11782
12331
  }
11783
12332
 
11784
12333
  // src/commands/rollback.ts
11785
12334
  init_dist3();
11786
12335
  import { execFileSync as execFileSync10 } from "child_process";
11787
- import { Command as Command90, Option as Option3, InvalidArgumentError } from "commander";
12336
+ import { Command as Command91, Option as Option3, InvalidArgumentError } from "commander";
11788
12337
 
11789
12338
  // src/rollback/compose.ts
11790
12339
  var ROLLBACK_LABEL = "harness:rollback";
@@ -11842,12 +12391,12 @@ async function composeRevertPr(decision, originalTitle, opts) {
11842
12391
 
11843
12392
  // src/rollback/breadcrumb.ts
11844
12393
  import { appendFileSync, mkdirSync as mkdirSync19 } from "fs";
11845
- import { dirname as dirname20, join as join50 } from "path";
11846
- var ROLLBACK_EVENTS_FILE = join50(".harness", "signals", "rollback-events.jsonl");
12394
+ import { dirname as dirname20, join as join51 } from "path";
12395
+ var ROLLBACK_EVENTS_FILE = join51(".harness", "signals", "rollback-events.jsonl");
11847
12396
  async function appendRollbackEvent(event, opts = {}) {
11848
12397
  const root = opts.root ?? process.cwd();
11849
12398
  const ts = (opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))();
11850
- const file = join50(root, ROLLBACK_EVENTS_FILE);
12399
+ const file = join51(root, ROLLBACK_EVENTS_FILE);
11851
12400
  mkdirSync19(dirname20(file), { recursive: true });
11852
12401
  appendFileSync(file, `${JSON.stringify({ ...event, ts })}
11853
12402
  `, "utf-8");
@@ -11874,7 +12423,7 @@ async function linkRollbackEventToGraph(event, opts = {}) {
11874
12423
  if (target) {
11875
12424
  store.addEdge({ from: nodeId, to: target.id, type: "references" });
11876
12425
  }
11877
- await store.save(join50(root, ".harness", "graph"));
12426
+ await store.save(join51(root, ".harness", "graph"));
11878
12427
  } catch {
11879
12428
  }
11880
12429
  }
@@ -11906,8 +12455,8 @@ function parseConflictPaths(stdout) {
11906
12455
  if (line === void 0 || line.trim() === "") break;
11907
12456
  const tab = line.indexOf(" ");
11908
12457
  if (tab === -1) continue;
11909
- const path81 = line.slice(tab + 1).trim();
11910
- if (path81) paths.add(path81);
12458
+ const path82 = line.slice(tab + 1).trim();
12459
+ if (path82) paths.add(path82);
11911
12460
  }
11912
12461
  return [...paths];
11913
12462
  }
@@ -12153,7 +12702,7 @@ async function runRollbackSweepCommand(deps) {
12153
12702
  });
12154
12703
  }
12155
12704
  function createRollbackCommand() {
12156
- const rollback = new Command90("rollback").description(
12705
+ const rollback = new Command91("rollback").description(
12157
12706
  "Post-ship revert circuit breaker (propose-only in v1)"
12158
12707
  );
12159
12708
  rollback.command("evaluate").description("Classify a merged PR for revert-readiness and, if ready, propose a revert PR").requiredOption("--pr <n>", "target merged PR number", (v) => {
@@ -12206,10 +12755,10 @@ function createRollbackCommand() {
12206
12755
  }
12207
12756
 
12208
12757
  // src/commands/routing/index.ts
12209
- import { Command as Command96 } from "commander";
12758
+ import { Command as Command97 } from "commander";
12210
12759
 
12211
12760
  // src/commands/routing/config.ts
12212
- import { Command as Command91 } from "commander";
12761
+ import { Command as Command92 } from "commander";
12213
12762
 
12214
12763
  // src/commands/routing/http-client.ts
12215
12764
  function orchestratorBase() {
@@ -12219,9 +12768,9 @@ function authHeader() {
12219
12768
  const tok = process.env["HARNESS_API_TOKEN"];
12220
12769
  return tok ? { Authorization: `Bearer ${tok}` } : {};
12221
12770
  }
12222
- async function getJson(path81) {
12771
+ async function getJson(path82) {
12223
12772
  try {
12224
- const res = await fetch(`${orchestratorBase()}${path81}`, {
12773
+ const res = await fetch(`${orchestratorBase()}${path82}`, {
12225
12774
  headers: { ...authHeader() }
12226
12775
  });
12227
12776
  const text = await res.text();
@@ -12236,9 +12785,9 @@ async function getJson(path81) {
12236
12785
  };
12237
12786
  }
12238
12787
  }
12239
- async function postJson(path81, body) {
12788
+ async function postJson(path82, body) {
12240
12789
  try {
12241
- const res = await fetch(`${orchestratorBase()}${path81}`, {
12790
+ const res = await fetch(`${orchestratorBase()}${path82}`, {
12242
12791
  method: "POST",
12243
12792
  headers: { "Content-Type": "application/json", ...authHeader() },
12244
12793
  body: JSON.stringify(body)
@@ -12257,7 +12806,7 @@ async function postJson(path81, body) {
12257
12806
  }
12258
12807
 
12259
12808
  // src/commands/routing/config.ts
12260
- function renderHuman(data) {
12809
+ function renderHuman2(data) {
12261
12810
  console.log("Backends:");
12262
12811
  for (const b of data.backends) console.log(` - ${b}`);
12263
12812
  console.log("");
@@ -12274,7 +12823,7 @@ function renderHuman(data) {
12274
12823
  }
12275
12824
  }
12276
12825
  function createConfigCommand() {
12277
- return new Command91("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12826
+ return new Command92("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12278
12827
  const r = await getJson("/api/v1/routing/config");
12279
12828
  if (!r.ok) {
12280
12829
  if (r.status === 0) {
@@ -12295,12 +12844,12 @@ function createConfigCommand() {
12295
12844
  console.log(JSON.stringify(r.body, null, 2));
12296
12845
  return;
12297
12846
  }
12298
- if (r.body) renderHuman(r.body);
12847
+ if (r.body) renderHuman2(r.body);
12299
12848
  });
12300
12849
  }
12301
12850
 
12302
12851
  // src/commands/routing/trace.ts
12303
- import { Command as Command92 } from "commander";
12852
+ import { Command as Command93 } from "commander";
12304
12853
  var COMPLEXITY_VALUES = ["trivial", "simple", "moderate", "complex"];
12305
12854
  var RISK_VALUES = ["low", "high"];
12306
12855
  function validateEnum(flag, value, allowed) {
@@ -12314,20 +12863,28 @@ function buildUseCase(opts) {
12314
12863
  if (opts.mode) return { kind: "mode", cognitiveMode: opts.mode };
12315
12864
  return null;
12316
12865
  }
12317
- function renderHuman2(r) {
12318
- console.log(`Backend: ${r.decision.backendName} (type: ${r.def.type})`);
12866
+ function renderHuman3(r) {
12867
+ const amr = r.tierRequired !== void 0 && r.costedBackendName !== void 0;
12868
+ const backend = amr ? r.costedBackendName : r.decision.backendName;
12869
+ const type = amr && r.costedBackendType !== void 0 ? r.costedBackendType : r.def.type;
12870
+ console.log(`Backend: ${backend} (type: ${type})`);
12319
12871
  console.log(`Duration: ${r.decision.durationMs.toFixed(2)} ms`);
12320
12872
  console.log("Resolution path:");
12321
12873
  if (r.decision.resolutionPath.length === 0) {
12322
12874
  console.log(" (empty)");
12323
- return;
12324
- }
12325
- for (const step of r.decision.resolutionPath) {
12326
- console.log(` ${step.source}:${step.candidate} -> ${step.outcome}`);
12875
+ } else {
12876
+ for (const step of r.decision.resolutionPath) {
12877
+ console.log(` ${step.source}:${step.candidate} -> ${step.outcome}`);
12878
+ }
12327
12879
  }
12328
12880
  if (r.tierRequired !== void 0) {
12329
12881
  console.log(`Tier required: ${r.tierRequired}`);
12330
12882
  }
12883
+ if (amr && r.costedBackendName !== r.decision.backendName) {
12884
+ console.log(
12885
+ ` (AMR overrides the identity pick '${r.decision.backendName}' \u2192 cheapest backend at/above the tier)`
12886
+ );
12887
+ }
12331
12888
  if (r.estCostUsd !== void 0) {
12332
12889
  console.log(`Est cost: $${r.estCostUsd.toFixed(4)}`);
12333
12890
  }
@@ -12368,17 +12925,17 @@ async function runTrace(opts) {
12368
12925
  console.log(JSON.stringify(r.body, null, 2));
12369
12926
  return;
12370
12927
  }
12371
- if (r.body) renderHuman2(r.body);
12928
+ if (r.body) renderHuman3(r.body);
12372
12929
  }
12373
12930
  function createTraceCommand() {
12374
- return new Command92("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(
12931
+ return new Command93("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(
12375
12932
  "--complexity <level>",
12376
12933
  "Synthetic complexity (trivial|simple|moderate|complex) \u2014 dry-run only"
12377
12934
  ).option("--risk <band>", "Synthetic risk band (low|high) \u2014 dry-run only").option("--json", "Emit JSON to stdout instead of human-readable text").action(runTrace);
12378
12935
  }
12379
12936
 
12380
12937
  // src/commands/routing/decisions.ts
12381
- import { Command as Command93 } from "commander";
12938
+ import { Command as Command94 } from "commander";
12382
12939
  function summarizeUseCase(uc) {
12383
12940
  switch (uc.kind) {
12384
12941
  case "skill":
@@ -12402,7 +12959,7 @@ function shortIso(iso) {
12402
12959
  const tail = parts[1] ?? iso;
12403
12960
  return tail.replace("Z", "");
12404
12961
  }
12405
- function renderHuman3(data) {
12962
+ function renderHuman4(data) {
12406
12963
  if (data.decisions.length === 0) {
12407
12964
  console.log("(no decisions in buffer)");
12408
12965
  return;
@@ -12426,7 +12983,7 @@ function buildQuery(opts) {
12426
12983
  return q ? `?${q}` : "";
12427
12984
  }
12428
12985
  function createDecisionsCommand() {
12429
- return new Command93("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(
12986
+ return new Command94("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(
12430
12987
  async (opts) => {
12431
12988
  const query = buildQuery(opts);
12432
12989
  const r = await getJson(`/api/v1/routing/decisions${query}`);
@@ -12449,19 +13006,19 @@ function createDecisionsCommand() {
12449
13006
  console.log(JSON.stringify(r.body, null, 2));
12450
13007
  return;
12451
13008
  }
12452
- if (r.body) renderHuman3(r.body);
13009
+ if (r.body) renderHuman4(r.body);
12453
13010
  }
12454
13011
  );
12455
13012
  }
12456
13013
 
12457
13014
  // src/commands/routing/telemetry.ts
12458
- import { Command as Command94 } from "commander";
13015
+ import { Command as Command95 } from "commander";
12459
13016
  var TIERS = ["fast", "standard", "strong"];
12460
13017
  function shortIso2(iso) {
12461
13018
  const tail = iso.split("T")[1] ?? iso;
12462
13019
  return tail.replace("Z", "");
12463
13020
  }
12464
- function renderHuman4(data, tableLimit) {
13021
+ function renderHuman5(data, tableLimit) {
12465
13022
  if (data.decisions.length === 0) {
12466
13023
  console.log("(no routing telemetry \u2014 AMR is off or no decisions recorded yet)");
12467
13024
  return;
@@ -12499,7 +13056,7 @@ function renderHuman4(data, tableLimit) {
12499
13056
  }
12500
13057
  }
12501
13058
  function createTelemetryCommand() {
12502
- return new Command94("telemetry").description("Routing telemetry: per-decision tier/backend/cost + tier distribution (AMR)").option("--last <N>", "Show only the N most recent decisions in the per-decision table").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
13059
+ return new Command95("telemetry").description("Routing telemetry: per-decision tier/backend/cost + tier distribution (AMR)").option("--last <N>", "Show only the N most recent decisions in the per-decision table").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12503
13060
  const r = await getJson("/api/v1/routing/telemetry");
12504
13061
  if (!r.ok) {
12505
13062
  if (r.status === 0) {
@@ -12518,18 +13075,18 @@ function createTelemetryCommand() {
12518
13075
  return;
12519
13076
  }
12520
13077
  const tableLimit = opts.last && Number.isFinite(Number(opts.last)) && Number(opts.last) > 0 ? Math.floor(Number(opts.last)) : void 0;
12521
- renderHuman4(body, tableLimit);
13078
+ renderHuman5(body, tableLimit);
12522
13079
  });
12523
13080
  }
12524
13081
 
12525
13082
  // src/commands/routing/status.ts
12526
- import { Command as Command95 } from "commander";
13083
+ import { Command as Command96 } from "commander";
12527
13084
  function bar(pct, width = 24) {
12528
13085
  const clamped = Math.max(0, Math.min(100, pct));
12529
13086
  const filled = Math.round(clamped / 100 * width);
12530
13087
  return `[${"#".repeat(filled)}${"-".repeat(width - filled)}]`;
12531
13088
  }
12532
- function renderHuman5(s) {
13089
+ function renderHuman6(s) {
12533
13090
  if (!s.active) {
12534
13091
  console.log("Adaptive routing: OFF (no routing.policy configured \u2014 dispatch is unchanged)");
12535
13092
  return;
@@ -12563,7 +13120,7 @@ function renderHuman5(s) {
12563
13120
  );
12564
13121
  }
12565
13122
  function createStatusCommand() {
12566
- return new Command95("status").description(
13123
+ return new Command96("status").description(
12567
13124
  "Live routing status: budget spend-vs-cap, escalated units, provider allowlist (AMR)"
12568
13125
  ).option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12569
13126
  const r = await getJson("/api/v1/routing/status");
@@ -12588,13 +13145,13 @@ function createStatusCommand() {
12588
13145
  console.log(JSON.stringify(body, null, 2));
12589
13146
  return;
12590
13147
  }
12591
- renderHuman5(body);
13148
+ renderHuman6(body);
12592
13149
  });
12593
13150
  }
12594
13151
 
12595
13152
  // src/commands/routing/index.ts
12596
13153
  function createRoutingCommand() {
12597
- const cmd = new Command96("routing").description(
13154
+ const cmd = new Command97("routing").description(
12598
13155
  "Inspect routing config, trace decisions, and read AMR telemetry + status"
12599
13156
  );
12600
13157
  cmd.addCommand(createConfigCommand());
@@ -12607,9 +13164,9 @@ function createRoutingCommand() {
12607
13164
 
12608
13165
  // src/commands/scan-config.ts
12609
13166
  init_dist3();
12610
- import { Command as Command97 } from "commander";
12611
- import { existsSync as existsSync31, readFileSync as readFileSync22, writeFileSync as writeFileSync23 } from "fs";
12612
- import { join as join51, relative as relative4 } from "path";
13167
+ import { Command as Command98 } from "commander";
13168
+ import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync23 } from "fs";
13169
+ import { join as join52, relative as relative4 } from "path";
12613
13170
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
12614
13171
  function stripHighSeverityPatterns(content, injectionFindings) {
12615
13172
  const highLines = /* @__PURE__ */ new Set();
@@ -12642,10 +13199,10 @@ function applyFix(filePath, targetDir, content, injectionFindings) {
12642
13199
  }
12643
13200
  }
12644
13201
  function scanSingleFile(filePath, targetDir, scanner, options) {
12645
- if (!existsSync31(filePath)) return null;
13202
+ if (!existsSync32(filePath)) return null;
12646
13203
  let content;
12647
13204
  try {
12648
- content = readFileSync22(filePath, "utf8");
13205
+ content = readFileSync23(filePath, "utf8");
12649
13206
  } catch {
12650
13207
  return null;
12651
13208
  }
@@ -12666,7 +13223,7 @@ async function runScanConfig(targetDir, options) {
12666
13223
  const scanner = new SecurityScanner(parseSecurityConfig({}));
12667
13224
  const results = [];
12668
13225
  for (const configFile of CONFIG_FILES) {
12669
- const result = scanSingleFile(join51(targetDir, configFile), targetDir, scanner, options);
13226
+ const result = scanSingleFile(join52(targetDir, configFile), targetDir, scanner, options);
12670
13227
  if (result) results.push(result);
12671
13228
  }
12672
13229
  return { exitCode: computeScanExitCode(results), results };
@@ -12696,7 +13253,7 @@ function formatTextOutput(result) {
12696
13253
  }
12697
13254
  }
12698
13255
  function createScanConfigCommand() {
12699
- const command = new Command97("scan-config").description(
13256
+ const command = new Command98("scan-config").description(
12700
13257
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
12701
13258
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
12702
13259
  const globalOpts = cmd.optsWithGlobals();
@@ -12714,7 +13271,7 @@ function createScanConfigCommand() {
12714
13271
 
12715
13272
  // src/commands/search.ts
12716
13273
  init_dist();
12717
- import { Command as Command98 } from "commander";
13274
+ import { Command as Command99 } from "commander";
12718
13275
  function parseFileKinds(raw) {
12719
13276
  if (!raw) return void 0;
12720
13277
  const set = /* @__PURE__ */ new Set();
@@ -12735,7 +13292,7 @@ function fmtBytes(n) {
12735
13292
  return n.toFixed(0);
12736
13293
  }
12737
13294
  function createSearchCommand() {
12738
- return new Command98("search").description("Full-text search over archived + live session content.").argument(
13295
+ return new Command99("search").description("Full-text search over archived + live session content.").argument(
12739
13296
  "<query>",
12740
13297
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
12741
13298
  ).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(
@@ -12795,9 +13352,9 @@ function createSearchCommand() {
12795
13352
  }
12796
13353
 
12797
13354
  // src/commands/security-craft.ts
12798
- import { Command as Command99 } from "commander";
13355
+ import { Command as Command100 } from "commander";
12799
13356
  function createSecurityCraftCommand() {
12800
- return new Command99("security-craft").description(
13357
+ return new Command100("security-craft").description(
12801
13358
  "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."
12802
13359
  ).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) => {
12803
13360
  const globalOpts = cmd.optsWithGlobals();
@@ -12844,10 +13401,10 @@ function printResult5(result, mode, _formatter) {
12844
13401
  list.push(f);
12845
13402
  byFile.set(f.target.file, list);
12846
13403
  }
12847
- for (const [file, fs51] of byFile) {
13404
+ for (const [file, fs52] of byFile) {
12848
13405
  console.log(`
12849
13406
  ${file}`);
12850
- for (const f of fs51) {
13407
+ for (const f of fs52) {
12851
13408
  console.log(
12852
13409
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.signal}:${f.target.line}`
12853
13410
  );
@@ -12863,24 +13420,24 @@ ${file}`);
12863
13420
  }
12864
13421
 
12865
13422
  // src/commands/setup.ts
12866
- import { Command as Command100 } from "commander";
12867
- import * as fs38 from "fs";
13423
+ import { Command as Command101 } from "commander";
13424
+ import * as fs39 from "fs";
12868
13425
  import * as os9 from "os";
12869
- import * as path62 from "path";
13426
+ import * as path63 from "path";
12870
13427
  import chalk16 from "chalk";
12871
13428
 
12872
13429
  // src/utils/first-run.ts
12873
- import * as fs36 from "fs";
13430
+ import * as fs37 from "fs";
12874
13431
  import * as os8 from "os";
12875
- import * as path60 from "path";
12876
- var HARNESS_DIR = path60.join(os8.homedir(), ".harness");
12877
- var MARKER_FILE = path60.join(HARNESS_DIR, ".setup-complete");
13432
+ import * as path61 from "path";
13433
+ var HARNESS_DIR = path61.join(os8.homedir(), ".harness");
13434
+ var MARKER_FILE = path61.join(HARNESS_DIR, ".setup-complete");
12878
13435
  function isFirstRun() {
12879
- return !fs36.existsSync(MARKER_FILE);
13436
+ return !fs37.existsSync(MARKER_FILE);
12880
13437
  }
12881
13438
  function markSetupComplete() {
12882
- fs36.mkdirSync(HARNESS_DIR, { recursive: true });
12883
- fs36.writeFileSync(MARKER_FILE, "", "utf-8");
13439
+ fs37.mkdirSync(HARNESS_DIR, { recursive: true });
13440
+ fs37.writeFileSync(MARKER_FILE, "", "utf-8");
12884
13441
  }
12885
13442
  function printFirstRunWelcome() {
12886
13443
  try {
@@ -12893,8 +13450,8 @@ function printFirstRunWelcome() {
12893
13450
  }
12894
13451
 
12895
13452
  // src/commands/telemetry-wizard.ts
12896
- import * as fs37 from "fs";
12897
- import * as path61 from "path";
13453
+ import * as fs38 from "fs";
13454
+ import * as path62 from "path";
12898
13455
  import readline2 from "readline";
12899
13456
  import chalk15 from "chalk";
12900
13457
  function prompt2(question) {
@@ -12925,21 +13482,21 @@ function isNo(answer) {
12925
13482
  return answer === "n" || answer === "no";
12926
13483
  }
12927
13484
  function isTelemetryConfigured(cwd) {
12928
- const configPath = path61.join(cwd, "harness.config.json");
13485
+ const configPath = path62.join(cwd, "harness.config.json");
12929
13486
  try {
12930
- const raw = JSON.parse(fs37.readFileSync(configPath, "utf-8"));
13487
+ const raw = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
12931
13488
  return raw.telemetry !== void 0 && raw.adoption !== void 0;
12932
13489
  } catch {
12933
13490
  return false;
12934
13491
  }
12935
13492
  }
12936
13493
  function writeTelemetryConfig(cwd, result) {
12937
- const configPath = path61.join(cwd, "harness.config.json");
13494
+ const configPath = path62.join(cwd, "harness.config.json");
12938
13495
  try {
12939
- const raw = JSON.parse(fs37.readFileSync(configPath, "utf-8"));
13496
+ const raw = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
12940
13497
  raw.telemetry = { enabled: result.telemetryEnabled };
12941
13498
  raw.adoption = { enabled: result.adoptionEnabled };
12942
- fs37.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
13499
+ fs38.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
12943
13500
  } catch (err) {
12944
13501
  console.warn(
12945
13502
  `\u26A0 Could not update ${configPath}: ${err instanceof Error ? err.message : String(err)}`
@@ -12947,10 +13504,10 @@ function writeTelemetryConfig(cwd, result) {
12947
13504
  }
12948
13505
  const hasIdentity = result.identity.project || result.identity.team || result.identity.alias;
12949
13506
  if (hasIdentity) {
12950
- const harnessDir = path61.join(cwd, ".harness");
12951
- fs37.mkdirSync(harnessDir, { recursive: true });
12952
- const telemetryFile = path61.join(harnessDir, "telemetry.json");
12953
- fs37.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
13507
+ const harnessDir = path62.join(cwd, ".harness");
13508
+ fs38.mkdirSync(harnessDir, { recursive: true });
13509
+ const telemetryFile = path62.join(harnessDir, "telemetry.json");
13510
+ fs38.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
12954
13511
  }
12955
13512
  }
12956
13513
  async function promptIdentity() {
@@ -12996,8 +13553,8 @@ async function runTelemetryWizard() {
12996
13553
  return { telemetryEnabled, adoptionEnabled, identity };
12997
13554
  }
12998
13555
  async function ensureTelemetryConfigured(cwd) {
12999
- const configPath = path61.join(cwd, "harness.config.json");
13000
- if (!fs37.existsSync(configPath)) {
13556
+ const configPath = path62.join(cwd, "harness.config.json");
13557
+ if (!fs38.existsSync(configPath)) {
13001
13558
  return { status: "warn", message: "Not a harness project \u2014 skipped telemetry configuration" };
13002
13559
  }
13003
13560
  if (isTelemetryConfigured(cwd)) {
@@ -13043,7 +13600,7 @@ function runSlashCommandGeneration() {
13043
13600
  }
13044
13601
  }
13045
13602
  function detectClient(dirName) {
13046
- return fs38.existsSync(path62.join(os9.homedir(), dirName));
13603
+ return fs39.existsSync(path63.join(os9.homedir(), dirName));
13047
13604
  }
13048
13605
  async function runMcpSetup(cwd) {
13049
13606
  const results = [];
@@ -13059,7 +13616,7 @@ async function runMcpSetup(cwd) {
13059
13616
  { name: "Cursor", dir: ".cursor", client: "cursor", configTarget: ".cursor/mcp.json" },
13060
13617
  {
13061
13618
  name: "OpenCode",
13062
- dir: path62.join(".config", "opencode"),
13619
+ dir: path63.join(".config", "opencode"),
13063
13620
  client: "opencode",
13064
13621
  configTarget: "opencode.json"
13065
13622
  }
@@ -13091,7 +13648,7 @@ function formatStep(result) {
13091
13648
  }
13092
13649
  function configureTier0Integrations(cwd) {
13093
13650
  try {
13094
- const mcpPath = path62.join(cwd, ".mcp.json");
13651
+ const mcpPath = path63.join(cwd, ".mcp.json");
13095
13652
  const config = readMcpConfig(mcpPath);
13096
13653
  const tier0 = INTEGRATION_REGISTRY.filter((i) => i.tier === 0);
13097
13654
  const added = [];
@@ -13100,9 +13657,9 @@ function configureTier0Integrations(cwd) {
13100
13657
  writeMcpEntry(mcpPath, integration.name, integration.mcpConfig);
13101
13658
  added.push(integration.displayName);
13102
13659
  }
13103
- const geminiDir = path62.join(cwd, ".gemini");
13104
- if (fs38.existsSync(geminiDir)) {
13105
- const geminiPath = path62.join(geminiDir, "settings.json");
13660
+ const geminiDir = path63.join(cwd, ".gemini");
13661
+ if (fs39.existsSync(geminiDir)) {
13662
+ const geminiPath = path63.join(geminiDir, "settings.json");
13106
13663
  const geminiConfig = readMcpConfig(geminiPath);
13107
13664
  for (const integration of tier0) {
13108
13665
  if (!geminiConfig.mcpServers[integration.name]) {
@@ -13110,9 +13667,9 @@ function configureTier0Integrations(cwd) {
13110
13667
  }
13111
13668
  }
13112
13669
  }
13113
- const opencodePath = path62.join(cwd, "opencode.json");
13114
- const opencodeGlobalDir = path62.join(os9.homedir(), ".config", "opencode");
13115
- if (fs38.existsSync(opencodePath) || fs38.existsSync(opencodeGlobalDir)) {
13670
+ const opencodePath = path63.join(cwd, "opencode.json");
13671
+ const opencodeGlobalDir = path63.join(os9.homedir(), ".config", "opencode");
13672
+ if (fs39.existsSync(opencodePath) || fs39.existsSync(opencodeGlobalDir)) {
13116
13673
  for (const integration of tier0) {
13117
13674
  writeOpencodeMcpEntry(opencodePath, integration.name, integration.mcpConfig);
13118
13675
  }
@@ -13130,14 +13687,14 @@ function configureTier0Integrations(cwd) {
13130
13687
  }
13131
13688
  }
13132
13689
  function ensureHooks(cwd) {
13133
- const configPath = path62.join(cwd, "harness.config.json");
13134
- if (!fs38.existsSync(configPath)) {
13690
+ const configPath = path63.join(cwd, "harness.config.json");
13691
+ if (!fs39.existsSync(configPath)) {
13135
13692
  return { status: "warn", message: "Not a harness project \u2014 skipped hook installation" };
13136
13693
  }
13137
13694
  let profile = "standard";
13138
- const profilePath = path62.join(cwd, ".harness", "hooks", "profile.json");
13695
+ const profilePath = path63.join(cwd, ".harness", "hooks", "profile.json");
13139
13696
  try {
13140
- const data = JSON.parse(fs38.readFileSync(profilePath, "utf-8"));
13697
+ const data = JSON.parse(fs39.readFileSync(profilePath, "utf-8"));
13141
13698
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
13142
13699
  profile = data.profile;
13143
13700
  }
@@ -13208,7 +13765,7 @@ async function runSetup(cwd) {
13208
13765
  return { steps, success };
13209
13766
  }
13210
13767
  function createSetupCommand() {
13211
- return new Command100("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
13768
+ return new Command101("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
13212
13769
  const cwd = process.cwd();
13213
13770
  console.log("");
13214
13771
  console.log(` ${chalk16.bold("harness setup")}`);
@@ -13231,15 +13788,15 @@ function createSetupCommand() {
13231
13788
 
13232
13789
  // src/commands/share.ts
13233
13790
  init_dist3();
13234
- import { Command as Command101 } from "commander";
13235
- import * as fs39 from "fs";
13236
- import * as path63 from "path";
13791
+ import { Command as Command102 } from "commander";
13792
+ import * as fs40 from "fs";
13793
+ import * as path64 from "path";
13237
13794
  import { parse as parseYaml3 } from "yaml";
13238
13795
  var MANIFEST_FILENAME = "constraints.yaml";
13239
13796
  async function runShareAction(projectPath, options) {
13240
- const rootDir = path63.resolve(projectPath);
13241
- const manifestPath = path63.join(rootDir, MANIFEST_FILENAME);
13242
- if (!fs39.existsSync(manifestPath)) {
13797
+ const rootDir = path64.resolve(projectPath);
13798
+ const manifestPath = path64.join(rootDir, MANIFEST_FILENAME);
13799
+ if (!fs40.existsSync(manifestPath)) {
13243
13800
  logger.error(
13244
13801
  `No ${MANIFEST_FILENAME} found at ${manifestPath}.
13245
13802
  Create a constraints.yaml in your project root to define what to share.`
@@ -13248,7 +13805,7 @@ Create a constraints.yaml in your project root to define what to share.`
13248
13805
  }
13249
13806
  let parsed;
13250
13807
  try {
13251
- const raw = fs39.readFileSync(manifestPath, "utf-8");
13808
+ const raw = fs40.readFileSync(manifestPath, "utf-8");
13252
13809
  parsed = parseYaml3(raw);
13253
13810
  } catch (err) {
13254
13811
  logger.error(
@@ -13262,7 +13819,7 @@ Create a constraints.yaml in your project root to define what to share.`
13262
13819
  process.exit(1);
13263
13820
  }
13264
13821
  const manifest = manifestResult.value;
13265
- const configResult = resolveConfig(path63.join(rootDir, "harness.config.json"));
13822
+ const configResult = resolveConfig(path64.join(rootDir, "harness.config.json"));
13266
13823
  if (!configResult.ok) {
13267
13824
  logger.error(configResult.error.message);
13268
13825
  process.exit(1);
@@ -13280,8 +13837,8 @@ Create a constraints.yaml in your project root to define what to share.`
13280
13837
  );
13281
13838
  process.exit(1);
13282
13839
  }
13283
- const outputDir = path63.resolve(options.output);
13284
- const outputPath = path63.join(outputDir, `${manifest.name}.harness-constraints.json`);
13840
+ const outputDir = path64.resolve(options.output);
13841
+ const outputPath = path64.join(outputDir, `${manifest.name}.harness-constraints.json`);
13285
13842
  const writeResult = await writeConfig(outputPath, bundle);
13286
13843
  if (!writeResult.ok) {
13287
13844
  logger.error(`Failed to write bundle: ${writeResult.error.message}`);
@@ -13290,28 +13847,28 @@ Create a constraints.yaml in your project root to define what to share.`
13290
13847
  logger.success(`Bundle written to ${outputPath}`);
13291
13848
  }
13292
13849
  function createShareCommand() {
13293
- return new Command101("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) => {
13850
+ return new Command102("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) => {
13294
13851
  await runShareAction(projectPath, options);
13295
13852
  });
13296
13853
  }
13297
13854
 
13298
13855
  // src/commands/skill/index.ts
13299
- import { Command as Command109 } from "commander";
13856
+ import { Command as Command110 } from "commander";
13300
13857
 
13301
13858
  // src/commands/skill/list.ts
13302
- import { Command as Command102 } from "commander";
13303
- import * as fs40 from "fs";
13304
- import * as path64 from "path";
13859
+ import { Command as Command103 } from "commander";
13860
+ import * as fs41 from "fs";
13861
+ import * as path65 from "path";
13305
13862
  import { parse } from "yaml";
13306
13863
  function scanDirectory(dirPath, source) {
13307
- if (!fs40.existsSync(dirPath)) return [];
13308
- const entries = fs40.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
13864
+ if (!fs41.existsSync(dirPath)) return [];
13865
+ const entries = fs41.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
13309
13866
  const skills = [];
13310
13867
  for (const name of entries) {
13311
- const yamlPath = path64.join(dirPath, name, "skill.yaml");
13312
- if (!fs40.existsSync(yamlPath)) continue;
13868
+ const yamlPath = path65.join(dirPath, name, "skill.yaml");
13869
+ if (!fs41.existsSync(yamlPath)) continue;
13313
13870
  try {
13314
- const raw = fs40.readFileSync(yamlPath, "utf-8");
13871
+ const raw = fs41.readFileSync(yamlPath, "utf-8");
13315
13872
  const parsed = parse(raw);
13316
13873
  const result = SkillMetadataSchema.safeParse(parsed);
13317
13874
  if (result.success) {
@@ -13329,10 +13886,10 @@ function scanDirectory(dirPath, source) {
13329
13886
  }
13330
13887
  function collectCommunitySkills(seen, allSkills) {
13331
13888
  const globalDir = resolveGlobalSkillsDir();
13332
- const skillsDir = path64.dirname(globalDir);
13333
- const communityBase = path64.join(skillsDir, "community");
13334
- const communityPlatformDir = path64.join(communityBase, "claude-code");
13335
- const lockfilePath = path64.join(communityBase, "skills-lock.json");
13889
+ const skillsDir = path65.dirname(globalDir);
13890
+ const communityBase = path65.join(skillsDir, "community");
13891
+ const communityPlatformDir = path65.join(communityBase, "claude-code");
13892
+ const lockfilePath = path65.join(communityBase, "skills-lock.json");
13336
13893
  const lockfile = readLockfile2(lockfilePath);
13337
13894
  const communitySkills = scanDirectory(communityPlatformDir, "community");
13338
13895
  for (const skill of communitySkills) {
@@ -13402,7 +13959,7 @@ function printSkillsVerbose(skills) {
13402
13959
  for (const s of skills) printSkillEntry(s);
13403
13960
  }
13404
13961
  function createListCommand3() {
13405
- return new Command102("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) => {
13962
+ return new Command103("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) => {
13406
13963
  const globalOpts = cmd.optsWithGlobals();
13407
13964
  const skills = collectSkills({ filter: resolveFilter(opts) });
13408
13965
  if (globalOpts.json) {
@@ -13417,9 +13974,9 @@ function createListCommand3() {
13417
13974
  }
13418
13975
 
13419
13976
  // src/commands/skill/run.ts
13420
- import { Command as Command103 } from "commander";
13421
- import * as fs41 from "fs";
13422
- import * as path65 from "path";
13977
+ import { Command as Command104 } from "commander";
13978
+ import * as fs42 from "fs";
13979
+ import * as path66 from "path";
13423
13980
  import { parse as parse2 } from "yaml";
13424
13981
 
13425
13982
  // src/skill/complexity.ts
@@ -13515,10 +14072,10 @@ ${options.principles}`);
13515
14072
 
13516
14073
  // src/commands/skill/run.ts
13517
14074
  function loadSkillMetadata(skillDir) {
13518
- const yamlPath = path65.join(skillDir, "skill.yaml");
13519
- if (!fs41.existsSync(yamlPath)) return null;
14075
+ const yamlPath = path66.join(skillDir, "skill.yaml");
14076
+ if (!fs42.existsSync(yamlPath)) return null;
13520
14077
  try {
13521
- const result = SkillMetadataSchema.safeParse(parse2(fs41.readFileSync(yamlPath, "utf-8")));
14078
+ const result = SkillMetadataSchema.safeParse(parse2(fs42.readFileSync(yamlPath, "utf-8")));
13522
14079
  return result.success ? result.data : null;
13523
14080
  } catch {
13524
14081
  return null;
@@ -13530,22 +14087,22 @@ function resolveComplexity(metadata, requested, projectPath) {
13530
14087
  return requested;
13531
14088
  }
13532
14089
  function loadPrinciples(projectPath) {
13533
- const principlesPath = path65.join(projectPath, "docs", "principles.md");
13534
- return fs41.existsSync(principlesPath) ? fs41.readFileSync(principlesPath, "utf-8") : void 0;
14090
+ const principlesPath = path66.join(projectPath, "docs", "principles.md");
14091
+ return fs42.existsSync(principlesPath) ? fs42.readFileSync(principlesPath, "utf-8") : void 0;
13535
14092
  }
13536
14093
  function readMostRecentFileInDir(dirPath) {
13537
- const files = fs41.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs41.statSync(path65.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
13538
- if (files.length > 0) return fs41.readFileSync(path65.join(dirPath, files[0].name), "utf-8");
14094
+ const files = fs42.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs42.statSync(path66.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
14095
+ if (files.length > 0) return fs42.readFileSync(path66.join(dirPath, files[0].name), "utf-8");
13539
14096
  return void 0;
13540
14097
  }
13541
14098
  function loadPriorState(metadata, projectPath) {
13542
14099
  if (!metadata?.state.persistent || metadata.state.files.length === 0) return void 0;
13543
14100
  for (const stateFilePath of metadata.state.files) {
13544
- const fullPath = path65.join(projectPath, stateFilePath);
13545
- if (!fs41.existsSync(fullPath)) continue;
13546
- const stat = fs41.statSync(fullPath);
14101
+ const fullPath = path66.join(projectPath, stateFilePath);
14102
+ if (!fs42.existsSync(fullPath)) continue;
14103
+ const stat = fs42.statSync(fullPath);
13547
14104
  if (stat.isDirectory()) return readMostRecentFileInDir(fullPath);
13548
- return fs41.readFileSync(fullPath, "utf-8");
14105
+ return fs42.readFileSync(fullPath, "utf-8");
13549
14106
  }
13550
14107
  return void 0;
13551
14108
  }
@@ -13565,7 +14122,7 @@ function resolvePhaseState(metadata, projectPath, phase) {
13565
14122
  }
13566
14123
  async function appendProjectState(content, metadata, projectPath, hasPathOpt) {
13567
14124
  if (!metadata?.state.persistent || !hasPathOpt) return content;
13568
- const { readHarnessState: readHarnessState2, isEmptyHarnessState } = await import("./state-events-PTWAEGJ2.js");
14125
+ const { readHarnessState: readHarnessState2, isEmptyHarnessState } = await import("./state-events-YLQEYOLI.js");
13569
14126
  const stateResult = await readHarnessState2(projectPath);
13570
14127
  if (!stateResult.ok || isEmptyHarnessState(stateResult.value)) return content;
13571
14128
  const stateContent = JSON.stringify(stateResult.value, null, 2);
@@ -13586,7 +14143,7 @@ async function runSkill(name, opts) {
13586
14143
  return;
13587
14144
  }
13588
14145
  const metadata = loadSkillMetadata(skillDir);
13589
- const projectPath = opts.path ? path65.resolve(opts.path) : process.cwd();
14146
+ const projectPath = opts.path ? path66.resolve(opts.path) : process.cwd();
13590
14147
  const complexity = resolveComplexity(
13591
14148
  metadata,
13592
14149
  opts.complexity ?? "standard",
@@ -13613,14 +14170,14 @@ async function runSkill(name, opts) {
13613
14170
  ...stateWarning !== void 0 && { stateWarning },
13614
14171
  ...opts.party !== void 0 && { party: opts.party }
13615
14172
  });
13616
- const skillMdPath = path65.join(skillDir, "SKILL.md");
13617
- if (!fs41.existsSync(skillMdPath)) {
14173
+ const skillMdPath = path66.join(skillDir, "SKILL.md");
14174
+ if (!fs42.existsSync(skillMdPath)) {
13618
14175
  logger.error(`SKILL.md not found for skill: ${name}`);
13619
14176
  process.exit(ExitCode.ERROR);
13620
14177
  return;
13621
14178
  }
13622
14179
  const content = await appendProjectState(
13623
- fs41.readFileSync(skillMdPath, "utf-8"),
14180
+ fs42.readFileSync(skillMdPath, "utf-8"),
13624
14181
  metadata,
13625
14182
  projectPath,
13626
14183
  !!opts.path
@@ -13631,16 +14188,16 @@ async function runSkill(name, opts) {
13631
14188
  process.exit(ExitCode.SUCCESS);
13632
14189
  }
13633
14190
  function createRunCommand3() {
13634
- return new Command103("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(
14191
+ return new Command104("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(
13635
14192
  "--backend <name>",
13636
14193
  "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
13637
14194
  ).action(async (name, opts) => runSkill(name, opts));
13638
14195
  }
13639
14196
 
13640
14197
  // src/commands/skill/validate.ts
13641
- import { Command as Command104 } from "commander";
13642
- import * as fs42 from "fs";
13643
- import * as path66 from "path";
14198
+ import { Command as Command105 } from "commander";
14199
+ import * as fs43 from "fs";
14200
+ import * as path67 from "path";
13644
14201
  import { parse as parse3 } from "yaml";
13645
14202
  var BEHAVIORAL_REQUIRED_SECTIONS = [
13646
14203
  "## When to Use",
@@ -13652,11 +14209,11 @@ var BEHAVIORAL_REQUIRED_SECTIONS = [
13652
14209
  ];
13653
14210
  var KNOWLEDGE_REQUIRED_SECTIONS = ["## Instructions"];
13654
14211
  function validateSkillMd(name, skillMdPath, skillType, errors) {
13655
- if (!fs42.existsSync(skillMdPath)) {
14212
+ if (!fs43.existsSync(skillMdPath)) {
13656
14213
  errors.push(`${name}: missing SKILL.md`);
13657
14214
  return;
13658
14215
  }
13659
- const mdContent = fs42.readFileSync(skillMdPath, "utf-8");
14216
+ const mdContent = fs43.readFileSync(skillMdPath, "utf-8");
13660
14217
  if (!mdContent.trim().startsWith("# ")) {
13661
14218
  errors.push(`${name}/SKILL.md: must start with an h1 heading`);
13662
14219
  }
@@ -13681,20 +14238,20 @@ function validateSkillMd(name, skillMdPath, skillType, errors) {
13681
14238
  }
13682
14239
  }
13683
14240
  function validateSkillEntry(name, skillsDir, errors) {
13684
- const skillDir = path66.join(skillsDir, name);
13685
- const yamlPath = path66.join(skillDir, "skill.yaml");
13686
- if (!fs42.existsSync(yamlPath)) {
14241
+ const skillDir = path67.join(skillsDir, name);
14242
+ const yamlPath = path67.join(skillDir, "skill.yaml");
14243
+ if (!fs43.existsSync(yamlPath)) {
13687
14244
  errors.push(`${name}: missing skill.yaml`);
13688
14245
  return false;
13689
14246
  }
13690
14247
  try {
13691
- const raw = fs42.readFileSync(yamlPath, "utf-8");
14248
+ const raw = fs43.readFileSync(yamlPath, "utf-8");
13692
14249
  const result = SkillMetadataSchema.safeParse(parse3(raw));
13693
14250
  if (!result.success) {
13694
14251
  errors.push(`${name}/skill.yaml: ${result.error.message}`);
13695
14252
  return false;
13696
14253
  }
13697
- validateSkillMd(name, path66.join(skillDir, "SKILL.md"), result.data.type, errors);
14254
+ validateSkillMd(name, path67.join(skillDir, "SKILL.md"), result.data.type, errors);
13698
14255
  return true;
13699
14256
  } catch (e) {
13700
14257
  errors.push(`${name}: parse error \u2014 ${e instanceof Error ? e.message : String(e)}`);
@@ -13702,15 +14259,15 @@ function validateSkillEntry(name, skillsDir, errors) {
13702
14259
  }
13703
14260
  }
13704
14261
  function createValidateCommand2() {
13705
- return new Command104("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
14262
+ return new Command105("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
13706
14263
  const globalOpts = cmd.optsWithGlobals();
13707
14264
  const skillsDir = resolveSkillsDir();
13708
- if (!fs42.existsSync(skillsDir)) {
14265
+ if (!fs43.existsSync(skillsDir)) {
13709
14266
  logger.info("No skills directory found.");
13710
14267
  process.exit(ExitCode.SUCCESS);
13711
14268
  return;
13712
14269
  }
13713
- const entries = fs42.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
14270
+ const entries = fs43.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
13714
14271
  const errors = [];
13715
14272
  let validated = 0;
13716
14273
  for (const name of entries) {
@@ -13732,9 +14289,9 @@ function createValidateCommand2() {
13732
14289
  }
13733
14290
 
13734
14291
  // src/commands/skill/info.ts
13735
- import { Command as Command105 } from "commander";
13736
- import * as fs43 from "fs";
13737
- import * as path67 from "path";
14292
+ import { Command as Command106 } from "commander";
14293
+ import * as fs44 from "fs";
14294
+ import * as path68 from "path";
13738
14295
  import { parse as parse4 } from "yaml";
13739
14296
  function loadSkillMetadata2(name) {
13740
14297
  const skillDir = resolveSkillDir(name);
@@ -13742,13 +14299,13 @@ function loadSkillMetadata2(name) {
13742
14299
  logger.error(`Skill not found: ${name}`);
13743
14300
  return { ok: false, exitCode: ExitCode.ERROR };
13744
14301
  }
13745
- const yamlPath = path67.join(skillDir, "skill.yaml");
13746
- if (!fs43.existsSync(yamlPath)) {
14302
+ const yamlPath = path68.join(skillDir, "skill.yaml");
14303
+ if (!fs44.existsSync(yamlPath)) {
13747
14304
  logger.error(`skill.yaml not found for skill: ${name}`);
13748
14305
  return { ok: false, exitCode: ExitCode.ERROR };
13749
14306
  }
13750
14307
  try {
13751
- const raw = fs43.readFileSync(yamlPath, "utf-8");
14308
+ const raw = fs44.readFileSync(yamlPath, "utf-8");
13752
14309
  const parsed = parse4(raw);
13753
14310
  const result = SkillMetadataSchema.safeParse(parsed);
13754
14311
  if (!result.success) {
@@ -13777,7 +14334,7 @@ function printSkillInfo(skill) {
13777
14334
  console.log(`Persistent: ${skill.state.persistent}`);
13778
14335
  }
13779
14336
  function createInfoCommand() {
13780
- return new Command105("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
14337
+ return new Command106("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
13781
14338
  const globalOpts = cmd.optsWithGlobals();
13782
14339
  const loaded = loadSkillMetadata2(name);
13783
14340
  if (!loaded.ok) {
@@ -13794,7 +14351,7 @@ function createInfoCommand() {
13794
14351
  }
13795
14352
 
13796
14353
  // src/commands/skill/search.ts
13797
- import { Command as Command106 } from "commander";
14354
+ import { Command as Command107 } from "commander";
13798
14355
  async function runSearch(query, opts) {
13799
14356
  const results = await searchNpmRegistry(query, opts.registry);
13800
14357
  return results.filter((r) => {
@@ -13839,15 +14396,15 @@ async function runSearchAction(query, opts, globalOpts) {
13839
14396
  }
13840
14397
  }
13841
14398
  function createSearchCommand2() {
13842
- return new Command106("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) => {
14399
+ return new Command107("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) => {
13843
14400
  await runSearchAction(query, opts, cmd.optsWithGlobals());
13844
14401
  });
13845
14402
  }
13846
14403
 
13847
14404
  // src/commands/skill/create.ts
13848
- import { Command as Command107 } from "commander";
13849
- import * as path68 from "path";
13850
- import * as fs44 from "fs";
14405
+ import { Command as Command108 } from "commander";
14406
+ import * as path69 from "path";
14407
+ import * as fs45 from "fs";
13851
14408
  import YAML from "yaml";
13852
14409
  var KEBAB_CASE_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
13853
14410
  function buildReadme(name, description) {
@@ -13931,22 +14488,22 @@ function runCreate(name, opts) {
13931
14488
  if (!KEBAB_CASE_RE.test(name)) {
13932
14489
  throw new Error(`Invalid skill name "${name}". Must be kebab-case (e.g., my-skill).`);
13933
14490
  }
13934
- const baseDir = opts.outputDir ?? path68.join(process.cwd(), "agents", "skills", "claude-code");
13935
- const skillDir = path68.join(baseDir, name);
13936
- if (fs44.existsSync(skillDir)) {
14491
+ const baseDir = opts.outputDir ?? path69.join(process.cwd(), "agents", "skills", "claude-code");
14492
+ const skillDir = path69.join(baseDir, name);
14493
+ if (fs45.existsSync(skillDir)) {
13937
14494
  throw new Error(`Skill directory already exists: ${skillDir}`);
13938
14495
  }
13939
- fs44.mkdirSync(skillDir, { recursive: true });
14496
+ fs45.mkdirSync(skillDir, { recursive: true });
13940
14497
  const description = opts.description || `A community skill: ${name}`;
13941
14498
  const skillYaml = buildSkillYaml(name, opts);
13942
- const skillYamlPath = path68.join(skillDir, "skill.yaml");
13943
- fs44.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
14499
+ const skillYamlPath = path69.join(skillDir, "skill.yaml");
14500
+ fs45.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
13944
14501
  const skillMd = buildSkillMd(name, description);
13945
- const skillMdPath = path68.join(skillDir, "SKILL.md");
13946
- fs44.writeFileSync(skillMdPath, skillMd);
14502
+ const skillMdPath = path69.join(skillDir, "SKILL.md");
14503
+ fs45.writeFileSync(skillMdPath, skillMd);
13947
14504
  const readme = buildReadme(name, description);
13948
- const readmePath = path68.join(skillDir, "README.md");
13949
- fs44.writeFileSync(readmePath, readme);
14505
+ const readmePath = path69.join(skillDir, "README.md");
14506
+ fs45.writeFileSync(readmePath, readme);
13950
14507
  return {
13951
14508
  name,
13952
14509
  directory: skillDir,
@@ -13960,12 +14517,12 @@ function printCreateResult(name, result) {
13960
14517
  }
13961
14518
  logger.info(`
13962
14519
  Next steps:`);
13963
- logger.info(` 1. Edit ${path68.join(result.directory, "SKILL.md")} with your skill content`);
14520
+ logger.info(` 1. Edit ${path69.join(result.directory, "SKILL.md")} with your skill content`);
13964
14521
  logger.info(` 2. Run: harness skill validate ${name}`);
13965
14522
  logger.info(` 3. Run: harness skills publish`);
13966
14523
  }
13967
14524
  function createCreateCommand() {
13968
- return new Command107("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) => {
14525
+ return new Command108("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) => {
13969
14526
  const globalOpts = cmd.optsWithGlobals();
13970
14527
  try {
13971
14528
  const result = runCreate(name, {
@@ -13988,26 +14545,26 @@ function createCreateCommand() {
13988
14545
  }
13989
14546
 
13990
14547
  // src/commands/skill/publish.ts
13991
- import { Command as Command108 } from "commander";
13992
- import * as fs46 from "fs";
13993
- import * as path70 from "path";
14548
+ import { Command as Command109 } from "commander";
14549
+ import * as fs47 from "fs";
14550
+ import * as path71 from "path";
13994
14551
  import { execFileSync as execFileSync12 } from "child_process";
13995
14552
 
13996
14553
  // src/registry/validator.ts
13997
- import * as fs45 from "fs";
13998
- import * as path69 from "path";
14554
+ import * as fs46 from "fs";
14555
+ import * as path70 from "path";
13999
14556
  import { parse as parse5 } from "yaml";
14000
14557
  import semver4 from "semver";
14001
14558
  async function validateForPublish(skillDir, registryUrl) {
14002
14559
  const errors = [];
14003
- const skillYamlPath = path69.join(skillDir, "skill.yaml");
14004
- if (!fs45.existsSync(skillYamlPath)) {
14560
+ const skillYamlPath = path70.join(skillDir, "skill.yaml");
14561
+ if (!fs46.existsSync(skillYamlPath)) {
14005
14562
  errors.push("skill.yaml not found. Create one with: harness skill create <name>");
14006
14563
  return { valid: false, errors };
14007
14564
  }
14008
14565
  let skillMeta;
14009
14566
  try {
14010
- const raw = fs45.readFileSync(skillYamlPath, "utf-8");
14567
+ const raw = fs46.readFileSync(skillYamlPath, "utf-8");
14011
14568
  const parsed = parse5(raw);
14012
14569
  const result = SkillMetadataSchema.safeParse(parsed);
14013
14570
  if (!result.success) {
@@ -14029,11 +14586,11 @@ async function validateForPublish(skillDir, registryUrl) {
14029
14586
  if (!skillMeta.triggers || skillMeta.triggers.length === 0) {
14030
14587
  errors.push("At least one trigger is required. Add triggers to skill.yaml.");
14031
14588
  }
14032
- const skillMdPath = path69.join(skillDir, "SKILL.md");
14033
- if (!fs45.existsSync(skillMdPath)) {
14589
+ const skillMdPath = path70.join(skillDir, "SKILL.md");
14590
+ if (!fs46.existsSync(skillMdPath)) {
14034
14591
  errors.push("SKILL.md not found. Create it with content describing your skill.");
14035
14592
  } else {
14036
- const content = fs45.readFileSync(skillMdPath, "utf-8");
14593
+ const content = fs46.readFileSync(skillMdPath, "utf-8");
14037
14594
  if (!content.includes("## When to Use")) {
14038
14595
  errors.push('SKILL.md must contain a "## When to Use" section.');
14039
14596
  }
@@ -14113,11 +14670,11 @@ ${errorList}`);
14113
14670
  }
14114
14671
  const meta = validation.skillMeta;
14115
14672
  const pkg = derivePackageJson(meta);
14116
- const pkgPath = path70.join(skillDir, "package.json");
14117
- fs46.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
14118
- const readmePath = path70.join(skillDir, "README.md");
14119
- if (!fs46.existsSync(readmePath)) {
14120
- const skillMdContent = fs46.readFileSync(path70.join(skillDir, "SKILL.md"), "utf-8");
14673
+ const pkgPath = path71.join(skillDir, "package.json");
14674
+ fs47.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
14675
+ const readmePath = path71.join(skillDir, "README.md");
14676
+ if (!fs47.existsSync(readmePath)) {
14677
+ const skillMdContent = fs47.readFileSync(path71.join(skillDir, "SKILL.md"), "utf-8");
14121
14678
  const readme = `# ${pkg.name}
14122
14679
 
14123
14680
  ${meta.description}
@@ -14131,7 +14688,7 @@ harness install ${meta.name}
14131
14688
  ---
14132
14689
 
14133
14690
  ${skillMdContent}`;
14134
- fs46.writeFileSync(readmePath, readme);
14691
+ fs47.writeFileSync(readmePath, readme);
14135
14692
  }
14136
14693
  if (opts.dryRun) {
14137
14694
  return {
@@ -14157,7 +14714,7 @@ ${skillMdContent}`;
14157
14714
  };
14158
14715
  }
14159
14716
  function createPublishCommand() {
14160
- return new Command108("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) => {
14717
+ return new Command109("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) => {
14161
14718
  const globalOpts = cmd.optsWithGlobals();
14162
14719
  const skillDir = opts.dir || process.cwd();
14163
14720
  try {
@@ -14182,7 +14739,7 @@ function createPublishCommand() {
14182
14739
 
14183
14740
  // src/commands/skill/index.ts
14184
14741
  function createSkillCommand() {
14185
- const command = new Command109("skill").description("Skill management commands");
14742
+ const command = new Command110("skill").description("Skill management commands");
14186
14743
  command.addCommand(createListCommand3());
14187
14744
  command.addCommand(createRunCommand3());
14188
14745
  command.addCommand(createValidateCommand2());
@@ -14195,7 +14752,7 @@ function createSkillCommand() {
14195
14752
 
14196
14753
  // src/commands/snapshot.ts
14197
14754
  init_dist3();
14198
- import { Command as Command110 } from "commander";
14755
+ import { Command as Command111 } from "commander";
14199
14756
  import { execSync as execSync5 } from "child_process";
14200
14757
  import chalk17 from "chalk";
14201
14758
  function getCommitHash3(cwd) {
@@ -14377,7 +14934,7 @@ function registerListCommand2(parent) {
14377
14934
  });
14378
14935
  }
14379
14936
  function createSnapshotCommand() {
14380
- const command = new Command110("snapshot").description("Architecture timeline snapshot commands");
14937
+ const command = new Command111("snapshot").description("Architecture timeline snapshot commands");
14381
14938
  registerCaptureCommand(command);
14382
14939
  registerTrendsCommand(command);
14383
14940
  registerListCommand2(command);
@@ -14385,9 +14942,9 @@ function createSnapshotCommand() {
14385
14942
  }
14386
14943
 
14387
14944
  // src/commands/spec-craft.ts
14388
- import { Command as Command111 } from "commander";
14945
+ import { Command as Command112 } from "commander";
14389
14946
  function createSpecCraftCommand() {
14390
- return new Command111("spec-craft").description(
14947
+ return new Command112("spec-craft").description(
14391
14948
  "LLM-judgment critique of spec quality (proposals + ADRs). Second craft-pipeline ceiling skill; 7 seed rubrics from the spec-quality canon. Per-section critique."
14392
14949
  ).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) => {
14393
14950
  const globalOpts = cmd.optsWithGlobals();
@@ -14435,10 +14992,10 @@ function printResult6(result, mode, _formatter) {
14435
14992
  list.push(f);
14436
14993
  byFile.set(f.target.file, list);
14437
14994
  }
14438
- for (const [file, fs51] of byFile) {
14995
+ for (const [file, fs52] of byFile) {
14439
14996
  console.log(`
14440
14997
  ${file}`);
14441
- for (const f of fs51) {
14998
+ for (const f of fs52) {
14442
14999
  console.log(
14443
15000
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ## ${f.target.section}:${f.target.line}`
14444
15001
  );
@@ -14455,7 +15012,7 @@ ${file}`);
14455
15012
 
14456
15013
  // src/commands/stale-constraints.ts
14457
15014
  init_dist3();
14458
- import { Command as Command112 } from "commander";
15015
+ import { Command as Command113 } from "commander";
14459
15016
  import chalk18 from "chalk";
14460
15017
  var CATEGORIES = [
14461
15018
  "circular-deps",
@@ -14542,7 +15099,7 @@ async function runStaleConstraintsCommand(options) {
14542
15099
  );
14543
15100
  }
14544
15101
  function createStaleConstraintsCommand() {
14545
- return new Command112("stale-constraints").description(
15102
+ return new Command113("stale-constraints").description(
14546
15103
  "Detect architectural constraints not violated within a window (candidates for removal)"
14547
15104
  ).option(
14548
15105
  "--window <days>",
@@ -14560,11 +15117,11 @@ function createStaleConstraintsCommand() {
14560
15117
  }
14561
15118
 
14562
15119
  // src/commands/state/index.ts
14563
- import { Command as Command117 } from "commander";
15120
+ import { Command as Command118 } from "commander";
14564
15121
 
14565
15122
  // src/commands/state/show.ts
14566
- import { Command as Command113 } from "commander";
14567
- import * as path71 from "path";
15123
+ import { Command as Command114 } from "commander";
15124
+ import * as path72 from "path";
14568
15125
  function printStateText(state, stream) {
14569
15126
  if (stream) console.log(`Stream: ${stream}`);
14570
15127
  console.log(`Schema Version: ${state.schemaVersion}`);
@@ -14588,9 +15145,9 @@ function printStateProgress(progress) {
14588
15145
  }
14589
15146
  }
14590
15147
  function createShowCommand() {
14591
- return new Command113("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
15148
+ return new Command114("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
14592
15149
  const globalOpts = cmd.optsWithGlobals();
14593
- const result = await readHarnessState(path71.resolve(opts.path), { stream: opts.stream });
15150
+ const result = await readHarnessState(path72.resolve(opts.path), { stream: opts.stream });
14594
15151
  if (!result.ok) {
14595
15152
  logger.error(result.error.message);
14596
15153
  process.exit(ExitCode.ERROR);
@@ -14606,8 +15163,8 @@ function createShowCommand() {
14606
15163
 
14607
15164
  // src/commands/state/reset.ts
14608
15165
  init_dist3();
14609
- import { Command as Command114 } from "commander";
14610
- import * as path72 from "path";
15166
+ import { Command as Command115 } from "commander";
15167
+ import * as path73 from "path";
14611
15168
  import * as readline3 from "readline";
14612
15169
  async function confirmReset() {
14613
15170
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
@@ -14618,7 +15175,7 @@ async function confirmReset() {
14618
15175
  return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
14619
15176
  }
14620
15177
  async function runReset(opts) {
14621
- const projectPath = path72.resolve(opts.path);
15178
+ const projectPath = path73.resolve(opts.path);
14622
15179
  if (!opts.yes && !await confirmReset()) {
14623
15180
  logger.info("Reset cancelled.");
14624
15181
  process.exit(ExitCode.SUCCESS);
@@ -14632,16 +15189,16 @@ async function runReset(opts) {
14632
15189
  process.exit(ExitCode.SUCCESS);
14633
15190
  }
14634
15191
  function createResetCommand() {
14635
- return new Command114("reset").description("Reset project state (truncates the event log to a fresh default)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
15192
+ return new Command115("reset").description("Reset project state (truncates the event log to a fresh default)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
14636
15193
  }
14637
15194
 
14638
15195
  // src/commands/state/learn.ts
14639
15196
  init_dist3();
14640
- import { Command as Command115 } from "commander";
14641
- import * as path73 from "path";
15197
+ import { Command as Command116 } from "commander";
15198
+ import * as path74 from "path";
14642
15199
  function createLearnCommand() {
14643
- return new Command115("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) => {
14644
- const projectPath = path73.resolve(opts.path);
15200
+ return new Command116("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) => {
15201
+ const projectPath = path74.resolve(opts.path);
14645
15202
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
14646
15203
  if (!result.ok) {
14647
15204
  logger.error(result.error.message);
@@ -14655,10 +15212,10 @@ function createLearnCommand() {
14655
15212
 
14656
15213
  // src/commands/state/streams.ts
14657
15214
  init_dist3();
14658
- import { Command as Command116 } from "commander";
14659
- import * as path74 from "path";
15215
+ import { Command as Command117 } from "commander";
15216
+ import * as path75 from "path";
14660
15217
  async function runListStreams(opts, globalOpts) {
14661
- const projectPath = path74.resolve(opts.path);
15218
+ const projectPath = path75.resolve(opts.path);
14662
15219
  const indexResult = await loadStreamIndex(projectPath);
14663
15220
  const result = await listStreams(projectPath);
14664
15221
  if (!result.ok) {
@@ -14679,7 +15236,7 @@ async function runListStreams(opts, globalOpts) {
14679
15236
  process.exit(ExitCode.SUCCESS);
14680
15237
  }
14681
15238
  async function runCreateStream(name, opts) {
14682
- const result = await createStream(path74.resolve(opts.path), name, opts.branch);
15239
+ const result = await createStream(path75.resolve(opts.path), name, opts.branch);
14683
15240
  if (!result.ok) {
14684
15241
  logger.error(result.error.message);
14685
15242
  process.exit(ExitCode.ERROR);
@@ -14688,7 +15245,7 @@ async function runCreateStream(name, opts) {
14688
15245
  process.exit(ExitCode.SUCCESS);
14689
15246
  }
14690
15247
  async function runArchiveStream(name, opts) {
14691
- const result = await archiveStream(path74.resolve(opts.path), name);
15248
+ const result = await archiveStream(path75.resolve(opts.path), name);
14692
15249
  if (!result.ok) {
14693
15250
  logger.error(result.error.message);
14694
15251
  process.exit(ExitCode.ERROR);
@@ -14697,7 +15254,7 @@ async function runArchiveStream(name, opts) {
14697
15254
  process.exit(ExitCode.SUCCESS);
14698
15255
  }
14699
15256
  async function runActivateStream(name, opts) {
14700
- const result = await setActiveStream(path74.resolve(opts.path), name);
15257
+ const result = await setActiveStream(path75.resolve(opts.path), name);
14701
15258
  if (!result.ok) {
14702
15259
  logger.error(result.error.message);
14703
15260
  process.exit(ExitCode.ERROR);
@@ -14706,7 +15263,7 @@ async function runActivateStream(name, opts) {
14706
15263
  process.exit(ExitCode.SUCCESS);
14707
15264
  }
14708
15265
  function createStreamsCommand() {
14709
- const command = new Command116("streams").description("Manage state streams");
15266
+ const command = new Command117("streams").description("Manage state streams");
14710
15267
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
14711
15268
  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));
14712
15269
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -14716,7 +15273,7 @@ function createStreamsCommand() {
14716
15273
 
14717
15274
  // src/commands/state/index.ts
14718
15275
  function createStateCommand() {
14719
- const command = new Command117("state").description("Project state management commands");
15276
+ const command = new Command118("state").description("Project state management commands");
14720
15277
  command.addCommand(createShowCommand());
14721
15278
  command.addCommand(createResetCommand());
14722
15279
  command.addCommand(createLearnCommand());
@@ -14725,9 +15282,9 @@ function createStateCommand() {
14725
15282
  }
14726
15283
 
14727
15284
  // src/commands/sync-analyses.ts
14728
- import * as fs47 from "fs";
14729
- import * as path75 from "path";
14730
- import { Command as Command118 } from "commander";
15285
+ import * as fs48 from "fs";
15286
+ import * as path76 from "path";
15287
+ import { Command as Command119 } from "commander";
14731
15288
  init_dist3();
14732
15289
  function isValidRecord(record) {
14733
15290
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -14753,7 +15310,7 @@ function extractAnalysisFromComments(comments) {
14753
15310
  return null;
14754
15311
  }
14755
15312
  function bootstrapTrackerCommand2(opts, verb) {
14756
- const projectPath = path75.resolve(opts.dir);
15313
+ const projectPath = path76.resolve(opts.dir);
14757
15314
  const trackerConfig = loadTrackerSyncConfig(projectPath);
14758
15315
  if (!trackerConfig) {
14759
15316
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -14765,8 +15322,8 @@ function bootstrapTrackerCommand2(opts, verb) {
14765
15322
  );
14766
15323
  return null;
14767
15324
  }
14768
- const projectEnvPath = path75.join(projectPath, ".env");
14769
- if (fs47.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
15325
+ const projectEnvPath = path76.join(projectPath, ".env");
15326
+ if (fs48.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
14770
15327
  __require("dotenv").config({ path: projectEnvPath });
14771
15328
  }
14772
15329
  const token = process.env.GITHUB_TOKEN;
@@ -14852,9 +15409,9 @@ async function runSyncAnalyses(opts) {
14852
15409
  return;
14853
15410
  }
14854
15411
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
14855
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-4CZLCE33.js");
15412
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-DTXVNQAY.js");
14856
15413
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
14857
- const archive = new AnalysisArchive(path75.join(projectPath, ".harness", "analyses"));
15414
+ const archive = new AnalysisArchive(path76.join(projectPath, ".harness", "analyses"));
14858
15415
  const publishedIndex = loadPublishedIndex2(projectPath);
14859
15416
  const { syncedCount, skippedCount, warnCount } = await syncFeatureAnalyses(
14860
15417
  features,
@@ -14874,7 +15431,7 @@ async function runSyncAnalyses(opts) {
14874
15431
  }
14875
15432
  }
14876
15433
  function createSyncAnalysesCommand() {
14877
- const command = new Command118("sync-analyses").description(
15434
+ const command = new Command119("sync-analyses").description(
14878
15435
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
14879
15436
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
14880
15437
  try {
@@ -14888,8 +15445,8 @@ function createSyncAnalysesCommand() {
14888
15445
  }
14889
15446
 
14890
15447
  // src/commands/sync-main.ts
14891
- import { Command as Command119 } from "commander";
14892
- import * as path76 from "path";
15448
+ import { Command as Command120 } from "commander";
15449
+ import * as path77 from "path";
14893
15450
  import {
14894
15451
  syncMain as defaultSyncMain
14895
15452
  } from "@harness-engineering/orchestrator";
@@ -14919,8 +15476,8 @@ function formatHuman2(r) {
14919
15476
  }
14920
15477
  }
14921
15478
  function createSyncMainCommand() {
14922
- return new Command119("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) => {
14923
- const cwd = path76.resolve(opts.path ?? ".");
15479
+ return new Command120("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) => {
15480
+ const cwd = path77.resolve(opts.path ?? ".");
14924
15481
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
14925
15482
  process.exit(exitCode);
14926
15483
  });
@@ -14928,7 +15485,7 @@ function createSyncMainCommand() {
14928
15485
 
14929
15486
  // src/commands/taint.ts
14930
15487
  init_dist3();
14931
- import { Command as Command120 } from "commander";
15488
+ import { Command as Command121 } from "commander";
14932
15489
  function getProjectRoot() {
14933
15490
  return process.cwd();
14934
15491
  }
@@ -15000,28 +15557,28 @@ function registerStatusCommand(taint) {
15000
15557
  });
15001
15558
  }
15002
15559
  function createTaintCommand() {
15003
- const taint = new Command120("taint").description("Manage sentinel session taint state");
15560
+ const taint = new Command121("taint").description("Manage sentinel session taint state");
15004
15561
  registerClearCommand(taint);
15005
15562
  registerStatusCommand(taint);
15006
15563
  return taint;
15007
15564
  }
15008
15565
 
15009
15566
  // src/commands/telemetry/index.ts
15010
- import { Command as Command124 } from "commander";
15567
+ import { Command as Command125 } from "commander";
15011
15568
 
15012
15569
  // src/commands/telemetry/identify.ts
15013
15570
  init_dist3();
15014
- import { Command as Command121 } from "commander";
15015
- import * as fs48 from "fs";
15016
- import * as path77 from "path";
15571
+ import { Command as Command122 } from "commander";
15572
+ import * as fs49 from "fs";
15573
+ import * as path78 from "path";
15017
15574
  function telemetryFilePath(cwd) {
15018
- return path77.join(cwd, ".harness", "telemetry.json");
15575
+ return path78.join(cwd, ".harness", "telemetry.json");
15019
15576
  }
15020
15577
  function writeTelemetryFile(cwd, data) {
15021
15578
  const filePath = telemetryFilePath(cwd);
15022
- const dir = path77.dirname(filePath);
15023
- fs48.mkdirSync(dir, { recursive: true });
15024
- fs48.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
15579
+ const dir = path78.dirname(filePath);
15580
+ fs49.mkdirSync(dir, { recursive: true });
15581
+ fs49.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
15025
15582
  }
15026
15583
  var IDENTITY_FIELDS = ["project", "team", "alias"];
15027
15584
  function applyIdentityFields(opts, identity) {
@@ -15035,7 +15592,7 @@ function printIdentity(identity) {
15035
15592
  }
15036
15593
  }
15037
15594
  function createIdentifyCommand() {
15038
- const cmd = new Command121("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) => {
15595
+ const cmd = new Command122("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) => {
15039
15596
  const cwd = process.cwd();
15040
15597
  if (opts.clear) {
15041
15598
  writeTelemetryFile(cwd, { identity: {} });
@@ -15060,7 +15617,7 @@ function createIdentifyCommand() {
15060
15617
 
15061
15618
  // src/commands/telemetry/status.ts
15062
15619
  init_dist3();
15063
- import { Command as Command122 } from "commander";
15620
+ import { Command as Command123 } from "commander";
15064
15621
  function gatherEnvOverrides() {
15065
15622
  const overrides = {};
15066
15623
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -15102,7 +15659,7 @@ function printHumanStatus(result) {
15102
15659
  printEnvOverrides(result.envOverrides);
15103
15660
  }
15104
15661
  function createStatusCommand2() {
15105
- const cmd = new Command122("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
15662
+ const cmd = new Command123("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
15106
15663
  const cwd = process.cwd();
15107
15664
  const envOverrides = gatherEnvOverrides();
15108
15665
  const consent = resolveConsent(cwd, void 0);
@@ -15135,11 +15692,11 @@ function createStatusCommand2() {
15135
15692
 
15136
15693
  // src/commands/telemetry/test.ts
15137
15694
  init_dist3();
15138
- import { Command as Command123 } from "commander";
15695
+ import { Command as Command124 } from "commander";
15139
15696
 
15140
15697
  // src/bin/command-telemetry.ts
15141
- import { existsSync as existsSync44, readFileSync as readFileSync32, mkdirSync as mkdirSync24, appendFileSync as appendFileSync2, writeFileSync as writeFileSync29 } from "fs";
15142
- import { join as join65, parse as parsePath, resolve as resolve46 } from "path";
15698
+ import { existsSync as existsSync45, readFileSync as readFileSync33, mkdirSync as mkdirSync24, appendFileSync as appendFileSync2, writeFileSync as writeFileSync29 } from "fs";
15699
+ import { join as join66, parse as parsePath, resolve as resolve46 } from "path";
15143
15700
  import { spawn as spawn2 } from "child_process";
15144
15701
  var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
15145
15702
  var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
@@ -15147,7 +15704,7 @@ function findProjectRoot(cwd) {
15147
15704
  let dir = resolve46(cwd);
15148
15705
  const { root } = parsePath(dir);
15149
15706
  while (dir !== root) {
15150
- if (existsSync44(join65(dir, "harness.config.json"))) return dir;
15707
+ if (existsSync45(join66(dir, "harness.config.json"))) return dir;
15151
15708
  dir = resolve46(dir, "..");
15152
15709
  }
15153
15710
  return cwd;
@@ -15185,7 +15742,7 @@ function resolveCommandName(cmd) {
15185
15742
  }
15186
15743
  function writeCommandRecordSync(cwd, command, duration, outcome) {
15187
15744
  try {
15188
- const metricsDir = join65(cwd, ".harness", "metrics");
15745
+ const metricsDir = join66(cwd, ".harness", "metrics");
15189
15746
  mkdirSync24(metricsDir, { recursive: true });
15190
15747
  const record = {
15191
15748
  skill: command,
@@ -15195,16 +15752,16 @@ function writeCommandRecordSync(cwd, command, duration, outcome) {
15195
15752
  outcome,
15196
15753
  phasesReached: []
15197
15754
  };
15198
- const adoptionFile = join65(metricsDir, "adoption.jsonl");
15755
+ const adoptionFile = join66(metricsDir, "adoption.jsonl");
15199
15756
  appendFileSync2(adoptionFile, JSON.stringify(record) + "\n");
15200
15757
  } catch {
15201
15758
  }
15202
15759
  }
15203
15760
  function isTelemetryDisabledByConfig(cwd) {
15204
- const configPath = join65(cwd, "harness.config.json");
15205
- if (!existsSync44(configPath)) return false;
15761
+ const configPath = join66(cwd, "harness.config.json");
15762
+ if (!existsSync45(configPath)) return false;
15206
15763
  try {
15207
- const config = JSON.parse(readFileSync32(configPath, "utf-8"));
15764
+ const config = JSON.parse(readFileSync33(configPath, "utf-8"));
15208
15765
  return config?.telemetry?.enabled === false;
15209
15766
  } catch {
15210
15767
  return false;
@@ -15216,11 +15773,11 @@ function isTelemetryOptedOut(cwd) {
15216
15773
  }
15217
15774
  function flushTelemetryBackground(cwd) {
15218
15775
  try {
15219
- const adoptionFile = join65(cwd, ".harness", "metrics", "adoption.jsonl");
15220
- if (!existsSync44(adoptionFile)) return;
15776
+ const adoptionFile = join66(cwd, ".harness", "metrics", "adoption.jsonl");
15777
+ if (!existsSync45(adoptionFile)) return;
15221
15778
  if (isTelemetryOptedOut(cwd)) return;
15222
- const reporterPath = join65(cwd, ".harness", "hooks", "telemetry-reporter.js");
15223
- if (!existsSync44(reporterPath)) return;
15779
+ const reporterPath = join66(cwd, ".harness", "hooks", "telemetry-reporter.js");
15780
+ if (!existsSync45(reporterPath)) return;
15224
15781
  const child = spawn2(process.execPath, [reporterPath], {
15225
15782
  cwd,
15226
15783
  stdio: ["pipe", "ignore", "ignore"],
@@ -15257,7 +15814,7 @@ function reportTestSuccess(status, distinctId, identity) {
15257
15814
  if (identity.team) logger.info(` team: ${identity.team}`);
15258
15815
  }
15259
15816
  function createTestCommand() {
15260
- return new Command123("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
15817
+ return new Command124("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
15261
15818
  const cwd = process.cwd();
15262
15819
  const consent = resolveConsent(cwd, void 0);
15263
15820
  if (!consent.allowed) {
@@ -15294,7 +15851,7 @@ function createTestCommand() {
15294
15851
 
15295
15852
  // src/commands/telemetry/index.ts
15296
15853
  function createTelemetryCommand2() {
15297
- const command = new Command124("telemetry").description("Telemetry identity and status management");
15854
+ const command = new Command125("telemetry").description("Telemetry identity and status management");
15298
15855
  command.addCommand(createIdentifyCommand());
15299
15856
  command.addCommand(createStatusCommand2());
15300
15857
  command.addCommand(createTestCommand());
@@ -15302,9 +15859,9 @@ function createTelemetryCommand2() {
15302
15859
  }
15303
15860
 
15304
15861
  // src/commands/test-craft.ts
15305
- import { Command as Command125 } from "commander";
15862
+ import { Command as Command126 } from "commander";
15306
15863
  function createTestCraftCommand() {
15307
- return new Command125("test-craft").description(
15864
+ return new Command126("test-craft").description(
15308
15865
  "LLM-judgment critique of test quality across vitest/jest/mocha/playwright. Fourth craft-pipeline ceiling skill. Per-test critique with best-effort source pairing."
15309
15866
  ).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) => {
15310
15867
  const globalOpts = cmd.optsWithGlobals();
@@ -15352,10 +15909,10 @@ function printResult7(result, mode, _formatter) {
15352
15909
  list.push(f);
15353
15910
  byFile.set(f.target.file, list);
15354
15911
  }
15355
- for (const [file, fs51] of byFile) {
15912
+ for (const [file, fs52] of byFile) {
15356
15913
  console.log(`
15357
15914
  ${file}`);
15358
- for (const f of fs51) {
15915
+ for (const f of fs52) {
15359
15916
  const nestingStr = f.target.nesting.length > 0 ? f.target.nesting.join(" > ") + " > " : "";
15360
15917
  console.log(
15361
15918
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.framework}:${f.target.line}`
@@ -15374,7 +15931,7 @@ ${file}`);
15374
15931
  }
15375
15932
 
15376
15933
  // src/commands/traceability.ts
15377
- import { Command as Command126 } from "commander";
15934
+ import { Command as Command127 } from "commander";
15378
15935
  import chalk19 from "chalk";
15379
15936
  function confidenceLabel(maxConfidence) {
15380
15937
  if (maxConfidence >= 0.8) return "explicit";
@@ -15514,7 +16071,7 @@ async function runTraceability(options) {
15514
16071
  process.exit(ExitCode.SUCCESS);
15515
16072
  }
15516
16073
  function createTraceabilityCommand() {
15517
- return new Command126("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) => {
16074
+ return new Command127("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) => {
15518
16075
  const globalOpts = cmd.optsWithGlobals();
15519
16076
  await runTraceability({
15520
16077
  spec: opts.spec,
@@ -15527,15 +16084,15 @@ function createTraceabilityCommand() {
15527
16084
  }
15528
16085
 
15529
16086
  // src/commands/uninstall.ts
15530
- import * as path78 from "path";
15531
- import { Command as Command127 } from "commander";
16087
+ import * as path79 from "path";
16088
+ import { Command as Command128 } from "commander";
15532
16089
  async function runUninstall(skillName, options) {
15533
16090
  const packageName = resolvePackageName(skillName);
15534
16091
  const shortName = extractSkillName(packageName);
15535
16092
  const globalDir = resolveGlobalSkillsDir();
15536
- const skillsDir = path78.dirname(globalDir);
15537
- const communityBase = path78.join(skillsDir, "community");
15538
- const lockfilePath = path78.join(communityBase, "skills-lock.json");
16093
+ const skillsDir = path79.dirname(globalDir);
16094
+ const communityBase = path79.join(skillsDir, "community");
16095
+ const lockfilePath = path79.join(communityBase, "skills-lock.json");
15539
16096
  const lockfile = readLockfile2(lockfilePath);
15540
16097
  const entry = lockfile.skills[packageName];
15541
16098
  if (!entry) {
@@ -15565,7 +16122,7 @@ async function runUninstall(skillName, options) {
15565
16122
  return result;
15566
16123
  }
15567
16124
  function createUninstallCommand() {
15568
- const cmd = new Command127("uninstall");
16125
+ const cmd = new Command128("uninstall");
15569
16126
  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) => {
15570
16127
  try {
15571
16128
  const result = await runUninstall(skill, opts);
@@ -15585,9 +16142,9 @@ function createUninstallCommand() {
15585
16142
 
15586
16143
  // src/commands/uninstall-constraints.ts
15587
16144
  init_dist3();
15588
- import * as fs49 from "fs/promises";
15589
- import * as path79 from "path";
15590
- import { Command as Command128 } from "commander";
16145
+ import * as fs50 from "fs/promises";
16146
+ import * as path80 from "path";
16147
+ import { Command as Command129 } from "commander";
15591
16148
  async function runUninstallConstraints(options) {
15592
16149
  const { packageName, configPath, lockfilePath } = options;
15593
16150
  const lockfileResult = await readLockfile(lockfilePath);
@@ -15607,7 +16164,7 @@ async function runUninstallConstraints(options) {
15607
16164
  }
15608
16165
  let localConfig;
15609
16166
  try {
15610
- const raw = await fs49.readFile(configPath, "utf-8");
16167
+ const raw = await fs50.readFile(configPath, "utf-8");
15611
16168
  localConfig = JSON.parse(raw);
15612
16169
  } catch (err) {
15613
16170
  return {
@@ -15644,11 +16201,11 @@ async function runUninstallConstraints(options) {
15644
16201
  };
15645
16202
  }
15646
16203
  function createUninstallConstraintsCommand() {
15647
- const cmd = new Command128("uninstall-constraints");
16204
+ const cmd = new Command129("uninstall-constraints");
15648
16205
  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) => {
15649
16206
  let configPath;
15650
16207
  if (opts.config) {
15651
- configPath = path79.resolve(opts.config);
16208
+ configPath = path80.resolve(opts.config);
15652
16209
  } else {
15653
16210
  const found = findConfigFile();
15654
16211
  if (!found.ok) {
@@ -15657,8 +16214,8 @@ function createUninstallConstraintsCommand() {
15657
16214
  }
15658
16215
  configPath = found.value;
15659
16216
  }
15660
- const projectRoot3 = path79.dirname(configPath);
15661
- const lockfilePath = path79.join(projectRoot3, ".harness", "constraints.lock.json");
16217
+ const projectRoot3 = path80.dirname(configPath);
16218
+ const lockfilePath = path80.join(projectRoot3, ".harness", "constraints.lock.json");
15662
16219
  const result = await runUninstallConstraints({
15663
16220
  packageName: name,
15664
16221
  configPath,
@@ -15684,10 +16241,10 @@ function createUninstallConstraintsCommand() {
15684
16241
 
15685
16242
  // src/commands/update.ts
15686
16243
  init_dist3();
15687
- import { Command as Command129 } from "commander";
16244
+ import { Command as Command130 } from "commander";
15688
16245
  import { execFile as execFile2, execFileSync as execFileSync13 } from "child_process";
15689
- import { realpathSync, existsSync as existsSync45, readFileSync as readFileSync33 } from "fs";
15690
- import { dirname as dirname25, join as join68 } from "path";
16246
+ import { realpathSync, existsSync as existsSync46, readFileSync as readFileSync34 } from "fs";
16247
+ import { dirname as dirname25, join as join69 } from "path";
15691
16248
  import { promisify as promisify2 } from "util";
15692
16249
  import readline4 from "readline";
15693
16250
  import chalk20 from "chalk";
@@ -15778,9 +16335,9 @@ function prompt3(question) {
15778
16335
  function findPackageDir(resolvedBin) {
15779
16336
  let dir = dirname25(resolvedBin);
15780
16337
  for (let i = 0; i < 6; i++) {
15781
- if (existsSync45(join68(dir, "package.json"))) {
16338
+ if (existsSync46(join69(dir, "package.json"))) {
15782
16339
  try {
15783
- const pkg = JSON.parse(readFileSync33(join68(dir, "package.json"), "utf-8"));
16340
+ const pkg = JSON.parse(readFileSync34(join69(dir, "package.json"), "utf-8"));
15784
16341
  if (pkg?.name === CLI_PACKAGE) return dir;
15785
16342
  } catch {
15786
16343
  }
@@ -15825,7 +16382,7 @@ function findAllInstalls() {
15825
16382
  if (!packageDir) continue;
15826
16383
  let version = null;
15827
16384
  try {
15828
- const pkg = JSON.parse(readFileSync33(join68(packageDir, "package.json"), "utf-8"));
16385
+ const pkg = JSON.parse(readFileSync34(join69(packageDir, "package.json"), "utf-8"));
15829
16386
  if (typeof pkg?.version === "string") version = pkg.version;
15830
16387
  } catch {
15831
16388
  }
@@ -15918,12 +16475,12 @@ async function ensureTelemetryIfNeeded() {
15918
16475
  }
15919
16476
  function refreshHooks() {
15920
16477
  const cwd = process.cwd();
15921
- const configPath = join68(cwd, "harness.config.json");
15922
- if (!existsSync45(configPath)) return;
16478
+ const configPath = join69(cwd, "harness.config.json");
16479
+ if (!existsSync46(configPath)) return;
15923
16480
  let profile = "standard";
15924
- const profilePath = join68(cwd, ".harness", "hooks", "profile.json");
16481
+ const profilePath = join69(cwd, ".harness", "hooks", "profile.json");
15925
16482
  try {
15926
- const data = JSON.parse(readFileSync33(profilePath, "utf-8"));
16483
+ const data = JSON.parse(readFileSync34(profilePath, "utf-8"));
15927
16484
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
15928
16485
  profile = data.profile;
15929
16486
  }
@@ -16052,7 +16609,7 @@ async function runUpdateAction(opts, globalOpts) {
16052
16609
  process.exit(ExitCode.SUCCESS);
16053
16610
  }
16054
16611
  function createUpdateCommand() {
16055
- return new Command129("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(
16612
+ return new Command130("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(
16056
16613
  "--regenerate",
16057
16614
  "Only regenerate slash commands and agent definitions (skip package updates)"
16058
16615
  ).action(async (opts, cmd) => {
@@ -16062,9 +16619,9 @@ function createUpdateCommand() {
16062
16619
  }
16063
16620
 
16064
16621
  // src/commands/usage.ts
16065
- import { Command as Command130 } from "commander";
16622
+ import { Command as Command131 } from "commander";
16066
16623
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
16067
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-4CZLCE33.js");
16624
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-DTXVNQAY.js");
16068
16625
  const records = readCostRecords(cwd);
16069
16626
  if (includeClaudeSessions) {
16070
16627
  const ccRecords = parseCCRecords();
@@ -16157,7 +16714,7 @@ function registerDailyCommand(usage) {
16157
16714
  else logger.info("No usage data found. Run some harness sessions first.");
16158
16715
  return;
16159
16716
  }
16160
- const { aggregateByDay } = await import("./dist-4CZLCE33.js");
16717
+ const { aggregateByDay } = await import("./dist-DTXVNQAY.js");
16161
16718
  const limited = aggregateByDay(records).slice(0, days);
16162
16719
  if (globalOpts.json) {
16163
16720
  console.log(
@@ -16186,7 +16743,7 @@ function registerSessionsCommand(usage) {
16186
16743
  }
16187
16744
  return;
16188
16745
  }
16189
- const { aggregateBySession } = await import("./dist-4CZLCE33.js");
16746
+ const { aggregateBySession } = await import("./dist-DTXVNQAY.js");
16190
16747
  const sessionData = aggregateBySession(records);
16191
16748
  const limited = sessionData.slice(0, limit);
16192
16749
  if (globalOpts.json) {
@@ -16266,7 +16823,7 @@ function registerSessionCommand(usage) {
16266
16823
  cwd,
16267
16824
  globalOpts.includeClaudeSessions
16268
16825
  );
16269
- const { aggregateBySession } = await import("./dist-4CZLCE33.js");
16826
+ const { aggregateBySession } = await import("./dist-DTXVNQAY.js");
16270
16827
  const sessionData = aggregateBySession(records);
16271
16828
  const match = sessionData.find((s) => s.sessionId === id);
16272
16829
  if (!match) {
@@ -16301,7 +16858,7 @@ function registerLatestCommand(usage) {
16301
16858
  }
16302
16859
  return;
16303
16860
  }
16304
- const { aggregateBySession } = await import("./dist-4CZLCE33.js");
16861
+ const { aggregateBySession } = await import("./dist-DTXVNQAY.js");
16305
16862
  const sessionData = aggregateBySession(records);
16306
16863
  const latest = sessionData[0];
16307
16864
  if (!latest) {
@@ -16327,7 +16884,7 @@ function registerLatestCommand(usage) {
16327
16884
  });
16328
16885
  }
16329
16886
  function createUsageCommand() {
16330
- const usage = new Command130("usage").description("Token usage and cost tracking");
16887
+ const usage = new Command131("usage").description("Token usage and cost tracking");
16331
16888
  usage.option(
16332
16889
  "--include-claude-sessions",
16333
16890
  "Include Claude Code session data from ~/.claude/projects/"
@@ -16342,9 +16899,9 @@ function createUsageCommand() {
16342
16899
  // src/commands/validate.ts
16343
16900
  init_dist3();
16344
16901
  init_dist3();
16345
- import { Command as Command131 } from "commander";
16346
- import * as fs50 from "fs";
16347
- import * as path80 from "path";
16902
+ import { Command as Command132 } from "commander";
16903
+ import * as fs51 from "fs";
16904
+ import * as path81 from "path";
16348
16905
  import { execFileSync as execFileSync14 } from "child_process";
16349
16906
  async function runValidate(options) {
16350
16907
  const configResult = resolveConfig(options.configPath);
@@ -16352,7 +16909,7 @@ async function runValidate(options) {
16352
16909
  return configResult;
16353
16910
  }
16354
16911
  const config = configResult.value;
16355
- const cwd = options.cwd ?? (options.configPath ? path80.dirname(path80.resolve(options.configPath)) : process.cwd());
16912
+ const cwd = options.cwd ?? (options.configPath ? path81.dirname(path81.resolve(options.configPath)) : process.cwd());
16356
16913
  const result = {
16357
16914
  valid: true,
16358
16915
  checks: {
@@ -16362,7 +16919,7 @@ async function runValidate(options) {
16362
16919
  },
16363
16920
  issues: []
16364
16921
  };
16365
- const agentsMapPath = path80.resolve(cwd, config.agentsMapPath);
16922
+ const agentsMapPath = path81.resolve(cwd, config.agentsMapPath);
16366
16923
  const agentsResult = await validateAgentsMap(agentsMapPath);
16367
16924
  if (agentsResult.ok) {
16368
16925
  result.checks.agentsMap = true;
@@ -16459,9 +17016,9 @@ async function runValidate(options) {
16459
17016
  }
16460
17017
  });
16461
17018
  }
16462
- const gitattributesPath = path80.join(cwd, ".gitattributes");
16463
- if (fs50.existsSync(gitattributesPath)) {
16464
- const gitattributesContent = fs50.readFileSync(gitattributesPath, "utf-8");
17019
+ const gitattributesPath = path81.join(cwd, ".gitattributes");
17020
+ if (fs51.existsSync(gitattributesPath)) {
17021
+ const gitattributesContent = fs51.readFileSync(gitattributesPath, "utf-8");
16465
17022
  let driverConfigured = false;
16466
17023
  try {
16467
17024
  const out = execFileSync14("git", ["config", "--get", "merge.ours.driver"], {
@@ -16485,10 +17042,10 @@ async function runValidate(options) {
16485
17042
  }
16486
17043
  }
16487
17044
  if (detectRoadmapStorageMode(cwd) === "sharded") {
16488
- const shardDir = path80.join(cwd, "docs", "roadmap.d");
17045
+ const shardDir = path81.join(cwd, "docs", "roadmap.d");
16489
17046
  const regenerated = await regenerate(shardDir, createNodeRoadmapIO());
16490
- const aggregatePath = path80.join(cwd, "docs", "roadmap.md");
16491
- const committedAggregate = fs50.existsSync(aggregatePath) ? fs50.readFileSync(aggregatePath, "utf-8") : null;
17047
+ const aggregatePath = path81.join(cwd, "docs", "roadmap.md");
17048
+ const committedAggregate = fs51.existsSync(aggregatePath) ? fs51.readFileSync(aggregatePath, "utf-8") : null;
16492
17049
  const drift = checkRoadmapAggregateDrift({
16493
17050
  shardDirExists: true,
16494
17051
  committedAggregate,
@@ -16506,9 +17063,9 @@ async function runValidate(options) {
16506
17063
  result.checks.roadmapAggregateDrift = true;
16507
17064
  }
16508
17065
  }
16509
- const roadmapPath = path80.join(cwd, "docs", "roadmap.md");
16510
- if (fs50.existsSync(roadmapPath)) {
16511
- const parsed = parseRoadmap(fs50.readFileSync(roadmapPath, "utf-8"));
17066
+ const roadmapPath = path81.join(cwd, "docs", "roadmap.md");
17067
+ if (fs51.existsSync(roadmapPath)) {
17068
+ const parsed = parseRoadmap(fs51.readFileSync(roadmapPath, "utf-8"));
16512
17069
  if (parsed.ok) {
16513
17070
  const findings = checkRoadmapHealth(parsed.value);
16514
17071
  result.checks.roadmapHealth = !findings.some((f) => f.severity === "error");
@@ -16650,11 +17207,11 @@ function resolveValidateMode(globalOpts) {
16650
17207
  return OutputMode.TEXT;
16651
17208
  }
16652
17209
  async function printCrossCheckWarnings(mode) {
16653
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-YYVYMSPA.js");
17210
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-QJGCDWRO.js");
16654
17211
  const cwd = process.cwd();
16655
17212
  const crossResult = await runCrossCheck2({
16656
- specsDir: path80.join(cwd, "docs", "specs"),
16657
- plansDir: path80.join(cwd, "docs", "plans"),
17213
+ specsDir: path81.join(cwd, "docs", "specs"),
17214
+ plansDir: path81.join(cwd, "docs", "plans"),
16658
17215
  projectPath: cwd
16659
17216
  });
16660
17217
  if (!crossResult.ok || crossResult.value.warnings === 0) return;
@@ -16666,7 +17223,7 @@ async function printCrossCheckWarnings(mode) {
16666
17223
  ${crossResult.value.warnings} warnings`);
16667
17224
  }
16668
17225
  function createValidateCommand3() {
16669
- const command = new Command131("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
17226
+ const command = new Command132("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
16670
17227
  "--agent-configs",
16671
17228
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
16672
17229
  ).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()));
@@ -16715,7 +17272,7 @@ Agent configs checked via ${engineLabel}${note}`);
16715
17272
 
16716
17273
  // src/commands/verify.ts
16717
17274
  init_dist3();
16718
- import { Command as Command132 } from "commander";
17275
+ import { Command as Command133 } from "commander";
16719
17276
  import { execSync as execSync6 } from "child_process";
16720
17277
  function loadBranchingConfig(configPath) {
16721
17278
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -16778,7 +17335,7 @@ async function runVerify(options) {
16778
17335
  process.exit(ExitCode.VALIDATION_FAILED);
16779
17336
  }
16780
17337
  function createVerifyCommand() {
16781
- return new Command132("verify").description(
17338
+ return new Command133("verify").description(
16782
17339
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
16783
17340
  ).option(
16784
17341
  "--branch <name>",
@@ -16906,7 +17463,7 @@ function registerDeprecatedGraphAliases(program) {
16906
17463
 
16907
17464
  // src/index.ts
16908
17465
  function createProgram() {
16909
- const program = new Command133();
17466
+ const program = new Command134();
16910
17467
  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");
16911
17468
  for (const creator of commandCreators) {
16912
17469
  program.addCommand(creator());