@rigour-labs/core 6.8.0 → 6.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/dist/inference/cloud-provider.js +12 -2
  2. package/package.json +11 -8
  3. package/dist/brief/briefing.test.d.ts +0 -1
  4. package/dist/brief/briefing.test.js +0 -107
  5. package/dist/context/automatic-index-cache.test.d.ts +0 -1
  6. package/dist/context/automatic-index-cache.test.js +0 -30
  7. package/dist/context/automatic-index.test.d.ts +0 -1
  8. package/dist/context/automatic-index.test.js +0 -45
  9. package/dist/context/cache-engine.test.d.ts +0 -1
  10. package/dist/context/cache-engine.test.js +0 -99
  11. package/dist/context/dependency-graph.test.d.ts +0 -1
  12. package/dist/context/dependency-graph.test.js +0 -13
  13. package/dist/context/index-status.test.d.ts +0 -1
  14. package/dist/context/index-status.test.js +0 -26
  15. package/dist/context.test.d.ts +0 -1
  16. package/dist/context.test.js +0 -228
  17. package/dist/deep/agent-review.test.d.ts +0 -1
  18. package/dist/deep/agent-review.test.js +0 -53
  19. package/dist/deep/code-context.test.d.ts +0 -1
  20. package/dist/deep/code-context.test.js +0 -48
  21. package/dist/deep/code-pass.test.d.ts +0 -1
  22. package/dist/deep/code-pass.test.js +0 -112
  23. package/dist/deep/code-review-prompt.test.d.ts +0 -1
  24. package/dist/deep/code-review-prompt.test.js +0 -20
  25. package/dist/deep/code-verifier.test.d.ts +0 -1
  26. package/dist/deep/code-verifier.test.js +0 -54
  27. package/dist/deep/diff-tests/calls.test.d.ts +0 -1
  28. package/dist/deep/diff-tests/calls.test.js +0 -33
  29. package/dist/deep/diff-tests/run.test.d.ts +0 -1
  30. package/dist/deep/diff-tests/run.test.js +0 -58
  31. package/dist/deep/fact-extractor.test.d.ts +0 -1
  32. package/dist/deep/fact-extractor.test.js +0 -581
  33. package/dist/deep/parse-findings.test.d.ts +0 -1
  34. package/dist/deep/parse-findings.test.js +0 -25
  35. package/dist/deep/pr-review.test.d.ts +0 -1
  36. package/dist/deep/pr-review.test.js +0 -80
  37. package/dist/deep/prompts.test.d.ts +0 -1
  38. package/dist/deep/prompts.test.js +0 -235
  39. package/dist/deep/reference-pack.test.d.ts +0 -1
  40. package/dist/deep/reference-pack.test.js +0 -46
  41. package/dist/deep/related-changes.test.d.ts +0 -1
  42. package/dist/deep/related-changes.test.js +0 -33
  43. package/dist/deep/review-context-export.test.d.ts +0 -1
  44. package/dist/deep/review-context-export.test.js +0 -32
  45. package/dist/deep/review-tools.test.d.ts +0 -1
  46. package/dist/deep/review-tools.test.js +0 -39
  47. package/dist/deep/risk.test.d.ts +0 -1
  48. package/dist/deep/risk.test.js +0 -101
  49. package/dist/deep/verifier.test.d.ts +0 -1
  50. package/dist/deep/verifier.test.js +0 -635
  51. package/dist/discovery.test.d.ts +0 -1
  52. package/dist/discovery.test.js +0 -93
  53. package/dist/environment.test.d.ts +0 -1
  54. package/dist/environment.test.js +0 -94
  55. package/dist/firewall/firewall.test.d.ts +0 -1
  56. package/dist/firewall/firewall.test.js +0 -117
  57. package/dist/firewall/trust-boundaries.test.d.ts +0 -1
  58. package/dist/firewall/trust-boundaries.test.js +0 -64
  59. package/dist/firewall/trusted-control.test.d.ts +0 -1
  60. package/dist/firewall/trusted-control.test.js +0 -188
  61. package/dist/gates/agent-team.test.d.ts +0 -1
  62. package/dist/gates/agent-team.test.js +0 -113
  63. package/dist/gates/ast.test.d.ts +0 -1
  64. package/dist/gates/ast.test.js +0 -112
  65. package/dist/gates/checkpoint.test.d.ts +0 -1
  66. package/dist/gates/checkpoint.test.js +0 -105
  67. package/dist/gates/content.test.d.ts +0 -1
  68. package/dist/gates/content.test.js +0 -73
  69. package/dist/gates/coverage.test.d.ts +0 -1
  70. package/dist/gates/coverage.test.js +0 -53
  71. package/dist/gates/dedupe-failures.test.d.ts +0 -1
  72. package/dist/gates/dedupe-failures.test.js +0 -12
  73. package/dist/gates/deep-analysis.test.d.ts +0 -1
  74. package/dist/gates/deep-analysis.test.js +0 -86
  75. package/dist/gates/deep-intent.test.d.ts +0 -1
  76. package/dist/gates/deep-intent.test.js +0 -51
  77. package/dist/gates/deep-timeout.test.d.ts +0 -1
  78. package/dist/gates/deep-timeout.test.js +0 -10
  79. package/dist/gates/deprecated-apis.test.d.ts +0 -1
  80. package/dist/gates/deprecated-apis.test.js +0 -318
  81. package/dist/gates/deprecated-dependencies.test.d.ts +0 -1
  82. package/dist/gates/deprecated-dependencies.test.js +0 -55
  83. package/dist/gates/frontend-secret-exposure.test.d.ts +0 -1
  84. package/dist/gates/frontend-secret-exposure.test.js +0 -148
  85. package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.d.ts +0 -1
  86. package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.js +0 -27
  87. package/dist/gates/hallucinated-imports/js-resolver-types.test.d.ts +0 -1
  88. package/dist/gates/hallucinated-imports/js-resolver-types.test.js +0 -14
  89. package/dist/gates/hallucinated-imports-sveltekit.test.d.ts +0 -1
  90. package/dist/gates/hallucinated-imports-sveltekit.test.js +0 -132
  91. package/dist/gates/hallucinated-imports.test.d.ts +0 -1
  92. package/dist/gates/hallucinated-imports.test.js +0 -1206
  93. package/dist/gates/js-style-context.test.d.ts +0 -1
  94. package/dist/gates/js-style-context.test.js +0 -35
  95. package/dist/gates/logic-drift.test.d.ts +0 -1
  96. package/dist/gates/logic-drift.test.js +0 -52
  97. package/dist/gates/phantom-apis.test.d.ts +0 -1
  98. package/dist/gates/phantom-apis.test.js +0 -396
  99. package/dist/gates/promise-safety.test.d.ts +0 -1
  100. package/dist/gates/promise-safety.test.js +0 -34
  101. package/dist/gates/runner.test.d.ts +0 -1
  102. package/dist/gates/runner.test.js +0 -77
  103. package/dist/gates/scoped-gates.test.d.ts +0 -1
  104. package/dist/gates/scoped-gates.test.js +0 -52
  105. package/dist/gates/security-patterns-owasp.test.d.ts +0 -1
  106. package/dist/gates/security-patterns-owasp.test.js +0 -186
  107. package/dist/gates/security-patterns.test.d.ts +0 -1
  108. package/dist/gates/security-patterns.test.js +0 -194
  109. package/dist/gates/semantic-bugs.test.d.ts +0 -1
  110. package/dist/gates/semantic-bugs.test.js +0 -76
  111. package/dist/gates/side-effect-analysis.test.d.ts +0 -1
  112. package/dist/gates/side-effect-analysis.test.js +0 -162
  113. package/dist/gates/style-drift.test.d.ts +0 -1
  114. package/dist/gates/style-drift.test.js +0 -26
  115. package/dist/gates/test-quality.test.d.ts +0 -1
  116. package/dist/gates/test-quality.test.js +0 -325
  117. package/dist/gates/trusted-reviews.test.d.ts +0 -1
  118. package/dist/gates/trusted-reviews.test.js +0 -16
  119. package/dist/gates/unindexed-reads/queries.test.d.ts +0 -1
  120. package/dist/gates/unindexed-reads/queries.test.js +0 -54
  121. package/dist/gates/unindexed-reads/schema.test.d.ts +0 -1
  122. package/dist/gates/unindexed-reads/schema.test.js +0 -81
  123. package/dist/gates/unindexed-reads/unindexed-reads.test.d.ts +0 -1
  124. package/dist/gates/unindexed-reads/unindexed-reads.test.js +0 -90
  125. package/dist/hooks/checker.test.d.ts +0 -1
  126. package/dist/hooks/checker.test.js +0 -159
  127. package/dist/hooks/dlp-confidence.test.d.ts +0 -1
  128. package/dist/hooks/dlp-confidence.test.js +0 -51
  129. package/dist/hooks/dlp-feedback.test.d.ts +0 -1
  130. package/dist/hooks/dlp-feedback.test.js +0 -131
  131. package/dist/hooks/input-validator.test.d.ts +0 -1
  132. package/dist/hooks/input-validator.test.js +0 -329
  133. package/dist/hooks/templates.test.d.ts +0 -1
  134. package/dist/hooks/templates.test.js +0 -27
  135. package/dist/inference/brain-placeholder.test.d.ts +0 -1
  136. package/dist/inference/brain-placeholder.test.js +0 -28
  137. package/dist/inference/cloud-provider.test.d.ts +0 -1
  138. package/dist/inference/cloud-provider.test.js +0 -139
  139. package/dist/inference/executable.test.d.ts +0 -1
  140. package/dist/inference/executable.test.js +0 -41
  141. package/dist/inference/http-download.test.d.ts +0 -1
  142. package/dist/inference/http-download.test.js +0 -109
  143. package/dist/inference/llama-engine-checksum.test.d.ts +0 -1
  144. package/dist/inference/llama-engine-checksum.test.js +0 -27
  145. package/dist/inference/llama-engine.test.d.ts +0 -1
  146. package/dist/inference/llama-engine.test.js +0 -51
  147. package/dist/inference/llama-process.test.d.ts +0 -1
  148. package/dist/inference/llama-process.test.js +0 -61
  149. package/dist/inference/local-model.test.d.ts +0 -1
  150. package/dist/inference/local-model.test.js +0 -23
  151. package/dist/inference/model-download.test.d.ts +0 -1
  152. package/dist/inference/model-download.test.js +0 -125
  153. package/dist/inference/model-manager.test.d.ts +0 -1
  154. package/dist/inference/model-manager.test.js +0 -24
  155. package/dist/inference/types.test.d.ts +0 -1
  156. package/dist/inference/types.test.js +0 -19
  157. package/dist/memory/recall.test.d.ts +0 -1
  158. package/dist/memory/recall.test.js +0 -36
  159. package/dist/pattern-index/indexer.test.d.ts +0 -6
  160. package/dist/pattern-index/indexer.test.js +0 -197
  161. package/dist/pattern-index/matcher.test.d.ts +0 -6
  162. package/dist/pattern-index/matcher.test.js +0 -238
  163. package/dist/pattern-index/pattern-reuse.test.d.ts +0 -1
  164. package/dist/pattern-index/pattern-reuse.test.js +0 -76
  165. package/dist/pattern-index/semantic-runtime.test.d.ts +0 -1
  166. package/dist/pattern-index/semantic-runtime.test.js +0 -31
  167. package/dist/pattern-index/staleness.test.d.ts +0 -6
  168. package/dist/pattern-index/staleness.test.js +0 -211
  169. package/dist/review/agent-fixes.test.d.ts +0 -1
  170. package/dist/review/agent-fixes.test.js +0 -32
  171. package/dist/review/backtest-init.test.d.ts +0 -1
  172. package/dist/review/backtest-init.test.js +0 -136
  173. package/dist/review/backtest-judges.test.d.ts +0 -1
  174. package/dist/review/backtest-judges.test.js +0 -32
  175. package/dist/review/backtest-last.test.d.ts +0 -1
  176. package/dist/review/backtest-last.test.js +0 -109
  177. package/dist/review/backtest.test.d.ts +0 -1
  178. package/dist/review/backtest.test.js +0 -183
  179. package/dist/review/baseline.test.d.ts +0 -1
  180. package/dist/review/baseline.test.js +0 -22
  181. package/dist/review/branch-checks.test.d.ts +0 -1
  182. package/dist/review/branch-checks.test.js +0 -48
  183. package/dist/review/check-outcomes.test.d.ts +0 -1
  184. package/dist/review/check-outcomes.test.js +0 -56
  185. package/dist/review/code-patterns.test.d.ts +0 -1
  186. package/dist/review/code-patterns.test.js +0 -142
  187. package/dist/review/dead-code.test.d.ts +0 -1
  188. package/dist/review/dead-code.test.js +0 -154
  189. package/dist/review/deep-runs.test.d.ts +0 -1
  190. package/dist/review/deep-runs.test.js +0 -23
  191. package/dist/review/effectiveness.test.d.ts +0 -1
  192. package/dist/review/effectiveness.test.js +0 -42
  193. package/dist/review/fix-scope.test.d.ts +0 -1
  194. package/dist/review/fix-scope.test.js +0 -104
  195. package/dist/review/generated-files.test.d.ts +0 -1
  196. package/dist/review/generated-files.test.js +0 -25
  197. package/dist/review/migration-order.test.d.ts +0 -1
  198. package/dist/review/migration-order.test.js +0 -62
  199. package/dist/review/quiet.test.d.ts +0 -1
  200. package/dist/review/quiet.test.js +0 -38
  201. package/dist/review/receipt.test.d.ts +0 -1
  202. package/dist/review/receipt.test.js +0 -60
  203. package/dist/review/review-task.test.d.ts +0 -1
  204. package/dist/review/review-task.test.js +0 -89
  205. package/dist/review/review.test.d.ts +0 -1
  206. package/dist/review/review.test.js +0 -203
  207. package/dist/review/reviewer/adapters.test.d.ts +0 -1
  208. package/dist/review/reviewer/adapters.test.js +0 -100
  209. package/dist/review/reviewer/api-judge.test.d.ts +0 -1
  210. package/dist/review/reviewer/api-judge.test.js +0 -108
  211. package/dist/review/reviewer/background.test.d.ts +0 -1
  212. package/dist/review/reviewer/background.test.js +0 -118
  213. package/dist/review/reviewer/context.test.d.ts +0 -1
  214. package/dist/review/reviewer/context.test.js +0 -45
  215. package/dist/review/reviewer/exec.test.d.ts +0 -1
  216. package/dist/review/reviewer/exec.test.js +0 -59
  217. package/dist/review/reviewer/inputs.test.d.ts +0 -1
  218. package/dist/review/reviewer/inputs.test.js +0 -52
  219. package/dist/review/reviewer/panel.test.d.ts +0 -1
  220. package/dist/review/reviewer/panel.test.js +0 -110
  221. package/dist/review/reviewer/record.test.d.ts +0 -1
  222. package/dist/review/reviewer/record.test.js +0 -40
  223. package/dist/review/reviewer/rule-writer.test.d.ts +0 -1
  224. package/dist/review/reviewer/rule-writer.test.js +0 -52
  225. package/dist/review/reviewer/settings.test.d.ts +0 -1
  226. package/dist/review/reviewer/settings.test.js +0 -57
  227. package/dist/review/reviewer/usage.test.d.ts +0 -1
  228. package/dist/review/reviewer/usage.test.js +0 -14
  229. package/dist/review/reviewer.test.d.ts +0 -1
  230. package/dist/review/reviewer.test.js +0 -792
  231. package/dist/review/stories.test.d.ts +0 -1
  232. package/dist/review/stories.test.js +0 -58
  233. package/dist/review/toolchain.test.d.ts +0 -1
  234. package/dist/review/toolchain.test.js +0 -108
  235. package/dist/review/typed/redundancy.test.d.ts +0 -1
  236. package/dist/review/typed/redundancy.test.js +0 -315
  237. package/dist/review/typed/schema-nullability.test.d.ts +0 -1
  238. package/dist/review/typed/schema-nullability.test.js +0 -63
  239. package/dist/review-learning/human-edits.test.d.ts +0 -1
  240. package/dist/review-learning/human-edits.test.js +0 -47
  241. package/dist/review-learning/repo-rules.test.d.ts +0 -1
  242. package/dist/review-learning/repo-rules.test.js +0 -93
  243. package/dist/review-learning/review-learning.test.d.ts +0 -1
  244. package/dist/review-learning/review-learning.test.js +0 -249
  245. package/dist/safety.test.d.ts +0 -1
  246. package/dist/safety.test.js +0 -42
  247. package/dist/semantic/benchmark.test.d.ts +0 -1
  248. package/dist/semantic/benchmark.test.js +0 -22
  249. package/dist/semantic/intent/intent.test.d.ts +0 -1
  250. package/dist/semantic/intent/intent.test.js +0 -46
  251. package/dist/semantic/learn/learn.test.d.ts +0 -1
  252. package/dist/semantic/learn/learn.test.js +0 -67
  253. package/dist/semantic/origins.test.d.ts +0 -1
  254. package/dist/semantic/origins.test.js +0 -77
  255. package/dist/semantic/project-facts.test.d.ts +0 -1
  256. package/dist/semantic/project-facts.test.js +0 -45
  257. package/dist/semantic/sites/call-sites.test.d.ts +0 -1
  258. package/dist/semantic/sites/call-sites.test.js +0 -46
  259. package/dist/services/adaptive-thresholds.test.d.ts +0 -1
  260. package/dist/services/adaptive-thresholds.test.js +0 -53
  261. package/dist/services/agent-history.test.d.ts +0 -1
  262. package/dist/services/agent-history.test.js +0 -69
  263. package/dist/services/context-scope-summary.test.d.ts +0 -1
  264. package/dist/services/context-scope-summary.test.js +0 -17
  265. package/dist/services/context-telemetry-service.test.d.ts +0 -1
  266. package/dist/services/context-telemetry-service.test.js +0 -182
  267. package/dist/services/cursor-usage-sync.test.d.ts +0 -1
  268. package/dist/services/cursor-usage-sync.test.js +0 -173
  269. package/dist/services/engineering-knowledge-graph.test.d.ts +0 -1
  270. package/dist/services/engineering-knowledge-graph.test.js +0 -76
  271. package/dist/services/model-pricing.test.d.ts +0 -1
  272. package/dist/services/model-pricing.test.js +0 -44
  273. package/dist/services/observed-savings.test.d.ts +0 -1
  274. package/dist/services/observed-savings.test.js +0 -37
  275. package/dist/services/score-history.test.d.ts +0 -1
  276. package/dist/services/score-history.test.js +0 -61
  277. package/dist/smoke.test.d.ts +0 -1
  278. package/dist/smoke.test.js +0 -17
  279. package/dist/storage/cache-cleanup.test.d.ts +0 -1
  280. package/dist/storage/cache-cleanup.test.js +0 -54
  281. package/dist/storage/context-telemetry.test.d.ts +0 -1
  282. package/dist/storage/context-telemetry.test.js +0 -80
  283. package/dist/storage/db.test.d.ts +0 -1
  284. package/dist/storage/db.test.js +0 -46
  285. package/dist/storage/fix-lessons.test.d.ts +0 -1
  286. package/dist/storage/fix-lessons.test.js +0 -61
  287. package/dist/storage/lessons.test.d.ts +0 -1
  288. package/dist/storage/lessons.test.js +0 -81
  289. package/dist/storage/local-encryption.test.d.ts +0 -1
  290. package/dist/storage/local-encryption.test.js +0 -34
  291. package/dist/storage/local-memory.test.d.ts +0 -1
  292. package/dist/storage/local-memory.test.js +0 -55
  293. package/dist/storage/share-memory.test.d.ts +0 -1
  294. package/dist/storage/share-memory.test.js +0 -34
  295. package/dist/storage/team-diagnostics.test.d.ts +0 -1
  296. package/dist/storage/team-diagnostics.test.js +0 -51
  297. package/dist/storage/team-scope.test.d.ts +0 -1
  298. package/dist/storage/team-scope.test.js +0 -22
  299. package/dist/storage/team-store.test.d.ts +0 -1
  300. package/dist/storage/team-store.test.js +0 -11
  301. package/dist/storage/team-sync-scope.test.d.ts +0 -1
  302. package/dist/storage/team-sync-scope.test.js +0 -100
  303. package/dist/storage/team-vector-store.test.d.ts +0 -1
  304. package/dist/storage/team-vector-store.test.js +0 -56
  305. package/dist/storage/telemetry-scope.test.d.ts +0 -1
  306. package/dist/storage/telemetry-scope.test.js +0 -38
  307. package/dist/task/thread.test.d.ts +0 -1
  308. package/dist/task/thread.test.js +0 -133
  309. package/dist/telemetry/telemetry.test.d.ts +0 -1
  310. package/dist/telemetry/telemetry.test.js +0 -64
  311. package/dist/types/index.test.d.ts +0 -1
  312. package/dist/types/index.test.js +0 -33
  313. package/dist/utils/command-line.test.d.ts +0 -1
  314. package/dist/utils/command-line.test.js +0 -8
  315. package/dist/utils/diff-removed.test.d.ts +0 -1
  316. package/dist/utils/diff-removed.test.js +0 -29
  317. package/dist/utils/diff.test.d.ts +0 -1
  318. package/dist/utils/diff.test.js +0 -38
  319. package/dist/utils/glob-paths.test.d.ts +0 -1
  320. package/dist/utils/glob-paths.test.js +0 -40
  321. package/dist/utils/profile.test.d.ts +0 -1
  322. package/dist/utils/profile.test.js +0 -68
  323. package/dist/utils/scanner.test.d.ts +0 -1
  324. package/dist/utils/scanner.test.js +0 -48
  325. package/dist/utils/scope.test.d.ts +0 -1
  326. package/dist/utils/scope.test.js +0 -38
