@harness-engineering/cli 6.0.1 → 8.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-VGDZAWCJ.js → chunk-MSJJU6KH.js} +1022 -377
  18. package/dist/{chunk-6Y6M3AZA.js → chunk-N3S6JTRS.js} +2 -2
  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,658 @@ 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
+ function selectActionableFeatures(roadmap, opts = {}) {
11991
+ let features = roadmap.milestones.flatMap((m) => m.features).filter(isActionable);
11992
+ if (opts.only !== void 0 && opts.only.trim().length > 0) {
11993
+ const needle = opts.only.trim().toLowerCase();
11994
+ features = features.filter((f) => f.name.toLowerCase().includes(needle));
11995
+ }
11996
+ if (opts.limit !== void 0 && opts.limit >= 0) {
11997
+ features = features.slice(0, opts.limit);
11998
+ }
11999
+ return features;
12000
+ }
12001
+ function isPlausibleForModel(verdict) {
12002
+ const scope = verdict.levers.scope.value;
12003
+ const scopeResolvedBounded = scope !== "unknown" && scope.resolved.length > 0;
12004
+ const level = verdict.verdict.level;
12005
+ const inBand = level === "trivial" || level === "simple";
12006
+ return scopeResolvedBounded && inBand;
12007
+ }
12008
+ async function runTriageReport(roadmap, deps = {}) {
12009
+ const features = selectActionableFeatures(roadmap, {
12010
+ ...deps.only !== void 0 ? { only: deps.only } : {},
12011
+ ...deps.limit !== void 0 ? { limit: deps.limit } : {}
12012
+ });
12013
+ const cheapDeps = {
12014
+ ...deps.graphStore ? { graphStore: deps.graphStore } : {},
12015
+ ...deps.precedent ? { precedent: deps.precedent } : {},
12016
+ ...deps.config ? { config: deps.config } : {}
12017
+ };
12018
+ const useModel = deps.offline !== true && deps.provider != null;
12019
+ const rows = [];
12020
+ for (const feature of features) {
12021
+ let verdict = await triageIssue(featureToIssue(feature), cheapDeps);
12022
+ if (useModel && isPlausibleForModel(verdict)) {
12023
+ deps.onProgress?.(`Refining "${feature.name}" on the local model\u2026`);
12024
+ verdict = await triageIssue(featureToIssue(feature), {
12025
+ ...cheapDeps,
12026
+ ...deps.provider ? { provider: deps.provider } : {}
12027
+ });
12028
+ }
12029
+ rows.push({
12030
+ externalId: verdict.externalId,
12031
+ name: feature.name,
12032
+ status: feature.status,
12033
+ ...rankingInputs(feature, verdict),
12034
+ verdict
12035
+ });
12036
+ }
12037
+ return rankTriageCandidates(rows);
12038
+ }
12039
+ function renderHuman(rows) {
12040
+ if (rows.length === 0) return "No actionable roadmap items to triage.";
12041
+ const lines = [];
12042
+ lines.push(`Triaged ${rows.length} actionable item(s):
12043
+ `);
12044
+ for (const row of rows) {
12045
+ const v = row.verdict;
12046
+ const badge = v.dispatchable ? "\u2713 DISPATCHABLE" : `\u2717 HELD (${v.holdReason})`;
12047
+ lines.push(`${badge} ${row.name}`);
12048
+ lines.push(
12049
+ ` level=${v.verdict.level} confidence=${v.verdict.confidence} impact=${row.impact} effort=${row.effort}`
12050
+ );
12051
+ lines.push(` ${v.rationale}`);
12052
+ lines.push("");
12053
+ }
12054
+ const dispatchable = rows.filter((r) => r.verdict.dispatchable).length;
12055
+ lines.push(
12056
+ `${dispatchable}/${rows.length} dispatchable; ${rows.length - dispatchable} to human.`
12057
+ );
12058
+ return lines.join("\n");
12059
+ }
12060
+ function renderJson(rows) {
12061
+ return JSON.stringify(
12062
+ {
12063
+ count: rows.length,
12064
+ dispatchable: rows.filter((r) => r.verdict.dispatchable).length,
12065
+ items: rows.map((r) => ({
12066
+ externalId: r.externalId,
12067
+ name: r.name,
12068
+ status: r.status,
12069
+ dispatchable: r.verdict.dispatchable,
12070
+ holdReason: r.verdict.holdReason ?? null,
12071
+ level: r.verdict.verdict.level,
12072
+ confidence: r.verdict.verdict.confidence,
12073
+ impact: r.impact,
12074
+ effort: r.effort,
12075
+ pilotInputs: { impact: r.impact, confidence: r.confidence, effort: r.effort },
12076
+ levers: r.verdict.levers,
12077
+ rationale: r.verdict.rationale
12078
+ }))
12079
+ },
12080
+ null,
12081
+ 2
12082
+ );
12083
+ }
12084
+ function skippedBrainstormRow(feature, verdict, level) {
12085
+ return {
12086
+ externalId: verdict.externalId,
12087
+ name: feature.name,
12088
+ status: feature.status,
12089
+ level,
12090
+ result: {
12091
+ outcome: {
12092
+ kind: "halted",
12093
+ reason: "error",
12094
+ fork: { id: "scope-gate", question: "", options: [] },
12095
+ detail: `Skipped brainstorm \u2014 not a plausible candidate (${verdict.holdReason ?? "held"}). Held to human by the cheap scope/band gate.`
12096
+ }
12097
+ }
12098
+ };
12099
+ }
12100
+ async function runBrainstormReport(roadmap, deps = {}) {
12101
+ const features = selectActionableFeatures(roadmap, {
12102
+ ...deps.only !== void 0 ? { only: deps.only } : {},
12103
+ ...deps.limit !== void 0 ? { limit: deps.limit } : {}
12104
+ });
12105
+ const rows = [];
12106
+ for (const feature of features) {
12107
+ const issue = featureToIssue(feature);
12108
+ const verdict = await triageIssue(issue, {
12109
+ ...deps.graphStore ? { graphStore: deps.graphStore } : {},
12110
+ ...deps.provider ? { provider: deps.provider } : {},
12111
+ ...deps.precedent ? { precedent: deps.precedent } : {},
12112
+ ...deps.config ? { config: deps.config } : {}
12113
+ });
12114
+ const level = verdict.verdict.level;
12115
+ if (deps.gatePlausible === true && !isPlausibleForModel(verdict)) {
12116
+ rows.push(skippedBrainstormRow(feature, verdict, level));
12117
+ continue;
12118
+ }
12119
+ deps.onProgress?.(`Brainstorming "${feature.name}" [${level}]\u2026`);
12120
+ const wiringDeps = {
12121
+ ...deps.generator ? { generator: deps.generator } : {},
12122
+ ...deps.provider ? { provider: deps.provider } : {},
12123
+ ...deps.generatorOptions ? { generatorOptions: deps.generatorOptions } : {},
12124
+ ...deps.docsRoot ? { docsRoot: deps.docsRoot } : {},
12125
+ // Re-score the enriched item on completion (SC4), reusing the same seams — the
12126
+ // precedent lever included so the RE-SCORE (the prediction the marker records) is
12127
+ // graded against real base-rates too (SC5).
12128
+ rescore: {
12129
+ ...deps.graphStore ? { graphStore: deps.graphStore } : {},
12130
+ ...deps.provider ? { provider: deps.provider } : {},
12131
+ ...deps.precedent ? { precedent: deps.precedent } : {},
12132
+ ...deps.config ? { config: deps.config } : {}
12133
+ }
12134
+ };
12135
+ const result = await runBrainstormForIssue(issue, level, wiringDeps);
12136
+ rows.push({
12137
+ externalId: verdict.externalId,
12138
+ name: feature.name,
12139
+ status: feature.status,
12140
+ level,
12141
+ result
12142
+ });
12143
+ }
12144
+ return rows;
12145
+ }
12146
+ function renderBrainstormHuman(rows) {
12147
+ if (rows.length === 0) return "No actionable roadmap items to brainstorm.";
12148
+ const lines = [];
12149
+ lines.push(`Brainstormed ${rows.length} actionable item(s):
12150
+ `);
12151
+ for (const row of rows) {
12152
+ const o = row.result.outcome;
12153
+ if (o.kind === "completed") {
12154
+ const where = row.result.specPath ? ` \u2192 ${row.result.specPath}` : " (dry run \u2014 no docs root)";
12155
+ lines.push(`\u2713 SPEC DRAFTED ${row.name} [${row.level}]${where}`);
12156
+ lines.push(` ${o.spec.decisions.length} fork(s) resolved at high confidence`);
12157
+ if (row.result.rescore) {
12158
+ const rv = row.result.rescore;
12159
+ lines.push(
12160
+ ` re-score: ${rv.dispatchable ? "DISPATCHABLE" : `held (${rv.holdReason})`} \u2014 ${rv.verdict.level}/${rv.verdict.confidence}`
12161
+ );
12162
+ }
12163
+ } else {
12164
+ lines.push(`\u2717 HALTED \u2192 HUMAN ${row.name} [${row.level}] (${o.reason})`);
12165
+ lines.push(` fork: ${o.fork.question || o.fork.id}`);
12166
+ lines.push(` ${o.detail}`);
12167
+ }
12168
+ lines.push("");
12169
+ }
12170
+ const completed = rows.filter((r) => r.result.outcome.kind === "completed").length;
12171
+ lines.push(
12172
+ `${completed}/${rows.length} spec(s) drafted; ${rows.length - completed} halted to human.`
12173
+ );
12174
+ return lines.join("\n");
12175
+ }
12176
+ function renderBrainstormJson(rows) {
12177
+ return JSON.stringify(
12178
+ {
12179
+ count: rows.length,
12180
+ drafted: rows.filter((r) => r.result.outcome.kind === "completed").length,
12181
+ items: rows.map((r) => {
12182
+ const o = r.result.outcome;
12183
+ return {
12184
+ externalId: r.externalId,
12185
+ name: r.name,
12186
+ status: r.status,
12187
+ level: r.level,
12188
+ outcome: o.kind,
12189
+ ...o.kind === "completed" ? {
12190
+ specPath: r.result.specPath ?? null,
12191
+ forks: o.spec.decisions.map((d) => ({
12192
+ id: d.fork.id,
12193
+ question: d.fork.question,
12194
+ recommendation: d.recommendation,
12195
+ confidence: d.confidence
12196
+ })),
12197
+ rescore: r.result.rescore ? {
12198
+ dispatchable: r.result.rescore.dispatchable,
12199
+ holdReason: r.result.rescore.holdReason ?? null,
12200
+ level: r.result.rescore.verdict.level,
12201
+ confidence: r.result.rescore.verdict.confidence
12202
+ } : null
12203
+ } : {
12204
+ halt: {
12205
+ reason: o.reason,
12206
+ fork: { id: o.fork.id, question: o.fork.question },
12207
+ detail: o.detail
12208
+ }
12209
+ }
12210
+ };
12211
+ })
12212
+ },
12213
+ null,
12214
+ 2
12215
+ );
12216
+ }
12217
+ function resolveBrainstormProvider(configPath, model) {
12218
+ const configResult = resolveConfig(configPath);
12219
+ if (!configResult.ok) return null;
12220
+ return resolveTriageProvider(configResult.value, model);
12221
+ }
12222
+ async function runApproveCommand(cwd, opts) {
12223
+ const configResult = resolveConfig(opts.config);
12224
+ const cfg = configResult.ok ? configResult.value : void 0;
12225
+ const autoTriage = cfg?.roadmap?.autoTriage;
12226
+ if (!autoTriage || autoTriage.enabled !== true) {
12227
+ return { marked: [], held: [], note: "disabled" };
12228
+ }
12229
+ const stage = autoTriage.ratchetStage ?? 1;
12230
+ const roadmapPath = path60.join(cwd, "docs", "roadmap.md");
12231
+ if (!fs36.existsSync(roadmapPath)) {
12232
+ return { marked: [], held: [], note: "no-roadmap" };
12233
+ }
12234
+ const parsed = parseRoadmap(fs36.readFileSync(roadmapPath, "utf-8"));
12235
+ if (!parsed.ok) return { marked: [], held: [], note: "roadmap-parse-error" };
12236
+ const graphStore = await loadGraphStore(cwd);
12237
+ const provider = resolveBrainstormProvider(opts.config);
12238
+ const precedent = await buildPrecedentLookup(cwd);
12239
+ const rows = await runBrainstormReport(parsed.value, {
12240
+ ...graphStore ? { graphStore } : {},
12241
+ ...provider ? { provider } : {},
12242
+ ...precedent ? { precedent } : {},
12243
+ docsRoot: path60.join(cwd, "docs")
12244
+ });
12245
+ const ready = deriveReadyCandidates(rows, parsed.value);
12246
+ const approvedIds = new Set(
12247
+ (opts.approve ?? "").split(",").map((s) => s.trim()).filter((s) => s.length > 0)
12248
+ );
12249
+ const historyForShape = await buildShapeHistory(cwd);
12250
+ const plan = buildApprovalPlan(ready, {
12251
+ approvedIds,
12252
+ ...opts.approveAll ? { approveAll: true } : {},
12253
+ stage,
12254
+ historyForShape
12255
+ });
12256
+ const store = resolveRoadmapStoreForFile({ roadmapPath });
12257
+ const recordPrediction = (payload) => event_sourcing_exports.recordTriagePrediction(cwd, payload);
12258
+ const result = await markApprovedForDispatch(plan.toMark, {
12259
+ store,
12260
+ config: { enabled: true, ratchetStage: stage },
12261
+ recordPrediction
12262
+ });
12263
+ if (!result.ok) {
12264
+ return { marked: [], held: plan.held, note: `mark-failed: ${result.error.message}` };
12265
+ }
12266
+ return { marked: result.value.marked, held: plan.held };
12267
+ }
12268
+ function renderApproveHuman(res) {
12269
+ if (res.note === "disabled") {
12270
+ return "Roadmap auto-triage is disabled (roadmap.autoTriage.enabled is not true). Enable it to use `triage approve`. No changes made.";
12271
+ }
12272
+ if (res.note === "no-roadmap") return "No roadmap aggregate at docs/roadmap.md. No changes made.";
12273
+ if (res.note === "roadmap-parse-error") return "Failed to parse roadmap. No changes made.";
12274
+ const lines = [];
12275
+ if (res.marked.length > 0) {
12276
+ lines.push(`Marked ${res.marked.length} item(s) eligible for orchestrator pickup:`);
12277
+ for (const id of res.marked) lines.push(` \u2713 ${id}`);
12278
+ } else {
12279
+ lines.push("No items marked.");
12280
+ }
12281
+ if (res.held.length > 0) {
12282
+ lines.push(`
12283
+ Held to human (${res.held.length}):`);
12284
+ for (const h of res.held) lines.push(` \u2717 ${h.externalId} \u2014 ${h.reason}`);
12285
+ }
12286
+ if (res.note && res.note.startsWith("mark-failed")) lines.push(`
12287
+ ERROR: ${res.note}`);
12288
+ lines.push(
12289
+ "\nApproved items are NOT dispatched here \u2014 the existing orchestrator pickup loop dispatches them through its normal gating on its next tick."
12290
+ );
12291
+ return lines.join("\n");
12292
+ }
12293
+ function createTriageApproveCommand() {
12294
+ return new Command89("approve").description(
12295
+ "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)."
12296
+ ).option(
12297
+ "--approve <ids>",
12298
+ "Comma-separated externalIds to approve (the explicit human go). Omit to mark nothing."
12299
+ ).option("--approve-all", "Approve every READY candidate (still subject to the category gate).").action(async (opts, cmd) => {
12300
+ const cwd = process.cwd();
12301
+ const globalOpts = cmd.optsWithGlobals();
12302
+ const res = await runApproveCommand(cwd, {
12303
+ ...opts,
12304
+ ...globalOpts.config !== void 0 ? { config: globalOpts.config } : {}
12305
+ });
12306
+ if (globalOpts.json) {
12307
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
12308
+ } else {
12309
+ logger.info(renderApproveHuman(res));
12310
+ }
12311
+ });
12312
+ }
12313
+ function createRoadmapTriageCommand() {
12314
+ return new Command89("triage").description(
12315
+ "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."
12316
+ ).option(
12317
+ "--brainstorm",
12318
+ "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."
12319
+ ).option(
12320
+ "--only <substring>",
12321
+ 'Process ONLY roadmap items whose title contains this substring (case-insensitive). Lets you triage/brainstorm a single item, e.g. --only "prefer-execfile".'
12322
+ ).option(
12323
+ "--limit <n>",
12324
+ "Process at most N items (applied after --only). Useful for a quick partial scan.",
12325
+ (v) => Number.parseInt(v, 10)
12326
+ ).option(
12327
+ "--offline",
12328
+ "Force the pure static path \u2014 never consult the local model. A fast scan that holds every item to a human (byte-identical to running without a resolvable model)."
12329
+ ).action(
12330
+ async (opts, cmd) => {
12331
+ await runTriageCommandAction(opts, cmd);
12332
+ }
12333
+ ).addCommand(createTriageApproveCommand());
12334
+ }
12335
+ async function runTriageCommandAction(opts, cmd) {
12336
+ const cwd = process.cwd();
12337
+ const globalOpts = cmd.optsWithGlobals();
12338
+ const parsed = gateAndParseRoadmap(cwd, globalOpts.config);
12339
+ if (!parsed) return;
12340
+ const graphStore = await loadGraphStore(cwd);
12341
+ const precedent = await buildPrecedentLookup(cwd);
12342
+ const provider = opts.offline === true ? null : resolveBrainstormProvider(globalOpts.config);
12343
+ const onProgress = globalOpts.json === true ? void 0 : (message) => logger.info(message);
12344
+ const shared = {
12345
+ ...graphStore ? { graphStore } : {},
12346
+ ...provider ? { provider } : {},
12347
+ ...precedent ? { precedent } : {},
12348
+ ...opts.only !== void 0 ? { only: opts.only } : {},
12349
+ ...typeof opts.limit === "number" && !Number.isNaN(opts.limit) ? { limit: opts.limit } : {},
12350
+ ...onProgress ? { onProgress } : {}
12351
+ };
12352
+ if (opts.brainstorm) {
12353
+ const rows2 = await runBrainstormReport(parsed, {
12354
+ ...shared,
12355
+ gatePlausible: true,
12356
+ docsRoot: path60.join(cwd, "docs")
12357
+ });
12358
+ emitReport(
12359
+ globalOpts.json === true,
12360
+ () => renderBrainstormJson(rows2),
12361
+ () => renderBrainstormHuman(rows2)
12362
+ );
12363
+ return;
12364
+ }
12365
+ const rows = await runTriageReport(parsed, {
12366
+ ...shared,
12367
+ ...opts.offline === true ? { offline: true } : {}
12368
+ });
12369
+ emitReport(
12370
+ globalOpts.json === true,
12371
+ () => renderJson(rows),
12372
+ () => renderHuman(rows)
12373
+ );
12374
+ }
12375
+ function gateAndParseRoadmap(cwd, configPath) {
12376
+ const configResult = resolveConfig(configPath);
12377
+ const enabled = configResult.ok && configResult.value.roadmap?.autoTriage?.enabled === true;
12378
+ if (!enabled) {
12379
+ logger.info(
12380
+ "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."
12381
+ );
12382
+ return null;
12383
+ }
12384
+ const roadmapPath = path60.join(cwd, "docs", "roadmap.md");
12385
+ if (!fs36.existsSync(roadmapPath)) {
12386
+ logger.error(
12387
+ `No roadmap aggregate at ${roadmapPath}. If your roadmap is sharded, run \`harness roadmap regen\` first, then re-run triage.`
12388
+ );
12389
+ process.exitCode = 1;
12390
+ return null;
12391
+ }
12392
+ const parsed = parseRoadmap(fs36.readFileSync(roadmapPath, "utf-8"));
12393
+ if (!parsed.ok) {
12394
+ logger.error(`Failed to parse roadmap: ${parsed.error.message}`);
12395
+ process.exitCode = 1;
12396
+ return null;
12397
+ }
12398
+ return parsed.value;
12399
+ }
12400
+ function emitReport(json, toJson, toHuman) {
12401
+ if (json) {
12402
+ process.stdout.write(toJson() + "\n");
12403
+ } else {
12404
+ logger.info(toHuman());
12405
+ }
12406
+ }
12407
+
11772
12408
  // src/commands/roadmap/index.ts
