@harness-engineering/cli 1.6.0 → 1.6.2

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 (41) hide show
  1. package/dist/agents/personas/code-reviewer.yaml +2 -0
  2. package/dist/agents/personas/codebase-health-analyst.yaml +5 -0
  3. package/dist/agents/personas/performance-guardian.yaml +26 -0
  4. package/dist/agents/personas/security-reviewer.yaml +35 -0
  5. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +494 -0
  6. package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +52 -0
  7. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +15 -0
  8. package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +20 -6
  9. package/dist/agents/skills/claude-code/harness-perf/SKILL.md +231 -0
  10. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +47 -0
  11. package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +236 -0
  12. package/dist/agents/skills/claude-code/harness-perf-tdd/skill.yaml +47 -0
  13. package/dist/agents/skills/claude-code/harness-pre-commit-review/SKILL.md +27 -2
  14. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +657 -0
  15. package/dist/agents/skills/claude-code/harness-release-readiness/skill.yaml +57 -0
  16. package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +206 -0
  17. package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +50 -0
  18. package/dist/agents/skills/claude-code/harness-security-scan/SKILL.md +102 -0
  19. package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +41 -0
  20. package/dist/agents/skills/claude-code/harness-state-management/SKILL.md +22 -8
  21. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +494 -0
  22. package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +52 -0
  23. package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +231 -0
  24. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +47 -0
  25. package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +236 -0
  26. package/dist/agents/skills/gemini-cli/harness-perf-tdd/skill.yaml +47 -0
  27. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +657 -0
  28. package/dist/agents/skills/gemini-cli/harness-release-readiness/skill.yaml +57 -0
  29. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +50 -0
  30. package/dist/agents/skills/gemini-cli/harness-security-scan/SKILL.md +102 -0
  31. package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +41 -0
  32. package/dist/bin/harness.js +3 -2
  33. package/dist/{chunk-VS4OTOKZ.js → chunk-IUFFBBYV.js} +1271 -461
  34. package/dist/{chunk-3U5VZYR7.js → chunk-UDWGSL3T.js} +4 -1
  35. package/dist/chunk-USEYPS7F.js +6150 -0
  36. package/dist/dist-4MYPT3OE.js +2528 -0
  37. package/dist/dist-RBZXXJHG.js +242 -0
  38. package/dist/index.js +3 -2
  39. package/dist/validate-cross-check-CPEPNLOD.js +7 -0
  40. package/package.json +12 -8
  41. package/dist/validate-cross-check-LNIZ7KGZ.js +0 -6
@@ -1,3 +1,38 @@
1
+ import {
2
+ BaselineManager,
3
+ CriticalPathResolver,
4
+ EntropyAnalyzer,
5
+ Err,
6
+ Ok,
7
+ SecurityScanner,
8
+ TypeScriptParser,
9
+ VERSION,
10
+ appendLearning,
11
+ applyFixes,
12
+ archiveStream,
13
+ buildSnapshot,
14
+ checkDocCoverage,
15
+ createFixes,
16
+ createSelfReview,
17
+ createStream,
18
+ defineLayer,
19
+ detectCircularDepsInFiles,
20
+ detectDeadCode,
21
+ detectDocDrift,
22
+ generateSuggestions,
23
+ listStreams,
24
+ loadState,
25
+ loadStreamIndex,
26
+ parseDiff,
27
+ parseSecurityConfig,
28
+ requestPeerReview,
29
+ resolveStreamPath,
30
+ runCIChecks,
31
+ setActiveStream,
32
+ validateAgentsMap,
33
+ validateDependencies,
34
+ validateKnowledgeMap
35
+ } from "./chunk-USEYPS7F.js";
1
36
  import {
2
37
  CLIError,
3
38
  ExitCode,
@@ -8,19 +43,15 @@ import {
8
43
  } from "./chunk-ACMDUQJG.js";
9
44
 
10
45
  // src/index.ts
11
- import { Command as Command39 } from "commander";
12
- import { VERSION } from "@harness-engineering/core";
46
+ import { Command as Command43 } from "commander";
13
47
 
14
48
  // src/commands/validate.ts
15
49
  import { Command } from "commander";
16
50
  import * as path2 from "path";
17
- import { Ok as Ok2 } from "@harness-engineering/core";
18
- import { validateAgentsMap, validateKnowledgeMap } from "@harness-engineering/core";
19
51
 
20
52
  // src/config/loader.ts
21
53
  import * as fs from "fs";
22
54
  import * as path from "path";
23
- import { Ok, Err } from "@harness-engineering/core";
24
55
 
25
56
  // src/config/schema.ts
26
57
  import { z } from "zod";
@@ -241,7 +272,7 @@ async function runValidate(options) {
241
272
  });
242
273
  }
243
274
  result.checks.fileStructure = true;
244
- return Ok2(result);
275
+ return Ok(result);
245
276
  }
