@diff-review-system/drs 4.0.0-rc.4 → 4.0.1

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 (315) hide show
  1. package/.pi/agents/describe/pr-describer.md +14 -0
  2. package/.pi/agents/review/unified-reviewer.md +31 -1
  3. package/.pi/agents/task/agents-md-updater.md +3 -1
  4. package/.pi/agents/task/review-issue-fixer.md +18 -1
  5. package/.pi/agents/visual/pr-explainer.md +205 -0
  6. package/.pi/workflows/github-pr-describe.yaml +10 -7
  7. package/.pi/workflows/github-pr-fix-review-issues-stacked.yaml +148 -0
  8. package/.pi/workflows/github-pr-post-comment.yaml +10 -10
  9. package/.pi/workflows/github-pr-review-post.yaml +19 -8
  10. package/.pi/workflows/github-pr-review.yaml +348 -7
  11. package/.pi/workflows/github-pr-show-changes.yaml +8 -8
  12. package/.pi/workflows/github-pr-update-agents-md-stacked.yaml +103 -0
  13. package/.pi/workflows/github-pr-visual-explain.yaml +35 -0
  14. package/.pi/workflows/gitlab-mr-describe.yaml +8 -5
  15. package/.pi/workflows/gitlab-mr-fix-review-issues-stacked.yaml +144 -0
  16. package/.pi/workflows/gitlab-mr-post-comment.yaml +8 -8
  17. package/.pi/workflows/gitlab-mr-review.yaml +348 -5
  18. package/.pi/workflows/gitlab-mr-show-changes.yaml +6 -6
  19. package/.pi/workflows/gitlab-mr-update-agents-md-stacked.yaml +100 -0
  20. package/.pi/workflows/gitlab-mr-visual-explain.yaml +33 -0
  21. package/.pi/workflows/local-fix-review-issues.yaml +82 -13
  22. package/.pi/workflows/local-review.yaml +9 -2
  23. package/.pi/workflows/local-update-agents-md.yaml +1 -1
  24. package/.pi/workflows/local-visual-explain.yaml +31 -0
  25. package/.pi/workflows/release-changelog-finalize.yaml +47 -0
  26. package/.pi/workflows/tag-changelog-update.yaml +4 -4
  27. package/README.md +91 -27
  28. package/dist/ci/runner.d.ts.map +1 -1
  29. package/dist/ci/runner.js +3 -1
  30. package/dist/ci/runner.js.map +1 -1
  31. package/dist/cli/index.js +48 -6
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/cli/run-agent.d.ts +2 -0
  34. package/dist/cli/run-agent.d.ts.map +1 -1
  35. package/dist/cli/run-agent.js +4 -0
  36. package/dist/cli/run-agent.js.map +1 -1
  37. package/dist/cli/workflow.d.ts +56 -2
  38. package/dist/cli/workflow.d.ts.map +1 -1
  39. package/dist/cli/workflow.js +2165 -85
  40. package/dist/cli/workflow.js.map +1 -1
  41. package/dist/github/client.d.ts +12 -0
  42. package/dist/github/client.d.ts.map +1 -1
  43. package/dist/github/client.js +27 -0
  44. package/dist/github/client.js.map +1 -1
  45. package/dist/github/platform-adapter.d.ts +6 -1
  46. package/dist/github/platform-adapter.d.ts.map +1 -1
  47. package/dist/github/platform-adapter.js +84 -8
  48. package/dist/github/platform-adapter.js.map +1 -1
  49. package/dist/gitlab/client.d.ts +11 -0
  50. package/dist/gitlab/client.d.ts.map +1 -1
  51. package/dist/gitlab/client.js +11 -0
  52. package/dist/gitlab/client.js.map +1 -1
  53. package/dist/gitlab/platform-adapter.d.ts +3 -1
  54. package/dist/gitlab/platform-adapter.d.ts.map +1 -1
  55. package/dist/gitlab/platform-adapter.js +32 -1
  56. package/dist/gitlab/platform-adapter.js.map +1 -1
  57. package/dist/lib/comment-formatter.d.ts +8 -0
  58. package/dist/lib/comment-formatter.d.ts.map +1 -1
  59. package/dist/lib/comment-formatter.js +12 -4
  60. package/dist/lib/comment-formatter.js.map +1 -1
  61. package/dist/lib/comment-poster.d.ts.map +1 -1
  62. package/dist/lib/comment-poster.js +28 -1
  63. package/dist/lib/comment-poster.js.map +1 -1
  64. package/dist/lib/config.d.ts +50 -11
  65. package/dist/lib/config.d.ts.map +1 -1
  66. package/dist/lib/config.js +163 -28
  67. package/dist/lib/config.js.map +1 -1
  68. package/dist/lib/context-compression.d.ts +10 -0
  69. package/dist/lib/context-compression.d.ts.map +1 -1
  70. package/dist/lib/context-compression.js +101 -13
  71. package/dist/lib/context-compression.js.map +1 -1
  72. package/dist/lib/context-loader.d.ts +2 -1
  73. package/dist/lib/context-loader.d.ts.map +1 -1
  74. package/dist/lib/context-loader.js +70 -1
  75. package/dist/lib/context-loader.js.map +1 -1
  76. package/dist/lib/describe-core.d.ts.map +1 -1
  77. package/dist/lib/describe-core.js +3 -2
  78. package/dist/lib/describe-core.js.map +1 -1
  79. package/dist/lib/diff-lines.d.ts +9 -0
  80. package/dist/lib/diff-lines.d.ts.map +1 -1
  81. package/dist/lib/diff-lines.js +17 -9
  82. package/dist/lib/diff-lines.js.map +1 -1
  83. package/dist/lib/exit.js +4 -4
  84. package/dist/lib/exit.js.map +1 -1
  85. package/dist/lib/html-artifact.d.ts +14 -0
  86. package/dist/lib/html-artifact.d.ts.map +1 -0
  87. package/dist/lib/html-artifact.js +59 -0
  88. package/dist/lib/html-artifact.js.map +1 -0
  89. package/dist/lib/issue-parser.js +3 -3
  90. package/dist/lib/issue-parser.js.map +1 -1
  91. package/dist/lib/json-output-schema.d.ts +70 -0
  92. package/dist/lib/json-output-schema.d.ts.map +1 -1
  93. package/dist/lib/json-output-schema.js +40 -0
  94. package/dist/lib/json-output-schema.js.map +1 -1
  95. package/dist/lib/platform-client.d.ts +26 -0
  96. package/dist/lib/platform-client.d.ts.map +1 -1
  97. package/dist/lib/review-artifact.d.ts +69 -0
  98. package/dist/lib/review-artifact.d.ts.map +1 -0
  99. package/dist/lib/review-artifact.js +171 -0
  100. package/dist/lib/review-artifact.js.map +1 -0
  101. package/dist/lib/review-core.d.ts +6 -4
  102. package/dist/lib/review-core.d.ts.map +1 -1
  103. package/dist/lib/review-core.js +71 -151
  104. package/dist/lib/review-core.js.map +1 -1
  105. package/dist/lib/review-orchestrator.d.ts +23 -0
  106. package/dist/lib/review-orchestrator.d.ts.map +1 -1
  107. package/dist/lib/review-orchestrator.js +20 -13
  108. package/dist/lib/review-orchestrator.js.map +1 -1
  109. package/dist/lib/review-usage.d.ts +4 -0
  110. package/dist/lib/review-usage.d.ts.map +1 -1
  111. package/dist/lib/review-usage.js +25 -0
  112. package/dist/lib/review-usage.js.map +1 -1
  113. package/dist/lib/trace-collector.d.ts +105 -0
  114. package/dist/lib/trace-collector.d.ts.map +1 -0
  115. package/dist/lib/trace-collector.js +255 -0
  116. package/dist/lib/trace-collector.js.map +1 -0
  117. package/dist/lib/trace-html.d.ts +3 -0
  118. package/dist/lib/trace-html.d.ts.map +1 -0
  119. package/dist/lib/trace-html.js +349 -0
  120. package/dist/lib/trace-html.js.map +1 -0
  121. package/dist/lib/workflow-artifacts.d.ts +54 -0
  122. package/dist/lib/workflow-artifacts.d.ts.map +1 -0
  123. package/dist/lib/workflow-artifacts.js +150 -0
  124. package/dist/lib/workflow-artifacts.js.map +1 -0
  125. package/dist/pi/sdk.d.ts.map +1 -1
  126. package/dist/pi/sdk.js +570 -6
  127. package/dist/pi/sdk.js.map +1 -1
  128. package/dist/runtime/agent-loader.js +2 -2
  129. package/dist/runtime/client.d.ts +2 -0
  130. package/dist/runtime/client.d.ts.map +1 -1
  131. package/dist/runtime/client.js +11 -5
  132. package/dist/runtime/client.js.map +1 -1
  133. package/package.json +21 -15
  134. package/.pi/workflows/github-pr-describe-post.yaml +0 -24
  135. package/.pi/workflows/gitlab-mr-describe-post.yaml +0 -22
  136. package/.pi/workflows/gitlab-mr-review-code-quality.yaml +0 -31
  137. package/.pi/workflows/gitlab-mr-review-post-code-quality.yaml +0 -40
  138. package/.pi/workflows/gitlab-mr-review-post.yaml +0 -30
  139. package/.pi/workflows/local-staged-review.yaml +0 -17
  140. package/dist/cli/run-agent.test.d.ts +0 -2
  141. package/dist/cli/run-agent.test.d.ts.map +0 -1
  142. package/dist/cli/run-agent.test.js +0 -204
  143. package/dist/cli/run-agent.test.js.map +0 -1
  144. package/dist/cli/workflow.test.d.ts +0 -2
  145. package/dist/cli/workflow.test.d.ts.map +0 -1
  146. package/dist/cli/workflow.test.js +0 -1410
  147. package/dist/cli/workflow.test.js.map +0 -1
  148. package/dist/github/client.test.d.ts +0 -2
  149. package/dist/github/client.test.d.ts.map +0 -1
  150. package/dist/github/client.test.js +0 -206
  151. package/dist/github/client.test.js.map +0 -1
  152. package/dist/github/platform-adapter.test.d.ts +0 -2
  153. package/dist/github/platform-adapter.test.d.ts.map +0 -1
  154. package/dist/github/platform-adapter.test.js +0 -40
  155. package/dist/github/platform-adapter.test.js.map +0 -1
  156. package/dist/gitlab/diff-parser.test.d.ts +0 -2
  157. package/dist/gitlab/diff-parser.test.d.ts.map +0 -1
  158. package/dist/gitlab/diff-parser.test.js +0 -315
  159. package/dist/gitlab/diff-parser.test.js.map +0 -1
  160. package/dist/gitlab/platform-adapter.test.d.ts +0 -2
  161. package/dist/gitlab/platform-adapter.test.d.ts.map +0 -1
  162. package/dist/gitlab/platform-adapter.test.js +0 -21
  163. package/dist/gitlab/platform-adapter.test.js.map +0 -1
  164. package/dist/index.test.d.ts +0 -2
  165. package/dist/index.test.d.ts.map +0 -1
  166. package/dist/index.test.js +0 -7
  167. package/dist/index.test.js.map +0 -1
  168. package/dist/lib/code-quality-report.test.d.ts +0 -2
  169. package/dist/lib/code-quality-report.test.d.ts.map +0 -1
  170. package/dist/lib/code-quality-report.test.js +0 -327
  171. package/dist/lib/code-quality-report.test.js.map +0 -1
  172. package/dist/lib/comment-formatter.test.d.ts +0 -2
  173. package/dist/lib/comment-formatter.test.d.ts.map +0 -1
  174. package/dist/lib/comment-formatter.test.js +0 -727
  175. package/dist/lib/comment-formatter.test.js.map +0 -1
  176. package/dist/lib/comment-manager.test.d.ts +0 -2
  177. package/dist/lib/comment-manager.test.d.ts.map +0 -1
  178. package/dist/lib/comment-manager.test.js +0 -680
  179. package/dist/lib/comment-manager.test.js.map +0 -1
  180. package/dist/lib/comment-poster.test.d.ts +0 -5
  181. package/dist/lib/comment-poster.test.d.ts.map +0 -1
  182. package/dist/lib/comment-poster.test.js +0 -255
  183. package/dist/lib/comment-poster.test.js.map +0 -1
  184. package/dist/lib/config-model-overrides.test.d.ts +0 -2
  185. package/dist/lib/config-model-overrides.test.d.ts.map +0 -1
  186. package/dist/lib/config-model-overrides.test.js +0 -218
  187. package/dist/lib/config-model-overrides.test.js.map +0 -1
  188. package/dist/lib/config.test.d.ts +0 -2
  189. package/dist/lib/config.test.d.ts.map +0 -1
  190. package/dist/lib/config.test.js +0 -353
  191. package/dist/lib/config.test.js.map +0 -1
  192. package/dist/lib/context-compression.test.d.ts +0 -2
  193. package/dist/lib/context-compression.test.d.ts.map +0 -1
  194. package/dist/lib/context-compression.test.js +0 -337
  195. package/dist/lib/context-compression.test.js.map +0 -1
  196. package/dist/lib/context-loader.test.d.ts +0 -2
  197. package/dist/lib/context-loader.test.d.ts.map +0 -1
  198. package/dist/lib/context-loader.test.js +0 -212
  199. package/dist/lib/context-loader.test.js.map +0 -1
  200. package/dist/lib/cursor-fix-link.test.d.ts +0 -2
  201. package/dist/lib/cursor-fix-link.test.d.ts.map +0 -1
  202. package/dist/lib/cursor-fix-link.test.js +0 -70
  203. package/dist/lib/cursor-fix-link.test.js.map +0 -1
  204. package/dist/lib/describe-core.test.d.ts +0 -2
  205. package/dist/lib/describe-core.test.d.ts.map +0 -1
  206. package/dist/lib/describe-core.test.js +0 -208
  207. package/dist/lib/describe-core.test.js.map +0 -1
  208. package/dist/lib/describe-output-path.test.d.ts +0 -2
  209. package/dist/lib/describe-output-path.test.d.ts.map +0 -1
  210. package/dist/lib/describe-output-path.test.js +0 -51
  211. package/dist/lib/describe-output-path.test.js.map +0 -1
  212. package/dist/lib/describe-parser.test.d.ts +0 -2
  213. package/dist/lib/describe-parser.test.d.ts.map +0 -1
  214. package/dist/lib/describe-parser.test.js +0 -282
  215. package/dist/lib/describe-parser.test.js.map +0 -1
  216. package/dist/lib/description-executor.test.d.ts +0 -2
  217. package/dist/lib/description-executor.test.d.ts.map +0 -1
  218. package/dist/lib/description-executor.test.js +0 -135
  219. package/dist/lib/description-executor.test.js.map +0 -1
  220. package/dist/lib/description-formatter.test.d.ts +0 -2
  221. package/dist/lib/description-formatter.test.d.ts.map +0 -1
  222. package/dist/lib/description-formatter.test.js +0 -57
  223. package/dist/lib/description-formatter.test.js.map +0 -1
  224. package/dist/lib/diff-lines.test.d.ts +0 -2
  225. package/dist/lib/diff-lines.test.d.ts.map +0 -1
  226. package/dist/lib/diff-lines.test.js +0 -13
  227. package/dist/lib/diff-lines.test.js.map +0 -1
  228. package/dist/lib/diff-parser.test.d.ts +0 -2
  229. package/dist/lib/diff-parser.test.d.ts.map +0 -1
  230. package/dist/lib/diff-parser.test.js +0 -335
  231. package/dist/lib/diff-parser.test.js.map +0 -1
  232. package/dist/lib/error-comment-poster.test.d.ts +0 -2
  233. package/dist/lib/error-comment-poster.test.d.ts.map +0 -1
  234. package/dist/lib/error-comment-poster.test.js +0 -128
  235. package/dist/lib/error-comment-poster.test.js.map +0 -1
  236. package/dist/lib/exit.test.d.ts +0 -2
  237. package/dist/lib/exit.test.d.ts.map +0 -1
  238. package/dist/lib/exit.test.js +0 -120
  239. package/dist/lib/exit.test.js.map +0 -1
  240. package/dist/lib/issue-parser.test.d.ts +0 -2
  241. package/dist/lib/issue-parser.test.d.ts.map +0 -1
  242. package/dist/lib/issue-parser.test.js +0 -281
  243. package/dist/lib/issue-parser.test.js.map +0 -1
  244. package/dist/lib/json-output-schema.test.d.ts +0 -2
  245. package/dist/lib/json-output-schema.test.d.ts.map +0 -1
  246. package/dist/lib/json-output-schema.test.js +0 -92
  247. package/dist/lib/json-output-schema.test.js.map +0 -1
  248. package/dist/lib/json-output.test.d.ts +0 -2
  249. package/dist/lib/json-output.test.d.ts.map +0 -1
  250. package/dist/lib/json-output.test.js +0 -141
  251. package/dist/lib/json-output.test.js.map +0 -1
  252. package/dist/lib/logger.test.d.ts +0 -2
  253. package/dist/lib/logger.test.d.ts.map +0 -1
  254. package/dist/lib/logger.test.js +0 -324
  255. package/dist/lib/logger.test.js.map +0 -1
  256. package/dist/lib/position-validator.test.d.ts +0 -2
  257. package/dist/lib/position-validator.test.d.ts.map +0 -1
  258. package/dist/lib/position-validator.test.js +0 -128
  259. package/dist/lib/position-validator.test.js.map +0 -1
  260. package/dist/lib/prompt-budget.test.d.ts +0 -2
  261. package/dist/lib/prompt-budget.test.d.ts.map +0 -1
  262. package/dist/lib/prompt-budget.test.js +0 -55
  263. package/dist/lib/prompt-budget.test.js.map +0 -1
  264. package/dist/lib/repository-validator.test.d.ts +0 -5
  265. package/dist/lib/repository-validator.test.d.ts.map +0 -1
  266. package/dist/lib/repository-validator.test.js +0 -341
  267. package/dist/lib/repository-validator.test.js.map +0 -1
  268. package/dist/lib/review-core.test.d.ts +0 -2
  269. package/dist/lib/review-core.test.d.ts.map +0 -1
  270. package/dist/lib/review-core.test.js +0 -614
  271. package/dist/lib/review-core.test.js.map +0 -1
  272. package/dist/lib/review-orchestrator.test.d.ts +0 -2
  273. package/dist/lib/review-orchestrator.test.d.ts.map +0 -1
  274. package/dist/lib/review-orchestrator.test.js +0 -552
  275. package/dist/lib/review-orchestrator.test.js.map +0 -1
  276. package/dist/lib/review-output-path.test.d.ts +0 -2
  277. package/dist/lib/review-output-path.test.d.ts.map +0 -1
  278. package/dist/lib/review-output-path.test.js +0 -83
  279. package/dist/lib/review-output-path.test.js.map +0 -1
  280. package/dist/lib/review-parser.test.d.ts +0 -2
  281. package/dist/lib/review-parser.test.d.ts.map +0 -1
  282. package/dist/lib/review-parser.test.js +0 -130
  283. package/dist/lib/review-parser.test.js.map +0 -1
  284. package/dist/lib/review-usage.test.d.ts +0 -2
  285. package/dist/lib/review-usage.test.d.ts.map +0 -1
  286. package/dist/lib/review-usage.test.js +0 -83
  287. package/dist/lib/review-usage.test.js.map +0 -1
  288. package/dist/lib/unified-review-executor.d.ts +0 -58
  289. package/dist/lib/unified-review-executor.d.ts.map +0 -1
  290. package/dist/lib/unified-review-executor.js +0 -201
  291. package/dist/lib/unified-review-executor.js.map +0 -1
  292. package/dist/lib/unified-review-executor.test.d.ts +0 -5
  293. package/dist/lib/unified-review-executor.test.d.ts.map +0 -1
  294. package/dist/lib/unified-review-executor.test.js +0 -472
  295. package/dist/lib/unified-review-executor.test.js.map +0 -1
  296. package/dist/lib/write-json-output.test.d.ts +0 -2
  297. package/dist/lib/write-json-output.test.d.ts.map +0 -1
  298. package/dist/lib/write-json-output.test.js +0 -259
  299. package/dist/lib/write-json-output.test.js.map +0 -1
  300. package/dist/pi/sdk.test.d.ts +0 -2
  301. package/dist/pi/sdk.test.d.ts.map +0 -1
  302. package/dist/pi/sdk.test.js +0 -488
  303. package/dist/pi/sdk.test.js.map +0 -1
  304. package/dist/runtime/agent-loader.test.d.ts +0 -2
  305. package/dist/runtime/agent-loader.test.d.ts.map +0 -1
  306. package/dist/runtime/agent-loader.test.js +0 -277
  307. package/dist/runtime/agent-loader.test.js.map +0 -1
  308. package/dist/runtime/client.test.d.ts +0 -2
  309. package/dist/runtime/client.test.d.ts.map +0 -1
  310. package/dist/runtime/client.test.js +0 -772
  311. package/dist/runtime/client.test.js.map +0 -1
  312. package/dist/runtime/path-config.test.d.ts +0 -2
  313. package/dist/runtime/path-config.test.d.ts.map +0 -1
  314. package/dist/runtime/path-config.test.js +0 -112
  315. package/dist/runtime/path-config.test.js.map +0 -1