11773
12409
  function createRoadmapCommand() {
11774
- const roadmap = new Command89("roadmap").description("Roadmap management");
12410
+ const roadmap = new Command90("roadmap").description("Roadmap management");
11775
12411
  roadmap.addCommand(createRoadmapMigrateCommand());
11776
12412
  roadmap.addCommand(createRoadmapShardCommand());
11777
12413
  roadmap.addCommand(createRoadmapUnshardCommand());
11778
12414
  roadmap.addCommand(createRoadmapRegenCommand());
11779
12415
  roadmap.addCommand(createRoadmapReconcileCommand());
11780
12416
  roadmap.addCommand(createRoadmapReferencedIssuesCommand());
12417
+ roadmap.addCommand(createRoadmapTriageCommand());
11781
12418
  return roadmap;
11782
12419
  }
11783
12420
 
11784
12421
  // src/commands/rollback.ts
11785
12422
  init_dist3();
11786
12423
  import { execFileSync as execFileSync10 } from "child_process";
11787
- import { Command as Command90, Option as Option3, InvalidArgumentError } from "commander";
12424
+ import { Command as Command91, Option as Option3, InvalidArgumentError } from "commander";
11788
12425
 
11789
12426
  // src/rollback/compose.ts
11790
12427
  var ROLLBACK_LABEL = "harness:rollback";
@@ -11842,12 +12479,12 @@ async function composeRevertPr(decision, originalTitle, opts) {
11842
12479
 
11843
12480
  // src/rollback/breadcrumb.ts
11844
12481
  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");
12482
+ import { dirname as dirname20, join as join51 } from "path";
12483
+ var ROLLBACK_EVENTS_FILE = join51(".harness", "signals", "rollback-events.jsonl");
11847
12484
  async function appendRollbackEvent(event, opts = {}) {
11848
12485
  const root = opts.root ?? process.cwd();
11849
12486
  const ts = (opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))();
11850
- const file = join50(root, ROLLBACK_EVENTS_FILE);
12487
+ const file = join51(root, ROLLBACK_EVENTS_FILE);
11851
12488
  mkdirSync19(dirname20(file), { recursive: true });
11852
12489
  appendFileSync(file, `${JSON.stringify({ ...event, ts })}
11853
12490
  `, "utf-8");
@@ -11874,7 +12511,7 @@ async function linkRollbackEventToGraph(event, opts = {}) {
11874
12511
  if (target) {
11875
12512
  store.addEdge({ from: nodeId, to: target.id, type: "references" });
11876
12513
  }
11877
- await store.save(join50(root, ".harness", "graph"));
12514
+ await store.save(join51(root, ".harness", "graph"));
11878
12515
  } catch {
11879
12516
  }
11880
12517
  }
@@ -11906,8 +12543,8 @@ function parseConflictPaths(stdout) {
11906
12543
  if (line === void 0 || line.trim() === "") break;
11907
12544
  const tab = line.indexOf(" ");
11908
12545
  if (tab === -1) continue;
11909
- const path81 = line.slice(tab + 1).trim();
11910
- if (path81) paths.add(path81);
12546
+ const path82 = line.slice(tab + 1).trim();
12547
+ if (path82) paths.add(path82);
11911
12548
  }
11912
12549
  return [...paths];
11913
12550
  }
@@ -12153,7 +12790,7 @@ async function runRollbackSweepCommand(deps) {
12153
12790
  });
12154
12791
  }
