@rigour-labs/core 6.7.10 → 6.8.1-rc.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 (346) hide show
  1. package/dist/brief/briefing.d.ts +59 -0
  2. package/dist/brief/briefing.js +126 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +2 -0
  5. package/dist/inference/cloud-provider.js +12 -2
  6. package/dist/review/backtest-init.d.ts +8 -5
  7. package/dist/review/backtest-init.js +27 -9
  8. package/dist/review/backtest-last.js +3 -1
  9. package/dist/review/reviewer/adapters.d.ts +4 -0
  10. package/dist/review/reviewer/adapters.js +23 -0
  11. package/dist/review/reviewer/inputs.d.ts +4 -1
  12. package/dist/review/reviewer/inputs.js +36 -2
  13. package/dist/review/reviewer/record.d.ts +5 -0
  14. package/dist/review/reviewer/record.js +3 -3
  15. package/dist/review/reviewer/verdict.d.ts +14 -0
  16. package/dist/review/reviewer/verdict.js +46 -6
  17. package/dist/review/reviewer.d.ts +2 -0
  18. package/dist/review/reviewer.js +24 -5
  19. package/dist/review-learning/repo-rules.d.ts +14 -2
  20. package/dist/review-learning/repo-rules.js +59 -9
  21. package/dist/task/thread.d.ts +47 -0
  22. package/dist/task/thread.js +234 -0
  23. package/dist/templates/universal-config.js +4 -0
  24. package/dist/types/index.d.ts +21 -0
  25. package/dist/types/index.js +7 -0
  26. package/package.json +11 -8
  27. package/dist/context/automatic-index-cache.test.d.ts +0 -1
  28. package/dist/context/automatic-index-cache.test.js +0 -30
  29. package/dist/context/automatic-index.test.d.ts +0 -1
  30. package/dist/context/automatic-index.test.js +0 -45
  31. package/dist/context/cache-engine.test.d.ts +0 -1
  32. package/dist/context/cache-engine.test.js +0 -99
  33. package/dist/context/dependency-graph.test.d.ts +0 -1
  34. package/dist/context/dependency-graph.test.js +0 -13
  35. package/dist/context/index-status.test.d.ts +0 -1
  36. package/dist/context/index-status.test.js +0 -26
  37. package/dist/context.test.d.ts +0 -1
  38. package/dist/context.test.js +0 -228
  39. package/dist/deep/agent-review.test.d.ts +0 -1
  40. package/dist/deep/agent-review.test.js +0 -53
  41. package/dist/deep/code-context.test.d.ts +0 -1
  42. package/dist/deep/code-context.test.js +0 -48
  43. package/dist/deep/code-pass.test.d.ts +0 -1
  44. package/dist/deep/code-pass.test.js +0 -112
  45. package/dist/deep/code-review-prompt.test.d.ts +0 -1
  46. package/dist/deep/code-review-prompt.test.js +0 -20
  47. package/dist/deep/code-verifier.test.d.ts +0 -1
  48. package/dist/deep/code-verifier.test.js +0 -54
  49. package/dist/deep/diff-tests/calls.test.d.ts +0 -1
  50. package/dist/deep/diff-tests/calls.test.js +0 -33
  51. package/dist/deep/diff-tests/run.test.d.ts +0 -1
  52. package/dist/deep/diff-tests/run.test.js +0 -58
  53. package/dist/deep/fact-extractor.test.d.ts +0 -1
  54. package/dist/deep/fact-extractor.test.js +0 -581
  55. package/dist/deep/parse-findings.test.d.ts +0 -1
  56. package/dist/deep/parse-findings.test.js +0 -25
  57. package/dist/deep/pr-review.test.d.ts +0 -1
  58. package/dist/deep/pr-review.test.js +0 -80
  59. package/dist/deep/prompts.test.d.ts +0 -1
  60. package/dist/deep/prompts.test.js +0 -235
  61. package/dist/deep/reference-pack.test.d.ts +0 -1
  62. package/dist/deep/reference-pack.test.js +0 -46
  63. package/dist/deep/related-changes.test.d.ts +0 -1
  64. package/dist/deep/related-changes.test.js +0 -33
  65. package/dist/deep/review-context-export.test.d.ts +0 -1
  66. package/dist/deep/review-context-export.test.js +0 -32
  67. package/dist/deep/review-tools.test.d.ts +0 -1
  68. package/dist/deep/review-tools.test.js +0 -39
  69. package/dist/deep/risk.test.d.ts +0 -1
  70. package/dist/deep/risk.test.js +0 -101
  71. package/dist/deep/verifier.test.d.ts +0 -1
  72. package/dist/deep/verifier.test.js +0 -635
  73. package/dist/discovery.test.d.ts +0 -1
  74. package/dist/discovery.test.js +0 -93
  75. package/dist/environment.test.d.ts +0 -1
  76. package/dist/environment.test.js +0 -94
  77. package/dist/firewall/firewall.test.d.ts +0 -1
  78. package/dist/firewall/firewall.test.js +0 -117
  79. package/dist/firewall/trust-boundaries.test.d.ts +0 -1
  80. package/dist/firewall/trust-boundaries.test.js +0 -64
  81. package/dist/firewall/trusted-control.test.d.ts +0 -1
  82. package/dist/firewall/trusted-control.test.js +0 -188
  83. package/dist/gates/agent-team.test.d.ts +0 -1
  84. package/dist/gates/agent-team.test.js +0 -113
  85. package/dist/gates/ast.test.d.ts +0 -1
  86. package/dist/gates/ast.test.js +0 -112
  87. package/dist/gates/checkpoint.test.d.ts +0 -1
  88. package/dist/gates/checkpoint.test.js +0 -105
  89. package/dist/gates/content.test.d.ts +0 -1
  90. package/dist/gates/content.test.js +0 -73
  91. package/dist/gates/coverage.test.d.ts +0 -1
  92. package/dist/gates/coverage.test.js +0 -53
  93. package/dist/gates/dedupe-failures.test.d.ts +0 -1
  94. package/dist/gates/dedupe-failures.test.js +0 -12
  95. package/dist/gates/deep-analysis.test.d.ts +0 -1
  96. package/dist/gates/deep-analysis.test.js +0 -86
  97. package/dist/gates/deep-intent.test.d.ts +0 -1
  98. package/dist/gates/deep-intent.test.js +0 -51
  99. package/dist/gates/deep-timeout.test.d.ts +0 -1
  100. package/dist/gates/deep-timeout.test.js +0 -10
  101. package/dist/gates/deprecated-apis.test.d.ts +0 -1
  102. package/dist/gates/deprecated-apis.test.js +0 -318
  103. package/dist/gates/deprecated-dependencies.test.d.ts +0 -1
  104. package/dist/gates/deprecated-dependencies.test.js +0 -55
  105. package/dist/gates/frontend-secret-exposure.test.d.ts +0 -1
  106. package/dist/gates/frontend-secret-exposure.test.js +0 -148
  107. package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.d.ts +0 -1
  108. package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.js +0 -27
  109. package/dist/gates/hallucinated-imports/js-resolver-types.test.d.ts +0 -1
  110. package/dist/gates/hallucinated-imports/js-resolver-types.test.js +0 -14
  111. package/dist/gates/hallucinated-imports-sveltekit.test.d.ts +0 -1
  112. package/dist/gates/hallucinated-imports-sveltekit.test.js +0 -132
  113. package/dist/gates/hallucinated-imports.test.d.ts +0 -1
  114. package/dist/gates/hallucinated-imports.test.js +0 -1206
  115. package/dist/gates/js-style-context.test.d.ts +0 -1
  116. package/dist/gates/js-style-context.test.js +0 -35
  117. package/dist/gates/logic-drift.test.d.ts +0 -1
  118. package/dist/gates/logic-drift.test.js +0 -52
  119. package/dist/gates/phantom-apis.test.d.ts +0 -1
  120. package/dist/gates/phantom-apis.test.js +0 -396
  121. package/dist/gates/promise-safety.test.d.ts +0 -1
  122. package/dist/gates/promise-safety.test.js +0 -34
  123. package/dist/gates/runner.test.d.ts +0 -1
  124. package/dist/gates/runner.test.js +0 -77
  125. package/dist/gates/scoped-gates.test.d.ts +0 -1
  126. package/dist/gates/scoped-gates.test.js +0 -52
  127. package/dist/gates/security-patterns-owasp.test.d.ts +0 -1
  128. package/dist/gates/security-patterns-owasp.test.js +0 -186
  129. package/dist/gates/security-patterns.test.d.ts +0 -1
  130. package/dist/gates/security-patterns.test.js +0 -194
  131. package/dist/gates/semantic-bugs.test.d.ts +0 -1
  132. package/dist/gates/semantic-bugs.test.js +0 -76
  133. package/dist/gates/side-effect-analysis.test.d.ts +0 -1
  134. package/dist/gates/side-effect-analysis.test.js +0 -162
  135. package/dist/gates/style-drift.test.d.ts +0 -1
  136. package/dist/gates/style-drift.test.js +0 -26
  137. package/dist/gates/test-quality.test.d.ts +0 -1
  138. package/dist/gates/test-quality.test.js +0 -325
  139. package/dist/gates/trusted-reviews.test.d.ts +0 -1
  140. package/dist/gates/trusted-reviews.test.js +0 -16
  141. package/dist/gates/unindexed-reads/queries.test.d.ts +0 -1
  142. package/dist/gates/unindexed-reads/queries.test.js +0 -54
  143. package/dist/gates/unindexed-reads/schema.test.d.ts +0 -1
  144. package/dist/gates/unindexed-reads/schema.test.js +0 -81
  145. package/dist/gates/unindexed-reads/unindexed-reads.test.d.ts +0 -1
  146. package/dist/gates/unindexed-reads/unindexed-reads.test.js +0 -90
  147. package/dist/hooks/checker.test.d.ts +0 -1
  148. package/dist/hooks/checker.test.js +0 -159
  149. package/dist/hooks/dlp-confidence.test.d.ts +0 -1
  150. package/dist/hooks/dlp-confidence.test.js +0 -51
  151. package/dist/hooks/dlp-feedback.test.d.ts +0 -1
  152. package/dist/hooks/dlp-feedback.test.js +0 -131
  153. package/dist/hooks/input-validator.test.d.ts +0 -1
  154. package/dist/hooks/input-validator.test.js +0 -329
  155. package/dist/hooks/templates.test.d.ts +0 -1
  156. package/dist/hooks/templates.test.js +0 -27
  157. package/dist/inference/brain-placeholder.test.d.ts +0 -1
  158. package/dist/inference/brain-placeholder.test.js +0 -28
  159. package/dist/inference/cloud-provider.test.d.ts +0 -1
  160. package/dist/inference/cloud-provider.test.js +0 -139
  161. package/dist/inference/executable.test.d.ts +0 -1
  162. package/dist/inference/executable.test.js +0 -41
  163. package/dist/inference/http-download.test.d.ts +0 -1
  164. package/dist/inference/http-download.test.js +0 -109
  165. package/dist/inference/llama-engine-checksum.test.d.ts +0 -1
  166. package/dist/inference/llama-engine-checksum.test.js +0 -27
  167. package/dist/inference/llama-engine.test.d.ts +0 -1
  168. package/dist/inference/llama-engine.test.js +0 -51
  169. package/dist/inference/llama-process.test.d.ts +0 -1
  170. package/dist/inference/llama-process.test.js +0 -61
  171. package/dist/inference/local-model.test.d.ts +0 -1
  172. package/dist/inference/local-model.test.js +0 -23
  173. package/dist/inference/model-download.test.d.ts +0 -1
  174. package/dist/inference/model-download.test.js +0 -125
  175. package/dist/inference/model-manager.test.d.ts +0 -1
  176. package/dist/inference/model-manager.test.js +0 -24
  177. package/dist/inference/types.test.d.ts +0 -1
  178. package/dist/inference/types.test.js +0 -19
  179. package/dist/memory/recall.test.d.ts +0 -1
  180. package/dist/memory/recall.test.js +0 -36
  181. package/dist/pattern-index/indexer.test.d.ts +0 -6
  182. package/dist/pattern-index/indexer.test.js +0 -197
  183. package/dist/pattern-index/matcher.test.d.ts +0 -6
  184. package/dist/pattern-index/matcher.test.js +0 -238
  185. package/dist/pattern-index/pattern-reuse.test.d.ts +0 -1
  186. package/dist/pattern-index/pattern-reuse.test.js +0 -76
  187. package/dist/pattern-index/semantic-runtime.test.d.ts +0 -1
  188. package/dist/pattern-index/semantic-runtime.test.js +0 -31
  189. package/dist/pattern-index/staleness.test.d.ts +0 -6
  190. package/dist/pattern-index/staleness.test.js +0 -211
  191. package/dist/review/agent-fixes.test.d.ts +0 -1
  192. package/dist/review/agent-fixes.test.js +0 -32
  193. package/dist/review/backtest-init.test.d.ts +0 -1
  194. package/dist/review/backtest-init.test.js +0 -98
  195. package/dist/review/backtest-judges.test.d.ts +0 -1
  196. package/dist/review/backtest-judges.test.js +0 -32
  197. package/dist/review/backtest-last.test.d.ts +0 -1
  198. package/dist/review/backtest-last.test.js +0 -109
  199. package/dist/review/backtest.test.d.ts +0 -1
  200. package/dist/review/backtest.test.js +0 -183
  201. package/dist/review/baseline.test.d.ts +0 -1
  202. package/dist/review/baseline.test.js +0 -22
  203. package/dist/review/branch-checks.test.d.ts +0 -1
  204. package/dist/review/branch-checks.test.js +0 -48
  205. package/dist/review/check-outcomes.test.d.ts +0 -1
  206. package/dist/review/check-outcomes.test.js +0 -56
  207. package/dist/review/code-patterns.test.d.ts +0 -1
  208. package/dist/review/code-patterns.test.js +0 -142
  209. package/dist/review/dead-code.test.d.ts +0 -1
  210. package/dist/review/dead-code.test.js +0 -154
  211. package/dist/review/deep-runs.test.d.ts +0 -1
  212. package/dist/review/deep-runs.test.js +0 -23
  213. package/dist/review/effectiveness.test.d.ts +0 -1
  214. package/dist/review/effectiveness.test.js +0 -42
  215. package/dist/review/fix-scope.test.d.ts +0 -1
  216. package/dist/review/fix-scope.test.js +0 -104
  217. package/dist/review/generated-files.test.d.ts +0 -1
  218. package/dist/review/generated-files.test.js +0 -25
  219. package/dist/review/migration-order.test.d.ts +0 -1
  220. package/dist/review/migration-order.test.js +0 -62
  221. package/dist/review/quiet.test.d.ts +0 -1
  222. package/dist/review/quiet.test.js +0 -38
  223. package/dist/review/receipt.test.d.ts +0 -1
  224. package/dist/review/receipt.test.js +0 -60
  225. package/dist/review/review-task.test.d.ts +0 -1
  226. package/dist/review/review-task.test.js +0 -89
  227. package/dist/review/review.test.d.ts +0 -1
  228. package/dist/review/review.test.js +0 -203
  229. package/dist/review/reviewer/adapters.test.d.ts +0 -1
  230. package/dist/review/reviewer/adapters.test.js +0 -60
  231. package/dist/review/reviewer/api-judge.test.d.ts +0 -1
  232. package/dist/review/reviewer/api-judge.test.js +0 -108
  233. package/dist/review/reviewer/background.test.d.ts +0 -1
  234. package/dist/review/reviewer/background.test.js +0 -118
  235. package/dist/review/reviewer/context.test.d.ts +0 -1
  236. package/dist/review/reviewer/context.test.js +0 -45
  237. package/dist/review/reviewer/exec.test.d.ts +0 -1
  238. package/dist/review/reviewer/exec.test.js +0 -59
  239. package/dist/review/reviewer/inputs.test.d.ts +0 -1
  240. package/dist/review/reviewer/inputs.test.js +0 -26
  241. package/dist/review/reviewer/panel.test.d.ts +0 -1
  242. package/dist/review/reviewer/panel.test.js +0 -110
  243. package/dist/review/reviewer/record.test.d.ts +0 -1
  244. package/dist/review/reviewer/record.test.js +0 -32
  245. package/dist/review/reviewer/rule-writer.test.d.ts +0 -1
  246. package/dist/review/reviewer/rule-writer.test.js +0 -52
  247. package/dist/review/reviewer/settings.test.d.ts +0 -1
  248. package/dist/review/reviewer/settings.test.js +0 -57
  249. package/dist/review/reviewer/usage.test.d.ts +0 -1
  250. package/dist/review/reviewer/usage.test.js +0 -14
  251. package/dist/review/reviewer.test.d.ts +0 -1
  252. package/dist/review/reviewer.test.js +0 -705
  253. package/dist/review/stories.test.d.ts +0 -1
  254. package/dist/review/stories.test.js +0 -58
  255. package/dist/review/toolchain.test.d.ts +0 -1
  256. package/dist/review/toolchain.test.js +0 -108
  257. package/dist/review/typed/redundancy.test.d.ts +0 -1
  258. package/dist/review/typed/redundancy.test.js +0 -315
  259. package/dist/review/typed/schema-nullability.test.d.ts +0 -1
  260. package/dist/review/typed/schema-nullability.test.js +0 -63
  261. package/dist/review-learning/human-edits.test.d.ts +0 -1
  262. package/dist/review-learning/human-edits.test.js +0 -47
  263. package/dist/review-learning/repo-rules.test.d.ts +0 -1
  264. package/dist/review-learning/repo-rules.test.js +0 -55
  265. package/dist/review-learning/review-learning.test.d.ts +0 -1
  266. package/dist/review-learning/review-learning.test.js +0 -249
  267. package/dist/safety.test.d.ts +0 -1
  268. package/dist/safety.test.js +0 -42
  269. package/dist/semantic/benchmark.test.d.ts +0 -1
  270. package/dist/semantic/benchmark.test.js +0 -22
  271. package/dist/semantic/intent/intent.test.d.ts +0 -1
  272. package/dist/semantic/intent/intent.test.js +0 -46
  273. package/dist/semantic/learn/learn.test.d.ts +0 -1
  274. package/dist/semantic/learn/learn.test.js +0 -67
  275. package/dist/semantic/origins.test.d.ts +0 -1
  276. package/dist/semantic/origins.test.js +0 -77
  277. package/dist/semantic/project-facts.test.d.ts +0 -1
  278. package/dist/semantic/project-facts.test.js +0 -45
  279. package/dist/semantic/sites/call-sites.test.d.ts +0 -1
  280. package/dist/semantic/sites/call-sites.test.js +0 -46
  281. package/dist/services/adaptive-thresholds.test.d.ts +0 -1
  282. package/dist/services/adaptive-thresholds.test.js +0 -53
  283. package/dist/services/agent-history.test.d.ts +0 -1
  284. package/dist/services/agent-history.test.js +0 -69
  285. package/dist/services/context-scope-summary.test.d.ts +0 -1
  286. package/dist/services/context-scope-summary.test.js +0 -17
  287. package/dist/services/context-telemetry-service.test.d.ts +0 -1
  288. package/dist/services/context-telemetry-service.test.js +0 -182
  289. package/dist/services/cursor-usage-sync.test.d.ts +0 -1
  290. package/dist/services/cursor-usage-sync.test.js +0 -173
  291. package/dist/services/engineering-knowledge-graph.test.d.ts +0 -1
  292. package/dist/services/engineering-knowledge-graph.test.js +0 -76
  293. package/dist/services/model-pricing.test.d.ts +0 -1
  294. package/dist/services/model-pricing.test.js +0 -44
  295. package/dist/services/observed-savings.test.d.ts +0 -1
  296. package/dist/services/observed-savings.test.js +0 -37
  297. package/dist/services/score-history.test.d.ts +0 -1
  298. package/dist/services/score-history.test.js +0 -61
  299. package/dist/smoke.test.d.ts +0 -1
  300. package/dist/smoke.test.js +0 -17
  301. package/dist/storage/cache-cleanup.test.d.ts +0 -1
  302. package/dist/storage/cache-cleanup.test.js +0 -54
  303. package/dist/storage/context-telemetry.test.d.ts +0 -1
  304. package/dist/storage/context-telemetry.test.js +0 -80
  305. package/dist/storage/db.test.d.ts +0 -1
  306. package/dist/storage/db.test.js +0 -46
  307. package/dist/storage/fix-lessons.test.d.ts +0 -1
  308. package/dist/storage/fix-lessons.test.js +0 -61
  309. package/dist/storage/lessons.test.d.ts +0 -1
  310. package/dist/storage/lessons.test.js +0 -81
  311. package/dist/storage/local-encryption.test.d.ts +0 -1
  312. package/dist/storage/local-encryption.test.js +0 -34
  313. package/dist/storage/local-memory.test.d.ts +0 -1
  314. package/dist/storage/local-memory.test.js +0 -55
  315. package/dist/storage/share-memory.test.d.ts +0 -1
  316. package/dist/storage/share-memory.test.js +0 -34
  317. package/dist/storage/team-diagnostics.test.d.ts +0 -1
  318. package/dist/storage/team-diagnostics.test.js +0 -51
  319. package/dist/storage/team-scope.test.d.ts +0 -1
  320. package/dist/storage/team-scope.test.js +0 -22
  321. package/dist/storage/team-store.test.d.ts +0 -1
  322. package/dist/storage/team-store.test.js +0 -11
  323. package/dist/storage/team-sync-scope.test.d.ts +0 -1
  324. package/dist/storage/team-sync-scope.test.js +0 -100
  325. package/dist/storage/team-vector-store.test.d.ts +0 -1
  326. package/dist/storage/team-vector-store.test.js +0 -56
  327. package/dist/storage/telemetry-scope.test.d.ts +0 -1
  328. package/dist/storage/telemetry-scope.test.js +0 -38
  329. package/dist/telemetry/telemetry.test.d.ts +0 -1
  330. package/dist/telemetry/telemetry.test.js +0 -64
  331. package/dist/types/index.test.d.ts +0 -1
  332. package/dist/types/index.test.js +0 -33
  333. package/dist/utils/command-line.test.d.ts +0 -1
  334. package/dist/utils/command-line.test.js +0 -8
  335. package/dist/utils/diff-removed.test.d.ts +0 -1
  336. package/dist/utils/diff-removed.test.js +0 -29
  337. package/dist/utils/diff.test.d.ts +0 -1
  338. package/dist/utils/diff.test.js +0 -38
  339. package/dist/utils/glob-paths.test.d.ts +0 -1
  340. package/dist/utils/glob-paths.test.js +0 -40
  341. package/dist/utils/profile.test.d.ts +0 -1
  342. package/dist/utils/profile.test.js +0 -68
  343. package/dist/utils/scanner.test.d.ts +0 -1
  344. package/dist/utils/scanner.test.js +0 -48
  345. package/dist/utils/scope.test.d.ts +0 -1
  346. package/dist/utils/scope.test.js +0 -38
