@sentry/warden 0.1.1 → 0.3.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 (589) hide show
  1. package/dist/cli/commands/init.d.ts.map +1 -1
  2. package/dist/cli/commands/init.js +36 -2
  3. package/dist/cli/commands/init.js.map +1 -1
  4. package/dist/cli/commands/setup-app/manifest.d.ts.map +1 -1
  5. package/dist/cli/commands/setup-app/manifest.js +3 -1
  6. package/dist/cli/commands/setup-app/manifest.js.map +1 -1
  7. package/dist/cli/commands/setup-app.js +1 -1
  8. package/dist/cli/commands/setup-app.js.map +1 -1
  9. package/dist/cli/diff-apply.d.ts +15 -0
  10. package/dist/cli/diff-apply.d.ts.map +1 -0
  11. package/dist/cli/diff-apply.js +69 -0
  12. package/dist/cli/diff-apply.js.map +1 -0
  13. package/dist/cli/files.d.ts +11 -1
  14. package/dist/cli/files.d.ts.map +1 -1
  15. package/dist/cli/files.js +145 -4
  16. package/dist/cli/files.js.map +1 -1
  17. package/dist/cli/fix.d.ts +1 -5
  18. package/dist/cli/fix.d.ts.map +1 -1
  19. package/dist/cli/fix.js +3 -62
  20. package/dist/cli/fix.js.map +1 -1
  21. package/dist/cli/git.d.ts.map +1 -1
  22. package/dist/cli/git.js +5 -9
  23. package/dist/cli/git.js.map +1 -1
  24. package/dist/cli/index.js +0 -0
  25. package/dist/cli/output/tasks.d.ts.map +1 -1
  26. package/dist/cli/output/tasks.js +5 -1
  27. package/dist/cli/output/tasks.js.map +1 -1
  28. package/dist/config/schema.d.ts.map +1 -1
  29. package/dist/config/schema.js +15 -1
  30. package/dist/config/schema.js.map +1 -1
  31. package/dist/diff/coalesce.d.ts +32 -2
  32. package/dist/diff/coalesce.d.ts.map +1 -1
  33. package/dist/diff/coalesce.js +174 -2
  34. package/dist/diff/coalesce.js.map +1 -1
  35. package/dist/output/dedup.d.ts +7 -4
  36. package/dist/output/dedup.d.ts.map +1 -1
  37. package/dist/output/dedup.js +48 -12
  38. package/dist/output/dedup.js.map +1 -1
  39. package/dist/output/renderer.d.ts.map +1 -1
  40. package/dist/output/renderer.js +52 -7
  41. package/dist/output/renderer.js.map +1 -1
  42. package/dist/output/stale.d.ts.map +1 -1
  43. package/dist/output/stale.js +7 -0
  44. package/dist/output/stale.js.map +1 -1
  45. package/dist/output/types.d.ts +15 -1
  46. package/dist/output/types.d.ts.map +1 -1
  47. package/dist/sdk/analyze.d.ts +18 -0
  48. package/dist/sdk/analyze.d.ts.map +1 -0
  49. package/dist/sdk/analyze.js +421 -0
  50. package/dist/sdk/analyze.js.map +1 -0
  51. package/dist/sdk/errors.d.ts +23 -0
  52. package/dist/sdk/errors.d.ts.map +1 -0
  53. package/dist/sdk/errors.js +74 -0
  54. package/dist/sdk/errors.js.map +1 -0
  55. package/dist/sdk/extract.d.ts +44 -0
  56. package/dist/sdk/extract.d.ts.map +1 -0
  57. package/dist/sdk/extract.js +224 -0
  58. package/dist/sdk/extract.js.map +1 -0
  59. package/dist/sdk/prepare.d.ts +13 -0
  60. package/dist/sdk/prepare.d.ts.map +1 -0
  61. package/dist/sdk/prepare.js +73 -0
  62. package/dist/sdk/prepare.js.map +1 -0
  63. package/dist/sdk/prompt.d.ts +30 -0
  64. package/dist/sdk/prompt.d.ts.map +1 -0
  65. package/dist/sdk/prompt.js +109 -0
  66. package/dist/sdk/prompt.js.map +1 -0
  67. package/dist/sdk/retry.d.ts +12 -0
  68. package/dist/sdk/retry.d.ts.map +1 -0
  69. package/dist/sdk/retry.js +31 -0
  70. package/dist/sdk/retry.js.map +1 -0
  71. package/dist/sdk/runner.d.ts +22 -199
  72. package/dist/sdk/runner.d.ts.map +1 -1
  73. package/dist/sdk/runner.js +26 -884
  74. package/dist/sdk/runner.js.map +1 -1
  75. package/dist/sdk/types.d.ts +127 -0
  76. package/dist/sdk/types.d.ts.map +1 -0
  77. package/dist/sdk/types.js +5 -0
  78. package/dist/sdk/types.js.map +1 -0
  79. package/dist/sdk/usage.d.ts +20 -0
  80. package/dist/sdk/usage.d.ts.map +1 -0
  81. package/dist/sdk/usage.js +44 -0
  82. package/dist/sdk/usage.js.map +1 -0
  83. package/dist/skills/remote.d.ts.map +1 -1
  84. package/dist/skills/remote.js +3 -7
  85. package/dist/skills/remote.js.map +1 -1
  86. package/dist/types/index.d.ts +1 -0
  87. package/dist/types/index.d.ts.map +1 -1
  88. package/dist/types/index.js +2 -0
  89. package/dist/types/index.js.map +1 -1
  90. package/dist/utils/exec.d.ts +61 -0
  91. package/dist/utils/exec.d.ts.map +1 -0
  92. package/dist/utils/exec.js +111 -0
  93. package/dist/utils/exec.js.map +1 -0
  94. package/dist/utils/index.d.ts +2 -0
  95. package/dist/utils/index.d.ts.map +1 -1
  96. package/dist/utils/index.js +1 -0
  97. package/dist/utils/index.js.map +1 -1
  98. package/package.json +15 -16
  99. package/.agents/skills/find-bugs/SKILL.md +0 -75
  100. package/.agents/skills/vercel-react-best-practices/AGENTS.md +0 -2934
  101. package/.agents/skills/vercel-react-best-practices/SKILL.md +0 -136
  102. package/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  103. package/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  104. package/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  105. package/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  106. package/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  107. package/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  108. package/.agents/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  109. package/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  110. package/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  111. package/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  112. package/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  113. package/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  114. package/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  115. package/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  116. package/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  117. package/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  118. package/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  119. package/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  120. package/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  121. package/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  122. package/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  123. package/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  124. package/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  125. package/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  126. package/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  127. package/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  128. package/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  129. package/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  130. package/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  131. package/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  132. package/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  133. package/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  134. package/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  135. package/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  136. package/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  137. package/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  138. package/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  139. package/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  140. package/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  141. package/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  142. package/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  143. package/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  144. package/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  145. package/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  146. package/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  147. package/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  148. package/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  149. package/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  150. package/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  151. package/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  152. package/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  153. package/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  154. package/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  155. package/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  156. package/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  157. package/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  158. package/.agents/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  159. package/.claude/settings.json +0 -57
  160. package/.claude/skills/agent-prompt/SKILL.md +0 -54
  161. package/.claude/skills/agent-prompt/references/agentic-patterns.md +0 -94
  162. package/.claude/skills/agent-prompt/references/anti-patterns.md +0 -140
  163. package/.claude/skills/agent-prompt/references/context-design.md +0 -124
  164. package/.claude/skills/agent-prompt/references/core-principles.md +0 -75
  165. package/.claude/skills/agent-prompt/references/model-guidance.md +0 -118
  166. package/.claude/skills/agent-prompt/references/output-formats.md +0 -98
  167. package/.claude/skills/agent-prompt/references/skill-structure.md +0 -115
  168. package/.claude/skills/agent-prompt/references/system-prompts.md +0 -115
  169. package/.claude/skills/notseer/SKILL.md +0 -131
  170. package/.claude/skills/skill-writer/SKILL.md +0 -140
  171. package/.claude/skills/testing-guidelines/SKILL.md +0 -132
  172. package/.claude/skills/warden-skill/SKILL.md +0 -226
  173. package/.claude/skills/warden-skill/references/config-schema.md +0 -116
  174. package/.dex/config.toml +0 -2
  175. package/.github/workflows/ci.yml +0 -33
  176. package/.github/workflows/release.yml +0 -59
  177. package/.github/workflows/warden.yml +0 -40
  178. package/AGENTS.md +0 -89
  179. package/CONTRIBUTING.md +0 -60
  180. package/SPEC.md +0 -263
  181. package/action.yml +0 -87
  182. package/assets/favicon.png +0 -0
  183. package/assets/warden-icon-bw.svg +0 -5
  184. package/assets/warden-icon-purple.png +0 -0
  185. package/assets/warden-icon-purple.svg +0 -5
  186. package/dist/action/159.index.js +0 -523
  187. package/dist/action/159.index.js.map +0 -1
  188. package/dist/action/action/index.d.ts +0 -2
  189. package/dist/action/action/index.d.ts.map +0 -1
  190. package/dist/action/action/main.d.ts +0 -2
  191. package/dist/action/action/main.d.ts.map +0 -1
  192. package/dist/action/cli/args.d.ts +0 -74
  193. package/dist/action/cli/args.d.ts.map +0 -1
  194. package/dist/action/cli/args.test.d.ts +0 -2
  195. package/dist/action/cli/args.test.d.ts.map +0 -1
  196. package/dist/action/cli/commands/add.d.ts +0 -7
  197. package/dist/action/cli/commands/add.d.ts.map +0 -1
  198. package/dist/action/cli/commands/init.d.ts +0 -10
  199. package/dist/action/cli/commands/init.d.ts.map +0 -1
  200. package/dist/action/cli/commands/init.test.d.ts +0 -2
  201. package/dist/action/cli/commands/init.test.d.ts.map +0 -1
  202. package/dist/action/cli/commands/setup-app/browser.d.ts +0 -9
  203. package/dist/action/cli/commands/setup-app/browser.d.ts.map +0 -1
  204. package/dist/action/cli/commands/setup-app/credentials.d.ts +0 -15
  205. package/dist/action/cli/commands/setup-app/credentials.d.ts.map +0 -1
  206. package/dist/action/cli/commands/setup-app/manifest.d.ts +0 -24
  207. package/dist/action/cli/commands/setup-app/manifest.d.ts.map +0 -1
  208. package/dist/action/cli/commands/setup-app/server.d.ts +0 -28
  209. package/dist/action/cli/commands/setup-app/server.d.ts.map +0 -1
  210. package/dist/action/cli/commands/setup-app.d.ts +0 -11
  211. package/dist/action/cli/commands/setup-app.d.ts.map +0 -1
  212. package/dist/action/cli/commands/sync.d.ts +0 -9
  213. package/dist/action/cli/commands/sync.d.ts.map +0 -1
  214. package/dist/action/cli/context.d.ts +0 -27
  215. package/dist/action/cli/context.d.ts.map +0 -1
  216. package/dist/action/cli/files.d.ts +0 -22
  217. package/dist/action/cli/files.d.ts.map +0 -1
  218. package/dist/action/cli/files.test.d.ts +0 -2
  219. package/dist/action/cli/files.test.d.ts.map +0 -1
  220. package/dist/action/cli/fix.d.ts +0 -41
  221. package/dist/action/cli/fix.d.ts.map +0 -1
  222. package/dist/action/cli/fix.test.d.ts +0 -2
  223. package/dist/action/cli/fix.test.d.ts.map +0 -1
  224. package/dist/action/cli/git.d.ts +0 -73
  225. package/dist/action/cli/git.d.ts.map +0 -1
  226. package/dist/action/cli/git.test.d.ts +0 -2
  227. package/dist/action/cli/git.test.d.ts.map +0 -1
  228. package/dist/action/cli/index.d.ts +0 -3
  229. package/dist/action/cli/index.d.ts.map +0 -1
  230. package/dist/action/cli/main.d.ts +0 -7
  231. package/dist/action/cli/main.d.ts.map +0 -1
  232. package/dist/action/cli/output/box.d.ts +0 -75
  233. package/dist/action/cli/output/box.d.ts.map +0 -1
  234. package/dist/action/cli/output/formatters.d.ts +0 -90
  235. package/dist/action/cli/output/formatters.d.ts.map +0 -1
  236. package/dist/action/cli/output/formatters.test.d.ts +0 -2
  237. package/dist/action/cli/output/formatters.test.d.ts.map +0 -1
  238. package/dist/action/cli/output/icons.d.ts +0 -15
  239. package/dist/action/cli/output/icons.d.ts.map +0 -1
  240. package/dist/action/cli/output/index.d.ts +0 -10
  241. package/dist/action/cli/output/index.d.ts.map +0 -1
  242. package/dist/action/cli/output/ink-runner.d.ts +0 -29
  243. package/dist/action/cli/output/ink-runner.d.ts.map +0 -1
  244. package/dist/action/cli/output/jsonl.d.ts +0 -43
  245. package/dist/action/cli/output/jsonl.d.ts.map +0 -1
  246. package/dist/action/cli/output/jsonl.test.d.ts +0 -2
  247. package/dist/action/cli/output/jsonl.test.d.ts.map +0 -1
  248. package/dist/action/cli/output/reporter.d.ts +0 -108
  249. package/dist/action/cli/output/reporter.d.ts.map +0 -1
  250. package/dist/action/cli/output/tasks.d.ts +0 -89
  251. package/dist/action/cli/output/tasks.d.ts.map +0 -1
  252. package/dist/action/cli/output/tty.d.ts +0 -21
  253. package/dist/action/cli/output/tty.d.ts.map +0 -1
  254. package/dist/action/cli/output/tty.test.d.ts +0 -2
  255. package/dist/action/cli/output/tty.test.d.ts.map +0 -1
  256. package/dist/action/cli/output/verbosity.d.ts +0 -20
  257. package/dist/action/cli/output/verbosity.d.ts.map +0 -1
  258. package/dist/action/cli/output/verbosity.test.d.ts +0 -2
  259. package/dist/action/cli/output/verbosity.test.d.ts.map +0 -1
  260. package/dist/action/cli/terminal.d.ts +0 -19
  261. package/dist/action/cli/terminal.d.ts.map +0 -1
  262. package/dist/action/cli/terminal.test.d.ts +0 -2
  263. package/dist/action/cli/terminal.test.d.ts.map +0 -1
  264. package/dist/action/config/index.d.ts +0 -4
  265. package/dist/action/config/index.d.ts.map +0 -1
  266. package/dist/action/config/loader.d.ts +0 -27
  267. package/dist/action/config/loader.d.ts.map +0 -1
  268. package/dist/action/config/loader.test.d.ts +0 -2
  269. package/dist/action/config/loader.test.d.ts.map +0 -1
  270. package/dist/action/config/schema.d.ts +0 -318
  271. package/dist/action/config/schema.d.ts.map +0 -1
  272. package/dist/action/config/writer.d.ts +0 -11
  273. package/dist/action/config/writer.d.ts.map +0 -1
  274. package/dist/action/config/writer.test.d.ts +0 -2
  275. package/dist/action/config/writer.test.d.ts.map +0 -1
  276. package/dist/action/diff/classify.d.ts +0 -29
  277. package/dist/action/diff/classify.d.ts.map +0 -1
  278. package/dist/action/diff/classify.test.d.ts +0 -2
  279. package/dist/action/diff/classify.test.d.ts.map +0 -1
  280. package/dist/action/diff/coalesce.d.ts +0 -42
  281. package/dist/action/diff/coalesce.d.ts.map +0 -1
  282. package/dist/action/diff/coalesce.test.d.ts +0 -2
  283. package/dist/action/diff/coalesce.test.d.ts.map +0 -1
  284. package/dist/action/diff/context.d.ts +0 -30
  285. package/dist/action/diff/context.d.ts.map +0 -1
  286. package/dist/action/diff/context.test.d.ts +0 -2
  287. package/dist/action/diff/context.test.d.ts.map +0 -1
  288. package/dist/action/diff/index.d.ts +0 -5
  289. package/dist/action/diff/index.d.ts.map +0 -1
  290. package/dist/action/diff/parser.d.ts +0 -52
  291. package/dist/action/diff/parser.d.ts.map +0 -1
  292. package/dist/action/diff/parser.test.d.ts +0 -2
  293. package/dist/action/diff/parser.test.d.ts.map +0 -1
  294. package/dist/action/event/context.d.ts +0 -9
  295. package/dist/action/event/context.d.ts.map +0 -1
  296. package/dist/action/event/index.d.ts +0 -3
  297. package/dist/action/event/index.d.ts.map +0 -1
  298. package/dist/action/event/schedule-context.d.ts +0 -30
  299. package/dist/action/event/schedule-context.d.ts.map +0 -1
  300. package/dist/action/examples/examples.integration.test.d.ts +0 -2
  301. package/dist/action/examples/examples.integration.test.d.ts.map +0 -1
  302. package/dist/action/examples/index.d.ts +0 -50
  303. package/dist/action/examples/index.d.ts.map +0 -1
  304. package/dist/action/examples/index.test.d.ts +0 -2
  305. package/dist/action/examples/index.test.d.ts.map +0 -1
  306. package/dist/action/examples/setup.d.ts +0 -2
  307. package/dist/action/examples/setup.d.ts.map +0 -1
  308. package/dist/action/index.d.ts +0 -11
  309. package/dist/action/index.d.ts.map +0 -1
  310. package/dist/action/index.js +0 -38231
  311. package/dist/action/index.js.map +0 -1
  312. package/dist/action/licenses.txt +0 -992
  313. package/dist/action/main.d.ts +0 -2
  314. package/dist/action/main.d.ts.map +0 -1
  315. package/dist/action/main.js +0 -707
  316. package/dist/action/main.js.map +0 -1
  317. package/dist/action/output/dedup.d.ts +0 -153
  318. package/dist/action/output/dedup.d.ts.map +0 -1
  319. package/dist/action/output/dedup.test.d.ts +0 -2
  320. package/dist/action/output/dedup.test.d.ts.map +0 -1
  321. package/dist/action/output/github-checks.d.ts +0 -106
  322. package/dist/action/output/github-checks.d.ts.map +0 -1
  323. package/dist/action/output/github-checks.test.d.ts +0 -2
  324. package/dist/action/output/github-checks.test.d.ts.map +0 -1
  325. package/dist/action/output/github-issues.d.ts +0 -35
  326. package/dist/action/output/github-issues.d.ts.map +0 -1
  327. package/dist/action/output/index.d.ts +0 -6
  328. package/dist/action/output/index.d.ts.map +0 -1
  329. package/dist/action/output/issue-renderer.d.ts +0 -20
  330. package/dist/action/output/issue-renderer.d.ts.map +0 -1
  331. package/dist/action/output/renderer.d.ts +0 -4
  332. package/dist/action/output/renderer.d.ts.map +0 -1
  333. package/dist/action/output/renderer.test.d.ts +0 -2
  334. package/dist/action/output/renderer.test.d.ts.map +0 -1
  335. package/dist/action/output/stale.d.ts +0 -31
  336. package/dist/action/output/stale.d.ts.map +0 -1
  337. package/dist/action/output/stale.test.d.ts +0 -2
  338. package/dist/action/output/stale.test.d.ts.map +0 -1
  339. package/dist/action/output/types.d.ts +0 -31
  340. package/dist/action/output/types.d.ts.map +0 -1
  341. package/dist/action/package.json +0 -3
  342. package/dist/action/sdk/index.d.ts +0 -2
  343. package/dist/action/sdk/index.d.ts.map +0 -1
  344. package/dist/action/sdk/runner.d.ts +0 -202
  345. package/dist/action/sdk/runner.d.ts.map +0 -1
  346. package/dist/action/sdk/runner.test.d.ts +0 -2
  347. package/dist/action/sdk/runner.test.d.ts.map +0 -1
  348. package/dist/action/skills/index.d.ts +0 -5
  349. package/dist/action/skills/index.d.ts.map +0 -1
  350. package/dist/action/skills/loader.d.ts +0 -111
  351. package/dist/action/skills/loader.d.ts.map +0 -1
  352. package/dist/action/skills/loader.test.d.ts +0 -2
  353. package/dist/action/skills/loader.test.d.ts.map +0 -1
  354. package/dist/action/skills/remote.d.ts +0 -117
  355. package/dist/action/skills/remote.d.ts.map +0 -1
  356. package/dist/action/skills/remote.test.d.ts +0 -2
  357. package/dist/action/skills/remote.test.d.ts.map +0 -1
  358. package/dist/action/sourcemap-register.cjs +0 -1
  359. package/dist/action/triggers/matcher.d.ts +0 -30
  360. package/dist/action/triggers/matcher.d.ts.map +0 -1
  361. package/dist/action/triggers/matcher.test.d.ts +0 -2
  362. package/dist/action/triggers/matcher.test.d.ts.map +0 -1
  363. package/dist/action/types/index.d.ts +0 -269
  364. package/dist/action/types/index.d.ts.map +0 -1
  365. package/dist/action/utils/async.d.ts +0 -5
  366. package/dist/action/utils/async.d.ts.map +0 -1
  367. package/dist/action/utils/index.d.ts +0 -16
  368. package/dist/action/utils/index.d.ts.map +0 -1
  369. package/dist/action/utils/index.test.d.ts +0 -2
  370. package/dist/action/utils/index.test.d.ts.map +0 -1
  371. package/dist/action/utils/version.d.ts +0 -3
  372. package/dist/action/utils/version.d.ts.map +0 -1
  373. package/dist/cli/args.test.d.ts +0 -2
  374. package/dist/cli/args.test.d.ts.map +0 -1
  375. package/dist/cli/args.test.js +0 -392
  376. package/dist/cli/args.test.js.map +0 -1
  377. package/dist/cli/commands/init.test.d.ts +0 -2
  378. package/dist/cli/commands/init.test.d.ts.map +0 -1
  379. package/dist/cli/commands/init.test.js +0 -117
  380. package/dist/cli/commands/init.test.js.map +0 -1
  381. package/dist/cli/files.test.d.ts +0 -2
  382. package/dist/cli/files.test.d.ts.map +0 -1
  383. package/dist/cli/files.test.js +0 -117
  384. package/dist/cli/files.test.js.map +0 -1
  385. package/dist/cli/fix.test.d.ts +0 -2
  386. package/dist/cli/fix.test.d.ts.map +0 -1
  387. package/dist/cli/fix.test.js +0 -251
  388. package/dist/cli/fix.test.js.map +0 -1
  389. package/dist/cli/git.test.d.ts +0 -2
  390. package/dist/cli/git.test.d.ts.map +0 -1
  391. package/dist/cli/git.test.js +0 -96
  392. package/dist/cli/git.test.js.map +0 -1
  393. package/dist/cli/output/formatters.test.d.ts +0 -2
  394. package/dist/cli/output/formatters.test.d.ts.map +0 -1
  395. package/dist/cli/output/formatters.test.js +0 -152
  396. package/dist/cli/output/formatters.test.js.map +0 -1
  397. package/dist/cli/output/jsonl.test.d.ts +0 -2
  398. package/dist/cli/output/jsonl.test.d.ts.map +0 -1
  399. package/dist/cli/output/jsonl.test.js +0 -284
  400. package/dist/cli/output/jsonl.test.js.map +0 -1
  401. package/dist/cli/output/tty.test.d.ts +0 -2
  402. package/dist/cli/output/tty.test.d.ts.map +0 -1
  403. package/dist/cli/output/tty.test.js +0 -105
  404. package/dist/cli/output/tty.test.js.map +0 -1
  405. package/dist/cli/output/verbosity.test.d.ts +0 -2
  406. package/dist/cli/output/verbosity.test.d.ts.map +0 -1
  407. package/dist/cli/output/verbosity.test.js +0 -35
  408. package/dist/cli/output/verbosity.test.js.map +0 -1
  409. package/dist/cli/terminal.test.d.ts +0 -2
  410. package/dist/cli/terminal.test.d.ts.map +0 -1
  411. package/dist/cli/terminal.test.js +0 -123
  412. package/dist/cli/terminal.test.js.map +0 -1
  413. package/dist/config/loader.test.d.ts +0 -2
  414. package/dist/config/loader.test.d.ts.map +0 -1
  415. package/dist/config/loader.test.js +0 -263
  416. package/dist/config/loader.test.js.map +0 -1
  417. package/dist/config/writer.test.d.ts +0 -2
  418. package/dist/config/writer.test.d.ts.map +0 -1
  419. package/dist/config/writer.test.js +0 -98
  420. package/dist/config/writer.test.js.map +0 -1
  421. package/dist/diff/classify.test.d.ts +0 -2
  422. package/dist/diff/classify.test.d.ts.map +0 -1
  423. package/dist/diff/classify.test.js +0 -140
  424. package/dist/diff/classify.test.js.map +0 -1
  425. package/dist/diff/coalesce.test.d.ts +0 -2
  426. package/dist/diff/coalesce.test.d.ts.map +0 -1
  427. package/dist/diff/coalesce.test.js +0 -159
  428. package/dist/diff/coalesce.test.js.map +0 -1
  429. package/dist/diff/context.test.d.ts +0 -2
  430. package/dist/diff/context.test.d.ts.map +0 -1
  431. package/dist/diff/context.test.js +0 -190
  432. package/dist/diff/context.test.js.map +0 -1
  433. package/dist/diff/parser.test.d.ts +0 -2
  434. package/dist/diff/parser.test.d.ts.map +0 -1
  435. package/dist/diff/parser.test.js +0 -178
  436. package/dist/diff/parser.test.js.map +0 -1
  437. package/dist/examples/examples.integration.test.d.ts +0 -2
  438. package/dist/examples/examples.integration.test.d.ts.map +0 -1
  439. package/dist/examples/examples.integration.test.js +0 -55
  440. package/dist/examples/examples.integration.test.js.map +0 -1
  441. package/dist/examples/index.test.d.ts +0 -2
  442. package/dist/examples/index.test.d.ts.map +0 -1
  443. package/dist/examples/index.test.js +0 -88
  444. package/dist/examples/index.test.js.map +0 -1
  445. package/dist/output/dedup.test.d.ts +0 -2
  446. package/dist/output/dedup.test.d.ts.map +0 -1
  447. package/dist/output/dedup.test.js +0 -357
  448. package/dist/output/dedup.test.js.map +0 -1
  449. package/dist/output/github-checks.test.d.ts +0 -2
  450. package/dist/output/github-checks.test.d.ts.map +0 -1
  451. package/dist/output/github-checks.test.js +0 -255
  452. package/dist/output/github-checks.test.js.map +0 -1
  453. package/dist/output/renderer.test.d.ts +0 -2
  454. package/dist/output/renderer.test.d.ts.map +0 -1
  455. package/dist/output/renderer.test.js +0 -645
  456. package/dist/output/renderer.test.js.map +0 -1
  457. package/dist/output/stale.test.d.ts +0 -2
  458. package/dist/output/stale.test.d.ts.map +0 -1
  459. package/dist/output/stale.test.js +0 -330
  460. package/dist/output/stale.test.js.map +0 -1
  461. package/dist/sdk/runner.test.d.ts +0 -2
  462. package/dist/sdk/runner.test.d.ts.map +0 -1
  463. package/dist/sdk/runner.test.js +0 -677
  464. package/dist/sdk/runner.test.js.map +0 -1
  465. package/dist/skills/loader.test.d.ts +0 -2
  466. package/dist/skills/loader.test.d.ts.map +0 -1
  467. package/dist/skills/loader.test.js +0 -241
  468. package/dist/skills/loader.test.js.map +0 -1
  469. package/dist/skills/remote.test.d.ts +0 -2
  470. package/dist/skills/remote.test.d.ts.map +0 -1
  471. package/dist/skills/remote.test.js +0 -582
  472. package/dist/skills/remote.test.js.map +0 -1
  473. package/dist/triggers/matcher.test.d.ts +0 -2
  474. package/dist/triggers/matcher.test.d.ts.map +0 -1
  475. package/dist/triggers/matcher.test.js +0 -234
  476. package/dist/triggers/matcher.test.js.map +0 -1
  477. package/dist/utils/index.test.d.ts +0 -2
  478. package/dist/utils/index.test.d.ts.map +0 -1
  479. package/dist/utils/index.test.js +0 -68
  480. package/dist/utils/index.test.js.map +0 -1
  481. package/docs/astro.config.mjs +0 -43
  482. package/docs/package.json +0 -19
  483. package/docs/pnpm-lock.yaml +0 -4000
  484. package/docs/public/favicon.svg +0 -5
  485. package/docs/src/components/Code.astro +0 -141
  486. package/docs/src/components/PackageManagerTabs.astro +0 -183
  487. package/docs/src/components/Terminal.astro +0 -212
  488. package/docs/src/layouts/Base.astro +0 -380
  489. package/docs/src/pages/cli.astro +0 -167
  490. package/docs/src/pages/config.astro +0 -395
  491. package/docs/src/pages/guide.astro +0 -450
  492. package/docs/src/pages/index.astro +0 -490
  493. package/docs/src/styles/global.css +0 -551
  494. package/docs/src/utils/version.ts +0 -6
  495. package/docs/tsconfig.json +0 -3
  496. package/docs/vercel.json +0 -5
  497. package/eslint.config.js +0 -33
  498. package/src/action/index.ts +0 -1
  499. package/src/action/main.ts +0 -868
  500. package/src/cli/args.test.ts +0 -477
  501. package/src/cli/args.ts +0 -414
  502. package/src/cli/commands/add.ts +0 -447
  503. package/src/cli/commands/init.test.ts +0 -137
  504. package/src/cli/commands/init.ts +0 -134
  505. package/src/cli/commands/setup-app/browser.ts +0 -38
  506. package/src/cli/commands/setup-app/credentials.ts +0 -45
  507. package/src/cli/commands/setup-app/manifest.ts +0 -48
  508. package/src/cli/commands/setup-app/server.ts +0 -172
  509. package/src/cli/commands/setup-app.ts +0 -156
  510. package/src/cli/commands/sync.ts +0 -114
  511. package/src/cli/context.ts +0 -131
  512. package/src/cli/files.test.ts +0 -155
  513. package/src/cli/files.ts +0 -89
  514. package/src/cli/fix.test.ts +0 -310
  515. package/src/cli/fix.ts +0 -387
  516. package/src/cli/git.test.ts +0 -119
  517. package/src/cli/git.ts +0 -318
  518. package/src/cli/index.ts +0 -14
  519. package/src/cli/main.ts +0 -672
  520. package/src/cli/output/box.ts +0 -235
  521. package/src/cli/output/formatters.test.ts +0 -187
  522. package/src/cli/output/formatters.ts +0 -269
  523. package/src/cli/output/icons.ts +0 -19
  524. package/src/cli/output/index.ts +0 -44
  525. package/src/cli/output/ink-runner.tsx +0 -366
  526. package/src/cli/output/jsonl.test.ts +0 -347
  527. package/src/cli/output/jsonl.ts +0 -126
  528. package/src/cli/output/reporter.ts +0 -434
  529. package/src/cli/output/tasks.ts +0 -374
  530. package/src/cli/output/tty.test.ts +0 -117
  531. package/src/cli/output/tty.ts +0 -60
  532. package/src/cli/output/verbosity.test.ts +0 -40
  533. package/src/cli/output/verbosity.ts +0 -31
  534. package/src/cli/terminal.test.ts +0 -148
  535. package/src/cli/terminal.ts +0 -301
  536. package/src/config/index.ts +0 -3
  537. package/src/config/loader.test.ts +0 -313
  538. package/src/config/loader.ts +0 -103
  539. package/src/config/schema.ts +0 -168
  540. package/src/config/writer.test.ts +0 -119
  541. package/src/config/writer.ts +0 -84
  542. package/src/diff/classify.test.ts +0 -162
  543. package/src/diff/classify.ts +0 -92
  544. package/src/diff/coalesce.test.ts +0 -208
  545. package/src/diff/coalesce.ts +0 -133
  546. package/src/diff/context.test.ts +0 -226
  547. package/src/diff/context.ts +0 -201
  548. package/src/diff/index.ts +0 -4
  549. package/src/diff/parser.test.ts +0 -212
  550. package/src/diff/parser.ts +0 -149
  551. package/src/event/context.ts +0 -132
  552. package/src/event/index.ts +0 -2
  553. package/src/event/schedule-context.ts +0 -101
  554. package/src/examples/examples.integration.test.ts +0 -66
  555. package/src/examples/index.test.ts +0 -101
  556. package/src/examples/index.ts +0 -122
  557. package/src/examples/setup.ts +0 -25
  558. package/src/index.ts +0 -115
  559. package/src/output/dedup.test.ts +0 -419
  560. package/src/output/dedup.ts +0 -607
  561. package/src/output/github-checks.test.ts +0 -300
  562. package/src/output/github-checks.ts +0 -476
  563. package/src/output/github-issues.ts +0 -329
  564. package/src/output/index.ts +0 -5
  565. package/src/output/issue-renderer.ts +0 -197
  566. package/src/output/renderer.test.ts +0 -727
  567. package/src/output/renderer.ts +0 -217
  568. package/src/output/stale.test.ts +0 -375
  569. package/src/output/stale.ts +0 -155
  570. package/src/output/types.ts +0 -34
  571. package/src/sdk/index.ts +0 -1
  572. package/src/sdk/runner.test.ts +0 -806
  573. package/src/sdk/runner.ts +0 -1232
  574. package/src/skills/index.ts +0 -36
  575. package/src/skills/loader.test.ts +0 -300
  576. package/src/skills/loader.ts +0 -423
  577. package/src/skills/remote.test.ts +0 -704
  578. package/src/skills/remote.ts +0 -604
  579. package/src/triggers/matcher.test.ts +0 -277
  580. package/src/triggers/matcher.ts +0 -152
  581. package/src/types/index.ts +0 -194
  582. package/src/utils/async.ts +0 -18
  583. package/src/utils/index.test.ts +0 -84
  584. package/src/utils/index.ts +0 -51
  585. package/src/utils/version.ts +0 -17
  586. package/tsconfig.json +0 -25
  587. package/vitest.config.ts +0 -8
  588. package/vitest.integration.config.ts +0 -11
  589. package/warden.toml +0 -19
