@harness-engineering/cli 4.3.2 → 5.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 (76) hide show
  1. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +3 -1
  2. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +5 -0
  3. package/dist/agents/skills/claude-code/harness-rollback/SKILL.md +124 -0
  4. package/dist/agents/skills/claude-code/harness-rollback/skill.yaml +52 -0
  5. package/dist/agents/skills/claude-code/product-requirements/SKILL.md +150 -0
  6. package/dist/agents/skills/claude-code/product-requirements/skill.yaml +70 -0
  7. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +3 -1
  8. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +5 -0
  9. package/dist/agents/skills/codex/harness-rollback/SKILL.md +124 -0
  10. package/dist/agents/skills/codex/harness-rollback/skill.yaml +52 -0
  11. package/dist/agents/skills/codex/product-requirements/SKILL.md +150 -0
  12. package/dist/agents/skills/codex/product-requirements/skill.yaml +70 -0
  13. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +3 -1
  14. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +5 -0
  15. package/dist/agents/skills/cursor/harness-rollback/SKILL.md +124 -0
  16. package/dist/agents/skills/cursor/harness-rollback/skill.yaml +52 -0
  17. package/dist/agents/skills/cursor/product-requirements/SKILL.md +150 -0
  18. package/dist/agents/skills/cursor/product-requirements/skill.yaml +70 -0
  19. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +3 -1
  20. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +5 -0
  21. package/dist/agents/skills/gemini-cli/harness-rollback/SKILL.md +124 -0
  22. package/dist/agents/skills/gemini-cli/harness-rollback/skill.yaml +52 -0
  23. package/dist/agents/skills/gemini-cli/product-requirements/SKILL.md +150 -0
  24. package/dist/agents/skills/gemini-cli/product-requirements/skill.yaml +70 -0
  25. package/dist/{agents-md-N4ULMUAK.js → agents-md-GOFDOUEI.js} +4 -4
  26. package/dist/{analyzer-XRCV63KC-WGRHW2ZM.js → analyzer-XRCV63KC-CUGBENHK.js} +2 -2
  27. package/dist/{architecture-OIMIBDJC.js → architecture-UJZTBKJ2.js} +5 -5
  28. package/dist/{assess-project-ITSB6W4L.js → assess-project-S3UOQUQW.js} +1 -1
  29. package/dist/bin/harness-mcp.js +15 -15
  30. package/dist/bin/harness.js +25 -25
  31. package/dist/{check-phase-gate-GN4X7HT6.js → check-phase-gate-SQ2X2Q7T.js} +5 -5
  32. package/dist/{chunk-F3GNBRGL.js → chunk-4ITYAEOA.js} +85 -85
  33. package/dist/{chunk-H5GN7R43.js → chunk-6RXT67Q4.js} +2 -2
  34. package/dist/{chunk-GTHL3TRZ.js → chunk-7BBQ5C7I.js} +2 -2
  35. package/dist/{chunk-574JCBYH.js → chunk-AIFPI3UZ.js} +2 -2
  36. package/dist/{chunk-CRHQYBDA.js → chunk-CFK4RJFP.js} +89 -4
  37. package/dist/{chunk-TKPAOB2T.js → chunk-DFWM2SNS.js} +2 -2
  38. package/dist/{chunk-LP764MGR.js → chunk-DPG2WNSN.js} +3 -3
  39. package/dist/{chunk-T46G6YNI.js → chunk-DSXUS6KG.js} +3 -3
  40. package/dist/{chunk-CMU4DNLY.js → chunk-DU6AUYTA.js} +1 -1
  41. package/dist/{chunk-MEDRUIRO.js → chunk-FXO3EODY.js} +3 -3
  42. package/dist/{chunk-D7A5JR7M.js → chunk-JGW4CHIJ.js} +2 -2
  43. package/dist/{chunk-JZL2O3RC.js → chunk-KI64IQLS.js} +5 -5
  44. package/dist/{chunk-5BUHPOCP.js → chunk-OIMJWYWF.js} +7 -7
  45. package/dist/{chunk-HJYAXAYQ.js → chunk-OWJTMHVP.js} +2 -2
  46. package/dist/{chunk-YVI7ZV73.js → chunk-PSFJ5YKQ.js} +585 -154
  47. package/dist/{chunk-VJDSB7CI.js → chunk-R5C7ZFON.js} +14 -0
  48. package/dist/{chunk-MIZQY35D.js → chunk-RD75T4XK.js} +2 -2
  49. package/dist/{chunk-7RH2NTLA.js → chunk-RPOBWUKV.js} +1 -1
  50. package/dist/{chunk-U2NOOATF.js → chunk-SQDQMVNE.js} +6 -6
  51. package/dist/{chunk-6NEJPS7W.js → chunk-T2PQWRRK.js} +2 -2
  52. package/dist/{chunk-NEMB36N4.js → chunk-UJW4POA3.js} +2 -2
  53. package/dist/{chunk-LTYVAKWK.js → chunk-V6QYVM6K.js} +20 -2
  54. package/dist/{chunk-PT65VY4S.js → chunk-WHPZG5TX.js} +6 -6
  55. package/dist/{chunk-XKILFNRK.js → chunk-XC7NR63Q.js} +2 -2
  56. package/dist/{chunk-73QZ43DF.js → chunk-YE7NZ44F.js} +2 -2
  57. package/dist/{ci-workflow-PA3WL6WK.js → ci-workflow-5WHUEHOF.js} +4 -4
  58. package/dist/{dist-ISDDHDOR.js → dist-O7MTFDG5.js} +1 -1
  59. package/dist/{dist-BWFFVKEW.js → dist-SOKOW7BC.js} +5 -3
  60. package/dist/{docs-HOTWQJQF.js → docs-AEHPPDKX.js} +5 -5
  61. package/dist/{engine-MVG2SPGD.js → engine-HYM5SLCD.js} +4 -4
  62. package/dist/{entropy-3B4U2BTF.js → entropy-6KH5G3NR.js} +5 -5
  63. package/dist/{feedback-WIWWDVUC.js → feedback-AUP2JK43.js} +1 -1
  64. package/dist/{generate-agent-definitions-KPRHY6X3.js → generate-agent-definitions-OH4RF445.js} +5 -5
  65. package/dist/index.d.ts +66 -0
  66. package/dist/index.js +25 -25
  67. package/dist/{loader-SPJ2ZGYW.js → loader-KWRPA7D5.js} +4 -4
  68. package/dist/{mcp-VSSIWTII.js → mcp-JTPO5RAK.js} +15 -15
  69. package/dist/{performance-JYFS27B3.js → performance-HW53ZIAF.js} +5 -5
  70. package/dist/{review-pipeline-BDT6Y6QV.js → review-pipeline-2R7UBFTG.js} +4 -4
  71. package/dist/{runtime-ZEPHPPQJ.js → runtime-BB35PFZY.js} +4 -4
  72. package/dist/{security-FWSDTTEW.js → security-IDJHGBBH.js} +1 -1
  73. package/dist/{state-events-PBDNQPXT.js → state-events-H3GGBKTB.js} +4 -4
  74. package/dist/{validate-XIMNCIKR.js → validate-6SDGP7AH.js} +5 -5
  75. package/dist/{validate-cross-check-H2OUHTID.js → validate-cross-check-OF3FPM32.js} +4 -4
  76. package/package.json +8 -8
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  generateRuntime
3
- } from "./chunk-574JCBYH.js";
3
+ } from "./chunk-AIFPI3UZ.js";
4
4
  import {
5
5
  generateAgentsMd
6
- } from "./chunk-TKPAOB2T.js";
6
+ } from "./chunk-DFWM2SNS.js";
7
7
  import {
8
8
  generateCIWorkflow
9
- } from "./chunk-GTHL3TRZ.js";
9
+ } from "./chunk-7BBQ5C7I.js";
10
10
  import {
11
11
  readHarnessState
12
- } from "./chunk-NEMB36N4.js";
12
+ } from "./chunk-UJW4POA3.js";
13
13
  import {
14
14
  runCrossCheck
15
- } from "./chunk-MIZQY35D.js";
15
+ } from "./chunk-RD75T4XK.js";
16
16
  import {
17
17
  createGenerateAgentDefinitionsCommand,
18
18
  generateAgentDefinitions
19
- } from "./chunk-CMU4DNLY.js";
19
+ } from "./chunk-DU6AUYTA.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-6NEJPS7W.js";
29
+ } from "./chunk-T2PQWRRK.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-73QZ43DF.js";
40
+ } from "./chunk-YE7NZ44F.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-LP764MGR.js";
54
+ } from "./chunk-DPG2WNSN.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-F3GNBRGL.js";
82
+ } from "./chunk-4ITYAEOA.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-LTYVAKWK.js";
111
+ } from "./chunk-V6QYVM6K.js";
112
112
  import {
113
113
  logger
114
114
  } from "./chunk-EBJQ6N4M.js";
@@ -146,6 +146,7 @@ import {
146
146
  checkRoadmapAggregateDrift,
147
147
  checkRoadmapHealth,
148
148
  checkTaint,
149
+ classifyRevert,
149
150
  clearTaint,
150
151
  computeHotspots,
151
152
  computeOverallSeverity,
@@ -225,7 +226,7 @@ import {
225
226
  writeConfig,
226
227
  writeLockfile,
227
228
  writeRegeneratedRoadmap
228
- } from "./chunk-CRHQYBDA.js";
229
+ } from "./chunk-CFK4RJFP.js";
229
230
  import {
230
231
  CLI_VERSION
231
232
  } from "./chunk-BM3PWGXQ.js";
