@sentry/warden 0.1.0 → 0.2.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 (588) hide show
  1. package/dist/cli/commands/init.d.ts.map +1 -1
  2. package/dist/cli/commands/init.js +3 -1
  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/files.d.ts +11 -1
  10. package/dist/cli/files.d.ts.map +1 -1
  11. package/dist/cli/files.js +145 -4
  12. package/dist/cli/files.js.map +1 -1
  13. package/dist/cli/git.d.ts.map +1 -1
  14. package/dist/cli/git.js +5 -9
  15. package/dist/cli/git.js.map +1 -1
  16. package/dist/cli/index.js +0 -0
  17. package/dist/cli/output/icons.d.ts +4 -0
  18. package/dist/cli/output/icons.d.ts.map +1 -1
  19. package/dist/cli/output/icons.js +4 -0
  20. package/dist/cli/output/icons.js.map +1 -1
  21. package/dist/cli/output/ink-runner.d.ts +20 -0
  22. package/dist/cli/output/ink-runner.d.ts.map +1 -1
  23. package/dist/cli/output/ink-runner.js +53 -19
  24. package/dist/cli/output/ink-runner.js.map +1 -1
  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.map +1 -1
  36. package/dist/output/dedup.js +8 -3
  37. package/dist/output/dedup.js.map +1 -1
  38. package/dist/output/renderer.d.ts.map +1 -1
  39. package/dist/output/renderer.js +49 -5
  40. package/dist/output/renderer.js.map +1 -1
  41. package/dist/output/stale.d.ts.map +1 -1
  42. package/dist/output/stale.js +7 -0
  43. package/dist/output/stale.js.map +1 -1
  44. package/dist/output/types.d.ts +15 -1
  45. package/dist/output/types.d.ts.map +1 -1
  46. package/dist/sdk/analyze.d.ts +18 -0
  47. package/dist/sdk/analyze.d.ts.map +1 -0
  48. package/dist/sdk/analyze.js +425 -0
  49. package/dist/sdk/analyze.js.map +1 -0
  50. package/dist/sdk/errors.d.ts +23 -0
  51. package/dist/sdk/errors.d.ts.map +1 -0
  52. package/dist/sdk/errors.js +72 -0
  53. package/dist/sdk/errors.js.map +1 -0
  54. package/dist/sdk/extract.d.ts +44 -0
  55. package/dist/sdk/extract.d.ts.map +1 -0
  56. package/dist/sdk/extract.js +224 -0
  57. package/dist/sdk/extract.js.map +1 -0
  58. package/dist/sdk/prepare.d.ts +13 -0
  59. package/dist/sdk/prepare.d.ts.map +1 -0
  60. package/dist/sdk/prepare.js +73 -0
  61. package/dist/sdk/prepare.js.map +1 -0
  62. package/dist/sdk/prompt.d.ts +30 -0
  63. package/dist/sdk/prompt.d.ts.map +1 -0
  64. package/dist/sdk/prompt.js +109 -0
  65. package/dist/sdk/prompt.js.map +1 -0
  66. package/dist/sdk/retry.d.ts +12 -0
  67. package/dist/sdk/retry.d.ts.map +1 -0
  68. package/dist/sdk/retry.js +31 -0
  69. package/dist/sdk/retry.js.map +1 -0
  70. package/dist/sdk/runner.d.ts +22 -199
  71. package/dist/sdk/runner.d.ts.map +1 -1
  72. package/dist/sdk/runner.js +26 -884
  73. package/dist/sdk/runner.js.map +1 -1
  74. package/dist/sdk/types.d.ts +127 -0
  75. package/dist/sdk/types.d.ts.map +1 -0
  76. package/dist/sdk/types.js +5 -0
  77. package/dist/sdk/types.js.map +1 -0
  78. package/dist/sdk/usage.d.ts +20 -0
  79. package/dist/sdk/usage.d.ts.map +1 -0
  80. package/dist/sdk/usage.js +44 -0
  81. package/dist/sdk/usage.js.map +1 -0
  82. package/dist/skills/remote.d.ts.map +1 -1
  83. package/dist/skills/remote.js +3 -7
  84. package/dist/skills/remote.js.map +1 -1
  85. package/dist/types/index.d.ts +1 -0
  86. package/dist/types/index.d.ts.map +1 -1
  87. package/dist/types/index.js +2 -0
  88. package/dist/types/index.js.map +1 -1
  89. package/dist/utils/exec.d.ts +61 -0
  90. package/dist/utils/exec.d.ts.map +1 -0
  91. package/dist/utils/exec.js +111 -0
  92. package/dist/utils/exec.js.map +1 -0
  93. package/dist/utils/index.d.ts +2 -0
  94. package/dist/utils/index.d.ts.map +1 -1
  95. package/dist/utils/index.js +1 -0
  96. package/dist/utils/index.js.map +1 -1
  97. package/package.json +15 -16
  98. package/.agents/skills/find-bugs/SKILL.md +0 -75
  99. package/.agents/skills/vercel-react-best-practices/AGENTS.md +0 -2934
  100. package/.agents/skills/vercel-react-best-practices/SKILL.md +0 -136
  101. package/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  102. package/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  103. package/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  104. package/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  105. package/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  106. package/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  107. package/.agents/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  108. package/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  109. package/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  110. package/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  111. package/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  112. package/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  113. package/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  114. package/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  115. package/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  116. package/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  117. package/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  118. package/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  119. package/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  120. package/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  121. package/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  122. package/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  123. package/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  124. package/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  125. package/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  126. package/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  127. package/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  128. package/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  129. package/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  130. package/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  131. package/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  132. package/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  133. package/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  134. package/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  135. package/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  136. package/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  137. package/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  138. package/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  139. package/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  140. package/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  141. package/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  142. package/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  143. package/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  144. package/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  145. package/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  146. package/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  147. package/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  148. package/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  149. package/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  150. package/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  151. package/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  152. package/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  153. package/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  154. package/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  155. package/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  156. package/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  157. package/.agents/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  158. package/.claude/settings.json +0 -57
  159. package/.claude/skills/agent-prompt/SKILL.md +0 -54
  160. package/.claude/skills/agent-prompt/references/agentic-patterns.md +0 -94
  161. package/.claude/skills/agent-prompt/references/anti-patterns.md +0 -140
  162. package/.claude/skills/agent-prompt/references/context-design.md +0 -124
  163. package/.claude/skills/agent-prompt/references/core-principles.md +0 -75
  164. package/.claude/skills/agent-prompt/references/model-guidance.md +0 -118
  165. package/.claude/skills/agent-prompt/references/output-formats.md +0 -98
  166. package/.claude/skills/agent-prompt/references/skill-structure.md +0 -115
  167. package/.claude/skills/agent-prompt/references/system-prompts.md +0 -115
  168. package/.claude/skills/notseer/SKILL.md +0 -131
  169. package/.claude/skills/skill-writer/SKILL.md +0 -140
  170. package/.claude/skills/testing-guidelines/SKILL.md +0 -132
  171. package/.claude/skills/warden-skill/SKILL.md +0 -250
  172. package/.claude/skills/warden-skill/references/config-schema.md +0 -133
  173. package/.dex/config.toml +0 -2
  174. package/.github/workflows/ci.yml +0 -33
  175. package/.github/workflows/release.yml +0 -59
  176. package/.github/workflows/warden.yml +0 -40
  177. package/AGENTS.md +0 -89
  178. package/CONTRIBUTING.md +0 -60
  179. package/SPEC.md +0 -263
  180. package/action.yml +0 -87
  181. package/assets/favicon.png +0 -0
  182. package/assets/warden-icon-bw.svg +0 -5
  183. package/assets/warden-icon-purple.png +0 -0
  184. package/assets/warden-icon-purple.svg +0 -5
  185. package/dist/action/159.index.js +0 -523
  186. package/dist/action/159.index.js.map +0 -1
  187. package/dist/action/action/index.d.ts +0 -2
  188. package/dist/action/action/index.d.ts.map +0 -1
  189. package/dist/action/action/main.d.ts +0 -2
  190. package/dist/action/action/main.d.ts.map +0 -1
  191. package/dist/action/cli/args.d.ts +0 -74
  192. package/dist/action/cli/args.d.ts.map +0 -1
  193. package/dist/action/cli/args.test.d.ts +0 -2
  194. package/dist/action/cli/args.test.d.ts.map +0 -1
  195. package/dist/action/cli/commands/add.d.ts +0 -7
  196. package/dist/action/cli/commands/add.d.ts.map +0 -1
  197. package/dist/action/cli/commands/init.d.ts +0 -10
  198. package/dist/action/cli/commands/init.d.ts.map +0 -1
  199. package/dist/action/cli/commands/init.test.d.ts +0 -2
  200. package/dist/action/cli/commands/init.test.d.ts.map +0 -1
  201. package/dist/action/cli/commands/setup-app/browser.d.ts +0 -9
  202. package/dist/action/cli/commands/setup-app/browser.d.ts.map +0 -1
  203. package/dist/action/cli/commands/setup-app/credentials.d.ts +0 -15
  204. package/dist/action/cli/commands/setup-app/credentials.d.ts.map +0 -1
  205. package/dist/action/cli/commands/setup-app/manifest.d.ts +0 -24
  206. package/dist/action/cli/commands/setup-app/manifest.d.ts.map +0 -1
  207. package/dist/action/cli/commands/setup-app/server.d.ts +0 -28
  208. package/dist/action/cli/commands/setup-app/server.d.ts.map +0 -1
  209. package/dist/action/cli/commands/setup-app.d.ts +0 -11
  210. package/dist/action/cli/commands/setup-app.d.ts.map +0 -1
  211. package/dist/action/cli/commands/sync.d.ts +0 -9
  212. package/dist/action/cli/commands/sync.d.ts.map +0 -1
  213. package/dist/action/cli/context.d.ts +0 -27
  214. package/dist/action/cli/context.d.ts.map +0 -1
  215. package/dist/action/cli/files.d.ts +0 -22
  216. package/dist/action/cli/files.d.ts.map +0 -1
  217. package/dist/action/cli/files.test.d.ts +0 -2
  218. package/dist/action/cli/files.test.d.ts.map +0 -1
  219. package/dist/action/cli/fix.d.ts +0 -41
  220. package/dist/action/cli/fix.d.ts.map +0 -1
  221. package/dist/action/cli/fix.test.d.ts +0 -2
  222. package/dist/action/cli/fix.test.d.ts.map +0 -1
  223. package/dist/action/cli/git.d.ts +0 -73
  224. package/dist/action/cli/git.d.ts.map +0 -1
  225. package/dist/action/cli/git.test.d.ts +0 -2
  226. package/dist/action/cli/git.test.d.ts.map +0 -1
  227. package/dist/action/cli/index.d.ts +0 -3
  228. package/dist/action/cli/index.d.ts.map +0 -1
  229. package/dist/action/cli/main.d.ts +0 -7
  230. package/dist/action/cli/main.d.ts.map +0 -1
  231. package/dist/action/cli/output/box.d.ts +0 -75
  232. package/dist/action/cli/output/box.d.ts.map +0 -1
  233. package/dist/action/cli/output/formatters.d.ts +0 -90
  234. package/dist/action/cli/output/formatters.d.ts.map +0 -1
  235. package/dist/action/cli/output/formatters.test.d.ts +0 -2
  236. package/dist/action/cli/output/formatters.test.d.ts.map +0 -1
  237. package/dist/action/cli/output/icons.d.ts +0 -11
  238. package/dist/action/cli/output/icons.d.ts.map +0 -1
  239. package/dist/action/cli/output/index.d.ts +0 -10
  240. package/dist/action/cli/output/index.d.ts.map +0 -1
  241. package/dist/action/cli/output/ink-runner.d.ts +0 -9
  242. package/dist/action/cli/output/ink-runner.d.ts.map +0 -1
  243. package/dist/action/cli/output/jsonl.d.ts +0 -43
  244. package/dist/action/cli/output/jsonl.d.ts.map +0 -1
  245. package/dist/action/cli/output/jsonl.test.d.ts +0 -2
  246. package/dist/action/cli/output/jsonl.test.d.ts.map +0 -1
  247. package/dist/action/cli/output/reporter.d.ts +0 -108
  248. package/dist/action/cli/output/reporter.d.ts.map +0 -1
  249. package/dist/action/cli/output/tasks.d.ts +0 -89
  250. package/dist/action/cli/output/tasks.d.ts.map +0 -1
  251. package/dist/action/cli/output/tty.d.ts +0 -21
  252. package/dist/action/cli/output/tty.d.ts.map +0 -1
  253. package/dist/action/cli/output/tty.test.d.ts +0 -2
  254. package/dist/action/cli/output/tty.test.d.ts.map +0 -1
  255. package/dist/action/cli/output/verbosity.d.ts +0 -20
  256. package/dist/action/cli/output/verbosity.d.ts.map +0 -1
  257. package/dist/action/cli/output/verbosity.test.d.ts +0 -2
  258. package/dist/action/cli/output/verbosity.test.d.ts.map +0 -1
  259. package/dist/action/cli/terminal.d.ts +0 -19
  260. package/dist/action/cli/terminal.d.ts.map +0 -1
  261. package/dist/action/cli/terminal.test.d.ts +0 -2
  262. package/dist/action/cli/terminal.test.d.ts.map +0 -1
  263. package/dist/action/config/index.d.ts +0 -4
  264. package/dist/action/config/index.d.ts.map +0 -1
  265. package/dist/action/config/loader.d.ts +0 -27
  266. package/dist/action/config/loader.d.ts.map +0 -1
  267. package/dist/action/config/loader.test.d.ts +0 -2
  268. package/dist/action/config/loader.test.d.ts.map +0 -1
  269. package/dist/action/config/schema.d.ts +0 -318
  270. package/dist/action/config/schema.d.ts.map +0 -1
  271. package/dist/action/config/writer.d.ts +0 -11
  272. package/dist/action/config/writer.d.ts.map +0 -1
  273. package/dist/action/config/writer.test.d.ts +0 -2
  274. package/dist/action/config/writer.test.d.ts.map +0 -1
  275. package/dist/action/diff/classify.d.ts +0 -29
  276. package/dist/action/diff/classify.d.ts.map +0 -1
  277. package/dist/action/diff/classify.test.d.ts +0 -2
  278. package/dist/action/diff/classify.test.d.ts.map +0 -1
  279. package/dist/action/diff/coalesce.d.ts +0 -42
  280. package/dist/action/diff/coalesce.d.ts.map +0 -1
  281. package/dist/action/diff/coalesce.test.d.ts +0 -2
  282. package/dist/action/diff/coalesce.test.d.ts.map +0 -1
  283. package/dist/action/diff/context.d.ts +0 -30
  284. package/dist/action/diff/context.d.ts.map +0 -1
  285. package/dist/action/diff/context.test.d.ts +0 -2
  286. package/dist/action/diff/context.test.d.ts.map +0 -1
  287. package/dist/action/diff/index.d.ts +0 -5
  288. package/dist/action/diff/index.d.ts.map +0 -1
  289. package/dist/action/diff/parser.d.ts +0 -52
  290. package/dist/action/diff/parser.d.ts.map +0 -1
  291. package/dist/action/diff/parser.test.d.ts +0 -2
  292. package/dist/action/diff/parser.test.d.ts.map +0 -1
  293. package/dist/action/event/context.d.ts +0 -9
  294. package/dist/action/event/context.d.ts.map +0 -1
  295. package/dist/action/event/index.d.ts +0 -3
  296. package/dist/action/event/index.d.ts.map +0 -1
  297. package/dist/action/event/schedule-context.d.ts +0 -30
  298. package/dist/action/event/schedule-context.d.ts.map +0 -1
  299. package/dist/action/examples/examples.integration.test.d.ts +0 -2
  300. package/dist/action/examples/examples.integration.test.d.ts.map +0 -1
  301. package/dist/action/examples/index.d.ts +0 -50
  302. package/dist/action/examples/index.d.ts.map +0 -1
  303. package/dist/action/examples/index.test.d.ts +0 -2
  304. package/dist/action/examples/index.test.d.ts.map +0 -1
  305. package/dist/action/examples/setup.d.ts +0 -2
  306. package/dist/action/examples/setup.d.ts.map +0 -1
  307. package/dist/action/index.d.ts +0 -11
  308. package/dist/action/index.d.ts.map +0 -1
  309. package/dist/action/index.js +0 -38231
  310. package/dist/action/index.js.map +0 -1
  311. package/dist/action/licenses.txt +0 -992
  312. package/dist/action/main.d.ts +0 -2
  313. package/dist/action/main.d.ts.map +0 -1
  314. package/dist/action/main.js +0 -707
  315. package/dist/action/main.js.map +0 -1
  316. package/dist/action/output/dedup.d.ts +0 -153
  317. package/dist/action/output/dedup.d.ts.map +0 -1
  318. package/dist/action/output/dedup.test.d.ts +0 -2
  319. package/dist/action/output/dedup.test.d.ts.map +0 -1
  320. package/dist/action/output/github-checks.d.ts +0 -106
  321. package/dist/action/output/github-checks.d.ts.map +0 -1
  322. package/dist/action/output/github-checks.test.d.ts +0 -2
  323. package/dist/action/output/github-checks.test.d.ts.map +0 -1
  324. package/dist/action/output/github-issues.d.ts +0 -35
  325. package/dist/action/output/github-issues.d.ts.map +0 -1
  326. package/dist/action/output/index.d.ts +0 -6
  327. package/dist/action/output/index.d.ts.map +0 -1
  328. package/dist/action/output/issue-renderer.d.ts +0 -20
  329. package/dist/action/output/issue-renderer.d.ts.map +0 -1
  330. package/dist/action/output/renderer.d.ts +0 -4
  331. package/dist/action/output/renderer.d.ts.map +0 -1
  332. package/dist/action/output/renderer.test.d.ts +0 -2
  333. package/dist/action/output/renderer.test.d.ts.map +0 -1
  334. package/dist/action/output/stale.d.ts +0 -31
  335. package/dist/action/output/stale.d.ts.map +0 -1
  336. package/dist/action/output/stale.test.d.ts +0 -2
  337. package/dist/action/output/stale.test.d.ts.map +0 -1
  338. package/dist/action/output/types.d.ts +0 -31
  339. package/dist/action/output/types.d.ts.map +0 -1
  340. package/dist/action/package.json +0 -3
  341. package/dist/action/sdk/index.d.ts +0 -2
  342. package/dist/action/sdk/index.d.ts.map +0 -1
  343. package/dist/action/sdk/runner.d.ts +0 -202
  344. package/dist/action/sdk/runner.d.ts.map +0 -1
  345. package/dist/action/sdk/runner.test.d.ts +0 -2
  346. package/dist/action/sdk/runner.test.d.ts.map +0 -1
  347. package/dist/action/skills/index.d.ts +0 -5
  348. package/dist/action/skills/index.d.ts.map +0 -1
  349. package/dist/action/skills/loader.d.ts +0 -111
  350. package/dist/action/skills/loader.d.ts.map +0 -1
  351. package/dist/action/skills/loader.test.d.ts +0 -2
  352. package/dist/action/skills/loader.test.d.ts.map +0 -1
  353. package/dist/action/skills/remote.d.ts +0 -117
  354. package/dist/action/skills/remote.d.ts.map +0 -1
  355. package/dist/action/skills/remote.test.d.ts +0 -2
  356. package/dist/action/skills/remote.test.d.ts.map +0 -1
  357. package/dist/action/sourcemap-register.cjs +0 -1
  358. package/dist/action/triggers/matcher.d.ts +0 -30
  359. package/dist/action/triggers/matcher.d.ts.map +0 -1
  360. package/dist/action/triggers/matcher.test.d.ts +0 -2
  361. package/dist/action/triggers/matcher.test.d.ts.map +0 -1
  362. package/dist/action/types/index.d.ts +0 -269
  363. package/dist/action/types/index.d.ts.map +0 -1
  364. package/dist/action/utils/async.d.ts +0 -5
  365. package/dist/action/utils/async.d.ts.map +0 -1
  366. package/dist/action/utils/index.d.ts +0 -16
  367. package/dist/action/utils/index.d.ts.map +0 -1
  368. package/dist/action/utils/index.test.d.ts +0 -2
  369. package/dist/action/utils/index.test.d.ts.map +0 -1
  370. package/dist/action/utils/version.d.ts +0 -3
  371. package/dist/action/utils/version.d.ts.map +0 -1
  372. package/dist/cli/args.test.d.ts +0 -2
  373. package/dist/cli/args.test.d.ts.map +0 -1
  374. package/dist/cli/args.test.js +0 -392
  375. package/dist/cli/args.test.js.map +0 -1
  376. package/dist/cli/commands/init.test.d.ts +0 -2
  377. package/dist/cli/commands/init.test.d.ts.map +0 -1
  378. package/dist/cli/commands/init.test.js +0 -117
  379. package/dist/cli/commands/init.test.js.map +0 -1
  380. package/dist/cli/files.test.d.ts +0 -2
  381. package/dist/cli/files.test.d.ts.map +0 -1
  382. package/dist/cli/files.test.js +0 -117
  383. package/dist/cli/files.test.js.map +0 -1
  384. package/dist/cli/fix.test.d.ts +0 -2
  385. package/dist/cli/fix.test.d.ts.map +0 -1
  386. package/dist/cli/fix.test.js +0 -251
  387. package/dist/cli/fix.test.js.map +0 -1
  388. package/dist/cli/git.test.d.ts +0 -2
  389. package/dist/cli/git.test.d.ts.map +0 -1
  390. package/dist/cli/git.test.js +0 -96
  391. package/dist/cli/git.test.js.map +0 -1
  392. package/dist/cli/output/formatters.test.d.ts +0 -2
  393. package/dist/cli/output/formatters.test.d.ts.map +0 -1
  394. package/dist/cli/output/formatters.test.js +0 -152
  395. package/dist/cli/output/formatters.test.js.map +0 -1
  396. package/dist/cli/output/jsonl.test.d.ts +0 -2
  397. package/dist/cli/output/jsonl.test.d.ts.map +0 -1
  398. package/dist/cli/output/jsonl.test.js +0 -284
  399. package/dist/cli/output/jsonl.test.js.map +0 -1
  400. package/dist/cli/output/tty.test.d.ts +0 -2
  401. package/dist/cli/output/tty.test.d.ts.map +0 -1
  402. package/dist/cli/output/tty.test.js +0 -105
  403. package/dist/cli/output/tty.test.js.map +0 -1
  404. package/dist/cli/output/verbosity.test.d.ts +0 -2
  405. package/dist/cli/output/verbosity.test.d.ts.map +0 -1
  406. package/dist/cli/output/verbosity.test.js +0 -35
  407. package/dist/cli/output/verbosity.test.js.map +0 -1
  408. package/dist/cli/terminal.test.d.ts +0 -2
  409. package/dist/cli/terminal.test.d.ts.map +0 -1
  410. package/dist/cli/terminal.test.js +0 -123
  411. package/dist/cli/terminal.test.js.map +0 -1
  412. package/dist/config/loader.test.d.ts +0 -2
  413. package/dist/config/loader.test.d.ts.map +0 -1
  414. package/dist/config/loader.test.js +0 -263
  415. package/dist/config/loader.test.js.map +0 -1
  416. package/dist/config/writer.test.d.ts +0 -2
  417. package/dist/config/writer.test.d.ts.map +0 -1
  418. package/dist/config/writer.test.js +0 -98
  419. package/dist/config/writer.test.js.map +0 -1
  420. package/dist/diff/classify.test.d.ts +0 -2
  421. package/dist/diff/classify.test.d.ts.map +0 -1
  422. package/dist/diff/classify.test.js +0 -140
  423. package/dist/diff/classify.test.js.map +0 -1
  424. package/dist/diff/coalesce.test.d.ts +0 -2
  425. package/dist/diff/coalesce.test.d.ts.map +0 -1
  426. package/dist/diff/coalesce.test.js +0 -159
  427. package/dist/diff/coalesce.test.js.map +0 -1
  428. package/dist/diff/context.test.d.ts +0 -2
  429. package/dist/diff/context.test.d.ts.map +0 -1
  430. package/dist/diff/context.test.js +0 -190
  431. package/dist/diff/context.test.js.map +0 -1
  432. package/dist/diff/parser.test.d.ts +0 -2
  433. package/dist/diff/parser.test.d.ts.map +0 -1
  434. package/dist/diff/parser.test.js +0 -178
  435. package/dist/diff/parser.test.js.map +0 -1
  436. package/dist/examples/examples.integration.test.d.ts +0 -2
  437. package/dist/examples/examples.integration.test.d.ts.map +0 -1
  438. package/dist/examples/examples.integration.test.js +0 -55
  439. package/dist/examples/examples.integration.test.js.map +0 -1
  440. package/dist/examples/index.test.d.ts +0 -2
  441. package/dist/examples/index.test.d.ts.map +0 -1
  442. package/dist/examples/index.test.js +0 -88
  443. package/dist/examples/index.test.js.map +0 -1
  444. package/dist/output/dedup.test.d.ts +0 -2
  445. package/dist/output/dedup.test.d.ts.map +0 -1
  446. package/dist/output/dedup.test.js +0 -357
  447. package/dist/output/dedup.test.js.map +0 -1
  448. package/dist/output/github-checks.test.d.ts +0 -2
  449. package/dist/output/github-checks.test.d.ts.map +0 -1
  450. package/dist/output/github-checks.test.js +0 -255
  451. package/dist/output/github-checks.test.js.map +0 -1
  452. package/dist/output/renderer.test.d.ts +0 -2
  453. package/dist/output/renderer.test.d.ts.map +0 -1
  454. package/dist/output/renderer.test.js +0 -645
  455. package/dist/output/renderer.test.js.map +0 -1
  456. package/dist/output/stale.test.d.ts +0 -2
  457. package/dist/output/stale.test.d.ts.map +0 -1
  458. package/dist/output/stale.test.js +0 -330
  459. package/dist/output/stale.test.js.map +0 -1
  460. package/dist/sdk/runner.test.d.ts +0 -2
  461. package/dist/sdk/runner.test.d.ts.map +0 -1
  462. package/dist/sdk/runner.test.js +0 -677
  463. package/dist/sdk/runner.test.js.map +0 -1
  464. package/dist/skills/loader.test.d.ts +0 -2
  465. package/dist/skills/loader.test.d.ts.map +0 -1
  466. package/dist/skills/loader.test.js +0 -241
  467. package/dist/skills/loader.test.js.map +0 -1
  468. package/dist/skills/remote.test.d.ts +0 -2
  469. package/dist/skills/remote.test.d.ts.map +0 -1
  470. package/dist/skills/remote.test.js +0 -582
  471. package/dist/skills/remote.test.js.map +0 -1
  472. package/dist/triggers/matcher.test.d.ts +0 -2
  473. package/dist/triggers/matcher.test.d.ts.map +0 -1
  474. package/dist/triggers/matcher.test.js +0 -234
  475. package/dist/triggers/matcher.test.js.map +0 -1
  476. package/dist/utils/index.test.d.ts +0 -2
  477. package/dist/utils/index.test.d.ts.map +0 -1
  478. package/dist/utils/index.test.js +0 -68
  479. package/dist/utils/index.test.js.map +0 -1
  480. package/docs/astro.config.mjs +0 -43
  481. package/docs/package.json +0 -19
  482. package/docs/pnpm-lock.yaml +0 -4000
  483. package/docs/public/favicon.svg +0 -5
  484. package/docs/src/components/Code.astro +0 -141
  485. package/docs/src/components/PackageManagerTabs.astro +0 -183
  486. package/docs/src/components/Terminal.astro +0 -212
  487. package/docs/src/layouts/Base.astro +0 -380
  488. package/docs/src/pages/cli.astro +0 -167
  489. package/docs/src/pages/config.astro +0 -395
  490. package/docs/src/pages/guide.astro +0 -450
  491. package/docs/src/pages/index.astro +0 -490
  492. package/docs/src/styles/global.css +0 -551
  493. package/docs/src/utils/version.ts +0 -6
  494. package/docs/tsconfig.json +0 -3
  495. package/docs/vercel.json +0 -5
  496. package/eslint.config.js +0 -33
  497. package/src/action/index.ts +0 -1
  498. package/src/action/main.ts +0 -868
  499. package/src/cli/args.test.ts +0 -477
  500. package/src/cli/args.ts +0 -414
  501. package/src/cli/commands/add.ts +0 -447
  502. package/src/cli/commands/init.test.ts +0 -137
  503. package/src/cli/commands/init.ts +0 -134
  504. package/src/cli/commands/setup-app/browser.ts +0 -38
  505. package/src/cli/commands/setup-app/credentials.ts +0 -45
  506. package/src/cli/commands/setup-app/manifest.ts +0 -48
  507. package/src/cli/commands/setup-app/server.ts +0 -172
  508. package/src/cli/commands/setup-app.ts +0 -156
  509. package/src/cli/commands/sync.ts +0 -114
  510. package/src/cli/context.ts +0 -131
  511. package/src/cli/files.test.ts +0 -155
  512. package/src/cli/files.ts +0 -89
  513. package/src/cli/fix.test.ts +0 -310
  514. package/src/cli/fix.ts +0 -387
  515. package/src/cli/git.test.ts +0 -119
  516. package/src/cli/git.ts +0 -318
  517. package/src/cli/index.ts +0 -14
  518. package/src/cli/main.ts +0 -672
  519. package/src/cli/output/box.ts +0 -235
  520. package/src/cli/output/formatters.test.ts +0 -187
  521. package/src/cli/output/formatters.ts +0 -269
  522. package/src/cli/output/icons.ts +0 -13
  523. package/src/cli/output/index.ts +0 -44
  524. package/src/cli/output/ink-runner.tsx +0 -337
  525. package/src/cli/output/jsonl.test.ts +0 -347
  526. package/src/cli/output/jsonl.ts +0 -126
  527. package/src/cli/output/reporter.ts +0 -434
  528. package/src/cli/output/tasks.ts +0 -374
  529. package/src/cli/output/tty.test.ts +0 -117
  530. package/src/cli/output/tty.ts +0 -60
  531. package/src/cli/output/verbosity.test.ts +0 -40
  532. package/src/cli/output/verbosity.ts +0 -31
  533. package/src/cli/terminal.test.ts +0 -148
  534. package/src/cli/terminal.ts +0 -301
  535. package/src/config/index.ts +0 -3
  536. package/src/config/loader.test.ts +0 -313
  537. package/src/config/loader.ts +0 -103
  538. package/src/config/schema.ts +0 -168
  539. package/src/config/writer.test.ts +0 -119
  540. package/src/config/writer.ts +0 -84
  541. package/src/diff/classify.test.ts +0 -162
  542. package/src/diff/classify.ts +0 -92
  543. package/src/diff/coalesce.test.ts +0 -208
  544. package/src/diff/coalesce.ts +0 -133
  545. package/src/diff/context.test.ts +0 -226
  546. package/src/diff/context.ts +0 -201
  547. package/src/diff/index.ts +0 -4
  548. package/src/diff/parser.test.ts +0 -212
  549. package/src/diff/parser.ts +0 -149
  550. package/src/event/context.ts +0 -132
  551. package/src/event/index.ts +0 -2
  552. package/src/event/schedule-context.ts +0 -101
  553. package/src/examples/examples.integration.test.ts +0 -66
  554. package/src/examples/index.test.ts +0 -101
  555. package/src/examples/index.ts +0 -122
  556. package/src/examples/setup.ts +0 -25
  557. package/src/index.ts +0 -115
  558. package/src/output/dedup.test.ts +0 -419
  559. package/src/output/dedup.ts +0 -607
  560. package/src/output/github-checks.test.ts +0 -300
  561. package/src/output/github-checks.ts +0 -476
  562. package/src/output/github-issues.ts +0 -329
  563. package/src/output/index.ts +0 -5
  564. package/src/output/issue-renderer.ts +0 -197
  565. package/src/output/renderer.test.ts +0 -727
  566. package/src/output/renderer.ts +0 -217
  567. package/src/output/stale.test.ts +0 -375
  568. package/src/output/stale.ts +0 -155
  569. package/src/output/types.ts +0 -34
  570. package/src/sdk/index.ts +0 -1
  571. package/src/sdk/runner.test.ts +0 -806
  572. package/src/sdk/runner.ts +0 -1232
  573. package/src/skills/index.ts +0 -36
  574. package/src/skills/loader.test.ts +0 -300
  575. package/src/skills/loader.ts +0 -423
  576. package/src/skills/remote.test.ts +0 -704
  577. package/src/skills/remote.ts +0 -604
  578. package/src/triggers/matcher.test.ts +0 -277
  579. package/src/triggers/matcher.ts +0 -152
  580. package/src/types/index.ts +0 -194
  581. package/src/utils/async.ts +0 -18
  582. package/src/utils/index.test.ts +0 -84
  583. package/src/utils/index.ts +0 -51
  584. package/src/utils/version.ts +0 -17
  585. package/tsconfig.json +0 -25
  586. package/vitest.config.ts +0 -8
  587. package/vitest.integration.config.ts +0 -11
  588. 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
- }