@rigour-labs/core 6.8.0 → 6.8.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 (326) hide show
  1. package/dist/inference/cloud-provider.js +12 -2
  2. package/package.json +11 -8
  3. package/dist/brief/briefing.test.d.ts +0 -1
  4. package/dist/brief/briefing.test.js +0 -107
  5. package/dist/context/automatic-index-cache.test.d.ts +0 -1
  6. package/dist/context/automatic-index-cache.test.js +0 -30
  7. package/dist/context/automatic-index.test.d.ts +0 -1
  8. package/dist/context/automatic-index.test.js +0 -45
  9. package/dist/context/cache-engine.test.d.ts +0 -1
  10. package/dist/context/cache-engine.test.js +0 -99
  11. package/dist/context/dependency-graph.test.d.ts +0 -1
  12. package/dist/context/dependency-graph.test.js +0 -13
  13. package/dist/context/index-status.test.d.ts +0 -1
  14. package/dist/context/index-status.test.js +0 -26
  15. package/dist/context.test.d.ts +0 -1
  16. package/dist/context.test.js +0 -228
  17. package/dist/deep/agent-review.test.d.ts +0 -1
  18. package/dist/deep/agent-review.test.js +0 -53
  19. package/dist/deep/code-context.test.d.ts +0 -1
  20. package/dist/deep/code-context.test.js +0 -48
  21. package/dist/deep/code-pass.test.d.ts +0 -1
  22. package/dist/deep/code-pass.test.js +0 -112
  23. package/dist/deep/code-review-prompt.test.d.ts +0 -1
  24. package/dist/deep/code-review-prompt.test.js +0 -20
  25. package/dist/deep/code-verifier.test.d.ts +0 -1
  26. package/dist/deep/code-verifier.test.js +0 -54
  27. package/dist/deep/diff-tests/calls.test.d.ts +0 -1
  28. package/dist/deep/diff-tests/calls.test.js +0 -33
  29. package/dist/deep/diff-tests/run.test.d.ts +0 -1
  30. package/dist/deep/diff-tests/run.test.js +0 -58
  31. package/dist/deep/fact-extractor.test.d.ts +0 -1
  32. package/dist/deep/fact-extractor.test.js +0 -581
  33. package/dist/deep/parse-findings.test.d.ts +0 -1
  34. package/dist/deep/parse-findings.test.js +0 -25
  35. package/dist/deep/pr-review.test.d.ts +0 -1
  36. package/dist/deep/pr-review.test.js +0 -80
  37. package/dist/deep/prompts.test.d.ts +0 -1
  38. package/dist/deep/prompts.test.js +0 -235
  39. package/dist/deep/reference-pack.test.d.ts +0 -1
  40. package/dist/deep/reference-pack.test.js +0 -46
  41. package/dist/deep/related-changes.test.d.ts +0 -1
  42. package/dist/deep/related-changes.test.js +0 -33
  43. package/dist/deep/review-context-export.test.d.ts +0 -1
  44. package/dist/deep/review-context-export.test.js +0 -32
  45. package/dist/deep/review-tools.test.d.ts +0 -1
  46. package/dist/deep/review-tools.test.js +0 -39
  47. package/dist/deep/risk.test.d.ts +0 -1
  48. package/dist/deep/risk.test.js +0 -101
  49. package/dist/deep/verifier.test.d.ts +0 -1
  50. package/dist/deep/verifier.test.js +0 -635
  51. package/dist/discovery.test.d.ts +0 -1
  52. package/dist/discovery.test.js +0 -93
  53. package/dist/environment.test.d.ts +0 -1
  54. package/dist/environment.test.js +0 -94
  55. package/dist/firewall/firewall.test.d.ts +0 -1
  56. package/dist/firewall/firewall.test.js +0 -117
  57. package/dist/firewall/trust-boundaries.test.d.ts +0 -1
  58. package/dist/firewall/trust-boundaries.test.js +0 -64
  59. package/dist/firewall/trusted-control.test.d.ts +0 -1
  60. package/dist/firewall/trusted-control.test.js +0 -188
  61. package/dist/gates/agent-team.test.d.ts +0 -1
  62. package/dist/gates/agent-team.test.js +0 -113
  63. package/dist/gates/ast.test.d.ts +0 -1
  64. package/dist/gates/ast.test.js +0 -112
  65. package/dist/gates/checkpoint.test.d.ts +0 -1
  66. package/dist/gates/checkpoint.test.js +0 -105
  67. package/dist/gates/content.test.d.ts +0 -1
  68. package/dist/gates/content.test.js +0 -73
  69. package/dist/gates/coverage.test.d.ts +0 -1
  70. package/dist/gates/coverage.test.js +0 -53
  71. package/dist/gates/dedupe-failures.test.d.ts +0 -1
  72. package/dist/gates/dedupe-failures.test.js +0 -12
  73. package/dist/gates/deep-analysis.test.d.ts +0 -1
  74. package/dist/gates/deep-analysis.test.js +0 -86
  75. package/dist/gates/deep-intent.test.d.ts +0 -1
  76. package/dist/gates/deep-intent.test.js +0 -51
  77. package/dist/gates/deep-timeout.test.d.ts +0 -1
  78. package/dist/gates/deep-timeout.test.js +0 -10
  79. package/dist/gates/deprecated-apis.test.d.ts +0 -1
  80. package/dist/gates/deprecated-apis.test.js +0 -318
  81. package/dist/gates/deprecated-dependencies.test.d.ts +0 -1
  82. package/dist/gates/deprecated-dependencies.test.js +0 -55
  83. package/dist/gates/frontend-secret-exposure.test.d.ts +0 -1
  84. package/dist/gates/frontend-secret-exposure.test.js +0 -148
  85. package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.d.ts +0 -1
  86. package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.js +0 -27
  87. package/dist/gates/hallucinated-imports/js-resolver-types.test.d.ts +0 -1
  88. package/dist/gates/hallucinated-imports/js-resolver-types.test.js +0 -14
  89. package/dist/gates/hallucinated-imports-sveltekit.test.d.ts +0 -1
  90. package/dist/gates/hallucinated-imports-sveltekit.test.js +0 -132
  91. package/dist/gates/hallucinated-imports.test.d.ts +0 -1
  92. package/dist/gates/hallucinated-imports.test.js +0 -1206
  93. package/dist/gates/js-style-context.test.d.ts +0 -1
  94. package/dist/gates/js-style-context.test.js +0 -35
  95. package/dist/gates/logic-drift.test.d.ts +0 -1
  96. package/dist/gates/logic-drift.test.js +0 -52
  97. package/dist/gates/phantom-apis.test.d.ts +0 -1
  98. package/dist/gates/phantom-apis.test.js +0 -396
  99. package/dist/gates/promise-safety.test.d.ts +0 -1
  100. package/dist/gates/promise-safety.test.js +0 -34
  101. package/dist/gates/runner.test.d.ts +0 -1
  102. package/dist/gates/runner.test.js +0 -77
  103. package/dist/gates/scoped-gates.test.d.ts +0 -1
  104. package/dist/gates/scoped-gates.test.js +0 -52
  105. package/dist/gates/security-patterns-owasp.test.d.ts +0 -1
  106. package/dist/gates/security-patterns-owasp.test.js +0 -186
  107. package/dist/gates/security-patterns.test.d.ts +0 -1
  108. package/dist/gates/security-patterns.test.js +0 -194
  109. package/dist/gates/semantic-bugs.test.d.ts +0 -1
  110. package/dist/gates/semantic-bugs.test.js +0 -76
  111. package/dist/gates/side-effect-analysis.test.d.ts +0 -1
  112. package/dist/gates/side-effect-analysis.test.js +0 -162
  113. package/dist/gates/style-drift.test.d.ts +0 -1
  114. package/dist/gates/style-drift.test.js +0 -26
  115. package/dist/gates/test-quality.test.d.ts +0 -1
  116. package/dist/gates/test-quality.test.js +0 -325
  117. package/dist/gates/trusted-reviews.test.d.ts +0 -1
  118. package/dist/gates/trusted-reviews.test.js +0 -16
  119. package/dist/gates/unindexed-reads/queries.test.d.ts +0 -1
  120. package/dist/gates/unindexed-reads/queries.test.js +0 -54
  121. package/dist/gates/unindexed-reads/schema.test.d.ts +0 -1
  122. package/dist/gates/unindexed-reads/schema.test.js +0 -81
  123. package/dist/gates/unindexed-reads/unindexed-reads.test.d.ts +0 -1
  124. package/dist/gates/unindexed-reads/unindexed-reads.test.js +0 -90
  125. package/dist/hooks/checker.test.d.ts +0 -1
  126. package/dist/hooks/checker.test.js +0 -159
  127. package/dist/hooks/dlp-confidence.test.d.ts +0 -1
  128. package/dist/hooks/dlp-confidence.test.js +0 -51
  129. package/dist/hooks/dlp-feedback.test.d.ts +0 -1
  130. package/dist/hooks/dlp-feedback.test.js +0 -131
  131. package/dist/hooks/input-validator.test.d.ts +0 -1
  132. package/dist/hooks/input-validator.test.js +0 -329
  133. package/dist/hooks/templates.test.d.ts +0 -1
  134. package/dist/hooks/templates.test.js +0 -27
  135. package/dist/inference/brain-placeholder.test.d.ts +0 -1
  136. package/dist/inference/brain-placeholder.test.js +0 -28
  137. package/dist/inference/cloud-provider.test.d.ts +0 -1
  138. package/dist/inference/cloud-provider.test.js +0 -139
  139. package/dist/inference/executable.test.d.ts +0 -1
  140. package/dist/inference/executable.test.js +0 -41
  141. package/dist/inference/http-download.test.d.ts +0 -1
  142. package/dist/inference/http-download.test.js +0 -109
  143. package/dist/inference/llama-engine-checksum.test.d.ts +0 -1
  144. package/dist/inference/llama-engine-checksum.test.js +0 -27
  145. package/dist/inference/llama-engine.test.d.ts +0 -1
  146. package/dist/inference/llama-engine.test.js +0 -51
  147. package/dist/inference/llama-process.test.d.ts +0 -1
  148. package/dist/inference/llama-process.test.js +0 -61
  149. package/dist/inference/local-model.test.d.ts +0 -1
  150. package/dist/inference/local-model.test.js +0 -23
  151. package/dist/inference/model-download.test.d.ts +0 -1
  152. package/dist/inference/model-download.test.js +0 -125
  153. package/dist/inference/model-manager.test.d.ts +0 -1
  154. package/dist/inference/model-manager.test.js +0 -24
  155. package/dist/inference/types.test.d.ts +0 -1
  156. package/dist/inference/types.test.js +0 -19
  157. package/dist/memory/recall.test.d.ts +0 -1
  158. package/dist/memory/recall.test.js +0 -36
  159. package/dist/pattern-index/indexer.test.d.ts +0 -6
  160. package/dist/pattern-index/indexer.test.js +0 -197
  161. package/dist/pattern-index/matcher.test.d.ts +0 -6
  162. package/dist/pattern-index/matcher.test.js +0 -238
  163. package/dist/pattern-index/pattern-reuse.test.d.ts +0 -1
  164. package/dist/pattern-index/pattern-reuse.test.js +0 -76
  165. package/dist/pattern-index/semantic-runtime.test.d.ts +0 -1
  166. package/dist/pattern-index/semantic-runtime.test.js +0 -31
  167. package/dist/pattern-index/staleness.test.d.ts +0 -6
  168. package/dist/pattern-index/staleness.test.js +0 -211
  169. package/dist/review/agent-fixes.test.d.ts +0 -1
  170. package/dist/review/agent-fixes.test.js +0 -32
  171. package/dist/review/backtest-init.test.d.ts +0 -1
  172. package/dist/review/backtest-init.test.js +0 -136
  173. package/dist/review/backtest-judges.test.d.ts +0 -1
  174. package/dist/review/backtest-judges.test.js +0 -32
  175. package/dist/review/backtest-last.test.d.ts +0 -1
  176. package/dist/review/backtest-last.test.js +0 -109
  177. package/dist/review/backtest.test.d.ts +0 -1
  178. package/dist/review/backtest.test.js +0 -183
  179. package/dist/review/baseline.test.d.ts +0 -1
  180. package/dist/review/baseline.test.js +0 -22
  181. package/dist/review/branch-checks.test.d.ts +0 -1
  182. package/dist/review/branch-checks.test.js +0 -48
  183. package/dist/review/check-outcomes.test.d.ts +0 -1
  184. package/dist/review/check-outcomes.test.js +0 -56
  185. package/dist/review/code-patterns.test.d.ts +0 -1
  186. package/dist/review/code-patterns.test.js +0 -142
  187. package/dist/review/dead-code.test.d.ts +0 -1
  188. package/dist/review/dead-code.test.js +0 -154
  189. package/dist/review/deep-runs.test.d.ts +0 -1
  190. package/dist/review/deep-runs.test.js +0 -23
  191. package/dist/review/effectiveness.test.d.ts +0 -1
  192. package/dist/review/effectiveness.test.js +0 -42
  193. package/dist/review/fix-scope.test.d.ts +0 -1
  194. package/dist/review/fix-scope.test.js +0 -104
  195. package/dist/review/generated-files.test.d.ts +0 -1
  196. package/dist/review/generated-files.test.js +0 -25
  197. package/dist/review/migration-order.test.d.ts +0 -1
  198. package/dist/review/migration-order.test.js +0 -62
  199. package/dist/review/quiet.test.d.ts +0 -1
  200. package/dist/review/quiet.test.js +0 -38
  201. package/dist/review/receipt.test.d.ts +0 -1
  202. package/dist/review/receipt.test.js +0 -60
  203. package/dist/review/review-task.test.d.ts +0 -1
  204. package/dist/review/review-task.test.js +0 -89
  205. package/dist/review/review.test.d.ts +0 -1
  206. package/dist/review/review.test.js +0 -203
  207. package/dist/review/reviewer/adapters.test.d.ts +0 -1
  208. package/dist/review/reviewer/adapters.test.js +0 -100
  209. package/dist/review/reviewer/api-judge.test.d.ts +0 -1
  210. package/dist/review/reviewer/api-judge.test.js +0 -108
  211. package/dist/review/reviewer/background.test.d.ts +0 -1
  212. package/dist/review/reviewer/background.test.js +0 -118
  213. package/dist/review/reviewer/context.test.d.ts +0 -1
  214. package/dist/review/reviewer/context.test.js +0 -45
  215. package/dist/review/reviewer/exec.test.d.ts +0 -1
  216. package/dist/review/reviewer/exec.test.js +0 -59
  217. package/dist/review/reviewer/inputs.test.d.ts +0 -1
  218. package/dist/review/reviewer/inputs.test.js +0 -52
  219. package/dist/review/reviewer/panel.test.d.ts +0 -1
  220. package/dist/review/reviewer/panel.test.js +0 -110
  221. package/dist/review/reviewer/record.test.d.ts +0 -1
  222. package/dist/review/reviewer/record.test.js +0 -40
  223. package/dist/review/reviewer/rule-writer.test.d.ts +0 -1
  224. package/dist/review/reviewer/rule-writer.test.js +0 -52
  225. package/dist/review/reviewer/settings.test.d.ts +0 -1
  226. package/dist/review/reviewer/settings.test.js +0 -57
  227. package/dist/review/reviewer/usage.test.d.ts +0 -1
  228. package/dist/review/reviewer/usage.test.js +0 -14
  229. package/dist/review/reviewer.test.d.ts +0 -1
  230. package/dist/review/reviewer.test.js +0 -792
  231. package/dist/review/stories.test.d.ts +0 -1
  232. package/dist/review/stories.test.js +0 -58
  233. package/dist/review/toolchain.test.d.ts +0 -1
  234. package/dist/review/toolchain.test.js +0 -108
  235. package/dist/review/typed/redundancy.test.d.ts +0 -1
  236. package/dist/review/typed/redundancy.test.js +0 -315
  237. package/dist/review/typed/schema-nullability.test.d.ts +0 -1
  238. package/dist/review/typed/schema-nullability.test.js +0 -63
  239. package/dist/review-learning/human-edits.test.d.ts +0 -1
  240. package/dist/review-learning/human-edits.test.js +0 -47
  241. package/dist/review-learning/repo-rules.test.d.ts +0 -1
  242. package/dist/review-learning/repo-rules.test.js +0 -93
  243. package/dist/review-learning/review-learning.test.d.ts +0 -1
  244. package/dist/review-learning/review-learning.test.js +0 -249
  245. package/dist/safety.test.d.ts +0 -1
  246. package/dist/safety.test.js +0 -42
  247. package/dist/semantic/benchmark.test.d.ts +0 -1
  248. package/dist/semantic/benchmark.test.js +0 -22
  249. package/dist/semantic/intent/intent.test.d.ts +0 -1
  250. package/dist/semantic/intent/intent.test.js +0 -46
  251. package/dist/semantic/learn/learn.test.d.ts +0 -1
  252. package/dist/semantic/learn/learn.test.js +0 -67
  253. package/dist/semantic/origins.test.d.ts +0 -1
  254. package/dist/semantic/origins.test.js +0 -77
  255. package/dist/semantic/project-facts.test.d.ts +0 -1
  256. package/dist/semantic/project-facts.test.js +0 -45
  257. package/dist/semantic/sites/call-sites.test.d.ts +0 -1
  258. package/dist/semantic/sites/call-sites.test.js +0 -46
  259. package/dist/services/adaptive-thresholds.test.d.ts +0 -1
  260. package/dist/services/adaptive-thresholds.test.js +0 -53
  261. package/dist/services/agent-history.test.d.ts +0 -1
  262. package/dist/services/agent-history.test.js +0 -69
  263. package/dist/services/context-scope-summary.test.d.ts +0 -1
  264. package/dist/services/context-scope-summary.test.js +0 -17
  265. package/dist/services/context-telemetry-service.test.d.ts +0 -1
  266. package/dist/services/context-telemetry-service.test.js +0 -182
  267. package/dist/services/cursor-usage-sync.test.d.ts +0 -1
  268. package/dist/services/cursor-usage-sync.test.js +0 -173
  269. package/dist/services/engineering-knowledge-graph.test.d.ts +0 -1
  270. package/dist/services/engineering-knowledge-graph.test.js +0 -76
  271. package/dist/services/model-pricing.test.d.ts +0 -1
  272. package/dist/services/model-pricing.test.js +0 -44
  273. package/dist/services/observed-savings.test.d.ts +0 -1
  274. package/dist/services/observed-savings.test.js +0 -37
  275. package/dist/services/score-history.test.d.ts +0 -1
  276. package/dist/services/score-history.test.js +0 -61
  277. package/dist/smoke.test.d.ts +0 -1
  278. package/dist/smoke.test.js +0 -17
  279. package/dist/storage/cache-cleanup.test.d.ts +0 -1
  280. package/dist/storage/cache-cleanup.test.js +0 -54
  281. package/dist/storage/context-telemetry.test.d.ts +0 -1
  282. package/dist/storage/context-telemetry.test.js +0 -80
  283. package/dist/storage/db.test.d.ts +0 -1
  284. package/dist/storage/db.test.js +0 -46
  285. package/dist/storage/fix-lessons.test.d.ts +0 -1
  286. package/dist/storage/fix-lessons.test.js +0 -61
  287. package/dist/storage/lessons.test.d.ts +0 -1
  288. package/dist/storage/lessons.test.js +0 -81
  289. package/dist/storage/local-encryption.test.d.ts +0 -1
  290. package/dist/storage/local-encryption.test.js +0 -34
  291. package/dist/storage/local-memory.test.d.ts +0 -1
  292. package/dist/storage/local-memory.test.js +0 -55
  293. package/dist/storage/share-memory.test.d.ts +0 -1
  294. package/dist/storage/share-memory.test.js +0 -34
  295. package/dist/storage/team-diagnostics.test.d.ts +0 -1
  296. package/dist/storage/team-diagnostics.test.js +0 -51
  297. package/dist/storage/team-scope.test.d.ts +0 -1
  298. package/dist/storage/team-scope.test.js +0 -22
  299. package/dist/storage/team-store.test.d.ts +0 -1
  300. package/dist/storage/team-store.test.js +0 -11
  301. package/dist/storage/team-sync-scope.test.d.ts +0 -1
  302. package/dist/storage/team-sync-scope.test.js +0 -100
  303. package/dist/storage/team-vector-store.test.d.ts +0 -1
  304. package/dist/storage/team-vector-store.test.js +0 -56
  305. package/dist/storage/telemetry-scope.test.d.ts +0 -1
  306. package/dist/storage/telemetry-scope.test.js +0 -38
  307. package/dist/task/thread.test.d.ts +0 -1
  308. package/dist/task/thread.test.js +0 -133
  309. package/dist/telemetry/telemetry.test.d.ts +0 -1
  310. package/dist/telemetry/telemetry.test.js +0 -64
  311. package/dist/types/index.test.d.ts +0 -1
  312. package/dist/types/index.test.js +0 -33
  313. package/dist/utils/command-line.test.d.ts +0 -1
  314. package/dist/utils/command-line.test.js +0 -8
  315. package/dist/utils/diff-removed.test.d.ts +0 -1
  316. package/dist/utils/diff-removed.test.js +0 -29
  317. package/dist/utils/diff.test.d.ts +0 -1
  318. package/dist/utils/diff.test.js +0 -38
  319. package/dist/utils/glob-paths.test.d.ts +0 -1
  320. package/dist/utils/glob-paths.test.js +0 -40
  321. package/dist/utils/profile.test.d.ts +0 -1
  322. package/dist/utils/profile.test.js +0 -68
  323. package/dist/utils/scanner.test.d.ts +0 -1
  324. package/dist/utils/scanner.test.js +0 -48
  325. package/dist/utils/scope.test.d.ts +0 -1
  326. package/dist/utils/scope.test.js +0 -38
