@harness-engineering/cli 2.7.1 → 2.8.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 (139) hide show
  1. package/dist/agents/personas/adversarial-reviewer.yaml +43 -0
  2. package/dist/agents/personas/frontend-races-reviewer.yaml +54 -0
  3. package/dist/agents/personas/typescript-strict-reviewer.yaml +53 -0
  4. package/dist/agents/skills/CHANGELOG.md +12 -0
  5. package/dist/agents/skills/claude-code/align-design-system/SKILL.md +18 -0
  6. package/dist/agents/skills/claude-code/align-design-system/skill.yaml +3 -0
  7. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +37 -5
  8. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +107 -22
  9. package/dist/agents/skills/claude-code/harness-code-review/references/confidence-rubric.md +45 -0
  10. package/dist/agents/skills/claude-code/harness-code-review/references/risk-keywords.md +40 -0
  11. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +3 -0
  12. package/dist/agents/skills/claude-code/harness-compound/SKILL.md +7 -4
  13. package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +277 -0
  14. package/dist/agents/skills/claude-code/harness-ideate/references/scoring.md +88 -0
  15. package/dist/agents/skills/claude-code/harness-ideate/skill.yaml +66 -0
  16. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +14 -4
  17. package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +12 -16
  18. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +34 -6
  19. package/dist/agents/skills/claude-code/harness-strategy/SKILL.md +152 -0
  20. package/dist/agents/skills/claude-code/harness-strategy/references/interview.md +122 -0
  21. package/dist/agents/skills/claude-code/harness-strategy/skill.yaml +54 -0
  22. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +76 -10
  23. package/dist/agents/skills/codex/align-design-system/SKILL.md +18 -0
  24. package/dist/agents/skills/codex/align-design-system/skill.yaml +3 -0
  25. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +37 -5
  26. package/dist/agents/skills/codex/harness-code-review/SKILL.md +107 -22
  27. package/dist/agents/skills/codex/harness-code-review/references/confidence-rubric.md +45 -0
  28. package/dist/agents/skills/codex/harness-code-review/references/risk-keywords.md +40 -0
  29. package/dist/agents/skills/codex/harness-code-review/skill.yaml +3 -0
  30. package/dist/agents/skills/codex/harness-compound/SKILL.md +7 -4
  31. package/dist/agents/skills/codex/harness-ideate/SKILL.md +277 -0
  32. package/dist/agents/skills/codex/harness-ideate/references/scoring.md +88 -0
  33. package/dist/agents/skills/codex/harness-ideate/skill.yaml +66 -0
  34. package/dist/agents/skills/codex/harness-planning/SKILL.md +14 -4
  35. package/dist/agents/skills/codex/harness-pulse/SKILL.md +12 -16
  36. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +34 -6
  37. package/dist/agents/skills/codex/harness-strategy/SKILL.md +152 -0
  38. package/dist/agents/skills/codex/harness-strategy/references/interview.md +122 -0
  39. package/dist/agents/skills/codex/harness-strategy/skill.yaml +54 -0
  40. package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +76 -10
  41. package/dist/agents/skills/cursor/align-design-system/SKILL.md +18 -0
  42. package/dist/agents/skills/cursor/align-design-system/skill.yaml +3 -0
  43. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +37 -5
  44. package/dist/agents/skills/cursor/harness-code-review/SKILL.md +107 -22
  45. package/dist/agents/skills/cursor/harness-code-review/references/confidence-rubric.md +45 -0
  46. package/dist/agents/skills/cursor/harness-code-review/references/risk-keywords.md +40 -0
  47. package/dist/agents/skills/cursor/harness-code-review/skill.yaml +3 -0
  48. package/dist/agents/skills/cursor/harness-compound/SKILL.md +7 -4
  49. package/dist/agents/skills/cursor/harness-ideate/SKILL.md +277 -0
  50. package/dist/agents/skills/cursor/harness-ideate/references/scoring.md +88 -0
  51. package/dist/agents/skills/cursor/harness-ideate/skill.yaml +66 -0
  52. package/dist/agents/skills/cursor/harness-planning/SKILL.md +14 -4
  53. package/dist/agents/skills/cursor/harness-pulse/SKILL.md +12 -16
  54. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +34 -6
  55. package/dist/agents/skills/cursor/harness-strategy/SKILL.md +152 -0
  56. package/dist/agents/skills/cursor/harness-strategy/references/interview.md +122 -0
  57. package/dist/agents/skills/cursor/harness-strategy/skill.yaml +54 -0
  58. package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +76 -10
  59. package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +18 -0
  60. package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +3 -0
  61. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +37 -5
  62. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +107 -22
  63. package/dist/agents/skills/gemini-cli/harness-code-review/references/confidence-rubric.md +45 -0
  64. package/dist/agents/skills/gemini-cli/harness-code-review/references/risk-keywords.md +40 -0
  65. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +3 -0
  66. package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +7 -4
  67. package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +277 -0
  68. package/dist/agents/skills/gemini-cli/harness-ideate/references/scoring.md +88 -0
  69. package/dist/agents/skills/gemini-cli/harness-ideate/skill.yaml +66 -0
  70. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +14 -4
  71. package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +12 -16
  72. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +34 -6
  73. package/dist/agents/skills/gemini-cli/harness-strategy/SKILL.md +152 -0
  74. package/dist/agents/skills/gemini-cli/harness-strategy/references/interview.md +122 -0
  75. package/dist/agents/skills/gemini-cli/harness-strategy/skill.yaml +54 -0
  76. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +76 -10
  77. package/dist/agents/skills/package.json +1 -1
  78. package/dist/agents/skills/tests/harness-strategy.test.ts +145 -0
  79. package/dist/agents-md-WMJO5HSM.js +13 -0
  80. package/dist/analyzer-V633GUHY-MBCQWKDU.js +26 -0
  81. package/dist/{architecture-LUR2I67H.js → architecture-EVYVGPRZ.js} +6 -6
  82. package/dist/{assess-project-OJWECOP2.js → assess-project-KZG563SO.js} +1 -1
  83. package/dist/bin/harness-mcp.js +17 -17
  84. package/dist/bin/harness.js +27 -27
  85. package/dist/{check-phase-gate-HS5KYLRO.js → check-phase-gate-MK364VXS.js} +6 -6
  86. package/dist/{chunk-6UHDQP2N.js → chunk-2N4OENGE.js} +1 -1
  87. package/dist/{chunk-FC4JPM6W.js → chunk-2SNRCAC3.js} +3 -3
  88. package/dist/{chunk-LGYXR2KZ.js → chunk-4BDOSCNY.js} +137 -71
  89. package/dist/{chunk-N5NSSLMU.js → chunk-5XL5QJ5B.js} +2 -2
  90. package/dist/{chunk-LECXPXS3.js → chunk-7EQAZKJ5.js} +2 -2
  91. package/dist/{chunk-LYIPI2SJ.js → chunk-ACOOG3UW.js} +6 -6
  92. package/dist/{chunk-FXZI6NJ2.js → chunk-B7KMTHN3.js} +51 -4
  93. package/dist/{chunk-OH3NXXUY.js → chunk-BDGTZRZ6.js} +11 -1
  94. package/dist/{chunk-NIVWM7OW.js → chunk-C7J55C6E.js} +10 -10
  95. package/dist/{chunk-7PLIWP7U.js → chunk-CAQPSFPT.js} +4042 -738
  96. package/dist/{chunk-TIH53QXY.js → chunk-CLI4K2CH.js} +1 -1
  97. package/dist/{chunk-INBTDBV2.js → chunk-EEFRPEWT.js} +1 -1
  98. package/dist/{chunk-VI4IS55S.js → chunk-FZ5MBXEG.js} +6 -6
  99. package/dist/{chunk-WZY5U6NS.js → chunk-GOHWCHCS.js} +1809 -812
  100. package/dist/{chunk-VSIRUZQP.js → chunk-HRSE6IQD.js} +2 -2
  101. package/dist/{chunk-CZPOPMMI.js → chunk-KBCPELBC.js} +3 -3
  102. package/dist/{chunk-7AF6C5GE.js → chunk-KI6PHH6Q.js} +3 -3
  103. package/dist/{chunk-KN3EMDZ5.js → chunk-LADPYELQ.js} +23 -3
  104. package/dist/{chunk-Y4T6ENKQ.js → chunk-N55WOGN3.js} +86 -17
  105. package/dist/{chunk-H2ZJOJ7A.js → chunk-PP6ZRL5T.js} +316 -42
  106. package/dist/{chunk-RJ2WEES5.js → chunk-STESM73J.js} +2 -2
  107. package/dist/{chunk-B2VAYLYI.js → chunk-UBZQE3JN.js} +2 -2
  108. package/dist/{chunk-GGSNWH7P.js → chunk-UJFNIWC7.js} +5 -5
  109. package/dist/{chunk-FEKBXX2J.js → chunk-UUO4K7NX.js} +9 -9
  110. package/dist/{chunk-Z3TMCCZB.js → chunk-UXPWSV3B.js} +9 -9
  111. package/dist/{chunk-O2ASYKA6.js → chunk-VBNJAKUH.js} +2 -2
  112. package/dist/{chunk-PTHX545Q.js → chunk-X4EFYVCZ.js} +2 -2
  113. package/dist/{ci-workflow-MDSTHJOY.js → ci-workflow-IW2H5DC4.js} +5 -5
  114. package/dist/{dist-E3SAAHCM.js → dist-ICW4QUEW.js} +5 -1
  115. package/dist/{dist-72ID44UE.js → dist-JCFK263L.js} +52 -4
  116. package/dist/{dist-R3TOOPJ7.js → dist-OWHMNL4W.js} +1 -1
  117. package/dist/{docs-2RFOJ6XY.js → docs-7CP6VV42.js} +6 -6
  118. package/dist/engine-MKJEBWU7.js +13 -0
  119. package/dist/{entropy-3UX6644G.js → entropy-6JOZJYG7.js} +5 -5
  120. package/dist/{feedback-CVCFYND4.js → feedback-T65AEJEG.js} +1 -1
  121. package/dist/{generate-agent-definitions-HZ3XENWO.js → generate-agent-definitions-4VI4YTO2.js} +6 -6
  122. package/dist/{glob-helper-EX4YZKZO.js → glob-helper-GLZAURJC.js} +1 -1
  123. package/dist/{graph-loader-EIFEOUVI.js → graph-loader-HHXN5FLP.js} +1 -1
  124. package/dist/index.d.ts +202 -0
  125. package/dist/index.js +27 -27
  126. package/dist/{loader-6RHWU5FH.js → loader-AWTHHE3A.js} +5 -5
  127. package/dist/{mcp-OYR26JDI.js → mcp-JBIBINO2.js} +17 -17
  128. package/dist/{performance-JJMIRXCH.js → performance-NCOUDOMW.js} +6 -6
  129. package/dist/{review-pipeline-BHQZIXWZ.js → review-pipeline-YIC6JPMY.js} +5 -5
  130. package/dist/{runtime-DALTAVTN.js → runtime-5MHV4UEE.js} +5 -5
  131. package/dist/{scan-LYKLM4EQ.js → scan-P7YFKB77.js} +1 -1
  132. package/dist/{security-RMLMYFPB.js → security-VZPJNIDP.js} +1 -1
  133. package/dist/{validate-R7DZRDFK.js → validate-7BE4VTFI.js} +6 -6
  134. package/dist/validate-cross-check-F7GEBRDH.js +13 -0
  135. package/package.json +7 -7
  136. package/dist/agents-md-FKMKH6ZF.js +0 -13
  137. package/dist/analyzer-H3AHBFSL-KPOPJYRB.js +0 -26
  138. package/dist/engine-BSFKOGPN.js +0 -13
  139. package/dist/validate-cross-check-AUUZFNVL.js +0 -13
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  init_dist
3
- } from "./chunk-WZY5U6NS.js";
3
+ } from "./chunk-GOHWCHCS.js";
4
4
  import {
5
5
  Err,
6
6
  Ok
7
- } from "./chunk-OH3NXXUY.js";
7
+ } from "./chunk-BDGTZRZ6.js";
8
8
 