@@ -2399,6 +2399,19 @@ export declare const ConfigSchema: z.ZodObject<{
2399
2399
  }, {
2400
2400
  report_path?: string | undefined;
2401
2401
  }>>>;
2402
+ /** The briefing an agent gets before it writes (rigour brief, the prompt hook, rigour_brief). */
2403
+ brief: z.ZodDefault<z.ZodOptional<z.ZodObject<{
2404
+ /** The kill switch: false stops every briefing, including an installed hook. The hook itself is installed only with `rigour hooks init --brief`. */
2405
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2406
+ /** At most this many items, never more than 10. */
2407
+ max_items: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
2408
+ }, "strip", z.ZodTypeAny, {
2409
+ enabled: boolean;
2410
+ max_items: number;
2411
+ }, {
2412
+ enabled?: boolean | undefined;
2413
+ max_items?: number | undefined;
2414
+ }>>>;
2402
2415
  /** rigour review / rigour_review / the PR bot / the stop hook. */
2403
2416
  review: z.ZodDefault<z.ZodOptional<z.ZodObject<{
2404
2417
  /** Let heuristic gates decide the verdict too; by default only findings that prove a defect do (quiet.ts). */
@@ -2873,6 +2886,10 @@ export declare const ConfigSchema: z.ZodObject<{
2873
2886
  output: {
2874
2887
  report_path: string;
2875
2888
  };
2889
+ brief: {
2890
+ enabled: boolean;
2891
+ max_items: number;
2892
+ };
2876
2893
  review: {
2877
2894
  include_heuristics: boolean;
2878
2895
  show_preexisting: boolean;
@@ -3165,6 +3182,10 @@ export declare const ConfigSchema: z.ZodObject<{
3165
3182
  output?: {
3166
3183
  report_path?: string | undefined;
3167
3184
  } | undefined;
3185
+ brief?: {
3186
+ enabled?: boolean | undefined;
3187
+ max_items?: number | undefined;
3188
+ } | undefined;
3168
3189
  review?: {
3169
3190
  include_heuristics?: boolean | undefined;
3170
3191
  show_preexisting?: boolean | undefined;
@@ -365,6 +365,13 @@ export const ConfigSchema = z.object({
365
365
  output: z.object({
366
366
  report_path: z.string().default('rigour-report.json'),
367
367
  }).optional().default({}),
368
+ /** The briefing an agent gets before it writes (rigour brief, the prompt hook, rigour_brief). */
369
+ brief: z.object({
370
+ /** The kill switch: false stops every briefing, including an installed hook. The hook itself is installed only with `rigour hooks init --brief`. */
371
+ enabled: z.boolean().optional().default(true),
372
+ /** At most this many items, never more than 10. */
373
+ max_items: z.number().int().min(1).max(10).optional().default(10),
374
+ }).optional().default({}),
368
375
  /** rigour review / rigour_review / the PR bot / the stop hook. */
369
376
  review: z.object({
370
377
  /** Let heuristic gates decide the verdict too; by default only findings that prove a defect do (quiet.ts). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/core",
3
- "version": "6.7.10",
3
+ "version": "6.8.1-rc.1",
4
4
  "description": "Rigour's review engine: deterministic gates on changed lines, rules and lessons learned from your team's fixes, and per-check precision from what you fix versus dismiss, across TypeScript, JavaScript, Python, Go, Ruby and C#.",
5
5
  "engines": {
6
6
  "node": ">=22.13"
@@ -30,7 +30,10 @@
30
30
  "type": "module",
31
31
  "files": [
32
32
  "dist",
33
- "README.md"
33
+ "README.md",
34
+ "!dist/**/*.test.js",
35
+ "!dist/**/*.test.d.ts",
36
+ "!dist/**/*.test.js.map"
34
37
  ],
35
38
  "main": "dist/index.js",
36
39
  "types": "dist/index.d.ts",
@@ -69,14 +72,14 @@
69
72
  "zod": "^3.22.4"
70
73
  },
71
74
  "optionalDependencies": {
72
- "@anthropic-ai/sdk": "^0.30.1",
75
+ "@anthropic-ai/sdk": "^0.132.1",
73
76
  "pg": "^8.16.3",
74
77
  "openai": "^5.23.2",
75
- "@rigour-labs/brain-darwin-arm64": "6.7.10",
76
- "@rigour-labs/brain-darwin-x64": "6.7.10",
77
- "@rigour-labs/brain-linux-x64": "6.7.10",
78
- "@rigour-labs/brain-win-x64": "6.7.10",
79
- "@rigour-labs/brain-linux-arm64": "6.7.10"
78
+ "@rigour-labs/brain-darwin-arm64": "6.8.1-rc.1",
79
+ "@rigour-labs/brain-darwin-x64": "6.8.1-rc.1",
80
+ "@rigour-labs/brain-linux-arm64": "6.8.1-rc.1",
81
+ "@rigour-labs/brain-linux-x64": "6.8.1-rc.1",
82
+ "@rigour-labs/brain-win-x64": "6.8.1-rc.1"
80
83
  },
81
84
  "devDependencies": {
82
85
  "@types/fs-extra": "^11.0.4",
@@ -1 +0,0 @@
1
- export {};
@@ -1,30 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
- const writes = vi.hoisted(() => ({ count: 0 }));
6
- vi.mock('../storage/context-telemetry.js', async (importOriginal) => ({
7
- ...(await importOriginal()),
8
- setContextCacheRecord: async () => { writes.count++; },
9
- }));
10
- const { ensureAutomaticIndex, updateAutomaticIndexForFiles } = await import('./automatic-index.js');
11
- let cwd;
12
- beforeEach(() => {
13
- writes.count = 0;
14
- cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'auto-index-'));
15
- fs.mkdirSync(path.join(cwd, 'src'));
16
- fs.writeFileSync(path.join(cwd, 'src/a.ts'), 'export function alpha() { return 1; }\n');
17
- fs.writeFileSync(path.join(cwd, 'src/b.ts'), 'export function beta() { return 2; }\n');
18
- });
19
- afterEach(() => fs.rmSync(cwd, { recursive: true, force: true }));
20
- describe('automatic indexing', () => {
21
- it('writes nothing to the context cache, however many edits it sees', async () => {
22
- await ensureAutomaticIndex(cwd, { backgroundSemantic: false });
23
- for (let edit = 0; edit < 5; edit++) {
24
- fs.writeFileSync(path.join(cwd, 'src/a.ts'), `export function alpha() { return ${edit}; }\n`);
25
- await updateAutomaticIndexForFiles(cwd, ['src/a.ts']);
26
- }
27
- expect(writes.count).toBe(0);
28
- expect(fs.existsSync(path.join(cwd, '.rigour', 'patterns.json'))).toBe(true);
29
- });
30
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,45 +0,0 @@
1
- import fs from 'fs-extra';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, describe, expect, it } from 'vitest';
5
- import { ensureAutomaticIndex, mergeSemanticEmbeddings, updateAutomaticIndexForFiles } from './automatic-index.js';
6
- describe('automatic incremental index', () => {
7
- const cwd = path.join(os.tmpdir(), `rigour-auto-index-${process.pid}`);
8
- afterEach(() => fs.remove(cwd));
9
- it('builds once and refreshes only changed files and their dependents', async () => {
10
- await fs.outputFile(path.join(cwd, 'src/value.ts'), 'export const value = 1;');
11
- await fs.outputFile(path.join(cwd, 'src/consumer.ts'), "import { value } from './value';\nexport const doubled = value * 2;");
12
- const baseline = await ensureAutomaticIndex(cwd, { backgroundSemantic: false });
13
- const untouched = baseline.files.find(file => file.path === 'src/consumer.ts')?.indexedAt;
14
- await fs.writeFile(path.join(cwd, 'src/value.ts'), 'export const value = 2;');
15
- const result = await updateAutomaticIndexForFiles(cwd, ['src/value.ts']);
16
- expect(result.affectedFiles.sort()).toEqual(['src/consumer.ts', 'src/value.ts']);
17
- expect(result.index.files.find(file => file.path === 'src/consumer.ts')?.indexedAt).not.toBe(untouched);
18
- });
19
- it('ignores changed-file paths outside the repository', async () => {
20
- await fs.outputFile(path.join(cwd, 'src/value.ts'), 'export const value = 1;');
21
- const baseline = await ensureAutomaticIndex(cwd, { backgroundSemantic: false });
22
- const result = await updateAutomaticIndexForFiles(cwd, [path.join(cwd, '..', 'outside.ts')]);
23
- expect(result.affectedFiles).toEqual([]);
24
- expect(result.index.patterns).toEqual(baseline.patterns);
25
- });
26
- it('merges background embeddings onto the latest structural snapshot', () => {
27
- const pattern = (id, file, embedding) => ({
28
- id, file, embedding, type: 'function', name: id, line: 1, endLine: 1,
29
- signature: '', description: '', keywords: [], hash: id, exported: true,
30
- usageCount: 0, indexedAt: '2026-09-10T00:00:00.000Z',
31
- });
32
- const makeIndex = (patterns) => ({
33
- version: '1.0.0', lastUpdated: '2026-09-10T00:00:00.000Z', rootDir: cwd,
34
- patterns,
35
- files: patterns.map(entry => ({ path: entry.file, hash: entry.hash, patternCount: 1, indexedAt: entry.indexedAt })),
36
- stats: { totalPatterns: patterns.length, totalFiles: patterns.length, byType: { function: patterns.length }, indexDurationMs: 1 },
37
- });
38
- const latest = makeIndex([pattern('changed', 'src/changed.ts'), pattern('new', 'src/new.ts')]);
39
- const enriched = makeIndex([pattern('changed', 'src/old.ts', [0.1, 0.2]), pattern('deleted', 'src/deleted.ts', [0.3])]);
40
- const merged = mergeSemanticEmbeddings(latest, enriched);
41
- expect(merged.patterns.map(entry => entry.id)).toEqual(['changed', 'new']);
42
- expect(merged.patterns[0].file).toBe('src/changed.ts');
43
- expect(merged.patterns[0].embedding).toEqual([0.1, 0.2]);
44
- });
45
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,99 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import path from 'path';
3
- import os from 'os';
4
- import fs from 'fs-extra';
5
- vi.mock('./db.js', () => ({
6
- isSQLiteAvailable: () => false,
7
- openDatabase: async () => null,
8
- DB_PATH: '/tmp/rigour-test.db',
9
- RIGOUR_DIR: '/tmp/.rigour',
10
- }));
11
- import { getSemanticQueryCache, setSemanticQueryCache, findRelatedSemanticQueryCache, queryTokenOverlap, distinctiveTokenAgreement, filterExistingEditScope, getTaskCheckpointCache, setTaskCheckpointCache, hashContent, normalizeQuery } from './cache-engine.js';
12
- describe('Context cache engine', () => {
13
- const testCwd = path.join(os.tmpdir(), `rigour-cache-test-${Date.now()}`);
14
- beforeEach(async () => {
15
- await fs.ensureDir(testCwd);
16
- });
17
- it('should calculate consistent SHA-256 hashes', () => {
18
- const hash1 = hashContent('const x = 1;');
19
- const hash2 = hashContent('const x = 1;');
20
- const hash3 = hashContent('const x = 2;');
21
- expect(hash1).toBe(hash2);
22
- expect(hash1).not.toBe(hash3);
23
- expect(hash1.length).toBe(16);
24
- });
25
- it('should normalize intent queries correctly', () => {
26
- expect(normalizeQuery(' Add priority to task!! ')).toBe('add priority to task');
27
- expect(normalizeQuery('Task SHOULD Support Priority.')).toBe('task should support priority');
28
- });
29
- it('Layer 3: should store and retrieve semantic query scope', async () => {
30
- const entry = {
31
- query: 'task priority persistence',
32
- resolvedOwner: 'task-team',
33
- editScope: ['services/task.ts'],
34
- validationScope: ['npm test'],
35
- evidence: ['AST match'],
36
- commitSha: 'commit-99',
37
- confidence: 0.95
38
- };
39
- await setSemanticQueryCache('add priority to task', 'commit-99', entry, testCwd);
40
- const retrieved = await getSemanticQueryCache('add priority to task', 'commit-99', testCwd);
41
- expect(retrieved).not.toBeNull();
42
- expect(retrieved?.resolvedOwner).toBe('task-team');
43
- expect(retrieved?.editScope).toContain('services/task.ts');
44
- });
45
- it('Layer 4: should store and retrieve subagent task checkpoint packet', async () => {
46
- const packet = {
47
- taskId: 'CTP-142',
48
- agentId: 'CTP-142-task',
49
- phase: 'implementation',
50
- component: 'services/task',
51
- changedFiles: ['services/task.ts'],
52
- decisions: ['Added priority field'],
53
- validation: ['npm test passed'],
54
- remainingWork: ['Add integration test'],
55
- risks: ['Migration needed']
56
- };
57
- await setTaskCheckpointCache(packet, 126000, testCwd);
58
- const retrieved = await getTaskCheckpointCache('CTP-142', 'CTP-142-task', 'implementation', testCwd);
59
- expect(retrieved).not.toBeNull();
60
- expect(retrieved?.taskId).toBe('CTP-142');
61
- expect(retrieved?.decisions).toContain('Added priority field');
62
- });
63
- it('Layer 3: finds related semantic queries at same commit for partial reuse', async () => {
64
- expect(queryTokenOverlap('task priority persistence service', 'task priority persistence service layer')).toBeGreaterThan(0.7);
65
- expect(distinctiveTokenAgreement('task service', 'payment service')).toBeLessThan(0.67);
66
- await setSemanticQueryCache('task priority persistence service', 'commit-rel', {
67
- query: 'task priority persistence service',
68
- resolvedOwner: 'task-team',
69
- editScope: ['services/task.ts'],
70
- validationScope: ['npm test'],
71
- evidence: ['related'],
72
- commitSha: 'commit-rel',
73
- confidence: 0.9,
74
- }, testCwd);
75
- const related = await findRelatedSemanticQueryCache('task priority persistence service layer', 'commit-rel', testCwd);
76
- expect(related).not.toBeNull();
77
- expect(related?.entry.editScope).toContain('services/task.ts');
78
- // Same generic stem, different distinctive noun → reject
79
- await setSemanticQueryCache('payment service billing', 'commit-rel', {
80
- query: 'payment service billing',
81
- resolvedOwner: 'pay',
82
- editScope: ['services/pay.ts'],
83
- validationScope: [],
84
- evidence: [],
85
- commitSha: 'commit-rel',
86
- confidence: 0.9,
87
- }, testCwd);
88
- const crossDomain = await findRelatedSemanticQueryCache('task service billing', 'commit-rel', testCwd);
89
- expect(crossDomain).toBeNull();
90
- const otherCommit = await findRelatedSemanticQueryCache('task priority persistence service layer', 'commit-other', testCwd);
91
- expect(otherCommit).toBeNull();
92
- });
93
- it('filters missing edit-scope files for quality', async () => {
94
- await fs.writeFile(path.join(testCwd, 'alive.ts'), 'export const ok = 1;\n');
95
- const result = await filterExistingEditScope(['alive.ts', 'gone.ts'], testCwd);
96
- expect(result.valid).toEqual(['alive.ts']);
97
- expect(result.missing).toEqual(['gone.ts']);
98
- });
99
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,13 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { affectedDependents } from './dependency-graph.js';
3
- describe('affectedDependents', () => {
4
- it('includes direct and transitive consumers', () => {
5
- const affected = affectedDependents({
6
- version: 1,
7
- generatedAt: '2026-09-10T00:00:00Z',
8
- nodes: ['a.ts', 'b.ts', 'c.ts'],
9
- edges: [{ from: 'b.ts', to: 'a.ts' }, { from: 'c.ts', to: 'b.ts' }],
10
- }, ['a.ts']);
11
- expect(new Set(affected)).toEqual(new Set(['a.ts', 'b.ts', 'c.ts']));
12
- });
13
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +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 { getAutomaticIndexStatus, recordIndexChoice } from './automatic-index.js';
6
- let cwd;
7
- beforeEach(() => { cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'index-status-')); });
8
- afterEach(() => fs.rmSync(cwd, { recursive: true, force: true }));
9
- const index = (embedded) => ({
10
- version: '1.0.0', lastUpdated: '', rootDir: cwd, files: [],
11
- patterns: [{ id: 'a', type: 'function', name: 'a', file: 'a.ts', line: 1, endLine: 1, signature: '', description: '', keywords: [], hash: 'a', exported: true, usageCount: 0, indexedAt: '', ...(embedded ? { embedding: [0.1] } : {}) }],
12
- stats: { totalPatterns: 1, totalFiles: 1, byType: {}, indexDurationMs: 0 },
13
- });
14
- describe('semantic index status', () => {
15
- it('treats no status yet as warming, not as an opt-out', async () => {
16
- expect((await getAutomaticIndexStatus(cwd)).semantic).toBe('warming');
17
- });
18
- it('records what an explicit index chose, so automatic indexing and Studio agree', async () => {
19
- await recordIndexChoice(cwd, index(false), false);
20
- expect((await getAutomaticIndexStatus(cwd)).semantic).toBe('disabled');
21
- await recordIndexChoice(cwd, index(true), true);
22
- expect((await getAutomaticIndexStatus(cwd)).semantic).toBe('ready');
23
- await recordIndexChoice(cwd, index(false), true);
24
- expect((await getAutomaticIndexStatus(cwd)).semantic).toBe('degraded');
25
- });
26
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,228 +0,0 @@
1
- import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
- import { GateRunner } from '../src/gates/runner.js';
3
- import fs from 'fs-extra';
4
- import path from 'path';
5
- import os from 'os';
6
- const TEST_CWD = path.join(os.tmpdir(), 'rigour-temp-test-context-' + process.pid);
7
- describe('Context Awareness Engine', () => {
8
- beforeAll(async () => {
9
- await fs.ensureDir(TEST_CWD);
10
- });
11
- afterAll(async () => {
12
- await fs.remove(TEST_CWD);
13
- });
14
- it('should detect context drift for redundant env suffixes (Golden Example)', async () => {
15
- // Setup: Define standard GCP_PROJECT_ID
16
- await fs.writeFile(path.join(TEST_CWD, '.env.example'), 'GCP_PROJECT_ID=my-project\n');
17
- // Setup: Use drifted GCP_PROJECT_ID_PRODUCTION
18
- await fs.writeFile(path.join(TEST_CWD, 'feature.js'), `
19
- const id = process.env.GCP_PROJECT_ID_PRODUCTION;
20
- console.log(id);
21
- `);
22
- const config = {
23
- version: 1,
24
- commands: {},
25
- gates: {
26
- context: {
27
- enabled: true,
28
- sensitivity: 0.8,
29
- mining_depth: 10,
30
- ignored_patterns: [],
31
- cross_file_patterns: true,
32
- naming_consistency: true,
33
- import_relationships: true,
34
- max_cross_file_depth: 50,
35
- },
36
- },
37
- output: { report_path: 'rigour-report.json' }
38
- };
39
- const runner = new GateRunner(config);
40
- const report = await runner.run(TEST_CWD);
41
- const driftFailures = report.failures.filter(f => f.id === 'context-drift');
42
- expect(driftFailures.length).toBeGreaterThan(0);
43
- expect(driftFailures[0].details).toContain('GCP_PROJECT_ID_PRODUCTION');
44
- expect(driftFailures[0].hint).toContain('GCP_PROJECT_ID');
45
- });
46
- it('should not flag valid environment variables', async () => {
47
- await fs.writeFile(path.join(TEST_CWD, 'valid.js'), `
48
- const id = process.env.GCP_PROJECT_ID;
49
- `);
50
- const config = {
51
- version: 1,
52
- commands: {},
53
- gates: {
54
- context: {
55
- enabled: true,
56
- sensitivity: 0.8,
57
- mining_depth: 100,
58
- ignored_patterns: [],
59
- cross_file_patterns: true,
60
- naming_consistency: true,
61
- import_relationships: true,
62
- max_cross_file_depth: 50,
63
- },
64
- },
65
- output: { report_path: 'rigour-report.json' }
66
- };
67
- const runner = new GateRunner(config);
68
- const report = await runner.run(TEST_CWD);
69
- const driftFailures = report.failures.filter(f => f.id === 'context-drift');
70
- // Filter out failures from other files if they still exist in TEST_CWD
71
- const specificFailures = driftFailures.filter(f => f.files?.includes('valid.js'));
72
- expect(specificFailures.length).toBe(0);
73
- });
74
- it('should classify arrow function exports as camelCase, not unknown', async () => {
75
- // Create files with arrow function patterns that previously returned 'unknown'
76
- await fs.writeFile(path.join(TEST_CWD, 'api.ts'), `
77
- export const fetchData = async () => { return []; };
78
- export const getUserProfile = async (id: string) => { return {}; };
79
- export const use = () => {};
80
- export const get = async () => {};
81
- const handleClick = (e: Event) => {};
82
- let processItem = async (item: any) => {};
83
- `);
84
- // Create a second file with consistent arrow function naming
85
- await fs.writeFile(path.join(TEST_CWD, 'service.ts'), `
86
- export const createUser = async (data: any) => {};
87
- export const deleteUser = async (id: string) => {};
88
- export const updateUser = async (id: string, data: any) => {};
89
- `);
90
- const config = {
91
- version: 1,
92
- commands: {},
93
- gates: {
94
- context: {
95
- enabled: true,
96
- sensitivity: 0.8,
97
- mining_depth: 10,
98
- ignored_patterns: [],
99
- cross_file_patterns: true,
100
- naming_consistency: true,
101
- import_relationships: true,
102
- max_cross_file_depth: 50,
103
- },
104
- },
105
- output: { report_path: 'rigour-report.json' }
106
- };
107
- const runner = new GateRunner(config);
108
- const report = await runner.run(TEST_CWD);
109
- // Should NOT have any "unknown" naming convention failures
110
- const namingFailures = report.failures.filter(f => f.id === 'context-drift' && f.details?.includes('unknown'));
111
- expect(namingFailures.length).toBe(0);
112
- });
113
- it('should not classify plain variable declarations as function patterns', async () => {
114
- // Create file with non-function const declarations
115
- await fs.writeFile(path.join(TEST_CWD, 'constants.ts'), `
116
- export const API_URL = 'https://api.example.com';
117
- export const MAX_RETRIES = 3;
118
- const config = { timeout: 5000 };
119
- let count = 0;
120
- `);
121
- // Create file with actual functions for a dominant pattern
122
- await fs.writeFile(path.join(TEST_CWD, 'utils.ts'), `
123
- function getData() { return []; }
124
- function setData(d: any) { return d; }
125
- function processRequest(req: any) { return req; }
126
- `);
127
- const config = {
128
- version: 1,
129
- commands: {},
130
- gates: {
131
- context: {
132
- enabled: true,
133
- sensitivity: 0.8,
134
- mining_depth: 10,
135
- ignored_patterns: [],
136
- cross_file_patterns: true,
137
- naming_consistency: true,
138
- import_relationships: true,
139
- max_cross_file_depth: 50,
140
- },
141
- },
142
- output: { report_path: 'rigour-report.json' }
143
- };
144
- const runner = new GateRunner(config);
145
- const report = await runner.run(TEST_CWD);
146
- // SCREAMING_SNAKE constants should NOT create naming drift failures
147
- // because they should not be in the 'function' pattern bucket at all
148
- const namingFailures = report.failures.filter(f => f.id === 'context-drift' && f.details?.includes('SCREAMING_SNAKE'));
149
- expect(namingFailures.length).toBe(0);
150
- });
151
- });
152
- /**
153
- * Direct unit tests for detectCasing logic
154
- */
155
- describe('detectCasing classification', () => {
156
- // We test the regex rules directly since detectCasing is private
157
- function detectCasing(name) {
158
- if (/^[A-Z][a-z]/.test(name) && /[a-z][A-Z]/.test(name))
159
- return 'PascalCase';
160
- if (/^[a-z]/.test(name) && /[a-z][A-Z]/.test(name))
161
- return 'camelCase';
162
- if (/^[a-z][a-zA-Z0-9]*$/.test(name))
163
- return 'camelCase'; // single-word lowercase
164
- if (/^[a-z]+(_[a-z]+)+$/.test(name))
165
- return 'snake_case';
166
- if (/^[A-Z]+(_[A-Z]+)*$/.test(name))
167
- return 'SCREAMING_SNAKE';
168
- if (/^[A-Z][a-zA-Z]*$/.test(name))
169
- return 'PascalCase';
170
- return 'unknown';
171
- }
172
- // Multi-word camelCase
173
- it('classifies multi-word camelCase', () => {
174
- expect(detectCasing('fetchData')).toBe('camelCase');
175
- expect(detectCasing('getUserProfile')).toBe('camelCase');
176
- expect(detectCasing('handleClick')).toBe('camelCase');
177
- expect(detectCasing('processItem')).toBe('camelCase');
178
- expect(detectCasing('createNewUser')).toBe('camelCase');
179
- });
180
- // Single-word lowercase (the bug fix)
181
- it('classifies single-word lowercase as camelCase', () => {
182
- expect(detectCasing('fetch')).toBe('camelCase');
183
- expect(detectCasing('use')).toBe('camelCase');
184
- expect(detectCasing('get')).toBe('camelCase');
185
- expect(detectCasing('set')).toBe('camelCase');
186
- expect(detectCasing('run')).toBe('camelCase');
187
- expect(detectCasing('a')).toBe('camelCase');
188
- expect(detectCasing('x')).toBe('camelCase');
189
- expect(detectCasing('id')).toBe('camelCase');
190
- });
191
- // Single-word lowercase with digits
192
- it('classifies lowercase with digits as camelCase', () => {
193
- expect(detectCasing('handler2')).toBe('camelCase');
194
- expect(detectCasing('config3')).toBe('camelCase');
195
- expect(detectCasing('v2')).toBe('camelCase');
196
- });
197
- // PascalCase
198
- it('classifies PascalCase', () => {
199
- expect(detectCasing('MyComponent')).toBe('PascalCase');
200
- expect(detectCasing('UserService')).toBe('PascalCase');
201
- expect(detectCasing('App')).toBe('PascalCase');
202
- expect(detectCasing('A')).toBe('SCREAMING_SNAKE'); // single uppercase letter
203
- });
204
- // snake_case
205
- it('classifies snake_case', () => {
206
- expect(detectCasing('my_func')).toBe('snake_case');
207
- expect(detectCasing('get_data')).toBe('snake_case');
208
- expect(detectCasing('process_all_items')).toBe('snake_case');
209
- });
210
- // SCREAMING_SNAKE
211
- it('classifies SCREAMING_SNAKE_CASE', () => {
212
- expect(detectCasing('API_URL')).toBe('SCREAMING_SNAKE');
213
- expect(detectCasing('MAX_RETRIES')).toBe('SCREAMING_SNAKE');
214
- expect(detectCasing('A')).toBe('SCREAMING_SNAKE');
215
- expect(detectCasing('DB')).toBe('SCREAMING_SNAKE');
216
- });
217
- // Edge cases that should NOT be unknown
218
- it('does not return unknown for valid identifiers', () => {
219
- const validIdentifiers = [
220
- 'fetch', 'getData', 'MyClass', 'my_func', 'API_KEY',
221
- 'use', 'run', 'a', 'x', 'id', 'App', 'handler2',
222
- 'processItem', 'UserProfile', 'get_all_data', 'MAX_SIZE',
223
- ];
224
- for (const name of validIdentifiers) {
225
- expect(detectCasing(name)).not.toBe('unknown');
226
- }
227
- });
228
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,53 +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 { reviewWithTools } from './agent-review.js';
6
- import { verifyCodeFindings } from './code-verifier.js';
7
- let repo;
8
- beforeEach(() => {
9
- repo = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-review-'));
10
- fs.writeFileSync(path.join(repo, 'limits.ts'), 'export const MAX_ROWS = 0;\n');
11
- fs.writeFileSync(path.join(repo, 'page.ts'), Array.from({ length: 60 }, (_, i) => `// line ${i + 1}`).join('\n'));
12
- });
13
- afterEach(() => { fs.rmSync(repo, { recursive: true, force: true }); });
14
- const context = { file: 'page.ts', language: 'typescript', text: '1| export function page() {}', ranges: [[1, 5]], source: 'export function page() {}' };
15
- function scripted(replies) {
16
- const seen = [];
17
- const provider = {
18
- name: 'fake', isAvailable: async () => true, setup: async () => { }, dispose: () => { }, analyze: async () => '',
19
- chat: async (messages, tools, options) => {
20
- seen.push({ messages: [...messages], tools: tools.length, toolChoice: options?.toolChoice });
21
- return replies.shift() ?? { text: '{"findings": []}', toolCalls: [] };
22
- },
23
- };
24
- return { provider, seen };
25
- }
26
- const findingJson = (line, description) => JSON.stringify({ findings: [{ category: 'correctness', severity: 'high', file: 'page.ts', line, description, suggestion: 's', confidence: 0.9 }] });
27
- describe('reviewWithTools', () => {
28
- it('runs the tools the model asks for, then grounds its finding in what it read', async () => {
29
- const { provider, seen } = scripted([
30
- { text: '', toolCalls: [{ id: 't1', name: 'read_file', arguments: { path: 'limits.ts' } }, { id: 't2', name: 'read_file', arguments: { path: 'page.ts', start_line: 40, end_line: 45 } }] },
31
- { text: findingJson(42, '`MAX_ROWS` is 0, so the page loop never runs.'), toolCalls: [] },
32
- ]);
33
- const result = await reviewWithTools(provider, context, '', repo, {});
34
- expect(result.toolCalls).toBe(2);
35
- const toolResults = seen[1].messages.filter(m => m.role === 'tool').map(m => m.content);
36
- expect(toolResults[0]).toContain('export const MAX_ROWS = 0;');
37
- // Line 42 was outside the sent source, but the model read it, and it read MAX_ROWS.
38
- expect(verifyCodeFindings(result.findings, [result.context])).toHaveLength(1);
39
- expect(verifyCodeFindings(result.findings, [context])).toHaveLength(0);
40
- });
41
- it('forbids tool calls after the budget, keeping the tools defined for the history, and asks for the answer', async () => {
42
- const greedy = Array.from({ length: 20 }, (_, i) => ({ text: '', toolCalls: [{ id: `t${i}`, name: 'grep', arguments: { pattern: 'line' } }] }));
43
- const { provider, seen } = scripted(greedy);
44
- const result = await reviewWithTools(provider, context, '', repo, {});
45
- expect(result.toolCalls).toBeLessThanOrEqual(12);
46
- expect(seen.at(-1)).toMatchObject({ tools: 2, toolChoice: 'none' });
47
- expect(result.findings).toEqual([]);
48
- });
49
- it('refuses a provider that cannot call tools', async () => {
50
- const provider = { name: 'local', isAvailable: async () => true, setup: async () => { }, dispose: () => { }, analyze: async () => '' };
51
- await expect(reviewWithTools(provider, context, '', repo, {})).rejects.toThrow('cannot call tools');
52
- });
53
- });
@@ -1 +0,0 @@
1
- export {};