@@ -1 +0,0 @@
1
- export {};
@@ -1,235 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { buildAnalysisPrompt, buildCrossFilePrompt, chunkFacts, DEEP_SYSTEM_PROMPT } from './prompts.js';
3
- import { factsToPromptString } from './fact-extractor.js';
4
- // ── Test helpers ──
5
- function makeGoFacts(overrides = {}) {
6
- return {
7
- path: 'pkg/server.go',
8
- language: 'go',
9
- lineCount: 200,
10
- classes: [],
11
- functions: [{
12
- name: 'Server.Start',
13
- lineStart: 10,
14
- lineEnd: 50,
15
- lineCount: 40,
16
- paramCount: 1,
17
- params: ['ctx context.Context'],
18
- maxNesting: 3,
19
- hasReturn: true,
20
- isAsync: false,
21
- isExported: true,
22
- }],
23
- imports: ['net/http', 'context', 'sync'],
24
- exports: [],
25
- errorHandling: [],
26
- testAssertions: 0,
27
- hasTests: false,
28
- structs: [{
29
- name: 'Server',
30
- lineStart: 5,
31
- lineEnd: 15,
32
- fieldCount: 5,
33
- methodCount: 4,
34
- methods: ['Start', 'Stop', 'Handle', 'Route'],
35
- lineCount: 10,
36
- embeds: ['BaseServer'],
37
- }],
38
- interfaces: [{
39
- name: 'Handler',
40
- lineStart: 20,
41
- methodCount: 2,
42
- methods: ['ServeHTTP', 'Health'],
43
- }],
44
- goroutines: 3,
45
- channels: 1,
46
- mutexes: 1,
47
- defers: 2,
48
- ...overrides,
49
- };
50
- }
51
- function makeTsFacts(overrides = {}) {
52
- return {
53
- path: 'src/service.ts',
54
- language: 'typescript',
55
- lineCount: 150,
56
- classes: [{
57
- name: 'UserService',
58
- lineStart: 5,
59
- lineEnd: 140,
60
- methodCount: 6,
61
- methods: ['find', 'create', 'update', 'delete', 'validate', 'notify'],
62
- publicMethods: ['find', 'create', 'update', 'delete'],
63
- lineCount: 135,
64
- dependencies: ['Database', 'Logger'],
65
- }],
66
- functions: [],
67
- imports: ['express', 'lodash', './types'],
68
- exports: ['UserService'],
69
- errorHandling: [
70
- { type: 'try-catch', lineStart: 10, isEmpty: false, strategy: 'throw' },
71
- ],
72
- testAssertions: 0,
73
- hasTests: false,
74
- ...overrides,
75
- };
76
- }
77
- describe('Deep Analysis Prompts', () => {
78
- // ── DEEP_SYSTEM_PROMPT ──
79
- describe('DEEP_SYSTEM_PROMPT', () => {
80
- it('should contain all category groups', () => {
81
- expect(DEEP_SYSTEM_PROMPT).toContain('SOLID Principles');
82
- expect(DEEP_SYSTEM_PROMPT).toContain('Design Patterns');
83
- expect(DEEP_SYSTEM_PROMPT).toContain('DRY');
84
- expect(DEEP_SYSTEM_PROMPT).toContain('Error Handling');
85
- expect(DEEP_SYSTEM_PROMPT).toContain('Concurrency');
86
- expect(DEEP_SYSTEM_PROMPT).toContain('Testing');
87
- });
88
- it('should contain key category IDs', () => {
89
- expect(DEEP_SYSTEM_PROMPT).toContain('god_class');
90
- expect(DEEP_SYSTEM_PROMPT).toContain('god_function');
91
- expect(DEEP_SYSTEM_PROMPT).toContain('srp_violation');
92
- expect(DEEP_SYSTEM_PROMPT).toContain('race_condition');
93
- expect(DEEP_SYSTEM_PROMPT).toContain('empty_catch');
94
- expect(DEEP_SYSTEM_PROMPT).toContain('missing_test');
95
- });
96
- it('should include output schema', () => {
97
- expect(DEEP_SYSTEM_PROMPT).toContain('"findings"');
98
- expect(DEEP_SYSTEM_PROMPT).toContain('"category"');
99
- expect(DEEP_SYSTEM_PROMPT).toContain('"severity"');
100
- expect(DEEP_SYSTEM_PROMPT).toContain('"confidence"');
101
- });
102
- it('should contain Go-specific guidance', () => {
103
- expect(DEEP_SYSTEM_PROMPT).toContain('Go code');
104
- expect(DEEP_SYSTEM_PROMPT).toContain('struct');
105
- expect(DEEP_SYSTEM_PROMPT).toContain('receiver method');
106
- });
107
- });
108
- // ── buildAnalysisPrompt ──
109
- describe('buildAnalysisPrompt', () => {
110
- it('should build prompt with default checks', () => {
111
- const factsStr = 'FILE: src/service.ts (typescript, 150 lines)';
112
- const prompt = buildAnalysisPrompt(factsStr);
113
- // Default checks include descriptions for SOLID, DRY, design patterns
114
- expect(prompt).toContain('SOLID');
115
- expect(prompt).toContain('DRY');
116
- expect(prompt).toContain('god class');
117
- expect(prompt).toContain(factsStr);
118
- });
119
- it('should include language-specific guidance for Go', () => {
120
- const factsStr = 'FILE: pkg/server.go (go, 200 lines)\n STRUCT Server (10 lines, 5 fields)';
121
- const prompt = buildAnalysisPrompt(factsStr);
122
- // Should detect Go as dominant language and add Go guidance
123
- expect(prompt.toLowerCase()).toContain('go');
124
- });
125
- it('should include language-specific guidance for TypeScript', () => {
126
- const factsStr = 'FILE: src/service.ts (typescript, 150 lines)\n CLASS UserService';
127
- const prompt = buildAnalysisPrompt(factsStr);
128
- expect(prompt.toLowerCase()).toContain('typescript');
129
- });
130
- it('should respect custom check selection', () => {
131
- const factsStr = 'FILE: src/service.ts (typescript, 150 lines)';
132
- const checks = {
133
- solid: true,
134
- dry: false,
135
- design_patterns: false,
136
- concurrency: true,
137
- };
138
- const prompt = buildAnalysisPrompt(factsStr, checks);
139
- expect(prompt).toContain('SOLID');
140
- expect(prompt).toContain('Concurrency');
141
- });
142
- });
143
- // ── buildCrossFilePrompt ──
144
- describe('buildCrossFilePrompt', () => {
145
- it('should analyze patterns across multiple files', () => {
146
- const allFacts = [
147
- makeTsFacts({ path: 'src/user.service.ts' }),
148
- makeTsFacts({
149
- path: 'src/order.service.ts',
150
- classes: [{
151
- name: 'OrderService',
152
- lineStart: 1,
153
- lineEnd: 100,
154
- methodCount: 5,
155
- methods: ['find', 'create', 'update', 'delete', 'process'],
156
- publicMethods: ['find', 'create'],
157
- lineCount: 100,
158
- dependencies: ['Database', 'Logger'],
159
- }],
160
- }),
161
- makeTsFacts({
162
- path: 'src/product.service.ts',
163
- errorHandling: [
164
- { type: 'try-catch', lineStart: 5, isEmpty: false, strategy: 'log' },
165
- { type: 'try-catch', lineStart: 15, isEmpty: false, strategy: 'throw' },
166
- ],
167
- }),
168
- ];
169
- const prompt = buildCrossFilePrompt(allFacts);
170
- expect(prompt).toBeDefined();
171
- expect(prompt.length).toBeGreaterThan(0);
172
- // Should reference file count
173
- expect(prompt).toContain('3');
174
- });
175
- it('should include Go-specific cross-file info', () => {
176
- const allFacts = [
177
- makeGoFacts({ path: 'pkg/server.go' }),
178
- makeGoFacts({
179
- path: 'pkg/handler.go',
180
- structs: [{
181
- name: 'Handler',
182
- lineStart: 1,
183
- lineEnd: 50,
184
- fieldCount: 3,
185
- methodCount: 5,
186
- methods: ['Get', 'Post', 'Put', 'Delete', 'Options'],
187
- lineCount: 50,
188
- embeds: [],
189
- }],
190
- }),
191
- ];
192
- const prompt = buildCrossFilePrompt(allFacts);
193
- expect(prompt).toBeDefined();
194
- expect(prompt.length).toBeGreaterThan(0);
195
- });
196
- });
197
- // ── chunkFacts ──
198
- describe('chunkFacts', () => {
199
- it('never lets the serialized chunk overrun the prompt budget, so no file is dropped', () => {
200
- const facts = Array.from({ length: 40 }, (_, i) => makeTsFacts({
201
- path: `src/deeply/nested/module-${i}/implementation-file-with-a-long-name-${i}.ts`,
202
- lineCount: 300,
203
- imports: Array.from({ length: 8 }, (_, j) => `@scope/package-with-long-name-${j}/sub/path`),
204
- }));
205
- const chunks = chunkFacts(facts, 6000);
206
- expect(chunks.flat()).toHaveLength(facts.length);
207
- for (const chunk of chunks) {
208
- const text = factsToPromptString(chunk);
209
- for (const f of chunk)
210
- expect(text).toContain(`FILE: ${f.path}`);
211
- }
212
- });
213
- it('should split facts into token-limited chunks', () => {
214
- const manyFacts = Array.from({ length: 50 }, (_, i) => makeTsFacts({
215
- path: `src/file${i}.ts`,
216
- lineCount: 200,
217
- }));
218
- const chunks = chunkFacts(manyFacts, 4000);
219
- expect(chunks.length).toBeGreaterThan(1);
220
- // All facts should be distributed across chunks
221
- const totalFiles = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
222
- expect(totalFiles).toBe(50);
223
- });
224
- it('should handle single file within budget', () => {
225
- const facts = [makeTsFacts()];
226
- const chunks = chunkFacts(facts, 10000);
227
- expect(chunks).toHaveLength(1);
228
- expect(chunks[0]).toHaveLength(1);
229
- });
230
- it('should handle empty input', () => {
231
- const chunks = chunkFacts([], 4000);
232
- expect(chunks).toHaveLength(0);
233
- });
234
- });
235
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,46 +0,0 @@
1
- import { execFileSync } from 'child_process';
2
- import fs from 'fs';
3
- import os from 'os';
4
- import path from 'path';
5
- import { afterEach, describe, expect, it } from 'vitest';
6
- import { buildReferencePack } from './reference-pack.js';
7
- let repo;
8
- afterEach(() => { if (repo)
9
- fs.rmSync(repo, { recursive: true, force: true }); repo = undefined; });
10
- function project() {
11
- repo = fs.mkdtempSync(path.join(os.tmpdir(), 'reference-pack-'));
12
- const files = {
13
- 'src/paths.ts': "export function cleanPath(p: string): string {\n return p.replace(/\\/+/g, '/');\n}\n",
14
- 'src/routes.ts': "import { cleanPath } from './paths';\nexport function routePath(dir: string, route: string): string {\n return cleanPath(`/${dir}${route}`);\n}\n",
15
- 'src/generator.ts': "import { routePath } from './routes';\nexport const home = routePath('.', '/');\n",
16
- };
17
- for (const [name, text] of Object.entries(files)) {
18
- fs.mkdirSync(path.dirname(path.join(repo, name)), { recursive: true });
19
- fs.writeFileSync(path.join(repo, name), text);
20
- }
21
- execFileSync('git', ['init', '-q'], { cwd: repo });
22
- execFileSync('git', ['add', '-A'], { cwd: repo });
23
- return repo;
24
- }
25
- describe('buildReferencePack', () => {
26
- it('carries the intent, removed lines, callee definitions and callers of a changed export', () => {
27
- const cwd = project();
28
- const pack = buildReferencePack({
29
- cwd, file: 'src/routes.ts', focusLines: [3], maxChars: 10_000,
30
- prBody: 'Normalize virtual route paths.',
31
- removed: [{ line: 3, text: [" return `/${dir}${route}`;"] }],
32
- });
33
- expect(pack.text).toContain('PR DESCRIPTION (what the author intends):\nNormalize virtual route paths.');
34
- expect(pack.text).toContain('REMOVED by this change, just before line 3 of src/routes.ts:\n- return `/${dir}${route}`;');
35
- expect(pack.text).toContain('CALLED: src/paths.ts:1\nexport function cleanPath');
36
- expect(pack.text).toContain("CALLER of routePath:\nsrc/generator.ts:2:export const home = routePath('.', '/');");
37
- expect(pack.source).toContain('cleanPath');
38
- });
39
- it('stays within its budget, keeping the highest-priority sections', () => {
40
- const cwd = project();
41
- const pack = buildReferencePack({ cwd, file: 'src/routes.ts', focusLines: [3], maxChars: 80, prBody: 'Normalize virtual route paths.' });
42
- expect(pack.text).toContain('PR DESCRIPTION');
43
- expect(pack.text).not.toContain('CALLED');
44
- expect(pack.text.length).toBeLessThanOrEqual(80);
45
- });
46
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,33 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
- import { importsFrom, relatedChanges } from './related-changes.js';
6
- import { rankChangedFunctions } from './risk.js';
7
- let dir;
8
- const write = (file, body) => {
9
- fs.mkdirSync(path.dirname(path.join(dir, file)), { recursive: true });
10
- fs.writeFileSync(path.join(dir, file), body);
11
- };
12
- beforeEach(() => { dir = fs.mkdtempSync(path.join(os.tmpdir(), 'related-')); });
13
- afterEach(() => { fs.rmSync(dir, { recursive: true, force: true }); });
14
- describe('relatedChanges', () => {
15
- it('links a changed function to another changed file that imports and calls it, never tests or same-named functions', () => {
16
- write('src/billing/price.ts', 'export function priceOf(row) {\n return row.currency;\n}\n');
17
- write('src/billing/invoice.ts', "import { priceOf } from './price';\n\nexport function invoice(row) {\n return { cur: 'USD', price: priceOf(row) };\n}\n");
18
- write('src/billing/price.test.ts', "import { priceOf } from './price';\npriceOf({});\n");
19
- write('src/other/price.ts', 'export function priceOf(x) {\n return 1;\n}\n');
20
- write('src/other/use.ts', "import { priceOf } from './price';\nexport const y = () => priceOf(2);\n");
21
- const focus = { 'src/billing/price.ts': [2], 'src/billing/invoice.ts': [4], 'src/billing/price.test.ts': [2], 'src/other/use.ts': [2] };
22
- const links = relatedChanges(dir, Object.keys(focus), rankChangedFunctions(dir, focus));
23
- expect(links).toEqual([{ callee: 'priceOf', calleeFile: 'src/billing/price.ts', calleeLine: 1, callerFile: 'src/billing/invoice.ts', callerLine: 4 }]);
24
- });
25
- });
26
- describe('importsFrom', () => {
27
- it('resolves relative and aliased module paths', () => {
28
- expect(importsFrom("import { a, b } from '../lib/x';", 'b', 'src/app/y.ts', 'src/lib/x.ts')).toBe(true);
29
- expect(importsFrom('import { b } from "@/lib/x";', 'b', 'src/app/y.ts', 'src/lib/x.ts')).toBe(true);
30
- expect(importsFrom("import { bb } from '../lib/x';", 'b', 'src/app/y.ts', 'src/lib/x.ts')).toBe(false);
31
- expect(importsFrom("import { b } from './x';", 'b', 'src/app/y.ts', 'src/lib/x.ts')).toBe(false);
32
- });
33
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,32 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, describe, expect, it } from 'vitest';
5
- import { buildCodeReviewPrompt } from './code-review-prompt.js';
6
- import { exportReviewContexts } from './review-context-export.js';
7
- let dir;
8
- afterEach(() => { if (dir)
9
- fs.rmSync(dir, { recursive: true, force: true }); dir = undefined; });
10
- const DIFF = `diff --git a/src/total.ts b/src/total.ts
11
- --- a/src/total.ts
12
- +++ b/src/total.ts
13
- @@ -2,2 +2,2 @@
14
- let sum = 0;
15
- - for (let i = 0; i < items.length; i++) sum += items[i];
16
- + for (let i = 0; i <= items.length; i++) sum += items[i];
17
- `;
18
- describe('exportReviewContexts', () => {
19
- it('emits the review prompt for each changed file, with its focus lines and what the change removed', async () => {
20
- dir = fs.mkdtempSync(path.join(os.tmpdir(), 'review-context-'));
21
- fs.mkdirSync(path.join(dir, 'src'));
22
- fs.writeFileSync(path.join(dir, 'src/total.ts'), 'export function total(items: number[]) {\n let sum = 0;\n for (let i = 0; i <= items.length; i++) sum += items[i];\n return sum;\n}\n');
23
- const [context, ...rest] = await exportReviewContexts(dir, DIFF, { prBody: 'Sum the basket.' });
24
- expect(rest).toEqual([]);
25
- expect(context.file).toBe('src/total.ts');
26
- expect(context.focusLines).toEqual([3]);
27
- expect(context.prompt.startsWith(buildCodeReviewPrompt({ file: '', language: '', text: '', ranges: [], source: '' }).slice(0, 60))).toBe(true);
28
- expect(context.prompt).toContain('3| for (let i = 0; i <= items.length; i++) sum += items[i];');
29
- expect(context.prompt).toContain('- for (let i = 0; i < items.length; i++) sum += items[i];');
30
- expect(context.prompt).toContain('Sum the basket.');
31
- });
32
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,39 +0,0 @@
1
- import { execFileSync } from 'child_process';
2
- import fs from 'fs';
3
- import os from 'os';
4
- import path from 'path';
5
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
6
- import { ReviewToolbox } from './review-tools.js';
7
- let repo;
8
- const call = (name, args) => ({ id: 'c1', name, arguments: args });
9
- beforeEach(() => {
10
- repo = fs.mkdtempSync(path.join(os.tmpdir(), 'review-tools-'));
11
- fs.mkdirSync(path.join(repo, 'src'));
12
- fs.writeFileSync(path.join(repo, 'src/a.ts'), Array.from({ length: 300 }, (_, i) => `const v${i + 1} = ${i + 1};`).join('\n'));
13
- fs.writeFileSync(path.join(repo, '.env'), 'API_KEY=secret');
14
- execFileSync('git', ['init', '-q'], { cwd: repo });
15
- execFileSync('git', ['add', '-A'], { cwd: repo });
16
- });
17
- afterEach(() => { fs.rmSync(repo, { recursive: true, force: true }); });
18
- describe('ReviewToolbox', () => {
19
- it('reads numbered lines, caps a call at 200 lines, and records what was read', () => {
20
- const tools = new ReviewToolbox(repo);
21
- const out = tools.run(call('read_file', { path: 'src/a.ts', start_line: 10, end_line: 900 }));
22
- expect(out).toContain('src/a.ts lines 10-209 of 300');
23
- expect(out).toContain(' 10| const v10 = 10;');
24
- expect(tools.reads.get('src/a.ts')).toEqual([[10, 209]]);
25
- expect(tools.readText).toContain('const v209');
26
- });
27
- it('refuses paths outside the repository and secrets files, without throwing', () => {
28
- const tools = new ReviewToolbox(repo);
29
- expect(tools.run(call('read_file', { path: '../../etc/passwd' }))).toMatch(/^Error:/);
30
- expect(tools.run(call('read_file', { path: '.env' }))).toBe('Error: this file is not readable by the reviewer');
31
- expect(tools.reads.size).toBe(0);
32
- });
33
- it('greps tracked files but never shows a secrets file', () => {
34
- const tools = new ReviewToolbox(repo);
35
- expect(tools.run(call('grep', { pattern: 'v12 =' }))).toBe('src/a.ts:12:const v12 = 12;');
36
- expect(tools.run(call('grep', { pattern: 'API_KEY' }))).toBe('No matches.');
37
- expect(tools.run(call('shell', {}))).toBe('Unknown tool "shell".');
38
- });
39
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,101 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
- import { functionHash, rankChangedFunctions, scoreRisk } from './risk.js';
6
- import { DEFAULT_MIN_SCORE, routeFiles } from './router.js';
7
- let dir;
8
- beforeEach(() => { dir = fs.mkdtempSync(path.join(os.tmpdir(), 'risk-')); });
9
- afterEach(() => { fs.rmSync(dir, { recursive: true, force: true }); });
10
- const SYNC = [
11
- 'export async function syncOrders(db, cursor) {', // 1
12
- ' for (const page of pages(cursor)) {', // 2
13
- ' if (page.rows.length) {', // 3
14
- " await db.from('orders').upsert(page.rows);", // 4
15
- ' }', // 5
16
- ' }', // 6
17
- '}', // 7
18
- 'function label(name) {', // 8
19
- ' return name.trim();', // 9
20
- '}', // 10
21
- ].join('\n');
22
- const plain = { exported: false, async: false, nesting: 0, lines: 3, removedGuard: false, sensitive: [] };
23
- describe('rankChangedFunctions', () => {
24
- it('reads the signals of each changed function', () => {
25
- fs.writeFileSync(path.join(dir, 'sync.ts'), SYNC);
26
- const ranked = rankChangedFunctions(dir, { 'sync.ts': [4, 9] }, { 'sync.ts': [{ line: 4, text: [' if (!page.ok) return;'] }] });
27
- const byName = Object.fromEntries(ranked.map(f => [f.name, f]));
28
- expect(byName.syncOrders.signals).toEqual({
29
- exported: true, async: true, nesting: 2, lines: 7, removedGuard: true, sensitive: ['data-write', 'paging'],
30
- });
31
- expect(byName.label.signals).toMatchObject({ exported: false, async: false, nesting: 0, removedGuard: false, sensitive: [] });
32
- expect([byName.label.start, byName.label.end]).toEqual([8, 10]);
33
- });
34
- });
35
- describe('test files', () => {
36
- it('are never routed, however their fixtures read', () => {
37
- fs.mkdirSync(path.join(dir, '__tests__'));
38
- for (const file of ['sync.test.ts', 'sync.spec.js', '__tests__/sync.ts'])
39
- fs.writeFileSync(path.join(dir, file), SYNC);
40
- expect(rankChangedFunctions(dir, { 'sync.test.ts': [4], 'sync.spec.js': [4], '__tests__/sync.ts': [4] })).toEqual([]);
41
- });
42
- });
43
- describe('team lessons as a risk signal', () => {
44
- const lesson = (over) => ({
45
- id: 'l1', text: 'Trim before comparing names.', file: 'sync.ts', symbols: ['trimStart'], state: 'verified',
46
- evidence: [{ pr: 1, comment: 'c', author: 'r' }], createdAt: '', updatedAt: '', ...over,
47
- });
48
- const LABEL = 'function label(name) {\n return name.trimStart();\n}\n';
49
- it('makes a plain function risky when a lesson for its file names a symbol it uses', () => {
50
- fs.writeFileSync(path.join(dir, 'sync.ts'), LABEL);
51
- const [f] = rankChangedFunctions(dir, { 'sync.ts': [2] }, {}, [lesson({})]);
52
- expect(f.signals.lesson).toBe('Trim before comparing names.');
53
- expect(f.score).toBeGreaterThanOrEqual(DEFAULT_MIN_SCORE);
54
- });
55
- it('ignores lessons for other files and lessons naming only common words', () => {
56
- fs.writeFileSync(path.join(dir, 'sync.ts'), LABEL);
57
- const other = rankChangedFunctions(dir, { 'sync.ts': [2] }, {}, [lesson({ file: 'other.ts' }), lesson({ symbols: ['name'] })]);
58
- expect(other[0].signals.lesson).toBeUndefined();
59
- expect(other[0].score).toBe(0);
60
- });
61
- });
62
- describe('scoreRisk', () => {
63
- it('ranks a data write behind a removed guard above a plain helper', () => {
64
- const risky = { exported: true, async: true, nesting: 2, lines: 30, removedGuard: true, sensitive: ['data-write', 'paging'] };
65
- expect(scoreRisk(risky)).toBeGreaterThan(scoreRisk(plain));
66
- });
67
- it('gives a short, flat, private, non-sensitive function no model review', () => {
68
- expect(scoreRisk(plain)).toBe(0);
69
- });
70
- it('never scores below zero', () => {
71
- expect(scoreRisk({ ...plain, lines: 1 })).toBeGreaterThanOrEqual(0);
72
- });
73
- });
74
- describe('routeFiles', () => {
75
- it('always keeps files it cannot rank, and reports what it left to the gates', () => {
76
- fs.writeFileSync(path.join(dir, 'helper.ts'), 'function label(name) {\n return name.trim();\n}\n');
77
- fs.writeFileSync(path.join(dir, 'query.py'), 'def f():\n return 1\n');
78
- const routed = routeFiles(dir, ['helper.ts', 'query.py'], { 'helper.ts': [2], 'query.py': [2] }, {}, { min_score: 1 });
79
- expect([...routed.files]).toEqual(['query.py']);
80
- expect(routed.stats).toEqual({ functions: 1, routed: 0, files_skipped: 1, already_reviewed: 0 });
81
- });
82
- it('skips a risky function reviewed before at exactly this code, and only that code', () => {
83
- fs.writeFileSync(path.join(dir, 'sync.ts'), SYNC);
84
- const [risky] = rankChangedFunctions(dir, { 'sync.ts': [4] });
85
- const cleared = routeFiles(dir, ['sync.ts'], { 'sync.ts': [4] }, {}, {}, [{ file: 'sync.ts', function: 'syncOrders', hash: risky.hash }]);
86
- expect(cleared.stats).toMatchObject({ routed: 0, already_reviewed: 1, files_skipped: 1 });
87
- const stale = routeFiles(dir, ['sync.ts'], { 'sync.ts': [4] }, {}, {}, [{ file: 'sync.ts', function: 'syncOrders', hash: 'old' }]);
88
- expect(stale.stats).toMatchObject({ routed: 1, already_reviewed: 0 });
89
- });
90
- });
91
- describe('functionHash', () => {
92
- it('changes when anything inside the function changes, strings included', () => {
93
- const a = 'function f() { return "a b"; }';
94
- const b = 'function f() { return "a b"; }';
95
- expect(functionHash(a)).not.toBe(functionHash(b));
96
- expect(functionHash('function f() { return `x ${y}`; }')).not.toBe(functionHash('function f() { return `x ${y}`; }'));
97
- });
98
- it('treats a Windows checkout of the same code as the same code', () => {
99
- expect(functionHash('function f() {\r\n return 1;\r\n}')).toBe(functionHash('function f() {\n return 1;\n}'));
100
- });
101
- });
@@ -1 +0,0 @@
1
- export {};