@@ -1,607 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import type { Octokit } from '@octokit/rest';
3
- import Anthropic from '@anthropic-ai/sdk';
4
- import { z } from 'zod';
5
- import type { Finding } from '../types/index.js';
6
-
7
- /**
8
- * Parsed marker data from a Warden comment.
9
- */
10
- export interface WardenMarker {
11
- path: string;
12
- line: number;
13
- contentHash: string;
14
- }
15
-
16
- /**
17
- * Existing comment from GitHub (either Warden or external).
18
- */
19
- export interface ExistingComment {
20
- id: number;
21
- path: string;
22
- line: number;
23
- title: string;
24
- description: string;
25
- contentHash: string;
26
- /** GraphQL node ID for the review thread (used to resolve stale comments) */
27
- threadId?: string;
28
- /** Whether the thread has been resolved (resolved comments are used for dedup but not stale detection) */
29
- isResolved?: boolean;
30
- /** Whether this is a Warden-generated comment */
31
- isWarden?: boolean;
32
- /** Skills that have already detected this issue (for Warden comments) */
33
- skills?: string[];
34
- /** The raw comment body (needed for updating Warden comments) */
35
- body?: string;
36
- /** GraphQL node ID for the comment (needed for adding reactions) */
37
- commentNodeId?: string;
38
- }
39
-
40
- /**
41
- * Type of action to take for a duplicate finding.
42
- */
43
- export type DuplicateActionType = 'update_warden' | 'react_external';
44
-
45
- /**
46
- * Action to take for a duplicate finding.
47
- */
48
- export interface DuplicateAction {
49
- type: DuplicateActionType;
50
- finding: Finding;
51
- existingComment: ExistingComment;
52
- /** Whether this was a hash match or semantic match */
53
- matchType: 'hash' | 'semantic';
54
- }
55
-
56
- /**
57
- * Result of deduplication with actions for duplicates.
58
- */
59
- export interface DeduplicateResult {
60
- /** Findings that are not duplicates - should be posted */
61
- newFindings: Finding[];
62
- /** Actions to take for duplicate findings */
63
- duplicateActions: DuplicateAction[];
64
- }
65
-
66
- /**
67
- * Generate a short content hash from title and description.
68
- * Used for exact-match deduplication.
69
- */
70
- export function generateContentHash(title: string, description: string): string {
71
- const content = `${title}\n${description}`;
72
- return createHash('sha256').update(content).digest('hex').slice(0, 8);
73
- }
74
-
75
- /**
76
- * Generate the marker HTML comment to embed in comment body.
77
- * Format: <!-- warden:v1:{path}:{line}:{contentHash} -->
78
- */
79
- export function generateMarker(path: string, line: number, contentHash: string): string {
80
- return `<!-- warden:v1:${path}:${line}:${contentHash} -->`;
81
- }
82
-
83
- /**
84
- * Parse a Warden marker from a comment body.
85
- * Returns null if no valid marker is found.
86
- */
87
- export function parseMarker(body: string): WardenMarker | null {
88
- const match = body.match(/<!-- warden:v1:([^:]+):(\d+):([a-f0-9]+) -->/);
89
- if (!match) {
90
- return null;
91
- }
92
-
93
- // Capture groups are guaranteed to exist when the regex matches
94
- const [, path, lineStr, contentHash] = match as [string, string, string, string];
95
-
96
- return {
97
- path,
98
- line: parseInt(lineStr, 10),
99
- contentHash,
100
- };
101
- }
102
-
103
- /**
104
- * Parse title and description from a Warden comment body.
105
- * Expected format: **:emoji: Title**\n\nDescription
106
- */
107
- export function parseWardenComment(body: string): { title: string; description: string } | null {
108
- // Match the title pattern: **:emoji: Title** or **Title**
109
- // Use non-greedy match to handle titles containing asterisks
110
- const titleMatch = body.match(/\*\*(?::[a-z_]+:\s*)?(.+?)\*\*/);
111
- if (!titleMatch || !titleMatch[1]) {
112
- return null;
113
- }
114
-
115
- const title = titleMatch[1].trim();
116
-
117
- // Get the description - everything after the title until the first ---
118
- const titleEnd = body.indexOf('**', body.indexOf('**') + 2) + 2;
119
- const separatorIndex = body.indexOf('---');
120
- const descEnd = separatorIndex > -1 ? separatorIndex : body.length;
121
-
122
- const description = body.slice(titleEnd, descEnd).trim();
123
-
124
- return { title, description };
125
- }
126
-
127
- /**
128
- * Check if a comment body is a Warden-generated comment.
129
- */
130
- export function isWardenComment(body: string): boolean {
131
- return body.includes('<sub>warden:') || body.includes('<!-- warden:v1:');
132
- }
133
-
134
- /**
135
- * Parse skill names from a Warden comment's attribution line.
136
- * Handles both single skill: "<sub>warden: skill-name</sub>"
137
- * And multiple skills: "<sub>warden: skill1, skill2</sub>"
138
- */
139
- export function parseWardenSkills(body: string): string[] {
140
- const match = body.match(/<sub>warden:\s*([^<]+)<\/sub>/);
141
- if (!match || !match[1]) {
142
- return [];
143
- }
144
- return match[1]
145
- .split(',')
146
- .map((s) => s.trim())
147
- .filter(Boolean);
148
- }
149
-
150
- /**
151
- * Update a Warden comment body to add a new skill to the attribution.
152
- * Changes "<sub>warden: skill1</sub>" to "<sub>warden: skill1, skill2</sub>"
153
- * Returns null if skill is already listed or if no <sub>warden:...</sub> tag exists.
154
- */
155
- export function updateWardenCommentBody(body: string, newSkill: string): string | null {
156
- const existingSkills = parseWardenSkills(body);
157
-
158
- // If no existing <sub>warden:...</sub> tag exists, we can't update it
159
- if (existingSkills.length === 0) {
160
- return null;
161
- }
162
-
163
- // Don't update if skill already listed
164
- if (existingSkills.includes(newSkill)) {
165
- return null;
166
- }
167
-
168
- const allSkills = [...existingSkills, newSkill].join(', ');
169
- // Use a replacer function to avoid special $ character interpretation in skill names
170
- return body.replace(/<sub>warden:\s*[^<]+<\/sub>/, () => `<sub>warden: ${allSkills}</sub>`);
171
- }
172
-
173
- /** GraphQL response structure for review threads */
174
- interface ReviewThreadNode {
175
- id: string;
176
- isResolved: boolean;
177
- comments: {
178
- nodes: {
179
- id: string; // GraphQL node ID (for reactions)
180
- databaseId: number;
181
- body: string;
182
- path: string;
183
- line: number | null;
184
- originalLine: number | null;
185
- }[];
186
- };
187
- }
188
-
189
- interface ReviewThreadsResponse {
190
- repository?: {
191
- pullRequest?: {
192
- reviewThreads: {
193
- pageInfo: {
194
- hasNextPage: boolean;
195
- endCursor: string | null;
196
- };
197
- nodes: ReviewThreadNode[];
198
- };
199
- } | null;
200
- } | null;
201
- }
202
-
203
- const REVIEW_THREADS_QUERY = `
204
- query($owner: String!, $repo: String!, $prNumber: Int!, $cursor: String) {
205
- repository(owner: $owner, name: $repo) {
206
- pullRequest(number: $prNumber) {
207
- reviewThreads(first: 100, after: $cursor) {
208
- pageInfo {
209
- hasNextPage
210
- endCursor
211
- }
212
- nodes {
213
- id
214
- isResolved
215
- comments(first: 1) {
216
- nodes {
217
- id
218
- databaseId
219
- body
220
- path
221
- line
222
- originalLine
223
- }
224
- }
225
- }
226
- }
227
- }
228
- }
229
- }
230
- `;
231
-
232
- /**
233
- * Fetch all existing review comments for a PR (both Warden and external).
234
- * Uses GraphQL to get thread IDs for stale comment resolution and node IDs for reactions.
235
- */
236
- export async function fetchExistingComments(
237
- octokit: Octokit,
238
- owner: string,
239
- repo: string,
240
- prNumber: number
241
- ): Promise<ExistingComment[]> {
242
- const comments: ExistingComment[] = [];
243
-
244
- // Use GraphQL to get thread IDs along with comment data
245
- let cursor: string | null = null;
246
- let hasNextPage = true;
247
-
248
- while (hasNextPage) {
249
- const response: ReviewThreadsResponse = await octokit.graphql(REVIEW_THREADS_QUERY, {
250
- owner,
251
- repo,
252
- prNumber,
253
- cursor,
254
- });
255
-
256
- const pullRequest = response.repository?.pullRequest;
257
- if (!pullRequest) {
258
- // PR doesn't exist or was deleted
259
- return comments;
260
- }
261
-
262
- const threads = pullRequest.reviewThreads;
263
-
264
- for (const thread of threads.nodes) {
265
- // Get the first comment in the thread
266
- const firstComment = thread.comments.nodes[0];
267
- if (!firstComment) {
268
- continue;
269
- }
270
-
271
- const isWarden = isWardenComment(firstComment.body);
272
- const marker = isWarden ? parseMarker(firstComment.body) : null;
273
- const parsed = parseWardenComment(firstComment.body);
274
-
275
- // For Warden comments, we need parsed title/description
276
- // For external comments, we extract what we can or use body as description
277
- const title = parsed?.title ?? '';
278
- const description = parsed?.description ?? firstComment.body.slice(0, 500);
279
-
280
- comments.push({
281
- id: firstComment.databaseId,
282
- path: marker?.path ?? firstComment.path,
283
- line: marker?.line ?? firstComment.line ?? firstComment.originalLine ?? 0,
284
- title,
285
- description,
286
- contentHash: marker?.contentHash ?? generateContentHash(title, description),
287
- threadId: thread.id,
288
- isResolved: thread.isResolved,
289
- isWarden,
290
- skills: isWarden ? parseWardenSkills(firstComment.body) : undefined,
291
- body: firstComment.body,
292
- commentNodeId: firstComment.id,
293
- });
294
- }
295
-
296
- hasNextPage = threads.pageInfo.hasNextPage;
297
- cursor = threads.pageInfo.endCursor;
298
- }
299
-
300
- return comments;
301
- }
302
-
303
- /**
304
- * @deprecated Use fetchExistingComments instead
305
- */
306
- export async function fetchExistingWardenComments(
307
- octokit: Octokit,
308
- owner: string,
309
- repo: string,
310
- prNumber: number
311
- ): Promise<ExistingComment[]> {
312
- const allComments = await fetchExistingComments(octokit, owner, repo, prNumber);
313
- return allComments.filter((c) => c.isWarden);
314
- }
315
-
316
- /** Schema for validating LLM deduplication response with matched indices */
317
- const DuplicateMatchesSchema = z.array(
318
- z.object({
319
- findingIndex: z.number().int(),
320
- existingIndex: z.number().int(),
321
- })
322
- );
323
-
324
- /**
325
- * Use LLM to identify which findings are semantic duplicates of existing comments.
326
- * Returns a Map of finding ID to matched ExistingComment.
327
- */
328
- async function findSemanticDuplicates(
329
- findings: Finding[],
330
- existingComments: ExistingComment[],
331
- apiKey: string
332
- ): Promise<Map<string, ExistingComment>> {
333
- if (findings.length === 0 || existingComments.length === 0) {
334
- return new Map();
335
- }
336
-
337
- const client = new Anthropic({ apiKey });
338
-
339
- const existingList = existingComments
340
- .map((c, i) => `${i + 1}. [${c.path}:${c.line}] "${c.title}" - ${c.description}`)
341
- .join('\n');
342
-
343
- const findingsList = findings
344
- .map((f, i) => {
345
- const line = f.location?.endLine ?? f.location?.startLine;
346
- const loc = f.location ? `${f.location.path}:${line}` : 'general';
347
- return `${i + 1}. [${loc}] "${f.title}" - ${f.description}`;
348
- })
349
- .join('\n');
350
-
351
- const prompt = `Compare these code review findings and identify duplicates.
352
-
353
- Existing comments:
354
- ${existingList}
355
-
356
- New findings:
357
- ${findingsList}
358
-
359
- Return a JSON array of objects identifying which findings are DUPLICATES of which existing comments.
360
- Only mark as duplicate if they describe the SAME issue at the SAME location (within a few lines).
361
- Different issues at the same location are NOT duplicates.
362
-
363
- Return ONLY the JSON array in this format:
364
- [{"findingIndex": 1, "existingIndex": 2}]
365
- where findingIndex is the 1-based index of the new finding and existingIndex is the 1-based index of the matching existing comment.
366
- Return [] if none are duplicates.`;
367
-
368
- try {
369
- const response = await client.messages.create({
370
- model: 'claude-haiku-4-5',
371
- max_tokens: 512,
372
- messages: [{ role: 'user', content: prompt }],
373
- });
374
-
375
- const content = response.content[0];
376
- if (!content || content.type !== 'text') {
377
- throw new Error('Unexpected response type');
378
- }
379
-
380
- const parsed = DuplicateMatchesSchema.parse(JSON.parse(content.text));
381
- const matches = new Map<string, ExistingComment>();
382
-
383
- for (const match of parsed) {
384
- const finding = findings[match.findingIndex - 1];
385
- const existing = existingComments[match.existingIndex - 1];
386
- if (finding && existing) {
387
- matches.set(finding.id, existing);
388
- }
389
- }
390
-
391
- return matches;
392
- } catch (error) {
393
- console.warn(`LLM deduplication failed, falling back to hash-only: ${error}`);
394
- return new Map();
395
- }
396
- }
397
-
398
- /**
399
- * Options for deduplication.
400
- */
401
- export interface DeduplicateOptions {
402
- /** Anthropic API key for LLM-based semantic deduplication */
403
- apiKey?: string;
404
- /** Skip LLM deduplication and only use exact hash matching */
405
- hashOnly?: boolean;
406
- /** Current skill name (for updating Warden comment attribution) */
407
- currentSkill?: string;
408
- }
409
-
410
- const ADD_REACTION_MUTATION = `
411
- mutation($subjectId: ID!, $content: ReactionContent!) {
412
- addReaction(input: { subjectId: $subjectId, content: $content }) {
413
- reaction {
414
- content
415
- }
416
- }
417
- }
418
- `;
419
-
420
- /**
421
- * Update an existing Warden PR review comment via REST API.
422
- */
423
- export async function updateWardenComment(
424
- octokit: Octokit,
425
- owner: string,
426
- repo: string,
427
- commentId: number,
428
- newBody: string
429
- ): Promise<void> {
430
- await octokit.pulls.updateReviewComment({
431
- owner,
432
- repo,
433
- comment_id: commentId,
434
- body: newBody,
435
- });
436
- }
437
-
438
- /**
439
- * Add a reaction to an existing PR review comment.
440
- * Uses GraphQL to handle review comments.
441
- */
442
- export async function addReactionToComment(
443
- octokit: Octokit,
444
- commentNodeId: string,
445
- reaction: 'THUMBS_UP' | 'EYES' = 'EYES'
446
- ): Promise<void> {
447
- await octokit.graphql(ADD_REACTION_MUTATION, {
448
- subjectId: commentNodeId,
449
- content: reaction,
450
- });
451
- }
452
-
453
- /**
454
- * Process duplicate actions - update Warden comments and add reactions.
455
- * Returns counts of actions taken for logging.
456
- */
457
- export async function processDuplicateActions(
458
- octokit: Octokit,
459
- owner: string,
460
- repo: string,
461
- actions: DuplicateAction[],
462
- currentSkill: string
463
- ): Promise<{ updated: number; reacted: number; skipped: number; failed: number }> {
464
- let updated = 0;
465
- let reacted = 0;
466
- let skipped = 0;
467
- let failed = 0;
468
-
469
- for (const action of actions) {
470
- try {
471
- if (action.type === 'update_warden') {
472
- if (!action.existingComment.body) {
473
- skipped++;
474
- continue;
475
- }
476
- const newBody = updateWardenCommentBody(action.existingComment.body, currentSkill);
477
- // Only update if body actually changed (skill wasn't already listed)
478
- if (newBody) {
479
- await updateWardenComment(octokit, owner, repo, action.existingComment.id, newBody);
480
- // Update in-memory body so subsequent triggers see the updated content
481
- action.existingComment.body = newBody;
482
- updated++;
483
- } else {
484
- skipped++;
485
- }
486
- } else if (action.type === 'react_external') {
487
- if (!action.existingComment.commentNodeId) {
488
- skipped++;
489
- continue;
490
- }
491
- await addReactionToComment(octokit, action.existingComment.commentNodeId);
492
- reacted++;
493
- }
494
- } catch (error) {
495
- console.warn(`Failed to process duplicate action for ${action.finding.title}: ${error}`);
496
- failed++;
497
- }
498
- }
499
-
500
- return { updated, reacted, skipped, failed };
501
- }
502
-
503
- /**
504
- * Convert a Finding to an ExistingComment for cross-trigger deduplication.
505
- * Returns null if the finding has no location.
506
- */
507
- export function findingToExistingComment(finding: Finding, skill?: string): ExistingComment | null {
508
- if (!finding.location) {
509
- return null;
510
- }
511
-
512
- return {
513
- id: -1, // Newly posted comments don't have IDs yet
514
- path: finding.location.path,
515
- line: finding.location.endLine ?? finding.location.startLine,
516
- title: finding.title,
517
- description: finding.description,
518
- contentHash: generateContentHash(finding.title, finding.description),
519
- isWarden: true,
520
- skills: skill ? [skill] : [],
521
- };
522
- }
523
-
524
- /**
525
- * Deduplicate findings against existing comments.
526
- * Returns non-duplicate findings and actions to take for duplicates.
527
- *
528
- * Deduplication is two-pass:
529
- * 1. Exact content hash match - instant match
530
- * 2. LLM semantic comparison for remaining findings (if API key provided)
531
- *
532
- * For duplicates:
533
- * - If matching a Warden comment: action to update attribution with new skill
534
- * - If matching an external comment: action to add reaction
535
- */
536
- export async function deduplicateFindings(
537
- findings: Finding[],
538
- existingComments: ExistingComment[],
539
- options: DeduplicateOptions = {}
540
- ): Promise<DeduplicateResult> {
541
- if (findings.length === 0 || existingComments.length === 0) {
542
- return { newFindings: findings, duplicateActions: [] };
543
- }
544
-
545
- // Build a map of existing comments by location+hash for fast lookup
546
- const existingByKey = new Map<string, ExistingComment>();
547
- for (const c of existingComments) {
548
- const key = `${c.path}:${c.line}:${c.contentHash}`;
549
- existingByKey.set(key, c);
550
- }
551
-
552
- // First pass: find exact matches (same content at same location)
553
- const hashDedupedFindings: Finding[] = [];
554
- const duplicateActions: DuplicateAction[] = [];
555
-
556
- for (const finding of findings) {
557
- const hash = generateContentHash(finding.title, finding.description);
558
- const line = finding.location?.endLine ?? finding.location?.startLine ?? 0;
559
- const path = finding.location?.path ?? '';
560
- const key = `${path}:${line}:${hash}`;
561
-
562
- const matchingComment = existingByKey.get(key);
563
- if (matchingComment) {
564
- duplicateActions.push({
565
- type: matchingComment.isWarden ? 'update_warden' : 'react_external',
566
- finding,
567
- existingComment: matchingComment,
568
- matchType: 'hash',
569
- });
570
- } else {
571
- hashDedupedFindings.push(finding);
572
- }
573
- }
574
-
575
- if (duplicateActions.length > 0) {
576
- console.log(`Dedup: ${duplicateActions.length} findings matched by content hash`);
577
- }
578
-
579
- // If hash-only mode, no API key, or no remaining findings, stop here
580
- if (options.hashOnly || !options.apiKey || hashDedupedFindings.length === 0) {
581
- return { newFindings: hashDedupedFindings, duplicateActions };
582
- }
583
-
584
- // Second pass: LLM semantic comparison for remaining findings
585
- const semanticMatches = await findSemanticDuplicates(hashDedupedFindings, existingComments, options.apiKey);
586
-
587
- if (semanticMatches.size > 0) {
588
- console.log(`Dedup: ${semanticMatches.size} findings identified as semantic duplicates by LLM`);
589
- }
590
-
591
- const newFindings: Finding[] = [];
592
- for (const finding of hashDedupedFindings) {
593
- const matchingComment = semanticMatches.get(finding.id);
594
- if (matchingComment) {
595
- duplicateActions.push({
596
- type: matchingComment.isWarden ? 'update_warden' : 'react_external',
597
- finding,
598
- existingComment: matchingComment,
599
- matchType: 'semantic',
600
- });
601
- } else {
602
- newFindings.push(finding);
603
- }
604
- }
605
-
606
- return { newFindings, duplicateActions };
607
- }