9
9
  // src/mcp/utils/config-resolver.ts
10
10
  init_dist();
@@ -27,7 +27,7 @@ var runSecurityScanDefinition = {
27
27
  };
28
28
  async function handleRunSecurityScan(input) {
29
29
  try {
30
- const core = await import("./dist-72ID44UE.js");
30
+ const core = await import("./dist-JCFK263L.js");
31
31
  const projectRoot = sanitizePath(input.path);
32
32
  let configData = {};
33
33
  try {
@@ -50,7 +50,7 @@ async function handleRunSecurityScan(input) {
50
50
  if (input.files && input.files.length > 0) {
51
51
  filesToScan = input.files.map((f) => path.resolve(projectRoot, f));
52
52
  } else {
53
- const { globFiles } = await import("./glob-helper-EX4YZKZO.js");
53
+ const { globFiles } = await import("./glob-helper-GLZAURJC.js");
54
54
  filesToScan = await globFiles(projectRoot, securityConfig.exclude);
55
55
  }
56
56
  const result = await scanner.scanFiles(filesToScan);
@@ -114,7 +114,7 @@ var getSecurityTrendsDefinition = {
114
114
  };
115
115
  async function handleGetSecurityTrends(input) {
116
116
  try {
117
- const core = await import("./dist-72ID44UE.js");
117
+ const core = await import("./dist-JCFK263L.js");
118
118
  const projectRoot = sanitizePath(input.path);
119
119
  const manager = new core.SecurityTimelineManager(projectRoot);
120
120
  const trendOptions = {};
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveProjectConfig
3
- } from "./chunk-VSIRUZQP.js";
3
+ } from "./chunk-HRSE6IQD.js";
4
4
  import {
5
5
  sanitizePath
6
6
  } from "./chunk-W6Y7ZW3Y.js";
@@ -49,7 +49,7 @@ async function handleValidateProject(input) {
49
49
  checks.config = "pass";
50
50
  const config = configResult.value;
51
51
  try {
52
- const core = await import("./dist-72ID44UE.js");
52
+ const core = await import("./dist-JCFK263L.js");
53
53
  if (typeof core.validateFileStructure === "function" && Array.isArray(config.conventions)) {
54
54
  const conventions = config.conventions;
55
55
  const structureResult = await core.validateFileStructure(projectPath, conventions);
@@ -68,7 +68,7 @@ async function handleValidateProject(input) {
68
68
  } catch {
69
69
  }
70
70
  try {
71
- const core = await import("./dist-72ID44UE.js");
71
+ const core = await import("./dist-JCFK263L.js");
72
72
  if (typeof core.validateAgentsMap === "function") {
73
73
  const agentsMapPath = path.join(projectPath, "AGENTS.md");
74
74
  const agentsResult = await core.validateAgentsMap(agentsMapPath);
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  init_dist,
6
6
  paginate
7
- } from "./chunk-WZY5U6NS.js";
7
+ } from "./chunk-GOHWCHCS.js";
8
8
 
9
9
  // src/mcp/tools/review-pipeline.ts
10
10
  init_dist();
@@ -57,6 +57,11 @@ var runCodeReviewDefinition = {
57
57
  type: "boolean",
58
58
  description: "Skip mechanical checks (useful if already run)"
59
59
  },
60
+ depth: {
61
+ type: "string",
62
+ enum: ["quick", "standard", "deep"],
63
+ description: 'Override Phase 3.5 depth calibration. "deep" forces all conditional subagents (adversarial, typescript-strict, frontend-races).'
64
+ },
60
65
  prNumber: {
61
66
  type: "number",
62
67
  description: "PR number (required for --comment and CI gate)"
@@ -79,7 +84,7 @@ var runCodeReviewDefinition = {
79
84
  };
80
85
  async function handleRunCodeReview(input) {
81
86
  try {
82
- const { parseDiff, runReviewPipeline } = await import("./dist-72ID44UE.js");
87
+ const { parseDiff, runReviewPipeline } = await import("./dist-JCFK263L.js");
83
88
  const parseResult = parseDiff(input.diff);
84
89
  if (!parseResult.ok) {
85
90
  return {
@@ -111,7 +116,8 @@ async function handleRunCodeReview(input) {
111
116
  comment: input.comment ?? false,
112
117
  ci: input.ci ?? false,
113
118
  deep: input.deep ?? false,
114
- noMechanical: input.noMechanical ?? false
119
+ noMechanical: input.noMechanical ?? false,
120
+ ...input.depth != null ? { depth: input.depth } : {}
115
121
  },
116
122
  ...input.repo != null ? { repo: input.repo } : {}
117
123
  });
@@ -130,6 +136,13 @@ async function handleRunCodeReview(input) {
130
136
  assessment: result.assessment,
131
137
  findings: sortedFindings,
132
138
  findingCount: sortedFindings.length,
139
+ depthCalibration: result.depthCalibration ? {
140
+ depth: result.depthCalibration.depth,
141
+ changedLines: result.depthCalibration.changedLines,
142
+ riskSignals: result.depthCalibration.riskSignals,
143
+ activations: [...result.depthCalibration.activations],
144
+ overridden: result.depthCalibration.overridden
145
+ } : void 0,
133
146
  terminalOutput: result.terminalOutput,
134
147
  githubCommentCount: result.githubComments.length,
135
148
  exitCode: result.exitCode
@@ -152,6 +165,13 @@ async function handleRunCodeReview(input) {
152
165
  findings: paged.items,
153
166
  findingCount: result.findings.length,
154
167
  pagination: paged.pagination,
168
+ depthCalibration: result.depthCalibration ? {
169
+ depth: result.depthCalibration.depth,
170
+ changedLines: result.depthCalibration.changedLines,
171
+ riskSignals: result.depthCalibration.riskSignals,
172
+ activations: [...result.depthCalibration.activations],
173
+ overridden: result.depthCalibration.overridden
174
+ } : void 0,
155
175
  terminalOutput: result.terminalOutput,
156
176
  githubCommentCount: result.githubComments.length,
157
177
  exitCode: result.exitCode
@@ -2,12 +2,12 @@ import {
2
2
  Err,
3
3
  Ok,
4
4
  init_dist
5
- } from "./chunk-OH3NXXUY.js";
5
+ } from "./chunk-BDGTZRZ6.js";
6
6
  import {
7
7
  DEFAULT_SKIP_DIRS,
8
8
  init_dist as init_dist2,
9
9
  skipDirGlobs
10
- } from "./chunk-H2ZJOJ7A.js";
10
+ } from "./chunk-PP6ZRL5T.js";
11
11
  import {
12
12
  __esm
13
13
  } from "./chunk-KFQGP6VL.js";
@@ -1605,7 +1605,7 @@ var init_chunk_MUWJHO2S = __esm({
1605
1605
  }
1606
1606
  });
1607
1607
 
1608
- // ../core/dist/chunk-I2JUTTPH.mjs
1608
+ // ../core/dist/chunk-S4DTDJ6J.mjs
1609
1609
  import { resolve as resolve2 } from "path";
1610
1610
  import { minimatch as minimatch2 } from "minimatch";
1611
1611
  import { join, resolve as resolve3 } from "path";
@@ -1882,6 +1882,11 @@ function extractCodeBlocks(content) {
1882
1882
  }
1883
1883
  return blocks;
1884
1884
  }
1885
+ function isLikelySymbolReference(reference) {
1886
+ if (BCP47_LOCALE_RE.test(reference)) return false;
1887
+ if (FILE_REFERENCE_RE.test(reference)) return false;
1888
+ return /^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*(\(.*\))?$/.test(reference);
1889
+ }
1885
1890
  function extractInlineRefs(content) {
1886
1891
  const refs = [];
1887
1892
  const lines = content.split("\n");
@@ -1893,7 +1898,7 @@ function extractInlineRefs(content) {
1893
1898
  while ((match = regex.exec(line)) !== null) {
1894
1899
  const reference = match[1];
1895
1900
  if (reference === void 0) continue;
1896
- if (reference.match(/^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*(\(.*\))?$/)) {
1901
+ if (isLikelySymbolReference(reference)) {
1897
1902
  refs.push({
1898
1903
  reference: reference.replace(/\(.*\)$/, ""),
1899
1904
  // Remove function parens
@@ -2140,6 +2145,10 @@ function findPossibleMatches(reference, exportNames, maxDistance = 5) {
2140
2145
  }
2141
2146
  return matches.sort((a, b) => a.score - b.score).slice(0, 3).map((m) => m.name);
2142
2147
  }
2148
+ function isForwardLookingDoc(docPath, forwardLookingPaths) {
2149
+ const normalized = docPath.replaceAll("\\", "/");
2150
+ return forwardLookingPaths.some((prefix) => normalized.includes(prefix));
2151
+ }
2143
2152
  function checkApiSignatureDrift(snapshot, config) {
2144
2153
  const drifts = [];
2145
2154
  const exportNames = Array.from(snapshot.exportMap.byName.keys());
@@ -2147,6 +2156,9 @@ function checkApiSignatureDrift(snapshot, config) {
2147
2156
  if (config.ignorePatterns.some((p) => ref.reference.match(new RegExp(p)))) {
2148
2157
  continue;
2149
2158
  }
2159
+ if (isForwardLookingDoc(ref.docFile, config.forwardLookingPaths)) {
2160
+ continue;
2161
+ }
2150
2162
  if (!snapshot.exportMap.byName.has(ref.reference)) {
2151
2163
  const possibleMatches = findPossibleMatches(ref.reference, exportNames);
2152
2164
  const confidence = possibleMatches.length > 0 ? "high" : "medium";
@@ -2179,32 +2191,80 @@ function extractFileLinks(content) {
2179
2191
  let match;
2180
2192
  while ((match = linkRegex.exec(line)) !== null) {
2181
2193
  const linkPath = match[2];
2182
- if (linkPath && !linkPath.startsWith("http") && !linkPath.startsWith("#") && (linkPath.includes(".") || linkPath.startsWith(".."))) {
2183
- links.push({ link: linkPath, line: i + 1 });
2184
- }
2194
+ if (!linkPath) continue;
2195
+ if (linkPath.startsWith("http")) continue;
2196
+ if (linkPath.startsWith("#")) continue;
2197
+ if (!linkPath.includes(".") && !linkPath.startsWith("..")) continue;
2198
+ const hashIdx = linkPath.indexOf("#");
2199
+ const filePart = hashIdx === -1 ? linkPath : linkPath.slice(0, hashIdx);
2200
+ const anchorPart = hashIdx === -1 ? void 0 : linkPath.slice(hashIdx + 1);
2201
+ if (!filePart) continue;
2202
+ links.push({
2203
+ raw: linkPath,
2204
+ path: filePart,
2205
+ ...anchorPart ? { anchor: anchorPart } : {},
2206
+ line: i + 1
2207
+ });
2185
2208
  }
2186
2209
  }
2187
2210
  return links;
2188
2211
  }
2212
+ function slugifyHeading(text) {
2213
+ return text.toLowerCase().replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-");
2214
+ }
2215
+ async function extractHeadingSlugs(filePath) {
2216
+ const slugs = /* @__PURE__ */ new Set();
2217
+ let content;
2218
+ try {
2219
+ const fs = await import("fs/promises");
2220
+ content = await fs.readFile(filePath, "utf-8");
2221
+ } catch {
2222
+ return slugs;
2223
+ }
2224
+ const headingRe = /^#{1,6}[ \t]+(.+?)[ \t]*#*\s*$/gm;
2225
+ let m;
2226
+ while ((m = headingRe.exec(content)) !== null) {
2227
+ const heading = m[1];
2228
+ if (heading) slugs.add(slugifyHeading(heading));
2229
+ }
2230
+ return slugs;
2231
+ }
2189
2232
  async function checkStructureDrift(snapshot, _config) {
2190
2233
  const drifts = [];
2191
2234
  for (const doc of snapshot.docs) {
2192
2235
  const fileLinks = extractFileLinks(doc.content);
2193
- for (const { link, line } of fileLinks) {
2194
- const resolvedPath = resolve32(dirname2(doc.path), link);
2236
+ for (const link of fileLinks) {
2237
+ const resolvedPath = resolve32(dirname2(doc.path), link.path);
2195
2238
  const exists = await fileExists(resolvedPath);
2196
2239
  if (!exists) {
2197
2240
  drifts.push({
2198
2241
  type: "structure",
2199
2242
  docFile: doc.path,
2200
- line,
2201
- reference: link,
2243
+ line: link.line,
2244
+ reference: link.raw,
2202
2245
  context: "link",
2203
2246
  issue: "NOT_FOUND",
2204
- details: `File "${link}" referenced in documentation does not exist`,
2247
+ details: `File "${link.path}" referenced in documentation does not exist`,
2205
2248
  suggestion: "Update the link or remove the reference",
2206
2249
  confidence: "high"
2207
2250
  });
2251
+ continue;
2252
+ }
2253
+ if (link.anchor && resolvedPath.toLowerCase().endsWith(".md")) {
2254
+ const slugs = await extractHeadingSlugs(resolvedPath);
2255
+ if (slugs.size > 0 && !slugs.has(link.anchor.toLowerCase())) {
2256
+ drifts.push({
2257
+ type: "structure",
2258
+ docFile: doc.path,
2259
+ line: link.line,
2260
+ reference: link.raw,
2261
+ context: "link-anchor",
2262
+ issue: "NOT_FOUND",
2263
+ details: `Anchor "#${link.anchor}" not found in "${link.path}"`,
2264
+ suggestion: "Check the target file for the correct heading slug",
2265
+ confidence: "medium"
2266
+ });
2267
+ }
2208
2268
  }
2209
2269
  }
2210
2270
  }
@@ -3001,9 +3061,9 @@ function generateSuggestions(deadCode, drift, patterns) {
3001
3061
  estimatedEffort
3002
3062
  };
3003
3063
  }
3004
- var TS_HINTS, TS_CONVENTIONS, PYTHON_HINTS, PYTHON_CONVENTIONS, DEFAULT_INCLUDE_PATTERNS, CODE_BLOCK_LANGUAGES, DEFAULT_DRIFT_CONFIG, JS_EXT_FALLBACKS2, FILE_TYPES, EXPORT_TYPES, CONVENTION_DESCRIPTIONS, RULE_CHECKERS, EntropyAnalyzer;
3005
- var init_chunk_I2JUTTPH = __esm({
3006
- "../core/dist/chunk-I2JUTTPH.mjs"() {
3064
+ var TS_HINTS, TS_CONVENTIONS, PYTHON_HINTS, PYTHON_CONVENTIONS, DEFAULT_INCLUDE_PATTERNS, BCP47_LOCALE_RE, FILE_REFERENCE_RE, CODE_BLOCK_LANGUAGES, DEFAULT_FORWARD_LOOKING_PATHS, DEFAULT_DRIFT_CONFIG, JS_EXT_FALLBACKS2, FILE_TYPES, EXPORT_TYPES, CONVENTION_DESCRIPTIONS, RULE_CHECKERS, EntropyAnalyzer;
3065
+ var init_chunk_S4DTDJ6J = __esm({
3066
+ "../core/dist/chunk-S4DTDJ6J.mjs"() {
3007
3067
  "use strict";
3008
3068
  init_chunk_MUWJHO2S();
3009
3069
  init_dist2();
@@ -3034,13 +3094,22 @@ var init_chunk_I2JUTTPH = __esm({
3034
3094
  "**/*.rs",
3035
3095
  "**/*.java"
3036
3096
  ];
3097
+ BCP47_LOCALE_RE = /^[a-z]{2,3}(?:-[A-Z][a-z]{3})?(?:-[A-Z]{2,4})?$/;
3098
+ FILE_REFERENCE_RE = /\.(md|json|toml|yaml|yml|txt|csv|html|xml|jsonl|env|ini|lock|gitignore|sh|sql)$/i;
3037
3099
  CODE_BLOCK_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "ts", "javascript", "js"]);
3100
+ DEFAULT_FORWARD_LOOKING_PATHS = [
3101
+ "docs/architecture/",
3102
+ "docs/decisions/",
3103
+ "docs/proposals/",
3104
+ "docs/adr/"
3105
+ ];
3038
3106
  DEFAULT_DRIFT_CONFIG = {
3039
3107
  docPaths: [],
3040
3108
  checkApiSignatures: true,
3041
3109
  checkExamples: true,
3042
3110
  checkStructure: true,
3043
- ignorePatterns: []
3111
+ ignorePatterns: [],
3112
+ forwardLookingPaths: DEFAULT_FORWARD_LOOKING_PATHS
3044
3113
  };
3045
3114
  JS_EXT_FALLBACKS2 = {
3046
3115
  ".js": [".ts", ".tsx", ".jsx"],
@@ -3333,5 +3402,5 @@ export {
3333
3402
  detectSizeBudgetViolations,
3334
3403
  generateSuggestions,
3335
3404
  EntropyAnalyzer,
3336
- init_chunk_I2JUTTPH
3405
+ init_chunk_S4DTDJ6J
3337
3406
  };