@oddessentials/odd-ai-reviewers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/README.md +190 -0
  2. package/dist/__tests__/hermetic-setup.d.ts +55 -0
  3. package/dist/__tests__/hermetic-setup.d.ts.map +1 -0
  4. package/dist/__tests__/hermetic-setup.js +62 -0
  5. package/dist/__tests__/hermetic-setup.js.map +1 -0
  6. package/dist/__tests__/test-utils/hermetic.d.ts +84 -0
  7. package/dist/__tests__/test-utils/hermetic.d.ts.map +1 -0
  8. package/dist/__tests__/test-utils/hermetic.js +147 -0
  9. package/dist/__tests__/test-utils/hermetic.js.map +1 -0
  10. package/dist/agents/ai_semantic_review.d.ts +12 -0
  11. package/dist/agents/ai_semantic_review.d.ts.map +1 -0
  12. package/dist/agents/ai_semantic_review.js +317 -0
  13. package/dist/agents/ai_semantic_review.js.map +1 -0
  14. package/dist/agents/control_flow/budget.d.ts +162 -0
  15. package/dist/agents/control_flow/budget.d.ts.map +1 -0
  16. package/dist/agents/control_flow/budget.js +331 -0
  17. package/dist/agents/control_flow/budget.js.map +1 -0
  18. package/dist/agents/control_flow/cfg-builder.d.ts +26 -0
  19. package/dist/agents/control_flow/cfg-builder.d.ts.map +1 -0
  20. package/dist/agents/control_flow/cfg-builder.js +776 -0
  21. package/dist/agents/control_flow/cfg-builder.js.map +1 -0
  22. package/dist/agents/control_flow/cfg-types.d.ts +186 -0
  23. package/dist/agents/control_flow/cfg-types.d.ts.map +1 -0
  24. package/dist/agents/control_flow/cfg-types.js +114 -0
  25. package/dist/agents/control_flow/cfg-types.js.map +1 -0
  26. package/dist/agents/control_flow/finding-generator.d.ts +118 -0
  27. package/dist/agents/control_flow/finding-generator.d.ts.map +1 -0
  28. package/dist/agents/control_flow/finding-generator.js +354 -0
  29. package/dist/agents/control_flow/finding-generator.js.map +1 -0
  30. package/dist/agents/control_flow/index.d.ts +39 -0
  31. package/dist/agents/control_flow/index.d.ts.map +1 -0
  32. package/dist/agents/control_flow/index.js +270 -0
  33. package/dist/agents/control_flow/index.js.map +1 -0
  34. package/dist/agents/control_flow/logger.d.ts +333 -0
  35. package/dist/agents/control_flow/logger.d.ts.map +1 -0
  36. package/dist/agents/control_flow/logger.js +607 -0
  37. package/dist/agents/control_flow/logger.js.map +1 -0
  38. package/dist/agents/control_flow/mitigation-detector.d.ts +207 -0
  39. package/dist/agents/control_flow/mitigation-detector.d.ts.map +1 -0
  40. package/dist/agents/control_flow/mitigation-detector.js +625 -0
  41. package/dist/agents/control_flow/mitigation-detector.js.map +1 -0
  42. package/dist/agents/control_flow/mitigation-patterns.d.ts +53 -0
  43. package/dist/agents/control_flow/mitigation-patterns.d.ts.map +1 -0
  44. package/dist/agents/control_flow/mitigation-patterns.js +620 -0
  45. package/dist/agents/control_flow/mitigation-patterns.js.map +1 -0
  46. package/dist/agents/control_flow/path-analyzer.d.ts +287 -0
  47. package/dist/agents/control_flow/path-analyzer.d.ts.map +1 -0
  48. package/dist/agents/control_flow/path-analyzer.js +695 -0
  49. package/dist/agents/control_flow/path-analyzer.js.map +1 -0
  50. package/dist/agents/control_flow/pattern-validator.d.ts +132 -0
  51. package/dist/agents/control_flow/pattern-validator.d.ts.map +1 -0
  52. package/dist/agents/control_flow/pattern-validator.js +420 -0
  53. package/dist/agents/control_flow/pattern-validator.js.map +1 -0
  54. package/dist/agents/control_flow/timeout-regex.d.ts +144 -0
  55. package/dist/agents/control_flow/timeout-regex.d.ts.map +1 -0
  56. package/dist/agents/control_flow/timeout-regex.js +339 -0
  57. package/dist/agents/control_flow/timeout-regex.js.map +1 -0
  58. package/dist/agents/control_flow/types.d.ts +782 -0
  59. package/dist/agents/control_flow/types.d.ts.map +1 -0
  60. package/dist/agents/control_flow/types.js +428 -0
  61. package/dist/agents/control_flow/types.js.map +1 -0
  62. package/dist/agents/control_flow/vulnerability-detector.d.ts +85 -0
  63. package/dist/agents/control_flow/vulnerability-detector.d.ts.map +1 -0
  64. package/dist/agents/control_flow/vulnerability-detector.js +493 -0
  65. package/dist/agents/control_flow/vulnerability-detector.js.map +1 -0
  66. package/dist/agents/date-utils.d.ts +19 -0
  67. package/dist/agents/date-utils.d.ts.map +1 -0
  68. package/dist/agents/date-utils.js +29 -0
  69. package/dist/agents/date-utils.js.map +1 -0
  70. package/dist/agents/index.d.ts +25 -0
  71. package/dist/agents/index.d.ts.map +1 -0
  72. package/dist/agents/index.js +50 -0
  73. package/dist/agents/index.js.map +1 -0
  74. package/dist/agents/json-utils.d.ts +34 -0
  75. package/dist/agents/json-utils.d.ts.map +1 -0
  76. package/dist/agents/json-utils.js +62 -0
  77. package/dist/agents/json-utils.js.map +1 -0
  78. package/dist/agents/local_llm.d.ts +24 -0
  79. package/dist/agents/local_llm.d.ts.map +1 -0
  80. package/dist/agents/local_llm.js +566 -0
  81. package/dist/agents/local_llm.js.map +1 -0
  82. package/dist/agents/metadata.d.ts +57 -0
  83. package/dist/agents/metadata.d.ts.map +1 -0
  84. package/dist/agents/metadata.js +45 -0
  85. package/dist/agents/metadata.js.map +1 -0
  86. package/dist/agents/opencode.d.ts +18 -0
  87. package/dist/agents/opencode.d.ts.map +1 -0
  88. package/dist/agents/opencode.js +364 -0
  89. package/dist/agents/opencode.js.map +1 -0
  90. package/dist/agents/path-filter.d.ts +25 -0
  91. package/dist/agents/path-filter.d.ts.map +1 -0
  92. package/dist/agents/path-filter.js +43 -0
  93. package/dist/agents/path-filter.js.map +1 -0
  94. package/dist/agents/pr_agent.d.ts +3 -0
  95. package/dist/agents/pr_agent.d.ts.map +1 -0
  96. package/dist/agents/pr_agent.js +312 -0
  97. package/dist/agents/pr_agent.js.map +1 -0
  98. package/dist/agents/retry.d.ts +12 -0
  99. package/dist/agents/retry.d.ts.map +1 -0
  100. package/dist/agents/retry.js +65 -0
  101. package/dist/agents/retry.js.map +1 -0
  102. package/dist/agents/reviewdog.d.ts +24 -0
  103. package/dist/agents/reviewdog.d.ts.map +1 -0
  104. package/dist/agents/reviewdog.js +259 -0
  105. package/dist/agents/reviewdog.js.map +1 -0
  106. package/dist/agents/security.d.ts +49 -0
  107. package/dist/agents/security.d.ts.map +1 -0
  108. package/dist/agents/security.js +302 -0
  109. package/dist/agents/security.js.map +1 -0
  110. package/dist/agents/semgrep.d.ts +8 -0
  111. package/dist/agents/semgrep.d.ts.map +1 -0
  112. package/dist/agents/semgrep.js +157 -0
  113. package/dist/agents/semgrep.js.map +1 -0
  114. package/dist/agents/types.d.ts +450 -0
  115. package/dist/agents/types.d.ts.map +1 -0
  116. package/dist/agents/types.js +127 -0
  117. package/dist/agents/types.js.map +1 -0
  118. package/dist/budget.d.ts +59 -0
  119. package/dist/budget.d.ts.map +1 -0
  120. package/dist/budget.js +82 -0
  121. package/dist/budget.js.map +1 -0
  122. package/dist/cache/key.d.ts +49 -0
  123. package/dist/cache/key.d.ts.map +1 -0
  124. package/dist/cache/key.js +71 -0
  125. package/dist/cache/key.js.map +1 -0
  126. package/dist/cache/store.d.ts +47 -0
  127. package/dist/cache/store.d.ts.map +1 -0
  128. package/dist/cache/store.js +328 -0
  129. package/dist/cache/store.js.map +1 -0
  130. package/dist/cli/commands/check.d.ts +60 -0
  131. package/dist/cli/commands/check.d.ts.map +1 -0
  132. package/dist/cli/commands/check.js +163 -0
  133. package/dist/cli/commands/check.js.map +1 -0
  134. package/dist/cli/commands/index.d.ts +12 -0
  135. package/dist/cli/commands/index.d.ts.map +1 -0
  136. package/dist/cli/commands/index.js +12 -0
  137. package/dist/cli/commands/index.js.map +1 -0
  138. package/dist/cli/commands/local-review.d.ts +149 -0
  139. package/dist/cli/commands/local-review.d.ts.map +1 -0
  140. package/dist/cli/commands/local-review.js +755 -0
  141. package/dist/cli/commands/local-review.js.map +1 -0
  142. package/dist/cli/config-wizard.d.ts +87 -0
  143. package/dist/cli/config-wizard.d.ts.map +1 -0
  144. package/dist/cli/config-wizard.js +240 -0
  145. package/dist/cli/config-wizard.js.map +1 -0
  146. package/dist/cli/dependencies/catalog.d.ts +44 -0
  147. package/dist/cli/dependencies/catalog.d.ts.map +1 -0
  148. package/dist/cli/dependencies/catalog.js +89 -0
  149. package/dist/cli/dependencies/catalog.js.map +1 -0
  150. package/dist/cli/dependencies/checker.d.ts +42 -0
  151. package/dist/cli/dependencies/checker.d.ts.map +1 -0
  152. package/dist/cli/dependencies/checker.js +240 -0
  153. package/dist/cli/dependencies/checker.js.map +1 -0
  154. package/dist/cli/dependencies/index.d.ts +16 -0
  155. package/dist/cli/dependencies/index.d.ts.map +1 -0
  156. package/dist/cli/dependencies/index.js +16 -0
  157. package/dist/cli/dependencies/index.js.map +1 -0
  158. package/dist/cli/dependencies/messages.d.ts +58 -0
  159. package/dist/cli/dependencies/messages.d.ts.map +1 -0
  160. package/dist/cli/dependencies/messages.js +183 -0
  161. package/dist/cli/dependencies/messages.js.map +1 -0
  162. package/dist/cli/dependencies/platform.d.ts +25 -0
  163. package/dist/cli/dependencies/platform.d.ts.map +1 -0
  164. package/dist/cli/dependencies/platform.js +42 -0
  165. package/dist/cli/dependencies/platform.js.map +1 -0
  166. package/dist/cli/dependencies/schemas.d.ts +65 -0
  167. package/dist/cli/dependencies/schemas.d.ts.map +1 -0
  168. package/dist/cli/dependencies/schemas.js +42 -0
  169. package/dist/cli/dependencies/schemas.js.map +1 -0
  170. package/dist/cli/dependencies/types.d.ts +112 -0
  171. package/dist/cli/dependencies/types.d.ts.map +1 -0
  172. package/dist/cli/dependencies/types.js +6 -0
  173. package/dist/cli/dependencies/types.js.map +1 -0
  174. package/dist/cli/dependencies/version.d.ts +67 -0
  175. package/dist/cli/dependencies/version.d.ts.map +1 -0
  176. package/dist/cli/dependencies/version.js +125 -0
  177. package/dist/cli/dependencies/version.js.map +1 -0
  178. package/dist/cli/git-context.d.ts +105 -0
  179. package/dist/cli/git-context.d.ts.map +1 -0
  180. package/dist/cli/git-context.js +313 -0
  181. package/dist/cli/git-context.js.map +1 -0
  182. package/dist/cli/interactive-prompts.d.ts +126 -0
  183. package/dist/cli/interactive-prompts.d.ts.map +1 -0
  184. package/dist/cli/interactive-prompts.js +128 -0
  185. package/dist/cli/interactive-prompts.js.map +1 -0
  186. package/dist/cli/options/index.d.ts +7 -0
  187. package/dist/cli/options/index.d.ts.map +1 -0
  188. package/dist/cli/options/index.js +11 -0
  189. package/dist/cli/options/index.js.map +1 -0
  190. package/dist/cli/options/local-review-options.d.ts +221 -0
  191. package/dist/cli/options/local-review-options.d.ts.map +1 -0
  192. package/dist/cli/options/local-review-options.js +332 -0
  193. package/dist/cli/options/local-review-options.js.map +1 -0
  194. package/dist/cli/output/colors.d.ts +154 -0
  195. package/dist/cli/output/colors.d.ts.map +1 -0
  196. package/dist/cli/output/colors.js +255 -0
  197. package/dist/cli/output/colors.js.map +1 -0
  198. package/dist/cli/output/errors.d.ts +157 -0
  199. package/dist/cli/output/errors.d.ts.map +1 -0
  200. package/dist/cli/output/errors.js +266 -0
  201. package/dist/cli/output/errors.js.map +1 -0
  202. package/dist/cli/output/index.d.ts +12 -0
  203. package/dist/cli/output/index.d.ts.map +1 -0
  204. package/dist/cli/output/index.js +15 -0
  205. package/dist/cli/output/index.js.map +1 -0
  206. package/dist/cli/output/progress.d.ts +237 -0
  207. package/dist/cli/output/progress.d.ts.map +1 -0
  208. package/dist/cli/output/progress.js +405 -0
  209. package/dist/cli/output/progress.js.map +1 -0
  210. package/dist/cli/signals.d.ts +145 -0
  211. package/dist/cli/signals.d.ts.map +1 -0
  212. package/dist/cli/signals.js +223 -0
  213. package/dist/cli/signals.js.map +1 -0
  214. package/dist/cli/validation-report.d.ts +106 -0
  215. package/dist/cli/validation-report.d.ts.map +1 -0
  216. package/dist/cli/validation-report.js +108 -0
  217. package/dist/cli/validation-report.js.map +1 -0
  218. package/dist/config/index.d.ts +9 -0
  219. package/dist/config/index.d.ts.map +1 -0
  220. package/dist/config/index.js +12 -0
  221. package/dist/config/index.js.map +1 -0
  222. package/dist/config/mitigation-config.d.ts +94 -0
  223. package/dist/config/mitigation-config.d.ts.map +1 -0
  224. package/dist/config/mitigation-config.js +430 -0
  225. package/dist/config/mitigation-config.js.map +1 -0
  226. package/dist/config/providers.d.ts +118 -0
  227. package/dist/config/providers.d.ts.map +1 -0
  228. package/dist/config/providers.js +229 -0
  229. package/dist/config/providers.js.map +1 -0
  230. package/dist/config/schemas.d.ts +278 -0
  231. package/dist/config/schemas.d.ts.map +1 -0
  232. package/dist/config/schemas.js +111 -0
  233. package/dist/config/schemas.js.map +1 -0
  234. package/dist/config/zero-config.d.ts +126 -0
  235. package/dist/config/zero-config.d.ts.map +1 -0
  236. package/dist/config/zero-config.js +243 -0
  237. package/dist/config/zero-config.js.map +1 -0
  238. package/dist/config.d.ts +110 -0
  239. package/dist/config.d.ts.map +1 -0
  240. package/dist/config.js +302 -0
  241. package/dist/config.js.map +1 -0
  242. package/dist/diff.d.ts +224 -0
  243. package/dist/diff.d.ts.map +1 -0
  244. package/dist/diff.js +832 -0
  245. package/dist/diff.js.map +1 -0
  246. package/dist/git-validators.d.ts +106 -0
  247. package/dist/git-validators.d.ts.map +1 -0
  248. package/dist/git-validators.js +224 -0
  249. package/dist/git-validators.js.map +1 -0
  250. package/dist/main.d.ts +61 -0
  251. package/dist/main.d.ts.map +1 -0
  252. package/dist/main.js +704 -0
  253. package/dist/main.js.map +1 -0
  254. package/dist/phases/execute.d.ts +60 -0
  255. package/dist/phases/execute.d.ts.map +1 -0
  256. package/dist/phases/execute.js +168 -0
  257. package/dist/phases/execute.js.map +1 -0
  258. package/dist/phases/index.d.ts +9 -0
  259. package/dist/phases/index.d.ts.map +1 -0
  260. package/dist/phases/index.js +9 -0
  261. package/dist/phases/index.js.map +1 -0
  262. package/dist/phases/preflight.d.ts +40 -0
  263. package/dist/phases/preflight.d.ts.map +1 -0
  264. package/dist/phases/preflight.js +122 -0
  265. package/dist/phases/preflight.js.map +1 -0
  266. package/dist/phases/report.d.ts +51 -0
  267. package/dist/phases/report.d.ts.map +1 -0
  268. package/dist/phases/report.js +152 -0
  269. package/dist/phases/report.js.map +1 -0
  270. package/dist/policy.d.ts +33 -0
  271. package/dist/policy.d.ts.map +1 -0
  272. package/dist/policy.js +34 -0
  273. package/dist/policy.js.map +1 -0
  274. package/dist/preflight.d.ts +181 -0
  275. package/dist/preflight.d.ts.map +1 -0
  276. package/dist/preflight.js +627 -0
  277. package/dist/preflight.js.map +1 -0
  278. package/dist/report/ado.d.ts +53 -0
  279. package/dist/report/ado.d.ts.map +1 -0
  280. package/dist/report/ado.js +411 -0
  281. package/dist/report/ado.js.map +1 -0
  282. package/dist/report/agent-icons.d.ts +36 -0
  283. package/dist/report/agent-icons.d.ts.map +1 -0
  284. package/dist/report/agent-icons.js +46 -0
  285. package/dist/report/agent-icons.js.map +1 -0
  286. package/dist/report/base.d.ts +30 -0
  287. package/dist/report/base.d.ts.map +1 -0
  288. package/dist/report/base.js +64 -0
  289. package/dist/report/base.js.map +1 -0
  290. package/dist/report/formats.d.ts +206 -0
  291. package/dist/report/formats.d.ts.map +1 -0
  292. package/dist/report/formats.js +481 -0
  293. package/dist/report/formats.js.map +1 -0
  294. package/dist/report/github.d.ts +44 -0
  295. package/dist/report/github.d.ts.map +1 -0
  296. package/dist/report/github.js +409 -0
  297. package/dist/report/github.js.map +1 -0
  298. package/dist/report/line-resolver.d.ts +208 -0
  299. package/dist/report/line-resolver.d.ts.map +1 -0
  300. package/dist/report/line-resolver.js +578 -0
  301. package/dist/report/line-resolver.js.map +1 -0
  302. package/dist/report/resolution.d.ts +158 -0
  303. package/dist/report/resolution.d.ts.map +1 -0
  304. package/dist/report/resolution.js +272 -0
  305. package/dist/report/resolution.js.map +1 -0
  306. package/dist/report/sanitize.d.ts +32 -0
  307. package/dist/report/sanitize.d.ts.map +1 -0
  308. package/dist/report/sanitize.js +84 -0
  309. package/dist/report/sanitize.js.map +1 -0
  310. package/dist/report/terminal.d.ts +440 -0
  311. package/dist/report/terminal.d.ts.map +1 -0
  312. package/dist/report/terminal.js +840 -0
  313. package/dist/report/terminal.js.map +1 -0
  314. package/dist/reviewignore.d.ts +125 -0
  315. package/dist/reviewignore.d.ts.map +1 -0
  316. package/dist/reviewignore.js +335 -0
  317. package/dist/reviewignore.js.map +1 -0
  318. package/dist/security-logger.d.ts +178 -0
  319. package/dist/security-logger.d.ts.map +1 -0
  320. package/dist/security-logger.js +256 -0
  321. package/dist/security-logger.js.map +1 -0
  322. package/dist/telemetry/backends/console.d.ts +24 -0
  323. package/dist/telemetry/backends/console.d.ts.map +1 -0
  324. package/dist/telemetry/backends/console.js +54 -0
  325. package/dist/telemetry/backends/console.js.map +1 -0
  326. package/dist/telemetry/backends/jsonl.d.ts +31 -0
  327. package/dist/telemetry/backends/jsonl.d.ts.map +1 -0
  328. package/dist/telemetry/backends/jsonl.js +121 -0
  329. package/dist/telemetry/backends/jsonl.js.map +1 -0
  330. package/dist/telemetry/emitter.d.ts +43 -0
  331. package/dist/telemetry/emitter.d.ts.map +1 -0
  332. package/dist/telemetry/emitter.js +83 -0
  333. package/dist/telemetry/emitter.js.map +1 -0
  334. package/dist/telemetry/hook.d.ts +53 -0
  335. package/dist/telemetry/hook.d.ts.map +1 -0
  336. package/dist/telemetry/hook.js +118 -0
  337. package/dist/telemetry/hook.js.map +1 -0
  338. package/dist/telemetry/index.d.ts +58 -0
  339. package/dist/telemetry/index.d.ts.map +1 -0
  340. package/dist/telemetry/index.js +143 -0
  341. package/dist/telemetry/index.js.map +1 -0
  342. package/dist/telemetry/types.d.ts +139 -0
  343. package/dist/telemetry/types.d.ts.map +1 -0
  344. package/dist/telemetry/types.js +133 -0
  345. package/dist/telemetry/types.js.map +1 -0
  346. package/dist/trust.d.ts +65 -0
  347. package/dist/trust.d.ts.map +1 -0
  348. package/dist/trust.js +78 -0
  349. package/dist/trust.js.map +1 -0
  350. package/dist/types/assert-never.d.ts +30 -0
  351. package/dist/types/assert-never.d.ts.map +1 -0
  352. package/dist/types/assert-never.js +32 -0
  353. package/dist/types/assert-never.js.map +1 -0
  354. package/dist/types/branded.d.ts +172 -0
  355. package/dist/types/branded.d.ts.map +1 -0
  356. package/dist/types/branded.js +262 -0
  357. package/dist/types/branded.js.map +1 -0
  358. package/dist/types/errors.d.ts +320 -0
  359. package/dist/types/errors.d.ts.map +1 -0
  360. package/dist/types/errors.js +551 -0
  361. package/dist/types/errors.js.map +1 -0
  362. package/dist/types/index.d.ts +37 -0
  363. package/dist/types/index.d.ts.map +1 -0
  364. package/dist/types/index.js +77 -0
  365. package/dist/types/index.js.map +1 -0
  366. package/dist/types/result.d.ts +323 -0
  367. package/dist/types/result.d.ts.map +1 -0
  368. package/dist/types/result.js +423 -0
  369. package/dist/types/result.js.map +1 -0
  370. package/package.json +63 -0
