@rigour-labs/core 6.8.0 → 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 (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,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 {};