@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,77 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import ts from 'typescript';
5
- import { afterEach, describe, expect, it } from 'vitest';
6
- import { forEachNode, symbolOf } from './ast.js';
7
- import { originsOf } from './origins.js';
8
- import { programBatches } from './program.js';
9
- let dir;
10
- afterEach(() => { if (dir)
11
- fs.rmSync(dir, { recursive: true, force: true }); dir = undefined; });
12
- /** Program over `files`; returns the checker and a finder for `probe(<expr>)` arguments in main.ts. */
13
- function setup(files) {
14
- dir = fs.mkdtempSync(path.join(os.tmpdir(), 'origins-'));
15
- for (const [name, body] of Object.entries(files))
16
- fs.writeFileSync(path.join(dir, name), body);
17
- const [program] = [...programBatches([path.join(dir, 'main.ts')], { strict: true, noEmit: true })];
18
- const checker = program.getTypeChecker();
19
- const main = program.getSourceFile(path.join(dir, 'main.ts'));
20
- const probe = () => {
21
- let found;
22
- forEachNode(main, (n) => {
23
- if (ts.isCallExpression(n) && ts.isIdentifier(n.expression) && n.expression.text === 'probe')
24
- found = n.arguments[0];
25
- });
26
- return found;
27
- };
28
- const kinds = () => originsOf(checker, probe()).map(o => o.kind === 'call' ? `call:${o.node.expression.getText()}` : o.kind === 'param' ? `param:${o.index}` : o.kind);
29
- return { kinds };
30
- }
31
- const PRELUDE = 'declare function probe(v: unknown): void;\ndeclare function a(): number;\ndeclare function b(): number;\n';
32
- describe('originsOf', () => {
33
- it('follows const initializers and let reassignments', () => {
34
- const { kinds } = setup({ 'main.ts': `${PRELUDE}let x = a();\nif (Math.random()) x = b();\nconst y = x;\nprobe(y);\n` });
35
- expect(kinds().sort()).toEqual(['call:a', 'call:b']);
36
- });
37
- it('maps an element of Promise.all([...]) to the matching call', async () => {
38
- const { kinds } = setup({ 'main.ts': `${PRELUDE}async function f() {\n const [first, second] = await Promise.all([a(), b()]);\n probe(second);\n return first;\n}\n` });
39
- expect(kinds()).toEqual(['call:b']);
40
- });
41
- it('reads a destructured property from an object literal', () => {
42
- const { kinds } = setup({ 'main.ts': `${PRELUDE}const obj = { left: a(), right: b() };\nconst { right } = obj;\nprobe(right);\n` });
43
- expect(kinds()).toEqual(['call:b']);
44
- });
45
- it('keeps both sides of ?? and of a conditional', () => {
46
- const { kinds } = setup({ 'main.ts': `${PRELUDE}const v = Math.random() > 0.5 ? a() : (b() ?? a());\nprobe(v);\n` });
47
- expect(kinds().sort()).toEqual(['call:a', 'call:a', 'call:b']);
48
- });
49
- it('reports a parameter with its index', () => {
50
- const { kinds } = setup({ 'main.ts': `${PRELUDE}function f(first: number, second: number) {\n probe(second);\n return first;\n}\n` });
51
- expect(kinds()).toEqual(['param:1']);
52
- });
53
- it('follows imports across files to the declaration', () => {
54
- const { kinds } = setup({
55
- 'lib.ts': 'export const shared = Math.max(1, 2);\n',
56
- 'main.ts': `${PRELUDE}import { shared } from './lib';\nprobe(shared);\n`,
57
- });
58
- expect(kinds()).toEqual(['call:Math.max']);
59
- });
60
- it('stays unknown for an import that does not resolve', () => {
61
- const { kinds } = setup({ 'main.ts': `${PRELUDE}import { missing } from './nowhere';\nprobe(missing);\n` });
62
- expect(kinds()).toEqual(['unknown']);
63
- });
64
- });
65
- describe('symbolOf', () => {
66
- it('resolves the name in a shorthand property to the variable it reads', () => {
67
- dir = fs.mkdtempSync(path.join(os.tmpdir(), 'origins-'));
68
- fs.writeFileSync(path.join(dir, 'main.ts'), "const headers = { 'x-token': 't' };\nexport const init = { headers };\n");
69
- const [program] = [...programBatches([path.join(dir, 'main.ts')], { strict: true, noEmit: true })];
70
- const main = program.getSourceFile(path.join(dir, 'main.ts'));
71
- let shorthand;
72
- forEachNode(main, (n) => { if (ts.isShorthandPropertyAssignment(n))
73
- shorthand = n; });
74
- const decl = symbolOf(program.getTypeChecker(), shorthand.name)?.valueDeclaration;
75
- expect(decl && ts.isVariableDeclaration(decl) && decl.name.getText()).toBe('headers');
76
- });
77
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,45 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, describe, expect, it } from 'vitest';
5
- import { ProjectFacts } from './project-facts.js';
6
- let root;
7
- afterEach(() => { if (root)
8
- fs.rmSync(root, { recursive: true, force: true }); root = undefined; });
9
- function write(files) {
10
- root = fs.mkdtempSync(path.join(os.tmpdir(), 'project-facts-'));
11
- for (const [name, text] of Object.entries(files)) {
12
- fs.mkdirSync(path.dirname(path.join(root, name)), { recursive: true });
13
- fs.writeFileSync(path.join(root, name), text);
14
- }
15
- return root;
16
- }
17
- describe('ProjectFacts', () => {
18
- it('reads the nearest package.json, so each monorepo package is judged by its own', () => {
19
- const dir = write({
20
- 'package.json': JSON.stringify({ name: 'root', devDependencies: { vite: '^5.0.0' } }),
21
- 'packages/ui/package.json': JSON.stringify({ name: '@x/ui', peerDependencies: { 'solid-js': '^1.8.0' } }),
22
- 'packages/ui/src/a.tsx': '',
23
- });
24
- const facts = new ProjectFacts(dir);
25
- expect(facts.declares('packages/ui/src/a.tsx', 'solid-js')).toBe(true);
26
- expect(facts.declares('packages/ui/src/a.tsx', 'vite')).toBe(false);
27
- expect(facts.majorVersion('packages/ui/src/a.tsx', 'solid-js')).toBe(1);
28
- expect(facts.packageName('packages/ui/src/a.tsx')).toBe('@x/ui');
29
- expect(facts.packageDir('packages/ui/src/a.tsx')).toBe(path.join(dir, 'packages/ui'));
30
- });
31
- it('never reads a manifest above cwd', () => {
32
- const dir = write({ 'package.json': JSON.stringify({ dependencies: { react: '^19.0.0' } }), 'app/src/a.tsx': '' });
33
- const facts = new ProjectFacts(path.join(dir, 'app'));
34
- expect(facts.dependencies('src/a.tsx').size).toBe(0);
35
- expect(facts.packageDir('src/a.tsx')).toBeUndefined();
36
- });
37
- it('resolves compiler options through tsconfig extends', () => {
38
- const dir = write({
39
- 'tsconfig.base.json': JSON.stringify({ compilerOptions: { stripInternal: true } }),
40
- 'pkg/tsconfig.json': JSON.stringify({ extends: '../tsconfig.base.json' }),
41
- 'pkg/src/a.ts': '',
42
- });
43
- expect(new ProjectFacts(dir).compilerOptions('pkg/src/a.ts').stripInternal).toBe(true);
44
- });
45
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,46 +0,0 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
4
- import { afterEach, describe, expect, it } from 'vitest';
5
- import { exportCallSites } from './export.js';
6
- let dir;
7
- afterEach(() => { if (dir)
8
- fs.rmSync(dir, { recursive: true, force: true }); dir = undefined; });
9
- function sites(code) {
10
- dir = fs.mkdtempSync(path.join(os.tmpdir(), 'call-sites-'));
11
- fs.writeFileSync(path.join(dir, 'main.ts'), code);
12
- return exportCallSites(dir, ['main.ts']).map(s => [s.function, s.callee, s.ordinal, s.handledBy]);
13
- }
14
- const DECLS = 'declare function a(): Promise<number>;\ndeclare function b(): Promise<number>;\n';
15
- describe('findCallSites', () => {
16
- it('reports awaited calls and says how each handles failure', () => {
17
- expect(sites(`${DECLS}
18
- export async function load() {
19
- const x = await a();
20
- try { await b(); } catch { return 0; }
21
- const y = await a().catch(() => 0);
22
- return x + y;
23
- }`)).toEqual([
24
- ['load', 'a', 0, null],
25
- ['load', 'b', 0, 'try'],
26
- ['load', 'a', 1, 'call'],
27
- ]);
28
- });
29
- it('treats each element of Promise.all as a site, and allSettled as handled', () => {
30
- expect(sites(`${DECLS}
31
- export async function both() {
32
- const [x, y] = await Promise.all([a(), b()]);
33
- const settled = await Promise.allSettled([a()]);
34
- return [x, y, settled];
35
- }`)).toEqual([
36
- ['both', 'a', 0, null],
37
- ['both', 'b', 0, null],
38
- ['both', 'a', 1, 'all-settled'],
39
- ]);
40
- });
41
- it('counts a callee that catches and returns as handled', () => {
42
- expect(sites(`${DECLS}
43
- async function safeA() { try { return await a(); } catch { return 0; } }
44
- export async function use() { return await safeA(); }`)).toContainEqual(['use', 'safeA', 0, 'call']);
45
- });
46
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,53 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { recordGateRun, getQualityTrend, clearAdaptiveHistory, } from './adaptive-thresholds.js';
3
- import * as fs from 'fs';
4
- import * as path from 'path';
5
- import * as os from 'os';
6
- describe('AdaptiveThresholds', () => {
7
- let testDir;
8
- beforeEach(() => {
9
- testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adaptive-test-'));
10
- });
11
- afterEach(() => {
12
- clearAdaptiveHistory(testDir);
13
- fs.rmSync(testDir, { recursive: true, force: true });
14
- });
15
- describe('historical tracking', () => {
16
- it('should record gate runs', () => {
17
- recordGateRun(testDir, 5, 2, 10);
18
- recordGateRun(testDir, 6, 1, 5);
19
- const historyPath = path.join(testDir, '.rigour', 'adaptive-history.json');
20
- expect(fs.existsSync(historyPath)).toBe(true);
21
- const history = JSON.parse(fs.readFileSync(historyPath, 'utf-8'));
22
- expect(history.runs).toHaveLength(2);
23
- });
24
- it('should return stable trend for new projects', () => {
25
- const trend = getQualityTrend(testDir);
26
- expect(trend).toBe('stable');
27
- });
28
- it('should detect improving trend', () => {
29
- // Baseline: 15 runs with high failures (with variance for valid std dev)
30
- for (let i = 0; i < 15; i++) {
31
- recordGateRun(testDir, 3, 5, 15 + (i % 5) * 3); // 15,18,21,24,27 repeating
32
- }
33
- // Recent: 5 runs with very low failures (clear improvement)
34
- for (let i = 0; i < 5; i++) {
35
- recordGateRun(testDir, 7, 0, 1);
36
- }
37
- const trend = getQualityTrend(testDir);
38
- expect(trend).toBe('improving');
39
- });
40
- it('should detect degrading trend', () => {
41
- // Baseline: 15 runs with low failures (with variance for valid std dev)
42
- for (let i = 0; i < 15; i++) {
43
- recordGateRun(testDir, 7, 1, 1 + (i % 3)); // 1,2,3 repeating
44
- }
45
- // Recent: 5 runs with high failures (clear degradation)
46
- for (let i = 0; i < 5; i++) {
47
- recordGateRun(testDir, 3, 5, 25);
48
- }
49
- const trend = getQualityTrend(testDir);
50
- expect(trend).toBe('degrading');
51
- });
52
- });
53
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,69 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { buildAgentRuns, normalizeAgentEvent, normalizeAgentEvents } from './agent-history.js';
3
- describe('agent history', () => {
4
- it('normalizes incomplete historical records without dropping them', () => {
5
- const event = normalizeAgentEvent({ type: 'tool_error', arguments: { files: ['src/a.ts'] } });
6
- expect(event.agentId).toBe('unknown-agent');
7
- expect(event.outcome).toBe('error');
8
- expect(event.files).toEqual(['src/a.ts']);
9
- });
10
- it('groups events into stable runs and retains outcomes', () => {
11
- const events = [
12
- normalizeAgentEvent({ id: '1', sessionId: 's1', agentId: 'a1', timestamp: '2026-01-01T00:00:00Z', tool: 'read' }),
13
- normalizeAgentEvent({ id: '2', sessionId: 's1', agentId: 'a1', timestamp: '2026-01-01T00:01:00Z', type: 'completed', files: ['src/a.ts'] }),
14
- ];
15
- expect(buildAgentRuns(events)).toMatchObject([{ id: 's1', eventCount: 2, status: 'success', files: ['src/a.ts'] }]);
16
- });
17
- it('normalizes guidance safely and builds an honest impact receipt', () => {
18
- const events = [normalizeAgentEvent({
19
- id: 'response-1', requestId: 'request-1', agentId: 'agent-1', timestamp: '2026-01-01T00:00:00Z',
20
- type: 'tool_response', status: 'success',
21
- guidance: {
22
- kind: 'context-scope',
23
- recommendation: 'Read only the two evidence-backed files.',
24
- patternRefs: [{ id: 'p1', label: 'withTransaction' }, { bad: true }],
25
- lessonRefs: [{ id: 'l1', label: 'Bound retries' }],
26
- selectedFiles: ['src/a.ts', 42],
27
- excludedFileCount: 18,
28
- },
29
- telemetry: {
30
- candidateTokens: 2400,
31
- returnedTokens: 400,
32
- candidateFiles: 20,
33
- returnedFiles: 2,
34
- cacheStatus: 'exact-hit',
35
- classification: 'measured estimate',
36
- },
37
- })];
38
- expect(events[0].guidance?.selectedFiles).toEqual(['src/a.ts']);
39
- expect(buildAgentRuns(events)[0].impact).toMatchObject({
40
- guidanceCount: 1,
41
- knowledgeItems: 2,
42
- avoidedTokens: 2000,
43
- excludedFiles: 18,
44
- cacheHits: 1,
45
- });
46
- });
47
- it('ignores malformed guidance rather than breaking legacy history', () => {
48
- const event = normalizeAgentEvent({ guidance: { kind: 'context-scope', recommendation: 42 }, telemetry: 'bad' });
49
- expect(event.guidance).toBeUndefined();
50
- expect(event.telemetry).toBeUndefined();
51
- });
52
- });
53
- describe('normalizeAgentEvents', () => {
54
- it('carries request identity into the matching response', () => {
55
- const events = normalizeAgentEvents([
56
- {
57
- type: 'tool_call', requestId: 'request-1', tool: 'rigour_checkpoint',
58
- timestamp: '2026-09-10T00:00:00Z',
59
- arguments: { agentId: 'agent-a', taskId: 'task-a', filesChanged: ['src/a.ts'] },
60
- },
61
- {
62
- type: 'tool_response', requestId: 'request-1', tool: 'rigour_checkpoint', status: 'success',
63
- timestamp: '2026-09-10T00:00:01Z',
64
- },
65
- ]);
66
- expect(events[1]).toMatchObject({ agentId: 'agent-a', taskId: 'task-a', files: ['src/a.ts'] });
67
- expect(buildAgentRuns(events)).toHaveLength(1);
68
- });
69
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +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 { getContextScopeSummary } from './context-telemetry-service.js';
6
- let root;
7
- beforeEach(() => { root = fs.mkdtempSync(path.join(os.tmpdir(), 'scope-summary-')); });
8
- afterEach(() => fs.rmSync(root, { recursive: true, force: true }));
9
- describe('getContextScopeSummary', () => {
10
- it('counts rule files and skips a rules directory such as .clinerules/', async () => {
11
- fs.mkdirSync(path.join(root, '.clinerules'));
12
- fs.writeFileSync(path.join(root, '.clinerules', 'rigour.md'), 'rules');
13
- fs.writeFileSync(path.join(root, 'CLAUDE.md'), 'Use small PRs.');
14
- const summary = await getContextScopeSummary(root);
15
- expect(summary.alwaysOnRuleTokens).toBeGreaterThan(0);
16
- });
17
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,182 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import path from 'path';
3
- import os from 'os';
4
- import fs from 'fs-extra';
5
- vi.mock('../storage/db.js', () => ({
6
- isSQLiteAvailable: () => false,
7
- openDatabase: async () => null,
8
- DB_PATH: '/tmp/rigour-test.db',
9
- RIGOUR_DIR: '/tmp/.rigour',
10
- }));
11
- import { getTaskContextStats, getTaskCostStats, getCacheStats, importCursorUsageCsv, importCursorUsageJson, getContextScopeSummary, getCheckpointSummary, estimateTokenCount, } from './context-telemetry-service.js';
12
- import { recordContextEvent, recordCheckpointMetric } from '../storage/context-telemetry.js';
13
- describe('context-telemetry-service', () => {
14
- const testCwd = path.join(os.tmpdir(), `rigour-ctx-service-${Date.now()}-${Math.random().toString(36).slice(2)}`);
15
- const taskId = `task-${Date.now()}`;
16
- beforeEach(async () => {
17
- await fs.ensureDir(path.join(testCwd, '.rigour'));
18
- });
19
- afterEach(async () => {
20
- await fs.remove(testCwd);
21
- });
22
- it('returns zeroed stats when no telemetry exists for task', async () => {
23
- const stats = await getTaskContextStats(taskId, testCwd);
24
- expect(stats.retrievals).toBe(0);
25
- expect(stats.candidateTokens).toBe(0);
26
- expect(stats.potentialAvoidedTokens).toBe(0);
27
- expect(stats.isEstimated).toBe(true);
28
- });
29
- it('calculates avoided context from recorded events', async () => {
30
- await recordContextEvent({
31
- taskId,
32
- toolName: 'rigour_check_pattern',
33
- cacheStatus: 'exact-hit',
34
- candidateTokens: 10000,
35
- returnedTokens: 2000,
36
- deduplicatedTokens: 3000,
37
- }, testCwd);
38
- const stats = await getTaskContextStats(taskId, testCwd);
39
- expect(stats.retrievals).toBe(1);
40
- expect(stats.potentialAvoidedTokens).toBe(8000);
41
- expect(stats.repeatedReadsPrevented).toBeGreaterThan(0);
42
- expect(stats.deduplicatedTokens).toBe(3000);
43
- expect(stats.isEstimated).toBe(false);
44
- });
45
- it('aggregates cache performance from events', async () => {
46
- const cacheTaskId = `${taskId}-cache`;
47
- await recordContextEvent({
48
- taskId: cacheTaskId,
49
- toolName: 'rigour_recall',
50
- cacheStatus: 'exact-hit',
51
- candidateTokens: 1000,
52
- returnedTokens: 200,
53
- }, testCwd);
54
- await recordContextEvent({
55
- taskId: cacheTaskId,
56
- toolName: 'rigour_context_explain',
57
- cacheStatus: 'miss',
58
- candidateTokens: 500,
59
- returnedTokens: 500,
60
- }, testCwd);
61
- const events = await import('../storage/context-telemetry.js').then(m => m.getContextEvents(cacheTaskId, testCwd));
62
- const cache = await getCacheStats(testCwd);
63
- const taskHits = events.filter(e => e.cacheStatus === 'exact-hit').length;
64
- const taskMisses = events.filter(e => e.cacheStatus === 'miss').length;
65
- expect(taskHits).toBe(1);
66
- expect(taskMisses).toBe(1);
67
- expect(cache.hitRate).toBe(0.5);
68
- expect(cache.isEstimated).toBe(false);
69
- });
70
- it('imports CSV usage and marks cost stats as observed', async () => {
71
- const csv = `Date,Model,Input Tokens,Output Tokens,Cost
72
- 2026-08-05,claude-3-5-sonnet,510000,62000,4.83`;
73
- const imported = await importCursorUsageCsv(csv, testCwd);
74
- expect(imported).toBe(1);
75
- const cost = await getTaskCostStats('cursor-imported', testCwd);
76
- expect(cost.actual.inputTokens).toBe(510000);
77
- expect(cost.actual.costUsd).toBe(4.83);
78
- expect(cost.actual.isEstimated).toBe(false);
79
- expect(cost.actual.classification).toBe('observed');
80
- });
81
- it('deduplicates CSV rows on re-import', async () => {
82
- const csv = `Date,Model,Input Tokens,Output Tokens,Cost
83
- 2026-08-05,claude-3-5-sonnet,1000,100,1.00`;
84
- expect(await importCursorUsageCsv(csv, testCwd)).toBe(1);
85
- expect(await importCursorUsageCsv(csv, testCwd)).toBe(0);
86
- });
87
- it('imports JSON usage records', async () => {
88
- const jsonTaskId = `${taskId}-json-${Math.random().toString(36).slice(2)}`;
89
- const imported = await importCursorUsageJson([{
90
- taskId: jsonTaskId,
91
- inputTokens: 2500,
92
- outputTokens: 300,
93
- observedCostUsd: 0.42,
94
- model: 'gpt-4o',
95
- }], testCwd);
96
- expect(imported).toBe(1);
97
- const cost = await getTaskCostStats(jsonTaskId, testCwd);
98
- expect(cost.actual.inputTokens).toBe(2500);
99
- });
100
- it('imports Admin API JSON events with chargedCents and dedupes against sync IDs', async () => {
101
- const adminEvent = {
102
- timestamp: '1750979225854',
103
- conversationId: 'conv-dedupe',
104
- model: 'composer-2.5-standard',
105
- chargedCents: 42.5,
106
- tokenUsage: { inputTokens: 100, outputTokens: 50 },
107
- };
108
- expect(await importCursorUsageJson([adminEvent], testCwd)).toBe(1);
109
- expect(await importCursorUsageJson([adminEvent], testCwd)).toBe(0);
110
- const cost = await getTaskCostStats('conv-dedupe', testCwd);
111
- expect(cost.actual.costUsd).toBeCloseTo(0.425, 3);
112
- expect(cost.actual.isEstimated).toBe(false);
113
- });
114
- it('summarizes agent scope overlap from session file', async () => {
115
- await fs.writeJson(path.join(testCwd, '.rigour', 'agent-session.json'), {
116
- agents: [
117
- { agentId: 'agent-a', taskScope: ['src/api/**'] },
118
- { agentId: 'agent-b', taskScope: ['src/api/**', 'tests/**'] },
119
- ],
120
- });
121
- const scope = await getContextScopeSummary(testCwd);
122
- expect(scope.activeAgentCount).toBe(2);
123
- expect(scope.overlappingScopesResolved).toBeGreaterThan(0);
124
- });
125
- it('estimates governance rule token overhead from AGENTS.md', async () => {
126
- await fs.writeFile(path.join(testCwd, 'AGENTS.md'), '# Agent rules\n'.repeat(40));
127
- const scope = await getContextScopeSummary(testCwd);
128
- expect(scope.alwaysOnRuleTokens).toBe(estimateTokenCount('# Agent rules\n'.repeat(40)));
129
- });
130
- it('aggregates checkpoint compression metrics', async () => {
131
- const cpTaskId = `${taskId}-cp`;
132
- await recordCheckpointMetric({
133
- checkpointId: `checkpoint:${cpTaskId}:a1:phase`,
134
- taskId: cpTaskId,
135
- agentId: 'a1',
136
- rawStateTokens: 10000,
137
- checkpointTokens: 500,
138
- replayTokensAvoided: 9500,
139
- }, testCwd);
140
- const summary = await getCheckpointSummary(cpTaskId, testCwd);
141
- expect(summary.checkpointCount).toBe(1);
142
- expect(summary.rawStateTokens).toBe(10000);
143
- expect(summary.compressionRatio).toBe(20);
144
- expect(summary.replayTokensAvoided).toBe(9500);
145
- });
146
- it('marks observed cost from usages and estimates avoided cost by model', async () => {
147
- const jsonTaskId = `${taskId}-composer-${Math.random().toString(36).slice(2)}`;
148
- await importCursorUsageJson([{
149
- id: `json-composer-${jsonTaskId}`,
150
- taskId: jsonTaskId,
151
- inputTokens: 2_000_000,
152
- outputTokens: 0,
153
- observedCostUsd: 1.25,
154
- model: 'composer-2.5-standard',
155
- source: 'cursor-admin-api',
156
- }], testCwd);
157
- await recordContextEvent({
158
- taskId: jsonTaskId,
159
- toolName: 'rigour_context_scope',
160
- cacheStatus: 'miss',
161
- candidateTokens: 3_000_000,
162
- returnedTokens: 1_000_000,
163
- }, testCwd);
164
- const cost = await getTaskCostStats(jsonTaskId, testCwd);
165
- expect(cost.actual.isEstimated).toBe(false);
166
- expect(cost.actual.costUsd).toBe(1.25);
167
- expect(cost.estimated.isEstimated).toBe(true);
168
- expect(cost.estimated.inputPricePerMillionUsd).toBe(0.5);
169
- expect(cost.estimated.estimatedCostAvoidedUsd).toBeGreaterThan(0);
170
- });
171
- it('does not combine retrieval and checkpoint counterfactuals', async () => {
172
- const id = `${taskId}-separate-${Math.random().toString(36).slice(2)}`;
173
- await recordContextEvent({ taskId: id, toolName: 'rigour_context_scope', cacheStatus: 'miss', candidateTokens: 5000, returnedTokens: 1000 }, testCwd);
174
- await recordCheckpointMetric({ checkpointId: `${id}-cp`, taskId: id, agentId: 'a1', rawStateTokens: 9000, checkpointTokens: 1000, replayTokensAvoided: 8000 }, testCwd);
175
- const cost = await getTaskCostStats(id, testCwd);
176
- expect(cost.estimated.retrievalAvoidedTokens).toBe(4000);
177
- expect(cost.estimated.checkpointReplayAvoidedTokens).toBe(8000);
178
- expect(cost.estimated.potentialContextAvoided).toBe(4000);
179
- expect(cost.estimated.categoriesAreAdditive).toBe(false);
180
- expect(cost.estimated.retrievalAvoidedCostRangeUsd?.max).toBeGreaterThan(cost.estimated.retrievalAvoidedCostRangeUsd?.min ?? 0);
181
- });
182
- });
@@ -1 +0,0 @@
1
- export {};