@@ -0,0 +1,409 @@
1
+ /**
2
+ * GitHub Reporter
3
+ * Posts findings as PR comments and check run summaries
4
+ * Includes deduplication and throttling
5
+ */
6
+ import { Octokit } from '@octokit/rest';
7
+ import { deduplicateFindings, sortFindings, generateSummaryMarkdown, renderPartialFindingsSection, toGitHubAnnotation, countBySeverity, extractFingerprintMarkers, getDedupeKey, buildProximityMap, isDuplicateByProximity, identifyStaleComments, updateProximityMap, } from './formats.js';
8
+ import { buildCommentToMarkersMap, shouldResolveComment, getPartiallyResolvedMarkers, hasMalformedMarkers, applyPartialResolutionVisual, stripOwnFingerprintMarkers, emitResolutionLog, emitMalformedMarkerWarning, } from './resolution.js';
9
+ import { canonicalizeDiffFiles } from '../diff.js';
10
+ import { delay, INLINE_COMMENT_DELAY_MS, formatInlineComment, formatGroupedInlineComment, } from './base.js';
11
+ import { buildLineResolver, normalizeFindingsForDiff, computeDriftSignal, generateDriftMarkdown, } from './line-resolver.js';
12
+ /**
13
+ * Start a check run in 'in_progress' state
14
+ * Call this at the beginning of the review to show users the review is running
15
+ */
16
+ export async function startCheckRun(context) {
17
+ const octokit = new Octokit({ auth: context.token });
18
+ const response = await octokit.checks.create({
19
+ owner: context.owner,
20
+ repo: context.repo,
21
+ name: 'AI Code Review',
22
+ head_sha: context.headSha,
23
+ status: 'in_progress',
24
+ started_at: new Date().toISOString(),
25
+ output: {
26
+ title: 'AI Code Review in progress...',
27
+ summary: 'Analyzing code changes. This may take a moment.',
28
+ },
29
+ });
30
+ console.log(`[github] Started check run ${response.data.id} (in_progress)`);
31
+ return response.data.id;
32
+ }
33
+ /**
34
+ * Post findings to GitHub
35
+ *
36
+ * (012-fix-agent-result-regressions) - Now accepts partialFindings to include
37
+ * in check summaries and PR comments. Partial findings are rendered in a dedicated
38
+ * section that makes clear they're from failed agents and don't affect gating.
39
+ */
40
+ export async function reportToGitHub(findings, partialFindings, context, config, diffFiles) {
41
+ const octokit = new Octokit({ auth: context.token });
42
+ const reportingConfig = config.reporting.github ?? {
43
+ mode: 'checks_and_comments',
44
+ max_inline_comments: 20,
45
+ summary: true,
46
+ };
47
+ // CANONICAL ENTRYPOINT: Ensure all diff paths are normalized FIRST
48
+ // This must happen before buildLineResolver, deleted set, or rename maps
49
+ const canonicalFiles = canonicalizeDiffFiles(diffFiles);
50
+ // Build line resolver and normalize findings from canonical files
51
+ const lineResolver = buildLineResolver(canonicalFiles);
52
+ const normalizationResult = normalizeFindingsForDiff(findings, lineResolver);
53
+ if (normalizationResult.stats.dropped > 0 || normalizationResult.stats.normalized > 0) {
54
+ console.log(`[github] Line validation: ${normalizationResult.stats.valid} valid, ` +
55
+ `${normalizationResult.stats.normalized} normalized, ${normalizationResult.stats.dropped} dropped`);
56
+ }
57
+ // Compute drift signal for visibility in check summary
58
+ const driftSignal = computeDriftSignal(normalizationResult.stats, normalizationResult.invalidDetails);
59
+ // Process normalized findings
60
+ const deduplicated = deduplicateFindings(normalizationResult.findings);
61
+ const sorted = sortFindings(deduplicated);
62
+ const counts = countBySeverity(sorted);
63
+ try {
64
+ let checkRunId;
65
+ let commentId;
66
+ let skippedDuplicates = 0;
67
+ // Create check run if enabled
68
+ if (reportingConfig.mode === 'checks_only' || reportingConfig.mode === 'checks_and_comments') {
69
+ checkRunId = await createCheckRun(octokit, context, sorted, partialFindings, counts, config, driftSignal);
70
+ }
71
+ // Post PR comment if enabled and we have a PR number
72
+ if (context.prNumber &&
73
+ (reportingConfig.mode === 'comments_only' || reportingConfig.mode === 'checks_and_comments')) {
74
+ // Build set of deleted files for belt-and-suspenders guard in postPRComment
75
+ // FR-003: Use canonicalFiles for path normalization consistency with findings
76
+ const deletedFiles = new Set(canonicalFiles.filter((f) => f.status === 'deleted').map((f) => f.path));
77
+ const result = await postPRComment(octokit, context, sorted, partialFindings, reportingConfig.max_inline_comments, deletedFiles);
78
+ commentId = result.commentId;
79
+ skippedDuplicates = result.skippedDuplicates;
80
+ }
81
+ return {
82
+ success: true,
83
+ checkRunId,
84
+ commentId,
85
+ skippedDuplicates,
86
+ validationStats: normalizationResult.stats,
87
+ invalidLineDetails: normalizationResult.invalidDetails.length > 0
88
+ ? normalizationResult.invalidDetails
89
+ : undefined,
90
+ };
91
+ }
92
+ catch (error) {
93
+ return {
94
+ success: false,
95
+ error: error instanceof Error ? error.message : 'Unknown error',
96
+ };
97
+ }
98
+ }
99
+ /**
100
+ * Create or update a GitHub check run with annotations
101
+ * If context.checkRunId is provided, updates existing check run (proper lifecycle)
102
+ * Otherwise creates a new check run (legacy/fallback behavior)
103
+ *
104
+ * (012-fix-agent-result-regressions) - Now includes partialFindings in summary
105
+ */
106
+ async function createCheckRun(octokit, context, findings, partialFindings, counts, config, driftSignal) {
107
+ // Determine conclusion based on gating config
108
+ let conclusion = 'success';
109
+ if (config.gating.enabled) {
110
+ if (config.gating.fail_on_severity === 'error' && counts.error > 0) {
111
+ conclusion = 'failure';
112
+ }
113
+ else if (config.gating.fail_on_severity === 'warning' &&
114
+ (counts.error > 0 || counts.warning > 0)) {
115
+ conclusion = 'failure';
116
+ }
117
+ else if (config.gating.fail_on_severity === 'info' &&
118
+ (counts.error > 0 || counts.warning > 0 || counts.info > 0)) {
119
+ conclusion = 'failure';
120
+ }
121
+ }
122
+ // Convert findings to annotations (max 50 per request)
123
+ const annotations = findings
124
+ .map(toGitHubAnnotation)
125
+ .filter((a) => a !== null)
126
+ .slice(0, 50);
127
+ const summary = generateSummaryMarkdown(findings);
128
+ // (012-fix-agent-result-regressions) - Append partial findings section if present
129
+ const partialSection = renderPartialFindingsSection(partialFindings);
130
+ // Append drift signal to summary (only shows when warn/fail threshold exceeded)
131
+ const driftMarkdown = generateDriftMarkdown(driftSignal);
132
+ const fullSummary = summary + partialSection + driftMarkdown;
133
+ const output = {
134
+ title: `AI Review: ${counts.error} errors, ${counts.warning} warnings, ${counts.info} info`,
135
+ summary: fullSummary,
136
+ annotations,
137
+ };
138
+ // If we have an existing check run ID, update it (proper lifecycle)
139
+ if (context.checkRunId) {
140
+ await octokit.checks.update({
141
+ owner: context.owner,
142
+ repo: context.repo,
143
+ check_run_id: context.checkRunId,
144
+ status: 'completed',
145
+ conclusion,
146
+ completed_at: new Date().toISOString(),
147
+ output,
148
+ });
149
+ console.log(`[github] Updated check run ${context.checkRunId} with conclusion: ${conclusion}`);
150
+ return context.checkRunId;
151
+ }
152
+ // Fallback: create new check run (legacy behavior if startCheckRun wasn't called)
153
+ const response = await octokit.checks.create({
154
+ owner: context.owner,
155
+ repo: context.repo,
156
+ name: 'AI Code Review',
157
+ head_sha: context.headSha,
158
+ status: 'completed',
159
+ conclusion,
160
+ output,
161
+ });
162
+ console.log(`[github] Created check run ${response.data.id} with conclusion: ${conclusion}`);
163
+ return response.data.id;
164
+ }
165
+ /**
166
+ * Post a summary comment on the PR with deduplication
167
+ */
168
+ async function postPRComment(octokit, context, findings, partialFindings, maxInlineComments, deletedFiles = new Set()) {
169
+ if (!context.prNumber) {
170
+ throw new Error('PR number required for comments');
171
+ }
172
+ // (012-fix-agent-result-regressions) - Include partial findings section in PR comment
173
+ const summary = generateSummaryMarkdown(findings) + renderPartialFindingsSection(partialFindings);
174
+ // Find existing comment to update
175
+ const existingComments = await octokit.issues.listComments({
176
+ owner: context.owner,
177
+ repo: context.repo,
178
+ issue_number: context.prNumber,
179
+ });
180
+ const botComment = existingComments.data.find((c) => c.user?.type === 'Bot' && c.body?.includes('## AI Code Review Summary'));
181
+ let commentId;
182
+ if (botComment) {
183
+ // Update existing comment
184
+ const response = await octokit.issues.updateComment({
185
+ owner: context.owner,
186
+ repo: context.repo,
187
+ comment_id: botComment.id,
188
+ body: summary,
189
+ });
190
+ commentId = response.data.id;
191
+ console.log(`[github] Updated existing comment ${commentId}`);
192
+ }
193
+ else {
194
+ // Create new comment
195
+ const response = await octokit.issues.createComment({
196
+ owner: context.owner,
197
+ repo: context.repo,
198
+ issue_number: context.prNumber,
199
+ body: summary,
200
+ });
201
+ commentId = response.data.id;
202
+ console.log(`[github] Created new comment ${commentId}`);
203
+ }
204
+ // Get existing review comments for deduplication
205
+ const existingReviewComments = await octokit.pulls.listReviewComments({
206
+ owner: context.owner,
207
+ repo: context.repo,
208
+ pull_number: context.prNumber,
209
+ });
210
+ // Build set of existing comment fingerprints and map to comment IDs for resolution
211
+ const existingDedupeKeys = [];
212
+ const dedupeKeyToCommentId = new Map();
213
+ for (const comment of existingReviewComments.data) {
214
+ if (comment.body) {
215
+ const markers = extractFingerprintMarkers(comment.body);
216
+ for (const marker of markers) {
217
+ existingDedupeKeys.push(marker);
218
+ dedupeKeyToCommentId.set(marker, comment.id);
219
+ }
220
+ }
221
+ }
222
+ // Build proximity-based deduplication structures
223
+ const existingFingerprintSet = new Set(existingDedupeKeys);
224
+ const proximityMap = buildProximityMap(existingDedupeKeys);
225
+ // Filter findings for inline comments
226
+ // Belt-and-suspenders: also filter out deleted files (should already be file-level)
227
+ const inlineFindings = findings
228
+ .filter((f) => f.line !== undefined && !deletedFiles.has(f.file))
229
+ .sort((a, b) => {
230
+ // Sort by severity (error > warning > info)
231
+ const severityOrder = { error: 0, warning: 1, info: 2 };
232
+ return (severityOrder[a.severity] ?? 2) - (severityOrder[b.severity] ?? 2);
233
+ });
234
+ // Group adjacent findings (within 3 lines of each other in same file)
235
+ const groupedFindings = groupAdjacentFindings(inlineFindings);
236
+ let skippedDuplicates = 0;
237
+ let postedCount = 0;
238
+ for (const findingOrGroup of groupedFindings) {
239
+ if (postedCount >= maxInlineComments)
240
+ break;
241
+ const findingsInGroup = Array.isArray(findingOrGroup) ? findingOrGroup : [findingOrGroup];
242
+ // Use proximity-based deduplication: skip if ALL findings in group are duplicates
243
+ // A finding is a duplicate if:
244
+ // 1. Exact dedupe key match (same fingerprint + file + line), OR
245
+ // 2. Same fingerprint+file within LINE_PROXIMITY_THRESHOLD lines
246
+ const allDuplicates = findingsInGroup.every((f) => isDuplicateByProximity(f, existingFingerprintSet, proximityMap));
247
+ if (allDuplicates) {
248
+ skippedDuplicates++;
249
+ continue;
250
+ }
251
+ const finding = findingsInGroup[0];
252
+ if (!finding)
253
+ continue;
254
+ const body = Array.isArray(findingOrGroup)
255
+ ? formatGroupedInlineComment(findingOrGroup)
256
+ : formatInlineComment(finding);
257
+ try {
258
+ const commentParams = {
259
+ owner: context.owner,
260
+ repo: context.repo,
261
+ pull_number: context.prNumber,
262
+ body,
263
+ commit_id: context.headSha,
264
+ path: finding.file,
265
+ line: finding.line,
266
+ side: 'RIGHT', // Always comment on new file (right side of diff)
267
+ };
268
+ // Add multi-line comment support if endLine is present
269
+ if (finding.endLine && finding.endLine !== finding.line) {
270
+ commentParams.start_line = finding.line;
271
+ commentParams.start_side = 'RIGHT';
272
+ commentParams.line = finding.endLine;
273
+ }
274
+ await octokit.pulls.createReviewComment(commentParams);
275
+ postedCount++;
276
+ // Update tracking structures with newly posted findings
277
+ for (const f of findingsInGroup) {
278
+ const key = getDedupeKey(f);
279
+ existingFingerprintSet.add(key);
280
+ // FR-001: Update proximityMap using canonical pattern
281
+ updateProximityMap(proximityMap, f);
282
+ }
283
+ // Rate limiting delay
284
+ await delay(INLINE_COMMENT_DELAY_MS);
285
+ }
286
+ catch (error) {
287
+ // Inline comments can fail for various reasons (line not in diff, etc.)
288
+ console.warn(`[github] Failed to post inline comment: ${error}`);
289
+ }
290
+ }
291
+ // Resolve stale comments (comments for issues that no longer exist)
292
+ // FIX: Use grouped comment resolution - only resolve when ALL markers are stale
293
+ const staleKeys = identifyStaleComments(existingDedupeKeys, findings);
294
+ const staleKeySet = new Set(staleKeys);
295
+ // Build reverse map: commentId -> all markers in that comment
296
+ const commentIdToMarkers = buildCommentToMarkersMap(dedupeKeyToCommentId);
297
+ // Track which comments we've already processed to avoid duplicate API calls
298
+ const processedCommentIds = new Set();
299
+ let resolvedCount = 0;
300
+ let partiallyResolvedCount = 0;
301
+ // Process each comment that has at least one stale marker
302
+ for (const staleKey of staleKeys) {
303
+ const commentIdToProcess = dedupeKeyToCommentId.get(staleKey);
304
+ if (!commentIdToProcess || processedCommentIds.has(commentIdToProcess))
305
+ continue;
306
+ processedCommentIds.add(commentIdToProcess);
307
+ // Get ALL markers for this comment
308
+ const allMarkersInComment = commentIdToMarkers.get(commentIdToProcess) ?? [];
309
+ // Emit warning if any markers are malformed (FR-010: exactly one warning per comment)
310
+ if (hasMalformedMarkers(allMarkersInComment)) {
311
+ emitMalformedMarkerWarning('github', commentIdToProcess);
312
+ }
313
+ // Check if comment should be resolved (ALL markers must be stale)
314
+ const shouldResolve = shouldResolveComment(allMarkersInComment, staleKeySet);
315
+ // Get partially resolved markers for visual indication
316
+ const partiallyResolved = getPartiallyResolvedMarkers(allMarkersInComment, staleKeySet);
317
+ // Emit resolution log (once per comment per run)
318
+ // FR-005: Simplified staleCount calculation for clarity
319
+ const staleCount = shouldResolve ? allMarkersInComment.length : partiallyResolved.length;
320
+ emitResolutionLog('github', commentIdToProcess, allMarkersInComment.length, staleCount, shouldResolve);
321
+ try {
322
+ // Get the existing comment to preserve its content
323
+ // Note: O(n) linear search is acceptable here - only called once per processed comment
324
+ // (not per marker), and processedCommentIds prevents duplicates. For enterprise PRs
325
+ // with 1000+ comments, consider indexing existingReviewComments.data by ID upfront.
326
+ const existingComment = existingReviewComments.data.find((c) => c.id === commentIdToProcess);
327
+ if (!existingComment?.body)
328
+ continue;
329
+ // Skip if already marked as fully resolved
330
+ if (existingComment.body.includes('✅ **Resolved**')) {
331
+ continue;
332
+ }
333
+ if (shouldResolve) {
334
+ // ALL markers are stale - resolve the entire comment
335
+ // Strip only our fingerprint markers, preserving any user-added HTML comments (FR-019)
336
+ const bodyWithoutOurMarkers = stripOwnFingerprintMarkers(existingComment.body);
337
+ const resolvedBody = `~~${bodyWithoutOurMarkers}~~\n\n` +
338
+ `✅ **Resolved** - This issue appears to have been fixed.\n\n` +
339
+ allMarkersInComment
340
+ .map((m) => `<!-- odd-ai-reviewers:fingerprint:v1:${m} -->`)
341
+ .join('\n');
342
+ await octokit.pulls.updateReviewComment({
343
+ owner: context.owner,
344
+ repo: context.repo,
345
+ comment_id: commentIdToProcess,
346
+ body: resolvedBody,
347
+ });
348
+ resolvedCount++;
349
+ }
350
+ else if (partiallyResolved.length > 0) {
351
+ // Only SOME markers are stale - apply visual indication (strikethrough)
352
+ const updatedBody = applyPartialResolutionVisual(existingComment.body, partiallyResolved);
353
+ // Only update if the body actually changed
354
+ if (updatedBody !== existingComment.body) {
355
+ await octokit.pulls.updateReviewComment({
356
+ owner: context.owner,
357
+ repo: context.repo,
358
+ comment_id: commentIdToProcess,
359
+ body: updatedBody,
360
+ });
361
+ partiallyResolvedCount++;
362
+ }
363
+ }
364
+ await delay(INLINE_COMMENT_DELAY_MS);
365
+ }
366
+ catch (error) {
367
+ console.warn(`[github] Failed to resolve/update comment ${commentIdToProcess}: ${error}`);
368
+ }
369
+ }
370
+ console.log(`[github] Posted ${postedCount} inline comments, skipped ${skippedDuplicates} duplicates, resolved ${resolvedCount} comments, ${partiallyResolvedCount} partially resolved`);
371
+ return { commentId, skippedDuplicates };
372
+ }
373
+ /**
374
+ * Group adjacent findings (within 3 lines in the same file)
375
+ */
376
+ function groupAdjacentFindings(findings) {
377
+ if (findings.length === 0)
378
+ return [];
379
+ const result = [];
380
+ const firstFinding = findings[0];
381
+ if (!firstFinding)
382
+ return [];
383
+ let currentGroup = [firstFinding];
384
+ for (let i = 1; i < findings.length; i++) {
385
+ const prev = currentGroup[currentGroup.length - 1];
386
+ const curr = findings[i];
387
+ if (!prev || !curr)
388
+ continue;
389
+ // Group if same file and within 3 lines
390
+ if (prev.file === curr.file && Math.abs(curr.line - prev.line) <= 3) {
391
+ currentGroup.push(curr);
392
+ }
393
+ else {
394
+ // Finish current group
395
+ const firstInGroup = currentGroup[0];
396
+ if (firstInGroup) {
397
+ result.push(currentGroup.length === 1 ? firstInGroup : currentGroup);
398
+ }
399
+ currentGroup = [curr];
400
+ }
401
+ }
402
+ // Don't forget the last group
403
+ const firstInGroup = currentGroup[0];
404
+ if (firstInGroup) {
405
+ result.push(currentGroup.length === 1 ? firstInGroup : currentGroup);
406
+ }
407
+ return result;
408
+ }
409
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/report/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Line Resolver Module
3
+ *
4
+ * Resolves and validates finding line numbers against unified diffs to prevent
5
+ * misaligned inline comments on GitHub and Azure DevOps.
6
+ *
7
+ * Design Philosophy:
8
+ * - Early normalization before deduplication (INVARIANTS #22)
9
+ * - Comprehensive validation with detailed reporting
10
+ * - Agent-aware resolution (LLMs may emit diff lines, static tools emit file lines)
11
+ * - Graceful degradation (drop unresolvable lines to file-level comments)
12
+ */
13
+ import type { CanonicalDiffFile } from '../diff.js';
14
+ import type { Finding } from '../agents/types.js';
15
+ /**
16
+ * Represents a single diff hunk with line tracking
17
+ */
18
+ export interface DiffHunk {
19
+ /** Starting line number in the new file (from @@ header) */
20
+ newFileStart: number;
21
+ /** All valid line numbers in new file (added + context) */
22
+ newFileLines: number[];
23
+ /** Line numbers for added lines only ('+' prefix) */
24
+ addedLines: number[];
25
+ /** Line numbers for context lines only (' ' prefix) */
26
+ contextLines: number[];
27
+ }
28
+ /**
29
+ * Per-file mapping of valid lines from diff
30
+ */
31
+ export interface FileLineMapping {
32
+ /** All valid commentable lines (added + context) */
33
+ allLines: Set<number>;
34
+ /** Only added lines ('+' prefix in diff) */
35
+ addedLines: Set<number>;
36
+ /** Only context lines (' ' prefix in diff) */
37
+ contextLines: Set<number>;
38
+ /** Hunk metadata for debugging and summaries */
39
+ hunks: DiffHunk[];
40
+ }
41
+ /**
42
+ * Result of validating a single line number
43
+ */
44
+ export interface LineValidationResult {
45
+ /** Whether the line is valid for commenting */
46
+ valid: boolean;
47
+ /** The line number being validated */
48
+ line: number;
49
+ /** Whether this is an added line (vs context line) */
50
+ isAddition?: boolean;
51
+ /** Reason for invalid line (if applicable) */
52
+ reason?: string;
53
+ /** Suggested nearest valid line (if requested and available) */
54
+ nearestValidLine?: number;
55
+ }
56
+ /**
57
+ * Statistics from finding normalization (fine-grained accounting)
58
+ */
59
+ export interface ValidationStats {
60
+ /** Total findings processed */
61
+ total: number;
62
+ /** Findings with valid lines (no changes needed) */
63
+ valid: number;
64
+ /** Findings auto-fixed to nearest valid line */
65
+ normalized: number;
66
+ /** Findings downgraded to file-level (invalid line or deleted file) */
67
+ downgraded: number;
68
+ /** Findings dropped entirely (removed) */
69
+ dropped: number;
70
+ /** Subset of downgraded: findings on deleted files */
71
+ deletedFiles: number;
72
+ /** Subset of downgraded: findings on ambiguous rename paths */
73
+ ambiguousRenames: number;
74
+ /** Findings remapped from old path to new path (successful rename handling) */
75
+ remappedPaths: number;
76
+ }
77
+ /**
78
+ * Details about an invalid line finding
79
+ */
80
+ export interface InvalidLineDetail {
81
+ file: string;
82
+ line?: number;
83
+ reason: string;
84
+ nearestValidLine?: number;
85
+ sourceAgent?: string;
86
+ }
87
+ /**
88
+ * Line resolver interface for validating and normalizing line numbers
89
+ */
90
+ export interface LineResolver {
91
+ /** Validate a line number for a file */
92
+ validateLine(filePath: string, line: number | undefined, options?: LineValidationOptions): LineValidationResult;
93
+ /** Get debug summary for a file */
94
+ getFileSummary(filePath: string): string;
95
+ /** Check if a file exists in the diff */
96
+ hasFile(filePath: string): boolean;
97
+ /** Check if a file is deleted (no inline comments allowed) */
98
+ isDeleted(filePath: string): boolean;
99
+ /**
100
+ * Remap an old path to its new canonical path (for renames)
101
+ * Returns the new path if rename mapping exists, otherwise returns original path
102
+ */
103
+ remapPath(filePath: string): string;
104
+ /**
105
+ * Check if a path mapping is ambiguous (multiple old paths map to same new path)
106
+ * Ambiguous renames should be downgraded to file-level comments
107
+ */
108
+ isAmbiguousRename(filePath: string): boolean;
109
+ }
110
+ export interface LineValidationOptions {
111
+ /** Only accept added lines ('+'), not context lines */
112
+ additionsOnly?: boolean;
113
+ /** Find and suggest nearest valid line when invalid */
114
+ suggestNearest?: boolean;
115
+ /** Agent source for resolution strategy */
116
+ sourceAgent?: string;
117
+ }
118
+ /**
119
+ * Parse unified diff hunks from a patch string
120
+ *
121
+ * Extracts line number information from diff hunks, distinguishing:
122
+ * - Added lines ('+' prefix) - exist in new file
123
+ * - Deleted lines ('-' prefix) - do NOT exist in new file
124
+ * - Context lines (' ' prefix) - exist in new file
125
+ *
126
+ * @param patch - Unified diff patch content
127
+ * @returns Array of parsed hunks with line tracking
128
+ */
129
+ export declare function parseDiffHunks(patch: string): DiffHunk[];
130
+ /**
131
+ * Build a line resolver from diff files
132
+ *
133
+ * @param files - Array of DiffFile objects with patches
134
+ * @returns LineResolver instance for validation and normalization
135
+ */
136
+ export declare function buildLineResolver(files: CanonicalDiffFile[]): LineResolver;
137
+ /**
138
+ * Normalize findings against diff, validating and adjusting line numbers
139
+ *
140
+ * Strategy:
141
+ * - Valid lines pass through unchanged
142
+ * - Invalid lines are dropped (line set to undefined) for file-level comment
143
+ * - Stats and invalid details are collected for reporting
144
+ *
145
+ * @param findings - Array of findings to normalize
146
+ * @param resolver - Line resolver built from diff
147
+ * @param options - Normalization options
148
+ * @returns Normalized findings with statistics
149
+ */
150
+ export declare function normalizeFindingsForDiff(findings: Finding[], resolver: LineResolver, options?: {
151
+ additionsOnly?: boolean;
152
+ autoFix?: boolean;
153
+ }): {
154
+ findings: Finding[];
155
+ stats: ValidationStats;
156
+ invalidDetails: InvalidLineDetail[];
157
+ };
158
+ /**
159
+ * Drift signal result - indicates overall health of line validation
160
+ */
161
+ export interface DriftSignal {
162
+ /** Signal level: ok (< warn threshold), warn (< fail threshold), fail (>= fail threshold) */
163
+ level: 'ok' | 'warn' | 'fail';
164
+ /** Degradation percentage (dropped + downgraded) / total */
165
+ degradationPercent: number;
166
+ /** Auto-fix percentage (normalized) / total */
167
+ autoFixPercent: number;
168
+ /** Human-readable message explaining the signal */
169
+ message: string;
170
+ /** Top invalid samples for debugging (up to maxSamples) */
171
+ samples: InvalidLineDetail[];
172
+ }
173
+ /**
174
+ * Configuration for drift signal thresholds
175
+ */
176
+ export interface DriftConfig {
177
+ /** Warn threshold for degradation percentage (default: 20) */
178
+ warnThresholdPercent: number;
179
+ /** Fail threshold for degradation percentage (default: 50) */
180
+ failThresholdPercent: number;
181
+ /** Maximum samples to include in signal (default: 5) */
182
+ maxSamples: number;
183
+ }
184
+ /** Default drift configuration */
185
+ export declare const DEFAULT_DRIFT_CONFIG: DriftConfig;
186
+ /**
187
+ * Compute drift signal from validation stats and invalid details
188
+ *
189
+ * This provides an enterprise-grade health check for line validation:
190
+ * - ok: Everything is fine, degradation is within acceptable limits
191
+ * - warn: Degradation is concerning, should investigate
192
+ * - fail: Degradation is too high, likely indicates a systemic issue
193
+ *
194
+ * @param stats - Validation statistics from normalizeFindingsForDiff
195
+ * @param invalidDetails - Details about invalid lines
196
+ * @param config - Optional configuration for thresholds
197
+ * @returns DriftSignal indicating health and samples for debugging
198
+ */
199
+ export declare function computeDriftSignal(stats: ValidationStats, invalidDetails: InvalidLineDetail[], config?: Partial<DriftConfig>): DriftSignal;
200
+ /**
201
+ * Generate markdown section for drift signal to include in check summaries
202
+ * Only generates content when drift level is warn or fail
203
+ *
204
+ * @param drift - Computed drift signal
205
+ * @returns Markdown string (empty if level is 'ok')
206
+ */
207
+ export declare function generateDriftMarkdown(drift: DriftSignal): string;
208
+ //# sourceMappingURL=line-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-resolver.d.ts","sourceRoot":"","sources":["../../src/report/line-resolver.ts"],"names":[],"mappings":"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"}