@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
@@ -1,159 +0,0 @@
1
- /**
2
- * Tests for the hooks fast-checker module.
3
- * Verifies all 4 fast gates: file-size, hallucinated-imports, promise-safety, security-patterns.
4
- */
5
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
- import { runHookChecker } from './checker.js';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import * as os from 'os';
10
- import yaml from 'yaml';
11
- describe('runHookChecker', () => {
12
- let testDir;
13
- beforeEach(() => {
14
- testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hook-checker-test-'));
15
- // Write minimal rigour.yml
16
- fs.writeFileSync(path.join(testDir, 'rigour.yml'), yaml.stringify({
17
- version: 1,
18
- gates: { max_file_lines: 50 },
19
- }));
20
- // Write package.json for import resolution
21
- fs.writeFileSync(path.join(testDir, 'package.json'), JSON.stringify({
22
- name: 'test-proj',
23
- dependencies: { express: '^4.0.0' },
24
- }));
25
- });
26
- afterEach(() => {
27
- fs.rmSync(testDir, { recursive: true, force: true });
28
- });
29
- it('should return pass for clean files', async () => {
30
- const filePath = path.join(testDir, 'clean.ts');
31
- fs.writeFileSync(filePath, 'export const x = 1;\n');
32
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
33
- expect(result.status).toBe('pass');
34
- expect(result.failures).toHaveLength(0);
35
- expect(result.duration_ms).toBeGreaterThanOrEqual(0);
36
- });
37
- it('lets an agent edit CLAUDE.md by default, and blocks it only when the team opts in', async () => {
38
- const filePath = path.join(testDir, 'CLAUDE.md');
39
- fs.writeFileSync(filePath, '# Rules\n\n- Use the retry wrapper for partner APIs.\n');
40
- const byDefault = await runHookChecker({ cwd: testDir, files: [filePath] });
41
- expect(byDefault.failures.filter(f => f.gate === 'governance')).toEqual([]);
42
- fs.writeFileSync(path.join(testDir, 'rigour.yml'), yaml.stringify({ version: 1, gates: { governance: { enforce_memory: true } } }));
43
- const optedIn = await runHookChecker({ cwd: testDir, files: [filePath] });
44
- expect(optedIn.failures.some(f => f.gate === 'governance')).toBe(true);
45
- });
46
- it("refuses an agent edit to Rigour's own state, even when rigour.yml ignores .rigour/", async () => {
47
- fs.writeFileSync(path.join(testDir, 'rigour.yml'), 'version: 1\nignore:\n - ".rigour/**"\n');
48
- fs.mkdirSync(path.join(testDir, '.rigour'), { recursive: true });
49
- fs.writeFileSync(path.join(testDir, '.rigour', 'dismissed.json'), '{"version":1,"entries":[]}');
50
- const result = await runHookChecker({ cwd: testDir, files: ['.rigour/dismissed.json'] });
51
- expect(result.status).toBe('fail');
52
- expect(result.failures[0]).toMatchObject({ gate: 'file-guard', severity: 'critical' });
53
- });
54
- it('catches a real vendor key whatever it is named, and leaves publishable and test keys alone', async () => {
55
- // Built at runtime: a key-shaped literal in this source would be (rightly) refused by secret scanning.
56
- const fake = (prefix) => `${prefix}_${'51HxQ'}${'abcdefghijklmnopqrstuv'}`;
57
- fs.writeFileSync(path.join(testDir, 'pay.ts'), `export const stripe = {\n value: "${fake('sk_live')}",\n};\n`);
58
- fs.writeFileSync(path.join(testDir, 'public.ts'), `export const key = "${fake('pk_live')}";\nexport const t = "${fake('sk_test')}";\n`);
59
- const leaked = await runHookChecker({ cwd: testDir, files: ['pay.ts'] });
60
- expect(leaked.failures).toEqual([expect.objectContaining({ gate: 'security-patterns', line: 2, severity: 'critical', message: 'Stripe API key detected in code' })]);
61
- const fine = await runHookChecker({ cwd: testDir, files: ['public.ts'] });
62
- expect(fine.failures.filter(f => f.gate === 'security-patterns')).toEqual([]);
63
- });
64
- it('should detect file size violations', async () => {
65
- const filePath = path.join(testDir, 'big.ts');
66
- const lines = Array.from({ length: 100 }, (_, i) => `export const v${i} = ${i};`);
67
- fs.writeFileSync(filePath, lines.join('\n'));
68
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
69
- expect(result.status).toBe('fail');
70
- expect(result.failures.some(f => f.gate === 'file-size')).toBe(true);
71
- });
72
- it('should detect hardcoded secrets', async () => {
73
- const filePath = path.join(testDir, 'auth.ts');
74
- fs.writeFileSync(filePath, `
75
- const api_key = "abcdefghijklmnopqrstuvwxyz123456";
76
- `);
77
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
78
- expect(result.status).toBe('fail');
79
- expect(result.failures.some(f => f.gate === 'security-patterns')).toBe(true);
80
- });
81
- it('should detect command injection patterns', async () => {
82
- const filePath = path.join(testDir, 'cmd.ts');
83
- fs.writeFileSync(filePath, `
84
- import { exec } from 'child_process';
85
- exec(\`rm -rf \${userInput}\`);
86
- `);
87
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
88
- expect(result.status).toBe('fail');
89
- expect(result.failures.some(f => f.gate === 'security-patterns' && f.message.includes('command injection'))).toBe(true);
90
- });
91
- it('should detect JSON.parse without try/catch', async () => {
92
- const filePath = path.join(testDir, 'parse.ts');
93
- fs.writeFileSync(filePath, `
94
- const data = JSON.parse(input);
95
- console.log(data);
96
- `);
97
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
98
- expect(result.status).toBe('fail');
99
- expect(result.failures.some(f => f.gate === 'promise-safety')).toBe(true);
100
- });
101
- it('should skip non-existent files gracefully', async () => {
102
- const result = await runHookChecker({
103
- cwd: testDir,
104
- files: ['/does/not/exist.ts'],
105
- });
106
- expect(result.status).toBe('pass');
107
- expect(result.failures).toHaveLength(0);
108
- });
109
- it('should handle multiple files', async () => {
110
- const cleanFile = path.join(testDir, 'clean.ts');
111
- fs.writeFileSync(cleanFile, 'export const x = 1;\n');
112
- const badFile = path.join(testDir, 'bad.ts');
113
- fs.writeFileSync(badFile, `const password = "supersecretpassword123456";`);
114
- const result = await runHookChecker({
115
- cwd: testDir,
116
- files: [cleanFile, badFile],
117
- });
118
- expect(result.status).toBe('fail');
119
- expect(result.failures.length).toBeGreaterThan(0);
120
- });
121
- it('should handle missing config gracefully', async () => {
122
- // Remove rigour.yml
123
- fs.unlinkSync(path.join(testDir, 'rigour.yml'));
124
- const filePath = path.join(testDir, 'test.ts');
125
- fs.writeFileSync(filePath, 'export const x = 1;\n');
126
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
127
- expect(result.status).toBe('pass');
128
- });
129
- it('should complete within timeout', async () => {
130
- const filePath = path.join(testDir, 'test.ts');
131
- fs.writeFileSync(filePath, 'export const x = 1;\n');
132
- const result = await runHookChecker({
133
- cwd: testDir,
134
- files: [filePath],
135
- timeout_ms: 5000,
136
- });
137
- expect(result.duration_ms).toBeLessThan(5000);
138
- });
139
- it('should detect hallucinated relative imports', async () => {
140
- const filePath = path.join(testDir, 'app.ts');
141
- fs.writeFileSync(filePath, `
142
- import { helper } from './nonexistent-module';
143
- `);
144
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
145
- expect(result.status).toBe('fail');
146
- expect(result.failures.some(f => f.gate === 'hallucinated-imports')).toBe(true);
147
- });
148
- it('should not flag existing relative imports', async () => {
149
- const helperPath = path.join(testDir, 'helper.ts');
150
- fs.writeFileSync(helperPath, 'export const help = true;\n');
151
- const filePath = path.join(testDir, 'app.ts');
152
- fs.writeFileSync(filePath, `
153
- import { help } from './helper';
154
- `);
155
- const result = await runHookChecker({ cwd: testDir, files: [filePath] });
156
- const importFailures = result.failures.filter(f => f.gate === 'hallucinated-imports');
157
- expect(importFailures).toHaveLength(0);
158
- });
159
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,51 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { createDLPAuditEntry, formatDLPAlert, scanInputForCredentials, } from './input-validator.js';
3
- describe('DLP confidence engine', () => {
4
- it('allows explicit example password assignments', () => {
5
- const result = scanInputForCredentials('password = "examplepassword"');
6
- expect(result.status).toBe('clean');
7
- expect(result.allowed_detections?.[0].decision).toBe('allow');
8
- });
9
- it('warns on high-entropy values even with api_key label', () => {
10
- const result = scanInputForCredentials('api_key: "abcdefZ9y8X7w6V5u4T3s2R1q0P9o8N7m6"');
11
- expect(result.status).toBe('warning');
12
- expect(result.detections[0].decision).toBe('warn');
13
- });
14
- it('allows localhost database URLs with placeholder credentials', () => {
15
- const result = scanInputForCredentials('DATABASE_URL=postgresql://user:password@localhost:5432/db');
16
- expect(result.status).toBe('clean');
17
- });
18
- it('warns for live Stripe publishable keys', () => {
19
- const result = scanInputForCredentials('STRIPE_PUBLIC_KEY=pk_live_123456789012345678901234');
20
- expect(result.status).toBe('warning');
21
- expect(result.detections[0].decision).toBe('warn');
22
- expect(result.detections[0].reason_codes).toContain('public_live_key');
23
- });
24
- it('allows provider keys in comments (reduced false positives)', () => {
25
- const result = scanInputForCredentials('// AWS_ACCESS_KEY_ID=AKIAZ9Y8X7W6V5U4T3Q2');
26
- expect(result.status).toBe('clean');
27
- });
28
- it('allows GitHub tokens in comments', () => {
29
- const result = scanInputForCredentials('// ghp_Z9Y8X7W6V5U4T3S2R1Q0P9O8N7M6B5C4A3D2');
30
- expect(result.status).toBe('clean');
31
- });
32
- it('blocks JWT tokens in comments', () => {
33
- const jwt = '// token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJwcm9kLXVzZXIiLCJpc3MiOiJhdXRoLXNlcnZpY2UifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
34
- const result = scanInputForCredentials(jwt);
35
- expect(result.status).toBe('blocked');
36
- expect(result.detections.some(d => d.type === 'jwt_token')).toBe(true);
37
- });
38
- it('shows allowed safe values in clean output', () => {
39
- const result = scanInputForCredentials('api_key: "abcdefghijklmnopqrstuvwxyz"');
40
- const alert = formatDLPAlert(result);
41
- expect(alert).toContain('allowed 1 sample or safe credential-like value');
42
- });
43
- it('includes allowed detections without raw values in audit log', () => {
44
- const result = scanInputForCredentials('api_key: "abcdefghijklmnopqrstuvwxyz"');
45
- const entry = createDLPAuditEntry(result, { agent: 'claude' });
46
- const allowed = entry.allowed_detections;
47
- expect(allowed).toHaveLength(1);
48
- expect(allowed[0].decision).toBe('allow');
49
- expect(allowed[0].match).toBeUndefined();
50
- });
51
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,131 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import path from 'path';
3
- import os from 'os';
4
- import fs from 'fs-extra';
5
- import { recordDLPFeedback, feedbackFingerprint, loadDLPFeedbackStoreSync, isLearnedAllowSync, writeDLPBlockManifest, allowLastDLPBlock, } from './dlp-feedback.js';
6
- import { scanInputForCredentials } from './input-validator.js';
7
- import { generateDLPHookFiles } from './dlp-templates.js';
8
- describe('DLP feedback learning', () => {
9
- const testCwd = path.join(os.tmpdir(), `rigour-dlp-fb-${Date.now()}`);
10
- beforeEach(async () => {
11
- await fs.ensureDir(path.join(testCwd, '.rigour'));
12
- });
13
- afterEach(async () => {
14
- await fs.remove(testCwd);
15
- });
16
- it('produces stable fingerprints for same shape', () => {
17
- const a = feedbackFingerprint('password_assignment', 'api_key = "your-key-here"');
18
- const b = feedbackFingerprint('password_assignment', 'api_key = "your-key-here"');
19
- expect(a).toBe(b);
20
- });
21
- it('records and applies learned false positives', async () => {
22
- const match = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
23
- await recordDLPFeedback(testCwd, {
24
- type: 'password_assignment',
25
- match,
26
- confidence: 55,
27
- source: 'hook',
28
- });
29
- const store = loadDLPFeedbackStoreSync(testCwd);
30
- expect(isLearnedAllowSync(store, 'password_assignment', match)).toBe(true);
31
- const result = scanInputForCredentials(match, { cwd: testCwd });
32
- expect(result.status).toBe('clean');
33
- expect(result.allowed_detections?.[0].reason_codes).toContain('learned_false_positive');
34
- });
35
- it('allowLastDLPBlock learns from manifest', async () => {
36
- const text = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
37
- const blocked = scanInputForCredentials(text, { cwd: testCwd, block_on_detection: true });
38
- expect(blocked.status).toBe('warning');
39
- await writeDLPBlockManifest(testCwd, blocked.detections, text);
40
- const learned = await allowLastDLPBlock(testCwd, 'hook');
41
- expect(learned).toBeGreaterThan(0);
42
- const retry = scanInputForCredentials(text, { cwd: testCwd });
43
- expect(retry.status).toBe('clean');
44
- });
45
- it('never learns provider or high-confidence detections', async () => {
46
- const provider = await recordDLPFeedback(testCwd, {
47
- type: 'openai_key',
48
- match: 'sk-proj-Z9Y8X7W6V5U4T3S2R1Q0P9O8N7M6',
49
- confidence: 92,
50
- });
51
- const highConfidence = await recordDLPFeedback(testCwd, {
52
- type: 'password_assignment',
53
- match: 'password = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"',
54
- confidence: 95,
55
- });
56
- expect(provider).toBeNull();
57
- expect(highConfidence).toBeNull();
58
- expect(loadDLPFeedbackStoreSync(testCwd).entries).toHaveLength(0);
59
- });
60
- it('does not retain raw credential fragments in manifests', async () => {
61
- const text = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
62
- const result = scanInputForCredentials(text);
63
- expect(result.detections[0].match).toBe(result.detections[0].redacted);
64
- expect(result.detections[0].match).not.toContain('Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4');
65
- await writeDLPBlockManifest(testCwd, result.detections, text);
66
- const manifest = fs.readFileSync(path.join(testCwd, '.rigour', 'dlp-last-block.json'), 'utf-8');
67
- expect(manifest).not.toContain('Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4');
68
- expect(manifest).not.toContain('match');
69
- expect(manifest).not.toContain('shape');
70
- });
71
- it('rejects and consumes expired manifests', async () => {
72
- const text = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
73
- const result = scanInputForCredentials(text);
74
- await writeDLPBlockManifest(testCwd, result.detections, text);
75
- const manifestPath = path.join(testCwd, '.rigour', 'dlp-last-block.json');
76
- const manifest = fs.readJsonSync(manifestPath);
77
- manifest.timestamp = '2020-01-01T00:00:00.000Z';
78
- fs.writeJsonSync(manifestPath, manifest);
79
- expect(await allowLastDLPBlock(testCwd, 'hook')).toBe(0);
80
- expect(fs.existsSync(manifestPath)).toBe(false);
81
- });
82
- it('rejects and consumes malformed manifests', async () => {
83
- const manifestPath = path.join(testCwd, '.rigour', 'dlp-last-block.json');
84
- fs.writeFileSync(manifestPath, '{not-json');
85
- expect(await allowLastDLPBlock(testCwd, 'hook')).toBe(0);
86
- expect(fs.existsSync(manifestPath)).toBe(false);
87
- });
88
- });
89
- describe('DLP scanner URL boundaries', () => {
90
- it('detects genuine HTTP basic-auth credentials', () => {
91
- const result = scanInputForCredentials('https://alice:S3cr3t-Prod-9842@example.com/v1');
92
- expect(result.status).toBe('warning');
93
- expect(result.detections.some(d => d.type === 'credentials_in_url')).toBe(true);
94
- });
95
- it('allows signed GCS URLs without URL user-info', () => {
96
- const url = 'https://storage.googleapis.com/example/archive.zip'
97
- + '?X-Goog-Credential=service%40example.invalid&X-Goog-Signature=redacted';
98
- expect(scanInputForCredentials(url).status).toBe('clean');
99
- });
100
- it('does not cross multiline JSON boundaries while scanning URLs', () => {
101
- const input = `{
102
- "task_archive_url": "https://storage.googleapis.com/example/archive.zip",
103
- "provider": { "npm": "@ai-sdk/openai-compatible" }
104
- }`;
105
- expect(scanInputForCredentials(input).status).toBe('clean');
106
- });
107
- it('allows nested OpenCode configuration with scoped npm packages', () => {
108
- const config = JSON.stringify({
109
- $schema: 'https://opencode.ai/config.json',
110
- provider: {
111
- moonshot: {
112
- npm: '@ai-sdk/openai-compatible',
113
- options: {
114
- baseURL: 'https://api.moonshot.ai/v1',
115
- apiKey: '{env:OPENAI_API_KEY}',
116
- },
117
- },
118
- },
119
- }, null, 2);
120
- expect(scanInputForCredentials(config).status).toBe('clean');
121
- });
122
- });
123
- describe('DLP hook warning templates', () => {
124
- it.each(['cursor', 'cline', 'windsurf'])('generates non-blocking %s warnings', (tool) => {
125
- const content = generateDLPHookFiles(tool, 'rigour hooks check')
126
- .map(file => file.content)
127
- .join('\n');
128
- expect(content).toContain('possible credential');
129
- expect(content).not.toContain('process.exit(2)');
130
- });
131
- });
@@ -1 +0,0 @@
1
- export {};