@harness-engineering/cli 1.28.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/agents/skills/claude-code/harness-compound/SKILL.md +153 -0
  2. package/dist/agents/skills/claude-code/harness-compound/skill.yaml +60 -0
  3. package/dist/agents/skills/claude-code/harness-knowledge-pipeline/SKILL.md +12 -1
  4. package/dist/agents/skills/claude-code/harness-observability/SKILL.md +2 -0
  5. package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +138 -0
  6. package/dist/agents/skills/claude-code/harness-pulse/references/interview.md +77 -0
  7. package/dist/agents/skills/claude-code/harness-pulse/skill.yaml +61 -0
  8. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +25 -1
  9. package/dist/agents/skills/codex/harness-compound/SKILL.md +153 -0
  10. package/dist/agents/skills/codex/harness-compound/skill.yaml +60 -0
  11. package/dist/agents/skills/codex/harness-knowledge-pipeline/SKILL.md +12 -1
  12. package/dist/agents/skills/codex/harness-observability/SKILL.md +2 -0
  13. package/dist/agents/skills/codex/harness-pulse/SKILL.md +138 -0
  14. package/dist/agents/skills/codex/harness-pulse/references/interview.md +77 -0
  15. package/dist/agents/skills/codex/harness-pulse/skill.yaml +61 -0
  16. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +25 -1
  17. package/dist/agents/skills/cursor/harness-compound/SKILL.md +153 -0
  18. package/dist/agents/skills/cursor/harness-compound/skill.yaml +60 -0
  19. package/dist/agents/skills/cursor/harness-knowledge-pipeline/SKILL.md +12 -1
  20. package/dist/agents/skills/cursor/harness-observability/SKILL.md +2 -0
  21. package/dist/agents/skills/cursor/harness-pulse/SKILL.md +138 -0
  22. package/dist/agents/skills/cursor/harness-pulse/references/interview.md +77 -0
  23. package/dist/agents/skills/cursor/harness-pulse/skill.yaml +61 -0
  24. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +25 -1
  25. package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +153 -0
  26. package/dist/agents/skills/gemini-cli/harness-compound/skill.yaml +60 -0
  27. package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/SKILL.md +12 -1
  28. package/dist/agents/skills/gemini-cli/harness-observability/SKILL.md +2 -0
  29. package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +138 -0
  30. package/dist/agents/skills/gemini-cli/harness-pulse/references/interview.md +77 -0
  31. package/dist/agents/skills/gemini-cli/harness-pulse/skill.yaml +61 -0
  32. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +25 -1
  33. package/dist/agents/skills/package.json +1 -0
  34. package/dist/agents/skills/tests/fixtures/harness-compound/bug-track-fixture/input.json +10 -0
  35. package/dist/agents/skills/tests/fixtures/harness-compound/duplicate-detection-fixture/docs/solutions/bug-track/integration-issues/stalled-lease-cleanup.md +28 -0
  36. package/dist/agents/skills/tests/fixtures/harness-compound/duplicate-detection-fixture/expected.json +4 -0
  37. package/dist/agents/skills/tests/fixtures/harness-compound/duplicate-detection-fixture/input.json +10 -0
  38. package/dist/agents/skills/tests/fixtures/harness-compound/knowledge-track-fixture/input.json +10 -0
  39. package/dist/agents/skills/tests/harness-compound.test.ts +86 -0
  40. package/dist/{agents-md-6SAMHE7H.js → agents-md-XCAWON2D.js} +3 -3
  41. package/dist/{architecture-5YR52NSV.js → architecture-KERHEEQZ.js} +4 -4
  42. package/dist/{assess-project-5X7TYQFM.js → assess-project-NPYA3UVI.js} +1 -1
  43. package/dist/bin/harness-mcp.js +16 -15
  44. package/dist/bin/harness.js +26 -25
  45. package/dist/{check-phase-gate-PLV2VDOL.js → check-phase-gate-GE5ALEEU.js} +5 -4
  46. package/dist/{chunk-KJD4J54I.js → chunk-4FVHBBPY.js} +6 -1
  47. package/dist/{chunk-PFM3BVVU.js → chunk-AEFZJ543.js} +1 -1
  48. package/dist/{chunk-S2WB4LE7.js → chunk-BMM3GXV6.js} +384 -28
  49. package/dist/{chunk-RYDPFIJY.js → chunk-D5FE4L2O.js} +1 -1
  50. package/dist/{chunk-HT7HYYGT.js → chunk-DRD7LLFC.js} +1 -1
  51. package/dist/{chunk-2IBXUG6J.js → chunk-EFA4OEEN.js} +2 -2
  52. package/dist/{chunk-JZST2WZS.js → chunk-FBQYKH7R.js} +3 -3
  53. package/dist/{chunk-MTPHNOJW.js → chunk-FQAJAM54.js} +506 -242
  54. package/dist/{chunk-R2CBBZA6.js → chunk-GCYGGQFM.js} +1 -1
  55. package/dist/{chunk-7JQ7HLM4.js → chunk-GHPWBWUW.js} +8 -8
  56. package/dist/{chunk-6L2BU4BP.js → chunk-HBQ3BK2E.js} +1 -1
  57. package/dist/{chunk-ZYLBIDLE.js → chunk-IIX5OJES.js} +1 -1
  58. package/dist/{chunk-DXGI7DL3.js → chunk-KTWKW6KJ.js} +1 -1
  59. package/dist/{chunk-6GXSJGSW.js → chunk-LY2TY6NE.js} +3 -3
  60. package/dist/{chunk-JNKALGRM.js → chunk-M4C3ZIGL.js} +5 -5
  61. package/dist/{chunk-RFYF7TJS.js → chunk-MAFI6UWT.js} +1701 -769
  62. package/dist/{chunk-BYS3TQOO.js → chunk-OXFFN3FD.js} +1 -1
  63. package/dist/{chunk-XHOGGZS7.js → chunk-PCX4GPNT.js} +1 -1
  64. package/dist/{chunk-BFBZK6BC.js → chunk-RCHXBL2M.js} +6 -6
  65. package/dist/{chunk-74YADB7T.js → chunk-T7MNLCUD.js} +92 -92
  66. package/dist/{chunk-SITVRO7K.js → chunk-URLDPALI.js} +9 -9
  67. package/dist/{chunk-ELJ2MXMO.js → chunk-UWIOBHZL.js} +9 -9
  68. package/dist/{chunk-QDRBWVVY.js → chunk-WW6AUOA3.js} +2 -2
  69. package/dist/{chunk-5ME3WG3G.js → chunk-YBGVZQQE.js} +5 -5
  70. package/dist/{chunk-YJE23GRZ.js → chunk-YG4ZBGEH.js} +39 -5
  71. package/dist/chunk-ZCZD7FHU.js +16 -0
  72. package/dist/{ci-workflow-7T2XKB3P.js → ci-workflow-A2E2RTOP.js} +3 -3
  73. package/dist/{dist-42AYXCAK.js → dist-D27LJR2T.js} +7 -1
  74. package/dist/{dist-77VNTHWV.js → dist-K22DQUYY.js} +78 -2
  75. package/dist/{docs-MSIJ6SDO.js → docs-GXJOFVCF.js} +5 -4
  76. package/dist/{engine-F4P5RBE4.js → engine-JBUIA2XO.js} +3 -3
  77. package/dist/{entropy-GSUTIORR.js → entropy-Y7LUT4BZ.js} +3 -3
  78. package/dist/{feedback-NST6T4HI.js → feedback-BHOBVKI3.js} +1 -1
  79. package/dist/{generate-agent-definitions-BOUGQIPA.js → generate-agent-definitions-VL3ZVR32.js} +4 -4
  80. package/dist/glob-helper-FZPPTGJN.js +62 -0
  81. package/dist/{graph-loader-IAUPGLRV.js → graph-loader-5MKHAJJF.js} +1 -1
  82. package/dist/index.d.ts +44 -6
  83. package/dist/index.js +26 -25
  84. package/dist/{loader-6QTJC7IN.js → loader-WCKVMDYR.js} +3 -3
  85. package/dist/{mcp-QFBGTUX6.js → mcp-FA2CKHFY.js} +16 -15
  86. package/dist/{performance-B2NAAIE5.js → performance-NISUL5AA.js} +5 -4
  87. package/dist/{review-pipeline-6EYMBS6B.js → review-pipeline-CHE5LJ5D.js} +3 -3
  88. package/dist/{runtime-VFZK6BCZ.js → runtime-3SKKEVPF.js} +3 -3
  89. package/dist/{scan-DB6FNYGG.js → scan-BIJYHOE7.js} +2 -1
  90. package/dist/{security-HRNTYHPM.js → security-MF54MY3P.js} +1 -1
  91. package/dist/templates/orchestrator/harness.orchestrator.md +31 -8
  92. package/dist/{validate-YEMAFWJE.js → validate-SIWFNTXI.js} +4 -4
  93. package/dist/{validate-cross-check-DGHTJFVH.js → validate-cross-check-GBX7B7CQ.js} +3 -3
  94. package/package.json +8 -7
  95. package/dist/glob-helper-VCQXK5XY.js +0 -54
@@ -13,7 +13,7 @@ import {
13
13
  NODE_STABILITY,
14
14
  init_dist as init_dist2,
15
15
  queryTraceability
16
- } from "./chunk-S2WB4LE7.js";
16
+ } from "./chunk-BMM3GXV6.js";
17
17
  import {
18
18
  __esm,
19
19
  __export
@@ -69,17 +69,17 @@ function resolveFileToLayer(file, layers) {
69
69
  }
70
70
  return void 0;
71
71
  }