@@ -1,680 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createIssueFingerprint, extractCommentId, extractIssueFingerprints, filterCriticalAndHigh, filterDuplicateIssues, findExistingSummaryComment, findExistingErrorComment, collectExistingFingerprints, prepareIssuesForPosting, BOT_COMMENT_ID, ERROR_COMMENT_ID, } from './comment-manager.js';
3
- describe('comment-manager', () => {
4
- describe('createIssueFingerprint', () => {
5
- it('should create fingerprint with line number', () => {
6
- const issue = {
7
- category: 'SECURITY',
8
- severity: 'HIGH',
9
- title: 'SQL Injection',
10
- file: 'src/db.ts',
11
- line: 42,
12
- problem: 'Unsafe query',
13
- solution: 'Use parameterized queries',
14
- agent: 'security',
15
- };
16
- const fingerprint = createIssueFingerprint(issue);
17
- expect(fingerprint).toBe('src/db.ts:42:SECURITY:SQL Injection');
18
- });
19
- it('should create fingerprint without line number', () => {
20
- const issue = {
21
- category: 'QUALITY',
22
- severity: 'MEDIUM',
23
- title: 'Code smell',
24
- file: 'src/app.ts',
25
- problem: 'Complex function',
26
- solution: 'Refactor',
27
- agent: 'quality',
28
- };
29
- const fingerprint = createIssueFingerprint(issue);
30
- expect(fingerprint).toBe('src/app.ts:general:QUALITY:Code smell');
31
- });
32
- it('should create fingerprint with line 0 (treated as general)', () => {
33
- const issue = {
34
- category: 'STYLE',
35
- severity: 'LOW',
36
- title: 'Missing import',
37
- file: 'src/utils.ts',
38
- line: 0,
39
- problem: 'Missing import',
40
- solution: 'Add import',
41
- agent: 'style',
42
- };
43
- const fingerprint = createIssueFingerprint(issue);
44
- expect(fingerprint).toBe('src/utils.ts:general:STYLE:Missing import');
45
- });
46
- it('should create unique fingerprints for different issues', () => {
47
- const issue1 = {
48
- category: 'SECURITY',
49
- severity: 'HIGH',
50
- title: 'Issue 1',
51
- file: 'file1.ts',
52
- line: 10,
53
- problem: 'Problem',
54
- solution: 'Solution',
55
- agent: 'security',
56
- };
57
- const issue2 = {
58
- category: 'SECURITY',
59
- severity: 'HIGH',
60
- title: 'Issue 2',
61
- file: 'file1.ts',
62
- line: 10,
63
- problem: 'Problem',
64
- solution: 'Solution',
65
- agent: 'security',
66
- };
67
- const fp1 = createIssueFingerprint(issue1);
68
- const fp2 = createIssueFingerprint(issue2);
69
- expect(fp1).not.toBe(fp2);
70
- });
71
- });
72
- describe('extractCommentId', () => {
73
- it('should extract comment ID from body', () => {
74
- const body = 'Some text\n<!-- drs-comment-id: drs-review-summary -->\nMore text';
75
- const id = extractCommentId(body);
76
- expect(id).toBe('drs-review-summary');
77
- });
78
- it('should return null if no comment ID found', () => {
79
- const body = 'Just some regular text without markers';
80
- const id = extractCommentId(body);
81
- expect(id).toBeNull();
82
- });
83
- it('should extract custom comment ID', () => {
84
- const body = '<!-- drs-comment-id: custom-id-123 -->';
85
- const id = extractCommentId(body);
86
- expect(id).toBe('custom-id-123');
87
- });
88
- it('should handle multiple comment IDs and return first', () => {
89
- const body = '<!-- drs-comment-id: first-id -->\n<!-- drs-comment-id: second-id -->';
90
- const id = extractCommentId(body);
91
- expect(id).toBe('first-id');
92
- });
93
- });
94
- describe('extractIssueFingerprints', () => {
95
- it('should extract single fingerprint', () => {
96
- const body = 'Issue here\n<!-- issue-fp: src/app.ts:10:SECURITY:SQL Injection -->';
97
- const fingerprints = extractIssueFingerprints(body);
98
- expect(fingerprints.size).toBe(1);
99
- expect(fingerprints.has('src/app.ts:10:SECURITY:SQL Injection')).toBe(true);
100
- });
101
- it('should extract multiple fingerprints', () => {
102
- const body = `
103
- <!-- issue-fp: src/app.ts:10:SECURITY:Issue 1 -->
104
- Some text
105
- <!-- issue-fp: src/db.ts:20:QUALITY:Issue 2 -->
106
- More text
107
- <!-- issue-fp: src/utils.ts:general:STYLE:Issue 3 -->
108
- `;
109
- const fingerprints = extractIssueFingerprints(body);
110
- expect(fingerprints.size).toBe(3);
111
- expect(fingerprints.has('src/app.ts:10:SECURITY:Issue 1')).toBe(true);
112
- expect(fingerprints.has('src/db.ts:20:QUALITY:Issue 2')).toBe(true);
113
- expect(fingerprints.has('src/utils.ts:general:STYLE:Issue 3')).toBe(true);
114
- });
115
- it('should return empty set if no fingerprints found', () => {
116
- const body = 'Just regular text with no fingerprints';
117
- const fingerprints = extractIssueFingerprints(body);
118
- expect(fingerprints.size).toBe(0);
119
- });
120
- it('should handle duplicate fingerprints in same comment', () => {
121
- const body = `
122
- <!-- issue-fp: src/app.ts:10:SECURITY:Issue -->
123
- <!-- issue-fp: src/app.ts:10:SECURITY:Issue -->
124
- `;
125
- const fingerprints = extractIssueFingerprints(body);
126
- expect(fingerprints.size).toBe(1);
127
- });
128
- });
129
- describe('filterCriticalAndHigh', () => {
130
- it('should filter only CRITICAL issues', () => {
131
- const issues = [
132
- {
133
- category: 'SECURITY',
134
- severity: 'CRITICAL',
135
- title: 'Critical issue',
136
- file: 'file.ts',
137
- line: 1,
138
- problem: 'Problem',
139
- solution: 'Solution',
140
- agent: 'security',
141
- },
142
- {
143
- category: 'QUALITY',
144
- severity: 'MEDIUM',
145
- title: 'Medium issue',
146
- file: 'file.ts',
147
- line: 2,
148
- problem: 'Problem',
149
- solution: 'Solution',
150
- agent: 'quality',
151
- },
152
- ];
153
- const filtered = filterCriticalAndHigh(issues);
154
- expect(filtered).toHaveLength(1);
155
- expect(filtered[0].severity).toBe('CRITICAL');
156
- });
157
- it('should filter only HIGH issues', () => {
158
- const issues = [
159
- {
160
- category: 'SECURITY',
161
- severity: 'HIGH',
162
- title: 'High issue',
163
- file: 'file.ts',
164
- line: 1,
165
- problem: 'Problem',
166
- solution: 'Solution',
167
- agent: 'security',
168
- },
169
- {
170
- category: 'QUALITY',
171
- severity: 'LOW',
172
- title: 'Low issue',
173
- file: 'file.ts',
174
- line: 2,
175
- problem: 'Problem',
176
- solution: 'Solution',
177
- agent: 'quality',
178
- },
179
- ];
180
- const filtered = filterCriticalAndHigh(issues);
181
- expect(filtered).toHaveLength(1);
182
- expect(filtered[0].severity).toBe('HIGH');
183
- });
184
- it('should filter both CRITICAL and HIGH issues', () => {
185
- const issues = [
186
- {
187
- category: 'SECURITY',
188
- severity: 'CRITICAL',
189
- title: 'Critical',
190
- file: 'file.ts',
191
- line: 1,
192
- problem: 'Problem',
193
- solution: 'Solution',
194
- agent: 'security',
195
- },
196
- {
197
- category: 'SECURITY',
198
- severity: 'HIGH',
199
- title: 'High',
200
- file: 'file.ts',
201
- line: 2,
202
- problem: 'Problem',
203
- solution: 'Solution',
204
- agent: 'security',
205
- },
206
- {
207
- category: 'QUALITY',
208
- severity: 'MEDIUM',
209
- title: 'Medium',
210
- file: 'file.ts',
211
- line: 3,
212
- problem: 'Problem',
213
- solution: 'Solution',
214
- agent: 'quality',
215
- },
216
- {
217
- category: 'STYLE',
218
- severity: 'LOW',
219
- title: 'Low',
220
- file: 'file.ts',
221
- line: 4,
222
- problem: 'Problem',
223
- solution: 'Solution',
224
- agent: 'style',
225
- },
226
- ];
227
- const filtered = filterCriticalAndHigh(issues);
228
- expect(filtered).toHaveLength(2);
229
- expect(filtered.every((i) => i.severity === 'CRITICAL' || i.severity === 'HIGH')).toBe(true);
230
- });
231
- it('should return empty array if no critical/high issues', () => {
232
- const issues = [
233
- {
234
- category: 'QUALITY',
235
- severity: 'MEDIUM',
236
- title: 'Medium',
237
- file: 'file.ts',
238
- line: 1,
239
- problem: 'Problem',
240
- solution: 'Solution',
241
- agent: 'quality',
242
- },
243
- {
244
- category: 'STYLE',
245
- severity: 'LOW',
246
- title: 'Low',
247
- file: 'file.ts',
248
- line: 2,
249
- problem: 'Problem',
250
- solution: 'Solution',
251
- agent: 'style',
252
- },
253
- ];
254
- const filtered = filterCriticalAndHigh(issues);
255
- expect(filtered).toHaveLength(0);
256
- });
257
- });
258
- describe('filterDuplicateIssues', () => {
259
- it('should filter out duplicate issues', () => {
260
- const issues = [
261
- {
262
- category: 'SECURITY',
263
- severity: 'HIGH',
264
- title: 'SQL Injection',
265
- file: 'src/db.ts',
266
- line: 42,
267
- problem: 'Problem',
268
- solution: 'Solution',
269
- agent: 'security',
270
- },
271
- {
272
- category: 'QUALITY',
273
- severity: 'MEDIUM',
274
- title: 'Code smell',
275
- file: 'src/app.ts',
276
- line: 10,
277
- problem: 'Problem',
278
- solution: 'Solution',
279
- agent: 'quality',
280
- },
281
- ];
282
- const existingFingerprints = new Set(['src/db.ts:42:SECURITY:SQL Injection']);
283
- const filtered = filterDuplicateIssues(issues, existingFingerprints);
284
- expect(filtered).toHaveLength(1);
285
- expect(filtered[0].title).toBe('Code smell');
286
- });
287
- it('should return all issues if no duplicates', () => {
288
- const issues = [
289
- {
290
- category: 'SECURITY',
291
- severity: 'HIGH',
292
- title: 'Issue 1',
293
- file: 'file1.ts',
294
- line: 1,
295
- problem: 'Problem',
296
- solution: 'Solution',
297
- agent: 'security',
298
- },
299
- {
300
- category: 'QUALITY',
301
- severity: 'MEDIUM',
302
- title: 'Issue 2',
303
- file: 'file2.ts',
304
- line: 2,
305
- problem: 'Problem',
306
- solution: 'Solution',
307
- agent: 'quality',
308
- },
309
- ];
310
- const existingFingerprints = new Set();
311
- const filtered = filterDuplicateIssues(issues, existingFingerprints);
312
- expect(filtered).toHaveLength(2);
313
- });
314
- it('should filter all issues if all are duplicates', () => {
315
- const issues = [
316
- {
317
- category: 'SECURITY',
318
- severity: 'HIGH',
319
- title: 'Issue 1',
320
- file: 'file1.ts',
321
- line: 1,
322
- problem: 'Problem',
323
- solution: 'Solution',
324
- agent: 'security',
325
- },
326
- {
327
- category: 'QUALITY',
328
- severity: 'MEDIUM',
329
- title: 'Issue 2',
330
- file: 'file2.ts',
331
- line: 2,
332
- problem: 'Problem',
333
- solution: 'Solution',
334
- agent: 'quality',
335
- },
336
- ];
337
- const existingFingerprints = new Set([
338
- 'file1.ts:1:SECURITY:Issue 1',
339
- 'file2.ts:2:QUALITY:Issue 2',
340
- ]);
341
- const filtered = filterDuplicateIssues(issues, existingFingerprints);
342
- expect(filtered).toHaveLength(0);
343
- });
344
- });
345
- describe('findExistingSummaryComment', () => {
346
- it('should find summary comment with bot marker', () => {
347
- const comments = [
348
- { id: 1, body: 'Regular comment' },
349
- {
350
- id: 2,
351
- body: `Review Summary\n<!-- drs-comment-id: ${BOT_COMMENT_ID} -->\nSummary text`,
352
- },
353
- { id: 3, body: 'Another comment' },
354
- ];
355
- const found = findExistingSummaryComment(comments);
356
- expect(found).not.toBeNull();
357
- expect(found?.id).toBe(2);
358
- });
359
- it('should return null if no summary comment exists', () => {
360
- const comments = [
361
- { id: 1, body: 'Regular comment 1' },
362
- { id: 2, body: 'Regular comment 2' },
363
- ];
364
- const found = findExistingSummaryComment(comments);
365
- expect(found).toBeNull();
366
- });
367
- it('should return first summary comment if multiple exist', () => {
368
- const comments = [
369
- {
370
- id: 1,
371
- body: `Summary 1\n<!-- drs-comment-id: ${BOT_COMMENT_ID} -->`,
372
- },
373
- {
374
- id: 2,
375
- body: `Summary 2\n<!-- drs-comment-id: ${BOT_COMMENT_ID} -->`,
376
- },
377
- ];
378
- const found = findExistingSummaryComment(comments);
379
- expect(found?.id).toBe(1);
380
- });
381
- it('should handle empty comments array', () => {
382
- const comments = [];
383
- const found = findExistingSummaryComment(comments);
384
- expect(found).toBeNull();
385
- });
386
- });
387
- describe('findExistingErrorComment', () => {
388
- it('should find error comment with error marker', () => {
389
- const comments = [
390
- { id: 1, body: 'Regular comment' },
391
- {
392
- id: 2,
393
- body: `Error!\n<!-- drs-comment-id: ${ERROR_COMMENT_ID} -->\nError details`,
394
- },
395
- { id: 3, body: 'Another comment' },
396
- ];
397
- const found = findExistingErrorComment(comments);
398
- expect(found).not.toBeNull();
399
- expect(found?.id).toBe(2);
400
- });
401
- it('should return null if no error comment exists', () => {
402
- const comments = [
403
- { id: 1, body: 'Regular comment 1' },
404
- { id: 2, body: 'Regular comment 2' },
405
- {
406
- id: 3,
407
- body: `Summary\n<!-- drs-comment-id: ${BOT_COMMENT_ID} -->`,
408
- },
409
- ];
410
- const found = findExistingErrorComment(comments);
411
- expect(found).toBeNull();
412
- });
413
- it('should return first error comment if multiple exist', () => {
414
- const comments = [
415
- {
416
- id: 1,
417
- body: `Error 1\n<!-- drs-comment-id: ${ERROR_COMMENT_ID} -->`,
418
- },
419
- {
420
- id: 2,
421
- body: `Error 2\n<!-- drs-comment-id: ${ERROR_COMMENT_ID} -->`,
422
- },
423
- ];
424
- const found = findExistingErrorComment(comments);
425
- expect(found?.id).toBe(1);
426
- });
427
- it('should handle empty comments array', () => {
428
- const comments = [];
429
- const found = findExistingErrorComment(comments);
430
- expect(found).toBeNull();
431
- });
432
- it('should distinguish between error and summary comments', () => {
433
- const comments = [
434
- {
435
- id: 1,
436
- body: `Summary\n<!-- drs-comment-id: ${BOT_COMMENT_ID} -->`,
437
- },
438
- {
439
- id: 2,
440
- body: `Error\n<!-- drs-comment-id: ${ERROR_COMMENT_ID} -->`,
441
- },
442
- ];
443
- const errorComment = findExistingErrorComment(comments);
444
- const summaryComment = findExistingSummaryComment(comments);
445
- expect(errorComment?.id).toBe(2);
446
- expect(summaryComment?.id).toBe(1);
447
- });
448
- });
449
- describe('collectExistingFingerprints', () => {
450
- it('should collect fingerprints from multiple comments', () => {
451
- const comments = [
452
- {
453
- id: 1,
454
- body: `Issue 1\n<!-- issue-fp: file1.ts:10:SECURITY:Issue 1 -->`,
455
- },
456
- {
457
- id: 2,
458
- body: `Issue 2\n<!-- issue-fp: file2.ts:20:QUALITY:Issue 2 -->`,
459
- },
460
- ];
461
- const fingerprints = collectExistingFingerprints(comments);
462
- expect(fingerprints.size).toBe(2);
463
- expect(fingerprints.has('file1.ts:10:SECURITY:Issue 1')).toBe(true);
464
- expect(fingerprints.has('file2.ts:20:QUALITY:Issue 2')).toBe(true);
465
- });
466
- it('should collect multiple fingerprints from single comment', () => {
467
- const comments = [
468
- {
469
- id: 1,
470
- body: `
471
- <!-- issue-fp: file1.ts:10:SECURITY:Issue 1 -->
472
- <!-- issue-fp: file2.ts:20:QUALITY:Issue 2 -->
473
- <!-- issue-fp: file3.ts:30:STYLE:Issue 3 -->
474
- `,
475
- },
476
- ];
477
- const fingerprints = collectExistingFingerprints(comments);
478
- expect(fingerprints.size).toBe(3);
479
- });
480
- it('should deduplicate fingerprints across comments', () => {
481
- const comments = [
482
- {
483
- id: 1,
484
- body: `<!-- issue-fp: file1.ts:10:SECURITY:Issue -->`,
485
- },
486
- {
487
- id: 2,
488
- body: `<!-- issue-fp: file1.ts:10:SECURITY:Issue -->`,
489
- },
490
- ];
491
- const fingerprints = collectExistingFingerprints(comments);
492
- expect(fingerprints.size).toBe(1);
493
- });
494
- it('should return empty set for comments with no fingerprints', () => {
495
- const comments = [
496
- { id: 1, body: 'Regular comment 1' },
497
- { id: 2, body: 'Regular comment 2' },
498
- ];
499
- const fingerprints = collectExistingFingerprints(comments);
500
- expect(fingerprints.size).toBe(0);
501
- });
502
- it('should handle empty comments array', () => {
503
- const comments = [];
504
- const fingerprints = collectExistingFingerprints(comments);
505
- expect(fingerprints.size).toBe(0);
506
- });
507
- });
508
- describe('prepareIssuesForPosting', () => {
509
- it('should filter and prepare issues correctly', () => {
510
- const allIssues = [
511
- {
512
- category: 'SECURITY',
513
- severity: 'CRITICAL',
514
- title: 'New critical issue',
515
- file: 'file1.ts',
516
- line: 10,
517
- problem: 'Problem',
518
- solution: 'Solution',
519
- agent: 'security',
520
- },
521
- {
522
- category: 'SECURITY',
523
- severity: 'HIGH',
524
- title: 'New high issue',
525
- file: 'file2.ts',
526
- line: 20,
527
- problem: 'Problem',
528
- solution: 'Solution',
529
- agent: 'security',
530
- },
531
- {
532
- category: 'QUALITY',
533
- severity: 'MEDIUM',
534
- title: 'Medium issue',
535
- file: 'file3.ts',
536
- line: 30,
537
- problem: 'Problem',
538
- solution: 'Solution',
539
- agent: 'quality',
540
- },
541
- {
542
- category: 'STYLE',
543
- severity: 'LOW',
544
- title: 'Low issue',
545
- file: 'file4.ts',
546
- line: 40,
547
- problem: 'Problem',
548
- solution: 'Solution',
549
- agent: 'style',
550
- },
551
- ];
552
- const existingComments = [];
553
- const result = prepareIssuesForPosting(allIssues, existingComments);
554
- expect(result.inlineIssues).toHaveLength(2);
555
- expect(result.deduplicatedCount).toBe(0);
556
- expect(result.nonInlineCount).toBe(2); // MEDIUM + LOW
557
- });
558
- it('should deduplicate existing issues', () => {
559
- const allIssues = [
560
- {
561
- category: 'SECURITY',
562
- severity: 'CRITICAL',
563
- title: 'Existing issue',
564
- file: 'file1.ts',
565
- line: 10,
566
- problem: 'Problem',
567
- solution: 'Solution',
568
- agent: 'security',
569
- },
570
- {
571
- category: 'SECURITY',
572
- severity: 'HIGH',
573
- title: 'New issue',
574
- file: 'file2.ts',
575
- line: 20,
576
- problem: 'Problem',
577
- solution: 'Solution',
578
- agent: 'security',
579
- },
580
- ];
581
- const existingComments = [
582
- {
583
- id: 1,
584
- body: '<!-- issue-fp: file1.ts:10:SECURITY:Existing issue -->',
585
- },
586
- ];
587
- const result = prepareIssuesForPosting(allIssues, existingComments);
588
- expect(result.inlineIssues).toHaveLength(1);
589
- expect(result.inlineIssues[0].title).toBe('New issue');
590
- expect(result.deduplicatedCount).toBe(1);
591
- });
592
- it('should filter out issues without line numbers', () => {
593
- const allIssues = [
594
- {
595
- category: 'SECURITY',
596
- severity: 'CRITICAL',
597
- title: 'With line',
598
- file: 'file1.ts',
599
- line: 10,
600
- problem: 'Problem',
601
- solution: 'Solution',
602
- agent: 'security',
603
- },
604
- {
605
- category: 'SECURITY',
606
- severity: 'HIGH',
607
- title: 'Without line',
608
- file: 'file2.ts',
609
- problem: 'Problem',
610
- solution: 'Solution',
611
- agent: 'security',
612
- },
613
- ];
614
- const existingComments = [];
615
- const result = prepareIssuesForPosting(allIssues, existingComments);
616
- expect(result.inlineIssues).toHaveLength(1);
617
- expect(result.inlineIssues[0].title).toBe('With line');
618
- });
619
- it('should apply custom valid lines checker', () => {
620
- const allIssues = [
621
- {
622
- category: 'SECURITY',
623
- severity: 'CRITICAL',
624
- title: 'Valid line',
625
- file: 'file1.ts',
626
- line: 10,
627
- problem: 'Problem',
628
- solution: 'Solution',
629
- agent: 'security',
630
- },
631
- {
632
- category: 'SECURITY',
633
- severity: 'HIGH',
634
- title: 'Invalid line',
635
- file: 'file2.ts',
636
- line: 999,
637
- problem: 'Problem',
638
- solution: 'Solution',
639
- agent: 'security',
640
- },
641
- ];
642
- const existingComments = [];
643
- // Only allow lines <= 100
644
- const validLinesChecker = (issue) => {
645
- return issue.line !== undefined && issue.line <= 100;
646
- };
647
- const result = prepareIssuesForPosting(allIssues, existingComments, validLinesChecker);
648
- expect(result.inlineIssues).toHaveLength(1);
649
- expect(result.inlineIssues[0].title).toBe('Valid line');
650
- });
651
- it('should handle all issues being filtered out', () => {
652
- const allIssues = [
653
- {
654
- category: 'QUALITY',
655
- severity: 'MEDIUM',
656
- title: 'Medium issue',
657
- file: 'file1.ts',
658
- line: 10,
659
- problem: 'Problem',
660
- solution: 'Solution',
661
- agent: 'quality',
662
- },
663
- ];
664
- const existingComments = [];
665
- const result = prepareIssuesForPosting(allIssues, existingComments);
666
- expect(result.inlineIssues).toHaveLength(0);
667
- expect(result.nonInlineCount).toBe(1);
668
- expect(result.deduplicatedCount).toBe(0);
669
- });
670
- it('should handle empty issues array', () => {
671
- const allIssues = [];
672
- const existingComments = [];
673
- const result = prepareIssuesForPosting(allIssues, existingComments);
674
- expect(result.inlineIssues).toHaveLength(0);
675
- expect(result.nonInlineCount).toBe(0);
676
- expect(result.deduplicatedCount).toBe(0);
677
- });
678
- });
679
- });
680
- //# sourceMappingURL=comment-manager.test.js.map