12155
12792
  function createRollbackCommand() {
12156
- const rollback = new Command90("rollback").description(
12793
+ const rollback = new Command91("rollback").description(
12157
12794
  "Post-ship revert circuit breaker (propose-only in v1)"
12158
12795
  );
12159
12796
  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 +12843,10 @@ function createRollbackCommand() {
12206
12843
  }
12207
12844
 
12208
12845
  // src/commands/routing/index.ts
12209
- import { Command as Command96 } from "commander";
12846
+ import { Command as Command97 } from "commander";
12210
12847
 
12211
12848
  // src/commands/routing/config.ts
12212
- import { Command as Command91 } from "commander";
12849
+ import { Command as Command92 } from "commander";
12213
12850
 
12214
12851
  // src/commands/routing/http-client.ts
12215
12852
  function orchestratorBase() {
@@ -12219,9 +12856,9 @@ function authHeader() {
12219
12856
  const tok = process.env["HARNESS_API_TOKEN"];
12220
12857
  return tok ? { Authorization: `Bearer ${tok}` } : {};
12221
12858
  }
12222
- async function getJson(path81) {
12859
+ async function getJson(path82) {
12223
12860
  try {
12224
- const res = await fetch(`${orchestratorBase()}${path81}`, {
12861
+ const res = await fetch(`${orchestratorBase()}${path82}`, {
12225
12862
  headers: { ...authHeader() }
12226
12863
  });
12227
12864
  const text = await res.text();
@@ -12236,9 +12873,9 @@ async function getJson(path81) {
12236
12873
  };
12237
12874
  }
12238
12875
  }
12239
- async function postJson(path81, body) {
12876
+ async function postJson(path82, body) {
12240
12877
  try {
12241
- const res = await fetch(`${orchestratorBase()}${path81}`, {
12878
+ const res = await fetch(`${orchestratorBase()}${path82}`, {
12242
12879
  method: "POST",
12243
12880
  headers: { "Content-Type": "application/json", ...authHeader() },
12244
12881
  body: JSON.stringify(body)
@@ -12257,7 +12894,7 @@ async function postJson(path81, body) {
12257
12894
  }
12258
12895
 
12259
12896
  // src/commands/routing/config.ts
12260
- function renderHuman(data) {
12897
+ function renderHuman2(data) {
12261
12898
  console.log("Backends:");
12262
12899
  for (const b of data.backends) console.log(` - ${b}`);
12263
12900
  console.log("");
@@ -12274,7 +12911,7 @@ function renderHuman(data) {
12274
12911
  }
12275
12912
  }
12276
12913
  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) => {
12914
+ 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
12915
  const r = await getJson("/api/v1/routing/config");
12279
12916
  if (!r.ok) {
12280
12917
  if (r.status === 0) {
@@ -12295,12 +12932,12 @@ function createConfigCommand() {
12295
12932
  console.log(JSON.stringify(r.body, null, 2));
12296
12933
  return;
12297
12934
  }
12298
- if (r.body) renderHuman(r.body);
12935
+ if (r.body) renderHuman2(r.body);
12299
12936
  });
12300
12937
  }
12301
12938
 
12302
12939
  // src/commands/routing/trace.ts
12303
- import { Command as Command92 } from "commander";
12940
+ import { Command as Command93 } from "commander";
12304
12941
  var COMPLEXITY_VALUES = ["trivial", "simple", "moderate", "complex"];
12305
12942
  var RISK_VALUES = ["low", "high"];
12306
12943
  function validateEnum(flag, value, allowed) {
@@ -12314,20 +12951,28 @@ function buildUseCase(opts) {
12314
12951
  if (opts.mode) return { kind: "mode", cognitiveMode: opts.mode };
12315
12952
  return null;
12316
12953
  }
12317
- function renderHuman2(r) {
12318
- console.log(`Backend: ${r.decision.backendName} (type: ${r.def.type})`);
12954
+ function renderHuman3(r) {
12955
+ const amr = r.tierRequired !== void 0 && r.costedBackendName !== void 0;
12956
+ const backend = amr ? r.costedBackendName : r.decision.backendName;
12957
+ const type = amr && r.costedBackendType !== void 0 ? r.costedBackendType : r.def.type;
12958
+ console.log(`Backend: ${backend} (type: ${type})`);
12319
12959
  console.log(`Duration: ${r.decision.durationMs.toFixed(2)} ms`);
12320
12960
  console.log("Resolution path:");
12321
12961
  if (r.decision.resolutionPath.length === 0) {
12322
12962
  console.log(" (empty)");
12323
- return;
12324
- }
12325
- for (const step of r.decision.resolutionPath) {
12326
- console.log(` ${step.source}:${step.candidate} -> ${step.outcome}`);
12963
+ } else {
12964
+ for (const step of r.decision.resolutionPath) {
12965
+ console.log(` ${step.source}:${step.candidate} -> ${step.outcome}`);
12966
+ }
12327
12967
  }
12328
12968
  if (r.tierRequired !== void 0) {
12329
12969
  console.log(`Tier required: ${r.tierRequired}`);
12330
12970
  }
12971
+ if (amr && r.costedBackendName !== r.decision.backendName) {
12972
+ console.log(
12973
+ ` (AMR overrides the identity pick '${r.decision.backendName}' \u2192 cheapest backend at/above the tier)`
12974
+ );
12975
+ }
12331
12976
  if (r.estCostUsd !== void 0) {
12332
12977
  console.log(`Est cost: $${r.estCostUsd.toFixed(4)}`);
12333
12978
  }
@@ -12368,17 +13013,17 @@ async function runTrace(opts) {
12368
13013
  console.log(JSON.stringify(r.body, null, 2));
12369
13014
  return;
12370
13015
  }
12371
- if (r.body) renderHuman2(r.body);
13016
+ if (r.body) renderHuman3(r.body);
12372
13017
  }
12373
13018
  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(
13019
+ 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
13020
  "--complexity <level>",
12376
13021
  "Synthetic complexity (trivial|simple|moderate|complex) \u2014 dry-run only"
12377
13022
  ).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
13023
  }
12379
13024
 
12380
13025
  // src/commands/routing/decisions.ts
12381
- import { Command as Command93 } from "commander";
13026
+ import { Command as Command94 } from "commander";
12382
13027
  function summarizeUseCase(uc) {
12383
13028
  switch (uc.kind) {
12384
13029
  case "skill":
@@ -12402,7 +13047,7 @@ function shortIso(iso) {
12402
13047
  const tail = parts[1] ?? iso;
12403
13048
  return tail.replace("Z", "");
12404
13049
  }
12405
- function renderHuman3(data) {
13050
+ function renderHuman4(data) {
12406
13051
  if (data.decisions.length === 0) {
12407
13052
  console.log("(no decisions in buffer)");
12408
13053
  return;
@@ -12426,7 +13071,7 @@ function buildQuery(opts) {
12426
13071
  return q ? `?${q}` : "";
12427
13072
  }
12428
13073
  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(
13074
+ 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
13075
  async (opts) => {
12431
13076
  const query = buildQuery(opts);
12432
13077
  const r = await getJson(`/api/v1/routing/decisions${query}`);
@@ -12449,19 +13094,19 @@ function createDecisionsCommand() {
12449
13094
  console.log(JSON.stringify(r.body, null, 2));
12450
13095
  return;
12451
13096
  }
12452
- if (r.body) renderHuman3(r.body);
13097
+ if (r.body) renderHuman4(r.body);
12453
13098
  }
12454
13099
  );
12455
13100
  }
12456
13101
 
12457
13102
  // src/commands/routing/telemetry.ts
12458
- import { Command as Command94 } from "commander";
13103
+ import { Command as Command95 } from "commander";
12459
13104
  var TIERS = ["fast", "standard", "strong"];
12460
13105
  function shortIso2(iso) {
12461
13106
  const tail = iso.split("T")[1] ?? iso;
12462
13107
  return tail.replace("Z", "");
12463
13108
  }
12464
- function renderHuman4(data, tableLimit) {
13109
+ function renderHuman5(data, tableLimit) {
12465
13110
  if (data.decisions.length === 0) {
12466
13111
  console.log("(no routing telemetry \u2014 AMR is off or no decisions recorded yet)");
12467
13112
  return;
@@ -12499,7 +13144,7 @@ function renderHuman4(data, tableLimit) {
12499
13144
  }
12500
13145
  }
12501
13146
  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) => {
13147
+ 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
13148
  const r = await getJson("/api/v1/routing/telemetry");
12504
13149
  if (!r.ok) {
12505
13150
  if (r.status === 0) {
@@ -12518,18 +13163,18 @@ function createTelemetryCommand() {
12518
13163
  return;
12519
13164
  }
12520
13165
  const tableLimit = opts.last && Number.isFinite(Number(opts.last)) && Number(opts.last) > 0 ? Math.floor(Number(opts.last)) : void 0;
12521
- renderHuman4(body, tableLimit);
13166
+ renderHuman5(body, tableLimit);
12522
13167
  });
12523
13168
  }
12524
13169
 
12525
13170
  // src/commands/routing/status.ts
12526
- import { Command as Command95 } from "commander";
13171
+ import { Command as Command96 } from "commander";
12527
13172
  function bar(pct, width = 24) {
12528
13173
  const clamped = Math.max(0, Math.min(100, pct));
12529
13174
  const filled = Math.round(clamped / 100 * width);
12530
13175
  return `[${"#".repeat(filled)}${"-".repeat(width - filled)}]`;
12531
13176
  }
12532
- function renderHuman5(s) {
13177
+ function renderHuman6(s) {
12533
13178
  if (!s.active) {
12534
13179
  console.log("Adaptive routing: OFF (no routing.policy configured \u2014 dispatch is unchanged)");
12535
13180
  return;
@@ -12563,7 +13208,7 @@ function renderHuman5(s) {
12563
13208
  );
12564
13209
  }
12565
13210
  function createStatusCommand() {
12566
- return new Command95("status").description(
13211
+ return new Command96("status").description(
12567
13212
  "Live routing status: budget spend-vs-cap, escalated units, provider allowlist (AMR)"
12568
13213
  ).option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12569
13214
  const r = await getJson("/api/v1/routing/status");
@@ -12588,13 +13233,13 @@ function createStatusCommand() {
12588
13233
  console.log(JSON.stringify(body, null, 2));
12589
13234
  return;
12590
13235
  }
12591
- renderHuman5(body);
13236
+ renderHuman6(body);
12592
13237
  });
12593
13238
  }
12594
13239
 
12595
13240
  // src/commands/routing/index.ts
12596
13241
  function createRoutingCommand() {
12597
- const cmd = new Command96("routing").description(
13242
+ const cmd = new Command97("routing").description(
12598
13243
  "Inspect routing config, trace decisions, and read AMR telemetry + status"
12599
13244
  );
12600
13245
  cmd.addCommand(createConfigCommand());
@@ -12607,9 +13252,9 @@ function createRoutingCommand() {
12607
13252
 
12608
13253
  // src/commands/scan-config.ts
12609
13254
  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";
13255
+ import { Command as Command98 } from "commander";
13256
+ import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync23 } from "fs";
13257
+ import { join as join52, relative as relative4 } from "path";
12613
13258
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
12614
13259
  function stripHighSeverityPatterns(content, injectionFindings) {
12615
13260
  const highLines = /* @__PURE__ */ new Set();
@@ -12642,10 +13287,10 @@ function applyFix(filePath, targetDir, content, injectionFindings) {
12642
13287
  }
12643
13288
  }
12644
13289
  function scanSingleFile(filePath, targetDir, scanner, options) {
12645
- if (!existsSync31(filePath)) return null;
13290
+ if (!existsSync32(filePath)) return null;
12646
13291
  let content;
12647
13292
  try {
12648
- content = readFileSync22(filePath, "utf8");
13293
+ content = readFileSync23(filePath, "utf8");
12649
13294
  } catch {
12650
13295
  return null;
12651
13296
  }
@@ -12666,7 +13311,7 @@ async function runScanConfig(targetDir, options) {
12666
13311
  const scanner = new SecurityScanner(parseSecurityConfig({}));
12667
13312
  const results = [];
12668
13313
  for (const configFile of CONFIG_FILES) {
12669
- const result = scanSingleFile(join51(targetDir, configFile), targetDir, scanner, options);
13314
+ const result = scanSingleFile(join52(targetDir, configFile), targetDir, scanner, options);
12670
13315
  if (result) results.push(result);
12671
13316
  }
12672
13317
  return { exitCode: computeScanExitCode(results), results };
@@ -12696,7 +13341,7 @@ function formatTextOutput(result) {
12696
13341
  }
12697
13342
  }
12698
13343
  function createScanConfigCommand() {
12699
- const command = new Command97("scan-config").description(
13344
+ const command = new Command98("scan-config").description(
12700
13345
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
12701
13346
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
12702
13347
  const globalOpts = cmd.optsWithGlobals();
@@ -12714,7 +13359,7 @@ function createScanConfigCommand() {
12714
13359
 
12715
13360
  // src/commands/search.ts
12716
13361
  init_dist();
12717
- import { Command as Command98 } from "commander";
13362
+ import { Command as Command99 } from "commander";
12718
13363
  function parseFileKinds(raw) {
12719
13364
  if (!raw) return void 0;
12720
13365
  const set = /* @__PURE__ */ new Set();
@@ -12735,7 +13380,7 @@ function fmtBytes(n) {
12735
13380
  return n.toFixed(0);
12736
13381
  }
12737
13382
  function createSearchCommand() {
12738
- return new Command98("search").description("Full-text search over archived + live session content.").argument(
13383
+ return new Command99("search").description("Full-text search over archived + live session content.").argument(
12739
13384
  "<query>",
12740
13385
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
12741
13386
  ).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 +13440,9 @@ function createSearchCommand() {
12795
13440
  }
12796
13441
 
12797
13442
  // src/commands/security-craft.ts
12798
- import { Command as Command99 } from "commander";
13443
+ import { Command as Command100 } from "commander";
12799
13444
  function createSecurityCraftCommand() {
12800
- return new Command99("security-craft").description(
13445
+ return new Command100("security-craft").description(
12801
13446
  "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
13447
  ).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
13448
  const globalOpts = cmd.optsWithGlobals();
@@ -12844,10 +13489,10 @@ function printResult5(result, mode, _formatter) {
12844
13489
  list.push(f);
12845
13490
  byFile.set(f.target.file, list);
12846
13491
  }
12847
- for (const [file, fs51] of byFile) {
13492
+ for (const [file, fs52] of byFile) {
12848
13493
  console.log(`
12849
13494
  ${file}`);
12850
- for (const f of fs51) {
13495
+ for (const f of fs52) {
12851
13496
  console.log(
12852
13497
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.signal}:${f.target.line}`
12853
13498
  );
@@ -12863,24 +13508,24 @@ ${file}`);
12863
13508
  }
12864
13509
 
12865
13510
  // src/commands/setup.ts
12866
- import { Command as Command100 } from "commander";
12867
- import * as fs38 from "fs";
13511
+ import { Command as Command101 } from "commander";
13512
+ import * as fs39 from "fs";
12868
13513
  import * as os9 from "os";
12869
- import * as path62 from "path";
13514
+ import * as path63 from "path";
12870
13515
  import chalk16 from "chalk";
12871
13516
 
12872
13517
  // src/utils/first-run.ts
12873
- import * as fs36 from "fs";
13518
+ import * as fs37 from "fs";
12874
13519
  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");
13520
+ import * as path61 from "path";
13521
+ var HARNESS_DIR = path61.join(os8.homedir(), ".harness");
13522
+ var MARKER_FILE = path61.join(HARNESS_DIR, ".setup-complete");
12878
13523
  function isFirstRun() {
12879
- return !fs36.existsSync(MARKER_FILE);
13524
+ return !fs37.existsSync(MARKER_FILE);
12880
13525
  }
12881
13526
  function markSetupComplete() {
12882
- fs36.mkdirSync(HARNESS_DIR, { recursive: true });
12883
- fs36.writeFileSync(MARKER_FILE, "", "utf-8");
13527
+ fs37.mkdirSync(HARNESS_DIR, { recursive: true });
13528
+ fs37.writeFileSync(MARKER_FILE, "", "utf-8");
12884
13529
  }
12885
13530
  function printFirstRunWelcome() {
12886
13531
  try {
@@ -12893,8 +13538,8 @@ function printFirstRunWelcome() {
12893
13538
  }
12894
13539
 
12895
13540
  // src/commands/telemetry-wizard.ts
12896
- import * as fs37 from "fs";
12897
- import * as path61 from "path";
13541
+ import * as fs38 from "fs";
13542
+ import * as path62 from "path";
12898
13543
  import readline2 from "readline";
12899
13544
  import chalk15 from "chalk";
12900
13545
  function prompt2(question) {
@@ -12925,21 +13570,21 @@ function isNo(answer) {
12925
13570
  return answer === "n" || answer === "no";
12926
13571
  }
12927
13572
  function isTelemetryConfigured(cwd) {
12928
- const configPath = path61.join(cwd, "harness.config.json");
13573
+ const configPath = path62.join(cwd, "harness.config.json");
12929
13574
  try {
12930
- const raw = JSON.parse(fs37.readFileSync(configPath, "utf-8"));
13575
+ const raw = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
12931
13576
  return raw.telemetry !== void 0 && raw.adoption !== void 0;
12932
13577
  } catch {
12933
13578
  return false;
12934
13579
  }
12935
13580
  }
12936
13581
  function writeTelemetryConfig(cwd, result) {
12937
- const configPath = path61.join(cwd, "harness.config.json");
13582
+ const configPath = path62.join(cwd, "harness.config.json");
12938
13583
  try {
12939
- const raw = JSON.parse(fs37.readFileSync(configPath, "utf-8"));
13584
+ const raw = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
12940
13585
  raw.telemetry = { enabled: result.telemetryEnabled };
12941
13586
  raw.adoption = { enabled: result.adoptionEnabled };
12942
- fs37.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
13587
+ fs38.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
12943
13588
  } catch (err) {
12944
13589
  console.warn(
12945
13590
  `\u26A0 Could not update ${configPath}: ${err instanceof Error ? err.message : String(err)}`
@@ -12947,10 +13592,10 @@ function writeTelemetryConfig(cwd, result) {
12947
13592
  }
12948
13593
  const hasIdentity = result.identity.project || result.identity.team || result.identity.alias;
12949
13594
  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");
13595
+ const harnessDir = path62.join(cwd, ".harness");
13596
+ fs38.mkdirSync(harnessDir, { recursive: true });
13597
+ const telemetryFile = path62.join(harnessDir, "telemetry.json");
13598
+ fs38.writeFileSync(telemetryFile, JSON.stringify({ identity: result.identity }, null, 2) + "\n");
12954
13599
  }
12955
13600
  }
12956
13601
  async function promptIdentity() {
@@ -12996,8 +13641,8 @@ async function runTelemetryWizard() {
12996
13641
  return { telemetryEnabled, adoptionEnabled, identity };
12997
13642
  }
12998
13643
  async function ensureTelemetryConfigured(cwd) {
12999
- const configPath = path61.join(cwd, "harness.config.json");
13000
- if (!fs37.existsSync(configPath)) {
13644
+ const configPath = path62.join(cwd, "harness.config.json");
13645
+ if (!fs38.existsSync(configPath)) {
13001
13646
  return { status: "warn", message: "Not a harness project \u2014 skipped telemetry configuration" };
13002
13647
  }
13003
13648
  if (isTelemetryConfigured(cwd)) {
@@ -13043,7 +13688,7 @@ function runSlashCommandGeneration() {
13043
13688
  }
13044
13689
  }
13045
13690
  function detectClient(dirName) {
13046
- return fs38.existsSync(path62.join(os9.homedir(), dirName));
13691
+ return fs39.existsSync(path63.join(os9.homedir(), dirName));
13047
13692
  }
13048
13693
  async function runMcpSetup(cwd) {
13049
13694
  const results = [];
@@ -13059,7 +13704,7 @@ async function runMcpSetup(cwd) {
13059
13704
  { name: "Cursor", dir: ".cursor", client: "cursor", configTarget: ".cursor/mcp.json" },
13060
13705
  {
13061
13706
  name: "OpenCode",
13062
- dir: path62.join(".config", "opencode"),
13707
+ dir: path63.join(".config", "opencode"),
13063
13708
  client: "opencode",
13064
13709
  configTarget: "opencode.json"
13065
13710
  }
@@ -13091,7 +13736,7 @@ function formatStep(result) {
13091
13736
  }
13092
13737
  function configureTier0Integrations(cwd) {
13093
13738
  try {
13094
- const mcpPath = path62.join(cwd, ".mcp.json");
13739
+ const mcpPath = path63.join(cwd, ".mcp.json");
13095
13740
  const config = readMcpConfig(mcpPath);
13096
13741
  const tier0 = INTEGRATION_REGISTRY.filter((i) => i.tier === 0);
13097
13742
  const added = [];
@@ -13100,9 +13745,9 @@ function configureTier0Integrations(cwd) {
13100
13745
  writeMcpEntry(mcpPath, integration.name, integration.mcpConfig);
13101
13746
  added.push(integration.displayName);
13102
13747
  }
13103
- const geminiDir = path62.join(cwd, ".gemini");
13104
- if (fs38.existsSync(geminiDir)) {
13105
- const geminiPath = path62.join(geminiDir, "settings.json");
13748
+ const geminiDir = path63.join(cwd, ".gemini");
13749
+ if (fs39.existsSync(geminiDir)) {
13750
+ const geminiPath = path63.join(geminiDir, "settings.json");
13106
13751
  const geminiConfig = readMcpConfig(geminiPath);
13107
13752
  for (const integration of tier0) {
13108
13753
  if (!geminiConfig.mcpServers[integration.name]) {
@@ -13110,9 +13755,9 @@ function configureTier0Integrations(cwd) {
13110
13755
  }
13111
13756
  }
13112
13757
  }
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)) {
13758
+ const opencodePath = path63.join(cwd, "opencode.json");
13759
+ const opencodeGlobalDir = path63.join(os9.homedir(), ".config", "opencode");
13760
+ if (fs39.existsSync(opencodePath) || fs39.existsSync(opencodeGlobalDir)) {
13116
13761
  for (const integration of tier0) {
13117
13762
  writeOpencodeMcpEntry(opencodePath, integration.name, integration.mcpConfig);
13118
13763
  }
@@ -13130,14 +13775,14 @@ function configureTier0Integrations(cwd) {
13130
13775
  }
13131
13776
  }
13132
13777
  function ensureHooks(cwd) {
13133
- const configPath = path62.join(cwd, "harness.config.json");
13134
- if (!fs38.existsSync(configPath)) {
13778
+ const configPath = path63.join(cwd, "harness.config.json");
13779
+ if (!fs39.existsSync(configPath)) {
13135
13780
  return { status: "warn", message: "Not a harness project \u2014 skipped hook installation" };
13136
13781
  }
13137
13782
  let profile = "standard";
13138
- const profilePath = path62.join(cwd, ".harness", "hooks", "profile.json");
13783
+ const profilePath = path63.join(cwd, ".harness", "hooks", "profile.json");
13139
13784
  try {
13140
- const data = JSON.parse(fs38.readFileSync(profilePath, "utf-8"));
13785
+ const data = JSON.parse(fs39.readFileSync(profilePath, "utf-8"));
13141
13786
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
13142
13787
  profile = data.profile;
13143
13788
  }
@@ -13208,7 +13853,7 @@ async function runSetup(cwd) {
13208
13853
  return { steps, success };
13209
13854
  }
13210
13855
  function createSetupCommand() {
13211
- return new Command100("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
13856
+ return new Command101("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
13212
13857
  const cwd = process.cwd();
13213
13858
  console.log("");
13214
13859
  console.log(` ${chalk16.bold("harness setup")}`);
@@ -13231,15 +13876,15 @@ function createSetupCommand() {
13231
13876
 
13232
13877
  // src/commands/share.ts
13233
13878
  init_dist3();
13234
- import { Command as Command101 } from "commander";
13235
- import * as fs39 from "fs";
13236
- import * as path63 from "path";
13879
+ import { Command as Command102 } from "commander";
13880
+ import * as fs40 from "fs";
13881
+ import * as path64 from "path";
13237
13882
  import { parse as parseYaml3 } from "yaml";
13238
13883
  var MANIFEST_FILENAME = "constraints.yaml";
13239
13884
  async function runShareAction(projectPath, options) {
13240
- const rootDir = path63.resolve(projectPath);
13241
- const manifestPath = path63.join(rootDir, MANIFEST_FILENAME);
13242
- if (!fs39.existsSync(manifestPath)) {
13885
+ const rootDir = path64.resolve(projectPath);
13886
+ const manifestPath = path64.join(rootDir, MANIFEST_FILENAME);
13887
+ if (!fs40.existsSync(manifestPath)) {
13243
13888
  logger.error(
13244
13889
  `No ${MANIFEST_FILENAME} found at ${manifestPath}.
13245
13890
  Create a constraints.yaml in your project root to define what to share.`
@@ -13248,7 +13893,7 @@ Create a constraints.yaml in your project root to define what to share.`
13248
13893
  }
13249
13894
  let parsed;
13250
13895
  try {
13251
- const raw = fs39.readFileSync(manifestPath, "utf-8");
13896
+ const raw = fs40.readFileSync(manifestPath, "utf-8");
13252
13897
  parsed = parseYaml3(raw);
13253
13898
  } catch (err) {
13254
13899
  logger.error(
@@ -13262,7 +13907,7 @@ Create a constraints.yaml in your project root to define what to share.`
13262
13907
  process.exit(1);
13263
13908
  }
13264
13909
  const manifest = manifestResult.value;
13265
- const configResult = resolveConfig(path63.join(rootDir, "harness.config.json"));
13910
+ const configResult = resolveConfig(path64.join(rootDir, "harness.config.json"));
13266
13911
  if (!configResult.ok) {
13267
13912
  logger.error(configResult.error.message);
13268
13913
  process.exit(1);
@@ -13280,8 +13925,8 @@ Create a constraints.yaml in your project root to define what to share.`
13280
13925
  );
13281
13926
  process.exit(1);
13282
13927
  }
13283
- const outputDir = path63.resolve(options.output);
13284
- const outputPath = path63.join(outputDir, `${manifest.name}.harness-constraints.json`);
13928
+ const outputDir = path64.resolve(options.output);
13929
+ const outputPath = path64.join(outputDir, `${manifest.name}.harness-constraints.json`);
13285
13930
  const writeResult = await writeConfig(outputPath, bundle);
13286
13931
  if (!writeResult.ok) {
13287
13932
  logger.error(`Failed to write bundle: ${writeResult.error.message}`);
@@ -13290,28 +13935,28 @@ Create a constraints.yaml in your project root to define what to share.`
13290
13935
  logger.success(`Bundle written to ${outputPath}`);
13291
13936
  }
13292
13937
  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) => {
13938
+ 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
13939
  await runShareAction(projectPath, options);
13295
13940
  });
13296
13941
  }
13297
13942
 
13298
13943
  // src/commands/skill/index.ts
13299
- import { Command as Command109 } from "commander";
13944
+ import { Command as Command110 } from "commander";
13300
13945
 
13301
13946
  // src/commands/skill/list.ts
13302
- import { Command as Command102 } from "commander";
13303
- import * as fs40 from "fs";
13304
- import * as path64 from "path";
13947
+ import { Command as Command103 } from "commander";
13948
+ import * as fs41 from "fs";
13949
+ import * as path65 from "path";
13305
13950
  import { parse } from "yaml";
13306
13951
  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);
13952
+ if (!fs41.existsSync(dirPath)) return [];
13953
+ const entries = fs41.readdirSync(dirPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
13309
13954
  const skills = [];
13310
13955
  for (const name of entries) {
13311
- const yamlPath = path64.join(dirPath, name, "skill.yaml");
13312
- if (!fs40.existsSync(yamlPath)) continue;
13956
+ const yamlPath = path65.join(dirPath, name, "skill.yaml");
13957
+ if (!fs41.existsSync(yamlPath)) continue;
13313
13958
  try {
13314
- const raw = fs40.readFileSync(yamlPath, "utf-8");
13959
+ const raw = fs41.readFileSync(yamlPath, "utf-8");
13315
13960
  const parsed = parse(raw);
13316
13961
  const result = SkillMetadataSchema.safeParse(parsed);
13317
13962
  if (result.success) {
@@ -13329,10 +13974,10 @@ function scanDirectory(dirPath, source) {
13329
13974
  }
13330
13975
  function collectCommunitySkills(seen, allSkills) {
13331
13976
  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");
13977
+ const skillsDir = path65.dirname(globalDir);
13978
+ const communityBase = path65.join(skillsDir, "community");
13979
+ const communityPlatformDir = path65.join(communityBase, "claude-code");
13980
+ const lockfilePath = path65.join(communityBase, "skills-lock.json");
13336
13981
  const lockfile = readLockfile2(lockfilePath);
13337
13982
  const communitySkills = scanDirectory(communityPlatformDir, "community");
13338
13983
  for (const skill of communitySkills) {
@@ -13402,7 +14047,7 @@ function printSkillsVerbose(skills) {
13402
14047
  for (const s of skills) printSkillEntry(s);
13403
14048
  }
13404
14049
  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) => {
14050
+ 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
14051
  const globalOpts = cmd.optsWithGlobals();
13407
14052
  const skills = collectSkills({ filter: resolveFilter(opts) });
13408
14053
  if (globalOpts.json) {
@@ -13417,9 +14062,9 @@ function createListCommand3() {
13417
14062
  }
13418
14063
 
13419
14064
  // src/commands/skill/run.ts
13420
- import { Command as Command103 } from "commander";
13421
- import * as fs41 from "fs";
13422
- import * as path65 from "path";
14065
+ import { Command as Command104 } from "commander";
14066
+ import * as fs42 from "fs";
14067
+ import * as path66 from "path";
13423
14068
  import { parse as parse2 } from "yaml";
13424
14069
 
13425
14070
  // src/skill/complexity.ts
@@ -13515,10 +14160,10 @@ ${options.principles}`);
13515
14160
 
13516
14161
  // src/commands/skill/run.ts
13517
14162
  function loadSkillMetadata(skillDir) {
13518
- const yamlPath = path65.join(skillDir, "skill.yaml");
13519
- if (!fs41.existsSync(yamlPath)) return null;
14163
+ const yamlPath = path66.join(skillDir, "skill.yaml");
14164
+ if (!fs42.existsSync(yamlPath)) return null;
13520
14165
  try {
13521
- const result = SkillMetadataSchema.safeParse(parse2(fs41.readFileSync(yamlPath, "utf-8")));
14166
+ const result = SkillMetadataSchema.safeParse(parse2(fs42.readFileSync(yamlPath, "utf-8")));
13522
14167
  return result.success ? result.data : null;
13523
14168
  } catch {
13524
14169
  return null;
@@ -13530,22 +14175,22 @@ function resolveComplexity(metadata, requested, projectPath) {
13530
14175
  return requested;
13531
14176
  }
13532
14177
  function loadPrinciples(projectPath) {
13533
- const principlesPath = path65.join(projectPath, "docs", "principles.md");
13534
- return fs41.existsSync(principlesPath) ? fs41.readFileSync(principlesPath, "utf-8") : void 0;
14178
+ const principlesPath = path66.join(projectPath, "docs", "principles.md");
14179
+ return fs42.existsSync(principlesPath) ? fs42.readFileSync(principlesPath, "utf-8") : void 0;
13535
14180
  }
13536
14181
  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");
14182
+ const files = fs42.readdirSync(dirPath).map((f) => ({ name: f, mtime: fs42.statSync(path66.join(dirPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
14183
+ if (files.length > 0) return fs42.readFileSync(path66.join(dirPath, files[0].name), "utf-8");
13539
14184
  return void 0;
13540
14185
  }
13541
14186
  function loadPriorState(metadata, projectPath) {
13542
14187
  if (!metadata?.state.persistent || metadata.state.files.length === 0) return void 0;
13543
14188
  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);
14189
+ const fullPath = path66.join(projectPath, stateFilePath);
14190
+ if (!fs42.existsSync(fullPath)) continue;
14191
+ const stat = fs42.statSync(fullPath);
13547
14192
  if (stat.isDirectory()) return readMostRecentFileInDir(fullPath);
13548
- return fs41.readFileSync(fullPath, "utf-8");
14193
+ return fs42.readFileSync(fullPath, "utf-8");
13549
14194
  }
13550
14195
  return void 0;
13551
14196
  }
@@ -13565,7 +14210,7 @@ function resolvePhaseState(metadata, projectPath, phase) {
13565
14210
  }
13566
14211
  async function appendProjectState(content, metadata, projectPath, hasPathOpt) {
13567
14212
  if (!metadata?.state.persistent || !hasPathOpt) return content;
13568
- const { readHarnessState: readHarnessState2, isEmptyHarnessState } = await import("./state-events-PTWAEGJ2.js");
14213
+ const { readHarnessState: readHarnessState2, isEmptyHarnessState } = await import("./state-events-YLQEYOLI.js");
13569
14214
  const stateResult = await readHarnessState2(projectPath);
13570
14215
  if (!stateResult.ok || isEmptyHarnessState(stateResult.value)) return content;
13571
14216
  const stateContent = JSON.stringify(stateResult.value, null, 2);
@@ -13586,7 +14231,7 @@ async function runSkill(name, opts) {
13586
14231
  return;
13587
14232
  }
13588
14233
  const metadata = loadSkillMetadata(skillDir);
13589
- const projectPath = opts.path ? path65.resolve(opts.path) : process.cwd();
14234
+ const projectPath = opts.path ? path66.resolve(opts.path) : process.cwd();
13590
14235
  const complexity = resolveComplexity(
13591
14236
  metadata,
13592
14237
  opts.complexity ?? "standard",
@@ -13613,14 +14258,14 @@ async function runSkill(name, opts) {
13613
14258
  ...stateWarning !== void 0 && { stateWarning },
13614
14259
  ...opts.party !== void 0 && { party: opts.party }
13615
14260
  });
13616
- const skillMdPath = path65.join(skillDir, "SKILL.md");
13617
- if (!fs41.existsSync(skillMdPath)) {
14261
+ const skillMdPath = path66.join(skillDir, "SKILL.md");
14262
+ if (!fs42.existsSync(skillMdPath)) {
13618
14263
  logger.error(`SKILL.md not found for skill: ${name}`);
13619
14264
  process.exit(ExitCode.ERROR);
13620
14265
  return;
13621
14266
  }
13622
14267
  const content = await appendProjectState(
13623
- fs41.readFileSync(skillMdPath, "utf-8"),
14268
+ fs42.readFileSync(skillMdPath, "utf-8"),
13624
14269
  metadata,
13625
14270
  projectPath,
13626
14271
  !!opts.path
@@ -13631,16 +14276,16 @@ async function runSkill(name, opts) {
13631
14276
  process.exit(ExitCode.SUCCESS);
13632
14277
  }
13633
14278
  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(
14279
+ 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
14280
  "--backend <name>",
13636
14281
  "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
13637
14282
  ).action(async (name, opts) => runSkill(name, opts));
13638
14283
  }
13639
14284
 
13640
14285
  // src/commands/skill/validate.ts
13641
- import { Command as Command104 } from "commander";
13642
- import * as fs42 from "fs";
13643
- import * as path66 from "path";
14286
+ import { Command as Command105 } from "commander";
14287
+ import * as fs43 from "fs";
14288
+ import * as path67 from "path";
13644
14289
  import { parse as parse3 } from "yaml";
13645
14290
  var BEHAVIORAL_REQUIRED_SECTIONS = [
13646
14291
  "## When to Use",
@@ -13652,11 +14297,11 @@ var BEHAVIORAL_REQUIRED_SECTIONS = [
13652
14297
  ];
13653
14298
  var KNOWLEDGE_REQUIRED_SECTIONS = ["## Instructions"];
13654
14299
  function validateSkillMd(name, skillMdPath, skillType, errors) {
13655
- if (!fs42.existsSync(skillMdPath)) {
14300
+ if (!fs43.existsSync(skillMdPath)) {
13656
14301
  errors.push(`${name}: missing SKILL.md`);
13657
14302
  return;
13658
14303
  }
13659
- const mdContent = fs42.readFileSync(skillMdPath, "utf-8");
14304
+ const mdContent = fs43.readFileSync(skillMdPath, "utf-8");
13660
14305
  if (!mdContent.trim().startsWith("# ")) {
13661
14306
  errors.push(`${name}/SKILL.md: must start with an h1 heading`);
13662
14307
  }
@@ -13681,20 +14326,20 @@ function validateSkillMd(name, skillMdPath, skillType, errors) {
13681
14326
  }
13682
14327
  }
13683
14328
  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)) {
14329
+ const skillDir = path67.join(skillsDir, name);
14330
+ const yamlPath = path67.join(skillDir, "skill.yaml");
14331
+ if (!fs43.existsSync(yamlPath)) {
13687
14332
  errors.push(`${name}: missing skill.yaml`);
13688
14333
  return false;
13689
14334
  }
13690
14335
  try {
13691
- const raw = fs42.readFileSync(yamlPath, "utf-8");
14336
+ const raw = fs43.readFileSync(yamlPath, "utf-8");
13692
14337
  const result = SkillMetadataSchema.safeParse(parse3(raw));
13693
14338
  if (!result.success) {
13694
14339
  errors.push(`${name}/skill.yaml: ${result.error.message}`);
13695
14340
  return false;
13696
14341
  }
13697
- validateSkillMd(name, path66.join(skillDir, "SKILL.md"), result.data.type, errors);
14342
+ validateSkillMd(name, path67.join(skillDir, "SKILL.md"), result.data.type, errors);
13698
14343
  return true;
13699
14344
  } catch (e) {
13700
14345
  errors.push(`${name}: parse error \u2014 ${e instanceof Error ? e.message : String(e)}`);
@@ -13702,15 +14347,15 @@ function validateSkillEntry(name, skillsDir, errors) {
13702
14347
  }
13703
14348
  }
13704
14349
  function createValidateCommand2() {
13705
- return new Command104("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
14350
+ return new Command105("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
13706
14351
  const globalOpts = cmd.optsWithGlobals();
13707
14352
  const skillsDir = resolveSkillsDir();
13708
- if (!fs42.existsSync(skillsDir)) {
14353
+ if (!fs43.existsSync(skillsDir)) {
13709
14354
  logger.info("No skills directory found.");
13710
14355
  process.exit(ExitCode.SUCCESS);
13711
14356
  return;
13712
14357
  }
13713
- const entries = fs42.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
14358
+ const entries = fs43.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
13714
14359
  const errors = [];
13715
14360
  let validated = 0;
13716
14361
  for (const name of entries) {
@@ -13732,9 +14377,9 @@ function createValidateCommand2() {
13732
14377
  }
13733
14378
 
13734
14379
  // src/commands/skill/info.ts
13735
- import { Command as Command105 } from "commander";
13736
- import * as fs43 from "fs";
13737
- import * as path67 from "path";
14380
+ import { Command as Command106 } from "commander";
14381
+ import * as fs44 from "fs";
14382
+ import * as path68 from "path";
13738
14383
  import { parse as parse4 } from "yaml";
13739
14384
  function loadSkillMetadata2(name) {
13740
14385
  const skillDir = resolveSkillDir(name);
@@ -13742,13 +14387,13 @@ function loadSkillMetadata2(name) {
13742
14387
  logger.error(`Skill not found: ${name}`);
13743
14388
  return { ok: false, exitCode: ExitCode.ERROR };
13744
14389
  }
13745
- const yamlPath = path67.join(skillDir, "skill.yaml");
13746
- if (!fs43.existsSync(yamlPath)) {
14390
+ const yamlPath = path68.join(skillDir, "skill.yaml");
14391
+ if (!fs44.existsSync(yamlPath)) {
13747
14392
  logger.error(`skill.yaml not found for skill: ${name}`);
13748
14393
  return { ok: false, exitCode: ExitCode.ERROR };
13749
14394
  }
13750
14395
  try {
13751
- const raw = fs43.readFileSync(yamlPath, "utf-8");
14396
+ const raw = fs44.readFileSync(yamlPath, "utf-8");
13752
14397
  const parsed = parse4(raw);
13753
14398
  const result = SkillMetadataSchema.safeParse(parsed);
13754
14399
  if (!result.success) {
@@ -13777,7 +14422,7 @@ function printSkillInfo(skill) {
13777
14422
  console.log(`Persistent: ${skill.state.persistent}`);
13778
14423
  }
13779
14424
  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) => {
14425
+ return new Command106("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
13781
14426
  const globalOpts = cmd.optsWithGlobals();
13782
14427
  const loaded = loadSkillMetadata2(name);
13783
14428
  if (!loaded.ok) {
@@ -13794,7 +14439,7 @@ function createInfoCommand() {
13794
14439
  }
13795
14440
 
13796
14441
  // src/commands/skill/search.ts
13797
- import { Command as Command106 } from "commander";
14442
+ import { Command as Command107 } from "commander";
13798
14443
  async function runSearch(query, opts) {
13799
14444
  const results = await searchNpmRegistry(query, opts.registry);
13800
14445
  return results.filter((r) => {
@@ -13839,15 +14484,15 @@ async function runSearchAction(query, opts, globalOpts) {
13839
14484
  }
13840
14485
  }
13841
14486
  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) => {
14487
+ 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
14488
  await runSearchAction(query, opts, cmd.optsWithGlobals());
13844
14489
  });
13845
14490
  }
13846
14491
 
13847
14492
  // src/commands/skill/create.ts
13848
- import { Command as Command107 } from "commander";
13849
- import * as path68 from "path";
13850
- import * as fs44 from "fs";
14493
+ import { Command as Command108 } from "commander";
14494
+ import * as path69 from "path";
14495
+ import * as fs45 from "fs";
13851
14496
  import YAML from "yaml";
13852
14497
  var KEBAB_CASE_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
13853
14498
  function buildReadme(name, description) {
@@ -13931,22 +14576,22 @@ function runCreate(name, opts) {
13931
14576
  if (!KEBAB_CASE_RE.test(name)) {
13932
14577
  throw new Error(`Invalid skill name "${name}". Must be kebab-case (e.g., my-skill).`);
13933
14578
  }
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)) {
14579
+ const baseDir = opts.outputDir ?? path69.join(process.cwd(), "agents", "skills", "claude-code");
14580
+ const skillDir = path69.join(baseDir, name);
14581
+ if (fs45.existsSync(skillDir)) {
13937
14582
  throw new Error(`Skill directory already exists: ${skillDir}`);
13938
14583
  }
13939
- fs44.mkdirSync(skillDir, { recursive: true });
14584
+ fs45.mkdirSync(skillDir, { recursive: true });
13940
14585
  const description = opts.description || `A community skill: ${name}`;
13941
14586
  const skillYaml = buildSkillYaml(name, opts);
13942
- const skillYamlPath = path68.join(skillDir, "skill.yaml");
13943
- fs44.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
14587
+ const skillYamlPath = path69.join(skillDir, "skill.yaml");
14588
+ fs45.writeFileSync(skillYamlPath, YAML.stringify(skillYaml));
13944
14589
  const skillMd = buildSkillMd(name, description);
13945
- const skillMdPath = path68.join(skillDir, "SKILL.md");
13946
- fs44.writeFileSync(skillMdPath, skillMd);
14590
+ const skillMdPath = path69.join(skillDir, "SKILL.md");
14591
+ fs45.writeFileSync(skillMdPath, skillMd);
13947
14592
  const readme = buildReadme(name, description);
13948
- const readmePath = path68.join(skillDir, "README.md");
13949
- fs44.writeFileSync(readmePath, readme);
14593
+ const readmePath = path69.join(skillDir, "README.md");
14594
+ fs45.writeFileSync(readmePath, readme);
13950
14595
  return {
13951
14596
  name,
13952
14597
  directory: skillDir,
@@ -13960,12 +14605,12 @@ function printCreateResult(name, result) {
13960
14605
  }
13961
14606
  logger.info(`
13962
14607
  Next steps:`);
13963
- logger.info(` 1. Edit ${path68.join(result.directory, "SKILL.md")} with your skill content`);
14608
+ logger.info(` 1. Edit ${path69.join(result.directory, "SKILL.md")} with your skill content`);
13964
14609
  logger.info(` 2. Run: harness skill validate ${name}`);
13965
14610
  logger.info(` 3. Run: harness skills publish`);
13966
14611
  }
13967
14612
  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) => {
14613
+ 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
14614
  const globalOpts = cmd.optsWithGlobals();
13970
14615
  try {
13971
14616
  const result = runCreate(name, {
@@ -13988,26 +14633,26 @@ function createCreateCommand() {
13988
14633
  }
13989
14634
 
13990
14635
  // src/commands/skill/publish.ts
13991
- import { Command as Command108 } from "commander";
13992
- import * as fs46 from "fs";
13993
- import * as path70 from "path";
14636
+ import { Command as Command109 } from "commander";
14637
+ import * as fs47 from "fs";
14638
+ import * as path71 from "path";
13994
14639
  import { execFileSync as execFileSync12 } from "child_process";
13995
14640
 
13996
14641
  // src/registry/validator.ts
13997
- import * as fs45 from "fs";
13998
- import * as path69 from "path";
14642
+ import * as fs46 from "fs";
14643
+ import * as path70 from "path";
13999
14644
  import { parse as parse5 } from "yaml";
14000
14645
  import semver4 from "semver";
14001
14646
  async function validateForPublish(skillDir, registryUrl) {
14002
14647
  const errors = [];
14003
- const skillYamlPath = path69.join(skillDir, "skill.yaml");
14004
- if (!fs45.existsSync(skillYamlPath)) {
14648
+ const skillYamlPath = path70.join(skillDir, "skill.yaml");
14649
+ if (!fs46.existsSync(skillYamlPath)) {
14005
14650
  errors.push("skill.yaml not found. Create one with: harness skill create <name>");
14006
14651
  return { valid: false, errors };
14007
14652
  }
14008
14653
  let skillMeta;
14009
14654
  try {
14010
- const raw = fs45.readFileSync(skillYamlPath, "utf-8");
14655
+ const raw = fs46.readFileSync(skillYamlPath, "utf-8");
14011
14656
  const parsed = parse5(raw);
14012
14657
  const result = SkillMetadataSchema.safeParse(parsed);
14013
14658
  if (!result.success) {
@@ -14029,11 +14674,11 @@ async function validateForPublish(skillDir, registryUrl) {
14029
14674
  if (!skillMeta.triggers || skillMeta.triggers.length === 0) {
14030
14675
  errors.push("At least one trigger is required. Add triggers to skill.yaml.");
14031
14676
  }
14032
- const skillMdPath = path69.join(skillDir, "SKILL.md");
14033
- if (!fs45.existsSync(skillMdPath)) {
14677
+ const skillMdPath = path70.join(skillDir, "SKILL.md");
14678
+ if (!fs46.existsSync(skillMdPath)) {
14034
14679
  errors.push("SKILL.md not found. Create it with content describing your skill.");
14035
14680
  } else {
14036
- const content = fs45.readFileSync(skillMdPath, "utf-8");
14681
+ const content = fs46.readFileSync(skillMdPath, "utf-8");
14037
14682
  if (!content.includes("## When to Use")) {
14038
14683
  errors.push('SKILL.md must contain a "## When to Use" section.');
14039
14684
  }
@@ -14113,11 +14758,11 @@ ${errorList}`);
14113
14758
  }
14114
14759
  const meta = validation.skillMeta;
14115
14760
  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");
14761
+ const pkgPath = path71.join(skillDir, "package.json");
14762
+ fs47.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
14763
+ const readmePath = path71.join(skillDir, "README.md");
14764
+ if (!fs47.existsSync(readmePath)) {
14765
+ const skillMdContent = fs47.readFileSync(path71.join(skillDir, "SKILL.md"), "utf-8");
14121
14766
  const readme = `# ${pkg.name}
14122
14767
 
14123
14768
  ${meta.description}
@@ -14131,7 +14776,7 @@ harness install ${meta.name}
14131
14776
  ---
14132
14777
 
14133
14778
  ${skillMdContent}`;
14134
- fs46.writeFileSync(readmePath, readme);
14779
+ fs47.writeFileSync(readmePath, readme);
14135
14780
  }
14136
14781
  if (opts.dryRun) {
14137
14782
  return {
@@ -14157,7 +14802,7 @@ ${skillMdContent}`;
14157
14802
  };
14158
14803
  }
14159
14804
  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) => {
14805
+ 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
14806
  const globalOpts = cmd.optsWithGlobals();
14162
14807
  const skillDir = opts.dir || process.cwd();
14163
14808
  try {
@@ -14182,7 +14827,7 @@ function createPublishCommand() {
14182
14827
 
14183
14828
  // src/commands/skill/index.ts
14184
14829
  function createSkillCommand() {
14185
- const command = new Command109("skill").description("Skill management commands");
14830
+ const command = new Command110("skill").description("Skill management commands");
14186
14831
  command.addCommand(createListCommand3());
14187
14832
  command.addCommand(createRunCommand3());
14188
14833
  command.addCommand(createValidateCommand2());
@@ -14195,7 +14840,7 @@ function createSkillCommand() {
14195
14840
 
14196
14841
  // src/commands/snapshot.ts
14197
14842
  init_dist3();
14198
- import { Command as Command110 } from "commander";
14843
+ import { Command as Command111 } from "commander";
14199
14844
  import { execSync as execSync5 } from "child_process";
14200
14845
  import chalk17 from "chalk";
14201
14846
  function getCommitHash3(cwd) {
@@ -14377,7 +15022,7 @@ function registerListCommand2(parent) {
14377
15022
  });
14378
15023
  }
14379
15024
  function createSnapshotCommand() {
14380
- const command = new Command110("snapshot").description("Architecture timeline snapshot commands");
15025
+ const command = new Command111("snapshot").description("Architecture timeline snapshot commands");
14381
15026
  registerCaptureCommand(command);
14382
15027
  registerTrendsCommand(command);
14383
15028
  registerListCommand2(command);
@@ -14385,9 +15030,9 @@ function createSnapshotCommand() {
14385
15030
  }
14386
15031
 
14387
15032
  // src/commands/spec-craft.ts
14388
- import { Command as Command111 } from "commander";
15033
+ import { Command as Command112 } from "commander";
14389
15034
  function createSpecCraftCommand() {
14390
- return new Command111("spec-craft").description(
15035
+ return new Command112("spec-craft").description(
14391
15036
  "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
15037
  ).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
15038
  const globalOpts = cmd.optsWithGlobals();
@@ -14435,10 +15080,10 @@ function printResult6(result, mode, _formatter) {
14435
15080
  list.push(f);
14436
15081
  byFile.set(f.target.file, list);
14437
15082
  }
14438
- for (const [file, fs51] of byFile) {
15083
+ for (const [file, fs52] of byFile) {
14439
15084
  console.log(`
14440
15085
  ${file}`);
14441
- for (const f of fs51) {
15086
+ for (const f of fs52) {
14442
15087
  console.log(
14443
15088
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ## ${f.target.section}:${f.target.line}`
14444
15089
  );
@@ -14455,7 +15100,7 @@ ${file}`);
14455
15100
 
14456
15101
  // src/commands/stale-constraints.ts
14457
15102
  init_dist3();
14458
- import { Command as Command112 } from "commander";
15103
+ import { Command as Command113 } from "commander";
14459
15104
  import chalk18 from "chalk";
14460
15105
  var CATEGORIES = [
14461
15106
  "circular-deps",
@@ -14542,7 +15187,7 @@ async function runStaleConstraintsCommand(options) {
14542
15187
  );
14543
15188
  }
14544
15189
  function createStaleConstraintsCommand() {
14545
- return new Command112("stale-constraints").description(
15190
+ return new Command113("stale-constraints").description(
14546
15191
  "Detect architectural constraints not violated within a window (candidates for removal)"
14547
15192
  ).option(
14548
15193
  "--window <days>",
@@ -14560,11 +15205,11 @@ function createStaleConstraintsCommand() {
14560
15205
  }
14561
15206
 
14562
15207
  // src/commands/state/index.ts
14563
- import { Command as Command117 } from "commander";
15208
+ import { Command as Command118 } from "commander";
14564
15209
 
14565
15210
  // src/commands/state/show.ts
14566
- import { Command as Command113 } from "commander";
14567
- import * as path71 from "path";
15211
+ import { Command as Command114 } from "commander";
15212
+ import * as path72 from "path";
14568
15213
  function printStateText(state, stream) {
14569
15214
  if (stream) console.log(`Stream: ${stream}`);
14570
15215
  console.log(`Schema Version: ${state.schemaVersion}`);
@@ -14588,9 +15233,9 @@ function printStateProgress(progress) {
14588
15233
  }
14589
15234
  }
14590
15235
  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) => {
15236
+ 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
15237
  const globalOpts = cmd.optsWithGlobals();
14593
- const result = await readHarnessState(path71.resolve(opts.path), { stream: opts.stream });
15238
+ const result = await readHarnessState(path72.resolve(opts.path), { stream: opts.stream });
14594
15239
  if (!result.ok) {
14595
15240
  logger.error(result.error.message);
14596
15241
  process.exit(ExitCode.ERROR);
@@ -14606,8 +15251,8 @@ function createShowCommand() {
14606
15251
 
14607
15252
  // src/commands/state/reset.ts
14608
15253
  init_dist3();
14609
- import { Command as Command114 } from "commander";
14610
- import * as path72 from "path";
15254
+ import { Command as Command115 } from "commander";
15255
+ import * as path73 from "path";
14611
15256
  import * as readline3 from "readline";
14612
15257
  async function confirmReset() {
14613
15258
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
@@ -14618,7 +15263,7 @@ async function confirmReset() {
14618
15263
  return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
14619
15264
  }
14620
15265
  async function runReset(opts) {
14621
- const projectPath = path72.resolve(opts.path);
15266
+ const projectPath = path73.resolve(opts.path);
14622
15267
  if (!opts.yes && !await confirmReset()) {
14623
15268
  logger.info("Reset cancelled.");
14624
15269
  process.exit(ExitCode.SUCCESS);
@@ -14632,16 +15277,16 @@ async function runReset(opts) {
14632
15277
  process.exit(ExitCode.SUCCESS);
14633
15278
  }
14634
15279
  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));
15280
+ 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
15281
  }
14637
15282
 
14638
15283
  // src/commands/state/learn.ts
14639
15284
  init_dist3();
14640
- import { Command as Command115 } from "commander";
14641
- import * as path73 from "path";
15285
+ import { Command as Command116 } from "commander";
15286
+ import * as path74 from "path";
14642
15287
  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);
15288
+ 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) => {
15289
+ const projectPath = path74.resolve(opts.path);
14645
15290
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
14646
15291
  if (!result.ok) {
14647
15292
  logger.error(result.error.message);
@@ -14655,10 +15300,10 @@ function createLearnCommand() {
14655
15300
 
14656
15301
  // src/commands/state/streams.ts
14657
15302
  init_dist3();
14658
- import { Command as Command116 } from "commander";
14659
- import * as path74 from "path";
15303
+ import { Command as Command117 } from "commander";
15304
+ import * as path75 from "path";
14660
15305
  async function runListStreams(opts, globalOpts) {
14661
- const projectPath = path74.resolve(opts.path);
15306
+ const projectPath = path75.resolve(opts.path);
14662
15307
  const indexResult = await loadStreamIndex(projectPath);
14663
15308
  const result = await listStreams(projectPath);
14664
15309
  if (!result.ok) {
@@ -14679,7 +15324,7 @@ async function runListStreams(opts, globalOpts) {
14679
15324
  process.exit(ExitCode.SUCCESS);
14680
15325
  }
14681
15326
  async function runCreateStream(name, opts) {
14682
- const result = await createStream(path74.resolve(opts.path), name, opts.branch);
15327
+ const result = await createStream(path75.resolve(opts.path), name, opts.branch);
14683
15328
  if (!result.ok) {
14684
15329
  logger.error(result.error.message);
14685
15330
  process.exit(ExitCode.ERROR);
@@ -14688,7 +15333,7 @@ async function runCreateStream(name, opts) {
14688
15333
  process.exit(ExitCode.SUCCESS);
14689
15334
  }
14690
15335
  async function runArchiveStream(name, opts) {
14691
- const result = await archiveStream(path74.resolve(opts.path), name);
15336
+ const result = await archiveStream(path75.resolve(opts.path), name);
14692
15337
  if (!result.ok) {
14693
15338
  logger.error(result.error.message);
14694
15339
  process.exit(ExitCode.ERROR);
@@ -14697,7 +15342,7 @@ async function runArchiveStream(name, opts) {
14697
15342
  process.exit(ExitCode.SUCCESS);
14698
15343
  }
14699
15344
  async function runActivateStream(name, opts) {
14700
- const result = await setActiveStream(path74.resolve(opts.path), name);
15345
+ const result = await setActiveStream(path75.resolve(opts.path), name);
14701
15346
  if (!result.ok) {
14702
15347
  logger.error(result.error.message);
14703
15348
  process.exit(ExitCode.ERROR);
@@ -14706,7 +15351,7 @@ async function runActivateStream(name, opts) {
14706
15351
  process.exit(ExitCode.SUCCESS);
14707
15352
  }
14708
15353
  function createStreamsCommand() {
14709
- const command = new Command116("streams").description("Manage state streams");
15354
+ const command = new Command117("streams").description("Manage state streams");
14710
15355
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
14711
15356
  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
15357
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -14716,7 +15361,7 @@ function createStreamsCommand() {
14716
15361
 
14717
15362
  // src/commands/state/index.ts
14718
15363
  function createStateCommand() {
14719
- const command = new Command117("state").description("Project state management commands");
15364
+ const command = new Command118("state").description("Project state management commands");
14720
15365
  command.addCommand(createShowCommand());
14721
15366
  command.addCommand(createResetCommand());
14722
15367
  command.addCommand(createLearnCommand());
@@ -14725,9 +15370,9 @@ function createStateCommand() {
14725
15370
  }
14726
15371
 
14727
15372
  // src/commands/sync-analyses.ts
14728
- import * as fs47 from "fs";
14729
- import * as path75 from "path";
14730
- import { Command as Command118 } from "commander";
15373
+ import * as fs48 from "fs";
15374
+ import * as path76 from "path";
15375
+ import { Command as Command119 } from "commander";
14731
15376
  init_dist3();
14732
15377
  function isValidRecord(record) {
14733
15378
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -14753,7 +15398,7 @@ function extractAnalysisFromComments(comments) {
14753
15398
  return null;
14754
15399
  }
14755
15400
  function bootstrapTrackerCommand2(opts, verb) {
14756
- const projectPath = path75.resolve(opts.dir);
15401
+ const projectPath = path76.resolve(opts.dir);
14757
15402
  const trackerConfig = loadTrackerSyncConfig(projectPath);
14758
15403
  if (!trackerConfig) {
14759
15404
  logger.error(`No tracker config found in harness.config.json. Cannot ${verb}.`);
@@ -14765,8 +15410,8 @@ function bootstrapTrackerCommand2(opts, verb) {
14765
15410
  );
14766
15411
  return null;
14767
15412
  }
14768
- const projectEnvPath = path75.join(projectPath, ".env");
14769
- if (fs47.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
15413
+ const projectEnvPath = path76.join(projectPath, ".env");
15414
+ if (fs48.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
14770
15415
  __require("dotenv").config({ path: projectEnvPath });
14771
15416
  }
14772
15417
  const token = process.env.GITHUB_TOKEN;
@@ -14852,9 +15497,9 @@ async function runSyncAnalyses(opts) {
14852
15497
  return;
14853
15498
  }
14854
15499
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
14855
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-4CZLCE33.js");
15500
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-DTXVNQAY.js");
14856
15501
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
14857
- const archive = new AnalysisArchive(path75.join(projectPath, ".harness", "analyses"));
15502
+ const archive = new AnalysisArchive(path76.join(projectPath, ".harness", "analyses"));
14858
15503
  const publishedIndex = loadPublishedIndex2(projectPath);
14859
15504
  const { syncedCount, skippedCount, warnCount } = await syncFeatureAnalyses(
14860
15505
  features,
@@ -14874,7 +15519,7 @@ async function runSyncAnalyses(opts) {
14874
15519
  }
14875
15520
  }
14876
15521
  function createSyncAnalysesCommand() {
14877
- const command = new Command118("sync-analyses").description(
15522
+ const command = new Command119("sync-analyses").description(
14878
15523
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
14879
15524
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
14880
15525
  try {
@@ -14888,8 +15533,8 @@ function createSyncAnalysesCommand() {
14888
15533
  }
14889
15534
 
14890
15535
  // src/commands/sync-main.ts
14891
- import { Command as Command119 } from "commander";
14892
- import * as path76 from "path";
15536
+ import { Command as Command120 } from "commander";
15537
+ import * as path77 from "path";
14893
15538
  import {
14894
15539
  syncMain as defaultSyncMain
14895
15540
  } from "@harness-engineering/orchestrator";
@@ -14919,8 +15564,8 @@ function formatHuman2(r) {
14919
15564
  }
14920
15565
  }
14921
15566
  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 ?? ".");
15567
+ 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) => {
15568
+ const cwd = path77.resolve(opts.path ?? ".");
14924
15569
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
14925
15570
  process.exit(exitCode);
14926
15571
  });
@@ -14928,7 +15573,7 @@ function createSyncMainCommand() {
14928
15573
 
14929
15574
  // src/commands/taint.ts
14930
15575
  init_dist3();
14931
- import { Command as Command120 } from "commander";
15576
+ import { Command as Command121 } from "commander";
14932
15577
  function getProjectRoot() {
14933
15578
  return process.cwd();
14934
15579
  }
@@ -15000,28 +15645,28 @@ function registerStatusCommand(taint) {
15000
15645
  });
15001
15646
  }
15002
15647
  function createTaintCommand() {
15003
- const taint = new Command120("taint").description("Manage sentinel session taint state");
15648
+ const taint = new Command121("taint").description("Manage sentinel session taint state");
15004
15649
  registerClearCommand(taint);
15005
15650
  registerStatusCommand(taint);
15006
15651
  return taint;
15007
15652
  }
15008
15653
 
15009
15654
  // src/commands/telemetry/index.ts
15010
- import { Command as Command124 } from "commander";
15655
+ import { Command as Command125 } from "commander";
15011
15656
 
15012
15657
  // src/commands/telemetry/identify.ts
15013
15658
  init_dist3();
15014
- import { Command as Command121 } from "commander";
15015
- import * as fs48 from "fs";
15016
- import * as path77 from "path";
15659
+ import { Command as Command122 } from "commander";
15660
+ import * as fs49 from "fs";
15661
+ import * as path78 from "path";
15017
15662
  function telemetryFilePath(cwd) {
15018
- return path77.join(cwd, ".harness", "telemetry.json");
15663
+ return path78.join(cwd, ".harness", "telemetry.json");
15019
15664
  }
15020
15665
  function writeTelemetryFile(cwd, data) {
15021
15666
  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");
15667
+ const dir = path78.dirname(filePath);
15668
+ fs49.mkdirSync(dir, { recursive: true });
15669
+ fs49.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
15025
15670
  }
15026
15671
  var IDENTITY_FIELDS = ["project", "team", "alias"];
15027
15672
  function applyIdentityFields(opts, identity) {
@@ -15035,7 +15680,7 @@ function printIdentity(identity) {
15035
15680
  }
15036
15681
  }
15037
15682
  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) => {
15683
+ 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
15684
  const cwd = process.cwd();
15040
15685
  if (opts.clear) {
15041
15686
  writeTelemetryFile(cwd, { identity: {} });
@@ -15060,7 +15705,7 @@ function createIdentifyCommand() {
15060
15705
 
15061
15706
  // src/commands/telemetry/status.ts
15062
15707
  init_dist3();
15063
- import { Command as Command122 } from "commander";
15708
+ import { Command as Command123 } from "commander";
15064
15709
  function gatherEnvOverrides() {
15065
15710
  const overrides = {};
15066
15711
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -15102,7 +15747,7 @@ function printHumanStatus(result) {
15102
15747
  printEnvOverrides(result.envOverrides);
15103
15748
  }
15104
15749
  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) => {
15750
+ const cmd = new Command123("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
15106
15751
  const cwd = process.cwd();
15107
15752
  const envOverrides = gatherEnvOverrides();
15108
15753
  const consent = resolveConsent(cwd, void 0);
@@ -15135,11 +15780,11 @@ function createStatusCommand2() {
15135
15780
 
15136
15781
  // src/commands/telemetry/test.ts
15137
15782
  init_dist3();
15138
- import { Command as Command123 } from "commander";
15783
+ import { Command as Command124 } from "commander";
15139
15784
 
15140
15785
  // 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";
15786
+ import { existsSync as existsSync45, readFileSync as readFileSync33, mkdirSync as mkdirSync24, appendFileSync as appendFileSync2, writeFileSync as writeFileSync29 } from "fs";
15787
+ import { join as join66, parse as parsePath, resolve as resolve46 } from "path";
15143
15788
  import { spawn as spawn2 } from "child_process";
15144
15789
  var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
15145
15790
  var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
@@ -15147,7 +15792,7 @@ function findProjectRoot(cwd) {
15147
15792
  let dir = resolve46(cwd);
15148
15793
  const { root } = parsePath(dir);
15149
15794
  while (dir !== root) {
15150
- if (existsSync44(join65(dir, "harness.config.json"))) return dir;
15795
+ if (existsSync45(join66(dir, "harness.config.json"))) return dir;
15151
15796
  dir = resolve46(dir, "..");
15152
15797
  }
15153
15798
  return cwd;
@@ -15185,7 +15830,7 @@ function resolveCommandName(cmd) {
15185
15830
  }
15186
15831
  function writeCommandRecordSync(cwd, command, duration, outcome) {
15187
15832
  try {
15188
- const metricsDir = join65(cwd, ".harness", "metrics");
15833
+ const metricsDir = join66(cwd, ".harness", "metrics");
15189
15834
  mkdirSync24(metricsDir, { recursive: true });
15190
15835
  const record = {
15191
15836
  skill: command,
@@ -15195,16 +15840,16 @@ function writeCommandRecordSync(cwd, command, duration, outcome) {
15195
15840
  outcome,
15196
15841
  phasesReached: []
15197
15842
  };
15198
- const adoptionFile = join65(metricsDir, "adoption.jsonl");
15843
+ const adoptionFile = join66(metricsDir, "adoption.jsonl");
15199
15844
  appendFileSync2(adoptionFile, JSON.stringify(record) + "\n");
15200
15845
  } catch {
15201
15846
  }
15202
15847
  }
15203
15848
  function isTelemetryDisabledByConfig(cwd) {
15204
- const configPath = join65(cwd, "harness.config.json");
15205
- if (!existsSync44(configPath)) return false;
15849
+ const configPath = join66(cwd, "harness.config.json");
15850
+ if (!existsSync45(configPath)) return false;
15206
15851
  try {
15207
- const config = JSON.parse(readFileSync32(configPath, "utf-8"));
15852
+ const config = JSON.parse(readFileSync33(configPath, "utf-8"));
15208
15853
  return config?.telemetry?.enabled === false;
15209
15854
  } catch {
15210
15855
  return false;
@@ -15216,11 +15861,11 @@ function isTelemetryOptedOut(cwd) {
15216
15861
  }
15217
15862
  function flushTelemetryBackground(cwd) {
15218
15863
  try {
15219
- const adoptionFile = join65(cwd, ".harness", "metrics", "adoption.jsonl");
15220
- if (!existsSync44(adoptionFile)) return;
15864
+ const adoptionFile = join66(cwd, ".harness", "metrics", "adoption.jsonl");
15865
+ if (!existsSync45(adoptionFile)) return;
15221
15866
  if (isTelemetryOptedOut(cwd)) return;
15222
- const reporterPath = join65(cwd, ".harness", "hooks", "telemetry-reporter.js");
15223
- if (!existsSync44(reporterPath)) return;
15867
+ const reporterPath = join66(cwd, ".harness", "hooks", "telemetry-reporter.js");
15868
+ if (!existsSync45(reporterPath)) return;
15224
15869
  const child = spawn2(process.execPath, [reporterPath], {
15225
15870
  cwd,
15226
15871
  stdio: ["pipe", "ignore", "ignore"],
@@ -15257,7 +15902,7 @@ function reportTestSuccess(status, distinctId, identity) {
15257
15902
  if (identity.team) logger.info(` team: ${identity.team}`);
15258
15903
  }
15259
15904
  function createTestCommand() {
15260
- return new Command123("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
15905
+ return new Command124("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
15261
15906
  const cwd = process.cwd();
15262
15907
  const consent = resolveConsent(cwd, void 0);
15263
15908
  if (!consent.allowed) {
@@ -15294,7 +15939,7 @@ function createTestCommand() {
15294
15939
 
15295
15940
  // src/commands/telemetry/index.ts
15296
15941
  function createTelemetryCommand2() {
15297
- const command = new Command124("telemetry").description("Telemetry identity and status management");
15942
+ const command = new Command125("telemetry").description("Telemetry identity and status management");
15298
15943
  command.addCommand(createIdentifyCommand());
15299
15944
  command.addCommand(createStatusCommand2());
15300
15945
  command.addCommand(createTestCommand());
@@ -15302,9 +15947,9 @@ function createTelemetryCommand2() {
15302
15947
  }
15303
15948
 
15304
15949
  // src/commands/test-craft.ts
15305
- import { Command as Command125 } from "commander";
15950
+ import { Command as Command126 } from "commander";
15306
15951
  function createTestCraftCommand() {
15307
- return new Command125("test-craft").description(
15952
+ return new Command126("test-craft").description(
15308
15953
  "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
15954
  ).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
15955
  const globalOpts = cmd.optsWithGlobals();
@@ -15352,10 +15997,10 @@ function printResult7(result, mode, _formatter) {
15352
15997
  list.push(f);
15353
15998
  byFile.set(f.target.file, list);
15354
15999
  }
15355
- for (const [file, fs51] of byFile) {
16000
+ for (const [file, fs52] of byFile) {
15356
16001
  console.log(`
15357
16002
  ${file}`);
15358
- for (const f of fs51) {
16003
+ for (const f of fs52) {
15359
16004
  const nestingStr = f.target.nesting.length > 0 ? f.target.nesting.join(" > ") + " > " : "";
15360
16005
  console.log(
15361
16006
  ` ${f.code} [${f.tier}/${f.impact}/${f.confidence}] ${f.target.framework}:${f.target.line}`
@@ -15374,7 +16019,7 @@ ${file}`);
15374
16019
  }
15375
16020
 
15376
16021
  // src/commands/traceability.ts
15377
- import { Command as Command126 } from "commander";
16022
+ import { Command as Command127 } from "commander";
15378
16023
  import chalk19 from "chalk";
15379
16024
  function confidenceLabel(maxConfidence) {
15380
16025
  if (maxConfidence >= 0.8) return "explicit";
@@ -15514,7 +16159,7 @@ async function runTraceability(options) {
15514
16159
  process.exit(ExitCode.SUCCESS);
15515
16160
  }
15516
16161
  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) => {
16162
+ 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
16163
  const globalOpts = cmd.optsWithGlobals();
15519
16164
  await runTraceability({
15520
16165
  spec: opts.spec,
@@ -15527,15 +16172,15 @@ function createTraceabilityCommand() {
15527
16172
  }
15528
16173
 
15529
16174
  // src/commands/uninstall.ts
15530
- import * as path78 from "path";
15531
- import { Command as Command127 } from "commander";
16175
+ import * as path79 from "path";
16176
+ import { Command as Command128 } from "commander";
15532
16177
  async function runUninstall(skillName, options) {
15533
16178
  const packageName = resolvePackageName(skillName);
15534
16179
  const shortName = extractSkillName(packageName);
15535
16180
  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");
16181
+ const skillsDir = path79.dirname(globalDir);
16182
+ const communityBase = path79.join(skillsDir, "community");
16183
+ const lockfilePath = path79.join(communityBase, "skills-lock.json");
15539
16184
  const lockfile = readLockfile2(lockfilePath);
15540
16185
  const entry = lockfile.skills[packageName];
15541
16186
  if (!entry) {
@@ -15565,7 +16210,7 @@ async function runUninstall(skillName, options) {
15565
16210
  return result;
15566
16211
  }
15567
16212
  function createUninstallCommand() {
15568
- const cmd = new Command127("uninstall");
16213
+ const cmd = new Command128("uninstall");
15569
16214
  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
16215
  try {
15571
16216
  const result = await runUninstall(skill, opts);
@@ -15585,9 +16230,9 @@ function createUninstallCommand() {
15585
16230
 
15586
16231
  // src/commands/uninstall-constraints.ts
15587
16232
  init_dist3();
15588
- import * as fs49 from "fs/promises";
15589
- import * as path79 from "path";
15590
- import { Command as Command128 } from "commander";
16233
+ import * as fs50 from "fs/promises";
16234
+ import * as path80 from "path";
16235
+ import { Command as Command129 } from "commander";
15591
16236
  async function runUninstallConstraints(options) {
15592
16237
  const { packageName, configPath, lockfilePath } = options;
15593
16238
  const lockfileResult = await readLockfile(lockfilePath);
@@ -15607,7 +16252,7 @@ async function runUninstallConstraints(options) {
15607
16252
  }
15608
16253
  let localConfig;
15609
16254
  try {
15610
- const raw = await fs49.readFile(configPath, "utf-8");
16255
+ const raw = await fs50.readFile(configPath, "utf-8");
15611
16256
  localConfig = JSON.parse(raw);
15612
16257
  } catch (err) {
15613
16258
  return {
@@ -15644,11 +16289,11 @@ async function runUninstallConstraints(options) {
15644
16289
  };
15645
16290
  }
15646
16291
  function createUninstallConstraintsCommand() {
15647
- const cmd = new Command128("uninstall-constraints");
16292
+ const cmd = new Command129("uninstall-constraints");
15648
16293
  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
16294
  let configPath;
15650
16295
  if (opts.config) {
15651
- configPath = path79.resolve(opts.config);
16296
+ configPath = path80.resolve(opts.config);
15652
16297
  } else {
15653
16298
  const found = findConfigFile();
15654
16299
  if (!found.ok) {
@@ -15657,8 +16302,8 @@ function createUninstallConstraintsCommand() {
15657
16302
  }
15658
16303
  configPath = found.value;
15659
16304
  }
15660
- const projectRoot3 = path79.dirname(configPath);
15661
- const lockfilePath = path79.join(projectRoot3, ".harness", "constraints.lock.json");
16305
+ const projectRoot3 = path80.dirname(configPath);
16306
+ const lockfilePath = path80.join(projectRoot3, ".harness", "constraints.lock.json");
15662
16307
  const result = await runUninstallConstraints({
15663
16308
  packageName: name,
15664
16309
  configPath,
@@ -15684,10 +16329,10 @@ function createUninstallConstraintsCommand() {
15684
16329
 
15685
16330
  // src/commands/update.ts
15686
16331
  init_dist3();
15687
- import { Command as Command129 } from "commander";
16332
+ import { Command as Command130 } from "commander";
15688
16333
  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";
16334
+ import { realpathSync, existsSync as existsSync46, readFileSync as readFileSync34 } from "fs";
16335
+ import { dirname as dirname25, join as join69 } from "path";
15691
16336
  import { promisify as promisify2 } from "util";
15692
16337
  import readline4 from "readline";
15693
16338
  import chalk20 from "chalk";
@@ -15778,9 +16423,9 @@ function prompt3(question) {
15778
16423
  function findPackageDir(resolvedBin) {
15779
16424
  let dir = dirname25(resolvedBin);
15780
16425
  for (let i = 0; i < 6; i++) {
15781
- if (existsSync45(join68(dir, "package.json"))) {
16426
+ if (existsSync46(join69(dir, "package.json"))) {
15782
16427
  try {
15783
- const pkg = JSON.parse(readFileSync33(join68(dir, "package.json"), "utf-8"));
16428
+ const pkg = JSON.parse(readFileSync34(join69(dir, "package.json"), "utf-8"));
15784
16429
  if (pkg?.name === CLI_PACKAGE) return dir;
15785
16430
  } catch {
15786
16431
  }
@@ -15825,7 +16470,7 @@ function findAllInstalls() {
15825
16470
  if (!packageDir) continue;
15826
16471
  let version = null;
15827
16472
  try {
15828
- const pkg = JSON.parse(readFileSync33(join68(packageDir, "package.json"), "utf-8"));
16473
+ const pkg = JSON.parse(readFileSync34(join69(packageDir, "package.json"), "utf-8"));
15829
16474
  if (typeof pkg?.version === "string") version = pkg.version;
15830
16475
  } catch {
15831
16476
  }
@@ -15918,12 +16563,12 @@ async function ensureTelemetryIfNeeded() {
15918
16563
  }
15919
16564
  function refreshHooks() {
15920
16565
  const cwd = process.cwd();
15921
- const configPath = join68(cwd, "harness.config.json");
15922
- if (!existsSync45(configPath)) return;
16566
+ const configPath = join69(cwd, "harness.config.json");
16567
+ if (!existsSync46(configPath)) return;
15923
16568
  let profile = "standard";
15924
- const profilePath = join68(cwd, ".harness", "hooks", "profile.json");
16569
+ const profilePath = join69(cwd, ".harness", "hooks", "profile.json");
15925
16570
  try {
15926
- const data = JSON.parse(readFileSync33(profilePath, "utf-8"));
16571
+ const data = JSON.parse(readFileSync34(profilePath, "utf-8"));
15927
16572
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
15928
16573
  profile = data.profile;
15929
16574
  }
@@ -16052,7 +16697,7 @@ async function runUpdateAction(opts, globalOpts) {
16052
16697
  process.exit(ExitCode.SUCCESS);
16053
16698
  }
16054
16699
  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(
16700
+ 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
16701
  "--regenerate",
16057
16702
  "Only regenerate slash commands and agent definitions (skip package updates)"
16058
16703
  ).action(async (opts, cmd) => {
@@ -16062,9 +16707,9 @@ function createUpdateCommand() {
16062
16707
  }
16063
16708
 
16064
16709
  // src/commands/usage.ts
16065
- import { Command as Command130 } from "commander";
16710
+ import { Command as Command131 } from "commander";
16066
16711
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
16067
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-4CZLCE33.js");
16712
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-DTXVNQAY.js");
16068
16713
  const records = readCostRecords(cwd);
16069
16714
  if (includeClaudeSessions) {
16070
16715
  const ccRecords = parseCCRecords();
@@ -16157,7 +16802,7 @@ function registerDailyCommand(usage) {
16157
16802
  else logger.info("No usage data found. Run some harness sessions first.");
16158
16803
  return;
16159
16804
  }
16160
- const { aggregateByDay } = await import("./dist-4CZLCE33.js");
16805
+ const { aggregateByDay } = await import("./dist-DTXVNQAY.js");
16161
16806
  const limited = aggregateByDay(records).slice(0, days);
16162
16807
  if (globalOpts.json) {
16163
16808
  console.log(
@@ -16186,7 +16831,7 @@ function registerSessionsCommand(usage) {
16186
16831
  }
16187
16832
  return;
16188
16833
  }
16189
- const { aggregateBySession } = await import("./dist-4CZLCE33.js");
16834
+ const { aggregateBySession } = await import("./dist-DTXVNQAY.js");
16190
16835
  const sessionData = aggregateBySession(records);
16191
16836
  const limited = sessionData.slice(0, limit);
16192
16837
  if (globalOpts.json) {
@@ -16266,7 +16911,7 @@ function registerSessionCommand(usage) {
16266
16911
  cwd,
16267
16912
  globalOpts.includeClaudeSessions
16268
16913
  );
16269
- const { aggregateBySession } = await import("./dist-4CZLCE33.js");
16914
+ const { aggregateBySession } = await import("./dist-DTXVNQAY.js");
16270
16915
  const sessionData = aggregateBySession(records);
16271
16916
  const match = sessionData.find((s) => s.sessionId === id);
16272
16917
  if (!match) {
@@ -16301,7 +16946,7 @@ function registerLatestCommand(usage) {
16301
16946
  }
16302
16947
  return;
16303
16948
  }
16304
- const { aggregateBySession } = await import("./dist-4CZLCE33.js");
16949
+ const { aggregateBySession } = await import("./dist-DTXVNQAY.js");
16305
16950
  const sessionData = aggregateBySession(records);
16306
16951
  const latest = sessionData[0];
16307
16952
  if (!latest) {
@@ -16327,7 +16972,7 @@ function registerLatestCommand(usage) {
16327
16972
  });
16328
16973
  }
16329
16974
  function createUsageCommand() {
16330
- const usage = new Command130("usage").description("Token usage and cost tracking");
16975
+ const usage = new Command131("usage").description("Token usage and cost tracking");
16331
16976
  usage.option(
16332
16977
  "--include-claude-sessions",
16333
16978
  "Include Claude Code session data from ~/.claude/projects/"
@@ -16342,9 +16987,9 @@ function createUsageCommand() {
16342
16987
  // src/commands/validate.ts
16343
16988
  init_dist3();
16344
16989
  init_dist3();
16345
- import { Command as Command131 } from "commander";
16346
- import * as fs50 from "fs";
16347
- import * as path80 from "path";
16990
+ import { Command as Command132 } from "commander";
16991
+ import * as fs51 from "fs";
16992
+ import * as path81 from "path";
16348
16993
  import { execFileSync as execFileSync14 } from "child_process";
16349
16994
  async function runValidate(options) {
16350
16995
  const configResult = resolveConfig(options.configPath);
@@ -16352,7 +16997,7 @@ async function runValidate(options) {
16352
16997
  return configResult;
16353
16998
  }
16354
16999
  const config = configResult.value;
16355
- const cwd = options.cwd ?? (options.configPath ? path80.dirname(path80.resolve(options.configPath)) : process.cwd());
17000
+ const cwd = options.cwd ?? (options.configPath ? path81.dirname(path81.resolve(options.configPath)) : process.cwd());
16356
17001
  const result = {
16357
17002
  valid: true,
16358
17003
  checks: {
@@ -16362,7 +17007,7 @@ async function runValidate(options) {
16362
17007
  },
16363
17008
  issues: []
16364
17009
  };
16365
- const agentsMapPath = path80.resolve(cwd, config.agentsMapPath);
17010
+ const agentsMapPath = path81.resolve(cwd, config.agentsMapPath);
16366
17011
  const agentsResult = await validateAgentsMap(agentsMapPath);
16367
17012
  if (agentsResult.ok) {
16368
17013
  result.checks.agentsMap = true;
@@ -16459,9 +17104,9 @@ async function runValidate(options) {
16459
17104
  }
16460
17105
  });
16461
17106
  }
16462
- const gitattributesPath = path80.join(cwd, ".gitattributes");
16463
- if (fs50.existsSync(gitattributesPath)) {
16464
- const gitattributesContent = fs50.readFileSync(gitattributesPath, "utf-8");
17107
+ const gitattributesPath = path81.join(cwd, ".gitattributes");
17108
+ if (fs51.existsSync(gitattributesPath)) {
17109
+ const gitattributesContent = fs51.readFileSync(gitattributesPath, "utf-8");
16465
17110
  let driverConfigured = false;
16466
17111
  try {
16467
17112
  const out = execFileSync14("git", ["config", "--get", "merge.ours.driver"], {
@@ -16485,10 +17130,10 @@ async function runValidate(options) {
16485
17130
  }
16486
17131
  }
16487
17132
  if (detectRoadmapStorageMode(cwd) === "sharded") {
16488
- const shardDir = path80.join(cwd, "docs", "roadmap.d");
17133
+ const shardDir = path81.join(cwd, "docs", "roadmap.d");
16489
17134
  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;
17135
+ const aggregatePath = path81.join(cwd, "docs", "roadmap.md");
17136
+ const committedAggregate = fs51.existsSync(aggregatePath) ? fs51.readFileSync(aggregatePath, "utf-8") : null;
16492
17137
  const drift = checkRoadmapAggregateDrift({
16493
17138
  shardDirExists: true,
16494
17139
  committedAggregate,
@@ -16506,9 +17151,9 @@ async function runValidate(options) {
16506
17151
  result.checks.roadmapAggregateDrift = true;
16507
17152
  }
16508
17153
  }
16509
- const roadmapPath = path80.join(cwd, "docs", "roadmap.md");
16510
- if (fs50.existsSync(roadmapPath)) {
16511
- const parsed = parseRoadmap(fs50.readFileSync(roadmapPath, "utf-8"));
17154
+ const roadmapPath = path81.join(cwd, "docs", "roadmap.md");
17155
+ if (fs51.existsSync(roadmapPath)) {
17156
+ const parsed = parseRoadmap(fs51.readFileSync(roadmapPath, "utf-8"));
16512
17157
  if (parsed.ok) {
16513
17158
  const findings = checkRoadmapHealth(parsed.value);
16514
17159
  result.checks.roadmapHealth = !findings.some((f) => f.severity === "error");
@@ -16650,11 +17295,11 @@ function resolveValidateMode(globalOpts) {
16650
17295
  return OutputMode.TEXT;
16651
17296
  }
16652
17297
  async function printCrossCheckWarnings(mode) {
16653
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-YYVYMSPA.js");
17298
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-QJGCDWRO.js");
16654
17299
  const cwd = process.cwd();
16655
17300
  const crossResult = await runCrossCheck2({
16656
- specsDir: path80.join(cwd, "docs", "specs"),
16657
- plansDir: path80.join(cwd, "docs", "plans"),
17301
+ specsDir: path81.join(cwd, "docs", "specs"),
17302
+ plansDir: path81.join(cwd, "docs", "plans"),
16658
17303
  projectPath: cwd
16659
17304
  });
16660
17305
  if (!crossResult.ok || crossResult.value.warnings === 0) return;
@@ -16666,7 +17311,7 @@ async function printCrossCheckWarnings(mode) {
16666
17311
  ${crossResult.value.warnings} warnings`);
16667
17312
  }
16668
17313
  function createValidateCommand3() {
16669
- const command = new Command131("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
17314
+ const command = new Command132("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
16670
17315
  "--agent-configs",
16671
17316
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
16672
17317
  ).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 +17360,7 @@ Agent configs checked via ${engineLabel}${note}`);
16715
17360
 
16716
17361
  // src/commands/verify.ts
16717
17362
  init_dist3();
16718
- import { Command as Command132 } from "commander";
17363
+ import { Command as Command133 } from "commander";
16719
17364
  import { execSync as execSync6 } from "child_process";
16720
17365
  function loadBranchingConfig(configPath) {
16721
17366
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -16778,7 +17423,7 @@ async function runVerify(options) {
16778
17423
  process.exit(ExitCode.VALIDATION_FAILED);
16779
17424
  }
16780
17425
  function createVerifyCommand() {
16781
- return new Command132("verify").description(
17426
+ return new Command133("verify").description(
16782
17427
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
16783
17428
  ).option(
16784
17429
  "--branch <name>",
@@ -16906,7 +17551,7 @@ function registerDeprecatedGraphAliases(program) {
16906
17551
 
16907
17552
  // src/index.ts
16908
17553
  function createProgram() {
16909
- const program = new Command133();
17554
+ const program = new Command134();
16910
17555
  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
17556
  for (const creator of commandCreators) {
16912
17557
  program.addCommand(creator());