@@ -1 +0,0 @@
1
- export {};
@@ -1,35 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { extractComparableJsNames } from './js-style-context.js';
3
- describe('context-aware JS naming', () => {
4
- it('excludes exported Next route methods only inside app route files', () => {
5
- const code = `
6
- export async function GET() { return Response.json({}); }
7
- export const POST = async () => Response.json({});
8
- function GET_HELPER() { return 1; }
9
- `;
10
- expect(extractComparableJsNames(code, 'src/app/api/items/route.ts').map(item => item.name))
11
- .toEqual(['GET_HELPER']);
12
- expect(extractComparableJsNames(code, 'src/lib/route.ts').map(item => item.name))
13
- .toEqual(['GET', 'POST', 'GET_HELPER']);
14
- });
15
- it('excludes JSX-returning components but keeps ordinary PascalCase functions', () => {
16
- const code = `
17
- export function StepReview() { return <section />; }
18
- const WizardField = () => <input />;
19
- function ParseValue() { return 1; }
20
- `;
21
- expect(extractComparableJsNames(code, 'src/components/WizardField.tsx').map(item => item.name))
22
- .toEqual(['ParseValue']);
23
- });
24
- it('excludes module constants but keeps unconventional local variables', () => {
25
- const code = `
26
- const EMAIL_TEMPLATE = 'hello';
27
- function sendMessage() {
28
- const LOCAL_VALUE = 1;
29
- return LOCAL_VALUE;
30
- }
31
- `;
32
- expect(extractComparableJsNames(code, 'src/lib/template.ts').map(item => item.name))
33
- .toEqual(['sendMessage', 'LOCAL_VALUE']);
34
- });
35
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,52 +0,0 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
3
- import * as fs from 'fs';
4
- import * as os from 'os';
5
- import * as path from 'path';
6
- import { LogicDriftGate } from './logic-drift.js';
7
- describe('LogicDriftGate Git baseline', () => {
8
- let cwd;
9
- const git = (...args) => execFileSync('git', args, { cwd, stdio: 'pipe' });
10
- beforeEach(() => {
11
- cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'logic-drift-'));
12
- git('init', '-q', '-b', 'main');
13
- git('config', 'user.name', 'Rigour Test');
14
- git('config', 'user.email', 'test@example.invalid');
15
- fs.mkdirSync(path.join(cwd, 'src'));
16
- fs.writeFileSync(path.join(cwd, 'src/rules.ts'), 'export function eligible(score: number) { return score >= 10; }\n');
17
- git('add', '.');
18
- git('commit', '-qm', 'base');
19
- });
20
- afterEach(() => { fs.rmSync(cwd, { recursive: true, force: true }); });
21
- it('reports a branch mutation consistently and clears it after merge', async () => {
22
- const gate = new LogicDriftGate();
23
- expect(await gate.run({ cwd })).toEqual([]);
24
- git('switch', '-q', '-c', 'feature');
25
- fs.writeFileSync(path.join(cwd, 'src/rules.ts'), 'export function eligible(score: number) { return score > 10; }\n');
26
- const first = await gate.run({ cwd });
27
- const second = await gate.run({ cwd });
28
- expect(first).toEqual(second);
29
- expect(first).toHaveLength(1);
30
- expect(first.some(finding => finding.details.includes("'>=' to '>'"))).toBe(true);
31
- expect(fs.existsSync(path.join(cwd, '.rigour/logic-baseline.json'))).toBe(false);
32
- git('add', '.');
33
- git('commit', '-qm', 'change boundary');
34
- git('switch', '-q', 'main');
35
- git('merge', '-q', '--ff-only', 'feature');
36
- expect(await gate.run({ cwd })).toEqual([]);
37
- }, 30_000);
38
- it('reports return and branch count changes only when opted in', async () => {
39
- git('switch', '-q', '-c', 'feature');
40
- fs.writeFileSync(path.join(cwd, 'src/rules.ts'), 'export function eligible(score: number) {\n if (score < 0) return false;\n if (score > 100) return false;\n return score >= 10;\n}\n');
41
- expect(await new LogicDriftGate().run({ cwd })).toEqual([]);
42
- const opted = await new LogicDriftGate({ track_returns: true, track_branches: true }).run({ cwd });
43
- expect(opted.map(f => f.title).sort()).toEqual(['Logic Drift: Branch Change', 'Logic Drift: Return Change']);
44
- }, 30_000);
45
- it('does not use a moving local snapshot when Git has no main reference', async () => {
46
- git('switch', '-q', '-c', 'feature');
47
- git('branch', '-D', 'main');
48
- const gate = new LogicDriftGate();
49
- expect(await gate.run({ cwd })).toEqual([]);
50
- expect(fs.existsSync(path.join(cwd, '.rigour/logic-baseline.json'))).toBe(false);
51
- });
52
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,396 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- const mockFindFiles = vi.hoisted(() => vi.fn());
3
- const mockReadFile = vi.hoisted(() => vi.fn());
4
- const mockPathExists = vi.hoisted(() => vi.fn());
5
- vi.mock('../utils/scanner.js', () => ({
6
- FileScanner: { findFiles: mockFindFiles },
7
- }));
8
- vi.mock('fs-extra', () => ({
9
- default: {
10
- readFile: mockReadFile,
11
- pathExists: mockPathExists,
12
- pathExistsSync: vi.fn().mockReturnValue(false),
13
- readFileSync: vi.fn().mockReturnValue(''),
14
- readJson: vi.fn().mockResolvedValue(null),
15
- readdirSync: vi.fn().mockReturnValue([]),
16
- },
17
- }));
18
- import { PhantomApisGate } from './phantom-apis.js';
19
- describe('PhantomApisGate — Node.js', () => {
20
- let gate;
21
- beforeEach(() => {
22
- gate = new PhantomApisGate();
23
- vi.clearAllMocks();
24
- });
25
- it('should flag non-existent fs methods', async () => {
26
- mockFindFiles.mockResolvedValue(['src/utils.ts']);
27
- mockReadFile.mockResolvedValue(`
28
- import fs from 'fs';
29
- const data = fs.readFileAsync('test.txt');
30
- const result = fs.writeFilePromise('out.txt', data);
31
- `);
32
- const failures = await gate.run({ cwd: '/project' });
33
- expect(failures).toHaveLength(1);
34
- expect(failures[0].details).toContain('readFileAsync');
35
- expect(failures[0].details).toContain('writeFilePromise');
36
- });
37
- it('should NOT flag real fs methods', async () => {
38
- mockFindFiles.mockResolvedValue(['src/utils.ts']);
39
- mockReadFile.mockResolvedValue(`
40
- import fs from 'fs';
41
- const data = fs.readFileSync('test.txt', 'utf-8');
42
- fs.writeFileSync('out.txt', data);
43
- fs.existsSync('/tmp');
44
- const stream = fs.createReadStream('big.txt');
45
- `);
46
- const failures = await gate.run({ cwd: '/project' });
47
- expect(failures).toHaveLength(0);
48
- });
49
- it('should flag non-existent path methods', async () => {
50
- mockFindFiles.mockResolvedValue(['src/paths.ts']);
51
- mockReadFile.mockResolvedValue(`
52
- import path from 'path';
53
- const combined = path.combine('a', 'b');
54
- const exists = path.exists('/tmp');
55
- `);
56
- const failures = await gate.run({ cwd: '/project' });
57
- expect(failures).toHaveLength(1);
58
- expect(failures[0].details).toContain('combine');
59
- expect(failures[0].details).toContain('exists');
60
- });
61
- it('should NOT flag a property that shares the module name', async () => {
62
- mockFindFiles.mockResolvedValue(['src/generate.ts']);
63
- mockReadFile.mockResolvedValue(`
64
- import * as path from 'node:path';
65
- const tag = proc.path.split('.')[0];
66
- const dir = path.dirname(file);
67
- `);
68
- const failures = await gate.run({ cwd: '/project' });
69
- expect(failures).toHaveLength(0);
70
- });
71
- it('should NOT flag real path methods', async () => {
72
- mockFindFiles.mockResolvedValue(['src/paths.ts']);
73
- mockReadFile.mockResolvedValue(`
74
- import path from 'path';
75
- const p = path.join('a', 'b');
76
- const ext = path.extname('file.txt');
77
- const abs = path.resolve('.');
78
- `);
79
- const failures = await gate.run({ cwd: '/project' });
80
- expect(failures).toHaveLength(0);
81
- });
82
- it('should flag non-existent crypto methods', async () => {
83
- mockFindFiles.mockResolvedValue(['src/crypto.ts']);
84
- mockReadFile.mockResolvedValue(`
85
- import crypto from 'crypto';
86
- const hash = crypto.generateHash('sha256', 'data');
87
- const key = crypto.createKey('aes-256');
88
- `);
89
- const failures = await gate.run({ cwd: '/project' });
90
- expect(failures).toHaveLength(1);
91
- expect(failures[0].details).toContain('generateHash');
92
- expect(failures[0].details).toContain('createKey');
93
- });
94
- it('should NOT flag real crypto methods', async () => {
95
- mockFindFiles.mockResolvedValue(['src/crypto.ts']);
96
- mockReadFile.mockResolvedValue(`
97
- import crypto from 'crypto';
98
- const hash = crypto.createHash('sha256');
99
- const uuid = crypto.randomUUID();
100
- `);
101
- const failures = await gate.run({ cwd: '/project' });
102
- expect(failures).toHaveLength(0);
103
- });
104
- it('should handle require() imports', async () => {
105
- mockFindFiles.mockResolvedValue(['src/legacy.js']);
106
- mockReadFile.mockResolvedValue(`
107
- const fs = require('fs');
108
- fs.readFileAsync('data.txt');
109
- `);
110
- const failures = await gate.run({ cwd: '/project' });
111
- expect(failures).toHaveLength(1);
112
- expect(failures[0].details).toContain('readFileAsync');
113
- });
114
- it('should handle node: protocol imports', async () => {
115
- mockFindFiles.mockResolvedValue(['src/modern.ts']);
116
- mockReadFile.mockResolvedValue(`
117
- import os from 'node:os';
118
- const info = os.cpuInfo();
119
- `);
120
- const failures = await gate.run({ cwd: '/project' });
121
- expect(failures).toHaveLength(1);
122
- expect(failures[0].details).toContain('cpuInfo');
123
- });
124
- it('should suggest closest real method', async () => {
125
- mockFindFiles.mockResolvedValue(['src/typo.ts']);
126
- mockReadFile.mockResolvedValue(`
127
- import fs from 'fs';
128
- fs.readFileSyn('data.txt');
129
- `);
130
- const failures = await gate.run({ cwd: '/project' });
131
- expect(failures).toHaveLength(1);
132
- expect(failures[0].details).toContain('readFileSync');
133
- });
134
- it('should ignore phantom method mentions inside comments', async () => {
135
- mockFindFiles.mockResolvedValue(['src/docs.ts']);
136
- mockReadFile.mockResolvedValue(`
137
- import fs from 'fs';
138
- // fs.readFileAsync('data.txt')
139
- /* path.combine('a', 'b') */
140
- /**
141
- * fs.writeFilePromise('out.txt')
142
- */
143
- const data = fs.readFileSync('real.txt', 'utf-8');
144
- `);
145
- const failures = await gate.run({ cwd: '/project' });
146
- expect(failures).toHaveLength(0);
147
- });
148
- it('should not scan when disabled', async () => {
149
- const disabled = new PhantomApisGate({ enabled: false });
150
- const failures = await disabled.run({ cwd: '/project' });
151
- expect(failures).toHaveLength(0);
152
- expect(mockFindFiles).not.toHaveBeenCalled();
153
- });
154
- });
155
- describe('PhantomApisGate — Python', () => {
156
- let gate;
157
- beforeEach(() => {
158
- gate = new PhantomApisGate();
159
- vi.clearAllMocks();
160
- });
161
- it('should flag non-existent os methods', async () => {
162
- mockFindFiles.mockResolvedValue(['utils.py']);
163
- mockReadFile.mockResolvedValue(`
164
- import os
165
- current = os.getCurrentDirectory()
166
- files = os.listFiles('.')
167
- `);
168
- const failures = await gate.run({ cwd: '/project' });
169
- expect(failures).toHaveLength(1);
170
- expect(failures[0].details).toContain('getCurrentDirectory');
171
- expect(failures[0].details).toContain('listFiles');
172
- });
173
- it('should NOT flag real os methods', async () => {
174
- mockFindFiles.mockResolvedValue(['utils.py']);
175
- mockReadFile.mockResolvedValue(`
176
- import os
177
- current = os.getcwd()
178
- files = os.listdir('.')
179
- exists = os.path
180
- `);
181
- const failures = await gate.run({ cwd: '/project' });
182
- expect(failures).toHaveLength(0);
183
- });
184
- it('should flag non-existent json methods', async () => {
185
- mockFindFiles.mockResolvedValue(['parser.py']);
186
- mockReadFile.mockResolvedValue(`
187
- import json
188
- data = json.parse('{"key": "value"}')
189
- result = json.stringify(data)
190
- `);
191
- const failures = await gate.run({ cwd: '/project' });
192
- expect(failures).toHaveLength(1);
193
- expect(failures[0].details).toContain('parse');
194
- expect(failures[0].details).toContain('stringify');
195
- });
196
- it('should NOT flag real json methods', async () => {
197
- mockFindFiles.mockResolvedValue(['parser.py']);
198
- mockReadFile.mockResolvedValue(`
199
- import json
200
- data = json.loads('{"key": "value"}')
201
- output = json.dumps(data)
202
- `);
203
- const failures = await gate.run({ cwd: '/project' });
204
- expect(failures).toHaveLength(0);
205
- });
206
- it('should handle aliased imports', async () => {
207
- mockFindFiles.mockResolvedValue(['utils.py']);
208
- mockReadFile.mockResolvedValue(`
209
- import os as operating_system
210
- result = operating_system.getCurrentDirectory()
211
- `);
212
- const failures = await gate.run({ cwd: '/project' });
213
- expect(failures).toHaveLength(1);
214
- expect(failures[0].details).toContain('getCurrentDirectory');
215
- });
216
- it('should flag non-existent subprocess methods', async () => {
217
- mockFindFiles.mockResolvedValue(['runner.py']);
218
- mockReadFile.mockResolvedValue(`
219
- import subprocess
220
- result = subprocess.execute(['ls', '-la'])
221
- `);
222
- const failures = await gate.run({ cwd: '/project' });
223
- expect(failures).toHaveLength(1);
224
- expect(failures[0].details).toContain('execute');
225
- });
226
- });
227
- describe('PhantomApisGate — Go', () => {
228
- let gate;
229
- beforeEach(() => {
230
- gate = new PhantomApisGate();
231
- vi.clearAllMocks();
232
- });
233
- it('should flag Python-style Go method names', async () => {
234
- mockFindFiles.mockResolvedValue(['main.go']);
235
- mockReadFile.mockResolvedValue(`
236
- package main
237
- import "strings"
238
- func main() {
239
- result := strings.includes("hello", "ell")
240
- }
241
- `);
242
- const failures = await gate.run({ cwd: '/project' });
243
- expect(failures).toHaveLength(1);
244
- expect(failures[0].details).toContain('includes');
245
- expect(failures[0].details).toContain('strings.Contains');
246
- });
247
- it('should flag JS-style JSON methods in Go', async () => {
248
- mockFindFiles.mockResolvedValue(['parser.go']);
249
- mockReadFile.mockResolvedValue(`
250
- package main
251
- import "encoding/json"
252
- func parse() {
253
- data := json.parse(raw)
254
- out := json.stringify(data)
255
- }
256
- `);
257
- const failures = await gate.run({ cwd: '/project' });
258
- expect(failures).toHaveLength(1);
259
- expect(failures[0].details).toContain('parse');
260
- });
261
- it('should flag os.Exists in Go', async () => {
262
- mockFindFiles.mockResolvedValue(['files.go']);
263
- mockReadFile.mockResolvedValue(`
264
- package main
265
- import "os"
266
- func check() {
267
- exists := os.Exists("/tmp/file")
268
- }
269
- `);
270
- const failures = await gate.run({ cwd: '/project' });
271
- expect(failures).toHaveLength(1);
272
- expect(failures[0].details).toContain('Exists');
273
- });
274
- it('should NOT flag real Go stdlib functions (os.ReadFile, fmt.Print, math.Max)', async () => {
275
- mockFindFiles.mockResolvedValue(['main.go']);
276
- mockReadFile.mockResolvedValue(`
277
- package main
278
-
279
- import (
280
- "fmt"
281
- "math"
282
- "os"
283
- )
284
-
285
- func main() {
286
- data, err := os.ReadFile("config.json")
287
- if err != nil {
288
- fmt.Printf("error: %v\n", err)
289
- return
290
- }
291
- fmt.Println(string(data))
292
- fmt.Print("done\n")
293
- x := math.Max(1.5, 2.5)
294
- fmt.Sprintf("max: %f", x)
295
- fmt.Fprintf(os.Stderr, "log\n")
296
- }
297
- `);
298
- const failures = await gate.run({ cwd: '/project' });
299
- expect(failures).toHaveLength(0);
300
- });
301
- });
302
- describe('PhantomApisGate — C#', () => {
303
- let gate;
304
- beforeEach(() => {
305
- gate = new PhantomApisGate();
306
- vi.clearAllMocks();
307
- });
308
- it('should flag Java-style method casing in C#', async () => {
309
- mockFindFiles.mockResolvedValue(['Program.cs']);
310
- mockReadFile.mockResolvedValue(`
311
- using System;
312
- class Program {
313
- void Main() {
314
- string s = "hello";
315
- int len = s.length;
316
- bool eq = s.equals("world");
317
- string str = s.toString();
318
- }
319
- }
320
- `);
321
- const failures = await gate.run({ cwd: '/project' });
322
- expect(failures.length).toBeGreaterThanOrEqual(1);
323
- expect(failures[0].details).toMatch(/length|equals|toString/);
324
- });
325
- it('should flag Java collections in C#', async () => {
326
- mockFindFiles.mockResolvedValue(['Service.cs']);
327
- mockReadFile.mockResolvedValue(`
328
- using System.Collections.Generic;
329
- List<string> items = new ArrayList<string>();
330
- HashMap<string, int> map = new HashMap<string, int>();
331
- System.out.println("hello");
332
- `);
333
- const failures = await gate.run({ cwd: '/project' });
334
- expect(failures.length).toBeGreaterThanOrEqual(1);
335
- });
336
- });
337
- describe('PhantomApisGate — Java', () => {
338
- let gate;
339
- beforeEach(() => {
340
- gate = new PhantomApisGate();
341
- vi.clearAllMocks();
342
- });
343
- it('should flag JS/Python-style method names in Java', async () => {
344
- mockFindFiles.mockResolvedValue(['Main.java']);
345
- mockReadFile.mockResolvedValue(`
346
- import java.util.List;
347
- class Main {
348
- void test() {
349
- List<String> items = new ArrayList<>();
350
- items.push("hello");
351
- items.includes("test");
352
- }
353
- }
354
- `);
355
- const failures = await gate.run({ cwd: '/project' });
356
- expect(failures.length).toBeGreaterThanOrEqual(1);
357
- expect(failures[0].details).toMatch(/push|includes/);
358
- });
359
- it('should flag new List() in Java', async () => {
360
- mockFindFiles.mockResolvedValue(['Service.java']);
361
- mockReadFile.mockResolvedValue(`
362
- import java.util.*;
363
- class Service {
364
- List<String> items = new List<String>();
365
- Map<String, Integer> map = new Map<String, Integer>();
366
- }
367
- `);
368
- const failures = await gate.run({ cwd: '/project' });
369
- expect(failures.length).toBeGreaterThanOrEqual(1);
370
- });
371
- it('should NOT flag real Java methods (Deque.push, StringBuilder.append, stream().sorted(), List.reversed())', async () => {
372
- mockFindFiles.mockResolvedValue(['RealJava.java']);
373
- mockReadFile.mockResolvedValue(`
374
- import java.util.*;
375
- import java.util.stream.*;
376
- class RealJava {
377
- void test() {
378
- Deque<String> deque = new ArrayDeque<>();
379
- deque.push("hello");
380
-
381
- Stack<Integer> stack = new Stack<>();
382
- stack.push(42);
383
-
384
- StringBuilder sb = new StringBuilder();
385
- sb.append("world");
386
-
387
- List<Integer> nums = List.of(3, 1, 2);
388
- List<Integer> sorted = nums.stream().sorted().collect(Collectors.toList());
389
- List<Integer> rev = nums.reversed();
390
- }
391
- }
392
- `);
393
- const failures = await gate.run({ cwd: '/project' });
394
- expect(failures).toHaveLength(0);
395
- });
396
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,34 +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 { PromiseSafetyGate } from './promise-safety.js';
6
- describe('PromiseSafetyGate unhandled .then', () => {
7
- let cwd;
8
- beforeEach(() => { cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'promise-safety-')); });
9
- afterEach(() => { fs.rmSync(cwd, { recursive: true, force: true }); });
10
- async function thenFindings(code) {
11
- fs.writeFileSync(path.join(cwd, 'session.ts'), code);
12
- const failures = await new PromiseSafetyGate().run({ cwd });
13
- return failures.filter(f => f.details.includes('unhandled-then')).length;
14
- }
15
- it('flags a .then chain with no .catch', async () => {
16
- expect(await thenFindings('export function wake(p: Promise<number>) {\n p.then(n => {\n if (n > 1) log(n);\n });\n}\ndeclare function log(n: number): void;\n')).toBe(1);
17
- });
18
- it('finds the .catch that closes a chain whose callback body has if and return statements', async () => {
19
- const code = [
20
- 'export function wake(accepted: Promise<{ action: string }>) {',
21
- ' void accepted',
22
- ' .then(result => {',
23
- " if (result.action === 'wake') {",
24
- ' return run();',
25
- ' }',
26
- ' return undefined;',
27
- ' })',
28
- ' .catch(() => {});',
29
- '}',
30
- 'declare function run(): Promise<void>;',
31
- ].join('\n');
32
- expect(await thenFindings(code)).toBe(0);
33
- });
34
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,77 +0,0 @@
1
- import fs from 'fs-extra';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
- import { GateRunner } from './runner.js';
6
- import { DeepAnalysisGate } from './deep-analysis.js';
7
- function mockDeep(outcome, failures = []) {
8
- vi.spyOn(DeepAnalysisGate.prototype, 'run').mockResolvedValue(failures);
9
- vi.spyOn(DeepAnalysisGate.prototype, 'getOutcome').mockReturnValue({
10
- status: 'ok', mode: 'facts', filesAnalyzed: 1, chunksTotal: 1, chunksFailed: 0, ...outcome,
11
- });
12
- }
13
- describe('GateRunner deep stats execution mode', () => {
14
- let testDir;
15
- beforeEach(async () => {
16
- testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'rigour-runner-deep-'));
17
- await fs.writeFile(path.join(testDir, 'index.ts'), 'export const ok = true;\n');
18
- });
19
- afterEach(async () => {
20
- vi.restoreAllMocks();
21
- await fs.remove(testDir);
22
- });
23
- function createRunner() {
24
- return new GateRunner({
25
- version: 1,
26
- commands: {},
27
- gates: {
28
- max_file_lines: 500,
29
- forbid_todos: true,
30
- forbid_fixme: true,
31
- },
32
- });
33
- }
34
- it('reports local lite tier and the model the provider actually loaded', async () => {
35
- mockDeep({ model: 'Qwen2.5-Coder-0.5B-Instruct (stock)', modelFallback: true });
36
- const report = await createRunner().run(testDir, undefined, {
37
- enabled: true, apiKey: 'sk-test', provider: 'local', pro: false,
38
- });
39
- expect(report.stats.deep?.tier).toBe('lite');
40
- expect(report.stats.deep?.model).toBe('Qwen2.5-Coder-0.5B-Instruct (stock)');
41
- expect(report.stats.deep?.model_fallback).toBe(true);
42
- expect(report.stats.deep?.status).toBe('ok');
43
- expect(report.summary['deep-analysis']).toBe('PASS');
44
- });
45
- it('reports local deep tier when provider=local and pro=true', async () => {
46
- mockDeep({ model: 'Rigour-Deep-v5.0.0 (Qwen2.5-Coder-1.5B fine-tuned)', modelFallback: false });
47
- const report = await createRunner().run(testDir, undefined, {
48
- enabled: true, apiKey: 'sk-test', provider: 'local', pro: true,
49
- });
50
- expect(report.stats.deep?.tier).toBe('deep');
51
- expect(report.stats.deep?.model).toBe('Rigour-Deep-v5.0.0 (Qwen2.5-Coder-1.5B fine-tuned)');
52
- });
53
- it('reports cloud tier/model for cloud providers', async () => {
54
- mockDeep({ model: 'gpt-4.1-mini' });
55
- const report = await createRunner().run(testDir, undefined, {
56
- enabled: true, apiKey: 'sk-test', provider: 'openai', modelName: 'gpt-4.1-mini', pro: false,
57
- });
58
- expect(report.stats.deep?.tier).toBe('cloud');
59
- expect(report.stats.deep?.model).toBe('gpt-4.1-mini');
60
- });
61
- it('reports a deep run that could not analyze anything as ERROR with a visible failure', async () => {
62
- mockDeep({ status: 'error', chunksTotal: 3, chunksFailed: 3, error: 'All 3 inference call(s) failed.' });
63
- const report = await createRunner().run(testDir, undefined, { enabled: true, pro: false });
64
- expect(report.summary['deep-analysis']).toBe('ERROR');
65
- expect(report.status).toBe('FAIL');
66
- expect(report.stats.deep).toMatchObject({ status: 'error', chunks_total: 3, chunks_failed: 3, error: 'All 3 inference call(s) failed.' });
67
- const failure = report.failures.find(f => f.id === 'deep-analysis');
68
- expect(failure?.title).toBe('Deep analysis did not run');
69
- expect(failure?.details).toContain('All 3 inference call(s) failed.');
70
- });
71
- it('keeps a partial run as PASS/FAIL by findings and records failed chunks', async () => {
72
- mockDeep({ status: 'partial', chunksTotal: 4, chunksFailed: 1 });
73
- const report = await createRunner().run(testDir, undefined, { enabled: true, pro: false });
74
- expect(report.summary['deep-analysis']).toBe('PASS');
75
- expect(report.stats.deep).toMatchObject({ status: 'partial', chunks_total: 4, chunks_failed: 1 });
76
- });
77
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,52 +0,0 @@
1
- import fs from 'fs-extra';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
- import { ContextGate } from './context.js';
6
- import { DependencyGate } from './dependency.js';
7
- import { LogicDriftGate } from './logic-drift.js';
8
- import { StyleDriftGate } from './style-drift.js';
9
- describe('gates on a scoped run', () => {
10
- let cwd;
11
- beforeEach(async () => { cwd = await fs.mkdtemp(path.join(os.tmpdir(), 'rigour-scoped-')); });
12
- afterEach(async () => { await fs.remove(cwd); });
13
- it('context-drift reports only findings that cite a file in scope', async () => {
14
- await fs.outputFile(path.join(cwd, 'src/a.ts'), 'export const a = process.env.API_URL_PROD;\n');
15
- await fs.outputFile(path.join(cwd, 'src/b.ts'), 'export const b = process.env.API_URL_STAGING;\n');
16
- const gate = new ContextGate({ context: { enabled: true } });
17
- const record = { anchors: [{ type: 'env', id: 'API_URL', confidence: 1 }] };
18
- const unscoped = await gate.run({ cwd, record });
19
- const scoped = await gate.run({ cwd, record, patterns: ['src/a.ts'] });
20
- expect(unscoped.flatMap(f => f.files)).toEqual(expect.arrayContaining(['src/a.ts', 'src/b.ts']));
21
- expect(scoped.length).toBeGreaterThan(0);
22
- expect(scoped.every(f => f.files?.includes('src/a.ts'))).toBe(true);
23
- });
24
- it('dependency-guardian checks the manifest only when package.json is in scope', async () => {
25
- await fs.outputJson(path.join(cwd, 'package.json'), { dependencies: { 'left-pad': '1.0.0' } });
26
- await fs.outputFile(path.join(cwd, 'src/a.ts'), "import pad from 'left-pad';\n");
27
- const gate = new DependencyGate({ gates: { dependencies: { forbid: ['left-pad'] } } });
28
- expect(await gate.run({ cwd, patterns: ['src/a.ts'] })).toEqual([]);
29
- const withManifest = await gate.run({ cwd, patterns: ['package.json'] });
30
- expect(withManifest.some(f => f.title === 'Forbidden Dependency')).toBe(true);
31
- });
32
- it('logic-drift never creates or rewrites its baseline from a scoped run', async () => {
33
- const baseline = path.join(cwd, '.rigour/logic-baseline.json');
34
- await fs.outputFile(path.join(cwd, 'src/rules.ts'), 'export function eligible(score: number) { return score >= 10; }\n');
35
- await fs.outputFile(path.join(cwd, 'src/other.ts'), 'export function other(n: number) { return n > 1; }\n');
36
- const gate = new LogicDriftGate();
37
- expect(await gate.run({ cwd, patterns: ['src/rules.ts'] })).toEqual([]);
38
- expect(await fs.pathExists(baseline)).toBe(false);
39
- await gate.run({ cwd });
40
- const before = await fs.readFile(baseline, 'utf-8');
41
- await fs.outputFile(path.join(cwd, 'src/rules.ts'), 'export function eligible(score: number) { return score > 10; }\n');
42
- const scoped = await gate.run({ cwd, patterns: ['src/rules.ts'] });
43
- expect(scoped.some(f => f.details.includes("'>=' to '>'"))).toBe(true);
44
- expect(await fs.readFile(baseline, 'utf-8')).toBe(before);
45
- });
46
- it('style-drift does not create its baseline from a scoped run', async () => {
47
- await fs.outputFile(path.join(cwd, 'src/a.ts'), 'export function doThing() { return 1; }\n');
48
- const gate = new StyleDriftGate();
49
- expect(await gate.run({ cwd, patterns: ['src/a.ts'] })).toEqual([]);
50
- expect(await fs.pathExists(path.join(cwd, '.rigour/style-baseline.json'))).toBe(false);
51
- });
52
- });
@@ -1 +0,0 @@
1
- export {};