@@ -238,14 +239,14 @@ import {
238
239
  detectDocDrift,
239
240
  generateSuggestions,
240
241
  validateDependencies
241
- } from "./chunk-7RH2NTLA.js";
242
+ } from "./chunk-RPOBWUKV.js";
242
243
  import {
243
244
  Err,
244
245
  INDEXED_FILE_KINDS,
245
246
  INSIGHTS_KEYS,
246
247
  Ok,
247
248
  init_dist
248
- } from "./chunk-VJDSB7CI.js";
249
+ } from "./chunk-R5C7ZFON.js";
249
250
  import {
250
251
  DEFAULT_SKIP_DIRS,
251
252
  DesignConstraintAdapter,
@@ -262,7 +263,7 @@ import {
262
263
  } from "./chunk-KFQGP6VL.js";
263
264
 
264
265
  // src/index.ts
265
- import { Command as Command130 } from "commander";
266
+ import { Command as Command131 } from "commander";
266
267
 
267
268
  // src/commands/add.ts
268
269
  init_dist3();
@@ -453,7 +454,7 @@ function registerSkillsCommand(adoption) {
453
454
  const globalOpts = cmd.optsWithGlobals();
454
455
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
455
456
  const cwd = process.cwd();
456
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-BWFFVKEW.js");
457
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-SOKOW7BC.js");
457
458
  const records = readAdoptionRecords(cwd);
458
459
  if (records.length === 0) {
459
460
  if (globalOpts.json) {
@@ -489,7 +490,7 @@ function registerRecentCommand(adoption) {
489
490
  const globalOpts = cmd.optsWithGlobals();
490
491
  const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
491
492
  const cwd = process.cwd();
492
- const { readAdoptionRecords } = await import("./dist-BWFFVKEW.js");
493
+ const { readAdoptionRecords } = await import("./dist-SOKOW7BC.js");
493
494
  const records = readAdoptionRecords(cwd);
494
495
  if (records.length === 0) {
495
496
  if (globalOpts.json) {
@@ -567,7 +568,7 @@ function registerSkillCommand(adoption) {
567
568
  adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
568
569
  const globalOpts = cmd.optsWithGlobals();
569
570
  const cwd = process.cwd();
570
- const { readAdoptionRecords, aggregateBySkill } = await import("./dist-BWFFVKEW.js");
571
+ const { readAdoptionRecords, aggregateBySkill } = await import("./dist-SOKOW7BC.js");
571
572
  const records = readAdoptionRecords(cwd);
572
573
  const skillRecords = records.filter((r) => r.skill === name);
573
574
  if (skillRecords.length === 0) {
@@ -601,7 +602,7 @@ function registerRetrospectiveCommand(adoption) {
601
602
  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) => {
602
603
  const globalOpts = cmd.optsWithGlobals();
603
604
  const cwd = process.cwd();
604
- const { readAdoptionRecords, getCatalogRetrospectiveReport, renderRetrospectiveMarkdown } = await import("./dist-BWFFVKEW.js");
605
+ const { readAdoptionRecords, getCatalogRetrospectiveReport, renderRetrospectiveMarkdown } = await import("./dist-SOKOW7BC.js");
605
606
  const records = readAdoptionRecords(cwd);
606
607
  const catalogSkills = discoverCatalogSkills(cwd);
607
608
  const report = getCatalogRetrospectiveReport(records, {
@@ -6209,7 +6210,7 @@ function createInsightsCommand() {
6209
6210
  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) => {
6210
6211
  const cwd = process.cwd();
6211
6212
  const skip = parseSkip2(opts.skip);
6212
- const { composeInsights } = await import("./dist-BWFFVKEW.js");
6213
+ const { composeInsights } = await import("./dist-SOKOW7BC.js");
6213
6214
  const report = await composeInsights(cwd, { skip });
6214
6215
  if (opts.json) {
6215
6216
  console.log(JSON.stringify(report, null, 2));
@@ -7944,10 +7945,10 @@ function reportDispatcher() {
7944
7945
  function realGit(args, cwd) {
7945
7946
  return execFileSync4("git", args, { cwd, encoding: "utf-8" }).toString().trim();
7946
7947
  }
7947
- function createFixDispatcher(resolveBackend, git = realGit) {
7948
+ function createFixDispatcher(resolveBackend, git2 = realGit) {
7948
7949
  return createAgentDispatcher({
7949
7950
  resolveBackend,
7950
- git,
7951
+ git: git2,
7951
7952
  logger: {
7952
7953
  info: (message) => logger.info(message),
7953
7954
  warn: (message) => logger.warn(message)
@@ -8320,7 +8321,7 @@ function createMcpCommand() {
8320
8321
  parseBudget
8321
8322
  ).action(async (opts) => {
8322
8323
  const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
8323
- import("./mcp-VSSIWTII.js"),
8324
+ import("./mcp-JTPO5RAK.js"),
8324
8325
  import("./tool-tiers-OKK5FE57.js")
8325
8326
  ]);
8326
8327
  if (opts.tools && opts.tools.length > 0) {
@@ -9507,7 +9508,12 @@ function createNotificationsCommand() {
9507
9508
  // src/commands/orchestrator.ts
9508
9509
  import { Command as Command70 } from "commander";
9509
9510
  import * as path50 from "path";
9510
- import { Orchestrator, WorkflowLoader as WorkflowLoader2, launchTUI } from "@harness-engineering/orchestrator";
9511
+ import {
9512
+ Orchestrator,
9513
+ WorkflowLoader as WorkflowLoader2,
9514
+ launchTUI,
9515
+ discoverCandidates
9516
+ } from "@harness-engineering/orchestrator";
9511
9517
  function createOrchestratorCommand() {
9512
9518
  const orchestrator = new Command70("orchestrator");
9513
9519
  orchestrator.command("run").description("Run the orchestrator daemon").option("-w, --workflow <path>", "Path to harness.orchestrator.md", "harness.orchestrator.md").option("--headless", "Run without TUI (server-only mode for use with web dashboard)").action(async (opts) => {
@@ -9520,7 +9526,7 @@ function createOrchestratorCommand() {
9520
9526
  }
9521
9527
  const { config, promptTemplate, warnings } = result.value;
9522
9528
  for (const w of warnings) logger.warn(w);
9523
- const daemon = new Orchestrator(config, promptTemplate);
9529
+ const daemon = new Orchestrator(config, promptTemplate, { discoverCandidates });
9524
9530
  const shutdown = () => {
9525
9531
  daemon.stop();
9526
9532
  process.exit(ExitCode.SUCCESS);
@@ -9551,7 +9557,7 @@ function registerBenchCommand(perf) {
9551
9557
  perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
9552
9558
  const globalOpts = cmd.optsWithGlobals();
9553
9559
  const cwd = process.cwd();
9554
- const { BenchmarkRunner } = await import("./dist-BWFFVKEW.js");
9560
+ const { BenchmarkRunner } = await import("./dist-SOKOW7BC.js");
9555
9561
  const runner = new BenchmarkRunner();
9556
9562
  const benchFiles = runner.discover(cwd, glob2);
9557
9563
  if (benchFiles.length === 0) {
@@ -9615,7 +9621,7 @@ async function runBaselinesShow(globalOpts) {
9615
9621
  }
9616
9622
  async function runBaselinesUpdate(globalOpts) {
9617
9623
  const cwd = process.cwd();
9618
- const { BenchmarkRunner } = await import("./dist-BWFFVKEW.js");
9624
+ const { BenchmarkRunner } = await import("./dist-SOKOW7BC.js");
9619
9625
  const runner = new BenchmarkRunner();
9620
9626
  const manager = new BaselineManager(cwd);
9621
9627
  logger.info("Running benchmarks to update baselines...");
@@ -9656,7 +9662,7 @@ function registerReportCommand(perf) {
9656
9662
  perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
9657
9663
  const globalOpts = cmd.optsWithGlobals();
9658
9664
  const cwd = process.cwd();
9659
- const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-BWFFVKEW.js");
9665
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-SOKOW7BC.js");
9660
9666
  const analyzer = new EntropyAnalyzer2({
9661
9667
  rootDir: path51.resolve(cwd),
9662
9668
  analyze: { complexity: true, coupling: true }
@@ -10679,7 +10685,7 @@ async function runPublishAnalyses(opts) {
10679
10685
  const nameToExternalId = await buildNameToExternalIdMap(projectPath);
10680
10686
  if (!nameToExternalId) return process.exit(1);
10681
10687
  const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
10682
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-BWFFVKEW.js");
10688
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-SOKOW7BC.js");
10683
10689
  const archive = new AnalysisArchive(path53.join(projectPath, ".harness", "analyses"));
10684
10690
  const analyses = await archive.list();
10685
10691
  if (analyses.length === 0) {
@@ -11782,11 +11788,435 @@ function createRoadmapCommand() {
11782
11788
  return roadmap;
11783
11789
  }
11784
11790
 
11791
+ // src/commands/rollback.ts
11792
+ init_dist3();
11793
+ import { execFileSync as execFileSync10 } from "child_process";
11794
+ import { Command as Command90, Option as Option3, InvalidArgumentError } from "commander";
11795
+
11796
+ // src/rollback/compose.ts
11797
+ var ROLLBACK_LABEL = "harness:rollback";
11798
+ function buildRevertBody(d, originalTitle, reason) {
11799
+ const lines = [
11800
+ `## Automated rollback proposal`,
11801
+ ``,
11802
+ `**Trigger:** ${d.trigger}`,
11803
+ `**Target PR:** #${d.targetPr} \u2014 ${originalTitle}`,
11804
+ `**Revert-ready:** ${d.revertReady}`,
11805
+ d.blastRadius !== void 0 ? `**Blast radius:** ${d.blastRadius}` : void 0,
11806
+ // #4: surface the human-provided --reason when present (help text promises it).
11807
+ reason && reason.trim() !== "" ? `**Reason:** ${reason.trim()}` : void 0,
11808
+ ``,
11809
+ `### Classification`,
11810
+ ...d.reasons.map((r) => `- ${r}`)
11811
+ ];
11812
+ if (d.migrationWarnings.length > 0) {
11813
+ lines.push(
11814
+ ``,
11815
+ `### Migration / irreversibility warnings`,
11816
+ ...d.migrationWarnings.map((w) => `- ${w}`)
11817
+ );
11818
+ }
11819
+ if (d.dependentMerges.length > 0) {
11820
+ lines.push(
11821
+ ``,
11822
+ `### Dependent later merges`,
11823
+ `- ${d.dependentMerges.map((n) => `#${n}`).join(", ")}`
11824
+ );
11825
+ }
11826
+ return lines.filter((l) => l !== void 0).join("\n");
11827
+ }
11828
+ async function composeRevertPr(decision, originalTitle, opts) {
11829
+ if (!decision.revertReady) return { action: decision.action };
11830
+ const body = buildRevertBody(decision, originalTitle, opts.reason);
11831
+ if (opts.dryRun) {
11832
+ const print = opts.print ?? ((s) => process.stdout.write(`${s}
11833
+ `));
11834
+ print(body);
11835
+ return { action: "proposed" };
11836
+ }
11837
+ const existing = await opts.gh.findOpenRevertPr(decision.targetPr, ROLLBACK_LABEL);
11838
+ if (existing !== null) {
11839
+ return { action: "skipped", ...existing.url ? { prUrl: existing.url } : {} };
11840
+ }
11841
+ const prUrl = await opts.gh.openPr({
11842
+ title: `revert: ${originalTitle} (automated rollback)`,
11843
+ body,
11844
+ label: ROLLBACK_LABEL,
11845
+ targetPr: decision.targetPr
11846
+ });
11847
+ return { action: "proposed", prUrl };
11848
+ }
11849
+
11850
+ // src/rollback/breadcrumb.ts
11851
+ import { appendFileSync, mkdirSync as mkdirSync19 } from "fs";
11852
+ import { dirname as dirname21, join as join50 } from "path";
11853
+ var ROLLBACK_EVENTS_FILE = join50(".harness", "signals", "rollback-events.jsonl");
11854
+ async function appendRollbackEvent(event, opts = {}) {
11855
+ const root = opts.root ?? process.cwd();
11856
+ const ts = (opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))();
11857
+ const file = join50(root, ROLLBACK_EVENTS_FILE);
11858
+ mkdirSync19(dirname21(file), { recursive: true });
11859
+ appendFileSync(file, `${JSON.stringify({ ...event, ts })}
11860
+ `, "utf-8");
11861
+ }
11862
+ async function linkRollbackEventToGraph(event, opts = {}) {
11863
+ const root = opts.root ?? process.cwd();
11864
+ try {
11865
+ const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-STFGYKZH.js");
11866
+ const store = await loadGraphStore2(root);
11867
+ if (!store) return;
11868
+ const ts = (opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))();
11869
+ const nodeId = `rollback_event:${event.targetPr}:${ts}`;
11870
+ store.addNode({
11871
+ id: nodeId,
11872
+ type: "learning",
11873
+ name: `rollback ${event.action} for PR #${event.targetPr}`,
11874
+ metadata: { kind: "rollback_event", ...event, ts },
11875
+ lastModified: ts
11876
+ });
11877
+ const outcomes = store.findNodes({ type: "execution_outcome" });
11878
+ const target = outcomes.find(
11879
+ (n) => n.metadata.pr === event.targetPr
11880
+ );
11881
+ if (target) {
11882
+ store.addEdge({ from: nodeId, to: target.id, type: "references" });
11883
+ }
11884
+ await store.save(join50(root, ".harness", "graph"));
11885
+ } catch {
11886
+ }
11887
+ }
11888
+
11889
+ // src/rollback/io.ts
11890
+ import { execFileSync as execFileSync8 } from "child_process";
11891
+ var git = (args) => execFileSync8("git", args, { encoding: "utf-8" }).toString();
11892
+ var nodeGitSeam = {
11893
+ run: (args) => git(args).trim(),
11894
+ tryMergeTree: (args) => {
11895
+ try {
11896
+ const stdout = execFileSync8("git", args, {
11897
+ encoding: "utf-8",
11898
+ stdio: ["ignore", "pipe", "ignore"]
11899
+ }).toString();
11900
+ return { status: 0, stdout };
11901
+ } catch (err) {
11902
+ const e = err;
11903
+ return { status: e?.status ?? 1, stdout: e?.stdout?.toString?.() ?? "" };
11904
+ }
11905
+ }
11906
+ };
11907
+ var gh = (args) => execFileSync8("gh", args, { encoding: "utf-8" }).toString();
11908
+ function parseConflictPaths(stdout) {
11909
+ const lines = stdout.split("\n");
11910
+ const paths = /* @__PURE__ */ new Set();
11911
+ for (let i = 1; i < lines.length; i++) {
11912
+ const line = lines[i];
11913
+ if (line === void 0 || line.trim() === "") break;
11914
+ const tab = line.indexOf(" ");
11915
+ if (tab === -1) continue;
11916
+ const path81 = line.slice(tab + 1).trim();
11917
+ if (path81) paths.add(path81);
11918
+ }
11919
+ return [...paths];
11920
+ }
11921
+ async function computeRevertDryRun(mergeSha, gitSeam = nodeGitSeam) {
11922
+ const revList = gitSeam.run(["rev-list", "--parents", "-n", "1", mergeSha]);
11923
+ const parents = revList.trim().split(/\s+/).slice(1);
11924
+ if (parents.length === 0) {
11925
+ throw new Error(`cannot revert ${mergeSha}: commit has no parent (root commit)`);
11926
+ }
11927
+ const parent = parents[0];
11928
+ const { status, stdout } = gitSeam.tryMergeTree([
11929
+ "merge-tree",
11930
+ "--write-tree",
11931
+ "--merge-base",
11932
+ mergeSha,
11933
+ "HEAD",
11934
+ parent
11935
+ ]);
11936
+ if (status === 0) return { clean: true, conflictPaths: [] };
11937
+ if (status === 1) return { clean: false, conflictPaths: parseConflictPaths(stdout) };
11938
+ throw new Error(
11939
+ `git merge-tree failed for ${mergeSha} (exit ${status})${stdout ? `: ${stdout.trim()}` : ""}`
11940
+ );
11941
+ }
11942
+ async function revertDryRun(mergeSha) {
11943
+ return computeRevertDryRun(mergeSha, nodeGitSeam);
11944
+ }
11945
+ async function resolveTarget(pr) {
11946
+ const raw = gh(["pr", "view", String(pr), "--json", "mergeCommit,files,title"]);
11947
+ const parsed = JSON.parse(raw);
11948
+ return {
11949
+ mergeSha: parsed.mergeCommit?.oid ?? "",
11950
+ changedFiles: (parsed.files ?? []).map((f) => f.path),
11951
+ title: parsed.title ?? `PR #${pr}`
11952
+ };
11953
+ }
11954
+ async function listLaterMerges(pr) {
11955
+ const targetRaw = gh(["pr", "view", String(pr), "--json", "mergedAt"]);
11956
+ const targetMergedAt = JSON.parse(targetRaw).mergedAt;
11957
+ if (!targetMergedAt) return [];
11958
+ const raw = gh([
11959
+ "pr",
11960
+ "list",
11961
+ "--state",
11962
+ "merged",
11963
+ "--limit",
11964
+ "100",
11965
+ "--json",
11966
+ "number,files,mergedAt"
11967
+ ]);
11968
+ const list = JSON.parse(raw);
11969
+ return list.filter((p) => p.number !== pr && p.mergedAt > targetMergedAt).map((p) => ({ pr: p.number, changedFiles: (p.files ?? []).map((f) => f.path) }));
11970
+ }
11971
+ function createNodeRollbackIO() {
11972
+ return { revertDryRun, resolveTarget, listLaterMerges };
11973
+ }
11974
+
11975
+ // src/rollback/sweep.ts
11976
+ import { execFileSync as execFileSync9 } from "child_process";
11977
+ import { SignalTimelineStore } from "@harness-engineering/signals";
11978
+ var WINDOW_UNIT_MS = {
11979
+ h: 36e5,
11980
+ d: 864e5,
11981
+ w: 6048e5
11982
+ };
11983
+ function parseWindow(window) {
11984
+ const match = /^(\d+)([hdw])$/.exec(window);
11985
+ if (!match) throw new Error(`invalid window: ${window}`);
11986
+ const count = Number.parseInt(match[1] ?? "", 10);
11987
+ const unit = match[2];
11988
+ return count * WINDOW_UNIT_MS[unit];
11989
+ }
11990
+ function detectCrossing(points, rule) {
11991
+ const prev = points.at(-2);
11992
+ const curr = points.at(-1);
11993
+ if (!prev || !curr) return false;
11994
+ if (rule.direction === "above") {
11995
+ return prev.value < rule.threshold && curr.value >= rule.threshold;
11996
+ }
11997
+ return prev.value > rule.threshold && curr.value <= rule.threshold;
11998
+ }
11999
+ function windowStart(now, window) {
12000
+ return new Date(now.getTime() - parseWindow(window)).toISOString();
12001
+ }
12002
+ function pointsInWindow(points, now, window) {
12003
+ const startDate = windowStart(now, window).slice(0, 10);
12004
+ const nowDate = now.toISOString().slice(0, 10);
12005
+ return points.filter((p) => p.date >= startDate && p.date <= nowDate);
12006
+ }
12007
+ async function runRollbackSweep(signals, deps) {
12008
+ const now = (deps.now ?? (() => /* @__PURE__ */ new Date()))();
12009
+ for (const [name, rule] of Object.entries(signals)) {
12010
+ const pts = pointsInWindow(deps.readTimeline(name), now, rule.window);
12011
+ const crossed = detectCrossing(pts, rule);
12012
+ const forwarded = [];
12013
+ if (crossed) {
12014
+ const prs = await deps.resolveMergedPrs(windowStart(now, rule.window), now.toISOString());
12015
+ for (const pr of prs) {
12016
+ const decision = await deps.evaluate(pr);
12017
+ forwarded.push({
12018
+ pr,
12019
+ action: decision.action,
12020
+ ...decision.prUrl ? { prUrl: decision.prUrl } : {}
12021
+ });
12022
+ }
12023
+ }
12024
+ deps.report?.({ signal: name, window: rule.window, crossed, forwarded });
12025
+ }
12026
+ }
12027
+ function createTimelineReader(root) {
12028
+ const store = new SignalTimelineStore(root);
12029
+ return (name) => store.read(name);
12030
+ }
12031
+ function createPrResolver() {
12032
+ return async (startIso, nowIso) => {
12033
+ try {
12034
+ const raw = execFileSync9(
12035
+ "gh",
12036
+ [
12037
+ "pr",
12038
+ "list",
12039
+ "--state",
12040
+ "merged",
12041
+ "--search",
12042
+ `merged:${startIso}..${nowIso}`,
12043
+ "--json",
12044
+ "number",
12045
+ "--limit",
12046
+ "100"
12047
+ ],
12048
+ { encoding: "utf-8" }
12049
+ );
12050
+ return JSON.parse(raw).map((p) => p.number);
12051
+ } catch {
12052
+ return [];
12053
+ }
12054
+ };
12055
+ }
12056
+
12057
+ // src/commands/rollback.ts
12058
+ async function runRollbackEvaluate(args, deps) {
12059
+ const trigger = args.trigger ?? "signal";
12060
+ const target = await deps.io.resolveTarget(args.pr);
12061
+ const laterMerges = await deps.io.listLaterMerges(args.pr);
12062
+ const decision = await classifyRevert(
12063
+ {
12064
+ targetPr: args.pr,
12065
+ trigger,
12066
+ mergeSha: target.mergeSha,
12067
+ changedFiles: target.changedFiles,
12068
+ laterMerges
12069
+ },
12070
+ deps.io
12071
+ );
12072
+ const composed = await composeRevertPr(decision, target.title, {
12073
+ gh: deps.gh,
12074
+ ...args.dryRun ? { dryRun: true } : {},
12075
+ ...deps.print ? { print: deps.print } : {},
12076
+ ...args.reason !== void 0 ? { reason: args.reason } : {}
12077
+ });
12078
+ const finalDecision = {
12079
+ ...decision,
12080
+ action: composed.action,
12081
+ ...composed.prUrl ? { prUrl: composed.prUrl } : {}
12082
+ };
12083
+ await appendRollbackEvent(
12084
+ {
12085
+ targetPr: finalDecision.targetPr,
12086
+ trigger: finalDecision.trigger,
12087
+ revertReady: finalDecision.revertReady,
12088
+ action: finalDecision.action,
12089
+ ...finalDecision.prUrl ? { prUrl: finalDecision.prUrl } : {},
12090
+ // #4: record the human-provided reason on the breadcrumb (help text promises it).
12091
+ ...args.reason !== void 0 ? { reason: args.reason } : {}
12092
+ },
12093
+ deps.root !== void 0 ? { root: deps.root } : {}
12094
+ );
12095
+ return finalDecision;
12096
+ }
12097
+ var gh2 = (args) => execFileSync10("gh", args, { encoding: "utf-8" }).toString();
12098
+ function referencesTargetPr(text, targetPr) {
12099
+ if (!text) return false;
12100
+ return new RegExp(`(?<!\\d)#${targetPr}(?!\\d)`).test(text);
12101
+ }
12102
+ function findOpenRevertPrNode(targetPr) {
12103
+ try {
12104
+ const raw = gh2([
12105
+ "pr",
12106
+ "list",
12107
+ "--state",
12108
+ "open",
12109
+ "--label",
12110
+ ROLLBACK_LABEL,
12111
+ "--search",
12112
+ `#${targetPr}`,
12113
+ "--json",
12114
+ "number,url,body,title"
12115
+ ]);
12116
+ const list = JSON.parse(raw);
12117
+ const match = list.find(
12118
+ (p) => referencesTargetPr(p.body, targetPr) || referencesTargetPr(p.title, targetPr)
12119
+ );
12120
+ return match ? { number: match.number, url: match.url } : null;
12121
+ } catch {
12122
+ return null;
12123
+ }
12124
+ }
12125
+ function createGhSeam() {
12126
+ return {
12127
+ async findOpenRevertPr(targetPr) {
12128
+ return findOpenRevertPrNode(targetPr);
12129
+ },
12130
+ async openPr({ title, body, label }) {
12131
+ return execFileSync10(
12132
+ "gh",
12133
+ ["pr", "create", "--title", title, "--body-file", "-", "--label", label],
12134
+ { input: body, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
12135
+ ).toString().trim();
12136
+ }
12137
+ };
12138
+ }
12139
+ function summarizeSweepReport(r) {
12140
+ if (!r.crossed) {
12141
+ return `rollback sweep: ${r.signal} (${r.window}) \u2014 no crossing`;
12142
+ }
12143
+ if (r.forwarded.length === 0) {
12144
+ return `rollback sweep: ${r.signal} (${r.window}) \u2014 crossed, no PRs in window`;
12145
+ }
12146
+ const parts = r.forwarded.map((f) => `#${f.pr} \u2192 ${f.action}${f.prUrl ? ` (${f.prUrl})` : ""}`);
12147
+ return `rollback sweep: ${r.signal} (${r.window}) \u2014 crossed; forwarded ${parts.join(", ")}`;
12148
+ }
12149
+ async function runRollbackSweepCommand(deps) {
12150
+ const cfg = deps.resolveConfig();
12151
+ if (!cfg.ok) {
12152
+ deps.warn(`rollback sweep: config error, breaker inactive: ${cfg.error.message}`);
12153
+ }
12154
+ const signals = cfg.ok ? cfg.value.rollback?.signals ?? {} : {};
12155
+ await deps.runSweep(signals, {
12156
+ readTimeline: deps.makeReader(deps.root),
12157
+ resolveMergedPrs: deps.makeResolver(),
12158
+ evaluate: deps.evaluate,
12159
+ report: (r) => deps.info(summarizeSweepReport(r))
12160
+ });
12161
+ }
12162
+ function createRollbackCommand() {
12163
+ const rollback = new Command90("rollback").description(
12164
+ "Post-ship revert circuit breaker (propose-only in v1)"
12165
+ );
12166
+ 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) => {
12167
+ const n = Number.parseInt(v, 10);
12168
+ if (Number.isNaN(n)) throw new InvalidArgumentError("--pr must be a number");
12169
+ return n;
12170
+ }).addOption(
12171
+ new Option3("--trigger <trigger>", "what fired this evaluation").choices(["signal", "eval"]).default("signal")
12172
+ ).option("--reason <str>", "human-readable reason recorded on the proposal").option("--dry-run", "print the revert PR body without opening a PR", false).action(async (opts) => {
12173
+ const reason = opts.reason;
12174
+ const dryRun = opts.dryRun;
12175
+ const decision = await runRollbackEvaluate(
12176
+ {
12177
+ pr: opts.pr,
12178
+ trigger: opts.trigger,
12179
+ ...reason !== void 0 ? { reason } : {},
12180
+ ...dryRun !== void 0 ? { dryRun } : {}
12181
+ },
12182
+ { io: createNodeRollbackIO(), gh: createGhSeam() }
12183
+ );
12184
+ await linkRollbackEventToGraph({
12185
+ targetPr: decision.targetPr,
12186
+ trigger: decision.trigger,
12187
+ revertReady: decision.revertReady,
12188
+ action: decision.action,
12189
+ ...decision.prUrl ? { prUrl: decision.prUrl } : {}
12190
+ });
12191
+ logger.info(JSON.stringify(decision, null, 2));
12192
+ });
12193
+ rollback.command("sweep").description(
12194
+ "Read the signal timeline and propose reverts for threshold crossings (signal arm)"
12195
+ ).action(async () => {
12196
+ await runRollbackSweepCommand({
12197
+ resolveConfig,
12198
+ runSweep: runRollbackSweep,
12199
+ makeReader: createTimelineReader,
12200
+ makeResolver: createPrResolver,
12201
+ evaluate: (pr) => runRollbackEvaluate(
12202
+ { pr, trigger: "signal" },
12203
+ { io: createNodeRollbackIO(), gh: createGhSeam() }
12204
+ ),
12205
+ root: process.cwd(),
12206
+ // #S4: per-signal summary on stdout so the sweep's work is auditable.
12207
+ info: (line) => logger.info(line),
12208
+ // #I2: config error → disarm warning on stderr, never silent.
12209
+ warn: (line) => logger.error(line)
12210
+ });
12211
+ });
12212
+ return rollback;
12213
+ }
12214
+
11785
12215
  // src/commands/routing/index.ts
11786
- import { Command as Command93 } from "commander";
12216
+ import { Command as Command94 } from "commander";
11787
12217
 
11788
12218
  // src/commands/routing/config.ts
11789
- import { Command as Command90 } from "commander";
12219
+ import { Command as Command91 } from "commander";
11790
12220
 
11791
12221
  // src/commands/routing/http-client.ts
11792
12222
  function orchestratorBase() {
@@ -11851,7 +12281,7 @@ function renderHuman(data) {
11851
12281
  }
11852
12282
  }
11853
12283
  function createConfigCommand() {
11854
- return new Command90("config").description("Print active routing config and resolved fallback chains").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12284
+ 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) => {
11855
12285
  const r = await getJson("/api/v1/routing/config");
11856
12286
  if (!r.ok) {
11857
12287
  if (r.status === 0) {
@@ -11877,7 +12307,7 @@ function createConfigCommand() {
11877
12307
  }
11878
12308
 
11879
12309
  // src/commands/routing/trace.ts
11880
- import { Command as Command91 } from "commander";
12310
+ import { Command as Command92 } from "commander";
11881
12311
  function buildUseCase(opts) {
11882
12312
  if (opts.skill) {
11883
12313
  return opts.mode ? { kind: "skill", skillName: opts.skill, cognitiveMode: opts.mode } : { kind: "skill", skillName: opts.skill };
@@ -11898,7 +12328,7 @@ function renderHuman2(r) {
11898
12328
  }
11899
12329
  }
11900
12330
  function createTraceCommand() {
11901
- return new Command91("trace").description("Dry-run a routing decision without dispatching (Spec B F7)").option("--skill <name>", "Skill name to trace").option("--mode <m>", "Cognitive mode to trace (or attach to --skill per spec D12)").option("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
12331
+ 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("--json", "Emit JSON to stdout instead of human-readable text").action(async (opts) => {
11902
12332
  const useCase = buildUseCase(opts);
11903
12333
  if (!useCase) {
11904
12334
  logger.error("Either --skill <name> or --mode <m> is required");
@@ -11930,7 +12360,7 @@ function createTraceCommand() {
11930
12360
  }
11931
12361
 
11932
12362
  // src/commands/routing/decisions.ts
11933
- import { Command as Command92 } from "commander";
12363
+ import { Command as Command93 } from "commander";
11934
12364
  function summarizeUseCase(uc) {
11935
12365
  switch (uc.kind) {
11936
12366
  case "skill":
@@ -11978,7 +12408,7 @@ function buildQuery(opts) {
11978
12408
  return q ? `?${q}` : "";
11979
12409
  }
11980
12410
  function createDecisionsCommand() {
11981
- return new Command92("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(
12411
+ 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(
11982
12412
  async (opts) => {
11983
12413
  const query = buildQuery(opts);
11984
12414
  const r = await getJson(`/api/v1/routing/decisions${query}`);
@@ -12008,7 +12438,7 @@ function createDecisionsCommand() {
12008
12438
 
12009
12439
  // src/commands/routing/index.ts
12010
12440
  function createRoutingCommand() {
12011
- const cmd = new Command93("routing").description(
12441
+ const cmd = new Command94("routing").description(
12012
12442
  "Inspect routing config, trace decisions, and read recent dispatches"
12013
12443
  );
12014
12444
  cmd.addCommand(createConfigCommand());
@@ -12019,9 +12449,9 @@ function createRoutingCommand() {
12019
12449
 
12020
12450
  // src/commands/scan-config.ts
12021
12451
  init_dist3();
12022
- import { Command as Command94 } from "commander";
12452
+ import { Command as Command95 } from "commander";
12023
12453
  import { existsSync as existsSync31, readFileSync as readFileSync22, writeFileSync as writeFileSync23 } from "fs";
12024
- import { join as join50, relative as relative4 } from "path";
12454
+ import { join as join51, relative as relative4 } from "path";
12025
12455
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
12026
12456
  function stripHighSeverityPatterns(content, injectionFindings) {
12027
12457
  const highLines = /* @__PURE__ */ new Set();
@@ -12078,7 +12508,7 @@ async function runScanConfig(targetDir, options) {
12078
12508
  const scanner = new SecurityScanner(parseSecurityConfig({}));
12079
12509
  const results = [];
12080
12510
  for (const configFile of CONFIG_FILES) {
12081
- const result = scanSingleFile(join50(targetDir, configFile), targetDir, scanner, options);
12511
+ const result = scanSingleFile(join51(targetDir, configFile), targetDir, scanner, options);
12082
12512
  if (result) results.push(result);
12083
12513
  }
12084
12514
  return { exitCode: computeScanExitCode(results), results };
@@ -12108,7 +12538,7 @@ function formatTextOutput(result) {
12108
12538
  }
12109
12539
  }
12110
12540
  function createScanConfigCommand() {
12111
- const command = new Command94("scan-config").description(
12541
+ const command = new Command95("scan-config").description(
12112
12542
  "Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
12113
12543
  ).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
12114
12544
  const globalOpts = cmd.optsWithGlobals();
@@ -12126,7 +12556,7 @@ function createScanConfigCommand() {
12126
12556
 
12127
12557
  // src/commands/search.ts
12128
12558
  init_dist();
12129
- import { Command as Command95 } from "commander";
12559
+ import { Command as Command96 } from "commander";
12130
12560
  function parseFileKinds(raw) {
12131
12561
  if (!raw) return void 0;
12132
12562
  const set = /* @__PURE__ */ new Set();
@@ -12147,7 +12577,7 @@ function fmtBytes(n) {
12147
12577
  return n.toFixed(0);
12148
12578
  }
12149
12579
  function createSearchCommand() {
12150
- return new Command95("search").description("Full-text search over archived + live session content.").argument(
12580
+ return new Command96("search").description("Full-text search over archived + live session content.").argument(
12151
12581
  "<query>",
12152
12582
  "FTS5 query (bare words AND-joined; quotes/AND/OR/NOT/column: for advanced syntax)"
12153
12583
  ).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(
@@ -12207,9 +12637,9 @@ function createSearchCommand() {
12207
12637
  }
12208
12638
 
12209
12639
  // src/commands/security-craft.ts
12210
- import { Command as Command96 } from "commander";
12640
+ import { Command as Command97 } from "commander";
12211
12641
  function createSecurityCraftCommand() {
12212
- return new Command96("security-craft").description(
12642
+ return new Command97("security-craft").description(
12213
12643
  "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."
12214
12644
  ).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) => {
12215
12645
  const globalOpts = cmd.optsWithGlobals();
@@ -12275,7 +12705,7 @@ ${file}`);
12275
12705
  }
12276
12706
 
12277
12707
  // src/commands/setup.ts
12278
- import { Command as Command97 } from "commander";
12708
+ import { Command as Command98 } from "commander";
12279
12709
  import * as fs38 from "fs";
12280
12710
  import * as os9 from "os";
12281
12711
  import * as path62 from "path";
@@ -12620,7 +13050,7 @@ async function runSetup(cwd) {
12620
13050
  return { steps, success };
12621
13051
  }
12622
13052
  function createSetupCommand() {
12623
- return new Command97("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
13053
+ return new Command98("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
12624
13054
  const cwd = process.cwd();
12625
13055
  console.log("");
12626
13056
  console.log(` ${chalk16.bold("harness setup")}`);
@@ -12643,7 +13073,7 @@ function createSetupCommand() {
12643
13073
 
12644
13074
  // src/commands/share.ts
12645
13075
  init_dist3();
12646
- import { Command as Command98 } from "commander";
13076
+ import { Command as Command99 } from "commander";
12647
13077
  import * as fs39 from "fs";
12648
13078
  import * as path63 from "path";
12649
13079
  import { parse as parseYaml3 } from "yaml";
@@ -12702,16 +13132,16 @@ Create a constraints.yaml in your project root to define what to share.`
12702
13132
  logger.success(`Bundle written to ${outputPath}`);
12703
13133
  }
12704
13134
  function createShareCommand() {
12705
- return new Command98("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) => {
13135
+ return new Command99("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) => {
12706
13136
  await runShareAction(projectPath, options);
12707
13137
  });
12708
13138
  }
12709
13139
 
12710
13140
  // src/commands/skill/index.ts
12711
- import { Command as Command106 } from "commander";
13141
+ import { Command as Command107 } from "commander";
12712
13142
 
12713
13143
  // src/commands/skill/list.ts
12714
- import { Command as Command99 } from "commander";
13144
+ import { Command as Command100 } from "commander";
12715
13145
  import * as fs40 from "fs";
12716
13146
  import * as path64 from "path";
12717
13147
  import { parse } from "yaml";
@@ -12814,7 +13244,7 @@ function printSkillsVerbose(skills) {
12814
13244
  for (const s of skills) printSkillEntry(s);
12815
13245
  }
12816
13246
  function createListCommand3() {
12817
- return new Command99("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) => {
13247
+ return new Command100("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) => {
12818
13248
  const globalOpts = cmd.optsWithGlobals();
12819
13249
  const skills = collectSkills({ filter: resolveFilter(opts) });
12820
13250
  if (globalOpts.json) {
@@ -12829,13 +13259,13 @@ function createListCommand3() {
12829
13259
  }
12830
13260
 
12831
13261
  // src/commands/skill/run.ts
12832
- import { Command as Command100 } from "commander";
13262
+ import { Command as Command101 } from "commander";
12833
13263
  import * as fs41 from "fs";
12834
13264
  import * as path65 from "path";
12835
13265
  import { parse as parse2 } from "yaml";
12836
13266
 
12837
13267
  // src/skill/complexity.ts
12838
- import { execFileSync as execFileSync8 } from "child_process";
13268
+ import { execFileSync as execFileSync11 } from "child_process";
12839
13269
  function evaluateSignals(signals) {
12840
13270
  if (signals.fileCount >= 3) return "thorough";
12841
13271
  if (signals.newDir) return "thorough";
@@ -12847,17 +13277,17 @@ function evaluateSignals(signals) {
12847
13277
  }
12848
13278
  function detectComplexity(projectPath) {
12849
13279
  try {
12850
- const base = execFileSync8("git", ["merge-base", "HEAD", "main"], {
13280
+ const base = execFileSync11("git", ["merge-base", "HEAD", "main"], {
12851
13281
  cwd: projectPath,
12852
13282
  encoding: "utf-8",
12853
13283
  stdio: ["pipe", "pipe", "pipe"]
12854
13284
  }).trim();
12855
- const diffFiles = execFileSync8("git", ["diff", "--name-only", base], {
13285
+ const diffFiles = execFileSync11("git", ["diff", "--name-only", base], {
12856
13286
  cwd: projectPath,
12857
13287
  encoding: "utf-8",
12858
13288
  stdio: ["pipe", "pipe", "pipe"]
12859
13289
  }).trim().split("\n").filter(Boolean);
12860
- const diffStat = execFileSync8("git", ["diff", "--stat", base], {
13290
+ const diffStat = execFileSync11("git", ["diff", "--stat", base], {
12861
13291
  cwd: projectPath,
12862
13292
  encoding: "utf-8",
12863
13293
  stdio: ["pipe", "pipe", "pipe"]
@@ -12977,7 +13407,7 @@ function resolvePhaseState(metadata, projectPath, phase) {
12977
13407
  }
12978
13408
  async function appendProjectState(content, metadata, projectPath, hasPathOpt) {
12979
13409
  if (!metadata?.state.persistent || !hasPathOpt) return content;
12980
- const { readHarnessState: readHarnessState2, isEmptyHarnessState } = await import("./state-events-PBDNQPXT.js");
13410
+ const { readHarnessState: readHarnessState2, isEmptyHarnessState } = await import("./state-events-H3GGBKTB.js");
12981
13411
  const stateResult = await readHarnessState2(projectPath);
12982
13412
  if (!stateResult.ok || isEmptyHarnessState(stateResult.value)) return content;
12983
13413
  const stateContent = JSON.stringify(stateResult.value, null, 2);
@@ -13043,14 +13473,14 @@ async function runSkill(name, opts) {
13043
13473
  process.exit(ExitCode.SUCCESS);
13044
13474
  }
13045
13475
  function createRunCommand3() {
13046
- return new Command100("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(
13476
+ return new Command101("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(
13047
13477
  "--backend <name>",
13048
13478
  "Spec B: one-shot routing override forwarded to the orchestrator as HARNESS_BACKEND_OVERRIDE"
13049
13479
  ).action(async (name, opts) => runSkill(name, opts));
13050
13480
  }
13051
13481
 
13052
13482
  // src/commands/skill/validate.ts
13053
- import { Command as Command101 } from "commander";
13483
+ import { Command as Command102 } from "commander";
13054
13484
  import * as fs42 from "fs";
13055
13485
  import * as path66 from "path";
13056
13486
  import { parse as parse3 } from "yaml";
@@ -13114,7 +13544,7 @@ function validateSkillEntry(name, skillsDir, errors) {
13114
13544
  }
13115
13545
  }
13116
13546
  function createValidateCommand2() {
13117
- return new Command101("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
13547
+ return new Command102("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
13118
13548
  const globalOpts = cmd.optsWithGlobals();
13119
13549
  const skillsDir = resolveSkillsDir();
13120
13550
  if (!fs42.existsSync(skillsDir)) {
@@ -13144,7 +13574,7 @@ function createValidateCommand2() {
13144
13574
  }
13145
13575
 
13146
13576
  // src/commands/skill/info.ts
13147
- import { Command as Command102 } from "commander";
13577
+ import { Command as Command103 } from "commander";
13148
13578
  import * as fs43 from "fs";
13149
13579
  import * as path67 from "path";
13150
13580
  import { parse as parse4 } from "yaml";
@@ -13189,7 +13619,7 @@ function printSkillInfo(skill) {
13189
13619
  console.log(`Persistent: ${skill.state.persistent}`);
13190
13620
  }
13191
13621
  function createInfoCommand() {
13192
- return new Command102("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
13622
+ return new Command103("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
13193
13623
  const globalOpts = cmd.optsWithGlobals();
13194
13624
  const loaded = loadSkillMetadata2(name);
13195
13625
  if (!loaded.ok) {
@@ -13206,7 +13636,7 @@ function createInfoCommand() {
13206
13636
  }
13207
13637
 
13208
13638
  // src/commands/skill/search.ts
13209
- import { Command as Command103 } from "commander";
13639
+ import { Command as Command104 } from "commander";
13210
13640
  async function runSearch(query, opts) {
13211
13641
  const results = await searchNpmRegistry(query, opts.registry);
13212
13642
  return results.filter((r) => {
@@ -13251,13 +13681,13 @@ async function runSearchAction(query, opts, globalOpts) {
13251
13681
  }
13252
13682
  }
13253
13683
  function createSearchCommand2() {
13254
- return new Command103("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) => {
13684
+ return new Command104("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) => {
13255
13685
  await runSearchAction(query, opts, cmd.optsWithGlobals());
13256
13686
  });
13257
13687
  }
13258
13688
 
13259
13689
  // src/commands/skill/create.ts
13260
- import { Command as Command104 } from "commander";
13690
+ import { Command as Command105 } from "commander";
13261
13691
  import * as path68 from "path";
13262
13692
  import * as fs44 from "fs";
13263
13693
  import YAML from "yaml";
@@ -13377,7 +13807,7 @@ Next steps:`);
13377
13807
  logger.info(` 3. Run: harness skills publish`);
13378
13808
  }
13379
13809
  function createCreateCommand() {
13380
- return new Command104("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) => {
13810
+ return new Command105("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) => {
13381
13811
  const globalOpts = cmd.optsWithGlobals();
13382
13812
  try {
13383
13813
  const result = runCreate(name, {
@@ -13400,10 +13830,10 @@ function createCreateCommand() {
13400
13830
  }
13401
13831
 
13402
13832
  // src/commands/skill/publish.ts
13403
- import { Command as Command105 } from "commander";
13833
+ import { Command as Command106 } from "commander";
13404
13834
  import * as fs46 from "fs";
13405
13835
  import * as path70 from "path";
13406
- import { execFileSync as execFileSync9 } from "child_process";
13836
+ import { execFileSync as execFileSync12 } from "child_process";
13407
13837
 
13408
13838
  // src/registry/validator.ts
13409
13839
  import * as fs45 from "fs";
@@ -13557,7 +13987,7 @@ ${skillMdContent}`;
13557
13987
  if (opts.registry) {
13558
13988
  publishArgs.push("--registry", opts.registry);
13559
13989
  }
13560
- execFileSync9("npm", publishArgs, {
13990
+ execFileSync12("npm", publishArgs, {
13561
13991
  cwd: skillDir,
13562
13992
  stdio: "pipe",
13563
13993
  timeout: 6e4
@@ -13569,7 +13999,7 @@ ${skillMdContent}`;
13569
13999
  };
13570
14000
  }
13571
14001
  function createPublishCommand() {
13572
- return new Command105("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) => {
14002
+ return new Command106("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) => {
13573
14003
  const globalOpts = cmd.optsWithGlobals();
13574
14004
  const skillDir = opts.dir || process.cwd();
13575
14005
  try {
@@ -13594,7 +14024,7 @@ function createPublishCommand() {
13594
14024
 
13595
14025
  // src/commands/skill/index.ts
13596
14026
  function createSkillCommand() {
13597
- const command = new Command106("skill").description("Skill management commands");
14027
+ const command = new Command107("skill").description("Skill management commands");
13598
14028
  command.addCommand(createListCommand3());
13599
14029
  command.addCommand(createRunCommand3());
13600
14030
  command.addCommand(createValidateCommand2());
@@ -13607,7 +14037,7 @@ function createSkillCommand() {
13607
14037
 
13608
14038
  // src/commands/snapshot.ts
13609
14039
  init_dist3();
13610
- import { Command as Command107 } from "commander";
14040
+ import { Command as Command108 } from "commander";
13611
14041
  import { execSync as execSync5 } from "child_process";
13612
14042
  import chalk17 from "chalk";
13613
14043
  function getCommitHash3(cwd) {
@@ -13789,7 +14219,7 @@ function registerListCommand2(parent) {
13789
14219
  });
13790
14220
  }
13791
14221
  function createSnapshotCommand() {
13792
- const command = new Command107("snapshot").description("Architecture timeline snapshot commands");
14222
+ const command = new Command108("snapshot").description("Architecture timeline snapshot commands");
13793
14223
  registerCaptureCommand(command);
13794
14224
  registerTrendsCommand(command);
13795
14225
  registerListCommand2(command);
@@ -13797,9 +14227,9 @@ function createSnapshotCommand() {
13797
14227
  }
13798
14228
 
13799
14229
  // src/commands/spec-craft.ts
13800
- import { Command as Command108 } from "commander";
14230
+ import { Command as Command109 } from "commander";
13801
14231
  function createSpecCraftCommand() {
13802
- return new Command108("spec-craft").description(
14232
+ return new Command109("spec-craft").description(
13803
14233
  "LLM-judgment critique of spec quality (proposals + ADRs). Second craft-pipeline ceiling skill; 7 seed rubrics from the spec-quality canon. Per-section critique."
13804
14234
  ).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) => {
13805
14235
  const globalOpts = cmd.optsWithGlobals();
@@ -13867,7 +14297,7 @@ ${file}`);
13867
14297
 
13868
14298
  // src/commands/stale-constraints.ts
13869
14299
  init_dist3();
13870
- import { Command as Command109 } from "commander";
14300
+ import { Command as Command110 } from "commander";
13871
14301
  import chalk18 from "chalk";
13872
14302
  var CATEGORIES = [
13873
14303
  "circular-deps",
@@ -13954,7 +14384,7 @@ async function runStaleConstraintsCommand(options) {
13954
14384
  );
13955
14385
  }
13956
14386
  function createStaleConstraintsCommand() {
13957
- return new Command109("stale-constraints").description(
14387
+ return new Command110("stale-constraints").description(
13958
14388
  "Detect architectural constraints not violated within a window (candidates for removal)"
13959
14389
  ).option(
13960
14390
  "--window <days>",
@@ -13972,10 +14402,10 @@ function createStaleConstraintsCommand() {
13972
14402
  }
13973
14403
 
13974
14404
  // src/commands/state/index.ts
13975
- import { Command as Command114 } from "commander";
14405
+ import { Command as Command115 } from "commander";
13976
14406
 
13977
14407
  // src/commands/state/show.ts
13978
- import { Command as Command110 } from "commander";
14408
+ import { Command as Command111 } from "commander";
13979
14409
  import * as path71 from "path";
13980
14410
  function printStateText(state, stream) {
13981
14411
  if (stream) console.log(`Stream: ${stream}`);
@@ -14000,7 +14430,7 @@ function printStateProgress(progress) {
14000
14430
  }
14001
14431
  }
14002
14432
  function createShowCommand() {
14003
- return new Command110("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
14433
+ return new Command111("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
14004
14434
  const globalOpts = cmd.optsWithGlobals();
14005
14435
  const result = await readHarnessState(path71.resolve(opts.path), { stream: opts.stream });
14006
14436
  if (!result.ok) {
@@ -14018,7 +14448,7 @@ function createShowCommand() {
14018
14448
 
14019
14449
  // src/commands/state/reset.ts
14020
14450
  init_dist3();
14021
- import { Command as Command111 } from "commander";
14451
+ import { Command as Command112 } from "commander";
14022
14452
  import * as path72 from "path";
14023
14453
  import * as readline3 from "readline";
14024
14454
  async function confirmReset() {
@@ -14044,15 +14474,15 @@ async function runReset(opts) {
14044
14474
  process.exit(ExitCode.SUCCESS);
14045
14475
  }
14046
14476
  function createResetCommand() {
14047
- return new Command111("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));
14477
+ return new Command112("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));
14048
14478
  }
14049
14479
 
14050
14480
  // src/commands/state/learn.ts
14051
14481
  init_dist3();
14052
- import { Command as Command112 } from "commander";
14482
+ import { Command as Command113 } from "commander";
14053
14483
  import * as path73 from "path";
14054
14484
  function createLearnCommand() {
14055
- return new Command112("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) => {
14485
+ return new Command113("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) => {
14056
14486
  const projectPath = path73.resolve(opts.path);
14057
14487
  const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
14058
14488
  if (!result.ok) {
@@ -14067,7 +14497,7 @@ function createLearnCommand() {
14067
14497
 
14068
14498
  // src/commands/state/streams.ts
14069
14499
  init_dist3();
14070
- import { Command as Command113 } from "commander";
14500
+ import { Command as Command114 } from "commander";
14071
14501
  import * as path74 from "path";
14072
14502
  async function runListStreams(opts, globalOpts) {
14073
14503
  const projectPath = path74.resolve(opts.path);
@@ -14118,7 +14548,7 @@ async function runActivateStream(name, opts) {
14118
14548
  process.exit(ExitCode.SUCCESS);
14119
14549
  }
14120
14550
  function createStreamsCommand() {
14121
- const command = new Command113("streams").description("Manage state streams");
14551
+ const command = new Command114("streams").description("Manage state streams");
14122
14552
  command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
14123
14553
  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));
14124
14554
  command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
@@ -14128,7 +14558,7 @@ function createStreamsCommand() {
14128
14558
 
14129
14559
  // src/commands/state/index.ts
14130
14560
  function createStateCommand() {
14131
- const command = new Command114("state").description("Project state management commands");
14561
+ const command = new Command115("state").description("Project state management commands");
14132
14562
  command.addCommand(createShowCommand());
14133
14563
  command.addCommand(createResetCommand());
14134
14564
  command.addCommand(createLearnCommand());
@@ -14139,7 +14569,7 @@ function createStateCommand() {
14139
14569
  // src/commands/sync-analyses.ts
14140
14570
  import * as fs47 from "fs";
14141
14571
  import * as path75 from "path";
14142
- import { Command as Command115 } from "commander";
14572
+ import { Command as Command116 } from "commander";
14143
14573
  init_dist3();
14144
14574
  function isValidRecord(record) {
14145
14575
  return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
@@ -14264,7 +14694,7 @@ async function runSyncAnalyses(opts) {
14264
14694
  return;
14265
14695
  }
14266
14696
  const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
14267
- const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-BWFFVKEW.js");
14697
+ const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-SOKOW7BC.js");
14268
14698
  const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
14269
14699
  const archive = new AnalysisArchive(path75.join(projectPath, ".harness", "analyses"));
14270
14700
  const publishedIndex = loadPublishedIndex2(projectPath);
@@ -14286,7 +14716,7 @@ async function runSyncAnalyses(opts) {
14286
14716
  }
14287
14717
  }
14288
14718
  function createSyncAnalysesCommand() {
14289
- const command = new Command115("sync-analyses").description(
14719
+ const command = new Command116("sync-analyses").description(
14290
14720
  "Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
14291
14721
  ).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
14292
14722
  try {
@@ -14300,7 +14730,7 @@ function createSyncAnalysesCommand() {
14300
14730
  }
14301
14731
 
14302
14732
  // src/commands/sync-main.ts
14303
- import { Command as Command116 } from "commander";
14733
+ import { Command as Command117 } from "commander";
14304
14734
  import * as path76 from "path";
14305
14735
  import {
14306
14736
  syncMain as defaultSyncMain
@@ -14331,7 +14761,7 @@ function formatHuman2(r) {
14331
14761
  }
14332
14762
  }
14333
14763
  function createSyncMainCommand() {
14334
- return new Command116("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) => {
14764
+ return new Command117("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) => {
14335
14765
  const cwd = path76.resolve(opts.path ?? ".");
14336
14766
  const exitCode = await runSyncMain({ cwd, json: Boolean(opts.json) });
14337
14767
  process.exit(exitCode);
@@ -14340,7 +14770,7 @@ function createSyncMainCommand() {
14340
14770
 
14341
14771
  // src/commands/taint.ts
14342
14772
  init_dist3();
14343
- import { Command as Command117 } from "commander";
14773
+ import { Command as Command118 } from "commander";
14344
14774
  function getProjectRoot() {
14345
14775
  return process.cwd();
14346
14776
  }
@@ -14412,18 +14842,18 @@ function registerStatusCommand(taint) {
14412
14842
  });
14413
14843
  }
14414
14844
  function createTaintCommand() {
14415
- const taint = new Command117("taint").description("Manage sentinel session taint state");
14845
+ const taint = new Command118("taint").description("Manage sentinel session taint state");
14416
14846
  registerClearCommand(taint);
14417
14847
  registerStatusCommand(taint);
14418
14848
  return taint;
14419
14849
  }
14420
14850
 
14421
14851
  // src/commands/telemetry/index.ts
14422
- import { Command as Command121 } from "commander";
14852
+ import { Command as Command122 } from "commander";
14423
14853
 
14424
14854
  // src/commands/telemetry/identify.ts
14425
14855
  init_dist3();
14426
- import { Command as Command118 } from "commander";
14856
+ import { Command as Command119 } from "commander";
14427
14857
  import * as fs48 from "fs";
14428
14858
  import * as path77 from "path";
14429
14859
  function telemetryFilePath(cwd) {
@@ -14447,7 +14877,7 @@ function printIdentity(identity) {
14447
14877
  }
14448
14878
  }
14449
14879
  function createIdentifyCommand() {
14450
- const cmd = new Command118("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) => {
14880
+ const cmd = new Command119("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) => {
14451
14881
  const cwd = process.cwd();
14452
14882
  if (opts.clear) {
14453
14883
  writeTelemetryFile(cwd, { identity: {} });
@@ -14472,7 +14902,7 @@ function createIdentifyCommand() {
14472
14902
 
14473
14903
  // src/commands/telemetry/status.ts
14474
14904
  init_dist3();
14475
- import { Command as Command119 } from "commander";
14905
+ import { Command as Command120 } from "commander";
14476
14906
  function gatherEnvOverrides() {
14477
14907
  const overrides = {};
14478
14908
  if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
@@ -14514,7 +14944,7 @@ function printHumanStatus(result) {
14514
14944
  printEnvOverrides(result.envOverrides);
14515
14945
  }
14516
14946
  function createStatusCommand() {
14517
- const cmd = new Command119("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
14947
+ const cmd = new Command120("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
14518
14948
  const cwd = process.cwd();
14519
14949
  const envOverrides = gatherEnvOverrides();
14520
14950
  const consent = resolveConsent(cwd, void 0);
@@ -14547,11 +14977,11 @@ function createStatusCommand() {
14547
14977
 
14548
14978
  // src/commands/telemetry/test.ts
14549
14979
  init_dist3();
14550
- import { Command as Command120 } from "commander";
14980
+ import { Command as Command121 } from "commander";
14551
14981
 
14552
14982
  // src/bin/command-telemetry.ts
14553
- import { existsSync as existsSync44, readFileSync as readFileSync32, mkdirSync as mkdirSync23, appendFileSync, writeFileSync as writeFileSync29 } from "fs";
14554
- import { join as join64, parse as parsePath, resolve as resolve47 } from "path";
14983
+ import { existsSync as existsSync44, readFileSync as readFileSync32, mkdirSync as mkdirSync24, appendFileSync as appendFileSync2, writeFileSync as writeFileSync29 } from "fs";
14984
+ import { join as join65, parse as parsePath, resolve as resolve47 } from "path";
14555
14985
  import { spawn as spawn2 } from "child_process";
14556
14986
  var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
14557
14987
  var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
@@ -14559,7 +14989,7 @@ function findProjectRoot(cwd) {
14559
14989
  let dir = resolve47(cwd);
14560
14990
  const { root } = parsePath(dir);
14561
14991
  while (dir !== root) {
14562
- if (existsSync44(join64(dir, "harness.config.json"))) return dir;
14992
+ if (existsSync44(join65(dir, "harness.config.json"))) return dir;
14563
14993
  dir = resolve47(dir, "..");
14564
14994
  }
14565
14995
  return cwd;
@@ -14597,8 +15027,8 @@ function resolveCommandName(cmd) {
14597
15027
  }
14598
15028
  function writeCommandRecordSync(cwd, command, duration, outcome) {
14599
15029
  try {
14600
- const metricsDir = join64(cwd, ".harness", "metrics");
14601
- mkdirSync23(metricsDir, { recursive: true });
15030
+ const metricsDir = join65(cwd, ".harness", "metrics");
15031
+ mkdirSync24(metricsDir, { recursive: true });
14602
15032
  const record = {
14603
15033
  skill: command,
14604
15034
  session: `cli-${Date.now()}`,
@@ -14607,13 +15037,13 @@ function writeCommandRecordSync(cwd, command, duration, outcome) {
14607
15037
  outcome,
14608
15038
  phasesReached: []
14609
15039
  };
14610
- const adoptionFile = join64(metricsDir, "adoption.jsonl");
14611
- appendFileSync(adoptionFile, JSON.stringify(record) + "\n");
15040
+ const adoptionFile = join65(metricsDir, "adoption.jsonl");
15041
+ appendFileSync2(adoptionFile, JSON.stringify(record) + "\n");
14612
15042
  } catch {
14613
15043
  }
14614
15044
  }
14615
15045
  function isTelemetryDisabledByConfig(cwd) {
14616
- const configPath = join64(cwd, "harness.config.json");
15046
+ const configPath = join65(cwd, "harness.config.json");
14617
15047
  if (!existsSync44(configPath)) return false;
14618
15048
  try {
14619
15049
  const config = JSON.parse(readFileSync32(configPath, "utf-8"));
@@ -14628,10 +15058,10 @@ function isTelemetryOptedOut(cwd) {
14628
15058
  }
14629
15059
  function flushTelemetryBackground(cwd) {
14630
15060
  try {
14631
- const adoptionFile = join64(cwd, ".harness", "metrics", "adoption.jsonl");
15061
+ const adoptionFile = join65(cwd, ".harness", "metrics", "adoption.jsonl");
14632
15062
  if (!existsSync44(adoptionFile)) return;
14633
15063
  if (isTelemetryOptedOut(cwd)) return;
14634
- const reporterPath = join64(cwd, ".harness", "hooks", "telemetry-reporter.js");
15064
+ const reporterPath = join65(cwd, ".harness", "hooks", "telemetry-reporter.js");
14635
15065
  if (!existsSync44(reporterPath)) return;
14636
15066
  const child = spawn2(process.execPath, [reporterPath], {
14637
15067
  cwd,
@@ -14669,7 +15099,7 @@ function reportTestSuccess(status, distinctId, identity) {
14669
15099
  if (identity.team) logger.info(` team: ${identity.team}`);
14670
15100
  }
14671
15101
  function createTestCommand() {
14672
- return new Command120("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
15102
+ return new Command121("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
14673
15103
  const cwd = process.cwd();
14674
15104
  const consent = resolveConsent(cwd, void 0);
14675
15105
  if (!consent.allowed) {
@@ -14706,7 +15136,7 @@ function createTestCommand() {
14706
15136
 
14707
15137
  // src/commands/telemetry/index.ts
14708
15138
  function createTelemetryCommand() {
14709
- const command = new Command121("telemetry").description("Telemetry identity and status management");
15139
+ const command = new Command122("telemetry").description("Telemetry identity and status management");
14710
15140
  command.addCommand(createIdentifyCommand());
14711
15141
  command.addCommand(createStatusCommand());
14712
15142
  command.addCommand(createTestCommand());
@@ -14714,9 +15144,9 @@ function createTelemetryCommand() {
14714
15144
  }
14715
15145
 
14716
15146
  // src/commands/test-craft.ts
14717
- import { Command as Command122 } from "commander";
15147
+ import { Command as Command123 } from "commander";
14718
15148
  function createTestCraftCommand() {
14719
- return new Command122("test-craft").description(
15149
+ return new Command123("test-craft").description(
14720
15150
  "LLM-judgment critique of test quality across vitest/jest/mocha/playwright. Fourth craft-pipeline ceiling skill. Per-test critique with best-effort source pairing."
14721
15151
  ).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) => {
14722
15152
  const globalOpts = cmd.optsWithGlobals();
@@ -14786,7 +15216,7 @@ ${file}`);
14786
15216
  }
14787
15217
 
14788
15218
  // src/commands/traceability.ts
14789
- import { Command as Command123 } from "commander";
15219
+ import { Command as Command124 } from "commander";
14790
15220
  import chalk19 from "chalk";
14791
15221
  function confidenceLabel(maxConfidence) {
14792
15222
  if (maxConfidence >= 0.8) return "explicit";
@@ -14926,7 +15356,7 @@ async function runTraceability(options) {
14926
15356
  process.exit(ExitCode.SUCCESS);
14927
15357
  }
14928
15358
  function createTraceabilityCommand() {
14929
- return new Command123("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) => {
15359
+ return new Command124("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) => {
14930
15360
  const globalOpts = cmd.optsWithGlobals();
14931
15361
  await runTraceability({
14932
15362
  spec: opts.spec,
@@ -14940,7 +15370,7 @@ function createTraceabilityCommand() {
14940
15370
 
14941
15371
  // src/commands/uninstall.ts
14942
15372
  import * as path78 from "path";
14943
- import { Command as Command124 } from "commander";
15373
+ import { Command as Command125 } from "commander";
14944
15374
  async function runUninstall(skillName, options) {
14945
15375
  const packageName = resolvePackageName(skillName);
14946
15376
  const shortName = extractSkillName(packageName);
@@ -14977,7 +15407,7 @@ async function runUninstall(skillName, options) {
14977
15407
  return result;
14978
15408
  }
14979
15409
  function createUninstallCommand() {
14980
- const cmd = new Command124("uninstall");
15410
+ const cmd = new Command125("uninstall");
14981
15411
  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) => {
14982
15412
  try {
14983
15413
  const result = await runUninstall(skill, opts);
@@ -14999,7 +15429,7 @@ function createUninstallCommand() {
14999
15429
  init_dist3();
15000
15430
  import * as fs49 from "fs/promises";
15001
15431
  import * as path79 from "path";
15002
- import { Command as Command125 } from "commander";
15432
+ import { Command as Command126 } from "commander";
15003
15433
  async function runUninstallConstraints(options) {
15004
15434
  const { packageName, configPath, lockfilePath } = options;
15005
15435
  const lockfileResult = await readLockfile(lockfilePath);
@@ -15056,7 +15486,7 @@ async function runUninstallConstraints(options) {
15056
15486
  };
15057
15487
  }
15058
15488
  function createUninstallConstraintsCommand() {
15059
- const cmd = new Command125("uninstall-constraints");
15489
+ const cmd = new Command126("uninstall-constraints");
15060
15490
  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) => {
15061
15491
  let configPath;
15062
15492
  if (opts.config) {
@@ -15096,10 +15526,10 @@ function createUninstallConstraintsCommand() {
15096
15526
 
15097
15527
  // src/commands/update.ts
15098
15528
  init_dist3();
15099
- import { Command as Command126 } from "commander";
15100
- import { execFile as execFile2, execFileSync as execFileSync10 } from "child_process";
15529
+ import { Command as Command127 } from "commander";
15530
+ import { execFile as execFile2, execFileSync as execFileSync13 } from "child_process";
15101
15531
  import { realpathSync, existsSync as existsSync45, readFileSync as readFileSync33 } from "fs";
15102
- import { dirname as dirname25, join as join67 } from "path";
15532
+ import { dirname as dirname26, join as join68 } from "path";
15103
15533
  import { promisify as promisify2 } from "util";
15104
15534
  import readline4 from "readline";
15105
15535
  import chalk20 from "chalk";
@@ -15139,7 +15569,7 @@ async function getLatestVersionAsync(pkg) {
15139
15569
  function getInstalledVersions(pm, packages) {
15140
15570
  const versions = {};
15141
15571
  try {
15142
- const output = execFileSync10(pm, ["list", "-g", "--json"], {
15572
+ const output = execFileSync13(pm, ["list", "-g", "--json"], {
15143
15573
  encoding: "utf-8",
15144
15574
  timeout: 15e3
15145
15575
  });
@@ -15160,7 +15590,7 @@ function getInstalledVersions(pm, packages) {
15160
15590
  }
15161
15591
  function getInstalledPackages(pm) {
15162
15592
  try {
15163
- const output = execFileSync10(pm, ["list", "-g", "--json"], {
15593
+ const output = execFileSync13(pm, ["list", "-g", "--json"], {
15164
15594
  encoding: "utf-8",
15165
15595
  timeout: 15e3
15166
15596
  });
@@ -15188,16 +15618,16 @@ function prompt3(question) {
15188
15618
  });
15189
15619
  }
15190
15620
  function findPackageDir(resolvedBin) {
15191
- let dir = dirname25(resolvedBin);
15621
+ let dir = dirname26(resolvedBin);
15192
15622
  for (let i = 0; i < 6; i++) {
15193
- if (existsSync45(join67(dir, "package.json"))) {
15623
+ if (existsSync45(join68(dir, "package.json"))) {
15194
15624
  try {
15195
- const pkg = JSON.parse(readFileSync33(join67(dir, "package.json"), "utf-8"));
15625
+ const pkg = JSON.parse(readFileSync33(join68(dir, "package.json"), "utf-8"));
15196
15626
  if (pkg?.name === CLI_PACKAGE) return dir;
15197
15627
  } catch {
15198
15628
  }
15199
15629
  }
15200
- const parent = dirname25(dir);
15630
+ const parent = dirname26(dir);
15201
15631
  if (parent === dir) return null;
15202
15632
  dir = parent;
15203
15633
  }
@@ -15215,7 +15645,7 @@ function findAllInstalls() {
15215
15645
  const args = isWindows ? ["harness"] : ["-a", "harness"];
15216
15646
  let output;
15217
15647
  try {
15218
- const raw = execFileSync10(cmd, args, { encoding: "utf-8", timeout: 5e3 });
15648
+ const raw = execFileSync13(cmd, args, { encoding: "utf-8", timeout: 5e3 });
15219
15649
  if (typeof raw !== "string") return [];
15220
15650
  output = raw;
15221
15651
  } catch {
@@ -15237,7 +15667,7 @@ function findAllInstalls() {
15237
15667
  if (!packageDir) continue;
15238
15668
  let version = null;
15239
15669
  try {
15240
- const pkg = JSON.parse(readFileSync33(join67(packageDir, "package.json"), "utf-8"));
15670
+ const pkg = JSON.parse(readFileSync33(join68(packageDir, "package.json"), "utf-8"));
15241
15671
  if (typeof pkg?.version === "string") version = pkg.version;
15242
15672
  } catch {
15243
15673
  }
@@ -15292,7 +15722,7 @@ async function offerCleanupOfOtherInstalls(activeDir) {
15292
15722
  }
15293
15723
  try {
15294
15724
  logger.info(`Uninstalling: ${cmd.display}`);
15295
- execFileSync10(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
15725
+ execFileSync13(cmd.bin, cmd.args, { stdio: "inherit", timeout: 12e4 });
15296
15726
  } catch {
15297
15727
  logger.warn(`Uninstall failed for ${cmd.install.binPath}.`);
15298
15728
  console.log(` Run manually: ${chalk20.cyan(cmd.display)}`);
@@ -15330,10 +15760,10 @@ async function ensureTelemetryIfNeeded() {
15330
15760
  }
15331
15761
  function refreshHooks() {
15332
15762
  const cwd = process.cwd();
15333
- const configPath = join67(cwd, "harness.config.json");
15763
+ const configPath = join68(cwd, "harness.config.json");
15334
15764
  if (!existsSync45(configPath)) return;
15335
15765
  let profile = "standard";
15336
- const profilePath = join67(cwd, ".harness", "hooks", "profile.json");
15766
+ const profilePath = join68(cwd, ".harness", "hooks", "profile.json");
15337
15767
  try {
15338
15768
  const data = JSON.parse(readFileSync33(profilePath, "utf-8"));
15339
15769
  if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
@@ -15352,7 +15782,7 @@ function refreshHooks() {
15352
15782
  function runLocalGraphScan() {
15353
15783
  try {
15354
15784
  logger.info("Scanning codebase to rebuild knowledge graph...");
15355
- execFileSync10("harness", ["graph", "scan", "."], { stdio: "inherit" });
15785
+ execFileSync13("harness", ["graph", "scan", "."], { stdio: "inherit" });
15356
15786
  } catch {
15357
15787
  logger.warn("Graph scan failed. Run manually:");
15358
15788
  console.log(` ${chalk20.cyan("harness graph scan .")}`);
@@ -15367,7 +15797,7 @@ async function offerRegeneration() {
15367
15797
  const scopeAnswer = await prompt3("Generate for (G)lobal or (l)ocal project? (G/l) ");
15368
15798
  const isGlobal = scopeAnswer !== "l" && scopeAnswer !== "local";
15369
15799
  try {
15370
- execFileSync10("harness", ["generate", ...isGlobal ? ["--global"] : []], {
15800
+ execFileSync13("harness", ["generate", ...isGlobal ? ["--global"] : []], {
15371
15801
  stdio: "inherit"
15372
15802
  });
15373
15803
  } catch {
@@ -15447,7 +15877,7 @@ async function runUpdateAction(opts, globalOpts) {
15447
15877
  }
15448
15878
  try {
15449
15879
  logger.info("Updating packages...");
15450
- execFileSync10(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
15880
+ execFileSync13(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
15451
15881
  console.log("");
15452
15882
  logger.success("Update complete");
15453
15883
  invalidateCheckState();
@@ -15464,7 +15894,7 @@ async function runUpdateAction(opts, globalOpts) {
15464
15894
  process.exit(ExitCode.SUCCESS);
15465
15895
  }
15466
15896
  function createUpdateCommand() {
15467
- return new Command126("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(
15897
+ return new Command127("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(
15468
15898
  "--regenerate",
15469
15899
  "Only regenerate slash commands and agent definitions (skip package updates)"
15470
15900
  ).action(async (opts, cmd) => {
@@ -15474,9 +15904,9 @@ function createUpdateCommand() {
15474
15904
  }
15475
15905
 
15476
15906
  // src/commands/usage.ts
15477
- import { Command as Command127 } from "commander";
15907
+ import { Command as Command128 } from "commander";
15478
15908
  async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
15479
- const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-BWFFVKEW.js");
15909
+ const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-SOKOW7BC.js");
15480
15910
  const records = readCostRecords(cwd);
15481
15911
  if (includeClaudeSessions) {
15482
15912
  const ccRecords = parseCCRecords();
@@ -15569,7 +15999,7 @@ function registerDailyCommand(usage) {
15569
15999
  else logger.info("No usage data found. Run some harness sessions first.");
15570
16000
  return;
15571
16001
  }
15572
- const { aggregateByDay } = await import("./dist-BWFFVKEW.js");
16002
+ const { aggregateByDay } = await import("./dist-SOKOW7BC.js");
15573
16003
  const limited = aggregateByDay(records).slice(0, days);
15574
16004
  if (globalOpts.json) {
15575
16005
  console.log(
@@ -15598,7 +16028,7 @@ function registerSessionsCommand(usage) {
15598
16028
  }
15599
16029
  return;
15600
16030
  }
15601
- const { aggregateBySession } = await import("./dist-BWFFVKEW.js");
16031
+ const { aggregateBySession } = await import("./dist-SOKOW7BC.js");
15602
16032
  const sessionData = aggregateBySession(records);
15603
16033
  const limited = sessionData.slice(0, limit);
15604
16034
  if (globalOpts.json) {
@@ -15678,7 +16108,7 @@ function registerSessionCommand(usage) {
15678
16108
  cwd,
15679
16109
  globalOpts.includeClaudeSessions
15680
16110
  );
15681
- const { aggregateBySession } = await import("./dist-BWFFVKEW.js");
16111
+ const { aggregateBySession } = await import("./dist-SOKOW7BC.js");
15682
16112
  const sessionData = aggregateBySession(records);
15683
16113
  const match = sessionData.find((s) => s.sessionId === id);
15684
16114
  if (!match) {
@@ -15713,7 +16143,7 @@ function registerLatestCommand(usage) {
15713
16143
  }
15714
16144
  return;
15715
16145
  }
15716
- const { aggregateBySession } = await import("./dist-BWFFVKEW.js");
16146
+ const { aggregateBySession } = await import("./dist-SOKOW7BC.js");
15717
16147
  const sessionData = aggregateBySession(records);
15718
16148
  const latest = sessionData[0];
15719
16149
  if (!latest) {
@@ -15739,7 +16169,7 @@ function registerLatestCommand(usage) {
15739
16169
  });
15740
16170
  }
15741
16171
  function createUsageCommand() {
15742
- const usage = new Command127("usage").description("Token usage and cost tracking");
16172
+ const usage = new Command128("usage").description("Token usage and cost tracking");
15743
16173
  usage.option(
15744
16174
  "--include-claude-sessions",
15745
16175
  "Include Claude Code session data from ~/.claude/projects/"
@@ -15754,10 +16184,10 @@ function createUsageCommand() {
15754
16184
  // src/commands/validate.ts
15755
16185
  init_dist3();
15756
16186
  init_dist3();
15757
- import { Command as Command128 } from "commander";
16187
+ import { Command as Command129 } from "commander";
15758
16188
  import * as fs50 from "fs";
15759
16189
  import * as path80 from "path";
15760
- import { execFileSync as execFileSync11 } from "child_process";
16190
+ import { execFileSync as execFileSync14 } from "child_process";
15761
16191
  async function runValidate(options) {
15762
16192
  const configResult = resolveConfig(options.configPath);
15763
16193
  if (!configResult.ok) {
@@ -15876,7 +16306,7 @@ async function runValidate(options) {
15876
16306
  const gitattributesContent = fs50.readFileSync(gitattributesPath, "utf-8");
15877
16307
  let driverConfigured = false;
15878
16308
  try {
15879
- const out = execFileSync11("git", ["config", "--get", "merge.ours.driver"], {
16309
+ const out = execFileSync14("git", ["config", "--get", "merge.ours.driver"], {
15880
16310
  cwd,
15881
16311
  encoding: "utf-8",
15882
16312
  stdio: ["ignore", "pipe", "ignore"]
@@ -16062,7 +16492,7 @@ function resolveValidateMode(globalOpts) {
16062
16492
  return OutputMode.TEXT;
16063
16493
  }
16064
16494
  async function printCrossCheckWarnings(mode) {
16065
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-H2OUHTID.js");
16495
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-OF3FPM32.js");
16066
16496
  const cwd = process.cwd();
16067
16497
  const crossResult = await runCrossCheck2({
16068
16498
  specsDir: path80.join(cwd, "docs", "specs"),
@@ -16078,7 +16508,7 @@ async function printCrossCheckWarnings(mode) {
16078
16508
  ${crossResult.value.warnings} warnings`);
16079
16509
  }
16080
16510
  function createValidateCommand3() {
16081
- const command = new Command128("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
16511
+ const command = new Command129("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
16082
16512
  "--agent-configs",
16083
16513
  "Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
16084
16514
  ).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()));
@@ -16127,7 +16557,7 @@ Agent configs checked via ${engineLabel}${note}`);
16127
16557
 
16128
16558
  // src/commands/verify.ts
16129
16559
  init_dist3();
16130
- import { Command as Command129 } from "commander";
16560
+ import { Command as Command130 } from "commander";
16131
16561
  import { execSync as execSync6 } from "child_process";
16132
16562
  function loadBranchingConfig(configPath) {
16133
16563
  const shouldLoad = configPath !== void 0 || findConfigFile().ok;
@@ -16190,7 +16620,7 @@ async function runVerify(options) {
16190
16620
  process.exit(ExitCode.VALIDATION_FAILED);
16191
16621
  }
16192
16622
  function createVerifyCommand() {
16193
- return new Command129("verify").description(
16623
+ return new Command130("verify").description(
16194
16624
  "Verify project conventions (currently: branch naming). Works with or without a harness.config.json."
16195
16625
  ).option(
16196
16626
  "--branch <name>",
@@ -16268,6 +16698,7 @@ var commandCreators = [
16268
16698
  createRecommendCommand,
16269
16699
  createReviewCiCommand,
16270
16700
  createRoadmapCommand,
16701
+ createRollbackCommand,
16271
16702
  createRoutingCommand,
16272
16703
  createScanConfigCommand,
16273
16704
  createSearchCommand,
@@ -16317,7 +16748,7 @@ function registerDeprecatedGraphAliases(program) {
16317
16748
 
16318
16749
  // src/index.ts
16319
16750
  function createProgram() {
16320
- const program = new Command130();
16751
+ const program = new Command131();
16321
16752
  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");
16322
16753
  for (const creator of commandCreators) {
16323
16754
  program.addCommand(creator());