72
- async function fileExists(path37) {
72
+ async function fileExists(path42) {
73
73
  try {
74
- await accessAsync(path37, constants.F_OK);
74
+ await accessAsync(path42, constants.F_OK);
75
75
  return true;
76
76
  } catch {
77
77
  return false;
78
78
  }
79
79
  }
80
- async function readFileContent(path37) {
80
+ async function readFileContent(path42) {
81
81
  try {
82
- const content = await readFileAsync(path37, "utf-8");
82
+ const content = await readFileAsync(path42, "utf-8");
83
83
  return Ok(content);
84
84
  } catch (error) {
85
85
  return Err(error);
@@ -473,9 +473,9 @@ async function resolveWasmPath(grammarName) {
473
473
  const { createRequire } = await import("module");
474
474
  const require2 = createRequire(import.meta.url ?? __filename);
475
475
  const pkgPath = require2.resolve("tree-sitter-wasms/package.json");
476
- const path37 = await import("path");
477
- const pkgDir = path37.dirname(pkgPath);
478
- return path37.join(pkgDir, "out", `${grammarName}.wasm`);
476
+ const path42 = await import("path");
477
+ const pkgDir = path42.dirname(pkgPath);
478
+ return path42.join(pkgDir, "out", `${grammarName}.wasm`);
479
479
  }
480
480
  async function loadLanguage(lang) {
481
481
  const grammarName = GRAMMAR_MAP[lang];
@@ -1908,11 +1908,11 @@ var init_chunk_H73442AZ = __esm({
1908
1908
  TypeScriptParser = class {
1909
1909
  name = "typescript";
1910
1910
  extensions = [".ts", ".tsx", ".mts", ".cts"];
1911
- async parseFile(path37) {
1912
- const contentResult = await readFileContent(path37);
1911
+ async parseFile(path42) {
1912
+ const contentResult = await readFileContent(path42);
1913
1913
  if (!contentResult.ok) {
1914
1914
  return Err(
1915
- createParseError("NOT_FOUND", `File not found: ${path37}`, { path: path37 }, [
1915
+ createParseError("NOT_FOUND", `File not found: ${path42}`, { path: path42 }, [
1916
1916
  "Check that the file exists",
1917
1917
  "Verify the path is correct"
1918
1918
  ])
@@ -1922,7 +1922,7 @@ var init_chunk_H73442AZ = __esm({
1922
1922
  const ast = parse(contentResult.value, {
1923
1923
  loc: true,
1924
1924
  range: true,
1925
- jsx: path37.endsWith(".tsx"),
1925
+ jsx: path42.endsWith(".tsx"),
1926
1926
  errorOnUnknownASTType: false
1927
1927
  });
1928
1928
  return Ok({
@@ -1933,7 +1933,7 @@ var init_chunk_H73442AZ = __esm({
1933
1933
  } catch (e) {
1934
1934
  const error = e;
1935
1935
  return Err(
1936
- createParseError("SYNTAX_ERROR", `Failed to parse ${path37}: ${error.message}`, { path: path37 }, [
1936
+ createParseError("SYNTAX_ERROR", `Failed to parse ${path42}: ${error.message}`, { path: path42 }, [
1937
1937
  "Check for syntax errors in the file",
1938
1938
  "Ensure valid TypeScript syntax"
1939
1939
  ])
@@ -2248,11 +2248,11 @@ var init_chunk_H73442AZ = __esm({
2248
2248
  this.extensions = extensions;
2249
2249
  this.strategy = strategy;
2250
2250
  }
2251
- async parseFile(path37) {
2252
- const contentResult = await readFileContent(path37);
2251
+ async parseFile(path42) {
2252
+ const contentResult = await readFileContent(path42);
2253
2253
  if (!contentResult.ok) {
2254
2254
  return Err(
2255
- createParseError("NOT_FOUND", `File not found: ${path37}`, { path: path37 }, [
2255
+ createParseError("NOT_FOUND", `File not found: ${path42}`, { path: path42 }, [
2256
2256
  "Check that the file exists"
2257
2257
  ])
2258
2258
  );
@@ -2268,7 +2268,7 @@ var init_chunk_H73442AZ = __esm({
2268
2268
  } catch (e) {
2269
2269
  const error = e;
2270
2270
  return Err(
2271
- createParseError("SYNTAX_ERROR", `Failed to parse ${path37}: ${error.message}`, { path: path37 }, [
2271
+ createParseError("SYNTAX_ERROR", `Failed to parse ${path42}: ${error.message}`, { path: path42 }, [
2272
2272
  "Check for syntax errors in the file"
2273
2273
  ])
2274
2274
  );
@@ -2784,6 +2784,8 @@ var dist_exports = {};
2784
2784
  __export(dist_exports, {
2785
2785
  AGENT_DESCRIPTORS: () => AGENT_DESCRIPTORS,
2786
2786
  AGREEMENT_LINE_GAP: () => AGREEMENT_LINE_GAP,
2787
+ ALLOWED_FIELD_KEYS: () => ALLOWED_FIELD_KEYS,
2788
+ ALL_SOLUTION_CATEGORIES: () => ALL_SOLUTION_CATEGORIES,
2787
2789
  ARCHITECTURE_DESCRIPTOR: () => ARCHITECTURE_DESCRIPTOR,
2788
2790
  AdjustedForecastSchema: () => AdjustedForecastSchema,
2789
2791
  AgentActionEmitter: () => AgentActionEmitter,
@@ -2794,6 +2796,7 @@ __export(dist_exports, {
2794
2796
  ArchDiffResultSchema: () => ArchDiffResultSchema,
2795
2797
  ArchMetricCategorySchema: () => ArchMetricCategorySchema,
2796
2798
  BUG_DETECTION_DESCRIPTOR: () => BUG_DETECTION_DESCRIPTOR,
2799
+ BUG_TRACK_CATEGORIES: () => BUG_TRACK_CATEGORIES,
2797
2800
  BaselineManager: () => BaselineManager,
2798
2801
  BenchmarkRunner: () => BenchmarkRunner,
2799
2802
  BlueprintGenerator: () => BlueprintGenerator,
@@ -2811,6 +2814,7 @@ __export(dist_exports, {
2811
2814
  CircularDepsCollector: () => CircularDepsCollector,
2812
2815
  CompactionPipeline: () => CompactionPipeline,
2813
2816
  ComplexityCollector: () => ComplexityCollector,
2817
+ CompoundLockHeldError: () => CompoundLockHeldError,
2814
2818
  ConfidenceTierSchema: () => ConfidenceTierSchema,
2815
2819
  ConfirmationSchema: () => ConfirmationSchema,
2816
2820
  ConsoleSink: () => ConsoleSink,
@@ -2854,10 +2858,12 @@ __export(dist_exports, {
2854
2858
  HandoffSchema: () => HandoffSchema,
2855
2859
  HarnessStateSchema: () => HarnessStateSchema,
2856
2860
  InteractionTypeSchema: () => InteractionTypeSchema,
2861
+ KNOWLEDGE_TRACK_CATEGORIES: () => KNOWLEDGE_TRACK_CATEGORIES,
2857
2862
  LITELLM_PRICING_URL: () => LITELLM_PRICING_URL,
2858
2863
  LayerViolationCollector: () => LayerViolationCollector,
2859
2864
  LockfilePackageSchema: () => LockfilePackageSchema,
2860
2865
  LockfileSchema: () => LockfileSchema,
2866
+ MOCK_ADAPTER_NAME: () => MOCK_ADAPTER_NAME,
2861
2867
  ManifestSchema: () => ManifestSchema,
2862
2868
  MetricResultSchema: () => MetricResultSchema,
2863
2869
  ModuleSizeCollector: () => ModuleSizeCollector,
@@ -2866,6 +2872,9 @@ __export(dist_exports, {
2866
2872
  NoOpTelemetryAdapter: () => NoOpTelemetryAdapter,
2867
2873
  Ok: () => Ok,
2868
2874
  OpenAICacheAdapter: () => OpenAICacheAdapter,
2875
+ PII_FIELD_DENYLIST: () => PII_FIELD_DENYLIST,
2876
+ PII_LINE_RE: () => PII_LINE_RE,
2877
+ PII_TOKENS: () => PII_TOKENS,
2869
2878
  PatternConfigSchema: () => PatternConfigSchema,
2870
2879
  PredictionEngine: () => PredictionEngine,
2871
2880
  PredictionOptionsSchema: () => PredictionOptionsSchema,
@@ -2873,6 +2882,10 @@ __export(dist_exports, {
2873
2882
  PredictionResultSchema: () => PredictionResultSchema,
2874
2883
  PredictionWarningSchema: () => PredictionWarningSchema,
2875
2884
  ProjectScanner: () => ProjectScanner,
2885
+ PulseAdapterAlreadyRegisteredError: () => PulseAdapterAlreadyRegisteredError,
2886
+ PulseConfigSchema: () => PulseConfigSchema,
2887
+ PulseDbSourceSchema: () => PulseDbSourceSchema,
2888
+ PulseSourcesSchema: () => PulseSourcesSchema,
2876
2889
  QuestionSchema: () => QuestionSchema,
2877
2890
  REQUIRED_SECTIONS: () => REQUIRED_SECTIONS,
2878
2891
  RegressionDetector: () => RegressionDetector,
@@ -2897,6 +2910,7 @@ __export(dist_exports, {
2897
2910
  SharableLayerSchema: () => SharableLayerSchema,
2898
2911
  SharableSecurityRulesSchema: () => SharableSecurityRulesSchema,
2899
2912
  SkillEventSchema: () => SkillEventSchema,
2913
+ SolutionDocFrontmatterSchema: () => SolutionDocFrontmatterSchema,
2900
2914
  SpecImpactEstimateSchema: () => SpecImpactEstimateSchema,
2901
2915
  SpecImpactEstimator: () => SpecImpactEstimator,
2902
2916
  SpecImpactSignalsSchema: () => SpecImpactSignalsSchema,
@@ -2924,6 +2938,7 @@ __export(dist_exports, {
2924
2938
  ViolationHistorySchema: () => ViolationHistorySchema,
2925
2939
  ViolationSchema: () => ViolationSchema,
2926
2940
  ViolationSnapshotSchema: () => ViolationSnapshotSchema,
2941
+ acquireCompoundLock: () => acquireCompoundLock,
2927
2942
  addProvenance: () => addProvenance,
2928
2943
  agentConfigRules: () => agentConfigRules,
2929
2944
  aggregateAdoptionByDay: () => aggregateByDay2,
@@ -2946,6 +2961,9 @@ __export(dist_exports, {
2946
2961
  archiveLearnings: () => archiveLearnings,
2947
2962
  archiveSession: () => archiveSession,
2948
2963
  archiveStream: () => archiveStream,
2964
+ assembleCandidateReport: () => assembleCandidateReport,
2965
+ assembleReport: () => assembleReport,
2966
+ assertSanitized: () => assertSanitized,
2949
2967
  assignFeature: () => assignFeature,
2950
2968
  buildDependencyGraph: () => buildDependencyGraph,
2951
2969
  buildExclusionSet: () => buildExclusionSet,
@@ -2962,15 +2980,18 @@ __export(dist_exports, {
2962
2980
  clearEventHashCache: () => clearEventHashCache,
2963
2981
  clearFailuresCache: () => clearFailuresCache,
2964
2982
  clearLearningsCache: () => clearLearningsCache,
2983
+ clearPulseAdapters: () => clearPulseAdapters,
2965
2984
  clearTaint: () => clearTaint,
2966
2985
  clusterViolations: () => clusterViolations,
2967
2986
  collectEvents: () => collectEvents,
2968
2987
  computeContentHash: () => computeContentHash,
2988
+ computeHotspots: () => computeHotspots,
2969
2989
  computeLexicalSimilarity: () => computeLexicalSimilarity,
2970
2990
  computeLoadPlan: () => computeLoadPlan,
2971
2991
  computeOverallSeverity: () => computeOverallSeverity,
2972
2992
  computeScanExitCode: () => computeScanExitCode,
2973
2993
  computeTrustScores: () => computeTrustScores,
2994
+ computeWindow: () => computeWindow,
2974
2995
  configureFeedback: () => configureFeedback,
2975
2996
  constraintRuleId: () => constraintRuleId,
2976
2997
  contextBudget: () => contextBudget,
@@ -2986,6 +3007,7 @@ __export(dist_exports, {
2986
3007
  createRegionMap: () => createRegionMap,
2987
3008
  createSelfReview: () => createSelfReview,
2988
3009
  createStream: () => createStream,
3010
+ crossReferenceUndocumentedFixes: () => crossReferenceUndocumentedFixes,
2989
3011
  cryptoRules: () => cryptoRules,
2990
3012
  deduplicateCleanupFindings: () => deduplicateCleanupFindings,
2991
3013
  deduplicateFindings: () => deduplicateFindings,
@@ -3016,6 +3038,7 @@ __export(dist_exports, {
3016
3038
  extractBundle: () => extractBundle,
3017
3039
  extractDirectoryScope: () => extractDirectoryScope,
3018
3040
  extractFileReferences: () => extractFileReferences,
3041
+ extractHeadlines: () => extractHeadlines,
3019
3042
  extractIndexEntry: () => extractIndexEntry,
3020
3043
  extractLevel: () => extractLevel,
3021
3044
  extractMarkdownLinks: () => extractMarkdownLinks,
@@ -3027,6 +3050,7 @@ __export(dist_exports, {
3027
3050
  formatFindingBlock: () => formatFindingBlock,
3028
3051
  formatGitHubComment: () => formatGitHubComment,
3029
3052
  formatGitHubSummary: () => formatGitHubSummary,
3053
+ formatIsoWeek: () => formatIsoWeek,
3030
3054
  formatOutline: () => formatOutline,
3031
3055
  formatTerminalOutput: () => formatTerminalOutput,
3032
3056
  fullSync: () => fullSync,
@@ -3042,10 +3066,12 @@ __export(dist_exports, {
3042
3066
  getOutline: () => getOutline,
3043
3067
  getParser: () => getParser,
3044
3068
  getPhaseCategories: () => getPhaseCategories,
3069
+ getPulseAdapter: () => getPulseAdapter,
3045
3070
  getStreamForBranch: () => getStreamForBranch,
3046
3071
  getTaintFilePath: () => getTaintFilePath,
3047
3072
  getTrustLevel: () => getTrustLevel,
3048
3073
  getUpdateNotification: () => getUpdateNotification,
3074
+ gitScan: () => gitScan,
3049
3075
  goRules: () => goRules,
3050
3076
  injectionRules: () => injectionRules,
3051
3077
  insecureDefaultsRules: () => insecureDefaultsRules,
@@ -3053,9 +3079,12 @@ __export(dist_exports, {
3053
3079
  isErr: () => isErr,
3054
3080
  isOk: () => isOk,
3055
3081
  isRegression: () => isRegression,
3082
+ isSanitizedResult: () => isSanitizedResult,
3056
3083
  isSmallSuggestion: () => isSmallSuggestion,
3057
3084
  isUpdateCheckEnabled: () => isUpdateCheckEnabled,
3085
+ isoWeek: () => isoWeek,
3058
3086
  listActiveSessions: () => listActiveSessions,
3087
+ listPulseAdapters: () => listPulseAdapters,
3059
3088
  listStreams: () => listStreams,
3060
3089
  listTaintedSessions: () => listTaintedSessions,
3061
3090
  loadBudgetedLearnings: () => loadBudgetedLearnings,
@@ -3089,6 +3118,7 @@ __export(dist_exports, {
3089
3118
  parseFrontmatter: () => parseFrontmatter2,
3090
3119
  parseHarnessIgnore: () => parseHarnessIgnore,
3091
3120
  parseLiteLLMData: () => parseLiteLLMData,
3121
+ parseLookback: () => parseLookback,
3092
3122
  parseManifest: () => parseManifest,
3093
3123
  parseProtectedRegions: () => parseProtectedRegions,
3094
3124
  parseRoadmap: () => parseRoadmap,
@@ -3109,6 +3139,8 @@ __export(dist_exports, {
3109
3139
  readSessionSection: () => readSessionSection,
3110
3140
  readSessionSections: () => readSessionSections,
3111
3141
  readTaint: () => readTaint,
3142
+ registerMockAdapter: () => registerMockAdapter,
3143
+ registerPulseAdapter: () => registerPulseAdapter,
3112
3144
  removeContributions: () => removeContributions,
3113
3145
  removeProvenance: () => removeProvenance,
3114
3146
  requestMultiplePeerReviews: () => requestMultiplePeerReviews,
@@ -3134,6 +3166,7 @@ __export(dist_exports, {
3134
3166
  runMechanicalGate: () => runMechanicalGate,
3135
3167
  runMultiTurnPipeline: () => runMultiTurnPipeline,
3136
3168
  runPipeline: () => runPipeline,
3169
+ runPulse: () => runPulse,
3137
3170
  runReviewPipeline: () => runReviewPipeline,
3138
3171
  runSecurityAgent: () => runSecurityAgent,
3139
3172
  saveHandoff: () => saveHandoff,
@@ -3145,6 +3178,7 @@ __export(dist_exports, {
3145
3178
  searchSymbols: () => searchSymbols,
3146
3179
  secretRules: () => secretRules,
3147
3180
  securityFindingId: () => securityFindingId,
3181
+ seedFromStrategy: () => seedFromStrategy,
3148
3182
  send: () => send,
3149
3183
  serializeEnvelope: () => serializeEnvelope,
3150
3184
  serializeRoadmap: () => serializeRoadmap,
@@ -3154,6 +3188,7 @@ __export(dist_exports, {
3154
3188
  spawnBackgroundCheck: () => spawnBackgroundCheck,
3155
3189
  splitBundlesByStage: () => splitBundlesByStage,
3156
3190
  stageDomains: () => stageDomains,
3191
+ suggestCategory: () => suggestCategory,
3157
3192
  syncConstraintNodes: () => syncConstraintNodes,
3158
3193
  syncFromExternal: () => syncFromExternal,
3159
3194
  syncRoadmap: () => syncRoadmap,
@@ -3176,164 +3211,188 @@ __export(dist_exports, {
3176
3211
  validateFindings: () => validateFindings,
3177
3212
  validateKnowledgeMap: () => validateKnowledgeMap,
3178
3213
  validatePatternConfig: () => validatePatternConfig,
3214
+ validatePulseConfig: () => validatePulseConfig,
3215
+ validateSolutionsDir: () => validateSolutionsDir,
3179
3216
  violationId: () => violationId,
3180
3217
  weeksUntilThreshold: () => weeksUntilThreshold,
3181
3218
  weightedLinearRegression: () => weightedLinearRegression,
3182
3219
  writeConfig: () => writeConfig,
3183
3220
  writeLockfile: () => writeLockfile,
3221
+ writePulseConfig: () => writePulseConfig,
3184
3222
  writeSessionSummary: () => writeSessionSummary,
3185
3223
  writeTaint: () => writeTaint,
3186
3224
  xssRules: () => xssRules
3187
3225
  });
3226
+ import * as fs from "fs/promises";
3227
+ import * as path from "path";
3228
+ import { z as z2 } from "zod";
3229
+ import * as fs2 from "fs/promises";
3230
+ import * as path2 from "path";
3231
+ import matter from "gray-matter";
3232
+ import { z as z22 } from "zod";
3188
3233
  import { spawn } from "child_process";
3189
3234
  import { existsSync as existsSync2 } from "fs";
3190
- import { join as join4, isAbsolute } from "path";
3235
+ import { join as join32, isAbsolute } from "path";
3191
3236
  import { existsSync as existsSync22 } from "fs";
3192
- import { join as join22 } from "path";
3237
+ import { join as join42 } from "path";
3193
3238
  import { readFileSync as readFileSync2, statSync } from "fs";
3194
3239
  import { glob as glob2 } from "glob";
3195
3240
  import { existsSync as existsSync3 } from "fs";
3196
- import { isAbsolute as isAbsolute2, resolve as resolve3, join as join32 } from "path";
3241
+ import { isAbsolute as isAbsolute2, resolve as resolve3, join as join52 } from "path";
3197
3242
  import { glob as glob22 } from "glob";
3198
3243
  import { existsSync as existsSync4 } from "fs";
3199
- import { basename, dirname as dirname4, join as join42 } from "path";
3244
+ import { basename, dirname as dirname4, join as join6 } from "path";
3200
3245
  import { existsSync as existsSync5 } from "fs";
3201
- import { join as join5 } from "path";
3202
- import { existsSync as existsSync6 } from "fs";
3203
3246
  import { join as join7 } from "path";
3204
- import { join as join6, dirname as dirname22 } from "path";
3247
+ import { existsSync as existsSync6 } from "fs";
3248
+ import { join as join9 } from "path";
3249
+ import { join as join8, dirname as dirname22 } from "path";
3205
3250
  import { glob as glob3 } from "glob";
3206
3251
  import { existsSync as existsSync7 } from "fs";
3207
3252
  import { dirname as dirname32, resolve as resolve22, isAbsolute as isAbsolute3 } from "path";
3208
3253
  import { existsSync as existsSync8 } from "fs";
3209
- import { join as join8 } from "path";
3254
+ import { join as join10 } from "path";
3210
3255
  import { glob as glob4 } from "glob";
3211
3256
  import { existsSync as existsSync9 } from "fs";
3212
- import { join as join9 } from "path";
3257
+ import { join as join11 } from "path";
3213
3258
  import { existsSync as existsSync10 } from "fs";
3214
- import { join as join10 } from "path";
3259
+ import { join as join12 } from "path";
3215
3260
  import { minimatch as minimatch2 } from "minimatch";
3216
3261
  import { basename as basename2 } from "path";
3217
- import { join as join11, basename as basename3 } from "path";
3262
+ import { join as join13, basename as basename3 } from "path";
3218
3263
  import { basename as basename4, dirname as dirname42 } from "path";
3219
- import { z as z2 } from "zod";
3220
- import * as fs from "fs/promises";
3221
- import * as fs2 from "fs/promises";
3222
- import { join as join12, resolve as resolve32 } from "path";
3264
+ import { z as z3 } from "zod";
3265
+ import * as fs3 from "fs/promises";
3266
+ import * as fs4 from "fs/promises";
3267
+ import { join as join14, resolve as resolve32 } from "path";
3223
3268
  import { minimatch as minimatch22 } from "minimatch";
3224
3269
  import { dirname as dirname5, resolve as resolve4 } from "path";
3225
3270
  import { dirname as dirname6, resolve as resolve5 } from "path";
3226
3271
  import { minimatch as minimatch3 } from "minimatch";
3227
3272
  import { readdirSync, statSync as statSync2 } from "fs";
3228
- import { join as join13 } from "path";
3229
- import * as fs3 from "fs";
3273
+ import { join as join15 } from "path";
3274
+ import * as fs5 from "fs";
3230
3275
  import { promisify as promisify2 } from "util";
3231
- import { dirname as dirname7, basename as basename5, join as join14 } from "path";
3232
- import { z as z22 } from "zod";
3276
+ import { dirname as dirname7, basename as basename5, join as join16 } from "path";
3277
+ import { z as z4 } from "zod";
3233
3278
  import { readFileSync as readFileSync22, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync11 } from "fs";
3234
- import { join as join15, dirname as dirname8 } from "path";
3279
+ import { join as join17, dirname as dirname8 } from "path";
3235
3280
  import { execFileSync } from "child_process";
3236
- import * as fs4 from "fs";
3237
- import * as path from "path";
3281
+ import * as fs6 from "fs";
3282
+ import * as path3 from "path";
3238
3283
  import { appendFileSync, writeFileSync as writeFileSync22, existsSync as existsSync12, mkdirSync as mkdirSync22 } from "fs";
3239
3284
  import { dirname as dirname9 } from "path";
3240
- import { z as z3 } from "zod";
3285
+ import { z as z5 } from "zod";
3241
3286
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync2, mkdirSync as mkdirSync3, existsSync as existsSync13 } from "fs";
3242
3287
  import { randomBytes as randomBytes2 } from "crypto";
3243
- import { join as join17, dirname as dirname10 } from "path";
3244
- import { z as z4 } from "zod";
3245
- import * as fs5 from "fs";
3246
- import * as path2 from "path";
3247
- import * as fs6 from "fs";
3248
- import * as path3 from "path";
3288
+ import { join as join19, dirname as dirname10 } from "path";
3289
+ import { z as z6 } from "zod";
3249
3290
  import * as fs7 from "fs";
3250
3291
  import * as path4 from "path";
3251
- import { z as z5 } from "zod";
3252
- import * as fs11 from "fs";
3253
- import * as path8 from "path";
3254
- import * as fs10 from "fs";
3255
- import * as path7 from "path";
3256
3292
  import * as fs8 from "fs";
3257
3293
  import * as path5 from "path";
3258
- import { execSync } from "child_process";
3259
- import { z as z6 } from "zod";
3260
3294
  import * as fs9 from "fs";
3261
3295
  import * as path6 from "path";
3262
- import * as fs12 from "fs";
3263
- import * as path9 from "path";
3264
- import * as crypto2 from "crypto";
3296
+ import { z as z7 } from "zod";
3265
3297
  import * as fs13 from "fs";
3266
3298
  import * as path10 from "path";
3299
+ import * as fs12 from "fs";
3300
+ import * as path9 from "path";
3301
+ import * as fs10 from "fs";
3302
+ import * as path7 from "path";
3303
+ import { execSync } from "child_process";
3304
+ import { z as z8 } from "zod";
3305
+ import * as fs11 from "fs";
3306
+ import * as path8 from "path";
3267
3307
  import * as fs14 from "fs";
3268
3308
  import * as path11 from "path";
3269
- import * as crypto3 from "crypto";
3309
+ import * as crypto2 from "crypto";
3270
3310
  import * as fs15 from "fs";
3271
3311
  import * as path12 from "path";
3272
3312
  import * as fs16 from "fs";
3273
3313
  import * as path13 from "path";
3314
+ import * as crypto3 from "crypto";
3274
3315
  import * as fs17 from "fs";
3275
3316
  import * as path14 from "path";
3276
3317
  import * as fs18 from "fs";
3277
3318
  import * as path15 from "path";
3278
3319
  import * as fs19 from "fs";
3279
3320
  import * as path16 from "path";
3280
- import { execSync as execSync2 } from "child_process";
3281
3321
  import * as fs20 from "fs";
3282
3322
  import * as path17 from "path";
3283
3323
  import * as fs21 from "fs";
3284
3324
  import * as path18 from "path";
3325
+ import { execSync as execSync2 } from "child_process";
3285
3326
  import * as fs22 from "fs";
3286
3327
  import * as path19 from "path";
3287
3328
  import * as fs23 from "fs";
3288
3329
  import * as path20 from "path";
3289
- import { z as z7 } from "zod";
3290
- import * as fs25 from "fs/promises";
3291
- import { minimatch as minimatch4 } from "minimatch";
3292
- import { z as z8 } from "zod";
3293
3330
  import * as fs24 from "fs";
3294
3331
  import * as path21 from "path";
3332
+ import * as fs25 from "fs";
3333
+ import * as path22 from "path";
3334
+ import { z as z9 } from "zod";
3335
+ import * as fs27 from "fs/promises";
3336
+ import { minimatch as minimatch4 } from "minimatch";
3337
+ import { z as z10 } from "zod";
3338
+ import * as fs26 from "fs";
3339
+ import * as path23 from "path";
3295
3340
  import { readFileSync as readFileSync222, writeFileSync as writeFileSync15, unlinkSync as unlinkSync2, mkdirSync as mkdirSync14, readdirSync as readdirSync3 } from "fs";
3296
- import { join as join362, dirname as dirname12 } from "path";
3341
+ import { join as join382, dirname as dirname12 } from "path";
3297
3342
  import { createHash as createHash32 } from "crypto";
3298
- import { z as z9 } from "zod";
3343
+ import { z as z11 } from "zod";
3299
3344
  import { readFileSync as readFileSync23, writeFileSync as writeFileSync16, renameSync as renameSync82, mkdirSync as mkdirSync15, existsSync as existsSync332 } from "fs";
3300
3345
  import { execSync as execSync3 } from "child_process";
3301
3346
  import { randomBytes as randomBytes22 } from "crypto";
3302
- import { join as join372, dirname as dirname13 } from "path";
3303
- import * as path22 from "path";
3304
- import * as path23 from "path";
3347
+ import { join as join39, dirname as dirname13 } from "path";
3305
3348
  import * as path24 from "path";
3306
3349
  import * as path25 from "path";
3307
- import * as fs26 from "fs";
3308
3350
  import * as path26 from "path";
3309
- import * as fs27 from "fs";
3310
3351
  import * as path27 from "path";
3311
3352
  import * as fs28 from "fs";
3312
- import { z as z10 } from "zod";
3313
- import * as fs29 from "fs/promises";
3314
3353
  import * as path28 from "path";
3315
- import * as fs30 from "fs/promises";
3354
+ import * as fs29 from "fs";
3316
3355
  import * as path29 from "path";
3317
- import * as ejs from "ejs";
3318
- import * as fs31 from "fs";
3356
+ import * as fs30 from "fs";
3357
+ import { z as z12 } from "zod";
3358
+ import * as fs31 from "fs/promises";
3319
3359
  import * as path30 from "path";
3320
- import * as os from "os";
3321
- import { spawn as spawn2 } from "child_process";
3322
3360
  import * as fs32 from "fs/promises";
3323
3361
  import * as path31 from "path";
3362
+ import * as ejs from "ejs";
3324
3363
  import * as fs33 from "fs";
3325
3364
  import * as path32 from "path";
3326
- import * as fs34 from "fs";
3365
+ import * as os from "os";
3366
+ import { spawn as spawn2 } from "child_process";
3367
+ import * as fs34 from "fs/promises";
3327
3368
  import * as path33 from "path";
3328
- import * as os2 from "os";
3329
3369
  import * as fs35 from "fs";
3330
3370
  import * as path34 from "path";
3371
+ import * as fs36 from "fs";
3372
+ import * as path35 from "path";
3373
+ import * as os2 from "os";
3331
3374
  import * as fs37 from "fs";
3332
3375
  import * as path36 from "path";
3376
+ import * as fs39 from "fs";
3377
+ import * as path38 from "path";
3333
3378
  import { execFileSync as execFileSync2 } from "child_process";
3334
- import * as fs36 from "fs";
3335
- import * as path35 from "path";
3379
+ import * as fs38 from "fs";
3380
+ import * as path37 from "path";
3336
3381
  import * as crypto4 from "crypto";
3382
+ import * as fs40 from "fs";
3383
+ import * as path39 from "path";
3384
+ import * as fs41 from "fs";
3385
+ import * as fs42 from "fs";
3386
+ import * as path40 from "path";
3387
+ import { readFileSync as readFileSync36 } from "fs";
3388
+ import { fileURLToPath } from "url";
3389
+ import { dirname as dirname18, join as join572 } from "path";
3390
+ import { execFile } from "child_process";
3391
+ import { promisify as promisify22 } from "util";
3392
+ import { execFile as execFile2 } from "child_process";
3393
+ import { promisify as promisify3 } from "util";
3394
+ import * as fs43 from "fs/promises";
3395
+ import * as path41 from "path";
3337
3396
  async function validateFileStructure(projectPath, conventions) {
3338
3397
  const missing = [];
3339
3398
  const unexpected = [];
@@ -3369,15 +3428,15 @@ function validateConfig(data, schema) {
3369
3428
  let message = "Configuration validation failed";
3370
3429
  const suggestions = [];
3371
3430
  if (firstError) {
3372
- const path37 = firstError.path.join(".");
3373
- const pathDisplay = path37 ? ` at "${path37}"` : "";
3431
+ const path42 = firstError.path.join(".");
3432
+ const pathDisplay = path42 ? ` at "${path42}"` : "";
3374
3433
  if (firstError.code === "invalid_type") {
3375
3434
  const received = firstError.received;
3376
3435
  const expected = firstError.expected;
3377
3436
  if (received === "undefined") {
3378
3437
  code = "MISSING_FIELD";
3379
3438
  message = `Missing required field${pathDisplay}: ${firstError.message}`;
3380
- suggestions.push(`Field "${path37}" is required and must be of type "${expected}"`);
3439
+ suggestions.push(`Field "${path42}" is required and must be of type "${expected}"`);
3381
3440
  } else {
3382
3441
  code = "INVALID_TYPE";
3383
3442
  message = `Invalid type${pathDisplay}: ${firstError.message}`;
@@ -3487,6 +3546,82 @@ function validateConventionalCommit(message) {
3487
3546
  issues: []
3488
3547
  });
3489
3548
  }
3549
+ async function validatePulseConfig(cwd) {
3550
+ const configPath = path.join(cwd, "harness.config.json");
3551
+ let raw;
3552
+ try {
3553
+ raw = await fs.readFile(configPath, "utf-8");
3554
+ } catch {
3555
+ return Ok({ present: false, valid: true });
3556
+ }
3557
+ let parsed;
3558
+ try {
3559
+ parsed = JSON.parse(raw);
3560
+ } catch (e) {
3561
+ return Err(
3562
+ createError(
3563
+ "VALIDATION_FAILED",
3564
+ `harness.config.json is not valid JSON: ${e.message}`,
3565
+ {},
3566
+ []
3567
+ )
3568
+ );
3569
+ }
3570
+ if (!("pulse" in parsed)) return Ok({ present: false, valid: true });
3571
+ const result = validateConfig(parsed.pulse, PulseConfigSchema);
3572
+ if (!result.ok) return Err(result.error);
3573
+ return Ok({ present: true, valid: true });
3574
+ }
3575
+ async function* walk2(dir) {
3576
+ let entries;
3577
+ try {
3578
+ entries = await fs2.readdir(dir, { withFileTypes: true });
3579
+ } catch {
3580
+ return;
3581
+ }
3582
+ for (const e of entries) {
3583
+ const p = path2.join(dir, e.name);
3584
+ if (e.isDirectory()) yield* walk2(p);
3585
+ else if (e.isFile() && e.name.endsWith(".md")) yield p;
3586
+ }
3587
+ }
3588
+ async function validateSolutionsDir(cwd) {
3589
+ const root = path2.join(cwd, "docs", "solutions");
3590
+ try {
3591
+ await fs2.stat(root);
3592
+ } catch {
3593
+ return Ok({ filesChecked: 0, issues: [] });
3594
+ }
3595
+ const issues = [];
3596
+ let count = 0;
3597
+ for (const [track, categories] of TRACK_CATEGORIES) {
3598
+ for (const category of categories) {
3599
+ const categoryDir = path2.join(root, track, category);
3600
+ for await (const file of walk2(categoryDir)) {
3601
+ count++;
3602
+ const raw = await fs2.readFile(file, "utf-8");
3603
+ const parsed = matter(raw);
3604
+ const result = validateConfig(parsed.data, SolutionDocFrontmatterSchema);
3605
+ if (!result.ok)
3606
+ issues.push({
3607
+ file: path2.relative(cwd, file).replaceAll("\\", "/"),
3608
+ message: result.error.message
3609
+ });
3610
+ }
3611
+ }
3612
+ }
3613
+ if (issues.length > 0) {
3614
+ return Err(
3615
+ createError(
3616
+ "VALIDATION_FAILED",
3617
+ `${issues.length} solution doc(s) failed frontmatter validation`,
3618
+ { issues },
3619
+ []
3620
+ )
3621
+ );
3622
+ }
3623
+ return Ok({ filesChecked: count, issues: [] });
3624
+ }
3490
3625
  function resolveAgnixBinary(explicit) {
3491
3626
  if (explicit) return existsSync2(explicit) ? explicit : null;
3492
3627
  const fromEnv = process.env[HARNESS_AGNIX_BIN];
@@ -3507,7 +3642,7 @@ function lookupOnPath() {
3507
3642
  function firstExistingIn(dir, candidates) {
3508
3643
  if (!dir) return null;
3509
3644
  for (const name of candidates) {
3510
- const candidate = isAbsolute(dir) ? join4(dir, name) : join4(process.cwd(), dir, name);
3645
+ const candidate = isAbsolute(dir) ? join32(dir, name) : join32(process.cwd(), dir, name);
3511
3646
  if (existsSync2(candidate)) return candidate;
3512
3647
  }
3513
3648
  return null;
@@ -3584,7 +3719,7 @@ function extractDiagnostics(parsed) {
3584
3719
  }
3585
3720
  function normalizeDiagnostic(diag, cwd) {
3586
3721
  const finding = {
3587
- file: normalizeFilePath(readFile10(diag), cwd),
3722
+ file: normalizeFilePath(readFile32(diag), cwd),
3588
3723
  ruleId: readRuleId(diag),
3589
3724
  severity: normalizeSeverity(readSeverity(diag)),
3590
3725
  message: diag.message ?? "agnix diagnostic"
@@ -3592,7 +3727,7 @@ function normalizeDiagnostic(diag, cwd) {
3592
3727
  attachOptionalFields(finding, diag);
3593
3728
  return finding;
3594
3729
  }
3595
- function readFile10(diag) {
3730
+ function readFile32(diag) {
3596
3731
  return diag.file ?? diag.path ?? "";
3597
3732
  }
3598
3733
  function readRuleId(diag) {
@@ -3635,16 +3770,16 @@ function makeFinding(input) {
3635
3770
  if (input.suggestion) finding.suggestion = input.suggestion;
3636
3771
  return finding;
3637
3772
  }
3638
- function readTextSafe(path37) {
3773
+ function readTextSafe(path42) {
3639
3774
  try {
3640
- return readFileSync2(path37, "utf-8");
3775
+ return readFileSync2(path42, "utf-8");
3641
3776
  } catch {
3642
3777
  return null;
3643
3778
  }
3644
3779
  }
3645
- function safeFileSize(path37) {
3780
+ function safeFileSize(path42) {
3646
3781
  try {
3647
- return statSync(path37).size;
3782
+ return statSync(path42).size;
3648
3783
  } catch {
3649
3784
  return null;
3650
3785
  }
@@ -3681,7 +3816,7 @@ function stripQuotes(value) {
3681
3816
  function runClaudeMdRules(cwd) {
3682
3817
  const findings = [];
3683
3818
  for (const name of CONTEXT_FILES) {
3684
- const abs = join22(cwd, name);
3819
+ const abs = join42(cwd, name);
3685
3820
  if (!existsSync22(abs)) continue;
3686
3821
  findings.push(...inspectContextFile(abs, name));
3687
3822
  }
@@ -3828,7 +3963,7 @@ function appendDescriptionFindings(out, rel, description) {
3828
3963
  function runHookRules(cwd) {
3829
3964
  const findings = [];
3830
3965
  for (const rel of SETTINGS_PATHS) {
3831
- const abs = join32(cwd, rel);
3966
+ const abs = join52(cwd, rel);
3832
3967
  if (!existsSync3(abs)) continue;
3833
3968
  const content = readTextSafe(abs);
3834
3969
  if (content === null) continue;
@@ -3944,7 +4079,7 @@ async function runSkillRules(cwd) {
3944
4079
  for (const abs of skillFiles) {
3945
4080
  const rel = relPath(cwd, abs);
3946
4081
  const dirName = basename(dirname4(abs));
3947
- const siblingYaml = join42(dirname4(abs), "skill.yaml");
4082
+ const siblingYaml = join6(dirname4(abs), "skill.yaml");
3948
4083
  if (existsSync4(siblingYaml)) {
3949
4084
  const yamlFields = parseFrontmatterFields(readTextSafe(siblingYaml) ?? "");
3950
4085
  findings.push(...checkSkillMetadata(relPath(cwd, siblingYaml), dirName, yamlFields));
@@ -4050,7 +4185,7 @@ function runMcpRules(cwd) {
4050
4185
  return findings;
4051
4186
  }
4052
4187
  function loadMcpServers(cwd, rel) {
4053
- const abs = join5(cwd, rel);
4188
+ const abs = join7(cwd, rel);
4054
4189
  if (!existsSync5(abs)) return null;
4055
4190
  const content = readTextSafe(abs);
4056
4191
  if (content === null) return null;
@@ -4189,27 +4324,27 @@ function extractSections(content) {
4189
4324
  }
4190
4325
  return sections.map((section) => buildAgentMapSection(section, lines));
4191
4326
  }
4192
- function isExternalLink(path37) {
4193
- return path37.startsWith("http://") || path37.startsWith("https://") || path37.startsWith("#") || path37.startsWith("mailto:");
4327
+ function isExternalLink(path42) {
4328
+ return path42.startsWith("http://") || path42.startsWith("https://") || path42.startsWith("#") || path42.startsWith("mailto:");
4194
4329
  }
4195
4330
  function resolveLinkPath(linkPath, baseDir) {
4196
- return linkPath.startsWith(".") ? join6(baseDir, linkPath) : linkPath;
4331
+ return linkPath.startsWith(".") ? join8(baseDir, linkPath) : linkPath;
4197
4332
  }
4198
- async function validateAgentsMap(path37 = "./AGENTS.md") {
4199
- const contentResult = await readFileContent(path37);
4333
+ async function validateAgentsMap(path42 = "./AGENTS.md") {
4334
+ const contentResult = await readFileContent(path42);
4200
4335
  if (!contentResult.ok) {
4201
4336
  return Err(
4202
4337
  createError(
4203
4338
  "PARSE_ERROR",
4204
4339
  `Failed to read AGENTS.md: ${contentResult.error.message}`,
4205
- { path: path37 },
4340
+ { path: path42 },
4206
4341
  ["Ensure the file exists", "Check file permissions"]
4207
4342
  )
4208
4343
  );
4209
4344
  }
4210
4345
  const content = contentResult.value;
4211
4346
  const sections = extractSections(content);
4212
- const baseDir = dirname22(path37);
4347
+ const baseDir = dirname22(path42);
4213
4348
  const sectionTitles = sections.map((s) => s.title);
4214
4349
  const missingSections = REQUIRED_SECTIONS.filter(
4215
4350
  (required) => !sectionTitles.some((title) => title.toLowerCase().includes(required.toLowerCase()))
@@ -4248,7 +4383,7 @@ async function validateAgentsMap(path37 = "./AGENTS.md") {
4248
4383
  });
4249
4384
  }
4250
4385
  async function runAgentsMdRules(cwd) {
4251
- const abs = join7(cwd, "AGENTS.md");
4386
+ const abs = join9(cwd, "AGENTS.md");
4252
4387
  if (!existsSync6(abs)) return [];
4253
4388
  const result = await validateAgentsMap(abs);
4254
4389
  if (result.ok) return [];
@@ -4305,7 +4440,7 @@ function extractLinkTargets(content) {
4305
4440
  function runSettingsJsonRules(cwd) {
4306
4441
  const findings = [];
4307
4442
  for (const rel of SETTINGS_FILES) {
4308
- const abs = join8(cwd, rel);
4443
+ const abs = join10(cwd, rel);
4309
4444
  if (!existsSync8(abs)) continue;
4310
4445
  const content = readTextSafe(abs);
4311
4446
  if (content === null) continue;
@@ -4381,15 +4516,15 @@ function stripQuotes2(value) {
4381
4516
  return value;
4382
4517
  }
4383
4518
  function skillExists(cwd, slug) {
4384
- if (existsSync9(join9(cwd, "agents", "skills", slug, "SKILL.md"))) return true;
4519
+ if (existsSync9(join11(cwd, "agents", "skills", slug, "SKILL.md"))) return true;
4385
4520
  for (const platform of ["claude-code", "gemini-cli", "codex", "cursor", "shared"]) {
4386
- if (existsSync9(join9(cwd, "agents", "skills", platform, slug, "SKILL.md"))) return true;
4521
+ if (existsSync9(join11(cwd, "agents", "skills", platform, slug, "SKILL.md"))) return true;
4387
4522
  }
4388
4523
  return false;
4389
4524
  }
4390
4525
  function runAgnixTomlRules(cwd) {
4391
4526
  const rel = ".agnix.toml";
4392
- const abs = join10(cwd, rel);
4527
+ const abs = join12(cwd, rel);
4393
4528
  if (!existsSync10(abs)) return [];
4394
4529
  const content = readTextSafe(abs);
4395
4530
  if (content === null) return [];
@@ -4649,8 +4784,8 @@ async function checkDocCoverage(domain, options = {}) {
4649
4784
  );
4650
4785
  }
4651
4786
  }
4652
- function suggestFix(path37, existingFiles) {
4653
- const targetName = basename3(path37).toLowerCase();
4787
+ function suggestFix(path42, existingFiles) {
4788
+ const targetName = basename3(path42).toLowerCase();
4654
4789
  const similar = existingFiles.find((file) => {
4655
4790
  const fileName = basename3(file).toLowerCase();
4656
4791
  return fileName.includes(targetName) || targetName.includes(fileName);
@@ -4658,10 +4793,10 @@ function suggestFix(path37, existingFiles) {
4658
4793
  if (similar) {
4659
4794
  return `Did you mean "${similar}"?`;
4660
4795
  }
4661
- return `Create the file "${path37}" or remove the link`;
4796
+ return `Create the file "${path42}" or remove the link`;
4662
4797
  }
4663
4798
  async function validateKnowledgeMap(rootDir = process.cwd()) {
4664
- const agentsPath = join11(rootDir, "AGENTS.md");
4799
+ const agentsPath = join13(rootDir, "AGENTS.md");
4665
4800
  const agentsResult = await validateAgentsMap(agentsPath);
4666
4801
  if (!agentsResult.ok) {
4667
4802
  return Err(agentsResult.error);
@@ -5016,8 +5151,8 @@ function createBoundaryValidator(schema, name) {
5016
5151
  return Ok(result.data);
5017
5152
  }
5018
5153
  const suggestions = result.error.issues.map((issue) => {
5019
- const path37 = issue.path.join(".");
5020
- return path37 ? `${path37}: ${issue.message}` : issue.message;
5154
+ const path42 = issue.path.join(".");
5155
+ return path42 ? `${path42}: ${issue.message}` : issue.message;
5021
5156
  });
5022
5157
  return Err(
5023
5158
  createError(
@@ -5063,7 +5198,7 @@ function validateBoundaries(boundaries, data) {
5063
5198
  async function writeConfig(filePath, content) {
5064
5199
  try {
5065
5200
  const json = JSON.stringify(content, null, 2) + "\n";
5066
- await fs.writeFile(filePath, json, "utf-8");
5201
+ await fs3.writeFile(filePath, json, "utf-8");
5067
5202
  return Ok(void 0);
5068
5203
  } catch (error) {
5069
5204
  return Err(error instanceof Error ? error : new Error(String(error)));
@@ -5337,7 +5472,7 @@ function deepMergeConstraints(localConfig, bundleConstraints, _existingContribut
5337
5472
  async function readLockfile(lockfilePath) {
5338
5473
  let raw;
5339
5474
  try {
5340
- raw = await fs2.readFile(lockfilePath, "utf-8");
5475
+ raw = await fs4.readFile(lockfilePath, "utf-8");
5341
5476
  } catch (err) {
5342
5477
  if (isNodeError(err) && err.code === "ENOENT") {
5343
5478
  return { ok: true, value: null };
@@ -5640,7 +5775,7 @@ async function resolveEntryPoints(rootDir, explicitEntries) {
5640
5775
  if (explicitEntries && explicitEntries.length > 0) {
5641
5776
  return Ok(explicitEntries.map((e) => resolve32(rootDir, e)));
5642
5777
  }
5643
- const pkgPath = join12(rootDir, "package.json");
5778
+ const pkgPath = join14(rootDir, "package.json");
5644
5779
  if (await fileExists(pkgPath)) {
5645
5780
  const pkgContent = await readFileContent(pkgPath);
5646
5781
  if (pkgContent.ok) {
@@ -5654,7 +5789,7 @@ async function resolveEntryPoints(rootDir, explicitEntries) {
5654
5789
  }
5655
5790
  const conventions = ["src/index.ts", "src/main.ts", "index.ts", "main.ts"];
5656
5791
  for (const conv of conventions) {
5657
- const convPath = join12(rootDir, conv);
5792
+ const convPath = join14(rootDir, conv);
5658
5793
  if (await fileExists(convPath)) {
5659
5794
  return Ok([convPath]);
5660
5795
  }
@@ -5721,22 +5856,22 @@ function extractInlineRefs(content) {
5721
5856
  }
5722
5857
  return refs;
5723
5858
  }
5724
- async function parseDocumentationFile(path37) {
5725
- const contentResult = await readFileContent(path37);
5859
+ async function parseDocumentationFile(path42) {
5860
+ const contentResult = await readFileContent(path42);
5726
5861
  if (!contentResult.ok) {
5727
5862
  return Err(
5728
5863
  createEntropyError(
5729
5864
  "PARSE_ERROR",
5730
- `Failed to read documentation file: ${path37}`,
5731
- { file: path37 },
5865
+ `Failed to read documentation file: ${path42}`,
5866
+ { file: path42 },
5732
5867
  ["Check that the file exists"]
5733
5868
  )
5734
5869
  );
5735
5870
  }
5736
5871
  const content = contentResult.value;
5737
- const type = path37.endsWith(".md") ? "markdown" : "text";
5872
+ const type = path42.endsWith(".md") ? "markdown" : "text";
5738
5873
  return Ok({
5739
- path: path37,
5874
+ path: path42,
5740
5875
  type,
5741
5876
  content,
5742
5877
  codeBlocks: extractCodeBlocks(content),
@@ -6635,13 +6770,13 @@ function dirSize(dirPath) {
6635
6770
  }
6636
6771
  for (const entry of entries) {
6637
6772
  if (entry === "node_modules" || entry === ".git") continue;
6638
- const fullPath = join13(dirPath, entry);
6773
+ const fullPath = join15(dirPath, entry);
6639
6774
  try {
6640
- const stat = statSync2(fullPath);
6641
- if (stat.isDirectory()) {
6775
+ const stat2 = statSync2(fullPath);
6776
+ if (stat2.isDirectory()) {
6642
6777
  total += dirSize(fullPath);
6643
- } else if (stat.isFile()) {
6644
- total += stat.size;
6778
+ } else if (stat2.isFile()) {
6779
+ total += stat2.size;
6645
6780
  }
6646
6781
  } catch {
6647
6782
  continue;
@@ -6655,7 +6790,7 @@ async function detectSizeBudgetViolations(rootDir, config) {
6655
6790
  let packagesChecked = 0;
6656
6791
  for (const [pkgPath, budget] of Object.entries(budgets)) {
6657
6792
  packagesChecked++;
6658
- const distPath = join13(rootDir, pkgPath, "dist");
6793
+ const distPath = join15(rootDir, pkgPath, "dist");
6659
6794
  const currentSize = dirSize(distPath);
6660
6795
  if (budget.warn) {
6661
6796
  const budgetBytes = parseSize(budget.warn);
@@ -6899,7 +7034,7 @@ function previewFix(fix) {
6899
7034
  }
6900
7035
  }
6901
7036
  async function createBackup(filePath, backupDir) {
6902
- const backupPath = join14(backupDir, `${Date.now()}-${basename5(filePath)}`);
7037
+ const backupPath = join16(backupDir, `${Date.now()}-${basename5(filePath)}`);
6903
7038
  try {
6904
7039
  await mkdir22(dirname7(backupPath), { recursive: true });
6905
7040
  await copyFile2(filePath, backupPath);
@@ -6925,7 +7060,7 @@ async function applyDeleteFile(fix, config) {
6925
7060
  }
6926
7061
  async function applyDeleteLines(fix) {
6927
7062
  if (fix.line !== void 0) {
6928
- const content = await readFile42(fix.file, "utf-8");
7063
+ const content = await readFile62(fix.file, "utf-8");
6929
7064
  const lines = content.split("\n");
6930
7065
  lines.splice(fix.line - 1, 1);
6931
7066
  await writeFile32(fix.file, lines.join("\n"));
@@ -6933,13 +7068,13 @@ async function applyDeleteLines(fix) {
6933
7068
  }
6934
7069
  async function applyReplace(fix) {
6935
7070
  if (fix.oldContent && fix.newContent !== void 0) {
6936
- const content = await readFile42(fix.file, "utf-8");
7071
+ const content = await readFile62(fix.file, "utf-8");
6937
7072
  await writeFile32(fix.file, content.replace(fix.oldContent, fix.newContent));
6938
7073
  }
6939
7074
  }
6940
7075
  async function applyInsert(fix) {
6941
7076
  if (fix.line !== void 0 && fix.newContent) {
6942
- const content = await readFile42(fix.file, "utf-8");
7077
+ const content = await readFile62(fix.file, "utf-8");
6943
7078
  const lines = content.split("\n");
6944
7079
  lines.splice(fix.line - 1, 0, fix.newContent);
6945
7080
  await writeFile32(fix.file, lines.join("\n"));
@@ -7274,12 +7409,12 @@ function parseDiffHeader(part) {
7274
7409
  return headerMatch[2];
7275
7410
  }
7276
7411
  function parseDiffPart(part) {
7277
- const path37 = parseDiffHeader(part);
7278
- if (!path37) return null;
7412
+ const path42 = parseDiffHeader(part);
7413
+ if (!path42) return null;
7279
7414
  const additionRegex = /^\+(?!\+\+)/gm;
7280
7415
  const deletionRegex = /^-(?!--)/gm;
7281
7416
  return {
7282
- path: path37,
7417
+ path: path42,
7283
7418
  status: detectFileStatus(part),
7284
7419
  additions: (part.match(additionRegex) || []).length,
7285
7420
  deletions: (part.match(deletionRegex) || []).length
@@ -8064,10 +8199,10 @@ function detectEmergentConstraints(history, options) {
8064
8199
  return { suggestions, totalViolationsAnalyzed, windowWeeks, minOccurrences };
8065
8200
  }
8066
8201
  function streamsDir(projectPath) {
8067
- return path5.join(projectPath, HARNESS_DIR, STREAMS_DIR);
8202
+ return path7.join(projectPath, HARNESS_DIR, STREAMS_DIR);
8068
8203
  }
8069
8204
  function indexPath(projectPath) {
8070
- return path5.join(streamsDir(projectPath), INDEX_FILE);
8205
+ return path7.join(streamsDir(projectPath), INDEX_FILE);
8071
8206
  }
8072
8207
  function validateStreamName(name) {
8073
8208
  if (!STREAM_NAME_REGEX.test(name)) {
@@ -8081,11 +8216,11 @@ function validateStreamName(name) {
8081
8216
  }
8082
8217
  async function loadStreamIndex(projectPath) {
8083
8218
  const idxPath = indexPath(projectPath);
8084
- if (!fs8.existsSync(idxPath)) {
8219
+ if (!fs10.existsSync(idxPath)) {
8085
8220
  return Ok({ ...DEFAULT_STREAM_INDEX, streams: {} });
8086
8221
  }
8087
8222
  try {
8088
- const raw = fs8.readFileSync(idxPath, "utf-8");
8223
+ const raw = fs10.readFileSync(idxPath, "utf-8");
8089
8224
  const parsed = JSON.parse(raw);
8090
8225
  const result = StreamIndexSchema.safeParse(parsed);
8091
8226
  if (!result.success) {
@@ -8103,8 +8238,8 @@ async function loadStreamIndex(projectPath) {
8103
8238
  async function saveStreamIndex(projectPath, index) {
8104
8239
  const dir = streamsDir(projectPath);
8105
8240
  try {
8106
- fs8.mkdirSync(dir, { recursive: true });
8107
- fs8.writeFileSync(indexPath(projectPath), JSON.stringify(index, null, 2));
8241
+ fs10.mkdirSync(dir, { recursive: true });
8242
+ fs10.writeFileSync(indexPath(projectPath), JSON.stringify(index, null, 2));
8108
8243
  return Ok(void 0);
8109
8244
  } catch (error) {
8110
8245
  return Err(
@@ -8143,18 +8278,18 @@ async function resolveStreamPath(projectPath, options) {
8143
8278
  )
8144
8279
  );
8145
8280
  }
8146
- return Ok(path5.join(streamsDir(projectPath), options.stream));
8281
+ return Ok(path7.join(streamsDir(projectPath), options.stream));
8147
8282
  }
8148
8283
  const branch = getCurrentBranch(projectPath);
8149
8284
  if (branch && branch !== "main" && branch !== "master") {
8150
8285
  for (const [name, info] of Object.entries(index.streams)) {
8151
8286
  if (info.branch === branch) {
8152
- return Ok(path5.join(streamsDir(projectPath), name));
8287
+ return Ok(path7.join(streamsDir(projectPath), name));
8153
8288
  }
8154
8289
  }
8155
8290
  }
8156
8291
  if (index.activeStream && index.streams[index.activeStream]) {
8157
- return Ok(path5.join(streamsDir(projectPath), index.activeStream));
8292
+ return Ok(path7.join(streamsDir(projectPath), index.activeStream));
8158
8293
  }
8159
8294
  return Err(
8160
8295
  new Error(
@@ -8182,9 +8317,9 @@ async function createStream(projectPath, name, branch) {
8182
8317
  if (index.streams[name]) {
8183
8318
  return Err(new Error(`Stream '${name}' already exists`));
8184
8319
  }
8185
- const streamPath = path5.join(streamsDir(projectPath), name);
8320
+ const streamPath = path7.join(streamsDir(projectPath), name);
8186
8321
  try {
8187
- fs8.mkdirSync(streamPath, { recursive: true });
8322
+ fs10.mkdirSync(streamPath, { recursive: true });
8188
8323
  } catch (error) {
8189
8324
  return Err(
8190
8325
  new Error(
@@ -8225,12 +8360,12 @@ async function archiveStream(projectPath, name) {
8225
8360
  if (!index.streams[name]) {
8226
8361
  return Err(new Error(`Stream '${name}' not found`));
8227
8362
  }
8228
- const streamPath = path5.join(streamsDir(projectPath), name);
8229
- const archiveDir = path5.join(projectPath, HARNESS_DIR, "archive", "streams");
8363
+ const streamPath = path7.join(streamsDir(projectPath), name);
8364
+ const archiveDir = path7.join(projectPath, HARNESS_DIR, "archive", "streams");
8230
8365
  try {
8231
- fs8.mkdirSync(archiveDir, { recursive: true });
8366
+ fs10.mkdirSync(archiveDir, { recursive: true });
8232
8367
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
8233
- fs8.renameSync(streamPath, path5.join(archiveDir, `${name}-${date}`));
8368
+ fs10.renameSync(streamPath, path7.join(archiveDir, `${name}-${date}`));
8234
8369
  } catch (error) {
8235
8370
  return Err(
8236
8371
  new Error(
@@ -8251,19 +8386,19 @@ function getStreamForBranch(index, branch) {
8251
8386
  return null;
8252
8387
  }
8253
8388
  async function migrateToStreams(projectPath) {
8254
- const harnessDir = path5.join(projectPath, HARNESS_DIR);
8255
- if (fs8.existsSync(indexPath(projectPath))) {
8389
+ const harnessDir = path7.join(projectPath, HARNESS_DIR);
8390
+ if (fs10.existsSync(indexPath(projectPath))) {
8256
8391
  return Ok(void 0);
8257
8392
  }
8258
- const filesToMove = STATE_FILES.filter((f) => fs8.existsSync(path5.join(harnessDir, f)));
8393
+ const filesToMove = STATE_FILES.filter((f) => fs10.existsSync(path7.join(harnessDir, f)));
8259
8394
  if (filesToMove.length === 0) {
8260
8395
  return Ok(void 0);
8261
8396
  }
8262
- const defaultDir = path5.join(streamsDir(projectPath), "default");
8397
+ const defaultDir = path7.join(streamsDir(projectPath), "default");
8263
8398
  try {
8264
- fs8.mkdirSync(defaultDir, { recursive: true });
8399
+ fs10.mkdirSync(defaultDir, { recursive: true });
8265
8400
  for (const file of filesToMove) {
8266
- fs8.renameSync(path5.join(harnessDir, file), path5.join(defaultDir, file));
8401
+ fs10.renameSync(path7.join(harnessDir, file), path7.join(defaultDir, file));
8267
8402
  }
8268
8403
  } catch (error) {
8269
8404
  return Err(
@@ -8293,26 +8428,26 @@ function resolveSessionDir(projectPath, sessionSlug, options) {
8293
8428
  new Error(`Invalid session slug '${sessionSlug}': must not contain path traversal characters`)
8294
8429
  );
8295
8430
  }
8296
- const sessionDir = path6.join(projectPath, HARNESS_DIR, SESSIONS_DIR, sessionSlug);
8431
+ const sessionDir = path8.join(projectPath, HARNESS_DIR, SESSIONS_DIR, sessionSlug);
8297
8432
  if (options?.create) {
8298
- fs9.mkdirSync(sessionDir, { recursive: true });
8433
+ fs11.mkdirSync(sessionDir, { recursive: true });
8299
8434
  }
8300
8435
  return Ok(sessionDir);
8301
8436
  }
8302
8437
  function updateSessionIndex(projectPath, sessionSlug, description) {
8303
- const sessionsDir = path6.join(projectPath, HARNESS_DIR, SESSIONS_DIR);
8304
- fs9.mkdirSync(sessionsDir, { recursive: true });
8305
- const indexPath2 = path6.join(sessionsDir, SESSION_INDEX_FILE);
8438
+ const sessionsDir = path8.join(projectPath, HARNESS_DIR, SESSIONS_DIR);
8439
+ fs11.mkdirSync(sessionsDir, { recursive: true });
8440
+ const indexPath2 = path8.join(sessionsDir, SESSION_INDEX_FILE);
8306
8441
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
8307
8442
  const newLine = `- [${sessionSlug}](${sessionSlug}/summary.md) \u2014 ${description} (${date})`;
8308
- if (!fs9.existsSync(indexPath2)) {
8309
- fs9.writeFileSync(indexPath2, `## Active Sessions
8443
+ if (!fs11.existsSync(indexPath2)) {
8444
+ fs11.writeFileSync(indexPath2, `## Active Sessions
8310
8445
 
8311
8446
  ${newLine}
8312
8447
  `);
8313
8448
  return;
8314
8449
  }
8315
- const content = fs9.readFileSync(indexPath2, "utf-8");
8450
+ const content = fs11.readFileSync(indexPath2, "utf-8");
8316
8451
  const lines = content.split("\n");
8317
8452
  const slugPattern = `- [${sessionSlug}]`;
8318
8453
  const existingIdx = lines.findIndex((l) => l.startsWith(slugPattern));
@@ -8322,7 +8457,7 @@ ${newLine}
8322
8457
  const lastNonEmpty = lines.reduce((last, line, i) => line.trim() !== "" ? i : last, 0);
8323
8458
  lines.splice(lastNonEmpty + 1, 0, newLine);
8324
8459
  }
8325
- fs9.writeFileSync(indexPath2, lines.join("\n"));
8460
+ fs11.writeFileSync(indexPath2, lines.join("\n"));
8326
8461
  }
8327
8462
  function evictIfNeeded(map) {
8328
8463
  if (map.size > MAX_CACHE_ENTRIES) {
@@ -8335,8 +8470,8 @@ async function getStateDir(projectPath, stream, session) {
8335
8470
  const sessionResult = resolveSessionDir(projectPath, session, { create: true });
8336
8471
  return sessionResult;
8337
8472
  }
8338
- const streamsIndexPath = path7.join(projectPath, HARNESS_DIR, "streams", INDEX_FILE);
8339
- const hasStreams = fs10.existsSync(streamsIndexPath);
8473
+ const streamsIndexPath = path9.join(projectPath, HARNESS_DIR, "streams", INDEX_FILE);
8474
+ const hasStreams = fs12.existsSync(streamsIndexPath);
8340
8475
  if (stream || hasStreams) {
8341
8476
  const result = await resolveStreamPath(projectPath, stream ? { stream } : void 0);
8342
8477
  if (result.ok) {
@@ -8346,18 +8481,18 @@ async function getStateDir(projectPath, stream, session) {
8346
8481
  return result;
8347
8482
  }
8348
8483
  }
8349
- return Ok(path7.join(projectPath, HARNESS_DIR));
8484
+ return Ok(path9.join(projectPath, HARNESS_DIR));
8350
8485
  }
8351
8486
  async function loadState(projectPath, stream, session) {
8352
8487
  try {
8353
8488
  const dirResult = await getStateDir(projectPath, stream, session);
8354
8489
  if (!dirResult.ok) return dirResult;
8355
8490
  const stateDir = dirResult.value;
8356
- const statePath = path8.join(stateDir, STATE_FILE);
8357
- if (!fs11.existsSync(statePath)) {
8491
+ const statePath = path10.join(stateDir, STATE_FILE);
8492
+ if (!fs13.existsSync(statePath)) {
8358
8493
  return Ok({ ...DEFAULT_STATE });
8359
8494
  }
8360
- const raw = fs11.readFileSync(statePath, "utf-8");
8495
+ const raw = fs13.readFileSync(statePath, "utf-8");
8361
8496
  const parsed = JSON.parse(raw);
8362
8497
  const result = HarnessStateSchema.safeParse(parsed);
8363
8498
  if (!result.success) {
@@ -8375,11 +8510,11 @@ async function saveState(projectPath, state, stream, session) {
8375
8510
  const dirResult = await getStateDir(projectPath, stream, session);
8376
8511
  if (!dirResult.ok) return dirResult;
8377
8512
  const stateDir = dirResult.value;
8378
- const statePath = path8.join(stateDir, STATE_FILE);
8379
- fs11.mkdirSync(stateDir, { recursive: true });
8513
+ const statePath = path10.join(stateDir, STATE_FILE);
8514
+ fs13.mkdirSync(stateDir, { recursive: true });
8380
8515
  const tmpPath = statePath + ".tmp";
8381
- fs11.writeFileSync(tmpPath, JSON.stringify(state, null, 2));
8382
- fs11.renameSync(tmpPath, statePath);
8516
+ fs13.writeFileSync(tmpPath, JSON.stringify(state, null, 2));
8517
+ fs13.renameSync(tmpPath, statePath);
8383
8518
  return Ok(void 0);
8384
8519
  } catch (error) {
8385
8520
  return Err(
@@ -8465,10 +8600,10 @@ function computeContentHash(text) {
8465
8600
  return crypto2.createHash("sha256").update(text).digest("hex").slice(0, 16);
8466
8601
  }
8467
8602
  function loadContentHashes(stateDir) {
8468
- const hashesPath = path9.join(stateDir, CONTENT_HASHES_FILE);
8469
- if (!fs12.existsSync(hashesPath)) return {};
8603
+ const hashesPath = path11.join(stateDir, CONTENT_HASHES_FILE);
8604
+ if (!fs14.existsSync(hashesPath)) return {};
8470
8605
  try {
8471
- const raw = fs12.readFileSync(hashesPath, "utf-8");
8606
+ const raw = fs14.readFileSync(hashesPath, "utf-8");
8472
8607
  const parsed = JSON.parse(raw);
8473
8608
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
8474
8609
  return parsed;
@@ -8477,15 +8612,15 @@ function loadContentHashes(stateDir) {
8477
8612
  }
8478
8613
  }
8479
8614
  function saveContentHashes(stateDir, index) {
8480
- const hashesPath = path9.join(stateDir, CONTENT_HASHES_FILE);
8615
+ const hashesPath = path11.join(stateDir, CONTENT_HASHES_FILE);
8481
8616
  const tmpPath = hashesPath + ".tmp";
8482
- fs12.writeFileSync(tmpPath, JSON.stringify(index, null, 2) + "\n");
8483
- fs12.renameSync(tmpPath, hashesPath);
8617
+ fs14.writeFileSync(tmpPath, JSON.stringify(index, null, 2) + "\n");
8618
+ fs14.renameSync(tmpPath, hashesPath);
8484
8619
  }
8485
8620
  function rebuildContentHashes(stateDir, learningsFile) {
8486
- const learningsPath = path9.join(stateDir, learningsFile);
8487
- if (!fs12.existsSync(learningsPath)) return {};
8488
- const content = fs12.readFileSync(learningsPath, "utf-8");
8621
+ const learningsPath = path11.join(stateDir, learningsFile);
8622
+ if (!fs14.existsSync(learningsPath)) return {};
8623
+ const content = fs14.readFileSync(learningsPath, "utf-8");
8489
8624
  const lines = content.split("\n");
8490
8625
  const index = {};
8491
8626
  for (let i = 0; i < lines.length; i++) {
@@ -8544,18 +8679,18 @@ async function loadRelevantLearnings(projectPath, skillName, stream, session) {
8544
8679
  const dirResult = await getStateDir(projectPath, stream, session);
8545
8680
  if (!dirResult.ok) return dirResult;
8546
8681
  const stateDir = dirResult.value;
8547
- const learningsPath = path10.join(stateDir, LEARNINGS_FILE);
8548
- if (!fs13.existsSync(learningsPath)) {
8682
+ const learningsPath = path12.join(stateDir, LEARNINGS_FILE);
8683
+ if (!fs15.existsSync(learningsPath)) {
8549
8684
  return Ok([]);
8550
8685
  }
8551
- const stats = fs13.statSync(learningsPath);
8686
+ const stats = fs15.statSync(learningsPath);
8552
8687
  const cacheKey = learningsPath;
8553
8688
  const cached = learningsCacheMap.get(cacheKey);
8554
8689
  let entries;
8555
8690
  if (cached && cached.mtimeMs === stats.mtimeMs) {
8556
8691
  entries = cached.entries;
8557
8692
  } else {
8558
- const content = fs13.readFileSync(learningsPath, "utf-8");
8693
+ const content = fs15.readFileSync(learningsPath, "utf-8");
8559
8694
  const lines = content.split("\n");
8560
8695
  entries = [];
8561
8696
  let currentBlock = [];
@@ -8696,11 +8831,11 @@ function sleep(ms) {
8696
8831
  async function acquireFileLock(lockPath) {
8697
8832
  for (let attempt = 0; attempt < LOCK_RETRIES; attempt++) {
8698
8833
  try {
8699
- const fd = fs14.openSync(
8834
+ const fd = fs16.openSync(
8700
8835
  lockPath,
8701
- fs14.constants.O_CREAT | fs14.constants.O_EXCL | fs14.constants.O_WRONLY
8836
+ fs16.constants.O_CREAT | fs16.constants.O_EXCL | fs16.constants.O_WRONLY
8702
8837
  );
8703
- fs14.closeSync(fd);
8838
+ fs16.closeSync(fd);
8704
8839
  return;
8705
8840
  } catch (err) {
8706
8841
  const isExist = err instanceof Error && "code" in err && err.code === "EEXIST";
@@ -8714,20 +8849,20 @@ async function acquireFileLock(lockPath) {
8714
8849
  }
8715
8850
  function releaseFileLock(lockPath) {
8716
8851
  try {
8717
- fs14.unlinkSync(lockPath);
8852
+ fs16.unlinkSync(lockPath);
8718
8853
  } catch {
8719
8854
  }
8720
8855
  }
8721
8856
  function loadOrRebuildHashes(stateDir, learningsPath) {
8722
- const hashesPath = path11.join(stateDir, CONTENT_HASHES_FILE);
8723
- if (fs14.existsSync(hashesPath)) {
8857
+ const hashesPath = path13.join(stateDir, CONTENT_HASHES_FILE);
8858
+ if (fs16.existsSync(hashesPath)) {
8724
8859
  const hashes = loadContentHashes(stateDir);
8725
- if (Object.keys(hashes).length === 0 && fs14.existsSync(learningsPath)) {
8860
+ if (Object.keys(hashes).length === 0 && fs16.existsSync(learningsPath)) {
8726
8861
  return rebuildContentHashes(stateDir, LEARNINGS_FILE);
8727
8862
  }
8728
8863
  return hashes;
8729
8864
  }
8730
- if (fs14.existsSync(learningsPath)) {
8865
+ if (fs16.existsSync(learningsPath)) {
8731
8866
  return rebuildContentHashes(stateDir, LEARNINGS_FILE);
8732
8867
  }
8733
8868
  return {};
@@ -8751,8 +8886,8 @@ async function appendLearning(projectPath, learning, skillName, outcome, stream,
8751
8886
  const dirResult = await getStateDir(projectPath, stream, session);
8752
8887
  if (!dirResult.ok) return dirResult;
8753
8888
  const stateDir = dirResult.value;
8754
- const learningsPath = path11.join(stateDir, LEARNINGS_FILE);
8755
- fs14.mkdirSync(stateDir, { recursive: true });
8889
+ const learningsPath = path13.join(stateDir, LEARNINGS_FILE);
8890
+ fs16.mkdirSync(stateDir, { recursive: true });
8756
8891
  const lockPath = learningsPath + ".lock";
8757
8892
  await acquireFileLock(lockPath);
8758
8893
  try {
@@ -8782,17 +8917,17 @@ ${bulletLine}
8782
8917
  `;
8783
8918
  let overlapResult;
8784
8919
  let existingLineCount;
8785
- if (!fs14.existsSync(learningsPath)) {
8786
- fs14.writeFileSync(learningsPath, `# Learnings
8920
+ if (!fs16.existsSync(learningsPath)) {
8921
+ fs16.writeFileSync(learningsPath, `# Learnings
8787
8922
  ${entry}`);
8788
8923
  existingLineCount = 1;
8789
8924
  } else {
8790
- const existingContent = fs14.readFileSync(learningsPath, "utf-8");
8925
+ const existingContent = fs16.readFileSync(learningsPath, "utf-8");
8791
8926
  const existingEntries = existingContent.split("\n").filter((line) => /^- \*\*\d{4}-\d{2}-\d{2}/.test(line));
8792
8927
  const overlap = checkOverlap(bulletLine, existingEntries);
8793
8928
  if (overlap.score >= 0.7) overlapResult = overlap;
8794
8929
  existingLineCount = existingContent.split("\n").length;
8795
- fs14.appendFileSync(learningsPath, entry);
8930
+ fs16.appendFileSync(learningsPath, entry);
8796
8931
  }
8797
8932
  const bulletLineNum = existingLineCount + 2;
8798
8933
  contentHashes[contentHash] = { date: timestamp ?? "", line: bulletLineNum };
@@ -8897,11 +9032,11 @@ async function loadIndexEntries(projectPath, skillName, stream, session) {
8897
9032
  const dirResult = await getStateDir(projectPath, stream, session);
8898
9033
  if (!dirResult.ok) return dirResult;
8899
9034
  const stateDir = dirResult.value;
8900
- const learningsPath = path11.join(stateDir, LEARNINGS_FILE);
8901
- if (!fs14.existsSync(learningsPath)) {
9035
+ const learningsPath = path13.join(stateDir, LEARNINGS_FILE);
9036
+ if (!fs16.existsSync(learningsPath)) {
8902
9037
  return Ok([]);
8903
9038
  }
8904
- const content = fs14.readFileSync(learningsPath, "utf-8");
9039
+ const content = fs16.readFileSync(learningsPath, "utf-8");
8905
9040
  const lines = content.split("\n");
8906
9041
  const indexEntries = [];
8907
9042
  let pendingFrontmatter = null;
@@ -8943,16 +9078,16 @@ async function archiveLearnings(projectPath, entries, stream) {
8943
9078
  const dirResult = await getStateDir(projectPath, stream);
8944
9079
  if (!dirResult.ok) return dirResult;
8945
9080
  const stateDir = dirResult.value;
8946
- const archiveDir = path12.join(stateDir, "learnings-archive");
8947
- fs15.mkdirSync(archiveDir, { recursive: true });
9081
+ const archiveDir = path14.join(stateDir, "learnings-archive");
9082
+ fs17.mkdirSync(archiveDir, { recursive: true });
8948
9083
  const now = /* @__PURE__ */ new Date();
8949
9084
  const yearMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
8950
- const archivePath = path12.join(archiveDir, `${yearMonth}.md`);
9085
+ const archivePath = path14.join(archiveDir, `${yearMonth}.md`);
8951
9086
  const archiveContent = entries.join("\n\n") + "\n";
8952
- if (fs15.existsSync(archivePath)) {
8953
- fs15.appendFileSync(archivePath, "\n" + archiveContent);
9087
+ if (fs17.existsSync(archivePath)) {
9088
+ fs17.appendFileSync(archivePath, "\n" + archiveContent);
8954
9089
  } else {
8955
- fs15.writeFileSync(archivePath, `# Learnings Archive
9090
+ fs17.writeFileSync(archivePath, `# Learnings Archive
8956
9091
 
8957
9092
  ${archiveContent}`);
8958
9093
  }
@@ -8970,8 +9105,8 @@ async function pruneLearnings(projectPath, stream) {
8970
9105
  const dirResult = await getStateDir(projectPath, stream);
8971
9106
  if (!dirResult.ok) return dirResult;
8972
9107
  const stateDir = dirResult.value;
8973
- const learningsPath = path12.join(stateDir, LEARNINGS_FILE);
8974
- if (!fs15.existsSync(learningsPath)) {
9108
+ const learningsPath = path14.join(stateDir, LEARNINGS_FILE);
9109
+ if (!fs17.existsSync(learningsPath)) {
8975
9110
  return Ok({ kept: 0, archived: 0, patterns: [] });
8976
9111
  }
8977
9112
  const loadResult = await loadRelevantLearnings(projectPath, void 0, stream);
@@ -9002,7 +9137,7 @@ async function pruneLearnings(projectPath, stream) {
9002
9137
  if (!archiveResult.ok) return archiveResult;
9003
9138
  }
9004
9139
  const newContent = "# Learnings\n\n" + toKeep.join("\n\n") + "\n";
9005
- fs15.writeFileSync(learningsPath, newContent);
9140
+ fs17.writeFileSync(learningsPath, newContent);
9006
9141
  invalidateLearningsCacheEntry(learningsPath);
9007
9142
  return Ok({
9008
9143
  kept: toKeep.length,
@@ -9046,19 +9181,19 @@ async function promoteSessionLearnings(projectPath, sessionSlug, stream) {
9046
9181
  const dirResult = await getStateDir(projectPath, stream);
9047
9182
  if (!dirResult.ok) return dirResult;
9048
9183
  const stateDir = dirResult.value;
9049
- const globalPath = path12.join(stateDir, LEARNINGS_FILE);
9050
- const existingGlobal = fs15.existsSync(globalPath) ? fs15.readFileSync(globalPath, "utf-8") : "";
9184
+ const globalPath = path14.join(stateDir, LEARNINGS_FILE);
9185
+ const existingGlobal = fs17.existsSync(globalPath) ? fs17.readFileSync(globalPath, "utf-8") : "";
9051
9186
  const newEntries = toPromote.filter((entry) => !existingGlobal.includes(entry.trim()));
9052
9187
  if (newEntries.length === 0) {
9053
9188
  return Ok({ promoted: 0, skipped: skipped + toPromote.length });
9054
9189
  }
9055
9190
  const promotedContent = newEntries.join("\n\n") + "\n";
9056
9191
  if (!existingGlobal) {
9057
- fs15.writeFileSync(globalPath, `# Learnings
9192
+ fs17.writeFileSync(globalPath, `# Learnings
9058
9193
 
9059
9194
  ${promotedContent}`);
9060
9195
  } else {
9061
- fs15.appendFileSync(globalPath, "\n\n" + promotedContent);
9196
+ fs17.appendFileSync(globalPath, "\n\n" + promotedContent);
9062
9197
  }
9063
9198
  invalidateLearningsCacheEntry(globalPath);
9064
9199
  return Ok({
@@ -9094,13 +9229,13 @@ async function detectStaleLearnings(projectPath, stream, session) {
9094
9229
  freshCount++;
9095
9230
  continue;
9096
9231
  }
9097
- const resolvedRoot = path13.resolve(projectPath);
9232
+ const resolvedRoot = path15.resolve(projectPath);
9098
9233
  const missing = refs.filter((ref) => {
9099
- const absPath = path13.resolve(projectPath, ref);
9100
- if (!absPath.startsWith(resolvedRoot + path13.sep) && absPath !== resolvedRoot) {
9234
+ const absPath = path15.resolve(projectPath, ref);
9235
+ if (!absPath.startsWith(resolvedRoot + path15.sep) && absPath !== resolvedRoot) {
9101
9236
  return false;
9102
9237
  }
9103
- return !fs16.existsSync(absPath);
9238
+ return !fs18.existsSync(absPath);
9104
9239
  });
9105
9240
  if (missing.length > 0) {
9106
9241
  const idx = extractIndexEntry(entry);
@@ -9135,17 +9270,17 @@ async function appendFailure(projectPath, description, skillName, type, stream,
9135
9270
  const dirResult = await getStateDir(projectPath, stream, session);
9136
9271
  if (!dirResult.ok) return dirResult;
9137
9272
  const stateDir = dirResult.value;
9138
- const failuresPath = path14.join(stateDir, FAILURES_FILE);
9139
- fs17.mkdirSync(stateDir, { recursive: true });
9273
+ const failuresPath = path16.join(stateDir, FAILURES_FILE);
9274
+ fs19.mkdirSync(stateDir, { recursive: true });
9140
9275
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
9141
9276
  const entry = `
9142
9277
  - **${timestamp} [skill:${skillName}] [type:${type}]:** ${description}
9143
9278
  `;
9144
- if (!fs17.existsSync(failuresPath)) {
9145
- fs17.writeFileSync(failuresPath, `# Failures
9279
+ if (!fs19.existsSync(failuresPath)) {
9280
+ fs19.writeFileSync(failuresPath, `# Failures
9146
9281
  ${entry}`);
9147
9282
  } else {
9148
- fs17.appendFileSync(failuresPath, entry);
9283
+ fs19.appendFileSync(failuresPath, entry);
9149
9284
  }
9150
9285
  failuresCacheMap.delete(failuresPath);
9151
9286
  return Ok(void 0);
@@ -9162,17 +9297,17 @@ async function loadFailures(projectPath, stream, session) {
9162
9297
  const dirResult = await getStateDir(projectPath, stream, session);
9163
9298
  if (!dirResult.ok) return dirResult;
9164
9299
  const stateDir = dirResult.value;
9165
- const failuresPath = path14.join(stateDir, FAILURES_FILE);
9166
- if (!fs17.existsSync(failuresPath)) {
9300
+ const failuresPath = path16.join(stateDir, FAILURES_FILE);
9301
+ if (!fs19.existsSync(failuresPath)) {
9167
9302
  return Ok([]);
9168
9303
  }
9169
- const stats = fs17.statSync(failuresPath);
9304
+ const stats = fs19.statSync(failuresPath);
9170
9305
  const cacheKey = failuresPath;
9171
9306
  const cached = failuresCacheMap.get(cacheKey);
9172
9307
  if (cached && cached.mtimeMs === stats.mtimeMs) {
9173
9308
  return Ok(cached.entries);
9174
9309
  }
9175
- const content = fs17.readFileSync(failuresPath, "utf-8");
9310
+ const content = fs19.readFileSync(failuresPath, "utf-8");
9176
9311
  const entries = [];
9177
9312
  for (const line of content.split("\n")) {
9178
9313
  const match = line.match(FAILURE_LINE_REGEX);
@@ -9201,20 +9336,20 @@ async function archiveFailures(projectPath, stream, session) {
9201
9336
  const dirResult = await getStateDir(projectPath, stream, session);
9202
9337
  if (!dirResult.ok) return dirResult;
9203
9338
  const stateDir = dirResult.value;
9204
- const failuresPath = path14.join(stateDir, FAILURES_FILE);
9205
- if (!fs17.existsSync(failuresPath)) {
9339
+ const failuresPath = path16.join(stateDir, FAILURES_FILE);
9340
+ if (!fs19.existsSync(failuresPath)) {
9206
9341
  return Ok(void 0);
9207
9342
  }
9208
- const archiveDir = path14.join(stateDir, "archive");
9209
- fs17.mkdirSync(archiveDir, { recursive: true });
9343
+ const archiveDir = path16.join(stateDir, "archive");
9344
+ fs19.mkdirSync(archiveDir, { recursive: true });
9210
9345
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
9211
9346
  let archiveName = `failures-${date}.md`;
9212
9347
  let counter = 2;
9213
- while (fs17.existsSync(path14.join(archiveDir, archiveName))) {
9348
+ while (fs19.existsSync(path16.join(archiveDir, archiveName))) {
9214
9349
  archiveName = `failures-${date}-${counter}.md`;
9215
9350
  counter++;
9216
9351
  }
9217
- fs17.renameSync(failuresPath, path14.join(archiveDir, archiveName));
9352
+ fs19.renameSync(failuresPath, path16.join(archiveDir, archiveName));
9218
9353
  failuresCacheMap.delete(failuresPath);
9219
9354
  return Ok(void 0);
9220
9355
  } catch (error) {
@@ -9230,11 +9365,11 @@ async function saveHandoff(projectPath, handoff, stream, session) {
9230
9365
  const dirResult = await getStateDir(projectPath, stream, session);
9231
9366
  if (!dirResult.ok) return dirResult;
9232
9367
  const stateDir = dirResult.value;
9233
- const handoffPath = path15.join(stateDir, HANDOFF_FILE);
9234
- fs18.mkdirSync(stateDir, { recursive: true });
9368
+ const handoffPath = path17.join(stateDir, HANDOFF_FILE);
9369
+ fs20.mkdirSync(stateDir, { recursive: true });
9235
9370
  const tmpPath = handoffPath + ".tmp";
9236
- fs18.writeFileSync(tmpPath, JSON.stringify(handoff, null, 2));
9237
- fs18.renameSync(tmpPath, handoffPath);
9371
+ fs20.writeFileSync(tmpPath, JSON.stringify(handoff, null, 2));
9372
+ fs20.renameSync(tmpPath, handoffPath);
9238
9373
  return Ok(void 0);
9239
9374
  } catch (error) {
9240
9375
  return Err(
@@ -9247,11 +9382,11 @@ async function loadHandoff(projectPath, stream, session) {
9247
9382
  const dirResult = await getStateDir(projectPath, stream, session);
9248
9383
  if (!dirResult.ok) return dirResult;
9249
9384
  const stateDir = dirResult.value;
9250
- const handoffPath = path15.join(stateDir, HANDOFF_FILE);
9251
- if (!fs18.existsSync(handoffPath)) {
9385
+ const handoffPath = path17.join(stateDir, HANDOFF_FILE);
9386
+ if (!fs20.existsSync(handoffPath)) {
9252
9387
  return Ok(null);
9253
9388
  }
9254
- const raw = fs18.readFileSync(handoffPath, "utf-8");
9389
+ const raw = fs20.readFileSync(handoffPath, "utf-8");
9255
9390
  const parsed = JSON.parse(raw);
9256
9391
  const result = HandoffSchema.safeParse(parsed);
9257
9392
  if (!result.success) {
@@ -9265,28 +9400,28 @@ async function loadHandoff(projectPath, stream, session) {
9265
9400
  }
9266
9401
  }
9267
9402
  function loadChecksFromConfig(gateConfigPath) {
9268
- if (!fs19.existsSync(gateConfigPath)) return [];
9269
- const raw = JSON.parse(fs19.readFileSync(gateConfigPath, "utf-8"));
9403
+ if (!fs21.existsSync(gateConfigPath)) return [];
9404
+ const raw = JSON.parse(fs21.readFileSync(gateConfigPath, "utf-8"));
9270
9405
  const config = GateConfigSchema.safeParse(raw);
9271
9406
  if (config.success && config.data.checks) return config.data.checks;
9272
9407
  return [];
9273
9408
  }
9274
9409
  function discoverChecksFromProject(projectPath) {
9275
9410
  const checks = [];
9276
- const packageJsonPath = path16.join(projectPath, "package.json");
9277
- if (fs19.existsSync(packageJsonPath)) {
9278
- const pkg = JSON.parse(fs19.readFileSync(packageJsonPath, "utf-8"));
9411
+ const packageJsonPath = path18.join(projectPath, "package.json");
9412
+ if (fs21.existsSync(packageJsonPath)) {
9413
+ const pkg = JSON.parse(fs21.readFileSync(packageJsonPath, "utf-8"));
9279
9414
  const scripts = pkg.scripts || {};
9280
9415
  if (scripts.test) checks.push({ name: "test", command: "npm test" });
9281
9416
  if (scripts.lint) checks.push({ name: "lint", command: "npm run lint" });
9282
9417
  if (scripts.typecheck) checks.push({ name: "typecheck", command: "npm run typecheck" });
9283
9418
  if (scripts.build) checks.push({ name: "build", command: "npm run build" });
9284
9419
  }
9285
- if (fs19.existsSync(path16.join(projectPath, "go.mod"))) {
9420
+ if (fs21.existsSync(path18.join(projectPath, "go.mod"))) {
9286
9421
  checks.push({ name: "test", command: "go test ./..." });
9287
9422
  checks.push({ name: "build", command: "go build ./..." });
9288
9423
  }
9289
- if (fs19.existsSync(path16.join(projectPath, "pyproject.toml")) || fs19.existsSync(path16.join(projectPath, "setup.py"))) {
9424
+ if (fs21.existsSync(path18.join(projectPath, "pyproject.toml")) || fs21.existsSync(path18.join(projectPath, "setup.py"))) {
9290
9425
  checks.push({ name: "test", command: "python -m pytest" });
9291
9426
  }
9292
9427
  return checks;
@@ -9326,8 +9461,8 @@ function executeCheck(check, projectPath) {
9326
9461
  }
9327
9462
  }
9328
9463
  async function runMechanicalGate(projectPath) {
9329
- const harnessDir = path16.join(projectPath, HARNESS_DIR);
9330
- const gateConfigPath = path16.join(harnessDir, GATE_CONFIG_FILE);
9464
+ const harnessDir = path18.join(projectPath, HARNESS_DIR);
9465
+ const gateConfigPath = path18.join(harnessDir, GATE_CONFIG_FILE);
9331
9466
  try {
9332
9467
  let checks = loadChecksFromConfig(gateConfigPath);
9333
9468
  if (checks.length === 0) {
@@ -9383,9 +9518,9 @@ function writeSessionSummary(projectPath, sessionSlug, data) {
9383
9518
  const dirResult = resolveSessionDir(projectPath, sessionSlug, { create: true });
9384
9519
  if (!dirResult.ok) return dirResult;
9385
9520
  const sessionDir = dirResult.value;
9386
- const summaryPath = path17.join(sessionDir, SUMMARY_FILE);
9521
+ const summaryPath = path19.join(sessionDir, SUMMARY_FILE);
9387
9522
  const content = formatSummary(data);
9388
- fs20.writeFileSync(summaryPath, content);
9523
+ fs22.writeFileSync(summaryPath, content);
9389
9524
  const description = deriveIndexDescription(data);
9390
9525
  updateSessionIndex(projectPath, sessionSlug, description);
9391
9526
  return Ok(void 0);
@@ -9402,11 +9537,11 @@ function loadSessionSummary(projectPath, sessionSlug) {
9402
9537
  const dirResult = resolveSessionDir(projectPath, sessionSlug);
9403
9538
  if (!dirResult.ok) return dirResult;
9404
9539
  const sessionDir = dirResult.value;
9405
- const summaryPath = path17.join(sessionDir, SUMMARY_FILE);
9406
- if (!fs20.existsSync(summaryPath)) {
9540
+ const summaryPath = path19.join(sessionDir, SUMMARY_FILE);
9541
+ if (!fs22.existsSync(summaryPath)) {
9407
9542
  return Ok(null);
9408
9543
  }
9409
- const content = fs20.readFileSync(summaryPath, "utf-8");
9544
+ const content = fs22.readFileSync(summaryPath, "utf-8");
9410
9545
  return Ok(content);
9411
9546
  } catch (error) {
9412
9547
  return Err(
@@ -9418,11 +9553,11 @@ function loadSessionSummary(projectPath, sessionSlug) {
9418
9553
  }
9419
9554
  function listActiveSessions(projectPath) {
9420
9555
  try {
9421
- const indexPath2 = path17.join(projectPath, HARNESS_DIR, SESSIONS_DIR, SESSION_INDEX_FILE);
9422
- if (!fs20.existsSync(indexPath2)) {
9556
+ const indexPath2 = path19.join(projectPath, HARNESS_DIR, SESSIONS_DIR, SESSION_INDEX_FILE);
9557
+ if (!fs22.existsSync(indexPath2)) {
9423
9558
  return Ok(null);
9424
9559
  }
9425
- const content = fs20.readFileSync(indexPath2, "utf-8");
9560
+ const content = fs22.readFileSync(indexPath2, "utf-8");
9426
9561
  return Ok(content);
9427
9562
  } catch (error) {
9428
9563
  return Err(
@@ -9443,12 +9578,12 @@ async function loadSessionState(projectPath, sessionSlug) {
9443
9578
  const dirResult = resolveSessionDir(projectPath, sessionSlug);
9444
9579
  if (!dirResult.ok) return dirResult;
9445
9580
  const sessionDir = dirResult.value;
9446
- const filePath = path18.join(sessionDir, SESSION_STATE_FILE);
9447
- if (!fs21.existsSync(filePath)) {
9581
+ const filePath = path20.join(sessionDir, SESSION_STATE_FILE);
9582
+ if (!fs23.existsSync(filePath)) {
9448
9583
  return Ok(emptySections());
9449
9584
  }
9450
9585
  try {
9451
- const raw = fs21.readFileSync(filePath, "utf-8");
9586
+ const raw = fs23.readFileSync(filePath, "utf-8");
9452
9587
  const parsed = JSON.parse(raw);
9453
9588
  const sections = emptySections();
9454
9589
  for (const name of SESSION_SECTION_NAMES) {
@@ -9469,9 +9604,9 @@ async function saveSessionState(projectPath, sessionSlug, sections) {
9469
9604
  const dirResult = resolveSessionDir(projectPath, sessionSlug, { create: true });
9470
9605
  if (!dirResult.ok) return dirResult;
9471
9606
  const sessionDir = dirResult.value;
9472
- const filePath = path18.join(sessionDir, SESSION_STATE_FILE);
9607
+ const filePath = path20.join(sessionDir, SESSION_STATE_FILE);
9473
9608
  try {
9474
- fs21.writeFileSync(filePath, JSON.stringify(sections, null, 2));
9609
+ fs23.writeFileSync(filePath, JSON.stringify(sections, null, 2));
9475
9610
  return Ok(void 0);
9476
9611
  } catch (error) {
9477
9612
  return Err(
@@ -9527,26 +9662,26 @@ async function archiveSession(projectPath, sessionSlug) {
9527
9662
  const dirResult = resolveSessionDir(projectPath, sessionSlug);
9528
9663
  if (!dirResult.ok) return dirResult;
9529
9664
  const sessionDir = dirResult.value;
9530
- if (!fs22.existsSync(sessionDir)) {
9665
+ if (!fs24.existsSync(sessionDir)) {
9531
9666
  return Err(new Error(`Session '${sessionSlug}' not found at ${sessionDir}`));
9532
9667
  }
9533
- const archiveBase = path19.join(projectPath, HARNESS_DIR, ARCHIVE_DIR, "sessions");
9668
+ const archiveBase = path21.join(projectPath, HARNESS_DIR, ARCHIVE_DIR, "sessions");
9534
9669
  try {
9535
- fs22.mkdirSync(archiveBase, { recursive: true });
9670
+ fs24.mkdirSync(archiveBase, { recursive: true });
9536
9671
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
9537
9672
  let archiveName = `${sessionSlug}-${date}`;
9538
9673
  let counter = 1;
9539
- while (fs22.existsSync(path19.join(archiveBase, archiveName))) {
9674
+ while (fs24.existsSync(path21.join(archiveBase, archiveName))) {
9540
9675
  archiveName = `${sessionSlug}-${date}-${counter}`;
9541
9676
  counter++;
9542
9677
  }
9543
- const dest = path19.join(archiveBase, archiveName);
9678
+ const dest = path21.join(archiveBase, archiveName);
9544
9679
  try {
9545
- fs22.renameSync(sessionDir, dest);
9680
+ fs24.renameSync(sessionDir, dest);
9546
9681
  } catch (renameErr) {
9547
9682
  if (renameErr instanceof Error && "code" in renameErr && renameErr.code === "EXDEV") {
9548
- fs22.cpSync(sessionDir, dest, { recursive: true });
9549
- fs22.rmSync(sessionDir, { recursive: true });
9683
+ fs24.cpSync(sessionDir, dest, { recursive: true });
9684
+ fs24.rmSync(sessionDir, { recursive: true });
9550
9685
  } else {
9551
9686
  throw renameErr;
9552
9687
  }
@@ -9568,8 +9703,8 @@ function loadKnownHashes(eventsPath) {
9568
9703
  const cached = knownHashesCache.get(eventsPath);
9569
9704
  if (cached) return cached;
9570
9705
  const hashes = /* @__PURE__ */ new Set();
9571
- if (fs23.existsSync(eventsPath)) {
9572
- const content = fs23.readFileSync(eventsPath, "utf-8");
9706
+ if (fs25.existsSync(eventsPath)) {
9707
+ const content = fs25.readFileSync(eventsPath, "utf-8");
9573
9708
  const lines = content.split("\n").filter((line) => line.trim() !== "");
9574
9709
  for (const line of lines) {
9575
9710
  try {
@@ -9592,8 +9727,8 @@ async function emitEvent(projectPath, event, options) {
9592
9727
  const dirResult = await getStateDir(projectPath, options?.stream, options?.session);
9593
9728
  if (!dirResult.ok) return dirResult;
9594
9729
  const stateDir = dirResult.value;
9595
- const eventsPath = path20.join(stateDir, EVENTS_FILE);
9596
- fs23.mkdirSync(stateDir, { recursive: true });
9730
+ const eventsPath = path22.join(stateDir, EVENTS_FILE);
9731
+ fs25.mkdirSync(stateDir, { recursive: true });
9597
9732
  const contentHash = computeEventHash(event, options?.session);
9598
9733
  const knownHashes = loadKnownHashes(eventsPath);
9599
9734
  if (knownHashes.has(contentHash)) {
@@ -9607,7 +9742,7 @@ async function emitEvent(projectPath, event, options) {
9607
9742
  if (options?.session) {
9608
9743
  fullEvent.session = options.session;
9609
9744
  }
9610
- fs23.appendFileSync(eventsPath, JSON.stringify(fullEvent) + "\n");
9745
+ fs25.appendFileSync(eventsPath, JSON.stringify(fullEvent) + "\n");
9611
9746
  knownHashes.add(contentHash);
9612
9747
  return Ok({ written: true });
9613
9748
  } catch (error) {
@@ -9621,11 +9756,11 @@ async function loadEvents(projectPath, options) {
9621
9756
  const dirResult = await getStateDir(projectPath, options?.stream, options?.session);
9622
9757
  if (!dirResult.ok) return dirResult;
9623
9758
  const stateDir = dirResult.value;
9624
- const eventsPath = path20.join(stateDir, EVENTS_FILE);
9625
- if (!fs23.existsSync(eventsPath)) {
9759
+ const eventsPath = path22.join(stateDir, EVENTS_FILE);
9760
+ if (!fs25.existsSync(eventsPath)) {
9626
9761
  return Ok([]);
9627
9762
  }
9628
- const content = fs23.readFileSync(eventsPath, "utf-8");
9763
+ const content = fs25.readFileSync(eventsPath, "utf-8");
9629
9764
  const lines = content.split("\n").filter((line) => line.trim() !== "");
9630
9765
  const events = [];
9631
9766
  for (const line of lines) {
@@ -9874,11 +10009,11 @@ function nodeSubStacks(allDeps) {
9874
10009
  return found;
9875
10010
  }
9876
10011
  function detectNodeStacks(projectRoot) {
9877
- const pkgJsonPath = path21.join(projectRoot, "package.json");
9878
- if (!fs24.existsSync(pkgJsonPath)) return [];
10012
+ const pkgJsonPath = path23.join(projectRoot, "package.json");
10013
+ if (!fs26.existsSync(pkgJsonPath)) return [];
9879
10014
  const stacks = ["node"];
9880
10015
  try {
9881
- const pkgJson = JSON.parse(fs24.readFileSync(pkgJsonPath, "utf-8"));
10016
+ const pkgJson = JSON.parse(fs26.readFileSync(pkgJsonPath, "utf-8"));
9882
10017
  const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };
9883
10018
  stacks.push(...nodeSubStacks(allDeps));
9884
10019
  } catch {
@@ -9887,10 +10022,10 @@ function detectNodeStacks(projectRoot) {
9887
10022
  }
9888
10023
  function detectStack(projectRoot) {
9889
10024
  const stacks = [...detectNodeStacks(projectRoot)];
9890
- if (fs24.existsSync(path21.join(projectRoot, "go.mod"))) {
10025
+ if (fs26.existsSync(path23.join(projectRoot, "go.mod"))) {
9891
10026
  stacks.push("go");
9892
10027
  }
9893
- const hasPython = fs24.existsSync(path21.join(projectRoot, "requirements.txt")) || fs24.existsSync(path21.join(projectRoot, "pyproject.toml"));
10028
+ const hasPython = fs26.existsSync(path23.join(projectRoot, "requirements.txt")) || fs26.existsSync(path23.join(projectRoot, "pyproject.toml"));
9894
10029
  if (hasPython) {
9895
10030
  stacks.push("python");
9896
10031
  }
@@ -9933,7 +10068,7 @@ function getInjectionPatterns() {
9933
10068
  }
9934
10069
  function getTaintFilePath(projectRoot, sessionId) {
9935
10070
  const id = sessionId || DEFAULT_SESSION_ID;
9936
- return join362(projectRoot, ".harness", `session-taint-${id}.json`);
10071
+ return join382(projectRoot, ".harness", `session-taint-${id}.json`);
9937
10072
  }
9938
10073
  function readTaint(projectRoot, sessionId) {
9939
10074
  const filePath = getTaintFilePath(projectRoot, sessionId);
@@ -10015,14 +10150,14 @@ function clearTaint(projectRoot, sessionId) {
10015
10150
  return 0;
10016
10151
  }
10017
10152
  }
10018
- const harnessDir = join362(projectRoot, ".harness");
10153
+ const harnessDir = join382(projectRoot, ".harness");
10019
10154
  let count = 0;
10020
10155
  try {
10021
10156
  const files = readdirSync3(harnessDir);
10022
10157
  for (const file of files) {
10023
10158
  if (file.startsWith("session-taint-") && file.endsWith(".json")) {
10024
10159
  try {
10025
- unlinkSync2(join362(harnessDir, file));
10160
+ unlinkSync2(join382(harnessDir, file));
10026
10161
  count++;
10027
10162
  } catch {
10028
10163
  }
@@ -10033,7 +10168,7 @@ function clearTaint(projectRoot, sessionId) {
10033
10168
  return count;
10034
10169
  }
10035
10170
  function listTaintedSessions(projectRoot) {
10036
- const harnessDir = join362(projectRoot, ".harness");
10171
+ const harnessDir = join382(projectRoot, ".harness");
10037
10172
  const sessions = [];
10038
10173
  try {
10039
10174
  const files = readdirSync3(harnessDir);
@@ -10105,7 +10240,7 @@ function securityFindingId(finding) {
10105
10240
  }
10106
10241
  async function runValidateCheck(projectRoot, config) {
10107
10242
  const issues = [];
10108
- const agentsPath = path22.join(projectRoot, config.agentsMapPath ?? "AGENTS.md");
10243
+ const agentsPath = path24.join(projectRoot, config.agentsMapPath ?? "AGENTS.md");
10109
10244
  const result = await validateAgentsMap(agentsPath);
10110
10245
  if (!result.ok) {
10111
10246
  issues.push({ severity: "error", message: result.error.message });
@@ -10162,7 +10297,7 @@ async function runDepsCheck(projectRoot, config) {
10162
10297
  }
10163
10298
  async function runDocsCheck(projectRoot, config) {
10164
10299
  const issues = [];
10165
- const docsDir = path22.join(projectRoot, config.docsDir ?? "docs");
10300
+ const docsDir = path24.join(projectRoot, config.docsDir ?? "docs");
10166
10301
  const entropyConfig = config.entropy || {};
10167
10302
  const result = await checkDocCoverage("project", {
10168
10303
  docsDir,
@@ -10347,7 +10482,7 @@ async function runTraceabilityCheck(projectRoot, config) {
10347
10482
  const issues = [];
10348
10483
  const traceConfig = config.traceability || {};
10349
10484
  if (traceConfig.enabled === false) return issues;
10350
- const graphDir = path22.join(projectRoot, ".harness", "graph");
10485
+ const graphDir = path24.join(projectRoot, ".harness", "graph");
10351
10486
  const store = new GraphStore();
10352
10487
  const loaded = await store.load(graphDir);
10353
10488
  if (!loaded) {
@@ -10525,7 +10660,7 @@ async function runMechanicalChecks(options) {
10525
10660
  };
10526
10661
  if (!skip.includes("validate")) {
10527
10662
  try {
10528
- const agentsPath = path23.join(projectRoot, config.agentsMapPath ?? "AGENTS.md");
10663
+ const agentsPath = path25.join(projectRoot, config.agentsMapPath ?? "AGENTS.md");
10529
10664
  const result = await validateAgentsMap(agentsPath);
10530
10665
  if (!result.ok) {
10531
10666
  statuses.validate = "fail";
@@ -10562,7 +10697,7 @@ async function runMechanicalChecks(options) {
10562
10697
  statuses.validate = "fail";
10563
10698
  findings.push({
10564
10699
  tool: "validate",
10565
- file: path23.join(projectRoot, "AGENTS.md"),
10700
+ file: path25.join(projectRoot, "AGENTS.md"),
10566
10701
  message: err instanceof Error ? err.message : String(err),
10567
10702
  severity: "error"
10568
10703
  });
@@ -10626,7 +10761,7 @@ async function runMechanicalChecks(options) {
10626
10761
  (async () => {
10627
10762
  const localFindings = [];
10628
10763
  try {
10629
- const docsDir = path23.join(projectRoot, config.docsDir ?? "docs");
10764
+ const docsDir = path25.join(projectRoot, config.docsDir ?? "docs");
10630
10765
  const result = await checkDocCoverage("project", { docsDir });
10631
10766
  if (!result.ok) {
10632
10767
  statuses["check-docs"] = "warn";
@@ -10653,7 +10788,7 @@ async function runMechanicalChecks(options) {
10653
10788
  statuses["check-docs"] = "warn";
10654
10789
  localFindings.push({
10655
10790
  tool: "check-docs",
10656
- file: path23.join(projectRoot, "docs"),
10791
+ file: path25.join(projectRoot, "docs"),
10657
10792
  message: err instanceof Error ? err.message : String(err),
10658
10793
  severity: "warning"
10659
10794
  });
@@ -10750,18 +10885,18 @@ function computeContextBudget(diffLines) {
10750
10885
  return diffLines;
10751
10886
  }
10752
10887
  function isWithinProject(absPath, projectRoot) {
10753
- const resolvedRoot = path24.resolve(projectRoot) + path24.sep;
10754
- const resolvedPath = path24.resolve(absPath);
10755
- return resolvedPath.startsWith(resolvedRoot) || resolvedPath === path24.resolve(projectRoot);
10888
+ const resolvedRoot = path26.resolve(projectRoot) + path26.sep;
10889
+ const resolvedPath = path26.resolve(absPath);
10890
+ return resolvedPath.startsWith(resolvedRoot) || resolvedPath === path26.resolve(projectRoot);
10756
10891
  }
10757
10892
  async function readContextFile(projectRoot, filePath, reason) {
10758
- const absPath = path24.isAbsolute(filePath) ? filePath : path24.join(projectRoot, filePath);
10893
+ const absPath = path26.isAbsolute(filePath) ? filePath : path26.join(projectRoot, filePath);
10759
10894
  if (!isWithinProject(absPath, projectRoot)) return null;
10760
10895
  const result = await readFileContent(absPath);
10761
10896
  if (!result.ok) return null;
10762
10897
  const content = result.value;
10763
10898
  const lines = content.split("\n").length;
10764
- const relPath2 = path24.isAbsolute(filePath) ? relativePosix(projectRoot, filePath) : filePath;
10899
+ const relPath2 = path26.isAbsolute(filePath) ? relativePosix(projectRoot, filePath) : filePath;
10765
10900
  return { path: relPath2, content, reason, lines };
10766
10901
  }
10767
10902
  function extractImportSources2(content) {
@@ -10776,18 +10911,18 @@ function extractImportSources2(content) {
10776
10911
  }
10777
10912
  async function resolveImportPath2(projectRoot, fromFile, importSource) {
10778
10913
  if (!importSource.startsWith(".")) return null;
10779
- const fromDir = path24.dirname(path24.join(projectRoot, fromFile));
10780
- const basePath = path24.resolve(fromDir, importSource);
10914
+ const fromDir = path26.dirname(path26.join(projectRoot, fromFile));
10915
+ const basePath = path26.resolve(fromDir, importSource);
10781
10916
  if (!isWithinProject(basePath, projectRoot)) return null;
10782
10917
  const relBase = relativePosix(projectRoot, basePath);
10783
10918
  const candidates = [
10784
10919
  relBase + ".ts",
10785
10920
  relBase + ".tsx",
10786
10921
  relBase + ".mts",
10787
- path24.join(relBase, "index.ts")
10922
+ path26.join(relBase, "index.ts")
10788
10923
  ];
10789
10924
  for (const candidate of candidates) {
10790
- const absCandidate = path24.join(projectRoot, candidate);
10925
+ const absCandidate = path26.join(projectRoot, candidate);
10791
10926
  if (await fileExists(absCandidate)) {
10792
10927
  return candidate;
10793
10928
  }
@@ -10795,7 +10930,7 @@ async function resolveImportPath2(projectRoot, fromFile, importSource) {
10795
10930
  return null;
10796
10931
  }
10797
10932
  async function findTestFiles(projectRoot, sourceFile) {
10798
- const baseName = path24.basename(sourceFile, path24.extname(sourceFile));
10933
+ const baseName = path26.basename(sourceFile, path26.extname(sourceFile));
10799
10934
  const pattern = `**/${baseName}.{test,spec}.{ts,tsx,mts}`;
10800
10935
  const results = await findFiles(pattern, projectRoot);
10801
10936
  return results.map((f) => relativePosix(projectRoot, f));
@@ -11563,7 +11698,7 @@ function normalizePath(filePath, projectRoot) {
11563
11698
  let normalized = filePath;
11564
11699
  normalized = normalized.replace(/\\/g, "/");
11565
11700
  const normalizedRoot = projectRoot.replace(/\\/g, "/");
11566
- if (path25.isAbsolute(normalized)) {
11701
+ if (path27.isAbsolute(normalized)) {
11567
11702
  const root = normalizedRoot.endsWith("/") ? normalizedRoot : normalizedRoot + "/";
11568
11703
  if (normalized.startsWith(root)) {
11569
11704
  normalized = normalized.slice(root.length);
@@ -11575,12 +11710,12 @@ function normalizePath(filePath, projectRoot) {
11575
11710
  return normalized;
11576
11711
  }
11577
11712
  function resolveImportPath22(currentFile, importPath) {
11578
- const dir = path25.dirname(currentFile);
11579
- let resolved = path25.join(dir, importPath).replace(/\\/g, "/");
11713
+ const dir = path27.dirname(currentFile);
11714
+ let resolved = path27.join(dir, importPath).replace(/\\/g, "/");
11580
11715
  if (!resolved.match(/\.(ts|tsx|js|jsx)$/)) {
11581
11716
  resolved += ".ts";
11582
11717
  }
11583
- return path25.normalize(resolved).replace(/\\/g, "/");
11718
+ return path27.normalize(resolved).replace(/\\/g, "/");
11584
11719
  }
11585
11720
  function enqueueImports(content, current, visited, queue, maxDepth) {
11586
11721
  const importRegex = /import\s+.*?from\s+['"]([^'"]+)['"]/g;
@@ -11612,7 +11747,7 @@ function isMechanicallyExcluded(finding, exclusionSet, projectRoot) {
11612
11747
  const normalizedFile = normalizePath(finding.file, projectRoot);
11613
11748
  if (exclusionSet.isExcluded(normalizedFile, finding.lineRange)) return true;
11614
11749
  if (exclusionSet.isExcluded(finding.file, finding.lineRange)) return true;
11615
- const absoluteFile = path25.isAbsolute(finding.file) ? finding.file : path25.join(projectRoot, finding.file).replace(/\\/g, "/");
11750
+ const absoluteFile = path27.isAbsolute(finding.file) ? finding.file : path27.join(projectRoot, finding.file).replace(/\\/g, "/");
11616
11751
  return exclusionSet.isExcluded(absoluteFile, finding.lineRange);
11617
11752
  }
11618
11753
  async function validateWithGraph(crossFileRefs, graph) {
@@ -12620,7 +12755,7 @@ function isRegression(from, to) {
12620
12755
  }
12621
12756
  function collectAutopilotStatuses(autopilotPath, featurePlans, allTaskStatuses) {
12622
12757
  try {
12623
- const raw = fs26.readFileSync(autopilotPath, "utf-8");
12758
+ const raw = fs28.readFileSync(autopilotPath, "utf-8");
12624
12759
  const autopilot = JSON.parse(raw);
12625
12760
  if (!autopilot.phases) return;
12626
12761
  const linkedPhases = autopilot.phases.filter(
@@ -12652,10 +12787,10 @@ function inferStatus(feature, projectPath, allFeatures) {
12652
12787
  const featuresWithPlans = allFeatures.filter((f) => f.plans.length > 0);
12653
12788
  const useRootState = featuresWithPlans.length <= 1;
12654
12789
  if (useRootState) {
12655
- const rootStatePath = path26.join(projectPath, ".harness", "state.json");
12656
- if (fs26.existsSync(rootStatePath)) {
12790
+ const rootStatePath = path28.join(projectPath, ".harness", "state.json");
12791
+ if (fs28.existsSync(rootStatePath)) {
12657
12792
  try {
12658
- const raw = fs26.readFileSync(rootStatePath, "utf-8");
12793
+ const raw = fs28.readFileSync(rootStatePath, "utf-8");
12659
12794
  const state = JSON.parse(raw);
12660
12795
  if (state.progress) {
12661
12796
  for (const status of Object.values(state.progress)) {
@@ -12666,14 +12801,14 @@ function inferStatus(feature, projectPath, allFeatures) {
12666
12801
  }
12667
12802
  }
12668
12803
  }
12669
- const sessionsDir = path26.join(projectPath, ".harness", "sessions");
12670
- if (fs26.existsSync(sessionsDir)) {
12804
+ const sessionsDir = path28.join(projectPath, ".harness", "sessions");
12805
+ if (fs28.existsSync(sessionsDir)) {
12671
12806
  try {
12672
- const sessionDirs = fs26.readdirSync(sessionsDir, { withFileTypes: true });
12807
+ const sessionDirs = fs28.readdirSync(sessionsDir, { withFileTypes: true });
12673
12808
  for (const entry of sessionDirs) {
12674
12809
  if (!entry.isDirectory()) continue;
12675
- const autopilotPath = path26.join(sessionsDir, entry.name, "autopilot-state.json");
12676
- if (!fs26.existsSync(autopilotPath)) continue;
12810
+ const autopilotPath = path28.join(sessionsDir, entry.name, "autopilot-state.json");
12811
+ if (!fs28.existsSync(autopilotPath)) continue;
12677
12812
  collectAutopilotStatuses(autopilotPath, feature.plans, allTaskStatuses);
12678
12813
  }
12679
12814
  } catch {
@@ -12788,9 +12923,9 @@ function isValidTrackerShape(tracker) {
12788
12923
  }
12789
12924
  function loadTrackerSyncConfig(projectRoot) {
12790
12925
  try {
12791
- const configPath = path27.join(projectRoot, "harness.config.json");
12792
- if (!fs27.existsSync(configPath)) return null;
12793
- const raw = fs27.readFileSync(configPath, "utf-8");
12926
+ const configPath = path29.join(projectRoot, "harness.config.json");
12927
+ if (!fs29.existsSync(configPath)) return null;
12928
+ const raw = fs29.readFileSync(configPath, "utf-8");
12794
12929
  const config = JSON.parse(raw);
12795
12930
  const tracker = config.roadmap?.tracker;
12796
12931
  if (!isValidTrackerShape(tracker)) return null;
@@ -12817,14 +12952,14 @@ function buildDedupIndex(tickets, config) {
12817
12952
  }
12818
12953
  return index;
12819
12954
  }
12820
- async function resolveExternalId(feature, milestone, adapter, dedupIndex, result) {
12955
+ async function resolveExternalId(feature, milestone, adapter2, dedupIndex, result) {
12821
12956
  if (feature.externalId) return true;
12822
12957
  const existing = dedupIndex.get(feature.name.toLowerCase());
12823
12958
  if (existing) {
12824
12959
  feature.externalId = existing.externalId;
12825
12960
  return true;
12826
12961
  }
12827
- const createResult = await adapter.createTicket(feature, milestone);
12962
+ const createResult = await adapter2.createTicket(feature, milestone);
12828
12963
  if (createResult.ok) {
12829
12964
  feature.externalId = createResult.value.externalId;
12830
12965
  result.created.push(createResult.value);
@@ -12833,7 +12968,7 @@ async function resolveExternalId(feature, milestone, adapter, dedupIndex, result
12833
12968
  }
12834
12969
  return false;
12835
12970
  }
12836
- async function syncToExternal(roadmap, adapter, config, prefetchedTickets) {
12971
+ async function syncToExternal(roadmap, adapter2, config, prefetchedTickets) {
12837
12972
  const result = emptySyncResult();
12838
12973
  const dedupIndex = buildDedupIndex(prefetchedTickets, config);
12839
12974
  for (const milestone of roadmap.milestones) {
@@ -12841,12 +12976,12 @@ async function syncToExternal(roadmap, adapter, config, prefetchedTickets) {
12841
12976
  const shouldUpdate = await resolveExternalId(
12842
12977
  feature,
12843
12978
  milestone.name,
12844
- adapter,
12979
+ adapter2,
12845
12980
  dedupIndex,
12846
12981
  result
12847
12982
  );
12848
12983
  if (!shouldUpdate) continue;
12849
- const updateResult = await adapter.updateTicket(feature.externalId, feature, milestone.name);
12984
+ const updateResult = await adapter2.updateTicket(feature.externalId, feature, milestone.name);
12850
12985
  if (updateResult.ok) {
12851
12986
  result.updated.push(feature.externalId);
12852
12987
  } else {
@@ -12872,7 +13007,7 @@ function applyTicketToFeature(ticketState, feature, config, forceSync, result) {
12872
13007
  if (!forceSync && feature.status === "blocked" && newStatus === "planned") return;
12873
13008
  feature.status = newStatus;
12874
13009
  }
12875
- async function syncFromExternal(roadmap, adapter, config, options, prefetchedTickets) {
13010
+ async function syncFromExternal(roadmap, adapter2, config, options, prefetchedTickets) {
12876
13011
  const result = emptySyncResult();
12877
13012
  const forceSync = options?.forceSync ?? false;
12878
13013
  const featureByExternalId = /* @__PURE__ */ new Map();
@@ -12888,7 +13023,7 @@ async function syncFromExternal(roadmap, adapter, config, options, prefetchedTic
12888
13023
  if (prefetchedTickets) {
12889
13024
  tickets = prefetchedTickets;
12890
13025
  } else {
12891
- const fetchResult = await adapter.fetchAllTickets();
13026
+ const fetchResult = await adapter2.fetchAllTickets();
12892
13027
  if (!fetchResult.ok) {
12893
13028
  result.errors.push({ featureOrId: "*", error: fetchResult.error });
12894
13029
  return result;
@@ -12902,7 +13037,7 @@ async function syncFromExternal(roadmap, adapter, config, options, prefetchedTic
12902
13037
  }
12903
13038
  return result;
12904
13039
  }
12905
- async function fullSync(roadmapPath, adapter, config, options) {
13040
+ async function fullSync(roadmapPath, adapter2, config, options) {
12906
13041
  const previousSync = syncMutex;
12907
13042
  let releaseMutex;
12908
13043
  syncMutex = new Promise((resolve8) => {
@@ -12910,7 +13045,7 @@ async function fullSync(roadmapPath, adapter, config, options) {
12910
13045
  });
12911
13046
  await previousSync;
12912
13047
  try {
12913
- const raw = fs28.readFileSync(roadmapPath, "utf-8");
13048
+ const raw = fs30.readFileSync(roadmapPath, "utf-8");
12914
13049
  const parseResult = parseRoadmap(raw);
12915
13050
  if (!parseResult.ok) {
12916
13051
  return {
@@ -12919,11 +13054,11 @@ async function fullSync(roadmapPath, adapter, config, options) {
12919
13054
  };
12920
13055
  }
12921
13056
  const roadmap = parseResult.value;
12922
- const fetchResult = await adapter.fetchAllTickets();
13057
+ const fetchResult = await adapter2.fetchAllTickets();
12923
13058
  const tickets = fetchResult.ok ? fetchResult.value : void 0;
12924
- const pushResult = await syncToExternal(roadmap, adapter, config, tickets);
12925
- const pullResult = await syncFromExternal(roadmap, adapter, config, options);
12926
- fs28.writeFileSync(roadmapPath, serializeRoadmap(roadmap), "utf-8");
13059
+ const pushResult = await syncToExternal(roadmap, adapter2, config, tickets);
13060
+ const pullResult = await syncFromExternal(roadmap, adapter2, config, options);
13061
+ fs30.writeFileSync(roadmapPath, serializeRoadmap(roadmap), "utf-8");
12927
13062
  return {
12928
13063
  created: pushResult.created,
12929
13064
  updated: pushResult.updated,
@@ -13045,7 +13180,7 @@ function assignFeature(roadmap, feature, assignee, date) {
13045
13180
  }
13046
13181
  function getStatePath() {
13047
13182
  const home = process.env["HOME"] || os.homedir();
13048
- return path30.join(home, ".harness", "update-check.json");
13183
+ return path32.join(home, ".harness", "update-check.json");
13049
13184
  }
13050
13185
  function isUpdateCheckEnabled(configInterval) {
13051
13186
  if (process.env["HARNESS_NO_UPDATE_CHECK"] === "1") return false;
@@ -13058,7 +13193,7 @@ function shouldRunCheck(state, intervalMs) {
13058
13193
  }
13059
13194
  function readCheckState() {
13060
13195
  try {
13061
- const raw = fs31.readFileSync(getStatePath(), "utf-8");
13196
+ const raw = fs33.readFileSync(getStatePath(), "utf-8");
13062
13197
  const parsed = JSON.parse(raw);
13063
13198
  if (typeof parsed === "object" && parsed !== null && "lastCheckTime" in parsed && typeof parsed.lastCheckTime === "number" && "currentVersion" in parsed && typeof parsed.currentVersion === "string") {
13064
13199
  const state = parsed;
@@ -13075,7 +13210,7 @@ function readCheckState() {
13075
13210
  }
13076
13211
  function spawnBackgroundCheck(currentVersion) {
13077
13212
  const statePath = getStatePath();
13078
- const stateDir = path30.dirname(statePath);
13213
+ const stateDir = path32.dirname(statePath);
13079
13214
  const script = `
13080
13215
  const { execSync } = require('child_process');
13081
13216
  const fs = require('fs');
@@ -13318,14 +13453,14 @@ function getModelPrice(model, dataset) {
13318
13453
  return pricing;
13319
13454
  }
13320
13455
  function getCachePath(projectRoot) {
13321
- return path31.join(projectRoot, ".harness", "cache", "pricing.json");
13456
+ return path33.join(projectRoot, ".harness", "cache", "pricing.json");
13322
13457
  }
13323
13458
  function getStalenessMarkerPath(projectRoot) {
13324
- return path31.join(projectRoot, ".harness", "cache", "staleness-marker.json");
13459
+ return path33.join(projectRoot, ".harness", "cache", "staleness-marker.json");
13325
13460
  }
13326
13461
  async function readDiskCache(projectRoot) {
13327
13462
  try {
13328
- const raw = await fs32.readFile(getCachePath(projectRoot), "utf-8");
13463
+ const raw = await fs34.readFile(getCachePath(projectRoot), "utf-8");
13329
13464
  return JSON.parse(raw);
13330
13465
  } catch {
13331
13466
  return null;
@@ -13333,8 +13468,8 @@ async function readDiskCache(projectRoot) {
13333
13468
  }
13334
13469
  async function writeDiskCache(projectRoot, data) {
13335
13470
  const cachePath = getCachePath(projectRoot);
13336
- await fs32.mkdir(path31.dirname(cachePath), { recursive: true });
13337
- await fs32.writeFile(cachePath, JSON.stringify(data, null, 2));
13471
+ await fs34.mkdir(path33.dirname(cachePath), { recursive: true });
13472
+ await fs34.writeFile(cachePath, JSON.stringify(data, null, 2));
13338
13473
  }
13339
13474
  async function fetchFromNetwork() {
13340
13475
  try {
@@ -13361,7 +13496,7 @@ function loadFallbackDataset() {
13361
13496
  async function checkAndWarnStaleness(projectRoot) {
13362
13497
  const markerPath = getStalenessMarkerPath(projectRoot);
13363
13498
  try {
13364
- const raw = await fs32.readFile(markerPath, "utf-8");
13499
+ const raw = await fs34.readFile(markerPath, "utf-8");
13365
13500
  const marker = JSON.parse(raw);
13366
13501
  const firstUse = new Date(marker.firstFallbackUse).getTime();
13367
13502
  const now = Date.now();
@@ -13373,8 +13508,8 @@ async function checkAndWarnStaleness(projectRoot) {
13373
13508
  }
13374
13509
  } catch {
13375
13510
  try {
13376
- await fs32.mkdir(path31.dirname(markerPath), { recursive: true });
13377
- await fs32.writeFile(
13511
+ await fs34.mkdir(path33.dirname(markerPath), { recursive: true });
13512
+ await fs34.writeFile(
13378
13513
  markerPath,
13379
13514
  JSON.stringify({ firstFallbackUse: (/* @__PURE__ */ new Date()).toISOString() })
13380
13515
  );
@@ -13384,7 +13519,7 @@ async function checkAndWarnStaleness(projectRoot) {
13384
13519
  }
13385
13520
  async function clearStalenessMarker(projectRoot) {
13386
13521
  try {
13387
- await fs32.unlink(getStalenessMarkerPath(projectRoot));
13522
+ await fs34.unlink(getStalenessMarkerPath(projectRoot));
13388
13523
  } catch {
13389
13524
  }
13390
13525
  }
@@ -13621,10 +13756,10 @@ function parseLine(line, lineNumber) {
13621
13756
  return record;
13622
13757
  }
13623
13758
  function readCostRecords(projectRoot) {
13624
- const costsFile = path32.join(projectRoot, ".harness", "metrics", "costs.jsonl");
13759
+ const costsFile = path34.join(projectRoot, ".harness", "metrics", "costs.jsonl");
13625
13760
  let raw;
13626
13761
  try {
13627
- raw = fs33.readFileSync(costsFile, "utf-8");
13762
+ raw = fs35.readFileSync(costsFile, "utf-8");
13628
13763
  } catch {
13629
13764
  return [];
13630
13765
  }
@@ -13674,7 +13809,7 @@ function parseCCLine(line, filePath, lineNumber) {
13674
13809
  entry = JSON.parse(line);
13675
13810
  } catch {
13676
13811
  console.warn(
13677
- `[harness usage] Skipping malformed CC JSONL line ${lineNumber} in ${path33.basename(filePath)}`
13812
+ `[harness usage] Skipping malformed CC JSONL line ${lineNumber} in ${path35.basename(filePath)}`
13678
13813
  );
13679
13814
  return null;
13680
13815
  }
@@ -13688,7 +13823,7 @@ function parseCCLine(line, filePath, lineNumber) {
13688
13823
  function readCCFile(filePath) {
13689
13824
  let raw;
13690
13825
  try {
13691
- raw = fs34.readFileSync(filePath, "utf-8");
13826
+ raw = fs36.readFileSync(filePath, "utf-8");
13692
13827
  } catch {
13693
13828
  return [];
13694
13829
  }
@@ -13710,10 +13845,10 @@ function readCCFile(filePath) {
13710
13845
  }
13711
13846
  function parseCCRecords() {
13712
13847
  const homeDir = process.env.HOME ?? os2.homedir();
13713
- const projectsDir = path33.join(homeDir, ".claude", "projects");
13848
+ const projectsDir = path35.join(homeDir, ".claude", "projects");
13714
13849
  let projectDirs;
13715
13850
  try {
13716
- projectDirs = fs34.readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path33.join(projectsDir, d.name));
13851
+ projectDirs = fs36.readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path35.join(projectsDir, d.name));
13717
13852
  } catch {
13718
13853
  return [];
13719
13854
  }
@@ -13721,7 +13856,7 @@ function parseCCRecords() {
13721
13856
  for (const dir of projectDirs) {
13722
13857
  let files;
13723
13858
  try {
13724
- files = fs34.readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => path33.join(dir, f));
13859
+ files = fs36.readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => path35.join(dir, f));
13725
13860
  } catch {
13726
13861
  continue;
13727
13862
  }
@@ -13749,10 +13884,10 @@ function parseLine2(line, lineNumber) {
13749
13884
  }
13750
13885
  }
13751
13886
  function readAdoptionRecords(projectRoot) {
13752
- const adoptionFile = path34.join(projectRoot, ".harness", "metrics", "adoption.jsonl");
13887
+ const adoptionFile = path36.join(projectRoot, ".harness", "metrics", "adoption.jsonl");
13753
13888
  let raw;
13754
13889
  try {
13755
- raw = fs35.readFileSync(adoptionFile, "utf-8");
13890
+ raw = fs37.readFileSync(adoptionFile, "utf-8");
13756
13891
  } catch {
13757
13892
  return [];
13758
13893
  }
@@ -13900,25 +14035,25 @@ function resolveStability(contentType) {
13900
14035
  return STABILITY_LOOKUP[contentType] ?? "ephemeral";
13901
14036
  }
13902
14037
  function getOrCreateInstallId(projectRoot) {
13903
- const harnessDir = path35.join(projectRoot, ".harness");
13904
- const installIdFile = path35.join(harnessDir, ".install-id");
14038
+ const harnessDir = path37.join(projectRoot, ".harness");
14039
+ const installIdFile = path37.join(harnessDir, ".install-id");
13905
14040
  const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
13906
14041
  try {
13907
- const existing = fs36.readFileSync(installIdFile, "utf-8").trim();
14042
+ const existing = fs38.readFileSync(installIdFile, "utf-8").trim();
13908
14043
  if (UUID_V4_RE.test(existing)) {
13909
14044
  return existing;
13910
14045
  }
13911
14046
  } catch {
13912
14047
  }
13913
14048
  const id = crypto4.randomUUID();
13914
- fs36.mkdirSync(harnessDir, { recursive: true });
13915
- fs36.writeFileSync(installIdFile, id, { encoding: "utf-8", mode: 384 });
14049
+ fs38.mkdirSync(harnessDir, { recursive: true });
14050
+ fs38.writeFileSync(installIdFile, id, { encoding: "utf-8", mode: 384 });
13916
14051
  return id;
13917
14052
  }
13918
14053
  function parseIdentityFromTelemetryFile(filePath) {
13919
14054
  const identity = {};
13920
14055
  try {
13921
- const raw = fs37.readFileSync(filePath, "utf-8");
14056
+ const raw = fs39.readFileSync(filePath, "utf-8");
13922
14057
  const parsed = JSON.parse(raw);
13923
14058
  const src = parsed?.identity;
13924
14059
  if (!src || typeof src !== "object") return identity;
@@ -13931,7 +14066,7 @@ function parseIdentityFromTelemetryFile(filePath) {
13931
14066
  }
13932
14067
  function readProjectNameFallback(configPath) {
13933
14068
  try {
13934
- const raw = fs37.readFileSync(configPath, "utf-8");
14069
+ const raw = fs39.readFileSync(configPath, "utf-8");
13935
14070
  const config = JSON.parse(raw);
13936
14071
  return typeof config?.name === "string" ? config.name : void 0;
13937
14072
  } catch {
@@ -13952,10 +14087,10 @@ function readGitAliasFallback(cwd) {
13952
14087
  }
13953
14088
  }
13954
14089
  function readIdentity(projectRoot) {
13955
- const filePath = path36.join(projectRoot, ".harness", "telemetry.json");
14090
+ const filePath = path38.join(projectRoot, ".harness", "telemetry.json");
13956
14091
  const identity = parseIdentityFromTelemetryFile(filePath);
13957
14092
  if (!identity.project) {
13958
- const fallbackProject = readProjectNameFallback(path36.join(projectRoot, "harness.config.json"));
14093
+ const fallbackProject = readProjectNameFallback(path38.join(projectRoot, "harness.config.json"));
13959
14094
  if (fallbackProject) identity.project = fallbackProject;
13960
14095
  }
13961
14096
  if (!identity.alias) {
@@ -14025,7 +14160,557 @@ async function send(events, apiKey) {
14025
14160
  }
14026
14161
  }
14027
14162
  }
14028
- var VALID_TYPES, CONVENTIONAL_PATTERN, DEFAULT_AGNIX_TIMEOUT_MS, HARNESS_AGNIX_DISABLE, HARNESS_AGNIX_BIN, CLAUDE_MD_WARN_BYTES, CLAUDE_MD_ERROR_BYTES, CONTEXT_FILES, MIN_DESCRIPTION_LENGTH, SETTINGS_PATHS, KNOWN_HOOK_EVENTS, MCP_SETTINGS_FILES, REQUIRED_SECTIONS, SETTINGS_FILES, KNOWN_AGNIX_TOOLS, DEFAULT_SECTIONS, DEFAULT_RATIOS, NODE_TYPE_TO_CATEGORY, SECTION_LEVEL_MAP, DEFAULT_LEVEL, DEFAULT_BUDGET, DEFAULT_LOADER_CONFIG, LEVEL_FRACTIONS, PHASE_PRIORITIES, ManifestSchema, BundleConstraintsSchema, BundleSchema, ContributionsSchema, LockfilePackageSchema, LockfileSchema, SharableLayerSchema, SharableForbiddenImportSchema, SharableBoundaryConfigSchema, SharableSecurityRulesSchema, VALID_SCOPES, LINE_PATTERN, START_PATTERN, END_PATTERN, CODE_BLOCK_LANGUAGES, DEFAULT_DRIFT_CONFIG, FILE_TYPES, EXPORT_TYPES, CONVENTION_DESCRIPTIONS, RULE_CHECKERS, EntropyAnalyzer, readFile42, writeFile32, unlink22, mkdir22, copyFile2, DEFAULT_FIX_CONFIG, EXPORT_TYPE_KEYWORD, ALWAYS_UNSAFE_TYPES, idCounter, DEAD_CODE_FIX_ACTIONS, MustExportRuleSchema, MustExportDefaultRuleSchema, NoExportRuleSchema, MustImportRuleSchema, NoImportRuleSchema, NamingRuleSchema, MaxExportsRuleSchema, MaxLinesRuleSchema, RequireJSDocRuleSchema, RuleSchema, ConfigPatternSchema, PatternConfigSchema, DriftConfigSchema, DeadCodeConfigSchema, EntropyConfigSchema, BaselineManager, BenchmarkRunner, RegressionDetector, SKIP_DIRS, SOURCE_EXTENSIONS, FUNCTION_DECL_RE, CONST_DECL_RE, CriticalPathResolver, NoOpTelemetryAdapter, NoOpExecutor, ConsoleSink, feedbackConfig, ChecklistBuilder, AgentActionEmitter, globalEmitter, FileSink, NoOpSink, CategorySnapshotSchema, TimelineSnapshotSchema, TimelineFileSchema, TrendLineSchema, TrendResultSchema, DEFAULT_STABILITY_THRESHOLDS, ALL_CATEGORIES, TimelineManager, ConfidenceTierSchema, RegressionResultSchema, DirectionSchema, CategoryForecastSchema, SpecImpactSignalsSchema, SpecImpactEstimateSchema, ContributingFeatureSchema, AdjustedForecastSchema, PredictionWarningSchema, StabilityForecastSchema, PredictionResultSchema, PredictionOptionsSchema, VALID_STATUSES, EM_DASH, VALID_PRIORITIES, ALL_CATEGORIES2, DIRECTION_THRESHOLD, PredictionEngine, DEFAULT_COEFFICIENTS, SpecImpactEstimator, EMPTY_HISTORY, ViolationHistoryManager, NORMALIZERS, MAX_SAMPLES, DEFAULT_WINDOW_WEEKS, DEFAULT_MIN_OCCURRENCES, FailureEntrySchema, HandoffSchema, GateCheckSchema, GateResultSchema, GateConfigSchema, HarnessStateSchema, DEFAULT_STATE, StreamInfoSchema, StreamIndexSchema, DEFAULT_STREAM_INDEX, HARNESS_DIR, STATE_FILE, LEARNINGS_FILE, FAILURES_FILE, HANDOFF_FILE, GATE_CONFIG_FILE, INDEX_FILE, SESSIONS_DIR, SESSION_INDEX_FILE, SUMMARY_FILE, SESSION_STATE_FILE, ARCHIVE_DIR, CONTENT_HASHES_FILE, EVENTS_FILE, STREAMS_DIR, STREAM_NAME_REGEX, branchCache, BRANCH_CACHE_TTL_MS, STATE_FILES, MAX_CACHE_ENTRIES, learningsCacheMap, WEIGHTS, LOCK_RETRIES, LOCK_BACKOFFS, PROMOTABLE_OUTCOMES, failuresCacheMap, FAILURE_LINE_REGEX, SAFE_GATE_COMMAND, SkillEventSchema, knownHashesCache, EVENT_FORMATTERS, RuleRegistry, DEFAULT_SECURITY_CONFIG, RuleOverrideSchema, SecurityConfigSchema, secretRules, injectionRules, xssRules, cryptoRules, pathTraversalRules, networkRules, deserializationRules, agentConfigRules, mcpRules, insecureDefaultsRules, sharpEdgesRules, nodeRules, expressRules, reactRules, goRules, SecurityScanner, hiddenUnicodePatterns, reRolingPatterns, permissionEscalationPatterns, encodedPayloadPatterns, indirectInjectionPatterns, contextManipulationPatterns, socialEngineeringPatterns, suspiciousPatterns, ALL_PATTERNS, DESTRUCTIVE_BASH, TAINT_DURATION_MS, DEFAULT_SESSION_ID, SecurityCategorySnapshotSchema, SupplyChainSnapshotSchema, SecurityTimelineSnapshotSchema, FindingLifecycleSchema, SecurityTimelineFileSchema, DirectionSchema2, SecurityTrendLineSchema, TrendAttributionSchema, SecurityTrendResultSchema, TimeToFixStatsSchema, TimeToFixResultSchema, EMPTY_SUPPLY_CHAIN, SecurityTimelineManager, ALL_CHECKS, STATUS_ICONS, CINotifier, ExclusionSet, PREFIX_PATTERNS, TEST_FILE_PATTERN, MD_FILE_PATTERN, ALL_DOMAINS, SECURITY_PATTERNS, SEVERITY_RANK, SEVERITY_ORDER, SEVERITY_LABELS, VALIDATED_BY_RANK, VALIDATION_SCORES, DOMAIN_BASELINES, FACTOR_WEIGHTS, EVIDENCE_SATURATION, CORROBORATED_AGREEMENT, STANDALONE_AGREEMENT, AGREEMENT_LINE_GAP, COMPLIANCE_DESCRIPTOR, EXPORT_RE, BUG_DETECTION_DESCRIPTOR, SECURITY_DESCRIPTOR, EVAL_PATTERN, SECRET_PATTERNS, SQL_CONCAT_PATTERN, SHELL_EXEC_PATTERN, ARCHITECTURE_DESCRIPTOR, LARGE_FILE_THRESHOLD, VIOLATION_FILE_RE, LEARNINGS_DESCRIPTOR, RELEVANCE_THRESHOLD, AGENT_DESCRIPTORS, AGENT_RUNNERS, DOWNGRADE_MAP, DEFAULT_PROVIDER_TIERS, SMALL_SUGGESTION_LINE_LIMIT, FILE_LINE_RANGE_PATTERN, FILE_LINE_PATTERN, FILE_ONLY_PATTERN, SECURITY_SENSITIVE_PATH, MIGRATION_PATH, TEST_PATH, CONFIG_PATH, STAGE_DOMAINS, EM_DASH2, STATUS_RANK, RETRY_DEFAULTS, GitHubIssuesSyncAdapter, syncMutex, PRIORITY_RANK, POSITION_WEIGHT, DEPENDENTS_WEIGHT, AFFINITY_WEIGHT, InteractionTypeSchema, QuestionSchema, ConfirmationSchema, TransitionSchema, EmitInteractionInputSchema, ProjectScanner, SHELL_TEMPLATE, STYLES, SCRIPTS, MockLLMService, llmService, ContentPipeline, BlueprintGenerator, TOKENS_PER_MILLION, fallback_default, LITELLM_PRICING_URL, CACHE_TTL_MS, STALENESS_WARNING_DAYS, MICRODOLLARS_PER_DOLLAR, TOKENS_PER_MILLION2, StructuralStrategy, DEFAULT_TOKEN_BUDGET, CHARS_PER_TOKEN, TRUNCATION_MARKER, TruncationStrategy, CompactionPipeline, STABILITY_LOOKUP, TIER_ORDER, AnthropicCacheAdapter, TIER_ORDER2, OpenAICacheAdapter, TIER_ORDER3, CACHED_CONTENT_MARKER, GeminiCacheAdapter, VERSION, POSTHOG_BATCH_URL, MAX_ATTEMPTS, TIMEOUT_MS;
14163
+ function acquireCompoundLock(category, opts = {}) {
14164
+ if (!KNOWN_CATEGORIES.has(category)) {
14165
+ throw new Error(
14166
+ `Unknown category "${category}". Must be one of: ${[...KNOWN_CATEGORIES].join(", ")}`
14167
+ );
14168
+ }
14169
+ const cwd = opts.cwd ?? process.cwd();
14170
+ const lockDir = path39.join(cwd, ".harness", "locks");
14171
+ fs40.mkdirSync(lockDir, { recursive: true });
14172
+ const lockPath = path39.join(lockDir, `compound-${category}.lock`);
14173
+ let fd;
14174
+ try {
14175
+ fd = fs40.openSync(lockPath, "wx");
14176
+ } catch (e) {
14177
+ const err = e;
14178
+ if (err.code === "EEXIST") {
14179
+ const holderPid = readHolderPid(lockPath);
14180
+ throw new CompoundLockHeldError(category, holderPid, lockPath);
14181
+ }
14182
+ throw err;
14183
+ }
14184
+ fs40.writeSync(fd, String(process.pid));
14185
+ fs40.closeSync(fd);
14186
+ let released = false;
14187
+ const release = () => {
14188
+ if (released) return;
14189
+ released = true;
14190
+ try {
14191
+ fs40.unlinkSync(lockPath);
14192
+ } catch {
14193
+ }
14194
+ process.removeListener("exit", onExit);
14195
+ process.removeListener("SIGINT", onSignal);
14196
+ process.removeListener("SIGTERM", onSignal);
14197
+ process.removeListener("uncaughtException", onUncaught);
14198
+ };
14199
+ const onExit = () => release();
14200
+ const onSignal = (sig) => {
14201
+ release();
14202
+ process.kill(process.pid, sig);
14203
+ };
14204
+ const onUncaught = (err) => {
14205
+ release();
14206
+ console.error(err && err.stack ? err.stack : err);
14207
+ process.exit(1);
14208
+ };
14209
+ process.once("exit", onExit);
14210
+ process.once("SIGINT", onSignal);
14211
+ process.once("SIGTERM", onSignal);
14212
+ process.once("uncaughtException", onUncaught);
14213
+ return { category, lockPath, release };
14214
+ }
14215
+ function readHolderPid(lockPath) {
14216
+ try {
14217
+ const raw = fs40.readFileSync(lockPath, "utf-8").trim();
14218
+ const n = Number.parseInt(raw, 10);
14219
+ return Number.isFinite(n) ? n : -1;
14220
+ } catch {
14221
+ return -1;
14222
+ }
14223
+ }
14224
+ function isSanitizedResult(value) {
14225
+ if (!value || typeof value !== "object") return false;
14226
+ const v = value;
14227
+ if (!v.fields || typeof v.fields !== "object") return false;
14228
+ for (const k of Object.keys(v.fields)) {
14229
+ if (!ALLOWED_SET.has(k)) return false;
14230
+ if (PII_FIELD_DENYLIST.test(k)) return false;
14231
+ }
14232
+ if (!v.distributions || typeof v.distributions !== "object") return false;
14233
+ return true;
14234
+ }
14235
+ function assertSanitized(value) {
14236
+ if (!isSanitizedResult(value)) {
14237
+ throw new Error("PII boundary violated: result is not a SanitizedResult");
14238
+ }
14239
+ }
14240
+ function writePulseConfig(config, opts) {
14241
+ PulseConfigSchema.parse(config);
14242
+ if (!fs41.existsSync(opts.configPath)) {
14243
+ throw new Error(`harness.config.json not found at ${opts.configPath}`);
14244
+ }
14245
+ const raw = fs41.readFileSync(opts.configPath, "utf-8");
14246
+ let parsed;
14247
+ try {
14248
+ parsed = JSON.parse(raw);
14249
+ } catch (e) {
14250
+ throw new Error(`Invalid JSON in ${opts.configPath}: ${e.message}`, { cause: e });
14251
+ }
14252
+ const bakPath = `${opts.configPath}.bak`;
14253
+ if (!opts.skipBackup && !fs41.existsSync(bakPath)) {
14254
+ fs41.writeFileSync(bakPath, raw, "utf-8");
14255
+ }
14256
+ parsed.pulse = config;
14257
+ const serialized = JSON.stringify(parsed, null, 2) + "\n";
14258
+ const tmpPath = `${opts.configPath}.tmp-${process.pid}`;
14259
+ fs41.writeFileSync(tmpPath, serialized, "utf-8");
14260
+ try {
14261
+ fs41.renameSync(tmpPath, opts.configPath);
14262
+ } catch (e) {
14263
+ try {
14264
+ fs41.unlinkSync(tmpPath);
14265
+ } catch {
14266
+ }
14267
+ throw e;
14268
+ }
14269
+ }
14270
+ function seedFromStrategy(opts = {}) {
14271
+ const cwd = opts.cwd ?? process.cwd();
14272
+ const strategyPath = path40.join(cwd, "STRATEGY.md");
14273
+ const warnings = [];
14274
+ if (!fs42.existsSync(strategyPath)) {
14275
+ return { name: null, keyMetrics: [], warnings: ["STRATEGY.md not found"] };
14276
+ }
14277
+ const raw = fs42.readFileSync(strategyPath, "utf-8");
14278
+ let name = null;
14279
+ const fmMatch = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
14280
+ const fm = fmMatch?.[1];
14281
+ if (fm !== void 0) {
14282
+ const nameMatch = /^name:\s*['"]?([^'"\n]+)['"]?\s*$/m.exec(fm);
14283
+ const nameCapture = nameMatch?.[1];
14284
+ if (nameCapture !== void 0) {
14285
+ name = nameCapture.trim();
14286
+ }
14287
+ }
14288
+ if (name === null) {
14289
+ const h1 = /^#\s+(.+)$/m.exec(raw);
14290
+ const h1Capture = h1?.[1];
14291
+ if (h1Capture !== void 0) {
14292
+ name = h1Capture.trim();
14293
+ warnings.push("STRATEGY.md frontmatter missing name; used H1 fallback");
14294
+ }
14295
+ }
14296
+ const keyMetrics = [];
14297
+ const headerMatch = /^##\s+Key metrics\s*$/m.exec(raw);
14298
+ if (headerMatch && headerMatch.index !== void 0) {
14299
+ const startIdx = headerMatch.index + headerMatch[0].length;
14300
+ const after = raw.slice(startIdx);
14301
+ const stopMatch = /^(#{1,3})\s+/m.exec(after);
14302
+ const block = stopMatch ? after.slice(0, stopMatch.index) : after;
14303
+ for (const line of block.split("\n")) {
14304
+ const m = /^[-*]\s+(.+)$/.exec(line.trim());
14305
+ const capture = m?.[1];
14306
+ if (capture !== void 0) keyMetrics.push(capture.trim());
14307
+ }
14308
+ } else {
14309
+ warnings.push("STRATEGY.md is missing a `## Key metrics` section");
14310
+ }
14311
+ return { name, keyMetrics, warnings };
14312
+ }
14313
+ function registerPulseAdapter(name, adapter2) {
14314
+ if (!adapter2 || typeof adapter2 !== "object") {
14315
+ throw new TypeError(`Pulse adapter "${name}" must be an object with query and sanitize.`);
14316
+ }
14317
+ if (typeof adapter2.query !== "function") {
14318
+ throw new TypeError(`Pulse adapter "${name}" is missing required field: query`);
14319
+ }
14320
+ if (typeof adapter2.sanitize !== "function") {
14321
+ throw new TypeError(`Pulse adapter "${name}" is missing required field: sanitize`);
14322
+ }
14323
+ if (REGISTRY.has(name)) {
14324
+ throw new PulseAdapterAlreadyRegisteredError(name);
14325
+ }
14326
+ REGISTRY.set(name, adapter2);
14327
+ }
14328
+ function getPulseAdapter(name) {
14329
+ return REGISTRY.get(name);
14330
+ }
14331
+ function listPulseAdapters() {
14332
+ return [...REGISTRY.keys()].sort();
14333
+ }
14334
+ function clearPulseAdapters() {
14335
+ REGISTRY.clear();
14336
+ }
14337
+ function registerMockAdapter() {
14338
+ if (listPulseAdapters().includes(MOCK_ADAPTER_NAME)) return;
14339
+ registerPulseAdapter(MOCK_ADAPTER_NAME, adapter);
14340
+ }
14341
+ function parseLookback(input) {
14342
+ const match = LOOKBACK_RE.exec(input);
14343
+ if (!match) {
14344
+ throw new Error(`Invalid lookback "${input}": expected format like "24h" or "7d"`);
14345
+ }
14346
+ const n = Number(match[1]);
14347
+ const unit = match[2];
14348
+ return unit === "h" ? n * 60 * 60 * 1e3 : n * 24 * 60 * 60 * 1e3;
14349
+ }
14350
+ function computeWindow(now, lookback, bufferMinutes = 15) {
14351
+ const lookbackMs = parseLookback(lookback);
14352
+ const bufferMs = bufferMinutes * 60 * 1e3;
14353
+ const end = new Date(now.getTime() - bufferMs);
14354
+ const start = new Date(end.getTime() - lookbackMs);
14355
+ return { start, end };
14356
+ }
14357
+ async function querySource(name, window) {
14358
+ const adapter2 = getPulseAdapter(name);
14359
+ if (!adapter2) {
14360
+ return {
14361
+ ok: false,
14362
+ skipKind: "no-adapter",
14363
+ reason: `no adapter registered for "${name}"`
14364
+ };
14365
+ }
14366
+ let sanitized;
14367
+ try {
14368
+ const raw = await adapter2.query(window);
14369
+ sanitized = adapter2.sanitize(raw);
14370
+ } catch (err) {
14371
+ return {
14372
+ ok: false,
14373
+ skipKind: "query-failure",
14374
+ reason: err instanceof Error ? err.message : String(err)
14375
+ };
14376
+ }
14377
+ try {
14378
+ assertSanitized(sanitized);
14379
+ } catch (err) {
14380
+ return {
14381
+ ok: false,
14382
+ skipKind: "pii-violation",
14383
+ reason: err instanceof Error ? err.message : String(err)
14384
+ };
14385
+ }
14386
+ return { ok: true, result: sanitized };
14387
+ }
14388
+ async function runPulse(config, window) {
14389
+ const startedAt = Date.now();
14390
+ const sources = [];
14391
+ const sourcesQueried = [];
14392
+ const sourcesSkipped = [];
14393
+ const parallelSlots = [
14394
+ ["analytics", config.sources.analytics],
14395
+ ["tracing", config.sources.tracing],
14396
+ ["payments", config.sources.payments]
14397
+ ];
14398
+ const parallelEntries = parallelSlots.filter(
14399
+ (slot) => slot[1] != null
14400
+ );
14401
+ const parallelResults = await Promise.all(
14402
+ parallelEntries.map(([kind, n]) => querySource(n, window).then((r) => [kind, n, r]))
14403
+ );
14404
+ for (const [kind, name, r] of parallelResults) {
14405
+ if (r.ok) {
14406
+ sources.push({ kind, name, result: r.result });
14407
+ sourcesQueried.push(name);
14408
+ } else {
14409
+ sourcesSkipped.push({ name, kind, skipKind: r.skipKind, reason: r.reason });
14410
+ }
14411
+ }
14412
+ if (config.sources.db.enabled && config.sources.db.source) {
14413
+ const name = config.sources.db.source;
14414
+ const r = await querySource(name, window);
14415
+ if (r.ok) {
14416
+ sources.push({ kind: "db", name, result: r.result });
14417
+ sourcesQueried.push(name);
14418
+ } else {
14419
+ sourcesSkipped.push({ name, kind: "db", skipKind: r.skipKind, reason: r.reason });
14420
+ }
14421
+ }
14422
+ return { sources, sourcesQueried, sourcesSkipped, durationMs: Date.now() - startedAt };
14423
+ }
14424
+ function loadTemplate() {
14425
+ try {
14426
+ const url = import.meta?.url;
14427
+ if (!url) return INLINE_TEMPLATE;
14428
+ const here = dirname18(fileURLToPath(url));
14429
+ return readFileSync36(join572(here, "template.md"), "utf-8");
14430
+ } catch {
14431
+ return INLINE_TEMPLATE;
14432
+ }
14433
+ }
14434
+ function totalCount(s) {
14435
+ const c = s.fields.count;
14436
+ return typeof c === "number" ? c : 0;
14437
+ }
14438
+ function buildHeadlines(r) {
14439
+ const total = r.sources.reduce((sum, s) => sum + totalCount(s.result), 0);
14440
+ return [
14441
+ `- ${r.sourcesQueried.length} source(s) queried in ${r.durationMs}ms`,
14442
+ `- ${total} total events recorded`,
14443
+ `- ${r.sourcesSkipped.length} source(s) skipped`
14444
+ ].join("\n");
14445
+ }
14446
+ function buildUsage(r) {
14447
+ if (r.sources.length === 0) return "_(none)_";
14448
+ return r.sources.map((s) => {
14449
+ const name = s.result.fields.event_name ?? "unknown";
14450
+ const count = totalCount(s.result);
14451
+ return `- ${name}: count=${count}`;
14452
+ }).join("\n");
14453
+ }
14454
+ function buildSystemPerformance(r) {
14455
+ const tracing = r.sources.find((s) => s.kind === "tracing") ?? null;
14456
+ if (!tracing) return "_(no tracing source configured)_";
14457
+ const dist = tracing.result.distributions;
14458
+ const lines = Object.entries(dist).map(([k, v]) => `- ${k}: ${JSON.stringify(v)}`);
14459
+ return lines.length > 0 ? lines.join("\n") : "_(no distributions)_";
14460
+ }
14461
+ function buildFollowups(r) {
14462
+ if (r.sourcesSkipped.length === 0) return "_(none)_";
14463
+ return r.sourcesSkipped.map((s) => `- ${s.name} skipped: ${s.reason}`).join("\n");
14464
+ }
14465
+ function finalPiiSweep(text) {
14466
+ return text.split("\n").filter((l) => {
14467
+ if (l.startsWith("# ") || l.startsWith("## ")) return true;
14468
+ return !PII_LINE_RE.test(l);
14469
+ }).join("\n");
14470
+ }
14471
+ function truncateSection(lines, startIdx, endIdx) {
14472
+ const head = lines.slice(0, startIdx + 1);
14473
+ const section = lines.slice(startIdx + 1, endIdx);
14474
+ const tail = lines.slice(endIdx);
14475
+ let truncated = false;
14476
+ while (head.length + section.length + tail.length + (truncated ? 0 : 1) > MAX_LINES && section.length > 0) {
14477
+ section.pop();
14478
+ truncated = true;
14479
+ }
14480
+ if (truncated) section.push(TRUNCATION_MARKER2);
14481
+ return [...head, ...section, ...tail];
14482
+ }
14483
+ function truncateToFit(text) {
14484
+ let lines = text.split("\n");
14485
+ if (lines.length <= MAX_LINES) return text;
14486
+ const sections = [
14487
+ { header: "## Followups" },
14488
+ { header: "## System performance" },
14489
+ { header: "## Usage" }
14490
+ ];
14491
+ for (const { header } of sections) {
14492
+ if (lines.length <= MAX_LINES) break;
14493
+ const startIdx = lines.findIndex((l) => l === header || l.startsWith(`${header} `));
14494
+ if (startIdx < 0) continue;
14495
+ let endIdx = lines.length;
14496
+ for (let i = startIdx + 1; i < lines.length; i++) {
14497
+ const line = lines[i];
14498
+ if (line !== void 0 && line.startsWith("## ")) {
14499
+ endIdx = i;
14500
+ break;
14501
+ }
14502
+ }
14503
+ lines = truncateSection(lines, startIdx, endIdx);
14504
+ }
14505
+ if (lines.length > MAX_LINES) lines = lines.slice(0, MAX_LINES);
14506
+ return lines.join("\n");
14507
+ }
14508
+ function assembleReport(result, productName, windowLabel) {
14509
+ const template = loadTemplate();
14510
+ const filled = template.replace("{{productName}}", productName).replace("{{windowLabel}}", windowLabel).replace("{{headlines}}", buildHeadlines(result)).replace("{{usage}}", buildUsage(result)).replace("{{systemPerformance}}", buildSystemPerformance(result)).replace("{{followups}}", buildFollowups(result));
14511
+ const swept = finalPiiSweep(filled);
14512
+ return truncateToFit(swept);
14513
+ }
14514
+ function extractHeadlines(report) {
14515
+ const lines = report.split("\n");
14516
+ const headlinesIdx = lines.findIndex((l) => l === "## Headlines" || l.startsWith("## Headlines"));
14517
+ if (headlinesIdx < 0) return lines.slice(0, 5).join("\n");
14518
+ let endIdx = lines.length;
14519
+ for (let i = headlinesIdx + 1; i < lines.length; i++) {
14520
+ const line = lines[i];
14521
+ if (line !== void 0 && line.startsWith("## ")) {
14522
+ endIdx = i;
14523
+ break;
14524
+ }
14525
+ }
14526
+ while (endIdx > headlinesIdx + 1 && lines[endIdx - 1] === "") endIdx--;
14527
+ return lines.slice(0, endIdx).join("\n");
14528
+ }
14529
+ function isoWeek(date) {
14530
+ const d = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
14531
+ const dayNum = d.getUTCDay() || 7;
14532
+ d.setUTCDate(d.getUTCDate() + 4 - dayNum);
14533
+ const year = d.getUTCFullYear();
14534
+ const yearStart = new Date(Date.UTC(year, 0, 1));
14535
+ const week = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
14536
+ return { year, week };
14537
+ }
14538
+ function formatIsoWeek(w) {
14539
+ return `${w.year}-W${String(w.week).padStart(2, "0")}`;
14540
+ }
14541
+ function normalizeSince(since) {
14542
+ const m = /^(\d+)(h|d|w|mo)$/i.exec(since.trim());
14543
+ if (!m) {
14544
+ throw new Error(
14545
+ `Invalid lookback "${since}": expected format like "24h", "7d", "4w", or "3mo"`
14546
+ );
14547
+ }
14548
+ const n = m[1];
14549
+ const unit = m[2]?.toLowerCase();
14550
+ switch (unit) {
14551
+ case "h":
14552
+ return `${n} hours ago`;
14553
+ case "d":
14554
+ return `${n} days ago`;
14555
+ case "w":
14556
+ return `${n} weeks ago`;
14557
+ case "mo":
14558
+ return `${n} months ago`;
14559
+ default:
14560
+ throw new Error(`Invalid lookback "${since}"`);
14561
+ }
14562
+ }
14563
+ async function readCommits(opts) {
14564
+ let stdout;
14565
+ try {
14566
+ const r = await execFileAsync(
14567
+ "git",
14568
+ ["log", `--since=${normalizeSince(opts.since)}`, "--name-only", "--format=%x1e%H%x1f%s"],
14569
+ { cwd: opts.cwd, maxBuffer: 16 * 1024 * 1024 }
14570
+ );
14571
+ stdout = r.stdout;
14572
+ } catch (err) {
14573
+ const msg = err instanceof Error ? err.message : String(err);
14574
+ if (EMPTY_REPO_RE.test(msg)) {
14575
+ process.stderr.write(`gitScan: empty repo or non-repo at ${opts.cwd}; returning []
14576
+ `);
14577
+ return [];
14578
+ }
14579
+ throw err;
14580
+ }
14581
+ const records = stdout.split("").filter((r) => r.trim().length > 0);
14582
+ return records.map((rec) => {
14583
+ const [header, ...fileLines] = rec.split("\n");
14584
+ const [sha, subject] = (header ?? "").split("");
14585
+ const files = fileLines.map((l) => l.trim()).filter((l) => l.length > 0);
14586
+ return { sha: sha ?? "", subject: subject ?? "", files };
14587
+ });
14588
+ }
14589
+ async function gitScan(opts) {
14590
+ const all = await readCommits(opts);
14591
+ const fixes = all.filter((c) => FIX_RE.test(c.subject));
14592
+ return fixes.map((c) => {
14593
+ const overlap = all.filter(
14594
+ (other) => other.sha !== c.sha && other.files.some((f) => c.files.includes(f))
14595
+ ).length;
14596
+ return {
14597
+ sha: c.sha,
14598
+ subject: c.subject,
14599
+ filesChanged: c.files.length,
14600
+ branchIterations: overlap
14601
+ };
14602
+ });
14603
+ }
14604
+ async function computeHotspots(opts) {
14605
+ let stdout;
14606
+ try {
14607
+ const r = await execFileAsync2(
14608
+ "git",
14609
+ ["log", `--since=${normalizeSince(opts.since)}`, "--name-only", "--format="],
14610
+ { cwd: opts.cwd, maxBuffer: 16 * 1024 * 1024 }
14611
+ );
14612
+ stdout = r.stdout;
14613
+ } catch {
14614
+ return [];
14615
+ }
14616
+ const counts = /* @__PURE__ */ new Map();
14617
+ for (const line of stdout.split("\n")) {
14618
+ const path42 = line.trim();
14619
+ if (path42.length === 0) continue;
14620
+ counts.set(path42, (counts.get(path42) ?? 0) + 1);
14621
+ }
14622
+ return [...counts.entries()].filter(([, c]) => c > opts.threshold).map(([path42, churn]) => ({ path: path42, churn })).sort((a, b) => b.churn - a.churn);
14623
+ }
14624
+ function tokenize(text) {
14625
+ return new Set(
14626
+ text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length > 2 && !STOPWORDS.has(t))
14627
+ );
14628
+ }
14629
+ async function* walk22(dir) {
14630
+ let entries;
14631
+ try {
14632
+ entries = await fs43.readdir(dir, { withFileTypes: true });
14633
+ } catch {
14634
+ return;
14635
+ }
14636
+ for (const e of entries) {
14637
+ const p = path41.join(dir, e.name);
14638
+ if (e.isDirectory()) yield* walk22(p);
14639
+ else if (e.isFile() && e.name.endsWith(".md")) yield p;
14640
+ }
14641
+ }
14642
+ async function readDocumentedTokens(solutionsDir) {
14643
+ const docs = [];
14644
+ for (const [track, categories] of TRACK_CATEGORIES2) {
14645
+ for (const category of categories) {
14646
+ const dir = path41.join(solutionsDir, track, category);
14647
+ for await (const file of walk22(dir)) {
14648
+ const raw = await fs43.readFile(file, "utf-8");
14649
+ const m = /^#\s+(.+)$/m.exec(raw);
14650
+ const title = m?.[1] ?? path41.basename(file, ".md");
14651
+ docs.push(tokenize(title));
14652
+ }
14653
+ }
14654
+ }
14655
+ return docs;
14656
+ }
14657
+ function jaccard(a, b) {
14658
+ if (a.size === 0 || b.size === 0) return 0;
14659
+ let inter = 0;
14660
+ for (const t of a) if (b.has(t)) inter++;
14661
+ const union = a.size + b.size - inter;
14662
+ return union === 0 ? 0 : inter / union;
14663
+ }
14664
+ async function crossReferenceUndocumentedFixes(commits, solutionsDir) {
14665
+ const documented = await readDocumentedTokens(solutionsDir);
14666
+ const OVERLAP_THRESHOLD = 0.4;
14667
+ return commits.filter((c) => {
14668
+ const tokens = tokenize(c.subject);
14669
+ return !documented.some((d) => jaccard(tokens, d) >= OVERLAP_THRESHOLD);
14670
+ });
14671
+ }
14672
+ function suggestCategory(subject) {
14673
+ for (const [re, cat] of KEYWORD_TO_CATEGORY) if (re.test(subject)) return cat;
14674
+ return "bug-track/logic-errors";
14675
+ }
14676
+ function descriptor(subject) {
14677
+ return subject.replace(/^fix(\([^)]+\))?:\s*/i, "").trim();
14678
+ }
14679
+ function assembleCandidateReport(input) {
14680
+ const week = formatIsoWeek(input.isoWeek);
14681
+ const lines = [];
14682
+ lines.push(`# Compound candidates \u2014 week ${week}`, "");
14683
+ lines.push(`## Undocumented fixes (from \`git log\` past ${input.lookback})`, "");
14684
+ if (input.undocumentedFixes.length === 0) {
14685
+ lines.push("_(none this week)_", "");
14686
+ } else {
14687
+ for (const c of input.undocumentedFixes) {
14688
+ const d = descriptor(c.subject);
14689
+ const cat = suggestCategory(c.subject);
14690
+ lines.push(
14691
+ `- **${c.subject}** (commit ${c.sha.slice(0, 7)}, ${c.filesChanged} file(s), ${c.branchIterations} related commits)`
14692
+ );
14693
+ lines.push(` - Suggested category: ${cat}`);
14694
+ lines.push(` - Run: \`/harness:compound "${d}"\``);
14695
+ }
14696
+ lines.push("");
14697
+ }
14698
+ lines.push("## Pattern candidates (from churn + hotspot analysis)", "");
14699
+ if (input.hotspotCandidates.length === 0) {
14700
+ lines.push("_(none this week)_", "");
14701
+ } else {
14702
+ for (const h of input.hotspotCandidates) {
14703
+ lines.push(
14704
+ `- File \`${h.path}\` has ${h.churn} commits in ${input.lookback}; no docs/solutions/ entry`
14705
+ );
14706
+ lines.push(" - Suggested category: knowledge-track/architecture-patterns");
14707
+ lines.push(` - Run: \`/harness:compound "${h.path} pattern"\``);
14708
+ }
14709
+ lines.push("");
14710
+ }
14711
+ return lines.join("\n");
14712
+ }
14713
+ var VALID_TYPES, CONVENTIONAL_PATTERN, LOOKBACK_PATTERN, PulseDbSourceSchema, PulseSourcesSchema, PulseConfigSchema, BUG_TRACK_CATEGORIES, KNOWLEDGE_TRACK_CATEGORIES, ALL_SOLUTION_CATEGORIES, ISO_DATE, BugTrackSchema, KnowledgeTrackSchema, BaseFrontmatter, SolutionDocFrontmatterSchema, TRACK_CATEGORIES, DEFAULT_AGNIX_TIMEOUT_MS, HARNESS_AGNIX_DISABLE, HARNESS_AGNIX_BIN, CLAUDE_MD_WARN_BYTES, CLAUDE_MD_ERROR_BYTES, CONTEXT_FILES, MIN_DESCRIPTION_LENGTH, SETTINGS_PATHS, KNOWN_HOOK_EVENTS, MCP_SETTINGS_FILES, REQUIRED_SECTIONS, SETTINGS_FILES, KNOWN_AGNIX_TOOLS, DEFAULT_SECTIONS, DEFAULT_RATIOS, NODE_TYPE_TO_CATEGORY, SECTION_LEVEL_MAP, DEFAULT_LEVEL, DEFAULT_BUDGET, DEFAULT_LOADER_CONFIG, LEVEL_FRACTIONS, PHASE_PRIORITIES, ManifestSchema, BundleConstraintsSchema, BundleSchema, ContributionsSchema, LockfilePackageSchema, LockfileSchema, SharableLayerSchema, SharableForbiddenImportSchema, SharableBoundaryConfigSchema, SharableSecurityRulesSchema, VALID_SCOPES, LINE_PATTERN, START_PATTERN, END_PATTERN, CODE_BLOCK_LANGUAGES, DEFAULT_DRIFT_CONFIG, FILE_TYPES, EXPORT_TYPES, CONVENTION_DESCRIPTIONS, RULE_CHECKERS, EntropyAnalyzer, readFile62, writeFile32, unlink22, mkdir22, copyFile2, DEFAULT_FIX_CONFIG, EXPORT_TYPE_KEYWORD, ALWAYS_UNSAFE_TYPES, idCounter, DEAD_CODE_FIX_ACTIONS, MustExportRuleSchema, MustExportDefaultRuleSchema, NoExportRuleSchema, MustImportRuleSchema, NoImportRuleSchema, NamingRuleSchema, MaxExportsRuleSchema, MaxLinesRuleSchema, RequireJSDocRuleSchema, RuleSchema, ConfigPatternSchema, PatternConfigSchema, DriftConfigSchema, DeadCodeConfigSchema, EntropyConfigSchema, BaselineManager, BenchmarkRunner, RegressionDetector, SKIP_DIRS, SOURCE_EXTENSIONS, FUNCTION_DECL_RE, CONST_DECL_RE, CriticalPathResolver, NoOpTelemetryAdapter, NoOpExecutor, ConsoleSink, feedbackConfig, ChecklistBuilder, AgentActionEmitter, globalEmitter, FileSink, NoOpSink, CategorySnapshotSchema, TimelineSnapshotSchema, TimelineFileSchema, TrendLineSchema, TrendResultSchema, DEFAULT_STABILITY_THRESHOLDS, ALL_CATEGORIES, TimelineManager, ConfidenceTierSchema, RegressionResultSchema, DirectionSchema, CategoryForecastSchema, SpecImpactSignalsSchema, SpecImpactEstimateSchema, ContributingFeatureSchema, AdjustedForecastSchema, PredictionWarningSchema, StabilityForecastSchema, PredictionResultSchema, PredictionOptionsSchema, VALID_STATUSES, EM_DASH, VALID_PRIORITIES, ALL_CATEGORIES2, DIRECTION_THRESHOLD, PredictionEngine, DEFAULT_COEFFICIENTS, SpecImpactEstimator, EMPTY_HISTORY, ViolationHistoryManager, NORMALIZERS, MAX_SAMPLES, DEFAULT_WINDOW_WEEKS, DEFAULT_MIN_OCCURRENCES, FailureEntrySchema, HandoffSchema, GateCheckSchema, GateResultSchema, GateConfigSchema, HarnessStateSchema, DEFAULT_STATE, StreamInfoSchema, StreamIndexSchema, DEFAULT_STREAM_INDEX, HARNESS_DIR, STATE_FILE, LEARNINGS_FILE, FAILURES_FILE, HANDOFF_FILE, GATE_CONFIG_FILE, INDEX_FILE, SESSIONS_DIR, SESSION_INDEX_FILE, SUMMARY_FILE, SESSION_STATE_FILE, ARCHIVE_DIR, CONTENT_HASHES_FILE, EVENTS_FILE, STREAMS_DIR, STREAM_NAME_REGEX, branchCache, BRANCH_CACHE_TTL_MS, STATE_FILES, MAX_CACHE_ENTRIES, learningsCacheMap, WEIGHTS, LOCK_RETRIES, LOCK_BACKOFFS, PROMOTABLE_OUTCOMES, failuresCacheMap, FAILURE_LINE_REGEX, SAFE_GATE_COMMAND, SkillEventSchema, knownHashesCache, EVENT_FORMATTERS, RuleRegistry, DEFAULT_SECURITY_CONFIG, RuleOverrideSchema, SecurityConfigSchema, secretRules, injectionRules, xssRules, cryptoRules, pathTraversalRules, networkRules, deserializationRules, agentConfigRules, mcpRules, insecureDefaultsRules, sharpEdgesRules, nodeRules, expressRules, reactRules, goRules, SecurityScanner, hiddenUnicodePatterns, reRolingPatterns, permissionEscalationPatterns, encodedPayloadPatterns, indirectInjectionPatterns, contextManipulationPatterns, socialEngineeringPatterns, suspiciousPatterns, ALL_PATTERNS, DESTRUCTIVE_BASH, TAINT_DURATION_MS, DEFAULT_SESSION_ID, SecurityCategorySnapshotSchema, SupplyChainSnapshotSchema, SecurityTimelineSnapshotSchema, FindingLifecycleSchema, SecurityTimelineFileSchema, DirectionSchema2, SecurityTrendLineSchema, TrendAttributionSchema, SecurityTrendResultSchema, TimeToFixStatsSchema, TimeToFixResultSchema, EMPTY_SUPPLY_CHAIN, SecurityTimelineManager, ALL_CHECKS, STATUS_ICONS, CINotifier, ExclusionSet, PREFIX_PATTERNS, TEST_FILE_PATTERN, MD_FILE_PATTERN, ALL_DOMAINS, SECURITY_PATTERNS, SEVERITY_RANK, SEVERITY_ORDER, SEVERITY_LABELS, VALIDATED_BY_RANK, VALIDATION_SCORES, DOMAIN_BASELINES, FACTOR_WEIGHTS, EVIDENCE_SATURATION, CORROBORATED_AGREEMENT, STANDALONE_AGREEMENT, AGREEMENT_LINE_GAP, COMPLIANCE_DESCRIPTOR, EXPORT_RE, BUG_DETECTION_DESCRIPTOR, SECURITY_DESCRIPTOR, EVAL_PATTERN, SECRET_PATTERNS, SQL_CONCAT_PATTERN, SHELL_EXEC_PATTERN, ARCHITECTURE_DESCRIPTOR, LARGE_FILE_THRESHOLD, VIOLATION_FILE_RE, LEARNINGS_DESCRIPTOR, RELEVANCE_THRESHOLD, AGENT_DESCRIPTORS, AGENT_RUNNERS, DOWNGRADE_MAP, DEFAULT_PROVIDER_TIERS, SMALL_SUGGESTION_LINE_LIMIT, FILE_LINE_RANGE_PATTERN, FILE_LINE_PATTERN, FILE_ONLY_PATTERN, SECURITY_SENSITIVE_PATH, MIGRATION_PATH, TEST_PATH, CONFIG_PATH, STAGE_DOMAINS, EM_DASH2, STATUS_RANK, RETRY_DEFAULTS, GitHubIssuesSyncAdapter, syncMutex, PRIORITY_RANK, POSITION_WEIGHT, DEPENDENTS_WEIGHT, AFFINITY_WEIGHT, InteractionTypeSchema, QuestionSchema, ConfirmationSchema, TransitionSchema, EmitInteractionInputSchema, ProjectScanner, SHELL_TEMPLATE, STYLES, SCRIPTS, MockLLMService, llmService, ContentPipeline, BlueprintGenerator, TOKENS_PER_MILLION, fallback_default, LITELLM_PRICING_URL, CACHE_TTL_MS, STALENESS_WARNING_DAYS, MICRODOLLARS_PER_DOLLAR, TOKENS_PER_MILLION2, StructuralStrategy, DEFAULT_TOKEN_BUDGET, CHARS_PER_TOKEN, TRUNCATION_MARKER, TruncationStrategy, CompactionPipeline, STABILITY_LOOKUP, TIER_ORDER, AnthropicCacheAdapter, TIER_ORDER2, OpenAICacheAdapter, TIER_ORDER3, CACHED_CONTENT_MARKER, GeminiCacheAdapter, VERSION, POSTHOG_BATCH_URL, MAX_ATTEMPTS, TIMEOUT_MS, CompoundLockHeldError, KNOWN_CATEGORIES, ALLOWED_FIELD_KEYS, PII_TOKENS, PII_FIELD_DENYLIST, PII_LINE_RE, ALLOWED_SET, PulseAdapterAlreadyRegisteredError, REGISTRY, MOCK_ADAPTER_NAME, ALLOWED_FIELD_SET, adapter, LOOKBACK_RE, MAX_LINES, INLINE_TEMPLATE, TRUNCATION_MARKER2, execFileAsync, FIX_RE, EMPTY_REPO_RE, execFileAsync2, TRACK_CATEGORIES2, STOPWORDS, KEYWORD_TO_CATEGORY;
14029
14714
  var init_dist3 = __esm({
14030
14715
  "../core/dist/index.mjs"() {
14031
14716
  init_chunk_H73442AZ();
@@ -14050,6 +14735,76 @@ var init_dist3 = __esm({
14050
14735
  "revert"
14051
14736
  ];
14052
14737
  CONVENTIONAL_PATTERN = /^(\w+)(\(([^)]+)\))?(!)?: (.+)$/;
14738
+ LOOKBACK_PATTERN = /^\d+(h|d|w)$/;
14739
+ PulseDbSourceSchema = z2.object({
14740
+ enabled: z2.boolean(),
14741
+ connectionEnv: z2.string().optional()
14742
+ });
14743
+ PulseSourcesSchema = z2.object({
14744
+ analytics: z2.string().nullable(),
14745
+ tracing: z2.string().nullable(),
14746
+ payments: z2.string().nullable(),
14747
+ db: PulseDbSourceSchema
14748
+ });
14749
+ PulseConfigSchema = z2.object({
14750
+ enabled: z2.boolean(),
14751
+ lookbackDefault: z2.string().regex(LOOKBACK_PATTERN, 'lookback must be like "24h", "7d", or "1w"'),
14752
+ primaryEvent: z2.string(),
14753
+ valueEvent: z2.string(),
14754
+ completionEvents: z2.array(z2.string()),
14755
+ qualityScoring: z2.boolean(),
14756
+ qualityDimension: z2.string().nullable(),
14757
+ sources: PulseSourcesSchema,
14758
+ metricSourceOverrides: z2.record(z2.string(), z2.string()),
14759
+ pendingMetrics: z2.array(z2.string()),
14760
+ excludedMetrics: z2.array(z2.string())
14761
+ });
14762
+ BUG_TRACK_CATEGORIES = [
14763
+ "build-errors",
14764
+ "test-failures",
14765
+ "runtime-errors",
14766
+ "performance-issues",
14767
+ "database-issues",
14768
+ "security-issues",
14769
+ "ui-bugs",
14770
+ "integration-issues",
14771
+ "logic-errors"
14772
+ ];
14773
+ KNOWLEDGE_TRACK_CATEGORIES = [
14774
+ "architecture-patterns",
14775
+ "design-patterns",
14776
+ "tooling-decisions",
14777
+ "conventions",
14778
+ "dx",
14779
+ "best-practices"
14780
+ ];
14781
+ ALL_SOLUTION_CATEGORIES = [
14782
+ ...BUG_TRACK_CATEGORIES,
14783
+ ...KNOWLEDGE_TRACK_CATEGORIES
14784
+ ];
14785
+ ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
14786
+ BugTrackSchema = z22.object({
14787
+ track: z22.literal("bug-track"),
14788
+ category: z22.enum(BUG_TRACK_CATEGORIES)
14789
+ });
14790
+ KnowledgeTrackSchema = z22.object({
14791
+ track: z22.literal("knowledge-track"),
14792
+ category: z22.enum(KNOWLEDGE_TRACK_CATEGORIES)
14793
+ });
14794
+ BaseFrontmatter = z22.object({
14795
+ module: z22.string().min(1),
14796
+ tags: z22.array(z22.string()),
14797
+ problem_type: z22.string().min(1),
14798
+ last_updated: z22.string().regex(ISO_DATE, "last_updated must be ISO date YYYY-MM-DD")
14799
+ });
14800
+ SolutionDocFrontmatterSchema = z22.discriminatedUnion("track", [
14801
+ BaseFrontmatter.merge(BugTrackSchema),
14802
+ BaseFrontmatter.merge(KnowledgeTrackSchema)
14803
+ ]);
14804
+ TRACK_CATEGORIES = [
14805
+ ["bug-track", BUG_TRACK_CATEGORIES],
14806
+ ["knowledge-track", KNOWLEDGE_TRACK_CATEGORIES]
14807
+ ];
14053
14808
  DEFAULT_AGNIX_TIMEOUT_MS = 3e4;
14054
14809
  HARNESS_AGNIX_DISABLE = "HARNESS_AGNIX_DISABLE";
14055
14810
  HARNESS_AGNIX_BIN = "HARNESS_AGNIX_BIN";
@@ -14196,81 +14951,81 @@ var init_dist3 = __esm({
14196
14951
  { category: "config", patterns: ["harness.config.json", "package.json"], priority: 5 }
14197
14952
  ]
14198
14953
  };
14199
- ManifestSchema = z2.object({
14200
- name: z2.string(),
14201
- version: z2.string(),
14202
- description: z2.string().optional(),
14203
- include: z2.array(z2.string()).min(1),
14204
- minHarnessVersion: z2.string().optional(),
14205
- keywords: z2.array(z2.string()).optional().default([]),
14206
- layers: z2.record(z2.array(z2.string())).optional(),
14207
- boundaries: z2.array(
14208
- z2.object({
14209
- name: z2.string(),
14210
- layer: z2.string(),
14211
- direction: z2.enum(["input", "output"]),
14212
- schema: z2.string()
14954
+ ManifestSchema = z3.object({
14955
+ name: z3.string(),
14956
+ version: z3.string(),
14957
+ description: z3.string().optional(),
14958
+ include: z3.array(z3.string()).min(1),
14959
+ minHarnessVersion: z3.string().optional(),
14960
+ keywords: z3.array(z3.string()).optional().default([]),
14961
+ layers: z3.record(z3.array(z3.string())).optional(),
14962
+ boundaries: z3.array(
14963
+ z3.object({
14964
+ name: z3.string(),
14965
+ layer: z3.string(),
14966
+ direction: z3.enum(["input", "output"]),
14967
+ schema: z3.string()
14213
14968
  })
14214
14969
  ).optional()
14215
14970
  });
14216
- BundleConstraintsSchema = z2.object({
14217
- layers: z2.array(
14218
- z2.object({
14219
- name: z2.string(),
14220
- pattern: z2.string(),
14221
- allowedDependencies: z2.array(z2.string())
14971
+ BundleConstraintsSchema = z3.object({
14972
+ layers: z3.array(
14973
+ z3.object({
14974
+ name: z3.string(),
14975
+ pattern: z3.string(),
14976
+ allowedDependencies: z3.array(z3.string())
14222
14977
  })
14223
14978
  ).optional(),
14224
- forbiddenImports: z2.array(
14225
- z2.object({
14226
- from: z2.string(),
14227
- disallow: z2.array(z2.string()),
14228
- message: z2.string().optional()
14979
+ forbiddenImports: z3.array(
14980
+ z3.object({
14981
+ from: z3.string(),
14982
+ disallow: z3.array(z3.string()),
14983
+ message: z3.string().optional()
14229
14984
  })
14230
14985
  ).optional(),
14231
- boundaries: z2.object({
14232
- requireSchema: z2.array(z2.string()).optional()
14986
+ boundaries: z3.object({
14987
+ requireSchema: z3.array(z3.string()).optional()
14233
14988
  }).optional(),
14234
- architecture: z2.object({
14235
- thresholds: z2.record(z2.unknown()).optional(),
14236
- modules: z2.record(z2.record(z2.unknown())).optional()
14989
+ architecture: z3.object({
14990
+ thresholds: z3.record(z3.unknown()).optional(),
14991
+ modules: z3.record(z3.record(z3.unknown())).optional()
14237
14992
  }).optional(),
14238
- security: z2.object({
14239
- rules: z2.record(z2.string()).optional()
14993
+ security: z3.object({
14994
+ rules: z3.record(z3.string()).optional()
14240
14995
  }).optional()
14241
14996
  });
14242
- BundleSchema = z2.object({
14243
- name: z2.string(),
14244
- version: z2.string(),
14245
- description: z2.string().optional(),
14246
- minHarnessVersion: z2.string().optional(),
14997
+ BundleSchema = z3.object({
14998
+ name: z3.string(),
14999
+ version: z3.string(),
15000
+ description: z3.string().optional(),
15001
+ minHarnessVersion: z3.string().optional(),
14247
15002
  manifest: ManifestSchema,
14248
15003
  constraints: BundleConstraintsSchema,
14249
- contributions: z2.record(z2.unknown()).optional()
15004
+ contributions: z3.record(z3.unknown()).optional()
14250
15005
  });
14251
- ContributionsSchema = z2.record(z2.unknown());
14252
- LockfilePackageSchema = z2.object({
14253
- version: z2.string(),
14254
- source: z2.string(),
14255
- installedAt: z2.string(),
14256
- contributions: z2.record(z2.unknown()).optional().nullable(),
14257
- resolved: z2.string().optional(),
14258
- integrity: z2.string().optional(),
14259
- provenance: z2.array(z2.string()).optional()
15006
+ ContributionsSchema = z3.record(z3.unknown());
15007
+ LockfilePackageSchema = z3.object({
15008
+ version: z3.string(),
15009
+ source: z3.string(),
15010
+ installedAt: z3.string(),
15011
+ contributions: z3.record(z3.unknown()).optional().nullable(),
15012
+ resolved: z3.string().optional(),
15013
+ integrity: z3.string().optional(),
15014
+ provenance: z3.array(z3.string()).optional()
14260
15015
  });
14261
- LockfileSchema = z2.object({
14262
- version: z2.literal(1).optional(),
15016
+ LockfileSchema = z3.object({
15017
+ version: z3.literal(1).optional(),
14263
15018
  // Used by some tests
14264
- lockfileVersion: z2.literal(1).optional(),
15019
+ lockfileVersion: z3.literal(1).optional(),
14265
15020
  // Standard field
14266
- packages: z2.record(LockfilePackageSchema)
15021
+ packages: z3.record(LockfilePackageSchema)
14267
15022
  }).refine((data) => data.version !== void 0 || data.lockfileVersion !== void 0, {
14268
15023
  message: "Either 'version' or 'lockfileVersion' must be present and equal to 1"
14269
15024
  });
14270
- SharableLayerSchema = z2.unknown();
14271
- SharableForbiddenImportSchema = z2.unknown();
14272
- SharableBoundaryConfigSchema = z2.unknown();
14273
- SharableSecurityRulesSchema = z2.unknown();
15025
+ SharableLayerSchema = z3.unknown();
15026
+ SharableForbiddenImportSchema = z3.unknown();
15027
+ SharableBoundaryConfigSchema = z3.unknown();
15028
+ SharableSecurityRulesSchema = z3.unknown();
14274
15029
  VALID_SCOPES = /* @__PURE__ */ new Set([
14275
15030
  "entropy",
14276
15031
  "architecture",
@@ -14541,11 +15296,11 @@ var init_dist3 = __esm({
14541
15296
  return detectPatternViolations(snapshotResult.value, config);
14542
15297
  }
14543
15298
  };
14544
- readFile42 = promisify2(fs3.readFile);
14545
- writeFile32 = promisify2(fs3.writeFile);
14546
- unlink22 = promisify2(fs3.unlink);
14547
- mkdir22 = promisify2(fs3.mkdir);
14548
- copyFile2 = promisify2(fs3.copyFile);
15299
+ readFile62 = promisify2(fs5.readFile);
15300
+ writeFile32 = promisify2(fs5.writeFile);
15301
+ unlink22 = promisify2(fs5.unlink);
15302
+ mkdir22 = promisify2(fs5.mkdir);
15303
+ copyFile2 = promisify2(fs5.copyFile);
14549
15304
  DEFAULT_FIX_CONFIG = {
14550
15305
  dryRun: false,
14551
15306
  fixTypes: ["unused-imports", "dead-files"],
@@ -14573,45 +15328,45 @@ var init_dist3 = __esm({
14573
15328
  "commented-code": "Delete commented block",
14574
15329
  "unused-import": "Remove import"
14575
15330
  };
14576
- MustExportRuleSchema = z22.object({
14577
- type: z22.literal("must-export"),
14578
- names: z22.array(z22.string())
15331
+ MustExportRuleSchema = z4.object({
15332
+ type: z4.literal("must-export"),
15333
+ names: z4.array(z4.string())
14579
15334
  });
14580
- MustExportDefaultRuleSchema = z22.object({
14581
- type: z22.literal("must-export-default"),
14582
- kind: z22.enum(["class", "function", "object"]).optional()
15335
+ MustExportDefaultRuleSchema = z4.object({
15336
+ type: z4.literal("must-export-default"),
15337
+ kind: z4.enum(["class", "function", "object"]).optional()
14583
15338
  });
14584
- NoExportRuleSchema = z22.object({
14585
- type: z22.literal("no-export"),
14586
- names: z22.array(z22.string())
15339
+ NoExportRuleSchema = z4.object({
15340
+ type: z4.literal("no-export"),
15341
+ names: z4.array(z4.string())
14587
15342
  });
14588
- MustImportRuleSchema = z22.object({
14589
- type: z22.literal("must-import"),
14590
- from: z22.string(),
14591
- names: z22.array(z22.string()).optional()
15343
+ MustImportRuleSchema = z4.object({
15344
+ type: z4.literal("must-import"),
15345
+ from: z4.string(),
15346
+ names: z4.array(z4.string()).optional()
14592
15347
  });
14593
- NoImportRuleSchema = z22.object({
14594
- type: z22.literal("no-import"),
14595
- from: z22.string()
15348
+ NoImportRuleSchema = z4.object({
15349
+ type: z4.literal("no-import"),
15350
+ from: z4.string()
14596
15351
  });
14597
- NamingRuleSchema = z22.object({
14598
- type: z22.literal("naming"),
14599
- match: z22.string(),
14600
- convention: z22.enum(["camelCase", "PascalCase", "UPPER_SNAKE", "kebab-case"])
15352
+ NamingRuleSchema = z4.object({
15353
+ type: z4.literal("naming"),
15354
+ match: z4.string(),
15355
+ convention: z4.enum(["camelCase", "PascalCase", "UPPER_SNAKE", "kebab-case"])
14601
15356
  });
14602
- MaxExportsRuleSchema = z22.object({
14603
- type: z22.literal("max-exports"),
14604
- count: z22.number().positive()
15357
+ MaxExportsRuleSchema = z4.object({
15358
+ type: z4.literal("max-exports"),
15359
+ count: z4.number().positive()
14605
15360
  });
14606
- MaxLinesRuleSchema = z22.object({
14607
- type: z22.literal("max-lines"),
14608
- count: z22.number().positive()
15361
+ MaxLinesRuleSchema = z4.object({
15362
+ type: z4.literal("max-lines"),
15363
+ count: z4.number().positive()
14609
15364
  });
14610
- RequireJSDocRuleSchema = z22.object({
14611
- type: z22.literal("require-jsdoc"),
14612
- for: z22.array(z22.enum(["function", "class", "export"]))
15365
+ RequireJSDocRuleSchema = z4.object({
15366
+ type: z4.literal("require-jsdoc"),
15367
+ for: z4.array(z4.enum(["function", "class", "export"]))
14613
15368
  });
14614
- RuleSchema = z22.discriminatedUnion("type", [
15369
+ RuleSchema = z4.discriminatedUnion("type", [
14615
15370
  MustExportRuleSchema,
14616
15371
  MustExportDefaultRuleSchema,
14617
15372
  NoExportRuleSchema,
@@ -14622,52 +15377,52 @@ var init_dist3 = __esm({
14622
15377
  MaxLinesRuleSchema,
14623
15378
  RequireJSDocRuleSchema
14624
15379
  ]);
14625
- ConfigPatternSchema = z22.object({
14626
- name: z22.string().min(1),
14627
- description: z22.string(),
14628
- severity: z22.enum(["error", "warning"]),
14629
- files: z22.array(z22.string()),
15380
+ ConfigPatternSchema = z4.object({
15381
+ name: z4.string().min(1),
15382
+ description: z4.string(),
15383
+ severity: z4.enum(["error", "warning"]),
15384
+ files: z4.array(z4.string()),
14630
15385
  rule: RuleSchema,
14631
- message: z22.string().optional()
15386
+ message: z4.string().optional()
14632
15387
  });
14633
- PatternConfigSchema = z22.object({
14634
- patterns: z22.array(ConfigPatternSchema),
14635
- customPatterns: z22.array(z22.any()).optional(),
15388
+ PatternConfigSchema = z4.object({
15389
+ patterns: z4.array(ConfigPatternSchema),
15390
+ customPatterns: z4.array(z4.any()).optional(),
14636
15391
  // Code patterns are functions, can't validate
14637
- ignoreFiles: z22.array(z22.string()).optional()
15392
+ ignoreFiles: z4.array(z4.string()).optional()
14638
15393
  });
14639
- DriftConfigSchema = z22.object({
14640
- docPaths: z22.array(z22.string()).optional(),
14641
- checkApiSignatures: z22.boolean().optional(),
14642
- checkExamples: z22.boolean().optional(),
14643
- checkStructure: z22.boolean().optional(),
14644
- ignorePatterns: z22.array(z22.string()).optional()
15394
+ DriftConfigSchema = z4.object({
15395
+ docPaths: z4.array(z4.string()).optional(),
15396
+ checkApiSignatures: z4.boolean().optional(),
15397
+ checkExamples: z4.boolean().optional(),
15398
+ checkStructure: z4.boolean().optional(),
15399
+ ignorePatterns: z4.array(z4.string()).optional()
14645
15400
  });
14646
- DeadCodeConfigSchema = z22.object({
14647
- entryPoints: z22.array(z22.string()).optional(),
14648
- includeTypes: z22.boolean().optional(),
14649
- includeInternals: z22.boolean().optional(),
14650
- ignorePatterns: z22.array(z22.string()).optional(),
14651
- treatDynamicImportsAs: z22.enum(["used", "unknown"]).optional()
15401
+ DeadCodeConfigSchema = z4.object({
15402
+ entryPoints: z4.array(z4.string()).optional(),
15403
+ includeTypes: z4.boolean().optional(),
15404
+ includeInternals: z4.boolean().optional(),
15405
+ ignorePatterns: z4.array(z4.string()).optional(),
15406
+ treatDynamicImportsAs: z4.enum(["used", "unknown"]).optional()
14652
15407
  });
14653
- EntropyConfigSchema = z22.object({
14654
- rootDir: z22.string(),
14655
- parser: z22.any().optional(),
15408
+ EntropyConfigSchema = z4.object({
15409
+ rootDir: z4.string(),
15410
+ parser: z4.any().optional(),
14656
15411
  // LanguageParser instance, can't validate
14657
- entryPoints: z22.array(z22.string()).optional(),
14658
- analyze: z22.object({
14659
- drift: z22.union([z22.boolean(), DriftConfigSchema]).optional(),
14660
- deadCode: z22.union([z22.boolean(), DeadCodeConfigSchema]).optional(),
14661
- patterns: z22.union([z22.boolean(), PatternConfigSchema]).optional()
15412
+ entryPoints: z4.array(z4.string()).optional(),
15413
+ analyze: z4.object({
15414
+ drift: z4.union([z4.boolean(), DriftConfigSchema]).optional(),
15415
+ deadCode: z4.union([z4.boolean(), DeadCodeConfigSchema]).optional(),
15416
+ patterns: z4.union([z4.boolean(), PatternConfigSchema]).optional()
14662
15417
  }),
14663
- include: z22.array(z22.string()).optional(),
14664
- exclude: z22.array(z22.string()).optional(),
14665
- docPaths: z22.array(z22.string()).optional()
15418
+ include: z4.array(z4.string()).optional(),
15419
+ exclude: z4.array(z4.string()).optional(),
15420
+ docPaths: z4.array(z4.string()).optional()
14666
15421
  });
14667
15422
  BaselineManager = class {
14668
15423
  baselinesPath;
14669
15424
  constructor(projectRoot) {
14670
- this.baselinesPath = join15(projectRoot, ".harness", "perf", "baselines.json");
15425
+ this.baselinesPath = join17(projectRoot, ".harness", "perf", "baselines.json");
14671
15426
  }
14672
15427
  /**
14673
15428
  * Load the baselines file from disk.
@@ -14942,16 +15697,16 @@ var init_dist3 = __esm({
14942
15697
  walkDir(dir, entries) {
14943
15698
  let items;
14944
15699
  try {
14945
- items = fs4.readdirSync(dir, { withFileTypes: true });
15700
+ items = fs6.readdirSync(dir, { withFileTypes: true });
14946
15701
  } catch {
14947
15702
  return;
14948
15703
  }
14949
15704
  for (const item of items) {
14950
15705
  if (item.isDirectory()) {
14951
15706
  if (SKIP_DIRS.has(item.name)) continue;
14952
- this.walkDir(path.join(dir, item.name), entries);
14953
- } else if (item.isFile() && SOURCE_EXTENSIONS.has(path.extname(item.name))) {
14954
- this.scanFile(path.join(dir, item.name), entries);
15707
+ this.walkDir(path3.join(dir, item.name), entries);
15708
+ } else if (item.isFile() && SOURCE_EXTENSIONS.has(path3.extname(item.name))) {
15709
+ this.scanFile(path3.join(dir, item.name), entries);
14955
15710
  }
14956
15711
  }
14957
15712
  }
@@ -14966,12 +15721,12 @@ var init_dist3 = __esm({
14966
15721
  scanFile(filePath, entries) {
14967
15722
  let content;
14968
15723
  try {
14969
- content = fs4.readFileSync(filePath, "utf-8");
15724
+ content = fs6.readFileSync(filePath, "utf-8");
14970
15725
  } catch {
14971
15726
  return;
14972
15727
  }
14973
15728
  const lines = content.split("\n");
14974
- const relativePath = path.relative(this.projectRoot, filePath).replace(/\\/g, "/");
15729
+ const relativePath = path3.relative(this.projectRoot, filePath).replace(/\\/g, "/");
14975
15730
  for (let i = 0; i < lines.length; i++) {
14976
15731
  if (!lines[i].includes("@perf-critical")) continue;
14977
15732
  const fnName = this.resolveFunctionName(lines, i + 1);
@@ -15370,46 +16125,46 @@ var init_dist3 = __esm({
15370
16125
  return Ok(void 0);
15371
16126
  }
15372
16127
  };
15373
- CategorySnapshotSchema = z3.object({
16128
+ CategorySnapshotSchema = z5.object({
15374
16129
  /** Aggregate metric value (e.g., violation count, avg complexity) */
15375
- value: z3.number(),
16130
+ value: z5.number(),
15376
16131
  /** Count of violations in this category */
15377
- violationCount: z3.number()
16132
+ violationCount: z5.number()
15378
16133
  });
15379
- TimelineSnapshotSchema = z3.object({
16134
+ TimelineSnapshotSchema = z5.object({
15380
16135
  /** ISO 8601 timestamp of capture */
15381
- capturedAt: z3.string().datetime(),
16136
+ capturedAt: z5.string().datetime(),
15382
16137
  /** Git commit hash at capture time */
15383
- commitHash: z3.string(),
16138
+ commitHash: z5.string(),
15384
16139
  /** Composite stability score (0-100, higher is healthier) */
15385
- stabilityScore: z3.number().min(0).max(100),
16140
+ stabilityScore: z5.number().min(0).max(100),
15386
16141
  /** Per-category metric aggregates */
15387
- metrics: z3.record(ArchMetricCategorySchema, CategorySnapshotSchema)
16142
+ metrics: z5.record(ArchMetricCategorySchema, CategorySnapshotSchema)
15388
16143
  });
15389
- TimelineFileSchema = z3.object({
15390
- version: z3.literal(1),
15391
- snapshots: z3.array(TimelineSnapshotSchema)
16144
+ TimelineFileSchema = z5.object({
16145
+ version: z5.literal(1),
16146
+ snapshots: z5.array(TimelineSnapshotSchema)
15392
16147
  });
15393
- TrendLineSchema = z3.object({
16148
+ TrendLineSchema = z5.object({
15394
16149
  /** Current value */
15395
- current: z3.number(),
16150
+ current: z5.number(),
15396
16151
  /** Previous value (from comparison snapshot) */
15397
- previous: z3.number(),
16152
+ previous: z5.number(),
15398
16153
  /** Absolute delta (current - previous) */
15399
- delta: z3.number(),
16154
+ delta: z5.number(),
15400
16155
  /** Direction indicator */
15401
- direction: z3.enum(["improving", "stable", "declining"])
16156
+ direction: z5.enum(["improving", "stable", "declining"])
15402
16157
  });
15403
- TrendResultSchema = z3.object({
16158
+ TrendResultSchema = z5.object({
15404
16159
  /** Overall stability trend */
15405
16160
  stability: TrendLineSchema,
15406
16161
  /** Per-category trends */
15407
- categories: z3.record(ArchMetricCategorySchema, TrendLineSchema),
16162
+ categories: z5.record(ArchMetricCategorySchema, TrendLineSchema),
15408
16163
  /** Number of snapshots analyzed */
15409
- snapshotCount: z3.number(),
16164
+ snapshotCount: z5.number(),
15410
16165
  /** Time range covered */
15411
- from: z3.string(),
15412
- to: z3.string()
16166
+ from: z5.string(),
16167
+ to: z5.string()
15413
16168
  });
15414
16169
  DEFAULT_STABILITY_THRESHOLDS = {
15415
16170
  "circular-deps": 5,
@@ -15424,7 +16179,7 @@ var init_dist3 = __esm({
15424
16179
  TimelineManager = class {
15425
16180
  timelinePath;
15426
16181
  constructor(rootDir) {
15427
- this.timelinePath = join17(rootDir, ".harness", "arch", "timeline.json");
16182
+ this.timelinePath = join19(rootDir, ".harness", "arch", "timeline.json");
15428
16183
  }
15429
16184
  /**
15430
16185
  * Load timeline from disk.
@@ -15608,80 +16363,80 @@ var init_dist3 = __esm({
15608
16363
  };
15609
16364
  }
15610
16365
  };
15611
- ConfidenceTierSchema = z4.enum(["high", "medium", "low"]);
15612
- RegressionResultSchema = z4.object({
15613
- slope: z4.number(),
15614
- intercept: z4.number(),
15615
- rSquared: z4.number().min(0).max(1),
15616
- dataPoints: z4.number().int().min(0)
16366
+ ConfidenceTierSchema = z6.enum(["high", "medium", "low"]);
16367
+ RegressionResultSchema = z6.object({
16368
+ slope: z6.number(),
16369
+ intercept: z6.number(),
16370
+ rSquared: z6.number().min(0).max(1),
16371
+ dataPoints: z6.number().int().min(0)
15617
16372
  });
15618
- DirectionSchema = z4.enum(["improving", "stable", "declining"]);
15619
- CategoryForecastSchema = z4.object({
16373
+ DirectionSchema = z6.enum(["improving", "stable", "declining"]);
16374
+ CategoryForecastSchema = z6.object({
15620
16375
  category: ArchMetricCategorySchema,
15621
- current: z4.number(),
15622
- threshold: z4.number(),
15623
- projectedValue4w: z4.number(),
15624
- projectedValue8w: z4.number(),
15625
- projectedValue12w: z4.number(),
15626
- thresholdCrossingWeeks: z4.number().nullable(),
16376
+ current: z6.number(),
16377
+ threshold: z6.number(),
16378
+ projectedValue4w: z6.number(),
16379
+ projectedValue8w: z6.number(),
16380
+ projectedValue12w: z6.number(),
16381
+ thresholdCrossingWeeks: z6.number().nullable(),
15627
16382
  confidence: ConfidenceTierSchema,
15628
16383
  regression: RegressionResultSchema,
15629
16384
  direction: DirectionSchema
15630
16385
  });
15631
- SpecImpactSignalsSchema = z4.object({
15632
- newFileCount: z4.number().int().min(0),
15633
- affectedLayers: z4.array(z4.string()),
15634
- newDependencies: z4.number().int().min(0),
15635
- phaseCount: z4.number().int().min(0)
16386
+ SpecImpactSignalsSchema = z6.object({
16387
+ newFileCount: z6.number().int().min(0),
16388
+ affectedLayers: z6.array(z6.string()),
16389
+ newDependencies: z6.number().int().min(0),
16390
+ phaseCount: z6.number().int().min(0)
15636
16391
  });
15637
- SpecImpactEstimateSchema = z4.object({
15638
- specPath: z4.string(),
15639
- featureName: z4.string(),
16392
+ SpecImpactEstimateSchema = z6.object({
16393
+ specPath: z6.string(),
16394
+ featureName: z6.string(),
15640
16395
  signals: SpecImpactSignalsSchema,
15641
- deltas: z4.record(ArchMetricCategorySchema, z4.number()).optional()
16396
+ deltas: z6.record(ArchMetricCategorySchema, z6.number()).optional()
15642
16397
  });
15643
- ContributingFeatureSchema = z4.object({
15644
- name: z4.string(),
15645
- specPath: z4.string(),
15646
- delta: z4.number()
16398
+ ContributingFeatureSchema = z6.object({
16399
+ name: z6.string(),
16400
+ specPath: z6.string(),
16401
+ delta: z6.number()
15647
16402
  });
15648
- AdjustedForecastSchema = z4.object({
16403
+ AdjustedForecastSchema = z6.object({
15649
16404
  baseline: CategoryForecastSchema,
15650
16405
  adjusted: CategoryForecastSchema,
15651
- contributingFeatures: z4.array(ContributingFeatureSchema)
16406
+ contributingFeatures: z6.array(ContributingFeatureSchema)
15652
16407
  });
15653
- PredictionWarningSchema = z4.object({
15654
- severity: z4.enum(["critical", "warning", "info"]),
16408
+ PredictionWarningSchema = z6.object({
16409
+ severity: z6.enum(["critical", "warning", "info"]),
15655
16410
  category: ArchMetricCategorySchema,
15656
- message: z4.string(),
15657
- weeksUntil: z4.number(),
16411
+ message: z6.string(),
16412
+ weeksUntil: z6.number(),
15658
16413
  confidence: ConfidenceTierSchema,
15659
- contributingFeatures: z4.array(z4.string())
16414
+ contributingFeatures: z6.array(z6.string())
15660
16415
  });
15661
- StabilityForecastSchema = z4.object({
15662
- current: z4.number(),
15663
- projected4w: z4.number(),
15664
- projected8w: z4.number(),
15665
- projected12w: z4.number(),
16416
+ StabilityForecastSchema = z6.object({
16417
+ current: z6.number(),
16418
+ projected4w: z6.number(),
16419
+ projected8w: z6.number(),
16420
+ projected12w: z6.number(),
15666
16421
  confidence: ConfidenceTierSchema,
15667
16422
  direction: DirectionSchema
15668
16423
  });
15669
- PredictionResultSchema = z4.object({
15670
- generatedAt: z4.string(),
15671
- snapshotsUsed: z4.number().int().min(0),
15672
- timelineRange: z4.object({
15673
- from: z4.string(),
15674
- to: z4.string()
16424
+ PredictionResultSchema = z6.object({
16425
+ generatedAt: z6.string(),
16426
+ snapshotsUsed: z6.number().int().min(0),
16427
+ timelineRange: z6.object({
16428
+ from: z6.string(),
16429
+ to: z6.string()
15675
16430
  }),
15676
16431
  stabilityForecast: StabilityForecastSchema,
15677
- categories: z4.record(ArchMetricCategorySchema, AdjustedForecastSchema),
15678
- warnings: z4.array(PredictionWarningSchema)
16432
+ categories: z6.record(ArchMetricCategorySchema, AdjustedForecastSchema),
16433
+ warnings: z6.array(PredictionWarningSchema)
15679
16434
  });
15680
- PredictionOptionsSchema = z4.object({
15681
- horizon: z4.number().int().min(1).default(12),
15682
- includeRoadmap: z4.boolean().default(true),
15683
- categories: z4.array(ArchMetricCategorySchema).optional(),
15684
- thresholds: z4.record(ArchMetricCategorySchema, z4.number()).optional()
16435
+ PredictionOptionsSchema = z6.object({
16436
+ horizon: z6.number().int().min(1).default(12),
16437
+ includeRoadmap: z6.boolean().default(true),
16438
+ categories: z6.array(ArchMetricCategorySchema).optional(),
16439
+ thresholds: z6.record(ArchMetricCategorySchema, z6.number()).optional()
15685
16440
  });
15686
16441
  VALID_STATUSES = /* @__PURE__ */ new Set([
15687
16442
  "backlog",
@@ -16014,8 +16769,8 @@ var init_dist3 = __esm({
16014
16769
  return null;
16015
16770
  }
16016
16771
  try {
16017
- const roadmapPath = path2.join(this.rootDir, "roadmap.md");
16018
- const raw = fs5.readFileSync(roadmapPath, "utf-8");
16772
+ const roadmapPath = path4.join(this.rootDir, "roadmap.md");
16773
+ const raw = fs7.readFileSync(roadmapPath, "utf-8");
16019
16774
  const parseResult = parseRoadmap(raw);
16020
16775
  if (!parseResult.ok) return null;
16021
16776
  const features = parseResult.value.milestones.flatMap(
@@ -16050,8 +16805,8 @@ var init_dist3 = __esm({
16050
16805
  * @param specPath - Relative path from rootDir to the spec file.
16051
16806
  */
16052
16807
  estimate(specPath) {
16053
- const absolutePath = path3.join(this.rootDir, specPath);
16054
- const content = fs6.readFileSync(absolutePath, "utf-8");
16808
+ const absolutePath = path5.join(this.rootDir, specPath);
16809
+ const content = fs8.readFileSync(absolutePath, "utf-8");
16055
16810
  const newFileCount = this.extractNewFileCount(content);
16056
16811
  const affectedLayers = this.extractAffectedLayers(content);
16057
16812
  const newDependencies = this.extractNewDependencies(content);
@@ -16063,7 +16818,7 @@ var init_dist3 = __esm({
16063
16818
  phaseCount
16064
16819
  );
16065
16820
  const h1Match = content.match(/^#\s+(.+)$/m);
16066
- const featureName = h1Match ? h1Match[1].trim() : path3.basename(specPath, ".md");
16821
+ const featureName = h1Match ? h1Match[1].trim() : path5.basename(specPath, ".md");
16067
16822
  return {
16068
16823
  specPath,
16069
16824
  featureName,
@@ -16084,8 +16839,8 @@ var init_dist3 = __esm({
16084
16839
  const results = [];
16085
16840
  for (const feature of features) {
16086
16841
  if (!feature.spec) continue;
16087
- const absolutePath = path3.join(this.rootDir, feature.spec);
16088
- if (!fs6.existsSync(absolutePath)) continue;
16842
+ const absolutePath = path5.join(this.rootDir, feature.spec);
16843
+ if (!fs8.existsSync(absolutePath)) continue;
16089
16844
  const estimate = this.estimate(feature.spec);
16090
16845
  results.push({ ...estimate, featureName: feature.name });
16091
16846
  }
@@ -16113,8 +16868,8 @@ var init_dist3 = __esm({
16113
16868
  }
16114
16869
  let count = 0;
16115
16870
  for (const fp of filePaths) {
16116
- const absolute = path3.join(this.rootDir, fp);
16117
- if (!fs6.existsSync(absolute)) {
16871
+ const absolute = path5.join(this.rootDir, fp);
16872
+ if (!fs8.existsSync(absolute)) {
16118
16873
  count++;
16119
16874
  }
16120
16875
  }
@@ -16184,8 +16939,8 @@ var init_dist3 = __esm({
16184
16939
  // --- Private: Config Loading ---
16185
16940
  loadLayerNames() {
16186
16941
  try {
16187
- const configPath = path3.join(this.rootDir, "harness.config.json");
16188
- const raw = fs6.readFileSync(configPath, "utf-8");
16942
+ const configPath = path5.join(this.rootDir, "harness.config.json");
16943
+ const raw = fs8.readFileSync(configPath, "utf-8");
16189
16944
  const config = JSON.parse(raw);
16190
16945
  return (config.layers ?? []).map((l) => l.name);
16191
16946
  } catch {
@@ -16204,8 +16959,8 @@ var init_dist3 = __esm({
16204
16959
  historyPath;
16205
16960
  /** Load history from disk, returning empty history if file doesn't exist. */
16206
16961
  load() {
16207
- if (!fs7.existsSync(this.historyPath)) return { ...EMPTY_HISTORY, snapshots: [] };
16208
- const raw = fs7.readFileSync(this.historyPath, "utf-8");
16962
+ if (!fs9.existsSync(this.historyPath)) return { ...EMPTY_HISTORY, snapshots: [] };
16963
+ const raw = fs9.readFileSync(this.historyPath, "utf-8");
16209
16964
  return JSON.parse(raw);
16210
16965
  }
16211
16966
  /** Append a timestamped snapshot of current violations. */
@@ -16219,18 +16974,18 @@ var init_dist3 = __esm({
16219
16974
  }
16220
16975
  /** Prune snapshots older than retentionDays. */
16221
16976
  prune(retentionDays) {
16222
- if (!fs7.existsSync(this.historyPath)) return;
16977
+ if (!fs9.existsSync(this.historyPath)) return;
16223
16978
  const history = this.load();
16224
16979
  const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1e3;
16225
16980
  history.snapshots = history.snapshots.filter((s) => new Date(s.timestamp).getTime() >= cutoff);
16226
16981
  this.write(history);
16227
16982
  }
16228
16983
  write(history) {
16229
- const dir = path4.dirname(this.historyPath);
16230
- if (!fs7.existsSync(dir)) {
16231
- fs7.mkdirSync(dir, { recursive: true });
16984
+ const dir = path6.dirname(this.historyPath);
16985
+ if (!fs9.existsSync(dir)) {
16986
+ fs9.mkdirSync(dir, { recursive: true });
16232
16987
  }
16233
- fs7.writeFileSync(this.historyPath, JSON.stringify(history, null, 2), "utf-8");
16988
+ fs9.writeFileSync(this.historyPath, JSON.stringify(history, null, 2), "utf-8");
16234
16989
  }
16235
16990
  };
16236
16991
  NORMALIZERS = {
@@ -16245,81 +17000,81 @@ var init_dist3 = __esm({
16245
17000
  MAX_SAMPLES = 5;
16246
17001
  DEFAULT_WINDOW_WEEKS = 4;
16247
17002
  DEFAULT_MIN_OCCURRENCES = 3;
16248
- FailureEntrySchema = z5.object({
16249
- date: z5.string(),
16250
- skill: z5.string(),
16251
- type: z5.string(),
16252
- description: z5.string()
17003
+ FailureEntrySchema = z7.object({
17004
+ date: z7.string(),
17005
+ skill: z7.string(),
17006
+ type: z7.string(),
17007
+ description: z7.string()
16253
17008
  });
16254
- HandoffSchema = z5.object({
16255
- timestamp: z5.string(),
16256
- fromSkill: z5.string(),
16257
- phase: z5.string(),
16258
- summary: z5.string(),
16259
- completed: z5.array(z5.string()).default([]),
16260
- pending: z5.array(z5.string()).default([]),
16261
- concerns: z5.array(z5.string()).default([]),
16262
- decisions: z5.array(
16263
- z5.object({
16264
- what: z5.string(),
16265
- why: z5.string()
17009
+ HandoffSchema = z7.object({
17010
+ timestamp: z7.string(),
17011
+ fromSkill: z7.string(),
17012
+ phase: z7.string(),
17013
+ summary: z7.string(),
17014
+ completed: z7.array(z7.string()).default([]),
17015
+ pending: z7.array(z7.string()).default([]),
17016
+ concerns: z7.array(z7.string()).default([]),
17017
+ decisions: z7.array(
17018
+ z7.object({
17019
+ what: z7.string(),
17020
+ why: z7.string()
16266
17021
  })
16267
17022
  ).default([]),
16268
- blockers: z5.array(z5.string()).default([]),
16269
- contextKeywords: z5.array(z5.string()).default([]),
16270
- recommendedSkills: z5.object({
16271
- apply: z5.array(z5.string()),
16272
- reference: z5.array(z5.string()),
16273
- consider: z5.array(z5.string()),
16274
- skillsPath: z5.string()
17023
+ blockers: z7.array(z7.string()).default([]),
17024
+ contextKeywords: z7.array(z7.string()).default([]),
17025
+ recommendedSkills: z7.object({
17026
+ apply: z7.array(z7.string()),
17027
+ reference: z7.array(z7.string()),
17028
+ consider: z7.array(z7.string()),
17029
+ skillsPath: z7.string()
16275
17030
  }).optional()
16276
17031
  });
16277
- GateCheckSchema = z5.object({
16278
- name: z5.string(),
16279
- passed: z5.boolean(),
16280
- command: z5.string(),
16281
- output: z5.string().optional(),
16282
- duration: z5.number().optional()
17032
+ GateCheckSchema = z7.object({
17033
+ name: z7.string(),
17034
+ passed: z7.boolean(),
17035
+ command: z7.string(),
17036
+ output: z7.string().optional(),
17037
+ duration: z7.number().optional()
16283
17038
  });
16284
- GateResultSchema = z5.object({
16285
- passed: z5.boolean(),
16286
- checks: z5.array(GateCheckSchema)
17039
+ GateResultSchema = z7.object({
17040
+ passed: z7.boolean(),
17041
+ checks: z7.array(GateCheckSchema)
16287
17042
  });
16288
- GateConfigSchema = z5.object({
16289
- checks: z5.array(
16290
- z5.object({
16291
- name: z5.string(),
16292
- command: z5.string()
17043
+ GateConfigSchema = z7.object({
17044
+ checks: z7.array(
17045
+ z7.object({
17046
+ name: z7.string(),
17047
+ command: z7.string()
16293
17048
  })
16294
17049
  ).optional(),
16295
- trace: z5.boolean().optional()
17050
+ trace: z7.boolean().optional()
16296
17051
  });
16297
- HarnessStateSchema = z5.object({
16298
- schemaVersion: z5.literal(1),
16299
- position: z5.object({
16300
- phase: z5.string().optional(),
16301
- task: z5.string().optional()
17052
+ HarnessStateSchema = z7.object({
17053
+ schemaVersion: z7.literal(1),
17054
+ position: z7.object({
17055
+ phase: z7.string().optional(),
17056
+ task: z7.string().optional()
16302
17057
  }).default({}),
16303
- decisions: z5.array(
16304
- z5.object({
16305
- date: z5.string(),
16306
- decision: z5.string(),
16307
- context: z5.string()
17058
+ decisions: z7.array(
17059
+ z7.object({
17060
+ date: z7.string(),
17061
+ decision: z7.string(),
17062
+ context: z7.string()
16308
17063
  })
16309
17064
  ).default([]),
16310
- blockers: z5.array(
16311
- z5.object({
16312
- id: z5.string(),
16313
- description: z5.string(),
16314
- status: z5.enum(["open", "resolved"])
17065
+ blockers: z7.array(
17066
+ z7.object({
17067
+ id: z7.string(),
17068
+ description: z7.string(),
17069
+ status: z7.enum(["open", "resolved"])
16315
17070
  })
16316
17071
  ).default([]),
16317
- progress: z5.record(z5.enum(["pending", "in_progress", "complete"])).default({}),
16318
- lastSession: z5.object({
16319
- date: z5.string(),
16320
- summary: z5.string(),
16321
- lastSkill: z5.string().optional(),
16322
- pendingTasks: z5.array(z5.string()).optional()
17072
+ progress: z7.record(z7.enum(["pending", "in_progress", "complete"])).default({}),
17073
+ lastSession: z7.object({
17074
+ date: z7.string(),
17075
+ summary: z7.string(),
17076
+ lastSkill: z7.string().optional(),
17077
+ pendingTasks: z7.array(z7.string()).optional()
16323
17078
  }).optional()
16324
17079
  });
16325
17080
  DEFAULT_STATE = {
@@ -16329,16 +17084,16 @@ var init_dist3 = __esm({
16329
17084
  blockers: [],
16330
17085
  progress: {}
16331
17086
  };
16332
- StreamInfoSchema = z6.object({
16333
- name: z6.string(),
16334
- branch: z6.string().optional(),
16335
- createdAt: z6.string(),
16336
- lastActiveAt: z6.string()
17087
+ StreamInfoSchema = z8.object({
17088
+ name: z8.string(),
17089
+ branch: z8.string().optional(),
17090
+ createdAt: z8.string(),
17091
+ lastActiveAt: z8.string()
16337
17092
  });
16338
- StreamIndexSchema = z6.object({
16339
- schemaVersion: z6.literal(1),
16340
- activeStream: z6.string().nullable(),
16341
- streams: z6.record(StreamInfoSchema)
17093
+ StreamIndexSchema = z8.object({
17094
+ schemaVersion: z8.literal(1),
17095
+ activeStream: z8.string().nullable(),
17096
+ streams: z8.record(StreamInfoSchema)
16342
17097
  });
16343
17098
  DEFAULT_STREAM_INDEX = {
16344
17099
  schemaVersion: 1,
@@ -16379,15 +17134,15 @@ var init_dist3 = __esm({
16379
17134
  failuresCacheMap = /* @__PURE__ */ new Map();
16380
17135
  FAILURE_LINE_REGEX = /^- \*\*(\d{4}-\d{2}-\d{2}) \[skill:([^\]]+)\] \[type:([^\]]+)\]:\*\* (.+)$/;
16381
17136
  SAFE_GATE_COMMAND = /^(?:npm|pnpm|yarn)\s+(?:test|run\s+[\w.-]+|run-script\s+[\w.-]+)$|^go\s+(?:test|build|vet|fmt)\s+[\w./ -]+$|^(?:python|python3)\s+-m\s+[\w.-]+$|^make\s+[\w.-]+$|^cargo\s+(?:test|build|check|clippy)(?:\s+[\w./ -]+)?$|^(?:gradle|mvn)\s+[\w:.-]+$/;
16382
- SkillEventSchema = z7.object({
16383
- timestamp: z7.string(),
16384
- skill: z7.string(),
16385
- session: z7.string().optional(),
16386
- type: z7.enum(["phase_transition", "decision", "gate_result", "handoff", "error", "checkpoint"]),
16387
- summary: z7.string(),
16388
- data: z7.record(z7.unknown()).optional(),
16389
- refs: z7.array(z7.string()).optional(),
16390
- contentHash: z7.string().optional()
17137
+ SkillEventSchema = z9.object({
17138
+ timestamp: z9.string(),
17139
+ skill: z9.string(),
17140
+ session: z9.string().optional(),
17141
+ type: z9.enum(["phase_transition", "decision", "gate_result", "handoff", "error", "checkpoint"]),
17142
+ summary: z9.string(),
17143
+ data: z9.record(z9.unknown()).optional(),
17144
+ refs: z9.array(z9.string()).optional(),
17145
+ contentHash: z9.string().optional()
16391
17146
  });
16392
17147
  knownHashesCache = /* @__PURE__ */ new Map();
16393
17148
  EVENT_FORMATTERS = {
@@ -16430,19 +17185,19 @@ var init_dist3 = __esm({
16430
17185
  rules: {},
16431
17186
  exclude: ["**/node_modules/**", "**/dist/**", "**/*.test.ts", "**/fixtures/**"]
16432
17187
  };
16433
- RuleOverrideSchema = z8.enum(["off", "error", "warning", "info"]);
16434
- SecurityConfigSchema = z8.object({
16435
- enabled: z8.boolean().default(true),
16436
- strict: z8.boolean().default(false),
16437
- rules: z8.record(z8.string(), RuleOverrideSchema).optional().default({}),
16438
- exclude: z8.array(z8.string()).optional().default(["**/node_modules/**", "**/dist/**", "**/*.test.ts", "**/fixtures/**"]),
16439
- external: z8.object({
16440
- semgrep: z8.object({
16441
- enabled: z8.union([z8.literal("auto"), z8.boolean()]).default("auto"),
16442
- rulesets: z8.array(z8.string()).optional()
17188
+ RuleOverrideSchema = z10.enum(["off", "error", "warning", "info"]);
17189
+ SecurityConfigSchema = z10.object({
17190
+ enabled: z10.boolean().default(true),
17191
+ strict: z10.boolean().default(false),
17192
+ rules: z10.record(z10.string(), RuleOverrideSchema).optional().default({}),
17193
+ exclude: z10.array(z10.string()).optional().default(["**/node_modules/**", "**/dist/**", "**/*.test.ts", "**/fixtures/**"]),
17194
+ external: z10.object({
17195
+ semgrep: z10.object({
17196
+ enabled: z10.union([z10.literal("auto"), z10.boolean()]).default("auto"),
17197
+ rulesets: z10.array(z10.string()).optional()
16443
17198
  }).optional(),
16444
- gitleaks: z8.object({
16445
- enabled: z8.union([z8.literal("auto"), z8.boolean()]).default("auto")
17199
+ gitleaks: z10.object({
17200
+ enabled: z10.union([z10.literal("auto"), z10.boolean()]).default("auto")
16446
17201
  }).optional()
16447
17202
  }).optional()
16448
17203
  });
@@ -17232,7 +17987,7 @@ var init_dist3 = __esm({
17232
17987
  }
17233
17988
  async scanFile(filePath) {
17234
17989
  if (!this.config.enabled) return [];
17235
- const content = await fs25.readFile(filePath, "utf-8");
17990
+ const content = await fs27.readFile(filePath, "utf-8");
17236
17991
  return this.scanContentForFile(content, filePath, 1);
17237
17992
  }
17238
17993
  scanContentForFile(content, filePath, startLine = 1) {
@@ -17541,88 +18296,88 @@ var init_dist3 = __esm({
17541
18296
  ];
17542
18297
  TAINT_DURATION_MS = 30 * 60 * 1e3;
17543
18298
  DEFAULT_SESSION_ID = "default";
17544
- SecurityCategorySnapshotSchema = z9.object({
17545
- findingCount: z9.number(),
17546
- errorCount: z9.number(),
17547
- warningCount: z9.number(),
17548
- infoCount: z9.number()
18299
+ SecurityCategorySnapshotSchema = z11.object({
18300
+ findingCount: z11.number(),
18301
+ errorCount: z11.number(),
18302
+ warningCount: z11.number(),
18303
+ infoCount: z11.number()
17549
18304
  });
17550
- SupplyChainSnapshotSchema = z9.object({
17551
- critical: z9.number(),
17552
- high: z9.number(),
17553
- moderate: z9.number(),
17554
- low: z9.number(),
17555
- info: z9.number(),
17556
- total: z9.number()
18305
+ SupplyChainSnapshotSchema = z11.object({
18306
+ critical: z11.number(),
18307
+ high: z11.number(),
18308
+ moderate: z11.number(),
18309
+ low: z11.number(),
18310
+ info: z11.number(),
18311
+ total: z11.number()
17557
18312
  });
17558
- SecurityTimelineSnapshotSchema = z9.object({
17559
- capturedAt: z9.string().datetime(),
17560
- commitHash: z9.string(),
17561
- securityScore: z9.number().min(0).max(100),
17562
- totalFindings: z9.number(),
17563
- bySeverity: z9.object({
17564
- error: z9.number(),
17565
- warning: z9.number(),
17566
- info: z9.number()
18313
+ SecurityTimelineSnapshotSchema = z11.object({
18314
+ capturedAt: z11.string().datetime(),
18315
+ commitHash: z11.string(),
18316
+ securityScore: z11.number().min(0).max(100),
18317
+ totalFindings: z11.number(),
18318
+ bySeverity: z11.object({
18319
+ error: z11.number(),
18320
+ warning: z11.number(),
18321
+ info: z11.number()
17567
18322
  }),
17568
- byCategory: z9.record(z9.string(), SecurityCategorySnapshotSchema),
18323
+ byCategory: z11.record(z11.string(), SecurityCategorySnapshotSchema),
17569
18324
  supplyChain: SupplyChainSnapshotSchema,
17570
- suppressionCount: z9.number(),
17571
- findingIds: z9.array(z9.string())
18325
+ suppressionCount: z11.number(),
18326
+ findingIds: z11.array(z11.string())
17572
18327
  });
17573
- FindingLifecycleSchema = z9.object({
17574
- findingId: z9.string(),
17575
- ruleId: z9.string(),
17576
- category: z9.string(),
17577
- severity: z9.string(),
17578
- file: z9.string(),
17579
- firstSeenAt: z9.string().datetime(),
17580
- firstSeenCommit: z9.string(),
17581
- resolvedAt: z9.string().datetime().nullable(),
17582
- resolvedCommit: z9.string().nullable()
18328
+ FindingLifecycleSchema = z11.object({
18329
+ findingId: z11.string(),
18330
+ ruleId: z11.string(),
18331
+ category: z11.string(),
18332
+ severity: z11.string(),
18333
+ file: z11.string(),
18334
+ firstSeenAt: z11.string().datetime(),
18335
+ firstSeenCommit: z11.string(),
18336
+ resolvedAt: z11.string().datetime().nullable(),
18337
+ resolvedCommit: z11.string().nullable()
17583
18338
  });
17584
- SecurityTimelineFileSchema = z9.object({
17585
- version: z9.literal(1),
17586
- snapshots: z9.array(SecurityTimelineSnapshotSchema),
17587
- findingLifecycles: z9.array(FindingLifecycleSchema)
18339
+ SecurityTimelineFileSchema = z11.object({
18340
+ version: z11.literal(1),
18341
+ snapshots: z11.array(SecurityTimelineSnapshotSchema),
18342
+ findingLifecycles: z11.array(FindingLifecycleSchema)
17588
18343
  });
17589
- DirectionSchema2 = z9.enum(["improving", "stable", "declining"]);
17590
- SecurityTrendLineSchema = z9.object({
17591
- current: z9.number(),
17592
- previous: z9.number(),
17593
- delta: z9.number(),
18344
+ DirectionSchema2 = z11.enum(["improving", "stable", "declining"]);
18345
+ SecurityTrendLineSchema = z11.object({
18346
+ current: z11.number(),
18347
+ previous: z11.number(),
18348
+ delta: z11.number(),
17594
18349
  direction: DirectionSchema2
17595
18350
  });
17596
- TrendAttributionSchema = z9.object({
17597
- category: z9.string(),
17598
- delta: z9.number(),
18351
+ TrendAttributionSchema = z11.object({
18352
+ category: z11.string(),
18353
+ delta: z11.number(),
17599
18354
  direction: DirectionSchema2,
17600
- description: z9.string()
18355
+ description: z11.string()
17601
18356
  });
17602
- SecurityTrendResultSchema = z9.object({
18357
+ SecurityTrendResultSchema = z11.object({
17603
18358
  score: SecurityTrendLineSchema,
17604
18359
  totalFindings: SecurityTrendLineSchema,
17605
- bySeverity: z9.object({
18360
+ bySeverity: z11.object({
17606
18361
  error: SecurityTrendLineSchema,
17607
18362
  warning: SecurityTrendLineSchema,
17608
18363
  info: SecurityTrendLineSchema
17609
18364
  }),
17610
18365
  supplyChain: SecurityTrendLineSchema,
17611
- snapshotCount: z9.number(),
17612
- from: z9.string(),
17613
- to: z9.string(),
17614
- attribution: z9.array(TrendAttributionSchema)
18366
+ snapshotCount: z11.number(),
18367
+ from: z11.string(),
18368
+ to: z11.string(),
18369
+ attribution: z11.array(TrendAttributionSchema)
17615
18370
  });
17616
- TimeToFixStatsSchema = z9.object({
17617
- mean: z9.number(),
17618
- median: z9.number(),
17619
- count: z9.number()
18371
+ TimeToFixStatsSchema = z11.object({
18372
+ mean: z11.number(),
18373
+ median: z11.number(),
18374
+ count: z11.number()
17620
18375
  });
17621
- TimeToFixResultSchema = z9.object({
18376
+ TimeToFixResultSchema = z11.object({
17622
18377
  overall: TimeToFixStatsSchema,
17623
- byCategory: z9.record(z9.string(), TimeToFixStatsSchema),
17624
- openFindings: z9.number(),
17625
- oldestOpenDays: z9.number().nullable()
18378
+ byCategory: z11.record(z11.string(), TimeToFixStatsSchema),
18379
+ openFindings: z11.number(),
18380
+ oldestOpenDays: z11.number().nullable()
17626
18381
  });
17627
18382
  EMPTY_SUPPLY_CHAIN = {
17628
18383
  critical: 0,
@@ -17637,7 +18392,7 @@ var init_dist3 = __esm({
17637
18392
  timelinePath;
17638
18393
  constructor(rootDir) {
17639
18394
  this.rootDir = rootDir;
17640
- this.timelinePath = join372(rootDir, ".harness", "security", "timeline.json");
18395
+ this.timelinePath = join39(rootDir, ".harness", "security", "timeline.json");
17641
18396
  }
17642
18397
  /**
17643
18398
  * Load timeline from disk.
@@ -18015,8 +18770,8 @@ var init_dist3 = __esm({
18015
18770
  skip: "\u23ED\uFE0F"
18016
18771
  };
18017
18772
  CINotifier = class {
18018
- constructor(adapter, repo) {
18019
- this.adapter = adapter;
18773
+ constructor(adapter2, repo) {
18774
+ this.adapter = adapter2;
18020
18775
  this.repo = repo;
18021
18776
  }
18022
18777
  adapter;
@@ -18667,28 +19422,28 @@ var init_dist3 = __esm({
18667
19422
  POSITION_WEIGHT = 0.5;
18668
19423
  DEPENDENTS_WEIGHT = 0.3;
18669
19424
  AFFINITY_WEIGHT = 0.2;
18670
- InteractionTypeSchema = z10.enum(["question", "confirmation", "transition"]);
18671
- QuestionSchema = z10.object({
18672
- text: z10.string(),
18673
- options: z10.array(z10.string()).optional(),
18674
- default: z10.string().optional()
19425
+ InteractionTypeSchema = z12.enum(["question", "confirmation", "transition"]);
19426
+ QuestionSchema = z12.object({
19427
+ text: z12.string(),
19428
+ options: z12.array(z12.string()).optional(),
19429
+ default: z12.string().optional()
18675
19430
  });
18676
- ConfirmationSchema = z10.object({
18677
- text: z10.string(),
18678
- context: z10.string()
19431
+ ConfirmationSchema = z12.object({
19432
+ text: z12.string(),
19433
+ context: z12.string()
18679
19434
  });
18680
- TransitionSchema = z10.object({
18681
- completedPhase: z10.string(),
18682
- suggestedNext: z10.string(),
18683
- reason: z10.string(),
18684
- artifacts: z10.array(z10.string()),
18685
- requiresConfirmation: z10.boolean(),
18686
- summary: z10.string()
19435
+ TransitionSchema = z12.object({
19436
+ completedPhase: z12.string(),
19437
+ suggestedNext: z12.string(),
19438
+ reason: z12.string(),
19439
+ artifacts: z12.array(z12.string()),
19440
+ requiresConfirmation: z12.boolean(),
19441
+ summary: z12.string()
18687
19442
  });
18688
- EmitInteractionInputSchema = z10.object({
18689
- path: z10.string(),
19443
+ EmitInteractionInputSchema = z12.object({
19444
+ path: z12.string(),
18690
19445
  type: InteractionTypeSchema,
18691
- stream: z10.string().optional(),
19446
+ stream: z12.string().optional(),
18692
19447
  question: QuestionSchema.optional(),
18693
19448
  confirmation: ConfirmationSchema.optional(),
18694
19449
  transition: TransitionSchema.optional()
@@ -18699,10 +19454,10 @@ var init_dist3 = __esm({
18699
19454
  }
18700
19455
  rootDir;
18701
19456
  async scan() {
18702
- let projectName = path28.basename(this.rootDir);
19457
+ let projectName = path30.basename(this.rootDir);
18703
19458
  try {
18704
- const pkgPath = path28.join(this.rootDir, "package.json");
18705
- const pkgRaw = await fs29.readFile(pkgPath, "utf-8");
19459
+ const pkgPath = path30.join(this.rootDir, "package.json");
19460
+ const pkgRaw = await fs31.readFile(pkgPath, "utf-8");
18706
19461
  const pkg = JSON.parse(pkgRaw);
18707
19462
  if (pkg.name) projectName = pkg.name;
18708
19463
  } catch {
@@ -18815,8 +19570,8 @@ console.log('Blueprint player initialized.');
18815
19570
  styles: STYLES,
18816
19571
  scripts: SCRIPTS
18817
19572
  });
18818
- await fs30.mkdir(options.outputDir, { recursive: true });
18819
- await fs30.writeFile(path29.join(options.outputDir, "index.html"), html);
19573
+ await fs32.mkdir(options.outputDir, { recursive: true });
19574
+ await fs32.writeFile(path31.join(options.outputDir, "index.html"), html);
18820
19575
  }
18821
19576
  };
18822
19577
  TOKENS_PER_MILLION = 1e6;
@@ -19039,6 +19794,145 @@ console.log('Blueprint player initialized.');
19039
19794
  POSTHOG_BATCH_URL = "https://app.posthog.com/batch";
19040
19795
  MAX_ATTEMPTS = 3;
19041
19796
  TIMEOUT_MS = 5e3;
19797
+ CompoundLockHeldError = class extends Error {
19798
+ constructor(category, holderPid, lockPath) {
19799
+ super(
19800
+ `Compound lock for category "${category}" is held by pid ${holderPid} (lock file: ${lockPath}). If the holder is no longer running (e.g. it was SIGKILL'd), the lock is stale; recover with: rm ${lockPath}`
19801
+ );
19802
+ this.category = category;
19803
+ this.holderPid = holderPid;
19804
+ this.lockPath = lockPath;
19805
+ this.name = "CompoundLockHeldError";
19806
+ }
19807
+ category;
19808
+ holderPid;
19809
+ lockPath;
19810
+ };
19811
+ KNOWN_CATEGORIES = new Set(ALL_SOLUTION_CATEGORIES);
19812
+ ALLOWED_FIELD_KEYS = [
19813
+ "event_name",
19814
+ "count",
19815
+ "timestamp_bucket",
19816
+ "error_signature",
19817
+ "latency_ms",
19818
+ "category"
19819
+ ];
19820
+ PII_TOKENS = [
19821
+ "email",
19822
+ "user_id",
19823
+ "session_id",
19824
+ "ip",
19825
+ "name",
19826
+ "phone",
19827
+ "address",
19828
+ "message",
19829
+ "content",
19830
+ "payload"
19831
+ ];
19832
+ PII_FIELD_DENYLIST = new RegExp(`^(?:${PII_TOKENS.join("|")})$`, "i");
19833
+ PII_LINE_RE = new RegExp(`\\b(?:${PII_TOKENS.join("|")})\\b`, "i");
19834
+ ALLOWED_SET = new Set(ALLOWED_FIELD_KEYS);
19835
+ PulseAdapterAlreadyRegisteredError = class extends Error {
19836
+ constructor(adapterName) {
19837
+ super(`Pulse adapter "${adapterName}" is already registered.`);
19838
+ this.adapterName = adapterName;
19839
+ this.name = "PulseAdapterAlreadyRegisteredError";
19840
+ }
19841
+ adapterName;
19842
+ };
19843
+ REGISTRY = /* @__PURE__ */ new Map();
19844
+ MOCK_ADAPTER_NAME = "mock";
19845
+ ALLOWED_FIELD_SET = new Set(ALLOWED_FIELD_KEYS);
19846
+ adapter = {
19847
+ async query(_window, _eventNames) {
19848
+ return {
19849
+ event_name: "mock.event",
19850
+ count: 42,
19851
+ timestamp_bucket: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
19852
+ latency_ms: 123
19853
+ };
19854
+ },
19855
+ sanitize(raw) {
19856
+ const fields = {};
19857
+ if (raw && typeof raw === "object") {
19858
+ for (const [key, value] of Object.entries(raw)) {
19859
+ if (PII_FIELD_DENYLIST.test(key)) continue;
19860
+ if (!ALLOWED_FIELD_SET.has(key)) continue;
19861
+ fields[key] = value;
19862
+ }
19863
+ }
19864
+ return { fields, distributions: {} };
19865
+ }
19866
+ };
19867
+ registerMockAdapter();
19868
+ LOOKBACK_RE = /^(\d+)(h|d)$/;
19869
+ MAX_LINES = 40;
19870
+ INLINE_TEMPLATE = `# {{productName}} Pulse \u2014 {{windowLabel}}
19871
+
19872
+ ## Headlines
19873
+
19874
+ {{headlines}}
19875
+
19876
+ ## Usage
19877
+
19878
+ {{usage}}
19879
+
19880
+ ## System performance
19881
+
19882
+ {{systemPerformance}}
19883
+
19884
+ ## Followups
19885
+
19886
+ {{followups}}
19887
+ `;
19888
+ TRUNCATION_MARKER2 = "_(truncated to fit single-page constraint)_";
19889
+ execFileAsync = promisify22(execFile);
19890
+ FIX_RE = /^fix(\([^)]+\))?:/i;
19891
+ EMPTY_REPO_RE = /(does not have any commits yet|not a git repository)/i;
19892
+ execFileAsync2 = promisify3(execFile2);
19893
+ TRACK_CATEGORIES2 = [
19894
+ ["bug-track", BUG_TRACK_CATEGORIES],
19895
+ ["knowledge-track", KNOWLEDGE_TRACK_CATEGORIES]
19896
+ ];
19897
+ STOPWORDS = /* @__PURE__ */ new Set([
19898
+ "fix",
19899
+ "the",
19900
+ "a",
19901
+ "an",
19902
+ "in",
19903
+ "on",
19904
+ "of",
19905
+ "and",
19906
+ "or",
19907
+ "to",
19908
+ "for",
19909
+ "with",
19910
+ "is",
19911
+ "be",
19912
+ "when",
19913
+ "if",
19914
+ "this",
19915
+ "that",
19916
+ "edge",
19917
+ "case",
19918
+ "handle"
19919
+ ]);
19920
+ KEYWORD_TO_CATEGORY = [
19921
+ [/\b(test|flaky|spec)\b/i, "bug-track/test-failures"],
19922
+ [/\b(perf|slow|latency|throughput|timeout|deadlock|n\+1|oom)\b/i, "bug-track/performance-issues"],
19923
+ [
19924
+ /\b(security|sqli|injection|xss|csrf|jwt|oauth|auth(?:n|z|entication)?|crypt(?:o|ographic|ography)?|encrypt(?:ion)?|decrypt(?:ion)?|password|token|session|tls|ssl)\b/i,
19925
+ "bug-track/security-issues"
19926
+ ],
19927
+ [/\b(ui|css|color|contrast|layout|render)\b/i, "bug-track/ui-bugs"],
19928
+ [/\b(build|compile|tsc|webpack|tsup)\b/i, "bug-track/build-errors"],
19929
+ [
19930
+ /\b(db|database|sql|postgres|mysql|query|migration|transaction|deadlock)\b/i,
19931
+ "bug-track/database-issues"
19932
+ ],
19933
+ [/\b(runtime|crash|exception|panic)\b/i, "bug-track/runtime-errors"],
19934
+ [/\(orchestrator\)|\bintegrat|\blease\b|\brace\b|\bconcurren/i, "bug-track/integration-issues"]
19935
+ ];
19042
19936
  }
19043
19937
  });
19044
19938
 
@@ -19095,6 +19989,15 @@ export {
19095
19989
  validateFileStructure,
19096
19990
  validateConfig,
19097
19991
  validateCommitMessage,
19992
+ PulseDbSourceSchema,
19993
+ PulseSourcesSchema,
19994
+ PulseConfigSchema,
19995
+ validatePulseConfig,
19996
+ BUG_TRACK_CATEGORIES,
19997
+ KNOWLEDGE_TRACK_CATEGORIES,
19998
+ ALL_SOLUTION_CATEGORIES,
19999
+ SolutionDocFrontmatterSchema,
20000
+ validateSolutionsDir,
19098
20001
  REQUIRED_SECTIONS,
19099
20002
  extractMarkdownLinks,
19100
20003
  extractSections,
@@ -19438,6 +20341,35 @@ export {
19438
20341
  VERSION,
19439
20342
  collectEvents,
19440
20343
  send,
20344
+ CompoundLockHeldError,
20345
+ acquireCompoundLock,
20346
+ ALLOWED_FIELD_KEYS,
20347
+ PII_TOKENS,
20348
+ PII_FIELD_DENYLIST,
20349
+ PII_LINE_RE,
20350
+ isSanitizedResult,
20351
+ assertSanitized,
20352
+ writePulseConfig,
20353
+ seedFromStrategy,
20354
+ PulseAdapterAlreadyRegisteredError,
20355
+ registerPulseAdapter,
20356
+ getPulseAdapter,
20357
+ listPulseAdapters,
20358
+ clearPulseAdapters,
20359
+ MOCK_ADAPTER_NAME,
20360
+ registerMockAdapter,
20361
+ parseLookback,
20362
+ computeWindow,
20363
+ runPulse,
20364
+ assembleReport,
20365
+ extractHeadlines,
20366
+ isoWeek,
20367
+ formatIsoWeek,
20368
+ gitScan,
20369
+ computeHotspots,
20370
+ crossReferenceUndocumentedFixes,
20371
+ suggestCategory,
20372
+ assembleCandidateReport,
19441
20373
  dist_exports,
19442
20374
  init_dist3 as init_dist
19443
20375
  };