246
277
  function createValidateCommand() {
247
278
  const command = new Command("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").action(async (opts, cmd) => {
@@ -263,7 +294,7 @@ function createValidateCommand() {
263
294
  process.exit(result.error.exitCode);
264
295
  }
265
296
  if (opts.crossCheck) {
266
- const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-LNIZ7KGZ.js");
297
+ const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-CPEPNLOD.js");
267
298
  const cwd = process.cwd();
268
299
  const specsDir = path2.join(cwd, "docs", "specs");
269
300
  const plansDir = path2.join(cwd, "docs", "plans");
@@ -291,13 +322,6 @@ function createValidateCommand() {
291
322
  // src/commands/check-deps.ts
292
323
  import { Command as Command2 } from "commander";
293
324
  import * as path3 from "path";
294
- import { Ok as Ok3 } from "@harness-engineering/core";
295
- import {
296
- validateDependencies,
297
- detectCircularDepsInFiles,
298
- defineLayer,
299
- TypeScriptParser
300
- } from "@harness-engineering/core";
301
325
 
302
326
  // src/utils/files.ts
303
327
  import { glob } from "glob";
@@ -319,7 +343,7 @@ async function runCheckDeps(options) {
319
343
  circularDeps: []
320
344
  };
321
345
  if (!config.layers || config.layers.length === 0) {
322
- return Ok3(result);
346
+ return Ok(result);
323
347
  }
324
348
  const rootDir = path3.resolve(cwd, config.rootDir);
325
349
  const parser = new TypeScriptParser();
@@ -358,7 +382,7 @@ async function runCheckDeps(options) {
358
382
  }
359
383
  }
360
384
  }
361
- return Ok3(result);
385
+ return Ok(result);
362
386
  }
363
387
  function createCheckDepsCommand() {
364
388
  const command = new Command2("check-deps").description("Validate dependency layers and detect circular dependencies").action(async (_opts, cmd) => {
@@ -400,11 +424,400 @@ function createCheckDepsCommand() {
400
424
  return command;
401
425
  }
402
426
 
403
- // src/commands/check-docs.ts
427
+ // src/commands/check-perf.ts
404
428
  import { Command as Command3 } from "commander";
405
429
  import * as path4 from "path";
406
- import { Ok as Ok4, Err as Err2 } from "@harness-engineering/core";
407
- import { checkDocCoverage, validateKnowledgeMap as validateKnowledgeMap2 } from "@harness-engineering/core";
430
+ async function runCheckPerf(cwd, options) {
431
+ const runAll = !options.structural && !options.size && !options.coupling;
432
+ const analyzer = new EntropyAnalyzer({
433
+ rootDir: path4.resolve(cwd),
434
+ analyze: {
435
+ complexity: runAll || !!options.structural,
436
+ coupling: runAll || !!options.coupling,
437
+ sizeBudget: runAll || !!options.size
438
+ }
439
+ });
440
+ const analysisResult = await analyzer.analyze();
441
+ if (!analysisResult.ok) {
442
+ return Ok({
443
+ valid: false,
444
+ violations: [
445
+ {
446
+ tier: 1,
447
+ severity: "error",
448
+ metric: "analysis-error",
449
+ file: "",
450
+ value: 0,
451
+ threshold: 0,
452
+ message: `Analysis failed: ${analysisResult.error.message}`
453
+ }
454
+ ],
455
+ stats: { filesAnalyzed: 0, violationCount: 1, errorCount: 1, warningCount: 0, infoCount: 0 }
456
+ });
457
+ }
458
+ const report = analysisResult.value;
459
+ const violations = [];
460
+ if (report.complexity) {
461
+ for (const v of report.complexity.violations) {
462
+ violations.push({
463
+ tier: v.tier,
464
+ severity: v.severity,
465
+ metric: v.metric,
466
+ file: v.file,
467
+ value: v.value,
468
+ threshold: v.threshold,
469
+ message: v.message || `[Tier ${v.tier}] ${v.metric}: ${v.function} (${v.value} > ${v.threshold})`
470
+ });
471
+ }
472
+ }
473
+ if (report.coupling) {
474
+ for (const v of report.coupling.violations) {
475
+ violations.push({
476
+ tier: v.tier,
477
+ severity: v.severity,
478
+ metric: v.metric,
479
+ file: v.file,
480
+ value: v.value,
481
+ threshold: v.threshold,
482
+ message: v.message || `[Tier ${v.tier}] ${v.metric}: ${v.file} (${v.value} > ${v.threshold})`
483
+ });
484
+ }
485
+ }
486
+ if (report.sizeBudget) {
487
+ for (const v of report.sizeBudget.violations) {
488
+ violations.push({
489
+ tier: v.tier,
490
+ severity: v.severity,
491
+ metric: "sizeBudget",
492
+ file: v.package,
493
+ value: v.currentSize,
494
+ threshold: v.budgetSize,
495
+ message: `[Tier ${v.tier}] Size: ${v.package} (${v.currentSize}B > ${v.budgetSize}B)`
496
+ });
497
+ }
498
+ }
499
+ const hasErrors = violations.some((v) => v.severity === "error");
500
+ const errorCount = violations.filter((v) => v.severity === "error").length;
501
+ const warningCount = violations.filter((v) => v.severity === "warning").length;
502
+ const infoCount = violations.filter((v) => v.severity === "info").length;
503
+ return Ok({
504
+ valid: !hasErrors,
505
+ violations,
506
+ stats: {
507
+ filesAnalyzed: report.complexity?.stats.filesAnalyzed ?? 0,
508
+ violationCount: violations.length,
509
+ errorCount,
510
+ warningCount,
511
+ infoCount
512
+ }
513
+ });
514
+ }
515
+ function createCheckPerfCommand() {
516
+ const command = new Command3("check-perf").description("Run performance checks: structural complexity, coupling, and size budgets").option("--structural", "Run structural complexity checks only").option("--coupling", "Run coupling metric checks only").option("--size", "Run size budget checks only").action(async (opts, cmd) => {
517
+ const globalOpts = cmd.optsWithGlobals();
518
+ const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
519
+ const formatter = new OutputFormatter(mode);
520
+ const result = await runCheckPerf(process.cwd(), {
521
+ structural: opts.structural,
522
+ coupling: opts.coupling,
523
+ size: opts.size
524
+ });
525
+ if (!result.ok) {
526
+ if (mode === OutputMode.JSON) {
527
+ console.log(JSON.stringify({ error: result.error.message }));
528
+ } else {
529
+ logger.error(result.error.message);
530
+ }
531
+ process.exit(ExitCode.ERROR);
532
+ }
533
+ const issues = result.value.violations.map((v) => ({
534
+ file: v.file,
535
+ message: v.message
536
+ }));
537
+ const output = formatter.formatValidation({
538
+ valid: result.value.valid,
539
+ issues
540
+ });
541
+ if (output) {
542
+ console.log(output);
543
+ }
544
+ process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
545
+ });
546
+ return command;
547
+ }
548
+
549
+ // src/commands/check-security.ts
550
+ import { Command as Command4 } from "commander";
551
+ import * as path5 from "path";
552
+ import { execSync } from "child_process";
553
+ var SEVERITY_RANK = {
554
+ error: 3,
555
+ warning: 2,
556
+ info: 1
557
+ };
558
+ function getChangedFiles(cwd) {
559
+ try {
560
+ const output = execSync("git diff --name-only HEAD~1", {
561
+ cwd,
562
+ encoding: "utf-8"
563
+ });
564
+ return output.trim().split("\n").filter((f) => f.length > 0).map((f) => path5.resolve(cwd, f));
565
+ } catch {
566
+ return [];
567
+ }
568
+ }
569
+ async function runCheckSecurity(cwd, options) {
570
+ const projectRoot = path5.resolve(cwd);
571
+ let configData = {};
572
+ try {
573
+ const fs25 = await import("fs");
574
+ const configPath = path5.join(projectRoot, "harness.config.json");
575
+ if (fs25.existsSync(configPath)) {
576
+ const raw = fs25.readFileSync(configPath, "utf-8");
577
+ const parsed = JSON.parse(raw);
578
+ configData = parsed.security ?? {};
579
+ }
580
+ } catch {
581
+ }
582
+ const securityConfig = parseSecurityConfig(configData);
583
+ const scanner = new SecurityScanner(securityConfig);
584
+ scanner.configureForProject(projectRoot);
585
+ let filesToScan;
586
+ if (options.changedOnly) {
587
+ filesToScan = getChangedFiles(projectRoot);
588
+ } else {
589
+ const { glob: glob2 } = await import("glob");
590
+ const pattern = "**/*.{ts,tsx,js,jsx,go,py,java,rb}";
591
+ const ignore = securityConfig.exclude ?? [
592
+ "**/node_modules/**",
593
+ "**/dist/**",
594
+ "**/*.test.ts",
595
+ "**/fixtures/**"
596
+ ];
597
+ filesToScan = await glob2(pattern, { cwd: projectRoot, absolute: true, ignore });
598
+ }
599
+ const result = await scanner.scanFiles(filesToScan);
600
+ const threshold = options.severity ?? "warning";
601
+ const thresholdRank = SEVERITY_RANK[threshold];
602
+ const filtered = result.findings.filter((f) => SEVERITY_RANK[f.severity] >= thresholdRank);
603
+ const hasErrors = filtered.some((f) => f.severity === "error");
604
+ return Ok({
605
+ valid: !hasErrors,
606
+ findings: filtered,
607
+ stats: {
608
+ filesScanned: result.scannedFiles,
609
+ rulesApplied: result.rulesApplied,
610
+ errorCount: filtered.filter((f) => f.severity === "error").length,
611
+ warningCount: filtered.filter((f) => f.severity === "warning").length,
612
+ infoCount: filtered.filter((f) => f.severity === "info").length
613
+ }
614
+ });
615
+ }
616
+ function createCheckSecurityCommand() {
617
+ const command = new Command4("check-security").description("Run lightweight security scan: secrets, injection, XSS, weak crypto").option("--severity <level>", "Minimum severity threshold", "warning").hook("preAction", (thisCommand) => {
618
+ const severity = thisCommand.opts().severity;
619
+ if (!["error", "warning", "info"].includes(severity)) {
620
+ logger.error(`Invalid severity: "${severity}". Must be one of: error, warning, info`);
621
+ process.exit(ExitCode.ERROR);
622
+ }
623
+ }).option("--changed-only", "Only scan git-changed files").action(async (opts, cmd) => {
624
+ const globalOpts = cmd.optsWithGlobals();
625
+ const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
626
+ const formatter = new OutputFormatter(mode);
627
+ const result = await runCheckSecurity(process.cwd(), {
628
+ severity: opts.severity,
629
+ changedOnly: opts.changedOnly
630
+ });
631
+ if (!result.ok) {
632
+ if (mode === OutputMode.JSON) {
633
+ console.log(JSON.stringify({ error: result.error.message }));
634
+ } else {
635
+ logger.error(result.error.message);
636
+ }
637
+ process.exit(ExitCode.ERROR);
638
+ }
639
+ const issues = result.value.findings.map((f) => ({
640
+ file: `${f.file}:${f.line}`,
641
+ message: `[${f.ruleId}] ${f.severity.toUpperCase()} ${f.message}`
642
+ }));
643
+ const output = formatter.formatValidation({
644
+ valid: result.value.valid,
645
+ issues
646
+ });
647
+ if (output) {
648
+ console.log(output);
649
+ }
650
+ process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
651
+ });
652
+ return command;
653
+ }
654
+
655
+ // src/commands/perf.ts
656
+ import { Command as Command5 } from "commander";
657
+ import * as path6 from "path";
658
+ function createPerfCommand() {
659
+ const perf = new Command5("perf").description("Performance benchmark and baseline management");
660
+ perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
661
+ const globalOpts = cmd.optsWithGlobals();
662
+ const cwd = process.cwd();
663
+ const { BenchmarkRunner } = await import("./dist-RBZXXJHG.js");
664
+ const runner = new BenchmarkRunner();
665
+ const benchFiles = runner.discover(cwd, glob2);
666
+ if (benchFiles.length === 0) {
667
+ if (globalOpts.json) {
668
+ console.log(JSON.stringify({ benchFiles: [], message: "No .bench.ts files found" }));
669
+ } else {
670
+ logger.info("No .bench.ts files found. Create *.bench.ts files to add benchmarks.");
671
+ }
672
+ return;
673
+ }
674
+ if (globalOpts.json) {
675
+ logger.info(`Found ${benchFiles.length} benchmark file(s). Running...`);
676
+ } else {
677
+ logger.info(`Found ${benchFiles.length} benchmark file(s):`);
678
+ for (const f of benchFiles) {
679
+ logger.info(` ${f}`);
680
+ }
681
+ logger.info("Running benchmarks...");
682
+ }
683
+ const result = await runner.run(glob2 ? { cwd, glob: glob2 } : { cwd });
684
+ if (globalOpts.json) {
685
+ console.log(JSON.stringify({ results: result.results, success: result.success }));
686
+ } else {
687
+ if (result.success && result.results.length > 0) {
688
+ logger.info(`
689
+ Results (${result.results.length} benchmarks):`);
690
+ for (const r of result.results) {
691
+ logger.info(
692
+ ` ${r.file}::${r.name}: ${r.opsPerSec} ops/s (mean: ${r.meanMs.toFixed(2)}ms)`
693
+ );
694
+ }
695
+ logger.info("\nTo save as baselines: harness perf baselines update");
696
+ } else {
697
+ logger.info("Benchmark run completed. Check output above for details.");
698
+ if (result.rawOutput) {
699
+ console.log(result.rawOutput);
700
+ }
701
+ }
702
+ }
703
+ });
704
+ const baselines = perf.command("baselines").description("Manage performance baselines");
705
+ baselines.command("show").description("Display current baselines").action(async (_opts, cmd) => {
706
+ const globalOpts = cmd.optsWithGlobals();
707
+ const cwd = process.cwd();
708
+ const manager = new BaselineManager(cwd);
709
+ const data = manager.load();
710
+ if (!data) {
711
+ if (globalOpts.json) {
712
+ console.log(JSON.stringify({ baselines: null, message: "No baselines file found" }));
713
+ } else {
714
+ logger.info("No baselines file found at .harness/perf/baselines.json");
715
+ }
716
+ return;
717
+ }
718
+ if (globalOpts.json) {
719
+ console.log(JSON.stringify(data, null, 2));
720
+ } else {
721
+ logger.info(`Baselines (updated: ${data.updatedAt}, from: ${data.updatedFrom})`);
722
+ for (const [name, baseline] of Object.entries(data.benchmarks)) {
723
+ logger.info(
724
+ ` ${name}: ${baseline.opsPerSec} ops/s (mean: ${baseline.meanMs}ms, p99: ${baseline.p99Ms}ms)`
725
+ );
726
+ }
727
+ }
728
+ });
729
+ baselines.command("update").description("Update baselines from latest benchmark run").action(async (_opts, cmd) => {
730
+ const globalOpts = cmd.optsWithGlobals();
731
+ const cwd = process.cwd();
732
+ const { BenchmarkRunner } = await import("./dist-RBZXXJHG.js");
733
+ const runner = new BenchmarkRunner();
734
+ const manager = new BaselineManager(cwd);
735
+ logger.info("Running benchmarks to update baselines...");
736
+ const benchResult = await runner.run({ cwd });
737
+ if (!benchResult.success || benchResult.results.length === 0) {
738
+ logger.error(
739
+ "No benchmark results to save. Run `harness perf bench` first to verify benchmarks work."
740
+ );
741
+ return;
742
+ }
743
+ let commitHash = "unknown";
744
+ try {
745
+ const { execSync: execSync5 } = await import("child_process");
746
+ commitHash = execSync5("git rev-parse --short HEAD", { cwd, encoding: "utf-8" }).trim();
747
+ } catch {
748
+ }
749
+ manager.save(benchResult.results, commitHash);
750
+ if (globalOpts.json) {
751
+ console.log(JSON.stringify({ updated: benchResult.results.length, commitHash }));
752
+ } else {
753
+ logger.info(`Updated ${benchResult.results.length} baseline(s) from commit ${commitHash}`);
754
+ logger.info("Baselines saved to .harness/perf/baselines.json");
755
+ }
756
+ });
757
+ perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
758
+ const globalOpts = cmd.optsWithGlobals();
759
+ const cwd = process.cwd();
760
+ const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-RBZXXJHG.js");
761
+ const analyzer = new EntropyAnalyzer2({
762
+ rootDir: path6.resolve(cwd),
763
+ analyze: { complexity: true, coupling: true }
764
+ });
765
+ const result = await analyzer.analyze();
766
+ if (!result.ok) {
767
+ logger.error(result.error.message);
768
+ return;
769
+ }
770
+ const report = result.value;
771
+ if (globalOpts.json) {
772
+ console.log(
773
+ JSON.stringify(
774
+ {
775
+ complexity: report.complexity,
776
+ coupling: report.coupling,
777
+ sizeBudget: report.sizeBudget
778
+ },
779
+ null,
780
+ 2
781
+ )
782
+ );
783
+ } else {
784
+ logger.info("=== Performance Report ===");
785
+ if (report.complexity) {
786
+ logger.info(
787
+ `Complexity: ${report.complexity.stats.violationCount} violations (${report.complexity.stats.errorCount} errors, ${report.complexity.stats.warningCount} warnings)`
788
+ );
789
+ }
790
+ if (report.coupling) {
791
+ logger.info(
792
+ `Coupling: ${report.coupling.stats.violationCount} violations (${report.coupling.stats.warningCount} warnings)`
793
+ );
794
+ }
795
+ }
796
+ });
797
+ perf.command("critical-paths").description("Show resolved critical path set (annotations + graph inference)").action(async (_opts, cmd) => {
798
+ const globalOpts = cmd.optsWithGlobals();
799
+ const cwd = process.cwd();
800
+ const resolver = new CriticalPathResolver(cwd);
801
+ const result = await resolver.resolve();
802
+ if (globalOpts.json) {
803
+ console.log(JSON.stringify(result, null, 2));
804
+ } else {
805
+ logger.info(
806
+ `Critical paths: ${result.stats.total} (${result.stats.annotated} annotated, ${result.stats.graphInferred} graph-inferred)`
807
+ );
808
+ for (const entry of result.entries) {
809
+ logger.info(
810
+ ` ${entry.file}::${entry.function} [${entry.source}]${entry.fanIn ? ` (fan-in: ${entry.fanIn})` : ""}`
811
+ );
812
+ }
813
+ }
814
+ });
815
+ return perf;
816
+ }
817
+
818
+ // src/commands/check-docs.ts
819
+ import { Command as Command6 } from "commander";
820
+ import * as path7 from "path";
408
821
  async function runCheckDocs(options) {
409
822
  const cwd = options.cwd ?? process.cwd();
410
823
  const minCoverage = options.minCoverage ?? 80;
@@ -413,22 +826,22 @@ async function runCheckDocs(options) {
413
826
  return configResult;
414
827
  }
415
828
  const config = configResult.value;
416
- const docsDir = path4.resolve(cwd, config.docsDir);
417
- const sourceDir = path4.resolve(cwd, config.rootDir);
829
+ const docsDir = path7.resolve(cwd, config.docsDir);
830
+ const sourceDir = path7.resolve(cwd, config.rootDir);
418
831
  const coverageResult = await checkDocCoverage("project", {
419
832
  docsDir,
420
833
  sourceDir,
421
834
  excludePatterns: ["**/*.test.ts", "**/*.spec.ts", "**/node_modules/**"]
422
835
  });
423
836
  if (!coverageResult.ok) {
424
- return Err2(
837
+ return Err(
425
838
  new CLIError(
426
839
  `Documentation coverage check failed: ${coverageResult.error.message}`,
427
840
  ExitCode.ERROR
428
841
  )
429
842
  );
430
843
  }
431
- const knowledgeResult = await validateKnowledgeMap2(cwd);
844
+ const knowledgeResult = await validateKnowledgeMap(cwd);
432
845
  let brokenLinks = [];
433
846
  if (knowledgeResult.ok) {
434
847
  brokenLinks = knowledgeResult.value.brokenLinks.map((b) => b.path);
@@ -443,10 +856,10 @@ async function runCheckDocs(options) {
443
856
  undocumented: coverageResult.value.undocumented,
444
857
  brokenLinks
445
858
  };
446
- return Ok4(result);
859
+ return Ok(result);
447
860
  }
448
861
  function createCheckDocsCommand() {
449
- const command = new Command3("check-docs").description("Check documentation coverage").option("--min-coverage <percent>", "Minimum coverage percentage", "80").action(async (opts, cmd) => {
862
+ const command = new Command6("check-docs").description("Check documentation coverage").option("--min-coverage <percent>", "Minimum coverage percentage", "80").action(async (opts, cmd) => {
450
863
  const globalOpts = cmd.optsWithGlobals();
451
864
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
452
865
  const formatter = new OutputFormatter(mode);
@@ -498,17 +911,15 @@ function createCheckDocsCommand() {
498
911
  }
499
912
 
500
913
  // src/commands/init.ts
501
- import { Command as Command5 } from "commander";
914
+ import { Command as Command8 } from "commander";
502
915
  import chalk3 from "chalk";
503
916
  import * as fs5 from "fs";
504
- import * as path8 from "path";
505
- import { Ok as Ok6, Err as Err4 } from "@harness-engineering/core";
917
+ import * as path11 from "path";
506
918
 
507
919
  // src/templates/engine.ts
508
920
  import * as fs2 from "fs";
509
- import * as path5 from "path";
921
+ import * as path8 from "path";
510
922
  import Handlebars from "handlebars";
511
- import { Ok as Ok5, Err as Err3 } from "@harness-engineering/core";
512
923
 
513
924
  // src/templates/schema.ts
514
925
  import { z as z2 } from "zod";
@@ -576,15 +987,15 @@ var TemplateEngine = class {
576
987
  const templates = [];
577
988
  for (const entry of entries) {
578
989
  if (!entry.isDirectory()) continue;
579
- const metaPath = path5.join(this.templatesDir, entry.name, "template.json");
990
+ const metaPath = path8.join(this.templatesDir, entry.name, "template.json");
580
991
  if (!fs2.existsSync(metaPath)) continue;
581
992
  const raw = JSON.parse(fs2.readFileSync(metaPath, "utf-8"));
582
993
  const parsed = TemplateMetadataSchema.safeParse(raw);
583
994
  if (parsed.success) templates.push(parsed.data);
584
995
  }
585
- return Ok5(templates);
996
+ return Ok(templates);
586
997
  } catch (error) {
587
- return Err3(
998
+ return Err(
588
999
  new Error(
589
1000
  `Failed to list templates: ${error instanceof Error ? error.message : String(error)}`
590
1001
  )
@@ -593,16 +1004,16 @@ var TemplateEngine = class {
593
1004
  }
594
1005
  resolveTemplate(level, framework) {
595
1006
  const levelDir = this.findTemplateDir(level, "level");
596
- if (!levelDir) return Err3(new Error(`Template not found for level: ${level}`));
597
- const metaPath = path5.join(levelDir, "template.json");
1007
+ if (!levelDir) return Err(new Error(`Template not found for level: ${level}`));
1008
+ const metaPath = path8.join(levelDir, "template.json");
598
1009
  const metaRaw = JSON.parse(fs2.readFileSync(metaPath, "utf-8"));
599
1010
  const metaResult = TemplateMetadataSchema.safeParse(metaRaw);
600
1011
  if (!metaResult.success)
601
- return Err3(new Error(`Invalid template.json in ${level}: ${metaResult.error.message}`));
1012
+ return Err(new Error(`Invalid template.json in ${level}: ${metaResult.error.message}`));
602
1013
  const metadata = metaResult.data;
603
1014
  let files = [];
604
1015
  if (metadata.extends) {
605
- const baseDir = path5.join(this.templatesDir, metadata.extends);
1016
+ const baseDir = path8.join(this.templatesDir, metadata.extends);
606
1017
  if (fs2.existsSync(baseDir)) files = this.collectFiles(baseDir, metadata.extends);
607
1018
  }
608
1019
  const levelFiles = this.collectFiles(levelDir, level);
@@ -610,8 +1021,8 @@ var TemplateEngine = class {
610
1021
  let overlayMetadata;
611
1022
  if (framework) {
612
1023
  const frameworkDir = this.findTemplateDir(framework, "framework");
613
- if (!frameworkDir) return Err3(new Error(`Framework template not found: ${framework}`));
614
- const fMetaPath = path5.join(frameworkDir, "template.json");
1024
+ if (!frameworkDir) return Err(new Error(`Framework template not found: ${framework}`));
1025
+ const fMetaPath = path8.join(frameworkDir, "template.json");
615
1026
  const fMetaRaw = JSON.parse(fs2.readFileSync(fMetaPath, "utf-8"));
616
1027
  const fMetaResult = TemplateMetadataSchema.safeParse(fMetaRaw);
617
1028
  if (fMetaResult.success) overlayMetadata = fMetaResult.data;
@@ -621,7 +1032,7 @@ var TemplateEngine = class {
621
1032
  files = files.filter((f) => f.relativePath !== "template.json");
622
1033
  const resolved = { metadata, files };
623
1034
  if (overlayMetadata !== void 0) resolved.overlayMetadata = overlayMetadata;
624
- return Ok5(resolved);
1035
+ return Ok(resolved);
625
1036
  }
626
1037
  render(template, context) {
627
1038
  const rendered = [];
@@ -641,7 +1052,7 @@ var TemplateEngine = class {
641
1052
  }
642
1053
  } catch (error) {
643
1054
  const msg = error instanceof Error ? error.message : String(error);
644
- return Err3(
1055
+ return Err(
645
1056
  new Error(
646
1057
  `Template render failed in ${file.sourceTemplate}/${file.relativePath}: ${msg}`
647
1058
  )
@@ -653,7 +1064,7 @@ var TemplateEngine = class {
653
1064
  rendered.push({ relativePath: file.relativePath, content });
654
1065
  } catch (error) {
655
1066
  const msg = error instanceof Error ? error.message : String(error);
656
- return Err3(
1067
+ return Err(
657
1068
  new Error(
658
1069
  `Template render failed in ${file.sourceTemplate}/${file.relativePath}: ${msg}`
659
1070
  )
@@ -671,24 +1082,24 @@ var TemplateEngine = class {
671
1082
  }
672
1083
  } catch (error) {
673
1084
  const msg = error instanceof Error ? error.message : String(error);
674
- return Err3(new Error(`JSON merge failed: ${msg}`));
1085
+ return Err(new Error(`JSON merge failed: ${msg}`));
675
1086
  }
676
- return Ok5({ files: rendered });
1087
+ return Ok({ files: rendered });
677
1088
  }
678
1089
  write(files, targetDir, options) {
679
1090
  try {
680
1091
  const written = [];
681
1092
  for (const file of files.files) {
682
- const targetPath = path5.join(targetDir, file.relativePath);
683
- const dir = path5.dirname(targetPath);
1093
+ const targetPath = path8.join(targetDir, file.relativePath);
1094
+ const dir = path8.dirname(targetPath);
684
1095
  if (!options.overwrite && fs2.existsSync(targetPath)) continue;
685
1096
  fs2.mkdirSync(dir, { recursive: true });
686
1097
  fs2.writeFileSync(targetPath, file.content);
687
1098
  written.push(file.relativePath);
688
1099
  }
689
- return Ok5(written);
1100
+ return Ok(written);
690
1101
  } catch (error) {
691
- return Err3(
1102
+ return Err(
692
1103
  new Error(
693
1104
  `Failed to write files: ${error instanceof Error ? error.message : String(error)}`
694
1105
  )
@@ -699,16 +1110,16 @@ var TemplateEngine = class {
699
1110
  const entries = fs2.readdirSync(this.templatesDir, { withFileTypes: true });
700
1111
  for (const entry of entries) {
701
1112
  if (!entry.isDirectory()) continue;
702
- const metaPath = path5.join(this.templatesDir, entry.name, "template.json");
1113
+ const metaPath = path8.join(this.templatesDir, entry.name, "template.json");
703
1114
  if (!fs2.existsSync(metaPath)) continue;
704
1115
  const raw = JSON.parse(fs2.readFileSync(metaPath, "utf-8"));
705
1116
  const parsed = TemplateMetadataSchema.safeParse(raw);
706
1117
  if (!parsed.success) continue;
707
1118
  if (type === "level" && parsed.data.level === name)
708
- return path5.join(this.templatesDir, entry.name);
1119
+ return path8.join(this.templatesDir, entry.name);
709
1120
  if (type === "framework" && parsed.data.framework === name)
710
- return path5.join(this.templatesDir, entry.name);
711
- if (parsed.data.name === name) return path5.join(this.templatesDir, entry.name);
1121
+ return path8.join(this.templatesDir, entry.name);
1122
+ if (parsed.data.name === name) return path8.join(this.templatesDir, entry.name);
712
1123
  }
713
1124
  return null;
714
1125
  }
@@ -717,12 +1128,12 @@ var TemplateEngine = class {
717
1128
  const walk = (currentDir) => {
718
1129
  const entries = fs2.readdirSync(currentDir, { withFileTypes: true });
719
1130
  for (const entry of entries) {
720
- const fullPath = path5.join(currentDir, entry.name);
1131
+ const fullPath = path8.join(currentDir, entry.name);
721
1132
  if (entry.isDirectory()) {
722
1133
  walk(fullPath);
723
1134
  } else {
724
1135
  files.push({
725
- relativePath: path5.relative(dir, fullPath),
1136
+ relativePath: path8.relative(dir, fullPath),
726
1137
  absolutePath: fullPath,
727
1138
  isHandlebars: entry.name.endsWith(".hbs"),
728
1139
  sourceTemplate: sourceName
@@ -754,51 +1165,51 @@ var TemplateEngine = class {
754
1165
 
755
1166
  // src/utils/paths.ts
756
1167
  import * as fs3 from "fs";
757
- import * as path6 from "path";
1168
+ import * as path9 from "path";
758
1169
  import { fileURLToPath } from "url";
759
1170
  var __filename = fileURLToPath(import.meta.url);
760
- var __dirname = path6.dirname(__filename);
1171
+ var __dirname = path9.dirname(__filename);
761
1172
  function findUpDir(targetName, marker, maxLevels = 8) {
762
1173
  let dir = __dirname;
763
1174
  for (let i = 0; i < maxLevels; i++) {
764
- const candidate = path6.join(dir, targetName);
1175
+ const candidate = path9.join(dir, targetName);
765
1176
  if (fs3.existsSync(candidate) && fs3.statSync(candidate).isDirectory()) {
766
- if (fs3.existsSync(path6.join(candidate, marker))) {
1177
+ if (fs3.existsSync(path9.join(candidate, marker))) {
767
1178
  return candidate;
768
1179
  }
769
1180
  }
770
- dir = path6.dirname(dir);
1181
+ dir = path9.dirname(dir);
771
1182
  }
772
1183
  return null;
773
1184
  }
774
1185
  function resolveTemplatesDir() {
775
- return findUpDir("templates", "base") ?? path6.join(__dirname, "templates");
1186
+ return findUpDir("templates", "base") ?? path9.join(__dirname, "templates");
776
1187
  }
777
1188
  function resolvePersonasDir() {
778
1189
  const agentsDir = findUpDir("agents", "personas");
779
1190
  if (agentsDir) {
780
- return path6.join(agentsDir, "personas");
1191
+ return path9.join(agentsDir, "personas");
781
1192
  }
782
- return path6.join(__dirname, "agents", "personas");
1193
+ return path9.join(__dirname, "agents", "personas");
783
1194
  }
784
1195
  function resolveSkillsDir() {
785
1196
  const agentsDir = findUpDir("agents", "skills");
786
1197
  if (agentsDir) {
787
- return path6.join(agentsDir, "skills", "claude-code");
1198
+ return path9.join(agentsDir, "skills", "claude-code");
788
1199
  }
789
- return path6.join(__dirname, "agents", "skills", "claude-code");
1200
+ return path9.join(__dirname, "agents", "skills", "claude-code");
790
1201
  }
791
1202
  function resolveProjectSkillsDir(cwd) {
792
1203
  let dir = cwd ?? process.cwd();
793
1204
  for (let i = 0; i < 8; i++) {
794
- const candidate = path6.join(dir, "agents", "skills", "claude-code");
1205
+ const candidate = path9.join(dir, "agents", "skills", "claude-code");
795
1206
  if (fs3.existsSync(candidate) && fs3.statSync(candidate).isDirectory()) {
796
- const agentsDir = path6.join(dir, "agents");
797
- if (fs3.existsSync(path6.join(agentsDir, "skills"))) {
1207
+ const agentsDir = path9.join(dir, "agents");
1208
+ if (fs3.existsSync(path9.join(agentsDir, "skills"))) {
798
1209
  return candidate;
799
1210
  }
800
1211
  }
801
- const parent = path6.dirname(dir);
1212
+ const parent = path9.dirname(dir);
802
1213
  if (parent === dir) break;
803
1214
  dir = parent;
804
1215
  }
@@ -807,15 +1218,15 @@ function resolveProjectSkillsDir(cwd) {
807
1218
  function resolveGlobalSkillsDir() {
808
1219
  const agentsDir = findUpDir("agents", "skills");
809
1220
  if (agentsDir) {
810
- return path6.join(agentsDir, "skills", "claude-code");
1221
+ return path9.join(agentsDir, "skills", "claude-code");
811
1222
  }
812
- return path6.join(__dirname, "agents", "skills", "claude-code");
1223
+ return path9.join(__dirname, "agents", "skills", "claude-code");
813
1224
  }
814
1225
 
815
1226
  // src/commands/setup-mcp.ts
816
- import { Command as Command4 } from "commander";
1227
+ import { Command as Command7 } from "commander";
817
1228
  import * as fs4 from "fs";
818
- import * as path7 from "path";
1229
+ import * as path10 from "path";
819
1230
  import * as os from "os";
820
1231
  import chalk2 from "chalk";
821
1232
  var HARNESS_MCP_ENTRY = {
@@ -832,7 +1243,7 @@ function readJsonFile(filePath) {
832
1243
  }
833
1244
  }
834
1245
  function writeJsonFile(filePath, data) {
835
- const dir = path7.dirname(filePath);
1246
+ const dir = path10.dirname(filePath);
836
1247
  if (!fs4.existsSync(dir)) {
837
1248
  fs4.mkdirSync(dir, { recursive: true });
838
1249
  }
@@ -851,7 +1262,7 @@ function configureMcpServer(configPath) {
851
1262
  return true;
852
1263
  }
853
1264
  function addGeminiTrustedFolder(cwd) {
854
- const trustedPath = path7.join(os.homedir(), ".gemini", "trustedFolders.json");
1265
+ const trustedPath = path10.join(os.homedir(), ".gemini", "trustedFolders.json");
855
1266
  const folders = readJsonFile(trustedPath) ?? {};
856
1267
  if (folders[cwd] === "TRUST_FOLDER") {
857
1268
  return false;
@@ -865,7 +1276,7 @@ function setupMcp(cwd, client) {
865
1276
  const skipped = [];
866
1277
  let trustedFolder = false;
867
1278
  if (client === "all" || client === "claude") {
868
- const configPath = path7.join(cwd, ".mcp.json");
1279
+ const configPath = path10.join(cwd, ".mcp.json");
869
1280
  if (configureMcpServer(configPath)) {
870
1281
  configured.push("Claude Code");
871
1282
  } else {
@@ -873,7 +1284,7 @@ function setupMcp(cwd, client) {
873
1284
  }
874
1285
  }
875
1286
  if (client === "all" || client === "gemini") {
876
- const configPath = path7.join(cwd, ".gemini", "settings.json");
1287
+ const configPath = path10.join(cwd, ".gemini", "settings.json");
877
1288
  if (configureMcpServer(configPath)) {
878
1289
  configured.push("Gemini CLI");
879
1290
  } else {
@@ -884,7 +1295,7 @@ function setupMcp(cwd, client) {
884
1295
  return { configured, skipped, trustedFolder };
885
1296
  }
886
1297
  function createSetupMcpCommand() {
887
- return new Command4("setup-mcp").description("Configure MCP server for AI agent integration").option("--client <client>", "Client to configure (claude, gemini, all)", "all").action(async (opts, cmd) => {
1298
+ return new Command7("setup-mcp").description("Configure MCP server for AI agent integration").option("--client <client>", "Client to configure (claude, gemini, all)", "all").action(async (opts, cmd) => {
888
1299
  const globalOpts = cmd.optsWithGlobals();
889
1300
  const cwd = process.cwd();
890
1301
  const { configured, skipped, trustedFolder } = setupMcp(cwd, opts.client);
@@ -910,8 +1321,12 @@ function createSetupMcpCommand() {
910
1321
  }
911
1322
  console.log("");
912
1323
  console.log(chalk2.bold("The harness MCP server provides:"));
913
- console.log(" - 15 tools for validation, entropy detection, and skill execution");
914
- console.log(" - 4 resources for project context, skills, rules, and learnings");
1324
+ console.log(
1325
+ " - 31 tools for validation, entropy detection, skill execution, graph querying, and more"
1326
+ );
1327
+ console.log(
1328
+ " - 8 resources for project context, skills, rules, learnings, state, and graph data"
1329
+ );
915
1330
  console.log("");
916
1331
  console.log(`Run ${chalk2.cyan("harness skill list")} to see available skills.`);
917
1332
  console.log("");
@@ -923,12 +1338,12 @@ function createSetupMcpCommand() {
923
1338
  // src/commands/init.ts
924
1339
  async function runInit(options) {
925
1340
  const cwd = options.cwd ?? process.cwd();
926
- const name = options.name ?? path8.basename(cwd);
1341
+ const name = options.name ?? path11.basename(cwd);
927
1342
  const level = options.level ?? "basic";
928
1343
  const force = options.force ?? false;
929
- const configPath = path8.join(cwd, "harness.config.json");
1344
+ const configPath = path11.join(cwd, "harness.config.json");
930
1345
  if (!force && fs5.existsSync(configPath)) {
931
- return Err4(
1346
+ return Err(
932
1347
  new CLIError("Project already initialized. Use --force to overwrite.", ExitCode.ERROR)
933
1348
  );
934
1349
  }
@@ -936,7 +1351,7 @@ async function runInit(options) {
936
1351
  const engine = new TemplateEngine(templatesDir);
937
1352
  const resolveResult = engine.resolveTemplate(level, options.framework);
938
1353
  if (!resolveResult.ok) {
939
- return Err4(new CLIError(resolveResult.error.message, ExitCode.ERROR));
1354
+ return Err(new CLIError(resolveResult.error.message, ExitCode.ERROR));
940
1355
  }
941
1356
  const renderResult = engine.render(resolveResult.value, {
942
1357
  projectName: name,
@@ -944,16 +1359,16 @@ async function runInit(options) {
944
1359
  ...options.framework !== void 0 && { framework: options.framework }
945
1360
  });
946
1361
  if (!renderResult.ok) {
947
- return Err4(new CLIError(renderResult.error.message, ExitCode.ERROR));
1362
+ return Err(new CLIError(renderResult.error.message, ExitCode.ERROR));
948
1363
  }
949
1364
  const writeResult = engine.write(renderResult.value, cwd, { overwrite: force });
950
1365
  if (!writeResult.ok) {
951
- return Err4(new CLIError(writeResult.error.message, ExitCode.ERROR));
1366
+ return Err(new CLIError(writeResult.error.message, ExitCode.ERROR));
952
1367
  }
953
- return Ok6({ filesCreated: writeResult.value });
1368
+ return Ok({ filesCreated: writeResult.value });
954
1369
  }
955
1370
  function createInitCommand() {
956
- const command = new Command5("init").description("Initialize a new harness-engineering project").option("-n, --name <name>", "Project name").option("-l, --level <level>", "Adoption level (basic, intermediate, advanced)", "basic").option("--framework <framework>", "Framework overlay (nextjs)").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use defaults without prompting").action(async (opts, cmd) => {
1371
+ const command = new Command8("init").description("Initialize a new harness-engineering project").option("-n, --name <name>", "Project name").option("-l, --level <level>", "Adoption level (basic, intermediate, advanced)", "basic").option("--framework <framework>", "Framework overlay (nextjs)").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use defaults without prompting").action(async (opts, cmd) => {
957
1372
  const globalOpts = cmd.optsWithGlobals();
958
1373
  const result = await runInit({
959
1374
  name: opts.name,
@@ -995,15 +1410,14 @@ function createInitCommand() {
995
1410
  }
996
1411
 
997
1412
  // src/commands/cleanup.ts
998
- import { Command as Command6 } from "commander";
999
- import * as path9 from "path";
1000
- import { Ok as Ok7, Err as Err5, EntropyAnalyzer } from "@harness-engineering/core";
1413
+ import { Command as Command9 } from "commander";
1414
+ import * as path12 from "path";
1001
1415
  async function runCleanup(options) {
1002
1416
  const cwd = options.cwd ?? process.cwd();
1003
1417
  const type = options.type ?? "all";
1004
1418
  const configResult = resolveConfig(options.configPath);
1005
1419
  if (!configResult.ok) {
1006
- return Err5(configResult.error);
1420
+ return Err(configResult.error);
1007
1421
  }
1008
1422
  const config = configResult.value;
1009
1423
  const result = {
@@ -1012,11 +1426,11 @@ async function runCleanup(options) {
1012
1426
  patternViolations: [],
1013
1427
  totalIssues: 0
1014
1428
  };
1015
- const rootDir = path9.resolve(cwd, config.rootDir);
1016
- const docsDir = path9.resolve(cwd, config.docsDir);
1429
+ const rootDir = path12.resolve(cwd, config.rootDir);
1430
+ const docsDir = path12.resolve(cwd, config.docsDir);
1017
1431
  const entropyConfig = {
1018
1432
  rootDir,
1019
- entryPoints: [path9.join(rootDir, "src/index.ts")],
1433
+ entryPoints: [path12.join(rootDir, "src/index.ts")],
1020
1434
  docPaths: [docsDir],
1021
1435
  analyze: {
1022
1436
  drift: type === "all" || type === "drift",
@@ -1028,7 +1442,7 @@ async function runCleanup(options) {
1028
1442
  const analyzer = new EntropyAnalyzer(entropyConfig);
1029
1443
  const analysisResult = await analyzer.analyze();
1030
1444
  if (!analysisResult.ok) {
1031
- return Err5(
1445
+ return Err(
1032
1446
  new CLIError(`Entropy analysis failed: ${analysisResult.error.message}`, ExitCode.ERROR)
1033
1447
  );
1034
1448
  }
@@ -1053,10 +1467,10 @@ async function runCleanup(options) {
1053
1467
  }));
1054
1468
  }
1055
1469
  result.totalIssues = result.driftIssues.length + result.deadCode.length + result.patternViolations.length;
1056
- return Ok7(result);
1470
+ return Ok(result);
1057
1471
  }
1058
1472
  function createCleanupCommand() {
1059
- const command = new Command6("cleanup").description("Detect entropy issues (doc drift, dead code, patterns)").option("-t, --type <type>", "Issue type: drift, dead-code, patterns, all", "all").action(async (opts, cmd) => {
1473
+ const command = new Command9("cleanup").description("Detect entropy issues (doc drift, dead code, patterns)").option("-t, --type <type>", "Issue type: drift, dead-code, patterns, all", "all").action(async (opts, cmd) => {
1060
1474
  const globalOpts = cmd.optsWithGlobals();
1061
1475
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
1062
1476
  const formatter = new OutputFormatter(mode);
@@ -1116,31 +1530,21 @@ function createCleanupCommand() {
1116
1530
  }
1117
1531
 
1118
1532
  // src/commands/fix-drift.ts
1119
- import { Command as Command7 } from "commander";
1120
- import * as path10 from "path";
1121
- import {
1122
- Ok as Ok8,
1123
- Err as Err6,
1124
- buildSnapshot,
1125
- detectDocDrift,
1126
- detectDeadCode,
1127
- createFixes,
1128
- applyFixes,
1129
- generateSuggestions
1130
- } from "@harness-engineering/core";
1533
+ import { Command as Command10 } from "commander";
1534
+ import * as path13 from "path";
1131
1535
  async function runFixDrift(options) {
1132
1536
  const cwd = options.cwd ?? process.cwd();
1133
1537
  const dryRun = options.dryRun !== false;
1134
1538
  const configResult = resolveConfig(options.configPath);
1135
1539
  if (!configResult.ok) {
1136
- return Err6(configResult.error);
1540
+ return Err(configResult.error);
1137
1541
  }
1138
1542
  const config = configResult.value;
1139
- const rootDir = path10.resolve(cwd, config.rootDir);
1140
- const docsDir = path10.resolve(cwd, config.docsDir);
1543
+ const rootDir = path13.resolve(cwd, config.rootDir);
1544
+ const docsDir = path13.resolve(cwd, config.docsDir);
1141
1545
  const entropyConfig = {
1142
1546
  rootDir,
1143
- entryPoints: [path10.join(rootDir, "src/index.ts")],
1547
+ entryPoints: [path13.join(rootDir, "src/index.ts")],
1144
1548
  docPaths: [docsDir],
1145
1549
  analyze: {
1146
1550
  drift: true,
@@ -1151,21 +1555,21 @@ async function runFixDrift(options) {
1151
1555
  };
1152
1556
  const snapshotResult = await buildSnapshot(entropyConfig);
1153
1557
  if (!snapshotResult.ok) {
1154
- return Err6(
1558
+ return Err(
1155
1559
  new CLIError(`Failed to build snapshot: ${snapshotResult.error.message}`, ExitCode.ERROR)
1156
1560
  );
1157
1561
  }
1158
1562
  const snapshot = snapshotResult.value;
1159
1563
  const driftResult = await detectDocDrift(snapshot);
1160
1564
  if (!driftResult.ok) {
1161
- return Err6(
1565
+ return Err(
1162
1566
  new CLIError(`Failed to detect drift: ${driftResult.error.message}`, ExitCode.ERROR)
1163
1567
  );
1164
1568
  }
1165
1569
  const driftReport = driftResult.value;
1166
1570
  const deadCodeResult = await detectDeadCode(snapshot);
1167
1571
  if (!deadCodeResult.ok) {
1168
- return Err6(
1572
+ return Err(
1169
1573
  new CLIError(`Failed to detect dead code: ${deadCodeResult.error.message}`, ExitCode.ERROR)
1170
1574
  );
1171
1575
  }
@@ -1175,7 +1579,7 @@ async function runFixDrift(options) {
1175
1579
  if (!dryRun && fixes.length > 0) {
1176
1580
  const applyResult = await applyFixes(fixes, { dryRun: false });
1177
1581
  if (!applyResult.ok) {
1178
- return Err6(
1582
+ return Err(
1179
1583
  new CLIError(`Failed to apply fixes: ${applyResult.error.message}`, ExitCode.ERROR)
1180
1584
  );
1181
1585
  }
@@ -1224,10 +1628,10 @@ async function runFixDrift(options) {
1224
1628
  fixes: appliedFixes,
1225
1629
  suggestions
1226
1630
  };
1227
- return Ok8(result);
1631
+ return Ok(result);
1228
1632
  }
1229
1633
  function createFixDriftCommand() {
1230
- const command = new Command7("fix-drift").description("Auto-fix entropy issues (doc drift, dead code)").option("--no-dry-run", "Actually apply fixes (default is dry-run mode)").action(async (opts, cmd) => {
1634
+ const command = new Command10("fix-drift").description("Auto-fix entropy issues (doc drift, dead code)").option("--no-dry-run", "Actually apply fixes (default is dry-run mode)").action(async (opts, cmd) => {
1231
1635
  const globalOpts = cmd.optsWithGlobals();
1232
1636
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
1233
1637
  const formatter = new OutputFormatter(mode);
@@ -1287,20 +1691,17 @@ function createFixDriftCommand() {
1287
1691
  }
1288
1692
 
1289
1693
  // src/commands/agent/index.ts
1290
- import { Command as Command10 } from "commander";
1694
+ import { Command as Command13 } from "commander";
1291
1695
 
1292
1696
  // src/commands/agent/run.ts
1293
- import { Command as Command8 } from "commander";
1294
- import * as path14 from "path";
1697
+ import { Command as Command11 } from "commander";
1698
+ import * as path17 from "path";
1295
1699
  import * as childProcess from "child_process";
1296
- import { Ok as Ok10, Err as Err8 } from "@harness-engineering/core";
1297
- import { requestPeerReview } from "@harness-engineering/core";
1298
1700
 
1299
1701
  // src/persona/loader.ts
1300
1702
  import * as fs6 from "fs";
1301
- import * as path11 from "path";
1703
+ import * as path14 from "path";
1302
1704
  import YAML from "yaml";
1303
- import { Ok as Ok9, Err as Err7 } from "@harness-engineering/core";
1304
1705
 
1305
1706
  // src/persona/schema.ts
1306
1707
  import { z as z3 } from "zod";
@@ -1386,36 +1787,36 @@ function normalizePersona(raw) {
1386
1787
  function loadPersona(filePath) {
1387
1788
  try {
1388
1789
  if (!fs6.existsSync(filePath)) {
1389
- return Err7(new Error(`Persona file not found: ${filePath}`));
1790
+ return Err(new Error(`Persona file not found: ${filePath}`));
1390
1791
  }
1391
1792
  const raw = fs6.readFileSync(filePath, "utf-8");
1392
1793
  const parsed = YAML.parse(raw);
1393
1794
  const result = PersonaSchema.safeParse(parsed);
1394
1795
  if (!result.success) {
1395
- return Err7(new Error(`Invalid persona ${filePath}: ${result.error.message}`));
1796
+ return Err(new Error(`Invalid persona ${filePath}: ${result.error.message}`));
1396
1797
  }
1397
- return Ok9(normalizePersona(result.data));
1798
+ return Ok(normalizePersona(result.data));
1398
1799
  } catch (error) {
1399
- return Err7(
1800
+ return Err(
1400
1801
  new Error(`Failed to load persona: ${error instanceof Error ? error.message : String(error)}`)
1401
1802
  );
1402
1803
  }
1403
1804
  }
1404
1805
  function listPersonas(dir) {
1405
1806
  try {
1406
- if (!fs6.existsSync(dir)) return Ok9([]);
1807
+ if (!fs6.existsSync(dir)) return Ok([]);
1407
1808
  const entries = fs6.readdirSync(dir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
1408
1809
  const personas = [];
1409
1810
  for (const entry of entries) {
1410
- const filePath = path11.join(dir, entry);
1811
+ const filePath = path14.join(dir, entry);
1411
1812
  const result = loadPersona(filePath);
1412
1813
  if (result.ok) {
1413
1814
  personas.push({ name: result.value.name, description: result.value.description, filePath });
1414
1815
  }
1415
1816
  }
1416
- return Ok9(personas);
1817
+ return Ok(personas);
1417
1818
  } catch (error) {
1418
- return Err7(
1819
+ return Err(
1419
1820
  new Error(
1420
1821
  `Failed to list personas: ${error instanceof Error ? error.message : String(error)}`
1421
1822
  )
@@ -1425,9 +1826,9 @@ function listPersonas(dir) {
1425
1826
 
1426
1827
  // src/persona/trigger-detector.ts
1427
1828
  import * as fs7 from "fs";
1428
- import * as path12 from "path";
1829
+ import * as path15 from "path";
1429
1830
  function detectTrigger(projectPath) {
1430
- const handoffPath = path12.join(projectPath, ".harness", "handoff.json");
1831
+ const handoffPath = path15.join(projectPath, ".harness", "handoff.json");
1431
1832
  if (!fs7.existsSync(handoffPath)) {
1432
1833
  return { trigger: "manual" };
1433
1834
  }
@@ -1506,8 +1907,8 @@ async function runPersona(persona, context) {
1506
1907
  const result = await Promise.race([
1507
1908
  context.commandExecutor(step.command),
1508
1909
  new Promise(
1509
- (resolve18) => setTimeout(
1510
- () => resolve18({
1910
+ (resolve24) => setTimeout(
1911
+ () => resolve24({
1511
1912
  ok: false,
1512
1913
  error: new Error(TIMEOUT_ERROR_MESSAGE)
1513
1914
  }),
@@ -1562,7 +1963,7 @@ async function runPersona(persona, context) {
1562
1963
  const result = await Promise.race([
1563
1964
  context.skillExecutor(step.skill, skillContext),
1564
1965
  new Promise(
1565
- (resolve18) => setTimeout(() => resolve18(SKILL_TIMEOUT_RESULT), remainingTime)
1966
+ (resolve24) => setTimeout(() => resolve24(SKILL_TIMEOUT_RESULT), remainingTime)
1566
1967
  )
1567
1968
  ]);
1568
1969
  const durationMs = Date.now() - stepStart;
@@ -1606,7 +2007,7 @@ async function runPersona(persona, context) {
1606
2007
 
1607
2008
  // src/persona/skill-executor.ts
1608
2009
  import * as fs8 from "fs";
1609
- import * as path13 from "path";
2010
+ import * as path16 from "path";
1610
2011
  import { parse as parse2 } from "yaml";
1611
2012
  function resolveOutputMode(mode, trigger) {
1612
2013
  if (mode !== "auto") return mode;
@@ -1615,7 +2016,7 @@ function resolveOutputMode(mode, trigger) {
1615
2016
  function buildArtifactPath(projectPath, headSha) {
1616
2017
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1617
2018
  const sha = headSha?.slice(0, 7) ?? "unknown";
1618
- return path13.join(projectPath, ".harness", "reviews", `${date}-${sha}.md`);
2019
+ return path16.join(projectPath, ".harness", "reviews", `${date}-${sha}.md`);
1619
2020
  }
1620
2021
  function buildArtifactContent(skillName, trigger, headSha) {
1621
2022
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -1661,7 +2062,7 @@ function buildArtifactContent(skillName, trigger, headSha) {
1661
2062
  async function executeSkill(skillName, context) {
1662
2063
  const startTime = Date.now();
1663
2064
  const skillsDir = resolveSkillsDir();
1664
- const skillDir = path13.join(skillsDir, skillName);
2065
+ const skillDir = path16.join(skillsDir, skillName);
1665
2066
  if (!fs8.existsSync(skillDir)) {
1666
2067
  return {
1667
2068
  status: "fail",
@@ -1669,7 +2070,7 @@ async function executeSkill(skillName, context) {
1669
2070
  durationMs: Date.now() - startTime
1670
2071
  };
1671
2072
  }
1672
- const yamlPath = path13.join(skillDir, "skill.yaml");
2073
+ const yamlPath = path16.join(skillDir, "skill.yaml");
1673
2074
  if (!fs8.existsSync(yamlPath)) {
1674
2075
  return {
1675
2076
  status: "fail",
@@ -1687,7 +2088,7 @@ async function executeSkill(skillName, context) {
1687
2088
  durationMs: Date.now() - startTime
1688
2089
  };
1689
2090
  }
1690
- const skillMdPath = path13.join(skillDir, "SKILL.md");
2091
+ const skillMdPath = path16.join(skillDir, "SKILL.md");
1691
2092
  if (!fs8.existsSync(skillMdPath)) {
1692
2093
  return {
1693
2094
  status: "fail",
@@ -1707,7 +2108,7 @@ Trigger: ${context.trigger}
1707
2108
  if (resolvedMode === "artifact") {
1708
2109
  artifactPath = buildArtifactPath(context.projectPath, context.headSha);
1709
2110
  const artifactContent = buildArtifactContent(skillName, context.trigger, context.headSha);
1710
- const dir = path13.dirname(artifactPath);
2111
+ const dir = path16.dirname(artifactPath);
1711
2112
  fs8.mkdirSync(dir, { recursive: true });
1712
2113
  fs8.writeFileSync(artifactPath, artifactContent, "utf-8");
1713
2114
  }
@@ -1724,6 +2125,8 @@ var ALLOWED_PERSONA_COMMANDS = /* @__PURE__ */ new Set([
1724
2125
  "validate",
1725
2126
  "check-deps",
1726
2127
  "check-docs",
2128
+ "check-perf",
2129
+ "check-security",
1727
2130
  "cleanup",
1728
2131
  "fix-drift",
1729
2132
  "add"
@@ -1742,7 +2145,7 @@ async function runAgentTask(task, options) {
1742
2145
  };
1743
2146
  const agentType = agentTypeMap[task];
1744
2147
  if (!agentType) {
1745
- return Err8(
2148
+ return Err(
1746
2149
  new CLIError(
1747
2150
  `Unknown task: ${task}. Available: ${Object.keys(agentTypeMap).join(", ")}`,
1748
2151
  ExitCode.ERROR
@@ -1762,10 +2165,10 @@ async function runAgentTask(task, options) {
1762
2165
  { timeout }
1763
2166
  );
1764
2167
  if (!reviewResult.ok) {
1765
- return Err8(new CLIError(`Agent task failed: ${reviewResult.error.message}`, ExitCode.ERROR));
2168
+ return Err(new CLIError(`Agent task failed: ${reviewResult.error.message}`, ExitCode.ERROR));
1766
2169
  }
1767
2170
  const review = reviewResult.value;
1768
- return Ok10({
2171
+ return Ok({
1769
2172
  success: review.approved,
1770
2173
  output: review.approved ? `Agent task '${task}' completed successfully` : `Agent task '${task}' found issues:
1771
2174
  ${review.comments.map((c) => ` - ${c.message}`).join("\n")}`
@@ -1782,11 +2185,11 @@ var VALID_TRIGGERS = /* @__PURE__ */ new Set([
1782
2185
  "auto"
1783
2186
  ]);
1784
2187
  function createRunCommand() {
1785
- return new Command8("run").description("Run an agent task").argument("[task]", "Task to run (review, doc-review, test-review)").option("--timeout <ms>", "Timeout in milliseconds", "300000").option("--persona <name>", "Run a persona by name").option("--trigger <context>", "Trigger context (auto, on_pr, on_commit, manual)", "auto").action(async (task, opts, cmd) => {
2188
+ return new Command11("run").description("Run an agent task").argument("[task]", "Task to run (review, doc-review, test-review)").option("--timeout <ms>", "Timeout in milliseconds", "300000").option("--persona <name>", "Run a persona by name").option("--trigger <context>", "Trigger context (auto, on_pr, on_commit, manual)", "auto").action(async (task, opts, cmd) => {
1786
2189
  const globalOpts = cmd.optsWithGlobals();
1787
2190
  if (opts.persona) {
1788
2191
  const personasDir = resolvePersonasDir();
1789
- const filePath = path14.join(personasDir, `${opts.persona}.yaml`);
2192
+ const filePath = path17.join(personasDir, `${opts.persona}.yaml`);
1790
2193
  const personaResult = loadPersona(filePath);
1791
2194
  if (!personaResult.ok) {
1792
2195
  logger.error(personaResult.error.message);
@@ -1797,13 +2200,13 @@ function createRunCommand() {
1797
2200
  const trigger = opts.trigger === "auto" ? "auto" : VALID_TRIGGERS.has(opts.trigger) ? opts.trigger : "manual";
1798
2201
  const commandExecutor = async (command) => {
1799
2202
  if (!ALLOWED_PERSONA_COMMANDS.has(command)) {
1800
- return Err8(new Error(`Unknown harness command: ${command}`));
2203
+ return Err(new Error(`Unknown harness command: ${command}`));
1801
2204
  }
1802
2205
  try {
1803
2206
  childProcess.execFileSync("npx", ["harness", command], { stdio: "inherit" });
1804
- return Ok10(null);
2207
+ return Ok(null);
1805
2208
  } catch (error) {
1806
- return Err8(new Error(error instanceof Error ? error.message : String(error)));
2209
+ return Err(new Error(error instanceof Error ? error.message : String(error)));
1807
2210
  }
1808
2211
  };
1809
2212
  const report = await runPersona(persona, {
@@ -1843,10 +2246,8 @@ function createRunCommand() {
1843
2246
  }
1844
2247
 
1845
2248
  // src/commands/agent/review.ts
1846
- import { Command as Command9 } from "commander";
1847
- import { execSync } from "child_process";
1848
- import { Ok as Ok11, Err as Err9 } from "@harness-engineering/core";
1849
- import { createSelfReview, parseDiff } from "@harness-engineering/core";
2249
+ import { Command as Command12 } from "commander";
2250
+ import { execSync as execSync2 } from "child_process";
1850
2251
  async function runAgentReview(options) {
1851
2252
  const configResult = resolveConfig(options.configPath);
1852
2253
  if (!configResult.ok) {
@@ -1855,22 +2256,22 @@ async function runAgentReview(options) {
1855
2256
  const config = configResult.value;
1856
2257
  let diff;
1857
2258
  try {
1858
- diff = execSync("git diff --cached", { encoding: "utf-8" });
2259
+ diff = execSync2("git diff --cached", { encoding: "utf-8" });
1859
2260
  if (!diff) {
1860
- diff = execSync("git diff", { encoding: "utf-8" });
2261
+ diff = execSync2("git diff", { encoding: "utf-8" });
1861
2262
  }
1862
2263
  } catch {
1863
- return Err9(new CLIError("Failed to get git diff", ExitCode.ERROR));
2264
+ return Err(new CLIError("Failed to get git diff", ExitCode.ERROR));
1864
2265
  }
1865
2266
  if (!diff) {
1866
- return Ok11({
2267
+ return Ok({
1867
2268
  passed: true,
1868
2269
  checklist: [{ check: "No changes to review", passed: true }]
1869
2270
  });
1870
2271
  }
1871
2272
  const parsedDiffResult = parseDiff(diff);
1872
2273
  if (!parsedDiffResult.ok) {
1873
- return Err9(new CLIError(parsedDiffResult.error.message, ExitCode.ERROR));
2274
+ return Err(new CLIError(parsedDiffResult.error.message, ExitCode.ERROR));
1874
2275
  }
1875
2276
  const codeChanges = parsedDiffResult.value;
1876
2277
  const review = await createSelfReview(codeChanges, {
@@ -1881,9 +2282,9 @@ async function runAgentReview(options) {
1881
2282
  }
1882
2283
  });
1883
2284
  if (!review.ok) {
1884
- return Err9(new CLIError(review.error.message, ExitCode.ERROR));
2285
+ return Err(new CLIError(review.error.message, ExitCode.ERROR));
1885
2286
  }
1886
- return Ok11({
2287
+ return Ok({
1887
2288
  passed: review.value.passed,
1888
2289
  checklist: review.value.items.map((item) => ({
1889
2290
  check: item.check,
@@ -1893,7 +2294,7 @@ async function runAgentReview(options) {
1893
2294
  });
1894
2295
  }
1895
2296
  function createReviewCommand() {
1896
- return new Command9("review").description("Run self-review on current changes").action(async (_opts, cmd) => {
2297
+ return new Command12("review").description("Run self-review on current changes").action(async (_opts, cmd) => {
1897
2298
  const globalOpts = cmd.optsWithGlobals();
1898
2299
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : OutputMode.TEXT;
1899
2300
  const result = await runAgentReview({
@@ -1929,17 +2330,16 @@ function createReviewCommand() {
1929
2330
 
1930
2331
  // src/commands/agent/index.ts
1931
2332
  function createAgentCommand() {
1932
- const command = new Command10("agent").description("Agent orchestration commands");
2333
+ const command = new Command13("agent").description("Agent orchestration commands");
1933
2334
  command.addCommand(createRunCommand());
1934
2335
  command.addCommand(createReviewCommand());
1935
2336
  return command;
1936
2337
  }
1937
2338
 
1938
2339
  // src/commands/add.ts
1939
- import { Command as Command11 } from "commander";
2340
+ import { Command as Command14 } from "commander";
1940
2341
  import * as fs9 from "fs";
1941
- import * as path15 from "path";
1942
- import { Ok as Ok12, Err as Err10 } from "@harness-engineering/core";
2342
+ import * as path18 from "path";
1943
2343
  var LAYER_INDEX_TEMPLATE = (name) => `// ${name} layer
1944
2344
  // Add your ${name} exports here
1945
2345
 
@@ -1969,7 +2369,7 @@ async function runAdd(componentType, name, options) {
1969
2369
  const cwd = options.cwd ?? process.cwd();
1970
2370
  const NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
1971
2371
  if (!name || !NAME_PATTERN.test(name)) {
1972
- return Err10(
2372
+ return Err(
1973
2373
  new CLIError(
1974
2374
  "Invalid name. Must start with a letter and contain only alphanumeric characters, hyphens, and underscores.",
1975
2375
  ExitCode.ERROR
@@ -1983,12 +2383,12 @@ async function runAdd(componentType, name, options) {
1983
2383
  try {
1984
2384
  switch (componentType) {
1985
2385
  case "layer": {
1986
- const layerDir = path15.join(cwd, "src", name);
2386
+ const layerDir = path18.join(cwd, "src", name);
1987
2387
  if (!fs9.existsSync(layerDir)) {
1988
2388
  fs9.mkdirSync(layerDir, { recursive: true });
1989
2389
  created.push(`src/${name}/`);
1990
2390
  }
1991
- const indexPath = path15.join(layerDir, "index.ts");
2391
+ const indexPath = path18.join(layerDir, "index.ts");
1992
2392
  if (!fs9.existsSync(indexPath)) {
1993
2393
  fs9.writeFileSync(indexPath, LAYER_INDEX_TEMPLATE(name));
1994
2394
  created.push(`src/${name}/index.ts`);
@@ -1996,22 +2396,22 @@ async function runAdd(componentType, name, options) {
1996
2396
  break;
1997
2397
  }
1998
2398
  case "module": {
1999
- const modulePath = path15.join(cwd, "src", `${name}.ts`);
2399
+ const modulePath = path18.join(cwd, "src", `${name}.ts`);
2000
2400
  if (fs9.existsSync(modulePath)) {
2001
- return Err10(new CLIError(`Module ${name} already exists`, ExitCode.ERROR));
2401
+ return Err(new CLIError(`Module ${name} already exists`, ExitCode.ERROR));
2002
2402
  }
2003
2403
  fs9.writeFileSync(modulePath, MODULE_TEMPLATE(name));
2004
2404
  created.push(`src/${name}.ts`);
2005
2405
  break;
2006
2406
  }
2007
2407
  case "doc": {
2008
- const docsDir = path15.join(cwd, "docs");
2408
+ const docsDir = path18.join(cwd, "docs");
2009
2409
  if (!fs9.existsSync(docsDir)) {
2010
2410
  fs9.mkdirSync(docsDir, { recursive: true });
2011
2411
  }
2012
- const docPath = path15.join(docsDir, `${name}.md`);
2412
+ const docPath = path18.join(docsDir, `${name}.md`);
2013
2413
  if (fs9.existsSync(docPath)) {
2014
- return Err10(new CLIError(`Doc ${name} already exists`, ExitCode.ERROR));
2414
+ return Err(new CLIError(`Doc ${name} already exists`, ExitCode.ERROR));
2015
2415
  }
2016
2416
  fs9.writeFileSync(docPath, DOC_TEMPLATE(name));
2017
2417
  created.push(`docs/${name}.md`);
@@ -2022,20 +2422,20 @@ async function runAdd(componentType, name, options) {
2022
2422
  generateSkillFiles2({
2023
2423
  name,
2024
2424
  description: `${name} skill`,
2025
- outputDir: path15.join(cwd, "agents", "skills", "claude-code")
2425
+ outputDir: path18.join(cwd, "agents", "skills", "claude-code")
2026
2426
  });
2027
2427
  created.push(`agents/skills/claude-code/${name}/skill.yaml`);
2028
2428
  created.push(`agents/skills/claude-code/${name}/SKILL.md`);
2029
2429
  break;
2030
2430
  }
2031
2431
  case "persona": {
2032
- const personasDir = path15.join(cwd, "agents", "personas");
2432
+ const personasDir = path18.join(cwd, "agents", "personas");
2033
2433
  if (!fs9.existsSync(personasDir)) {
2034
2434
  fs9.mkdirSync(personasDir, { recursive: true });
2035
2435
  }
2036
- const personaPath = path15.join(personasDir, `${name}.yaml`);
2436
+ const personaPath = path18.join(personasDir, `${name}.yaml`);
2037
2437
  if (fs9.existsSync(personaPath)) {
2038
- return Err10(new CLIError(`Persona ${name} already exists`, ExitCode.ERROR));
2438
+ return Err(new CLIError(`Persona ${name} already exists`, ExitCode.ERROR));
2039
2439
  }
2040
2440
  fs9.writeFileSync(
2041
2441
  personaPath,
@@ -2051,7 +2451,7 @@ focus_areas: []
2051
2451
  }
2052
2452
  default: {
2053
2453
  const _exhaustive = componentType;
2054
- return Err10(
2454
+ return Err(
2055
2455
  new CLIError(
2056
2456
  `Unknown component type: ${String(_exhaustive)}. Use: layer, module, doc, skill, persona`,
2057
2457
  ExitCode.ERROR
@@ -2059,9 +2459,9 @@ focus_areas: []
2059
2459
  );
2060
2460
  }
2061
2461
  }
2062
- return Ok12({ created });
2462
+ return Ok({ created });
2063
2463
  } catch (error) {
2064
- return Err10(
2464
+ return Err(
2065
2465
  new CLIError(
2066
2466
  `Failed to add ${componentType}: ${error instanceof Error ? error.message : "Unknown error"}`,
2067
2467
  ExitCode.ERROR
@@ -2070,7 +2470,7 @@ focus_areas: []
2070
2470
  }
2071
2471
  }
2072
2472
  function createAddCommand() {
2073
- const command = new Command11("add").description("Add a component to the project").argument("<type>", "Component type (layer, module, doc, skill, persona)").argument("<name>", "Component name").action(async (type, name, _opts, cmd) => {
2473
+ const command = new Command14("add").description("Add a component to the project").argument("<type>", "Component type (layer, module, doc, skill, persona)").argument("<name>", "Component name").action(async (type, name, _opts, cmd) => {
2074
2474
  const globalOpts = cmd.optsWithGlobals();
2075
2475
  const result = await runAdd(type, name, {
2076
2476
  ...globalOpts.config !== void 0 && { configPath: globalOpts.config }
@@ -2091,13 +2491,352 @@ function createAddCommand() {
2091
2491
  }
2092
2492
 
2093
2493
  // src/commands/linter/index.ts
2094
- import { Command as Command14 } from "commander";
2494
+ import { Command as Command17 } from "commander";
2495
+
2496
+ // src/commands/linter/generate.ts
2497
+ import { Command as Command15 } from "commander";
2498
+
2499
+ // ../linter-gen/dist/generator/orchestrator.js
2500
+ import * as fs12 from "fs/promises";
2501
+ import * as path21 from "path";
2502
+
2503
+ // ../linter-gen/dist/parser/config-parser.js
2504
+ import * as fs10 from "fs/promises";
2505
+ import * as yaml from "yaml";
2506
+
2507
+ // ../linter-gen/dist/schema/linter-config.js
2508
+ import { z as z4 } from "zod";
2509
+ var RuleConfigSchema = z4.object({
2510
+ /** Rule name in kebab-case (e.g., 'no-ui-in-services') */
2511
+ name: z4.string().regex(/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, "Rule name must be kebab-case"),
2512
+ /** Rule type - determines which template to use */
2513
+ type: z4.string().min(1),
2514
+ /** ESLint severity level */
2515
+ severity: z4.enum(["error", "warn", "off"]).default("error"),
2516
+ /** Template-specific configuration */
2517
+ config: z4.record(z4.unknown())
2518
+ });
2519
+ var LinterConfigSchema = z4.object({
2520
+ /** Config version - currently only 1 is supported */
2521
+ version: z4.literal(1),
2522
+ /** Output directory for generated rules */
2523
+ output: z4.string().min(1),
2524
+ /** Optional explicit template path mappings (type → path) */
2525
+ templates: z4.record(z4.string()).optional(),
2526
+ /** Rules to generate */
2527
+ rules: z4.array(RuleConfigSchema).min(1, "At least one rule is required")
2528
+ });
2529
+
2530
+ // ../linter-gen/dist/parser/config-parser.js
2531
+ var ParseError = class extends Error {
2532
+ code;
2533
+ cause;
2534
+ constructor(message, code, cause) {
2535
+ super(message);
2536
+ this.code = code;
2537
+ this.cause = cause;
2538
+ this.name = "ParseError";
2539
+ }
2540
+ };
2541
+ async function parseConfig(configPath) {
2542
+ let content;
2543
+ try {
2544
+ content = await fs10.readFile(configPath, "utf-8");
2545
+ } catch (err) {
2546
+ if (err.code === "ENOENT") {
2547
+ return {
2548
+ success: false,
2549
+ error: new ParseError(`Config file not found: ${configPath}`, "FILE_NOT_FOUND", err)
2550
+ };
2551
+ }
2552
+ return {
2553
+ success: false,
2554
+ error: new ParseError(`Failed to read config file: ${configPath}`, "FILE_READ_ERROR", err)
2555
+ };
2556
+ }
2557
+ let parsed;
2558
+ try {
2559
+ parsed = yaml.parse(content);
2560
+ } catch (err) {
2561
+ return {
2562
+ success: false,
2563
+ error: new ParseError(`Invalid YAML syntax in ${configPath}: ${err.message}`, "YAML_PARSE_ERROR", err)
2564
+ };
2565
+ }
2566
+ const result = LinterConfigSchema.safeParse(parsed);
2567
+ if (!result.success) {
2568
+ const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
2569
+ return {
2570
+ success: false,
2571
+ error: new ParseError(`Invalid config: ${issues}`, "VALIDATION_ERROR", result.error)
2572
+ };
2573
+ }
2574
+ return {
2575
+ success: true,
2576
+ data: result.data,
2577
+ configPath
2578
+ };
2579
+ }
2580
+
2581
+ // ../linter-gen/dist/engine/template-loader.js
2582
+ import * as fs11 from "fs/promises";
2583
+ import * as path19 from "path";
2584
+ import { fileURLToPath as fileURLToPath2 } from "url";
2585
+ var __filename2 = fileURLToPath2(import.meta.url);
2586
+ var __dirname2 = path19.dirname(__filename2);
2587
+ var TemplateLoadError = class extends Error {
2588
+ code;
2589
+ cause;
2590
+ constructor(message, code, cause) {
2591
+ super(message);
2592
+ this.code = code;
2593
+ this.cause = cause;
2594
+ this.name = "TemplateLoadError";
2595
+ }
2596
+ };
2597
+ var BUILTIN_TEMPLATES = ["import-restriction", "boundary-validation", "dependency-graph"];
2598
+ async function fileExists(filePath) {
2599
+ try {
2600
+ await fs11.access(filePath);
2601
+ return true;
2602
+ } catch {
2603
+ return false;
2604
+ }
2605
+ }
2606
+ async function loadTemplateFile(filePath, type) {
2607
+ try {
2608
+ const content = await fs11.readFile(filePath, "utf-8");
2609
+ return {
2610
+ success: true,
2611
+ source: { type, path: filePath, content }
2612
+ };
2613
+ } catch (err) {
2614
+ return {
2615
+ success: false,
2616
+ error: new TemplateLoadError(`Failed to read template: ${filePath}`, "TEMPLATE_READ_ERROR", err)
2617
+ };
2618
+ }
2619
+ }
2620
+ async function loadTemplate(ruleType, templatesConfig, configDir) {
2621
+ if (templatesConfig?.[ruleType]) {
2622
+ const explicitPath = path19.resolve(configDir, templatesConfig[ruleType]);
2623
+ if (await fileExists(explicitPath)) {
2624
+ return loadTemplateFile(explicitPath, "explicit");
2625
+ }
2626
+ return {
2627
+ success: false,
2628
+ error: new TemplateLoadError(`Explicit template not found: ${explicitPath}`, "TEMPLATE_NOT_FOUND")
2629
+ };
2630
+ }
2631
+ const conventionPath = path19.join(configDir, "templates", `${ruleType}.ts.hbs`);
2632
+ if (await fileExists(conventionPath)) {
2633
+ return loadTemplateFile(conventionPath, "convention");
2634
+ }
2635
+ if (BUILTIN_TEMPLATES.includes(ruleType)) {
2636
+ const builtinPath = path19.join(__dirname2, "..", "templates", `${ruleType}.ts.hbs`);
2637
+ if (await fileExists(builtinPath)) {
2638
+ return loadTemplateFile(builtinPath, "builtin");
2639
+ }
2640
+ }
2641
+ return {
2642
+ success: false,
2643
+ error: new TemplateLoadError(`Template not found for type '${ruleType}'. Checked: explicit config, ./templates/${ruleType}.ts.hbs, built-in templates.`, "TEMPLATE_NOT_FOUND")
2644
+ };
2645
+ }
2646
+
2647
+ // ../linter-gen/dist/generator/rule-generator.js
2648
+ import * as path20 from "path";
2649
+
2650
+ // ../linter-gen/dist/engine/context-builder.js
2651
+ var GENERATOR_VERSION = "0.1.0";
2652
+ function toCamelCase(str) {
2653
+ return str.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCase());
2654
+ }
2655
+ function toPascalCase(str) {
2656
+ const camel = toCamelCase(str);
2657
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
2658
+ }
2659
+ function buildRuleContext(rule, configPath) {
2660
+ return {
2661
+ name: rule.name,
2662
+ nameCamel: toCamelCase(rule.name),
2663
+ namePascal: toPascalCase(rule.name),
2664
+ severity: rule.severity,
2665
+ config: rule.config,
2666
+ meta: {
2667
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2668
+ generatorVersion: GENERATOR_VERSION,
2669
+ configPath
2670
+ }
2671
+ };
2672
+ }
2673
+
2674
+ // ../linter-gen/dist/engine/template-renderer.js
2675
+ import Handlebars2 from "handlebars";
2676
+ var TemplateError = class extends Error {
2677
+ cause;
2678
+ constructor(message, cause) {
2679
+ super(message);
2680
+ this.cause = cause;
2681
+ this.name = "TemplateError";
2682
+ }
2683
+ };
2684
+ function toCamelCase2(str) {
2685
+ return str.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCase());
2686
+ }
2687
+ function toPascalCase2(str) {
2688
+ const camel = toCamelCase2(str);
2689
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
2690
+ }
2691
+ Handlebars2.registerHelper("json", (obj) => JSON.stringify(obj));
2692
+ Handlebars2.registerHelper("jsonPretty", (obj) => JSON.stringify(obj, null, 2));
2693
+ Handlebars2.registerHelper("camelCase", (str) => toCamelCase2(str));
2694
+ Handlebars2.registerHelper("pascalCase", (str) => toPascalCase2(str));
2695
+ function renderTemplate(templateSource, context) {
2696
+ try {
2697
+ const compiled = Handlebars2.compile(templateSource, { strict: true });
2698
+ const output = compiled(context);
2699
+ return { success: true, output };
2700
+ } catch (err) {
2701
+ return {
2702
+ success: false,
2703
+ error: new TemplateError(`Template rendering failed: ${err.message}`, err)
2704
+ };
2705
+ }
2706
+ }
2707
+
2708
+ // ../linter-gen/dist/generator/rule-generator.js
2709
+ function generateRule(rule, template, outputDir, configPath) {
2710
+ const context = buildRuleContext(rule, configPath);
2711
+ const renderResult = renderTemplate(template.content, context);
2712
+ if (!renderResult.success) {
2713
+ return {
2714
+ success: false,
2715
+ error: renderResult.error,
2716
+ ruleName: rule.name
2717
+ };
2718
+ }
2719
+ const outputPath = path20.join(outputDir, `${rule.name}.ts`);
2720
+ return {
2721
+ success: true,
2722
+ rule: {
2723
+ name: rule.name,
2724
+ outputPath,
2725
+ content: renderResult.output
2726
+ }
2727
+ };
2728
+ }
2729
+
2730
+ // ../linter-gen/dist/generator/index-generator.js
2731
+ function toCamelCase3(str) {
2732
+ return str.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCase());
2733
+ }
2734
+ function generateIndex(ruleNames) {
2735
+ const imports = ruleNames.map((name) => {
2736
+ const camel = toCamelCase3(name);
2737
+ return `import ${camel} from './${name}';`;
2738
+ }).join("\n");
2739
+ const rulesObject = ruleNames.map((name) => {
2740
+ const camel = toCamelCase3(name);
2741
+ return ` '${name}': ${camel},`;
2742
+ }).join("\n");
2743
+ const namedExports = ruleNames.map(toCamelCase3).join(", ");
2744
+ return `// Generated by @harness-engineering/linter-gen
2745
+ // Do not edit manually - regenerate from harness-linter.yml
2746
+
2747
+ ${imports}
2748
+
2749
+ export const rules = {
2750
+ ${rulesObject}
2751
+ };
2752
+
2753
+ export { ${namedExports} };
2754
+ `;
2755
+ }
2756
+
2757
+ // ../linter-gen/dist/generator/orchestrator.js
2758
+ async function validate(options) {
2759
+ const parseResult = await parseConfig(options.configPath);
2760
+ if (!parseResult.success) {
2761
+ return { success: false, error: parseResult.error };
2762
+ }
2763
+ return { success: true, ruleCount: parseResult.data.rules.length };
2764
+ }
2765
+ async function generate(options) {
2766
+ const errors = [];
2767
+ const parseResult = await parseConfig(options.configPath);
2768
+ if (!parseResult.success) {
2769
+ return { success: false, errors: [{ type: "parse", error: parseResult.error }] };
2770
+ }
2771
+ const config = parseResult.data;
2772
+ const configDir = path21.dirname(path21.resolve(options.configPath));
2773
+ const outputDir = options.outputDir ? path21.resolve(options.outputDir) : path21.resolve(configDir, config.output);
2774
+ if (options.clean && !options.dryRun) {
2775
+ try {
2776
+ await fs12.rm(outputDir, { recursive: true, force: true });
2777
+ } catch {
2778
+ }
2779
+ }
2780
+ if (!options.dryRun) {
2781
+ await fs12.mkdir(outputDir, { recursive: true });
2782
+ }
2783
+ const generatedRules = [];
2784
+ for (const rule of config.rules) {
2785
+ const templateResult = await loadTemplate(rule.type, config.templates, configDir);
2786
+ if (!templateResult.success) {
2787
+ errors.push({
2788
+ type: "template",
2789
+ error: templateResult.error,
2790
+ ruleName: rule.name
2791
+ });
2792
+ continue;
2793
+ }
2794
+ const ruleResult = generateRule(rule, templateResult.source, outputDir, options.configPath);
2795
+ if (!ruleResult.success) {
2796
+ errors.push({
2797
+ type: "render",
2798
+ error: ruleResult.error,
2799
+ ruleName: ruleResult.ruleName
2800
+ });
2801
+ continue;
2802
+ }
2803
+ if (!options.dryRun) {
2804
+ try {
2805
+ await fs12.writeFile(ruleResult.rule.outputPath, ruleResult.rule.content, "utf-8");
2806
+ } catch (err) {
2807
+ errors.push({
2808
+ type: "write",
2809
+ error: err,
2810
+ path: ruleResult.rule.outputPath
2811
+ });
2812
+ continue;
2813
+ }
2814
+ }
2815
+ generatedRules.push(rule.name);
2816
+ }
2817
+ if (generatedRules.length > 0 && !options.dryRun) {
2818
+ const indexContent = generateIndex(generatedRules);
2819
+ const indexPath = path21.join(outputDir, "index.ts");
2820
+ try {
2821
+ await fs12.writeFile(indexPath, indexContent, "utf-8");
2822
+ } catch (err) {
2823
+ errors.push({ type: "write", error: err, path: indexPath });
2824
+ }
2825
+ }
2826
+ if (errors.length > 0) {
2827
+ return { success: false, errors };
2828
+ }
2829
+ return {
2830
+ success: true,
2831
+ rulesGenerated: generatedRules,
2832
+ outputDir,
2833
+ dryRun: options.dryRun ?? false
2834
+ };
2835
+ }
2095
2836
 
2096
2837
  // src/commands/linter/generate.ts
2097
- import { Command as Command12 } from "commander";
2098
- import { generate } from "@harness-engineering/linter-gen";
2099
2838
  function createGenerateCommand() {
2100
- return new Command12("generate").description("Generate ESLint rules from harness-linter.yml").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("-o, --output <dir>", "Override output directory").option("--clean", "Remove existing files before generating").option("--dry-run", "Preview without writing files").option("--json", "Output as JSON").option("--verbose", "Show detailed output").action(async (options) => {
2839
+ return new Command15("generate").description("Generate ESLint rules from harness-linter.yml").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("-o, --output <dir>", "Override output directory").option("--clean", "Remove existing files before generating").option("--dry-run", "Preview without writing files").option("--json", "Output as JSON").option("--verbose", "Show detailed output").action(async (options) => {
2101
2840
  try {
2102
2841
  if (options.verbose) {
2103
2842
  logger.info(`Parsing config: ${options.config}`);
@@ -2159,10 +2898,9 @@ Generated ${result.rulesGenerated.length} rules to ${result.outputDir}`);
2159
2898
  }
2160
2899
 
2161
2900
  // src/commands/linter/validate.ts
2162
- import { Command as Command13 } from "commander";
2163
- import { validate } from "@harness-engineering/linter-gen";
2901
+ import { Command as Command16 } from "commander";
2164
2902
  function createValidateCommand2() {
2165
- return new Command13("validate").description("Validate harness-linter.yml config").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("--json", "Output as JSON").action(async (options) => {
2903
+ return new Command16("validate").description("Validate harness-linter.yml config").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("--json", "Output as JSON").action(async (options) => {
2166
2904
  try {
2167
2905
  const result = await validate({ configPath: options.config });
2168
2906
  if (options.json) {
@@ -2181,7 +2919,7 @@ function createValidateCommand2() {
2181
2919
 
2182
2920
  // src/commands/linter/index.ts
2183
2921
  function createLinterCommand() {
2184
- const linter = new Command14("linter").description(
2922
+ const linter = new Command17("linter").description(
2185
2923
  "Generate and validate ESLint rules from YAML config"
2186
2924
  );
2187
2925
  linter.addCommand(createGenerateCommand());
@@ -2190,12 +2928,12 @@ function createLinterCommand() {
2190
2928
  }
2191
2929
 
2192
2930
  // src/commands/persona/index.ts
2193
- import { Command as Command17 } from "commander";
2931
+ import { Command as Command20 } from "commander";
2194
2932
 
2195
2933
  // src/commands/persona/list.ts
2196
- import { Command as Command15 } from "commander";
2934
+ import { Command as Command18 } from "commander";
2197
2935
  function createListCommand() {
2198
- return new Command15("list").description("List available agent personas").action(async (_opts, cmd) => {
2936
+ return new Command18("list").description("List available agent personas").action(async (_opts, cmd) => {
2199
2937
  const globalOpts = cmd.optsWithGlobals();
2200
2938
  const personasDir = resolvePersonasDir();
2201
2939
  const result = listPersonas(personasDir);
@@ -2224,12 +2962,9 @@ function createListCommand() {
2224
2962
  }
2225
2963
 
2226
2964
  // src/commands/persona/generate.ts
2227
- import { Command as Command16 } from "commander";
2228
- import * as fs10 from "fs";
2229
- import * as path16 from "path";
2230
-
2231
- // src/persona/generators/runtime.ts
2232
- import { Ok as Ok13, Err as Err11 } from "@harness-engineering/core";
2965
+ import { Command as Command19 } from "commander";
2966
+ import * as fs13 from "fs";
2967
+ import * as path22 from "path";
2233
2968
 
2234
2969
  // src/utils/string.ts
2235
2970
  function toKebabCase(name) {
@@ -2246,9 +2981,9 @@ function generateRuntime(persona) {
2246
2981
  timeout: persona.config.timeout,
2247
2982
  severity: persona.config.severity
2248
2983
  };
2249
- return Ok13(JSON.stringify(config, null, 2));
2984
+ return Ok(JSON.stringify(config, null, 2));
2250
2985
  } catch (error) {
2251
- return Err11(
2986
+ return Err(
2252
2987
  new Error(
2253
2988
  `Failed to generate runtime config: ${error instanceof Error ? error.message : String(error)}`
2254
2989
  )
@@ -2257,7 +2992,6 @@ function generateRuntime(persona) {
2257
2992
  }
2258
2993
 
2259
2994
  // src/persona/generators/agents-md.ts
2260
- import { Ok as Ok14, Err as Err12 } from "@harness-engineering/core";
2261
2995
  function formatTrigger(trigger) {
2262
2996
  switch (trigger.event) {
2263
2997
  case "on_pr": {
@@ -2291,9 +3025,9 @@ function generateAgentsMd(persona) {
2291
3025
 
2292
3026
  **When this agent flags an issue:** Fix violations before merging. Run ${allCommands} locally to validate.
2293
3027
  `;
2294
- return Ok14(fragment);
3028
+ return Ok(fragment);
2295
3029
  } catch (error) {
2296
- return Err12(
3030
+ return Err(
2297
3031
  new Error(
2298
3032
  `Failed to generate AGENTS.md fragment: ${error instanceof Error ? error.message : String(error)}`
2299
3033
  )
@@ -2303,7 +3037,6 @@ function generateAgentsMd(persona) {
2303
3037
 
2304
3038
  // src/persona/generators/ci-workflow.ts
2305
3039
  import YAML2 from "yaml";
2306
- import { Ok as Ok15, Err as Err13 } from "@harness-engineering/core";
2307
3040
  function buildGitHubTriggers(triggers) {
2308
3041
  const on = {};
2309
3042
  for (const trigger of triggers) {
@@ -2329,7 +3062,7 @@ function buildGitHubTriggers(triggers) {
2329
3062
  }
2330
3063
  function generateCIWorkflow(persona, platform) {
2331
3064
  try {
2332
- if (platform === "gitlab") return Err13(new Error("GitLab CI generation is not yet supported"));
3065
+ if (platform === "gitlab") return Err(new Error("GitLab CI generation is not yet supported"));
2333
3066
  const severity = persona.config.severity;
2334
3067
  const steps = [
2335
3068
  { uses: "actions/checkout@v4" },
@@ -2351,9 +3084,9 @@ function generateCIWorkflow(persona, platform) {
2351
3084
  }
2352
3085
  }
2353
3086
  };
2354
- return Ok15(YAML2.stringify(workflow, { lineWidth: 0 }));
3087
+ return Ok(YAML2.stringify(workflow, { lineWidth: 0 }));
2355
3088
  } catch (error) {
2356
- return Err13(
3089
+ return Err(
2357
3090
  new Error(
2358
3091
  `Failed to generate CI workflow: ${error instanceof Error ? error.message : String(error)}`
2359
3092
  )
@@ -2363,43 +3096,43 @@ function generateCIWorkflow(persona, platform) {
2363
3096
 
2364
3097
  // src/commands/persona/generate.ts
2365
3098
  function createGenerateCommand2() {
2366
- return new Command16("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
3099
+ return new Command19("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
2367
3100
  const globalOpts = cmd.optsWithGlobals();
2368
3101
  const personasDir = resolvePersonasDir();
2369
- const filePath = path16.join(personasDir, `${name}.yaml`);
3102
+ const filePath = path22.join(personasDir, `${name}.yaml`);
2370
3103
  const personaResult = loadPersona(filePath);
2371
3104
  if (!personaResult.ok) {
2372
3105
  logger.error(personaResult.error.message);
2373
3106
  process.exit(ExitCode.ERROR);
2374
3107
  }
2375
3108
  const persona = personaResult.value;
2376
- const outputDir = path16.resolve(opts.outputDir);
3109
+ const outputDir = path22.resolve(opts.outputDir);
2377
3110
  const slug = toKebabCase(persona.name);
2378
3111
  const only = opts.only;
2379
3112
  const generated = [];
2380
3113
  if (!only || only === "runtime") {
2381
3114
  const result = generateRuntime(persona);
2382
3115
  if (result.ok) {
2383
- const outPath = path16.join(outputDir, `${slug}.runtime.json`);
2384
- fs10.mkdirSync(path16.dirname(outPath), { recursive: true });
2385
- fs10.writeFileSync(outPath, result.value);
3116
+ const outPath = path22.join(outputDir, `${slug}.runtime.json`);
3117
+ fs13.mkdirSync(path22.dirname(outPath), { recursive: true });
3118
+ fs13.writeFileSync(outPath, result.value);
2386
3119
  generated.push(outPath);
2387
3120
  }
2388
3121
  }
2389
3122
  if (!only || only === "agents-md") {
2390
3123
  const result = generateAgentsMd(persona);
2391
3124
  if (result.ok) {
2392
- const outPath = path16.join(outputDir, `${slug}.agents.md`);
2393
- fs10.writeFileSync(outPath, result.value);
3125
+ const outPath = path22.join(outputDir, `${slug}.agents.md`);
3126
+ fs13.writeFileSync(outPath, result.value);
2394
3127
  generated.push(outPath);
2395
3128
  }
2396
3129
  }
2397
3130
  if (!only || only === "ci") {
2398
3131
  const result = generateCIWorkflow(persona, "github");
2399
3132
  if (result.ok) {
2400
- const outPath = path16.join(outputDir, ".github", "workflows", `${slug}.yml`);
2401
- fs10.mkdirSync(path16.dirname(outPath), { recursive: true });
2402
- fs10.writeFileSync(outPath, result.value);
3133
+ const outPath = path22.join(outputDir, ".github", "workflows", `${slug}.yml`);
3134
+ fs13.mkdirSync(path22.dirname(outPath), { recursive: true });
3135
+ fs13.writeFileSync(outPath, result.value);
2403
3136
  generated.push(outPath);
2404
3137
  }
2405
3138
  }
@@ -2413,37 +3146,37 @@ function createGenerateCommand2() {
2413
3146
 
2414
3147
  // src/commands/persona/index.ts
2415
3148
  function createPersonaCommand() {
2416
- const command = new Command17("persona").description("Agent persona management commands");
3149
+ const command = new Command20("persona").description("Agent persona management commands");
2417
3150
  command.addCommand(createListCommand());
2418
3151
  command.addCommand(createGenerateCommand2());
2419
3152
  return command;
2420
3153
  }
2421
3154
 
2422
3155
  // src/commands/skill/index.ts
2423
- import { Command as Command22 } from "commander";
3156
+ import { Command as Command25 } from "commander";
2424
3157
 
2425
3158
  // src/commands/skill/list.ts
2426
- import { Command as Command18 } from "commander";
2427
- import * as fs11 from "fs";
2428
- import * as path17 from "path";
2429
- import { parse as parse3 } from "yaml";
3159
+ import { Command as Command21 } from "commander";
3160
+ import * as fs14 from "fs";
3161
+ import * as path23 from "path";
3162
+ import { parse as parse4 } from "yaml";
2430
3163
  function createListCommand2() {
2431
- return new Command18("list").description("List available skills").action(async (_opts, cmd) => {
3164
+ return new Command21("list").description("List available skills").action(async (_opts, cmd) => {
2432
3165
  const globalOpts = cmd.optsWithGlobals();
2433
3166
  const skillsDir = resolveSkillsDir();
2434
- if (!fs11.existsSync(skillsDir)) {
3167
+ if (!fs14.existsSync(skillsDir)) {
2435
3168
  logger.info("No skills directory found.");
2436
3169
  process.exit(ExitCode.SUCCESS);
2437
3170
  return;
2438
3171
  }
2439
- const entries = fs11.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
3172
+ const entries = fs14.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
2440
3173
  const skills = [];
2441
3174
  for (const name of entries) {
2442
- const yamlPath = path17.join(skillsDir, name, "skill.yaml");
2443
- if (!fs11.existsSync(yamlPath)) continue;
3175
+ const yamlPath = path23.join(skillsDir, name, "skill.yaml");
3176
+ if (!fs14.existsSync(yamlPath)) continue;
2444
3177
  try {
2445
- const raw = fs11.readFileSync(yamlPath, "utf-8");
2446
- const parsed = parse3(raw);
3178
+ const raw = fs14.readFileSync(yamlPath, "utf-8");
3179
+ const parsed = parse4(raw);
2447
3180
  const result = SkillMetadataSchema.safeParse(parsed);
2448
3181
  if (result.success) {
2449
3182
  skills.push(result.data);
@@ -2472,13 +3205,13 @@ function createListCommand2() {
2472
3205
  }
2473
3206
 
2474
3207
  // src/commands/skill/run.ts
2475
- import { Command as Command19 } from "commander";
2476
- import * as fs12 from "fs";
2477
- import * as path18 from "path";
2478
- import { parse as parse4 } from "yaml";
3208
+ import { Command as Command22 } from "commander";
3209
+ import * as fs15 from "fs";
3210
+ import * as path24 from "path";
3211
+ import { parse as parse5 } from "yaml";
2479
3212
 
2480
3213
  // src/skill/complexity.ts
2481
- import { execSync as execSync2 } from "child_process";
3214
+ import { execSync as execSync3 } from "child_process";
2482
3215
  function evaluateSignals(signals) {
2483
3216
  if (signals.fileCount >= 3) return "full";
2484
3217
  if (signals.newDir) return "full";
@@ -2490,17 +3223,17 @@ function evaluateSignals(signals) {
2490
3223
  }
2491
3224
  function detectComplexity(projectPath) {
2492
3225
  try {
2493
- const base = execSync2("git merge-base HEAD main", {
3226
+ const base = execSync3("git merge-base HEAD main", {
2494
3227
  cwd: projectPath,
2495
3228
  encoding: "utf-8",
2496
3229
  stdio: ["pipe", "pipe", "pipe"]
2497
3230
  }).trim();
2498
- const diffFiles = execSync2(`git diff --name-only ${base}`, {
3231
+ const diffFiles = execSync3(`git diff --name-only ${base}`, {
2499
3232
  cwd: projectPath,
2500
3233
  encoding: "utf-8",
2501
3234
  stdio: ["pipe", "pipe", "pipe"]
2502
3235
  }).trim().split("\n").filter(Boolean);
2503
- const diffStat = execSync2(`git diff --stat ${base}`, {
3236
+ const diffStat = execSync3(`git diff --stat ${base}`, {
2504
3237
  cwd: projectPath,
2505
3238
  encoding: "utf-8",
2506
3239
  stdio: ["pipe", "pipe", "pipe"]
@@ -2562,20 +3295,20 @@ ${options.priorState}`);
2562
3295
 
2563
3296
  // src/commands/skill/run.ts
2564
3297
  function createRunCommand2() {
2565
- return new Command19("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>", "Complexity: auto, light, full", "auto").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").action(async (name, opts, _cmd) => {
3298
+ return new Command22("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>", "Complexity: auto, light, full", "auto").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").action(async (name, opts, _cmd) => {
2566
3299
  const skillsDir = resolveSkillsDir();
2567
- const skillDir = path18.join(skillsDir, name);
2568
- if (!fs12.existsSync(skillDir)) {
3300
+ const skillDir = path24.join(skillsDir, name);
3301
+ if (!fs15.existsSync(skillDir)) {
2569
3302
  logger.error(`Skill not found: ${name}`);
2570
3303
  process.exit(ExitCode.ERROR);
2571
3304
  return;
2572
3305
  }
2573
- const yamlPath = path18.join(skillDir, "skill.yaml");
3306
+ const yamlPath = path24.join(skillDir, "skill.yaml");
2574
3307
  let metadata = null;
2575
- if (fs12.existsSync(yamlPath)) {
3308
+ if (fs15.existsSync(yamlPath)) {
2576
3309
  try {
2577
- const raw = fs12.readFileSync(yamlPath, "utf-8");
2578
- const parsed = parse4(raw);
3310
+ const raw = fs15.readFileSync(yamlPath, "utf-8");
3311
+ const parsed = parse5(raw);
2579
3312
  const result = SkillMetadataSchema.safeParse(parsed);
2580
3313
  if (result.success) metadata = result.data;
2581
3314
  } catch {
@@ -2585,17 +3318,17 @@ function createRunCommand2() {
2585
3318
  if (metadata?.phases && metadata.phases.length > 0) {
2586
3319
  const requested = opts.complexity ?? "auto";
2587
3320
  if (requested === "auto") {
2588
- const projectPath2 = opts.path ? path18.resolve(opts.path) : process.cwd();
3321
+ const projectPath2 = opts.path ? path24.resolve(opts.path) : process.cwd();
2589
3322
  complexity = detectComplexity(projectPath2);
2590
3323
  } else {
2591
3324
  complexity = requested;
2592
3325
  }
2593
3326
  }
2594
3327
  let principles;
2595
- const projectPath = opts.path ? path18.resolve(opts.path) : process.cwd();
2596
- const principlesPath = path18.join(projectPath, "docs", "principles.md");
2597
- if (fs12.existsSync(principlesPath)) {
2598
- principles = fs12.readFileSync(principlesPath, "utf-8");
3328
+ const projectPath = opts.path ? path24.resolve(opts.path) : process.cwd();
3329
+ const principlesPath = path24.join(projectPath, "docs", "principles.md");
3330
+ if (fs15.existsSync(principlesPath)) {
3331
+ principles = fs15.readFileSync(principlesPath, "utf-8");
2599
3332
  }
2600
3333
  let priorState;
2601
3334
  let stateWarning;
@@ -2610,16 +3343,16 @@ function createRunCommand2() {
2610
3343
  }
2611
3344
  if (metadata?.state.persistent && metadata.state.files.length > 0) {
2612
3345
  for (const stateFilePath of metadata.state.files) {
2613
- const fullPath = path18.join(projectPath, stateFilePath);
2614
- if (fs12.existsSync(fullPath)) {
2615
- const stat = fs12.statSync(fullPath);
3346
+ const fullPath = path24.join(projectPath, stateFilePath);
3347
+ if (fs15.existsSync(fullPath)) {
3348
+ const stat = fs15.statSync(fullPath);
2616
3349
  if (stat.isDirectory()) {
2617
- const files = fs12.readdirSync(fullPath).map((f) => ({ name: f, mtime: fs12.statSync(path18.join(fullPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
3350
+ const files = fs15.readdirSync(fullPath).map((f) => ({ name: f, mtime: fs15.statSync(path24.join(fullPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
2618
3351
  if (files.length > 0) {
2619
- priorState = fs12.readFileSync(path18.join(fullPath, files[0].name), "utf-8");
3352
+ priorState = fs15.readFileSync(path24.join(fullPath, files[0].name), "utf-8");
2620
3353
  }
2621
3354
  } else {
2622
- priorState = fs12.readFileSync(fullPath, "utf-8");
3355
+ priorState = fs15.readFileSync(fullPath, "utf-8");
2623
3356
  }
2624
3357
  break;
2625
3358
  }
@@ -2638,17 +3371,17 @@ function createRunCommand2() {
2638
3371
  ...stateWarning !== void 0 && { stateWarning },
2639
3372
  party: opts.party
2640
3373
  });
2641
- const skillMdPath = path18.join(skillDir, "SKILL.md");
2642
- if (!fs12.existsSync(skillMdPath)) {
3374
+ const skillMdPath = path24.join(skillDir, "SKILL.md");
3375
+ if (!fs15.existsSync(skillMdPath)) {
2643
3376
  logger.error(`SKILL.md not found for skill: ${name}`);
2644
3377
  process.exit(ExitCode.ERROR);
2645
3378
  return;
2646
3379
  }
2647
- let content = fs12.readFileSync(skillMdPath, "utf-8");
3380
+ let content = fs15.readFileSync(skillMdPath, "utf-8");
2648
3381
  if (metadata?.state.persistent && opts.path) {
2649
- const stateFile = path18.join(projectPath, ".harness", "state.json");
2650
- if (fs12.existsSync(stateFile)) {
2651
- const stateContent = fs12.readFileSync(stateFile, "utf-8");
3382
+ const stateFile = path24.join(projectPath, ".harness", "state.json");
3383
+ if (fs15.existsSync(stateFile)) {
3384
+ const stateContent = fs15.readFileSync(stateFile, "utf-8");
2652
3385
  content += `
2653
3386
 
2654
3387
  ---
@@ -2665,10 +3398,10 @@ ${stateContent}
2665
3398
  }
2666
3399
 
2667
3400
  // src/commands/skill/validate.ts
2668
- import { Command as Command20 } from "commander";
2669
- import * as fs13 from "fs";
2670
- import * as path19 from "path";
2671
- import { parse as parse5 } from "yaml";
3401
+ import { Command as Command23 } from "commander";
3402
+ import * as fs16 from "fs";
3403
+ import * as path25 from "path";
3404
+ import { parse as parse6 } from "yaml";
2672
3405
  var REQUIRED_SECTIONS = [
2673
3406
  "## When to Use",
2674
3407
  "## Process",
@@ -2677,35 +3410,35 @@ var REQUIRED_SECTIONS = [
2677
3410
  "## Examples"
2678
3411
  ];
2679
3412
  function createValidateCommand3() {
2680
- return new Command20("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
3413
+ return new Command23("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
2681
3414
  const globalOpts = cmd.optsWithGlobals();
2682
3415
  const skillsDir = resolveSkillsDir();
2683
- if (!fs13.existsSync(skillsDir)) {
3416
+ if (!fs16.existsSync(skillsDir)) {
2684
3417
  logger.info("No skills directory found.");
2685
3418
  process.exit(ExitCode.SUCCESS);
2686
3419
  return;
2687
3420
  }
2688
- const entries = fs13.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
3421
+ const entries = fs16.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
2689
3422
  const errors = [];
2690
3423
  let validated = 0;
2691
3424
  for (const name of entries) {
2692
- const skillDir = path19.join(skillsDir, name);
2693
- const yamlPath = path19.join(skillDir, "skill.yaml");
2694
- const skillMdPath = path19.join(skillDir, "SKILL.md");
2695
- if (!fs13.existsSync(yamlPath)) {
3425
+ const skillDir = path25.join(skillsDir, name);
3426
+ const yamlPath = path25.join(skillDir, "skill.yaml");
3427
+ const skillMdPath = path25.join(skillDir, "SKILL.md");
3428
+ if (!fs16.existsSync(yamlPath)) {
2696
3429
  errors.push(`${name}: missing skill.yaml`);
2697
3430
  continue;
2698
3431
  }
2699
3432
  try {
2700
- const raw = fs13.readFileSync(yamlPath, "utf-8");
2701
- const parsed = parse5(raw);
3433
+ const raw = fs16.readFileSync(yamlPath, "utf-8");
3434
+ const parsed = parse6(raw);
2702
3435
  const result = SkillMetadataSchema.safeParse(parsed);
2703
3436
  if (!result.success) {
2704
3437
  errors.push(`${name}/skill.yaml: ${result.error.message}`);
2705
3438
  continue;
2706
3439
  }
2707
- if (fs13.existsSync(skillMdPath)) {
2708
- const mdContent = fs13.readFileSync(skillMdPath, "utf-8");
3440
+ if (fs16.existsSync(skillMdPath)) {
3441
+ const mdContent = fs16.readFileSync(skillMdPath, "utf-8");
2709
3442
  for (const section of REQUIRED_SECTIONS) {
2710
3443
  if (!mdContent.includes(section)) {
2711
3444
  errors.push(`${name}/SKILL.md: missing section "${section}"`);
@@ -2746,29 +3479,29 @@ function createValidateCommand3() {
2746
3479
  }
2747
3480
 
2748
3481
  // src/commands/skill/info.ts
2749
- import { Command as Command21 } from "commander";
2750
- import * as fs14 from "fs";
2751
- import * as path20 from "path";
2752
- import { parse as parse6 } from "yaml";
3482
+ import { Command as Command24 } from "commander";
3483
+ import * as fs17 from "fs";
3484
+ import * as path26 from "path";
3485
+ import { parse as parse7 } from "yaml";
2753
3486
  function createInfoCommand() {
2754
- return new Command21("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
3487
+ return new Command24("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
2755
3488
  const globalOpts = cmd.optsWithGlobals();
2756
3489
  const skillsDir = resolveSkillsDir();
2757
- const skillDir = path20.join(skillsDir, name);
2758
- if (!fs14.existsSync(skillDir)) {
3490
+ const skillDir = path26.join(skillsDir, name);
3491
+ if (!fs17.existsSync(skillDir)) {
2759
3492
  logger.error(`Skill not found: ${name}`);
2760
3493
  process.exit(ExitCode.ERROR);
2761
3494
  return;
2762
3495
  }
2763
- const yamlPath = path20.join(skillDir, "skill.yaml");
2764
- if (!fs14.existsSync(yamlPath)) {
3496
+ const yamlPath = path26.join(skillDir, "skill.yaml");
3497
+ if (!fs17.existsSync(yamlPath)) {
2765
3498
  logger.error(`skill.yaml not found for skill: ${name}`);
2766
3499
  process.exit(ExitCode.ERROR);
2767
3500
  return;
2768
3501
  }
2769
3502
  try {
2770
- const raw = fs14.readFileSync(yamlPath, "utf-8");
2771
- const parsed = parse6(raw);
3503
+ const raw = fs17.readFileSync(yamlPath, "utf-8");
3504
+ const parsed = parse7(raw);
2772
3505
  const result = SkillMetadataSchema.safeParse(parsed);
2773
3506
  if (!result.success) {
2774
3507
  logger.error(`Invalid skill.yaml: ${result.error.message}`);
@@ -2808,7 +3541,7 @@ function createInfoCommand() {
2808
3541
 
2809
3542
  // src/commands/skill/index.ts
2810
3543
  function createSkillCommand() {
2811
- const command = new Command22("skill").description("Skill management commands");
3544
+ const command = new Command25("skill").description("Skill management commands");
2812
3545
  command.addCommand(createListCommand2());
2813
3546
  command.addCommand(createRunCommand2());
2814
3547
  command.addCommand(createValidateCommand3());
@@ -2817,17 +3550,16 @@ function createSkillCommand() {
2817
3550
  }
2818
3551
 
2819
3552
  // src/commands/state/index.ts
2820
- import { Command as Command26 } from "commander";
3553
+ import { Command as Command30 } from "commander";
2821
3554
 
2822
3555
  // src/commands/state/show.ts
2823
- import { Command as Command23 } from "commander";
2824
- import * as path21 from "path";
2825
- import { loadState } from "@harness-engineering/core";
3556
+ import { Command as Command26 } from "commander";
3557
+ import * as path27 from "path";
2826
3558
  function createShowCommand() {
2827
- return new Command23("show").description("Show current project state").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => {
3559
+ return new Command26("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
2828
3560
  const globalOpts = cmd.optsWithGlobals();
2829
- const projectPath = path21.resolve(opts.path);
2830
- const result = await loadState(projectPath);
3561
+ const projectPath = path27.resolve(opts.path);
3562
+ const result = await loadState(projectPath, opts.stream);
2831
3563
  if (!result.ok) {
2832
3564
  logger.error(result.error.message);
2833
3565
  process.exit(ExitCode.ERROR);
@@ -2839,6 +3571,7 @@ function createShowCommand() {
2839
3571
  } else if (globalOpts.quiet) {
2840
3572
  console.log(JSON.stringify(state));
2841
3573
  } else {
3574
+ if (opts.stream) console.log(`Stream: ${opts.stream}`);
2842
3575
  console.log(`Schema Version: ${state.schemaVersion}`);
2843
3576
  if (state.position.phase) console.log(`Phase: ${state.position.phase}`);
2844
3577
  if (state.position.task) console.log(`Task: ${state.position.task}`);
@@ -2865,23 +3598,34 @@ Decisions: ${state.decisions.length}`);
2865
3598
  }
2866
3599
 
2867
3600
  // src/commands/state/reset.ts
2868
- import { Command as Command24 } from "commander";
2869
- import * as fs15 from "fs";
2870
- import * as path22 from "path";
3601
+ import { Command as Command27 } from "commander";
3602
+ import * as fs18 from "fs";
3603
+ import * as path28 from "path";
2871
3604
  import * as readline from "readline";
2872
3605
  function createResetCommand() {
2873
- return new Command24("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--yes", "Skip confirmation prompt").action(async (opts, _cmd) => {
2874
- const projectPath = path22.resolve(opts.path);
2875
- const statePath = path22.join(projectPath, ".harness", "state.json");
2876
- if (!fs15.existsSync(statePath)) {
3606
+ return new Command27("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts, _cmd) => {
3607
+ const projectPath = path28.resolve(opts.path);
3608
+ let statePath;
3609
+ if (opts.stream) {
3610
+ const streamResult = await resolveStreamPath(projectPath, { stream: opts.stream });
3611
+ if (!streamResult.ok) {
3612
+ logger.error(streamResult.error.message);
3613
+ process.exit(ExitCode.ERROR);
3614
+ return;
3615
+ }
3616
+ statePath = path28.join(streamResult.value, "state.json");
3617
+ } else {
3618
+ statePath = path28.join(projectPath, ".harness", "state.json");
3619
+ }
3620
+ if (!fs18.existsSync(statePath)) {
2877
3621
  logger.info("No state file found. Nothing to reset.");
2878
3622
  process.exit(ExitCode.SUCCESS);
2879
3623
  return;
2880
3624
  }
2881
3625
  if (!opts.yes) {
2882
3626
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
2883
- const answer = await new Promise((resolve18) => {
2884
- rl.question("Reset project state? This cannot be undone. [y/N] ", resolve18);
3627
+ const answer = await new Promise((resolve24) => {
3628
+ rl.question("Reset project state? This cannot be undone. [y/N] ", resolve24);
2885
3629
  });
2886
3630
  rl.close();
2887
3631
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
@@ -2891,7 +3635,7 @@ function createResetCommand() {
2891
3635
  }
2892
3636
  }
2893
3637
  try {
2894
- fs15.unlinkSync(statePath);
3638
+ fs18.unlinkSync(statePath);
2895
3639
  logger.success("Project state reset.");
2896
3640
  } catch (e) {
2897
3641
  logger.error(`Failed to reset state: ${e instanceof Error ? e.message : String(e)}`);
@@ -2903,13 +3647,12 @@ function createResetCommand() {
2903
3647
  }
2904
3648
 
2905
3649
  // src/commands/state/learn.ts
2906
- import { Command as Command25 } from "commander";
2907
- import * as path23 from "path";
2908
- import { appendLearning } from "@harness-engineering/core";
3650
+ import { Command as Command28 } from "commander";
3651
+ import * as path29 from "path";
2909
3652
  function createLearnCommand() {
2910
- return new Command25("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").action(async (message, opts, _cmd) => {
2911
- const projectPath = path23.resolve(opts.path);
2912
- const result = await appendLearning(projectPath, message);
3653
+ return new Command28("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) => {
3654
+ const projectPath = path29.resolve(opts.path);
3655
+ const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
2913
3656
  if (!result.ok) {
2914
3657
  logger.error(result.error.message);
2915
3658
  process.exit(ExitCode.ERROR);
@@ -2920,29 +3663,95 @@ function createLearnCommand() {
2920
3663
  });
2921
3664
  }
2922
3665
 
3666
+ // src/commands/state/streams.ts
3667
+ import { Command as Command29 } from "commander";
3668
+ import * as path30 from "path";
3669
+ function createStreamsCommand() {
3670
+ const command = new Command29("streams").description("Manage state streams");
3671
+ command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => {
3672
+ const globalOpts = cmd.optsWithGlobals();
3673
+ const projectPath = path30.resolve(opts.path);
3674
+ const indexResult = await loadStreamIndex(projectPath);
3675
+ const result = await listStreams(projectPath);
3676
+ if (!result.ok) {
3677
+ logger.error(result.error.message);
3678
+ process.exit(ExitCode.ERROR);
3679
+ return;
3680
+ }
3681
+ const active = indexResult.ok ? indexResult.value.activeStream : null;
3682
+ if (globalOpts.json) {
3683
+ logger.raw({ activeStream: active, streams: result.value });
3684
+ } else {
3685
+ if (result.value.length === 0) {
3686
+ console.log("No streams found.");
3687
+ }
3688
+ for (const s of result.value) {
3689
+ const marker = s.name === active ? " (active)" : "";
3690
+ const branch = s.branch ? ` [${s.branch}]` : "";
3691
+ console.log(` ${s.name}${marker}${branch} \u2014 last active: ${s.lastActiveAt}`);
3692
+ }
3693
+ }
3694
+ process.exit(ExitCode.SUCCESS);
3695
+ });
3696
+ 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) => {
3697
+ const projectPath = path30.resolve(opts.path);
3698
+ const result = await createStream(projectPath, name, opts.branch);
3699
+ if (!result.ok) {
3700
+ logger.error(result.error.message);
3701
+ process.exit(ExitCode.ERROR);
3702
+ return;
3703
+ }
3704
+ logger.success(`Stream '${name}' created.`);
3705
+ process.exit(ExitCode.SUCCESS);
3706
+ });
3707
+ command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => {
3708
+ const projectPath = path30.resolve(opts.path);
3709
+ const result = await archiveStream(projectPath, name);
3710
+ if (!result.ok) {
3711
+ logger.error(result.error.message);
3712
+ process.exit(ExitCode.ERROR);
3713
+ return;
3714
+ }
3715
+ logger.success(`Stream '${name}' archived.`);
3716
+ process.exit(ExitCode.SUCCESS);
3717
+ });
3718
+ command.command("activate <name>").description("Set the active stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => {
3719
+ const projectPath = path30.resolve(opts.path);
3720
+ const result = await setActiveStream(projectPath, name);
3721
+ if (!result.ok) {
3722
+ logger.error(result.error.message);
3723
+ process.exit(ExitCode.ERROR);
3724
+ return;
3725
+ }
3726
+ logger.success(`Active stream set to '${name}'.`);
3727
+ process.exit(ExitCode.SUCCESS);
3728
+ });
3729
+ return command;
3730
+ }
3731
+
2923
3732
  // src/commands/state/index.ts
2924
3733
  function createStateCommand() {
2925
- const command = new Command26("state").description("Project state management commands");
3734
+ const command = new Command30("state").description("Project state management commands");
2926
3735
  command.addCommand(createShowCommand());
2927
3736
  command.addCommand(createResetCommand());
2928
3737
  command.addCommand(createLearnCommand());
3738
+ command.addCommand(createStreamsCommand());
2929
3739
  return command;
2930
3740
  }
2931
3741
 
2932
3742
  // src/commands/check-phase-gate.ts
2933
- import { Command as Command27 } from "commander";
2934
- import * as path24 from "path";
2935
- import * as fs16 from "fs";
2936
- import { Ok as Ok16 } from "@harness-engineering/core";
3743
+ import { Command as Command31 } from "commander";
3744
+ import * as path31 from "path";
3745
+ import * as fs19 from "fs";
2937
3746
  function resolveSpecPath(implFile, implPattern, specPattern, cwd) {
2938
- const relImpl = path24.relative(cwd, implFile);
3747
+ const relImpl = path31.relative(cwd, implFile);
2939
3748
  const implBase = (implPattern.split("*")[0] ?? "").replace(/\/+$/, "");
2940
3749
  const afterBase = relImpl.startsWith(implBase + "/") ? relImpl.slice(implBase.length + 1) : relImpl;
2941
3750
  const segments = afterBase.split("/");
2942
3751
  const firstSegment = segments[0] ?? "";
2943
- const feature = segments.length > 1 ? firstSegment : path24.basename(firstSegment, path24.extname(firstSegment));
3752
+ const feature = segments.length > 1 ? firstSegment : path31.basename(firstSegment, path31.extname(firstSegment));
2944
3753
  const specRelative = specPattern.replace("{feature}", feature);
2945
- return path24.resolve(cwd, specRelative);
3754
+ return path31.resolve(cwd, specRelative);
2946
3755
  }
2947
3756
  async function runCheckPhaseGate(options) {
2948
3757
  const configResult = resolveConfig(options.configPath);
@@ -2950,9 +3759,9 @@ async function runCheckPhaseGate(options) {
2950
3759
  return configResult;
2951
3760
  }
2952
3761
  const config = configResult.value;
2953
- const cwd = options.cwd ?? (options.configPath ? path24.dirname(path24.resolve(options.configPath)) : process.cwd());
3762
+ const cwd = options.cwd ?? (options.configPath ? path31.dirname(path31.resolve(options.configPath)) : process.cwd());
2954
3763
  if (!config.phaseGates?.enabled) {
2955
- return Ok16({
3764
+ return Ok({
2956
3765
  pass: true,
2957
3766
  skipped: true,
2958
3767
  missingSpecs: [],
@@ -2967,16 +3776,16 @@ async function runCheckPhaseGate(options) {
2967
3776
  for (const implFile of implFiles) {
2968
3777
  checkedFiles++;
2969
3778
  const expectedSpec = resolveSpecPath(implFile, mapping.implPattern, mapping.specPattern, cwd);
2970
- if (!fs16.existsSync(expectedSpec)) {
3779
+ if (!fs19.existsSync(expectedSpec)) {
2971
3780
  missingSpecs.push({
2972
- implFile: path24.relative(cwd, implFile),
2973
- expectedSpec: path24.relative(cwd, expectedSpec)
3781
+ implFile: path31.relative(cwd, implFile),
3782
+ expectedSpec: path31.relative(cwd, expectedSpec)
2974
3783
  });
2975
3784
  }
2976
3785
  }
2977
3786
  }
2978
3787
  const pass = missingSpecs.length === 0;
2979
- return Ok16({
3788
+ return Ok({
2980
3789
  pass,
2981
3790
  skipped: false,
2982
3791
  severity: phaseGates.severity,
@@ -2985,7 +3794,7 @@ async function runCheckPhaseGate(options) {
2985
3794
  });
2986
3795
  }
2987
3796
  function createCheckPhaseGateCommand() {
2988
- const command = new Command27("check-phase-gate").description("Verify that implementation files have matching spec documents").action(async (_opts, cmd) => {
3797
+ const command = new Command31("check-phase-gate").description("Verify that implementation files have matching spec documents").action(async (_opts, cmd) => {
2989
3798
  const globalOpts = cmd.optsWithGlobals();
2990
3799
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
2991
3800
  const formatter = new OutputFormatter(mode);
@@ -3039,16 +3848,16 @@ function createCheckPhaseGateCommand() {
3039
3848
  }
3040
3849
 
3041
3850
  // src/commands/generate-slash-commands.ts
3042
- import { Command as Command28 } from "commander";
3043
- import fs19 from "fs";
3044
- import path27 from "path";
3851
+ import { Command as Command32 } from "commander";
3852
+ import fs22 from "fs";
3853
+ import path34 from "path";
3045
3854
  import os2 from "os";
3046
3855
  import readline2 from "readline";
3047
3856
 
3048
3857
  // src/slash-commands/normalize.ts
3049
- import fs17 from "fs";
3050
- import path25 from "path";
3051
- import { parse as parse7 } from "yaml";
3858
+ import fs20 from "fs";
3859
+ import path32 from "path";
3860
+ import { parse as parse8 } from "yaml";
3052
3861
 
3053
3862
  // src/slash-commands/normalize-name.ts
3054
3863
  function normalizeName(skillName) {
@@ -3068,18 +3877,18 @@ function normalizeSkills(skillSources, platforms) {
3068
3877
  const specs = [];
3069
3878
  const nameMap = /* @__PURE__ */ new Map();
3070
3879
  for (const { dir: skillsDir, source } of skillSources) {
3071
- if (!fs17.existsSync(skillsDir)) continue;
3072
- const entries = fs17.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
3880
+ if (!fs20.existsSync(skillsDir)) continue;
3881
+ const entries = fs20.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
3073
3882
  for (const entry of entries) {
3074
- const yamlPath = path25.join(skillsDir, entry.name, "skill.yaml");
3075
- if (!fs17.existsSync(yamlPath)) continue;
3883
+ const yamlPath = path32.join(skillsDir, entry.name, "skill.yaml");
3884
+ if (!fs20.existsSync(yamlPath)) continue;
3076
3885
  let raw;
3077
3886
  try {
3078
- raw = fs17.readFileSync(yamlPath, "utf-8");
3887
+ raw = fs20.readFileSync(yamlPath, "utf-8");
3079
3888
  } catch {
3080
3889
  continue;
3081
3890
  }
3082
- const parsed = parse7(raw);
3891
+ const parsed = parse8(raw);
3083
3892
  const result = SkillMetadataSchema.safeParse(parsed);
3084
3893
  if (!result.success) {
3085
3894
  console.warn(`Skipping ${entry.name}: invalid skill.yaml`);
@@ -3099,15 +3908,15 @@ function normalizeSkills(skillSources, platforms) {
3099
3908
  continue;
3100
3909
  }
3101
3910
  nameMap.set(normalized, { skillName: meta.name, source });
3102
- const skillMdPath = path25.join(skillsDir, entry.name, "SKILL.md");
3103
- const skillMdContent = fs17.existsSync(skillMdPath) ? fs17.readFileSync(skillMdPath, "utf-8") : "";
3104
- const skillMdRelative = path25.relative(
3911
+ const skillMdPath = path32.join(skillsDir, entry.name, "SKILL.md");
3912
+ const skillMdContent = fs20.existsSync(skillMdPath) ? fs20.readFileSync(skillMdPath, "utf-8") : "";
3913
+ const skillMdRelative = path32.relative(
3105
3914
  process.cwd(),
3106
- path25.join(skillsDir, entry.name, "SKILL.md")
3915
+ path32.join(skillsDir, entry.name, "SKILL.md")
3107
3916
  );
3108
- const skillYamlRelative = path25.relative(
3917
+ const skillYamlRelative = path32.relative(
3109
3918
  process.cwd(),
3110
- path25.join(skillsDir, entry.name, "skill.yaml")
3919
+ path32.join(skillsDir, entry.name, "skill.yaml")
3111
3920
  );
3112
3921
  const args = (meta.cli?.args ?? []).map((a) => ({
3113
3922
  name: a.name,
@@ -3276,8 +4085,8 @@ function renderGemini(spec, skillMdContent, skillYamlContent) {
3276
4085
  }
3277
4086
 
3278
4087
  // src/slash-commands/sync.ts
3279
- import fs18 from "fs";
3280
- import path26 from "path";
4088
+ import fs21 from "fs";
4089
+ import path33 from "path";
3281
4090
 
3282
4091
  // src/agent-definitions/constants.ts
3283
4092
  var GENERATED_HEADER_AGENT = "<!-- Generated by harness generate-agent-definitions. Do not edit. -->";
@@ -3289,11 +4098,11 @@ function computeSyncPlan(outputDir, rendered) {
3289
4098
  const removed = [];
3290
4099
  const unchanged = [];
3291
4100
  for (const [filename, content] of rendered) {
3292
- const filePath = path26.join(outputDir, filename);
3293
- if (!fs18.existsSync(filePath)) {
4101
+ const filePath = path33.join(outputDir, filename);
4102
+ if (!fs21.existsSync(filePath)) {
3294
4103
  added.push(filename);
3295
4104
  } else {
3296
- const existing = fs18.readFileSync(filePath, "utf-8");
4105
+ const existing = fs21.readFileSync(filePath, "utf-8");
3297
4106
  if (existing === content) {
3298
4107
  unchanged.push(filename);
3299
4108
  } else {
@@ -3301,14 +4110,14 @@ function computeSyncPlan(outputDir, rendered) {
3301
4110
  }
3302
4111
  }
3303
4112
  }
3304
- if (fs18.existsSync(outputDir)) {
3305
- const existing = fs18.readdirSync(outputDir).filter((f) => {
3306
- const stat = fs18.statSync(path26.join(outputDir, f));
4113
+ if (fs21.existsSync(outputDir)) {
4114
+ const existing = fs21.readdirSync(outputDir).filter((f) => {
4115
+ const stat = fs21.statSync(path33.join(outputDir, f));
3307
4116
  return stat.isFile();
3308
4117
  });
3309
4118
  for (const filename of existing) {
3310
4119
  if (rendered.has(filename)) continue;
3311
- const content = fs18.readFileSync(path26.join(outputDir, filename), "utf-8");
4120
+ const content = fs21.readFileSync(path33.join(outputDir, filename), "utf-8");
3312
4121
  if (content.includes(GENERATED_HEADER_CLAUDE) || content.includes(GENERATED_HEADER_GEMINI) || content.includes(GENERATED_HEADER_AGENT)) {
3313
4122
  removed.push(filename);
3314
4123
  }
@@ -3317,18 +4126,18 @@ function computeSyncPlan(outputDir, rendered) {
3317
4126
  return { added, updated, removed, unchanged };
3318
4127
  }
3319
4128
  function applySyncPlan(outputDir, rendered, plan, deleteOrphans) {
3320
- fs18.mkdirSync(outputDir, { recursive: true });
4129
+ fs21.mkdirSync(outputDir, { recursive: true });
3321
4130
  for (const filename of [...plan.added, ...plan.updated]) {
3322
4131
  const content = rendered.get(filename);
3323
4132
  if (content !== void 0) {
3324
- fs18.writeFileSync(path26.join(outputDir, filename), content);
4133
+ fs21.writeFileSync(path33.join(outputDir, filename), content);
3325
4134
  }
3326
4135
  }
3327
4136
  if (deleteOrphans) {
3328
4137
  for (const filename of plan.removed) {
3329
- const filePath = path26.join(outputDir, filename);
3330
- if (fs18.existsSync(filePath)) {
3331
- fs18.unlinkSync(filePath);
4138
+ const filePath = path33.join(outputDir, filename);
4139
+ if (fs21.existsSync(filePath)) {
4140
+ fs21.unlinkSync(filePath);
3332
4141
  }
3333
4142
  }
3334
4143
  }
@@ -3337,24 +4146,24 @@ function applySyncPlan(outputDir, rendered, plan, deleteOrphans) {
3337
4146
  // src/commands/generate-slash-commands.ts
3338
4147
  function resolveOutputDir(platform, opts) {
3339
4148
  if (opts.output) {
3340
- return path27.join(opts.output, "harness");
4149
+ return path34.join(opts.output, "harness");
3341
4150
  }
3342
4151
  if (opts.global) {
3343
4152
  const home = os2.homedir();
3344
- return platform === "claude-code" ? path27.join(home, ".claude", "commands", "harness") : path27.join(home, ".gemini", "commands", "harness");
4153
+ return platform === "claude-code" ? path34.join(home, ".claude", "commands", "harness") : path34.join(home, ".gemini", "commands", "harness");
3345
4154
  }
3346
- return platform === "claude-code" ? path27.join("agents", "commands", "claude-code", "harness") : path27.join("agents", "commands", "gemini-cli", "harness");
4155
+ return platform === "claude-code" ? path34.join("agents", "commands", "claude-code", "harness") : path34.join("agents", "commands", "gemini-cli", "harness");
3347
4156
  }
3348
4157
  function fileExtension(platform) {
3349
4158
  return platform === "claude-code" ? ".md" : ".toml";
3350
4159
  }
3351
4160
  async function confirmDeletion(files) {
3352
4161
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
3353
- return new Promise((resolve18) => {
4162
+ return new Promise((resolve24) => {
3354
4163
  rl.question(`
3355
4164
  Remove ${files.length} orphaned command(s)? (y/N) `, (answer) => {
3356
4165
  rl.close();
3357
- resolve18(answer.toLowerCase() === "y");
4166
+ resolve24(answer.toLowerCase() === "y");
3358
4167
  });
3359
4168
  });
3360
4169
  }
@@ -3369,7 +4178,7 @@ function generateSlashCommands(opts) {
3369
4178
  }
3370
4179
  if (opts.includeGlobal || skillSources.length === 0) {
3371
4180
  const globalDir = resolveGlobalSkillsDir();
3372
- if (!projectDir || path27.resolve(globalDir) !== path27.resolve(projectDir)) {
4181
+ if (!projectDir || path34.resolve(globalDir) !== path34.resolve(projectDir)) {
3373
4182
  skillSources.push({ dir: globalDir, source: "global" });
3374
4183
  }
3375
4184
  }
@@ -3391,7 +4200,7 @@ function generateSlashCommands(opts) {
3391
4200
  executionContext: spec.prompt.executionContext.split("\n").map((line) => {
3392
4201
  if (line.startsWith("@")) {
3393
4202
  const relPath = line.slice(1);
3394
- return `@${path27.resolve(relPath)}`;
4203
+ return `@${path34.resolve(relPath)}`;
3395
4204
  }
3396
4205
  return line;
3397
4206
  }).join("\n")
@@ -3399,10 +4208,10 @@ function generateSlashCommands(opts) {
3399
4208
  } : spec;
3400
4209
  rendered.set(filename, renderClaudeCode(renderSpec));
3401
4210
  } else {
3402
- const mdPath = path27.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
3403
- const yamlPath = path27.join(spec.skillsBaseDir, spec.sourceDir, "skill.yaml");
3404
- const mdContent = fs19.existsSync(mdPath) ? fs19.readFileSync(mdPath, "utf-8") : "";
3405
- const yamlContent = fs19.existsSync(yamlPath) ? fs19.readFileSync(yamlPath, "utf-8") : "";
4211
+ const mdPath = path34.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
4212
+ const yamlPath = path34.join(spec.skillsBaseDir, spec.sourceDir, "skill.yaml");
4213
+ const mdContent = fs22.existsSync(mdPath) ? fs22.readFileSync(mdPath, "utf-8") : "";
4214
+ const yamlContent = fs22.existsSync(yamlPath) ? fs22.readFileSync(yamlPath, "utf-8") : "";
3406
4215
  rendered.set(filename, renderGemini(spec, mdContent, yamlContent));
3407
4216
  }
3408
4217
  }
@@ -3428,16 +4237,16 @@ async function handleOrphanDeletion(results, opts) {
3428
4237
  const shouldDelete = opts.yes || await confirmDeletion(result.removed);
3429
4238
  if (shouldDelete) {
3430
4239
  for (const filename of result.removed) {
3431
- const filePath = path27.join(result.outputDir, filename);
3432
- if (fs19.existsSync(filePath)) {
3433
- fs19.unlinkSync(filePath);
4240
+ const filePath = path34.join(result.outputDir, filename);
4241
+ if (fs22.existsSync(filePath)) {
4242
+ fs22.unlinkSync(filePath);
3434
4243
  }
3435
4244
  }
3436
4245
  }
3437
4246
  }
3438
4247
  }
3439
4248
  function createGenerateSlashCommandsCommand() {
3440
- return new Command28("generate-slash-commands").description(
4249
+ return new Command32("generate-slash-commands").description(
3441
4250
  "Generate native slash commands for Claude Code and Gemini CLI from skill metadata"
3442
4251
  ).option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global config directories", false).option("--include-global", "Include built-in global skills alongside project skills", false).option("--output <dir>", "Custom output directory").option("--skills-dir <path>", "Skills directory to scan").option("--dry-run", "Show what would change without writing", false).option("--yes", "Skip deletion confirmation prompts", false).action(async (opts, cmd) => {
3443
4252
  const globalOpts = cmd.optsWithGlobals();
@@ -3502,11 +4311,10 @@ ${result.platform} \u2192 ${result.outputDir}`);
3502
4311
  }
3503
4312
 
3504
4313
  // src/commands/ci/index.ts
3505
- import { Command as Command31 } from "commander";
4314
+ import { Command as Command35 } from "commander";
3506
4315
 
3507
4316
  // src/commands/ci/check.ts
3508
- import { Command as Command29 } from "commander";
3509
- import { runCIChecks } from "@harness-engineering/core";
4317
+ import { Command as Command33 } from "commander";
3510
4318
  var VALID_CHECKS = ["validate", "deps", "docs", "entropy", "phase-gate"];
3511
4319
  async function runCICheck(options) {
3512
4320
  const configResult = resolveConfig(options.configPath);
@@ -3537,7 +4345,7 @@ function parseFailOn(failOn) {
3537
4345
  return "error";
3538
4346
  }
3539
4347
  function createCheckCommand() {
3540
- return new Command29("check").description("Run all harness checks for CI (validate, deps, docs, entropy, phase-gate)").option("--skip <checks>", "Comma-separated checks to skip (e.g., entropy,docs)").option("--fail-on <severity>", "Fail on severity level: error (default) or warning", "error").action(async (opts, cmd) => {
4348
+ return new Command33("check").description("Run all harness checks for CI (validate, deps, docs, entropy, phase-gate)").option("--skip <checks>", "Comma-separated checks to skip (e.g., entropy,docs)").option("--fail-on <severity>", "Fail on severity level: error (default) or warning", "error").action(async (opts, cmd) => {
3541
4349
  const globalOpts = cmd.optsWithGlobals();
3542
4350
  const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
3543
4351
  const skip = parseSkip(opts.skip);
@@ -3581,10 +4389,9 @@ function createCheckCommand() {
3581
4389
  }
3582
4390
 
3583
4391
  // src/commands/ci/init.ts
3584
- import { Command as Command30 } from "commander";
3585
- import * as fs20 from "fs";
3586
- import * as path28 from "path";
3587
- import { Ok as Ok17, Err as Err14 } from "@harness-engineering/core";
4392
+ import { Command as Command34 } from "commander";
4393
+ import * as fs23 from "fs";
4394
+ import * as path35 from "path";
3588
4395
  var ALL_CHECKS = ["validate", "deps", "docs", "entropy", "phase-gate"];
3589
4396
  function buildSkipFlag(checks) {
3590
4397
  if (!checks) return "";
@@ -3668,20 +4475,20 @@ function generateCIConfig(options) {
3668
4475
  };
3669
4476
  const entry = generators[platform];
3670
4477
  if (!entry) {
3671
- return Err14(new CLIError(`Unknown platform: ${platform}`, ExitCode.ERROR));
4478
+ return Err(new CLIError(`Unknown platform: ${platform}`, ExitCode.ERROR));
3672
4479
  }
3673
- return Ok17({
4480
+ return Ok({
3674
4481
  filename: entry.filename,
3675
4482
  content: entry.generate(skipFlag)
3676
4483
  });
3677
4484
  }
3678
4485
  function detectPlatform() {
3679
- if (fs20.existsSync(".github")) return "github";
3680
- if (fs20.existsSync(".gitlab-ci.yml")) return "gitlab";
4486
+ if (fs23.existsSync(".github")) return "github";
4487
+ if (fs23.existsSync(".gitlab-ci.yml")) return "gitlab";
3681
4488
  return null;
3682
4489
  }
3683
4490
  function createInitCommand2() {
3684
- return new Command30("init").description("Generate CI configuration for harness checks").option("--platform <platform>", "CI platform: github, gitlab, or generic").option("--checks <list>", "Comma-separated list of checks to include").action(async (opts, cmd) => {
4491
+ return new Command34("init").description("Generate CI configuration for harness checks").option("--platform <platform>", "CI platform: github, gitlab, or generic").option("--checks <list>", "Comma-separated list of checks to include").action(async (opts, cmd) => {
3685
4492
  const globalOpts = cmd.optsWithGlobals();
3686
4493
  const platform = opts.platform ?? detectPlatform() ?? "generic";
3687
4494
  const checks = opts.checks ? opts.checks.split(",").map((s) => s.trim()) : void 0;
@@ -3693,12 +4500,12 @@ function createInitCommand2() {
3693
4500
  process.exit(result.error.exitCode);
3694
4501
  }
3695
4502
  const { filename, content } = result.value;
3696
- const targetPath = path28.resolve(filename);
3697
- const dir = path28.dirname(targetPath);
3698
- fs20.mkdirSync(dir, { recursive: true });
3699
- fs20.writeFileSync(targetPath, content);
4503
+ const targetPath = path35.resolve(filename);
4504
+ const dir = path35.dirname(targetPath);
4505
+ fs23.mkdirSync(dir, { recursive: true });
4506
+ fs23.writeFileSync(targetPath, content);
3700
4507
  if (platform === "generic") {
3701
- fs20.chmodSync(targetPath, "755");
4508
+ fs23.chmodSync(targetPath, "755");
3702
4509
  }
3703
4510
  if (globalOpts.json) {
3704
4511
  console.log(JSON.stringify({ file: filename, platform }));
@@ -3711,15 +4518,15 @@ function createInitCommand2() {
3711
4518
 
3712
4519
  // src/commands/ci/index.ts
3713
4520
  function createCICommand() {
3714
- const command = new Command31("ci").description("CI/CD integration commands");
4521
+ const command = new Command35("ci").description("CI/CD integration commands");
3715
4522
  command.addCommand(createCheckCommand());
3716
4523
  command.addCommand(createInitCommand2());
3717
4524
  return command;
3718
4525
  }
3719
4526
 
3720
4527
  // src/commands/update.ts
3721
- import { Command as Command32 } from "commander";
3722
- import { execSync as execSync3 } from "child_process";
4528
+ import { Command as Command36 } from "commander";
4529
+ import { execSync as execSync4 } from "child_process";
3723
4530
  import { realpathSync } from "fs";
3724
4531
  import readline3 from "readline";
3725
4532
  import chalk4 from "chalk";
@@ -3739,7 +4546,7 @@ function detectPackageManager() {
3739
4546
  return "npm";
3740
4547
  }
3741
4548
  function getLatestVersion(pkg = "@harness-engineering/cli") {
3742
- const output = execSync3(`npm view ${pkg} dist-tags.latest`, {
4549
+ const output = execSync4(`npm view ${pkg} dist-tags.latest`, {
3743
4550
  encoding: "utf-8",
3744
4551
  timeout: 15e3
3745
4552
  });
@@ -3747,7 +4554,7 @@ function getLatestVersion(pkg = "@harness-engineering/cli") {
3747
4554
  }
3748
4555
  function getInstalledVersion(pm) {
3749
4556
  try {
3750
- const output = execSync3(`${pm} list -g @harness-engineering/cli --json`, {
4557
+ const output = execSync4(`${pm} list -g @harness-engineering/cli --json`, {
3751
4558
  encoding: "utf-8",
3752
4559
  timeout: 15e3
3753
4560
  });
@@ -3760,7 +4567,7 @@ function getInstalledVersion(pm) {
3760
4567
  }
3761
4568
  function getInstalledPackages(pm) {
3762
4569
  try {
3763
- const output = execSync3(`${pm} list -g --json`, {
4570
+ const output = execSync4(`${pm} list -g --json`, {
3764
4571
  encoding: "utf-8",
3765
4572
  timeout: 15e3
3766
4573
  });
@@ -3776,15 +4583,15 @@ function prompt(question) {
3776
4583
  input: process.stdin,
3777
4584
  output: process.stdout
3778
4585
  });
3779
- return new Promise((resolve18) => {
4586
+ return new Promise((resolve24) => {
3780
4587
  rl.question(question, (answer) => {
3781
4588
  rl.close();
3782
- resolve18(answer.trim().toLowerCase());
4589
+ resolve24(answer.trim().toLowerCase());
3783
4590
  });
3784
4591
  });
3785
4592
  }
3786
4593
  function createUpdateCommand() {
3787
- return new Command32("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").action(async (opts, cmd) => {
4594
+ return new Command36("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").action(async (opts, cmd) => {
3788
4595
  const globalOpts = cmd.optsWithGlobals();
3789
4596
  const pm = detectPackageManager();
3790
4597
  if (globalOpts.verbose) {
@@ -3827,7 +4634,7 @@ function createUpdateCommand() {
3827
4634
  }
3828
4635
  try {
3829
4636
  logger.info("Updating packages...");
3830
- execSync3(installCmd, { stdio: "inherit", timeout: 12e4 });
4637
+ execSync4(installCmd, { stdio: "inherit", timeout: 12e4 });
3831
4638
  console.log("");
3832
4639
  logger.success("Update complete");
3833
4640
  } catch {
@@ -3837,15 +4644,15 @@ function createUpdateCommand() {
3837
4644
  process.exit(ExitCode.ERROR);
3838
4645
  }
3839
4646
  console.log("");
3840
- const regenAnswer = await prompt("Regenerate slash commands? (y/N) ");
4647
+ const regenAnswer = await prompt("Regenerate slash commands and agent definitions? (y/N) ");
3841
4648
  if (regenAnswer === "y" || regenAnswer === "yes") {
3842
4649
  const scopeAnswer = await prompt("Generate for (g)lobal or (l)ocal project? (g/l) ");
3843
4650
  const globalFlag = scopeAnswer === "g" || scopeAnswer === "global" ? " --global" : "";
3844
4651
  try {
3845
- execSync3(`harness generate-slash-commands${globalFlag}`, { stdio: "inherit" });
4652
+ execSync4(`harness generate${globalFlag}`, { stdio: "inherit" });
3846
4653
  } catch {
3847
- logger.warn("Slash command generation failed. Run manually:");
3848
- console.log(` ${chalk4.cyan(`harness generate-slash-commands${globalFlag}`)}`);
4654
+ logger.warn("Generation failed. Run manually:");
4655
+ console.log(` ${chalk4.cyan(`harness generate${globalFlag}`)}`);
3849
4656
  }
3850
4657
  }
3851
4658
  process.exit(ExitCode.SUCCESS);
@@ -3853,9 +4660,9 @@ function createUpdateCommand() {
3853
4660
  }
3854
4661
 
3855
4662
  // src/commands/generate-agent-definitions.ts
3856
- import { Command as Command33 } from "commander";
3857
- import * as fs21 from "fs";
3858
- import * as path29 from "path";
4663
+ import { Command as Command37 } from "commander";
4664
+ import * as fs24 from "fs";
4665
+ import * as path36 from "path";
3859
4666
  import * as os3 from "os";
3860
4667
 
3861
4668
  // src/agent-definitions/generator.ts
@@ -3991,19 +4798,19 @@ function renderGeminiAgent(def) {
3991
4798
  // src/commands/generate-agent-definitions.ts
3992
4799
  function resolveOutputDir2(platform, opts) {
3993
4800
  if (opts.output) {
3994
- return platform === "claude-code" ? path29.join(opts.output, "claude-code") : path29.join(opts.output, "gemini-cli");
4801
+ return platform === "claude-code" ? path36.join(opts.output, "claude-code") : path36.join(opts.output, "gemini-cli");
3995
4802
  }
3996
4803
  if (opts.global) {
3997
4804
  const home = os3.homedir();
3998
- return platform === "claude-code" ? path29.join(home, ".claude", "agents") : path29.join(home, ".gemini", "agents");
4805
+ return platform === "claude-code" ? path36.join(home, ".claude", "agents") : path36.join(home, ".gemini", "agents");
3999
4806
  }
4000
- return platform === "claude-code" ? path29.join("agents", "agents", "claude-code") : path29.join("agents", "agents", "gemini-cli");
4807
+ return platform === "claude-code" ? path36.join("agents", "agents", "claude-code") : path36.join("agents", "agents", "gemini-cli");
4001
4808
  }
4002
4809
  function loadSkillContent(skillName) {
4003
4810
  const skillsDir = resolveSkillsDir();
4004
- const skillMdPath = path29.join(skillsDir, skillName, "SKILL.md");
4005
- if (!fs21.existsSync(skillMdPath)) return null;
4006
- return fs21.readFileSync(skillMdPath, "utf-8");
4811
+ const skillMdPath = path36.join(skillsDir, skillName, "SKILL.md");
4812
+ if (!fs24.existsSync(skillMdPath)) return null;
4813
+ return fs24.readFileSync(skillMdPath, "utf-8");
4007
4814
  }
4008
4815
  function getRenderer(platform) {
4009
4816
  return platform === "claude-code" ? renderClaudeCodeAgent : renderGeminiAgent;
@@ -4047,7 +4854,7 @@ function generateAgentDefinitions(opts) {
4047
4854
  return results;
4048
4855
  }
4049
4856
  function createGenerateAgentDefinitionsCommand() {
4050
- return new Command33("generate-agent-definitions").description("Generate agent definition files from personas for Claude Code and Gemini CLI").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global agent directories", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).action(async (opts, cmd) => {
4857
+ return new Command37("generate-agent-definitions").description("Generate agent definition files from personas for Claude Code and Gemini CLI").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global agent directories", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).action(async (opts, cmd) => {
4051
4858
  const globalOpts = cmd.optsWithGlobals();
4052
4859
  const platforms = opts.platforms.split(",").map((p) => p.trim());
4053
4860
  for (const p of platforms) {
@@ -4095,9 +4902,9 @@ ${result.platform} \u2192 ${result.outputDir}`);
4095
4902
  }
4096
4903
 
4097
4904
  // src/commands/generate.ts
4098
- import { Command as Command34 } from "commander";
4905
+ import { Command as Command38 } from "commander";
4099
4906
  function createGenerateCommand3() {
4100
- return new Command34("generate").description("Generate all platform integrations (slash commands + agent definitions)").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global directories", false).option("--include-global", "Include built-in global skills", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).option("--yes", "Skip deletion confirmation prompts", false).action(async (opts, cmd) => {
4907
+ return new Command38("generate").description("Generate all platform integrations (slash commands + agent definitions)").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global directories", false).option("--include-global", "Include built-in global skills", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).option("--yes", "Skip deletion confirmation prompts", false).action(async (opts, cmd) => {
4101
4908
  const globalOpts = cmd.optsWithGlobals();
4102
4909
  const platforms = opts.platforms.split(",").map((p) => p.trim());
4103
4910
  for (const p of platforms) {
@@ -4156,10 +4963,10 @@ function createGenerateCommand3() {
4156
4963
  }
4157
4964
 
4158
4965
  // src/commands/graph/scan.ts
4159
- import { Command as Command35 } from "commander";
4160
- import * as path30 from "path";
4966
+ import { Command as Command39 } from "commander";
4967
+ import * as path37 from "path";
4161
4968
  async function runScan(projectPath) {
4162
- const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("@harness-engineering/graph");
4969
+ const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-4MYPT3OE.js");
4163
4970
  const store = new GraphStore();
4164
4971
  const start = Date.now();
4165
4972
  await new CodeIngestor(store).ingest(projectPath);
@@ -4170,13 +4977,13 @@ async function runScan(projectPath) {
4170
4977
  await new GitIngestor(store).ingest(projectPath);
4171
4978
  } catch {
4172
4979
  }
4173
- const graphDir = path30.join(projectPath, ".harness", "graph");
4980
+ const graphDir = path37.join(projectPath, ".harness", "graph");
4174
4981
  await store.save(graphDir);
4175
4982
  return { nodeCount: store.nodeCount, edgeCount: store.edgeCount, durationMs: Date.now() - start };
4176
4983
  }
4177
4984
  function createScanCommand() {
4178
- return new Command35("scan").description("Scan project and build knowledge graph").argument("[path]", "Project root path", ".").action(async (inputPath, _opts, cmd) => {
4179
- const projectPath = path30.resolve(inputPath);
4985
+ return new Command39("scan").description("Scan project and build knowledge graph").argument("[path]", "Project root path", ".").action(async (inputPath, _opts, cmd) => {
4986
+ const projectPath = path37.resolve(inputPath);
4180
4987
  const globalOpts = cmd.optsWithGlobals();
4181
4988
  try {
4182
4989
  const result = await runScan(projectPath);
@@ -4195,13 +5002,13 @@ function createScanCommand() {
4195
5002
  }
4196
5003
 
4197
5004
  // src/commands/graph/ingest.ts
4198
- import { Command as Command36 } from "commander";
4199
- import * as path31 from "path";
5005
+ import { Command as Command40 } from "commander";
5006
+ import * as path38 from "path";
4200
5007
  async function loadConnectorConfig(projectPath, source) {
4201
5008
  try {
4202
- const fs22 = await import("fs/promises");
4203
- const configPath = path31.join(projectPath, "harness.config.json");
4204
- const config = JSON.parse(await fs22.readFile(configPath, "utf-8"));
5009
+ const fs25 = await import("fs/promises");
5010
+ const configPath = path38.join(projectPath, "harness.config.json");
5011
+ const config = JSON.parse(await fs25.readFile(configPath, "utf-8"));
4205
5012
  const connector = config.graph?.connectors?.find(
4206
5013
  (c) => c.source === source
4207
5014
  );
@@ -4240,8 +5047,8 @@ async function runIngest(projectPath, source, opts) {
4240
5047
  SyncManager,
4241
5048
  JiraConnector,
4242
5049
  SlackConnector
4243
- } = await import("@harness-engineering/graph");
4244
- const graphDir = path31.join(projectPath, ".harness", "graph");
5050
+ } = await import("./dist-4MYPT3OE.js");
5051
+ const graphDir = path38.join(projectPath, ".harness", "graph");
4245
5052
  const store = new GraphStore();
4246
5053
  await store.load(graphDir);
4247
5054
  if (opts?.all) {
@@ -4302,13 +5109,13 @@ async function runIngest(projectPath, source, opts) {
4302
5109
  return result;
4303
5110
  }
4304
5111
  function createIngestCommand() {
4305
- return new Command36("ingest").description("Ingest data into the knowledge graph").option("--source <name>", "Source to ingest (code, knowledge, git, jira, slack)").option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(async (opts, cmd) => {
5112
+ return new Command40("ingest").description("Ingest data into the knowledge graph").option("--source <name>", "Source to ingest (code, knowledge, git, jira, slack)").option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(async (opts, cmd) => {
4306
5113
  if (!opts.source && !opts.all) {
4307
5114
  console.error("Error: --source or --all is required");
4308
5115
  process.exit(1);
4309
5116
  }
4310
5117
  const globalOpts = cmd.optsWithGlobals();
4311
- const projectPath = path31.resolve(globalOpts.config ? path31.dirname(globalOpts.config) : ".");
5118
+ const projectPath = path38.resolve(globalOpts.config ? path38.dirname(globalOpts.config) : ".");
4312
5119
  try {
4313
5120
  const result = await runIngest(projectPath, opts.source ?? "", {
4314
5121
  full: opts.full,
@@ -4330,12 +5137,12 @@ function createIngestCommand() {
4330
5137
  }
4331
5138
 
4332
5139
  // src/commands/graph/query.ts
4333
- import { Command as Command37 } from "commander";
4334
- import * as path32 from "path";
5140
+ import { Command as Command41 } from "commander";
5141
+ import * as path39 from "path";
4335
5142
  async function runQuery(projectPath, rootNodeId, opts) {
4336
- const { GraphStore, ContextQL } = await import("@harness-engineering/graph");
5143
+ const { GraphStore, ContextQL } = await import("./dist-4MYPT3OE.js");
4337
5144
  const store = new GraphStore();
4338
- const graphDir = path32.join(projectPath, ".harness", "graph");
5145
+ const graphDir = path39.join(projectPath, ".harness", "graph");
4339
5146
  const loaded = await store.load(graphDir);
4340
5147
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
4341
5148
  const params = {
@@ -4349,9 +5156,9 @@ async function runQuery(projectPath, rootNodeId, opts) {
4349
5156
  return cql.execute(params);
4350
5157
  }
4351
5158
  function createQueryCommand() {
4352
- return new Command37("query").description("Query the knowledge graph").argument("<rootNodeId>", "Starting node ID").option("--depth <n>", "Max traversal depth", "3").option("--types <types>", "Comma-separated node types to include").option("--edges <edges>", "Comma-separated edge types to include").option("--bidirectional", "Traverse both directions").action(async (rootNodeId, opts, cmd) => {
5159
+ return new Command41("query").description("Query the knowledge graph").argument("<rootNodeId>", "Starting node ID").option("--depth <n>", "Max traversal depth", "3").option("--types <types>", "Comma-separated node types to include").option("--edges <edges>", "Comma-separated edge types to include").option("--bidirectional", "Traverse both directions").action(async (rootNodeId, opts, cmd) => {
4353
5160
  const globalOpts = cmd.optsWithGlobals();
4354
- const projectPath = path32.resolve(globalOpts.config ? path32.dirname(globalOpts.config) : ".");
5161
+ const projectPath = path39.resolve(globalOpts.config ? path39.dirname(globalOpts.config) : ".");
4355
5162
  try {
4356
5163
  const result = await runQuery(projectPath, rootNodeId, {
4357
5164
  depth: parseInt(opts.depth),
@@ -4377,21 +5184,21 @@ function createQueryCommand() {
4377
5184
  }
4378
5185
 
4379
5186
  // src/commands/graph/index.ts
4380
- import { Command as Command38 } from "commander";
5187
+ import { Command as Command42 } from "commander";
4381
5188
 
4382
5189
  // src/commands/graph/status.ts
4383
- import * as path33 from "path";
5190
+ import * as path40 from "path";
4384
5191
  async function runGraphStatus(projectPath) {
4385
- const { GraphStore } = await import("@harness-engineering/graph");
4386
- const graphDir = path33.join(projectPath, ".harness", "graph");
5192
+ const { GraphStore } = await import("./dist-4MYPT3OE.js");
5193
+ const graphDir = path40.join(projectPath, ".harness", "graph");
4387
5194
  const store = new GraphStore();
4388
5195
  const loaded = await store.load(graphDir);
4389
5196
  if (!loaded) return { status: "no_graph", message: "No graph found. Run `harness scan` first." };
4390
- const fs22 = await import("fs/promises");
4391
- const metaPath = path33.join(graphDir, "metadata.json");
5197
+ const fs25 = await import("fs/promises");
5198
+ const metaPath = path40.join(graphDir, "metadata.json");
4392
5199
  let lastScan = "unknown";
4393
5200
  try {
4394
- const meta = JSON.parse(await fs22.readFile(metaPath, "utf-8"));
5201
+ const meta = JSON.parse(await fs25.readFile(metaPath, "utf-8"));
4395
5202
  lastScan = meta.lastScanTimestamp;
4396
5203
  } catch {
4397
5204
  }
@@ -4402,8 +5209,8 @@ async function runGraphStatus(projectPath) {
4402
5209
  }
4403
5210
  let connectorSyncStatus = {};
4404
5211
  try {
4405
- const syncMetaPath = path33.join(graphDir, "sync-metadata.json");
4406
- const syncMeta = JSON.parse(await fs22.readFile(syncMetaPath, "utf-8"));
5212
+ const syncMetaPath = path40.join(graphDir, "sync-metadata.json");
5213
+ const syncMeta = JSON.parse(await fs25.readFile(syncMetaPath, "utf-8"));
4407
5214
  for (const [name, data] of Object.entries(syncMeta.connectors ?? {})) {
4408
5215
  connectorSyncStatus[name] = data.lastSyncTimestamp;
4409
5216
  }
@@ -4420,10 +5227,10 @@ async function runGraphStatus(projectPath) {
4420
5227
  }
4421
5228
 
4422
5229
  // src/commands/graph/export.ts
4423
- import * as path34 from "path";
5230
+ import * as path41 from "path";
4424
5231
  async function runGraphExport(projectPath, format) {
4425
- const { GraphStore } = await import("@harness-engineering/graph");
4426
- const graphDir = path34.join(projectPath, ".harness", "graph");
5232
+ const { GraphStore } = await import("./dist-4MYPT3OE.js");
5233
+ const graphDir = path41.join(projectPath, ".harness", "graph");
4427
5234
  const store = new GraphStore();
4428
5235
  const loaded = await store.load(graphDir);
4429
5236
  if (!loaded) throw new Error("No graph found. Run `harness scan` first.");
@@ -4452,13 +5259,13 @@ async function runGraphExport(projectPath, format) {
4452
5259
  }
4453
5260
 
4454
5261
  // src/commands/graph/index.ts
4455
- import * as path35 from "path";
5262
+ import * as path42 from "path";
4456
5263
  function createGraphCommand() {
4457
- const graph = new Command38("graph").description("Knowledge graph management");
5264
+ const graph = new Command42("graph").description("Knowledge graph management");
4458
5265
  graph.command("status").description("Show graph statistics").action(async (_opts, cmd) => {
4459
5266
  try {
4460
5267
  const globalOpts = cmd.optsWithGlobals();
4461
- const projectPath = path35.resolve(globalOpts.config ? path35.dirname(globalOpts.config) : ".");
5268
+ const projectPath = path42.resolve(globalOpts.config ? path42.dirname(globalOpts.config) : ".");
4462
5269
  const result = await runGraphStatus(projectPath);
4463
5270
  if (globalOpts.json) {
4464
5271
  console.log(JSON.stringify(result, null, 2));
@@ -4485,7 +5292,7 @@ function createGraphCommand() {
4485
5292
  });
4486
5293
  graph.command("export").description("Export graph").requiredOption("--format <format>", "Output format (json, mermaid)").action(async (opts, cmd) => {
4487
5294
  const globalOpts = cmd.optsWithGlobals();
4488
- const projectPath = path35.resolve(globalOpts.config ? path35.dirname(globalOpts.config) : ".");
5295
+ const projectPath = path42.resolve(globalOpts.config ? path42.dirname(globalOpts.config) : ".");
4489
5296
  try {
4490
5297
  const output = await runGraphExport(projectPath, opts.format);
4491
5298
  console.log(output);
@@ -4499,11 +5306,14 @@ function createGraphCommand() {
4499
5306
 
4500
5307
  // src/index.ts
4501
5308
  function createProgram() {
4502
- const program = new Command39();
5309
+ const program = new Command43();
4503
5310
  program.name("harness").description("CLI for Harness Engineering toolkit").version(VERSION).option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--verbose", "Verbose output").option("--quiet", "Minimal output");
4504
5311
  program.addCommand(createValidateCommand());
4505
5312
  program.addCommand(createCheckDepsCommand());
4506
5313
  program.addCommand(createCheckDocsCommand());
5314
+ program.addCommand(createCheckPerfCommand());
5315
+ program.addCommand(createCheckSecurityCommand());
5316
+ program.addCommand(createPerfCommand());
4507
5317
  program.addCommand(createInitCommand());
4508
5318
  program.addCommand(createCleanupCommand());
4509
5319
  program.addCommand(createFixDriftCommand());