@vibecheckai/cli 3.4.0 → 3.5.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 (228) hide show
  1. package/bin/registry.js +154 -338
  2. package/bin/runners/context/generators/mcp.js +13 -15
  3. package/bin/runners/context/proof-context.js +1 -248
  4. package/bin/runners/lib/analysis-core.js +180 -198
  5. package/bin/runners/lib/analyzers.js +223 -1669
  6. package/bin/runners/lib/cli-output.js +210 -242
  7. package/bin/runners/lib/detectors-v2.js +785 -547
  8. package/bin/runners/lib/entitlements-v2.js +458 -96
  9. package/bin/runners/lib/error-handler.js +9 -16
  10. package/bin/runners/lib/global-flags.js +0 -37
  11. package/bin/runners/lib/route-truth.js +322 -1167
  12. package/bin/runners/lib/scan-output.js +469 -448
  13. package/bin/runners/lib/ship-output.js +27 -280
  14. package/bin/runners/lib/terminal-ui.js +733 -231
  15. package/bin/runners/lib/truth.js +321 -1004
  16. package/bin/runners/lib/unified-output.js +158 -162
  17. package/bin/runners/lib/upsell.js +204 -104
  18. package/bin/runners/runAllowlist.js +324 -0
  19. package/bin/runners/runAuth.js +95 -324
  20. package/bin/runners/runCheckpoint.js +21 -39
  21. package/bin/runners/runContext.js +24 -136
  22. package/bin/runners/runDoctor.js +67 -115
  23. package/bin/runners/runEvidencePack.js +219 -0
  24. package/bin/runners/runFix.js +5 -6
  25. package/bin/runners/runGuard.js +118 -212
  26. package/bin/runners/runInit.js +2 -14
  27. package/bin/runners/runInstall.js +281 -0
  28. package/bin/runners/runLabs.js +341 -0
  29. package/bin/runners/runMcp.js +52 -130
  30. package/bin/runners/runPolish.js +20 -43
  31. package/bin/runners/runProve.js +3 -13
  32. package/bin/runners/runReality.js +0 -14
  33. package/bin/runners/runReport.js +2 -3
  34. package/bin/runners/runScan.js +44 -511
  35. package/bin/runners/runShip.js +14 -28
  36. package/bin/runners/runValidate.js +2 -19
  37. package/bin/runners/runWatch.js +54 -118
  38. package/bin/vibecheck.js +41 -148
  39. package/mcp-server/ARCHITECTURE.md +339 -0
  40. package/mcp-server/__tests__/cache.test.ts +313 -0
  41. package/mcp-server/__tests__/executor.test.ts +239 -0
  42. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
  43. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
  44. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
  45. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
  46. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
  47. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
  48. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
  49. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
  50. package/mcp-server/__tests__/ids.test.ts +345 -0
  51. package/mcp-server/__tests__/integration/tools.test.ts +410 -0
  52. package/mcp-server/__tests__/registry.test.ts +365 -0
  53. package/mcp-server/__tests__/sandbox.test.ts +323 -0
  54. package/mcp-server/__tests__/schemas.test.ts +372 -0
  55. package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
  56. package/mcp-server/examples/doctor.request.json +14 -0
  57. package/mcp-server/examples/doctor.response.json +53 -0
  58. package/mcp-server/examples/error.response.json +15 -0
  59. package/mcp-server/examples/scan.request.json +14 -0
  60. package/mcp-server/examples/scan.response.json +108 -0
  61. package/mcp-server/handlers/tool-handler.ts +671 -0
  62. package/mcp-server/index-v3.ts +293 -0
  63. package/mcp-server/index.js +1072 -1573
  64. package/mcp-server/index.old.js +4137 -0
  65. package/mcp-server/lib/cache.ts +341 -0
  66. package/mcp-server/lib/errors.ts +346 -0
  67. package/mcp-server/lib/executor.ts +792 -0
  68. package/mcp-server/lib/ids.ts +238 -0
  69. package/mcp-server/lib/logger.ts +368 -0
  70. package/mcp-server/lib/metrics.ts +365 -0
  71. package/mcp-server/lib/sandbox.ts +337 -0
  72. package/mcp-server/lib/validator.ts +229 -0
  73. package/mcp-server/package-lock.json +165 -0
  74. package/mcp-server/package.json +32 -7
  75. package/mcp-server/premium-tools.js +2 -2
  76. package/mcp-server/registry/tools.json +476 -0
  77. package/mcp-server/schemas/error-envelope.schema.json +125 -0
  78. package/mcp-server/schemas/finding.schema.json +167 -0
  79. package/mcp-server/schemas/report-artifact.schema.json +88 -0
  80. package/mcp-server/schemas/run-request.schema.json +75 -0
  81. package/mcp-server/schemas/verdict.schema.json +168 -0
  82. package/mcp-server/tier-auth.d.ts +71 -0
  83. package/mcp-server/tier-auth.js +371 -183
  84. package/mcp-server/truth-context.js +90 -131
  85. package/mcp-server/truth-firewall-tools.js +1000 -1611
  86. package/mcp-server/tsconfig.json +34 -0
  87. package/mcp-server/vibecheck-tools.js +2 -2
  88. package/mcp-server/vitest.config.ts +16 -0
  89. package/package.json +3 -4
  90. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
  91. package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
  92. package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
  93. package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
  94. package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
  95. package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
  96. package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
  97. package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
  98. package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
  99. package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
  100. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
  101. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
  102. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
  103. package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
  104. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
  105. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
  106. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
  107. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
  108. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
  109. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
  110. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
  111. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
  112. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
  113. package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
  114. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
  115. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
  116. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
  117. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
  118. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
  119. package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
  120. package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
  121. package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
  122. package/bin/runners/lib/agent-firewall/logger.js +0 -141
  123. package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
  124. package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
  125. package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
  126. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
  127. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
  128. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
  129. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
  130. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
  131. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
  132. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
  133. package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
  134. package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
  135. package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
  136. package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
  137. package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
  138. package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
  139. package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
  140. package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
  141. package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
  142. package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
  143. package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
  144. package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
  145. package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
  146. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
  147. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
  148. package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
  149. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
  150. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
  151. package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
  152. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
  153. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
  154. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
  155. package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
  156. package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
  157. package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
  158. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
  159. package/bin/runners/lib/api-client.js +0 -269
  160. package/bin/runners/lib/authority-badge.js +0 -425
  161. package/bin/runners/lib/engines/accessibility-engine.js +0 -190
  162. package/bin/runners/lib/engines/api-consistency-engine.js +0 -162
  163. package/bin/runners/lib/engines/ast-cache.js +0 -99
  164. package/bin/runners/lib/engines/code-quality-engine.js +0 -255
  165. package/bin/runners/lib/engines/console-logs-engine.js +0 -115
  166. package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -268
  167. package/bin/runners/lib/engines/dead-code-engine.js +0 -198
  168. package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
  169. package/bin/runners/lib/engines/empty-catch-engine.js +0 -150
  170. package/bin/runners/lib/engines/file-filter.js +0 -131
  171. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
  172. package/bin/runners/lib/engines/mock-data-engine.js +0 -272
  173. package/bin/runners/lib/engines/parallel-processor.js +0 -71
  174. package/bin/runners/lib/engines/performance-issues-engine.js +0 -265
  175. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -243
  176. package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
  177. package/bin/runners/lib/engines/type-aware-engine.js +0 -152
  178. package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
  179. package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
  180. package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -15
  181. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
  182. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
  183. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
  184. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
  185. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
  186. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
  187. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
  188. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -139
  189. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
  190. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
  191. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
  192. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
  193. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
  194. package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
  195. package/bin/runners/lib/exit-codes.js +0 -275
  196. package/bin/runners/lib/fingerprint.js +0 -377
  197. package/bin/runners/lib/help-formatter.js +0 -413
  198. package/bin/runners/lib/logger.js +0 -38
  199. package/bin/runners/lib/ship-output-enterprise.js +0 -239
  200. package/bin/runners/lib/unified-cli-output.js +0 -604
  201. package/bin/runners/runAgent.d.ts +0 -5
  202. package/bin/runners/runAgent.js +0 -161
  203. package/bin/runners/runApprove.js +0 -1200
  204. package/bin/runners/runClassify.js +0 -859
  205. package/bin/runners/runContext.d.ts +0 -4
  206. package/bin/runners/runFirewall.d.ts +0 -5
  207. package/bin/runners/runFirewall.js +0 -134
  208. package/bin/runners/runFirewallHook.d.ts +0 -5
  209. package/bin/runners/runFirewallHook.js +0 -56
  210. package/bin/runners/runPolish.d.ts +0 -4
  211. package/bin/runners/runProof.zip +0 -0
  212. package/bin/runners/runTruth.d.ts +0 -5
  213. package/bin/runners/runTruth.js +0 -101
  214. package/mcp-server/HARDENING_SUMMARY.md +0 -299
  215. package/mcp-server/agent-firewall-interceptor.js +0 -500
  216. package/mcp-server/authority-tools.js +0 -569
  217. package/mcp-server/conductor/conflict-resolver.js +0 -588
  218. package/mcp-server/conductor/execution-planner.js +0 -544
  219. package/mcp-server/conductor/index.js +0 -377
  220. package/mcp-server/conductor/lock-manager.js +0 -615
  221. package/mcp-server/conductor/request-queue.js +0 -550
  222. package/mcp-server/conductor/session-manager.js +0 -500
  223. package/mcp-server/conductor/tools.js +0 -510
  224. package/mcp-server/lib/api-client.cjs +0 -13
  225. package/mcp-server/lib/logger.cjs +0 -30
  226. package/mcp-server/logger.js +0 -173
  227. package/mcp-server/tools-v3.js +0 -706
  228. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
@@ -1,200 +0,0 @@
1
- /**
2
- * Change Packet Store
3
- *
4
- * Stores change packets in .vibecheck/packets/YYYY-MM-DD/<hash>.json
5
- * Provides querying capabilities by agent, date, verdict.
6
- */
7
-
8
- "use strict";
9
-
10
- const fs = require("fs");
11
- const path = require("path");
12
-
13
- /**
14
- * Store a change packet to disk
15
- * @param {string} projectRoot - Project root directory
16
- * @param {object} packet - Change packet to store
17
- * @returns {string} Path where packet was stored
18
- */
19
- function storePacket(projectRoot, packet) {
20
- const packetsDir = path.join(projectRoot, ".vibecheck", "packets");
21
-
22
- // Create date-based directory
23
- const date = new Date(packet.timestamp);
24
- const dateDir = date.toISOString().split('T')[0]; // YYYY-MM-DD
25
- const dayDir = path.join(packetsDir, dateDir);
26
-
27
- // Ensure directory exists
28
- if (!fs.existsSync(dayDir)) {
29
- fs.mkdirSync(dayDir, { recursive: true });
30
- }
31
-
32
- // Write packet file
33
- const packetPath = path.join(dayDir, `${packet.id}.json`);
34
- fs.writeFileSync(packetPath, JSON.stringify(packet, null, 2));
35
-
36
- return packetPath;
37
- }
38
-
39
- /**
40
- * Load a change packet by ID
41
- * @param {string} projectRoot - Project root directory
42
- * @param {string} packetId - Packet ID
43
- * @returns {object|null} Change packet or null if not found
44
- */
45
- function loadPacket(projectRoot, packetId) {
46
- const packetsDir = path.join(projectRoot, ".vibecheck", "packets");
47
-
48
- // Search all date directories
49
- if (!fs.existsSync(packetsDir)) {
50
- return null;
51
- }
52
-
53
- const dateDirs = fs.readdirSync(packetsDir, { withFileTypes: true })
54
- .filter(dirent => dirent.isDirectory())
55
- .map(dirent => dirent.name);
56
-
57
- for (const dateDir of dateDirs) {
58
- const dayDir = path.join(packetsDir, dateDir);
59
- const packetPath = path.join(dayDir, `${packetId}.json`);
60
-
61
- if (fs.existsSync(packetPath)) {
62
- return JSON.parse(fs.readFileSync(packetPath, "utf8"));
63
- }
64
- }
65
-
66
- return null;
67
- }
68
-
69
- /**
70
- * Query change packets
71
- * @param {string} projectRoot - Project root directory
72
- * @param {object} filters - Query filters
73
- * @param {string} filters.agentId - Filter by agent ID
74
- * @param {string} filters.date - Filter by date (YYYY-MM-DD)
75
- * @param {string} filters.verdict - Filter by verdict (ALLOW, WARN, BLOCK)
76
- * @param {number} filters.limit - Maximum number of results
77
- * @returns {array} Array of change packets
78
- */
79
- function queryPackets(projectRoot, filters = {}) {
80
- const packetsDir = path.join(projectRoot, ".vibecheck", "packets");
81
-
82
- if (!fs.existsSync(packetsDir)) {
83
- return [];
84
- }
85
-
86
- const results = [];
87
- const { agentId, date, verdict, limit } = filters;
88
-
89
- // Determine which date directories to search
90
- const dateDirs = date
91
- ? [date]
92
- : fs.readdirSync(packetsDir, { withFileTypes: true })
93
- .filter(dirent => dirent.isDirectory())
94
- .map(dirent => dirent.name)
95
- .sort()
96
- .reverse(); // Most recent first
97
-
98
- for (const dateDir of dateDirs) {
99
- const dayDir = path.join(packetsDir, dateDir);
100
-
101
- if (!fs.existsSync(dayDir)) continue;
102
-
103
- const packetFiles = fs.readdirSync(dayDir)
104
- .filter(file => file.endsWith('.json'))
105
- .map(file => path.join(dayDir, file));
106
-
107
- for (const packetPath of packetFiles) {
108
- try {
109
- const packet = JSON.parse(fs.readFileSync(packetPath, "utf8"));
110
-
111
- // Apply filters
112
- if (agentId && packet.agentId !== agentId) continue;
113
- if (verdict && packet.verdict?.decision !== verdict) continue;
114
-
115
- results.push(packet);
116
-
117
- // Apply limit
118
- if (limit && results.length >= limit) {
119
- return results;
120
- }
121
- } catch (error) {
122
- // Skip invalid packets
123
- continue;
124
- }
125
- }
126
-
127
- // If we have a date filter, we only need to check that one directory
128
- if (date) break;
129
- }
130
-
131
- return results;
132
- }
133
-
134
- /**
135
- * Get statistics about stored packets
136
- * @param {string} projectRoot - Project root directory
137
- * @returns {object} Statistics
138
- */
139
- function getPacketStats(projectRoot) {
140
- const packetsDir = path.join(projectRoot, ".vibecheck", "packets");
141
-
142
- if (!fs.existsSync(packetsDir)) {
143
- return {
144
- total: 0,
145
- byAgent: {},
146
- byVerdict: { ALLOW: 0, WARN: 0, BLOCK: 0 },
147
- byDate: {}
148
- };
149
- }
150
-
151
- const stats = {
152
- total: 0,
153
- byAgent: {},
154
- byVerdict: { ALLOW: 0, WARN: 0, BLOCK: 0 },
155
- byDate: {}
156
- };
157
-
158
- const dateDirs = fs.readdirSync(packetsDir, { withFileTypes: true })
159
- .filter(dirent => dirent.isDirectory())
160
- .map(dirent => dirent.name);
161
-
162
- for (const dateDir of dateDirs) {
163
- const dayDir = path.join(packetsDir, dateDir);
164
- if (!fs.existsSync(dayDir)) continue;
165
-
166
- const packetFiles = fs.readdirSync(dayDir)
167
- .filter(file => file.endsWith('.json'));
168
-
169
- stats.byDate[dateDir] = packetFiles.length;
170
-
171
- for (const file of packetFiles) {
172
- try {
173
- const packet = JSON.parse(
174
- fs.readFileSync(path.join(dayDir, file), "utf8")
175
- );
176
-
177
- stats.total++;
178
-
179
- // Count by agent
180
- stats.byAgent[packet.agentId] = (stats.byAgent[packet.agentId] || 0) + 1;
181
-
182
- // Count by verdict
183
- const verdict = packet.verdict?.decision || "ALLOW";
184
- stats.byVerdict[verdict] = (stats.byVerdict[verdict] || 0) + 1;
185
- } catch (error) {
186
- // Skip invalid packets
187
- continue;
188
- }
189
- }
190
- }
191
-
192
- return stats;
193
- }
194
-
195
- module.exports = {
196
- storePacket,
197
- loadPacket,
198
- queryPackets,
199
- getPacketStats
200
- };
@@ -1,21 +0,0 @@
1
- /**
2
- * Claim Types
3
- *
4
- * Enumeration of claim types and criticality levels.
5
- */
6
-
7
- module.exports = {
8
- CLAIM_TYPES: {
9
- ROUTE: "route",
10
- ENV: "env_used",
11
- AUTH: "auth_boundary",
12
- CONTRACT: "data_contract",
13
- HTTP_CALL: "http_call",
14
- UI_SUCCESS: "ui_success_claim",
15
- SIDE_EFFECT: "side_effect"
16
- },
17
- CRITICALITY: {
18
- HARD: "hard",
19
- SOFT: "soft"
20
- }
21
- };
@@ -1,303 +0,0 @@
1
- /**
2
- * Claim Extractor
3
- *
4
- * Extracts "drift-causing claims" from changed files.
5
- * Uses AST-based extraction with Babel parser.
6
- */
7
-
8
- const fs = require("fs");
9
- const path = require("path");
10
- const parser = require("@babel/parser");
11
- const traverse = require("@babel/traverse").default;
12
- const t = require("@babel/types");
13
- const { CLAIM_TYPES, CRITICALITY } = require("./claim-types");
14
- const { ROUTE_LIKE, AUTH_HINTS, SUCCESS_UI } = require("./patterns");
15
- const { shouldIgnore } = require("../utils/ignore-checker");
16
-
17
- function parse(code) {
18
- return parser.parse(code, {
19
- sourceType: "unambiguous",
20
- plugins: ["typescript", "jsx"]
21
- });
22
- }
23
-
24
- function locPtr(fileRel, node) {
25
- const loc = node && node.loc;
26
- if (!loc) return null;
27
- return `${fileRel}:${loc.start.line}-${loc.end.line}`;
28
- }
29
-
30
- function pushClaim(out, claim) {
31
- const key = `${claim.type}|${claim.value}|${claim.pointer || ""}`;
32
- if (!out._dedupe.has(key)) {
33
- out._dedupe.add(key);
34
- out.claims.push(claim);
35
- }
36
- }
37
-
38
- function extractStringLiterals(code) {
39
- // Cheap scan for route-ish strings even if AST misses template parts.
40
- // Exclude import paths (from './api/...' or from '../api/...')
41
- const hits = [];
42
- const lines = code.split('\n');
43
-
44
- for (let i = 0; i < lines.length; i++) {
45
- const line = lines[i];
46
-
47
- // Skip import/require statements to avoid false positives
48
- if (/^\s*(import|export|require)\s+.*from\s+['"]/.test(line) ||
49
- /^\s*const\s+\w+\s*=\s*require\(/.test(line)) {
50
- continue;
51
- }
52
-
53
- // Check for route-like patterns in this line
54
- for (const rx of ROUTE_LIKE) {
55
- const matches = line.match(rx);
56
- if (matches) {
57
- // Filter out matches that are part of import paths
58
- for (const match of matches) {
59
- // Exclude if it's part of an import path (has './' or '../' before it)
60
- const matchIndex = line.indexOf(match);
61
- const beforeMatch = line.substring(Math.max(0, matchIndex - 10), matchIndex);
62
- if (!/['"]\.\.?\/.*$/.test(beforeMatch)) {
63
- hits.push(match);
64
- }
65
- }
66
- }
67
- }
68
- }
69
-
70
- return [...new Set(hits)];
71
- }
72
-
73
- function classifyFileDomain(fileRel) {
74
- const s = fileRel.toLowerCase();
75
- if (s.includes("auth")) return "auth";
76
- if (s.includes("stripe") || s.includes("payment")) return "payments";
77
- if (s.includes("routes") || s.includes("router") || s.includes("api")) return "routes";
78
- if (s.includes("schema") || s.includes("contract") || s.includes("openapi")) return "contracts";
79
- if (s.includes("ui") || s.includes("components") || s.includes("pages")) return "ui";
80
- return "general";
81
- }
82
-
83
- function extractClaimsFromFile({ repoRoot, fileAbs }) {
84
- const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
85
-
86
- // Skip ignored files (test files, fixtures, etc.)
87
- if (shouldIgnore(repoRoot, fileRel)) {
88
- return { fileRel, domain: "ignored", claims: [], _dedupe: new Set() };
89
- }
90
-
91
- const code = fs.readFileSync(fileAbs, "utf8");
92
- const ast = parse(code);
93
-
94
- const out = { fileRel, domain: classifyFileDomain(fileRel), claims: [], _dedupe: new Set() };
95
-
96
- // 1) quick string route-ish scan (skip - AST-based detection is more accurate)
97
- // Removed to avoid false positives from import paths
98
-
99
- // 2) AST-based env extraction
100
- traverse(ast, {
101
- MemberExpression(p) {
102
- // process.env.X
103
- const n = p.node;
104
- if (
105
- t.isMemberExpression(n.object) &&
106
- t.isIdentifier(n.object.object, { name: "process" }) &&
107
- t.isIdentifier(n.object.property, { name: "env" }) &&
108
- (t.isIdentifier(n.property) || t.isStringLiteral(n.property))
109
- ) {
110
- const name = t.isIdentifier(n.property) ? n.property.name : n.property.value;
111
- pushClaim(out, {
112
- type: CLAIM_TYPES.ENV,
113
- value: name,
114
- criticality: CRITICALITY.HARD,
115
- pointer: locPtr(fileRel, n),
116
- reason: "process.env usage"
117
- });
118
- }
119
-
120
- // import.meta.env.X (Vite)
121
- if (
122
- t.isMemberExpression(n.object) &&
123
- t.isMemberExpression(n.object.object) &&
124
- t.isIdentifier(n.object.object.object, { name: "import" }) &&
125
- t.isIdentifier(n.object.object.property, { name: "meta" }) &&
126
- t.isIdentifier(n.object.property, { name: "env" }) &&
127
- (t.isIdentifier(n.property) || t.isStringLiteral(n.property))
128
- ) {
129
- const name = t.isIdentifier(n.property) ? n.property.name : n.property.value;
130
- pushClaim(out, {
131
- type: CLAIM_TYPES.ENV,
132
- value: name,
133
- criticality: CRITICALITY.HARD,
134
- pointer: locPtr(fileRel, n),
135
- reason: "import.meta.env usage"
136
- });
137
- }
138
- },
139
-
140
- CallExpression(p) {
141
- const n = p.node;
142
-
143
- // fetch("/api/..." or fetch(`${url}/api/...`))
144
- if (t.isIdentifier(n.callee, { name: "fetch" }) && n.arguments[0]) {
145
- const a0 = n.arguments[0];
146
- if (t.isStringLiteral(a0)) {
147
- const routeValue = a0.value;
148
- // Skip if it's an external URL (starts with http:// or https://)
149
- // Only track Next.js API routes (starting with /api/)
150
- // External API calls (like /content/blog) are handled by backend, not validated here
151
- if (!routeValue.startsWith('http://') && !routeValue.startsWith('https://') && routeValue.startsWith('/api/')) {
152
- pushClaim(out, {
153
- type: CLAIM_TYPES.HTTP_CALL,
154
- value: routeValue,
155
- criticality: CRITICALITY.HARD,
156
- pointer: locPtr(fileRel, n),
157
- reason: "fetch call"
158
- });
159
- }
160
- } else if (t.isTemplateLiteral(a0)) {
161
- // Template literal like fetch(`${apiUrl}/api/...`)
162
- // Check if it contains /api/ pattern - this indicates an HTTP call
163
- const templateParts = a0.quasis.map(q => q.value.cooked || q.value.raw).join('');
164
- // Check if it uses apiUrl or similar variable (backend API call)
165
- const hasApiUrlVar = a0.expressions.some(expr =>
166
- t.isIdentifier(expr) && (
167
- expr.name.includes('apiUrl') ||
168
- expr.name.includes('API_URL') ||
169
- expr.name.includes('api')
170
- )
171
- );
172
-
173
- // Extract the actual route path if possible (e.g., /api/v1/dashboard/summary)
174
- const apiMatch = templateParts.match(/\/api\/[a-zA-Z0-9_\/\-]+/);
175
- if (apiMatch) {
176
- pushClaim(out, {
177
- type: CLAIM_TYPES.HTTP_CALL,
178
- value: apiMatch[0], // Use the actual matched route
179
- criticality: CRITICALITY.HARD,
180
- pointer: locPtr(fileRel, n),
181
- reason: hasApiUrlVar ? "fetch call (backend API - template literal)" : "fetch call (template literal)",
182
- isBackendApi: hasApiUrlVar // Flag for evidence resolver
183
- });
184
- } else if (templateParts.includes('/api/')) {
185
- // Fallback: if we can't extract exact route, still mark as HTTP call
186
- pushClaim(out, {
187
- type: CLAIM_TYPES.HTTP_CALL,
188
- value: '/api/*', // Pattern for template literals
189
- criticality: CRITICALITY.HARD,
190
- pointer: locPtr(fileRel, n),
191
- reason: hasApiUrlVar ? "fetch call (backend API - pattern)" : "fetch call (template literal - pattern)",
192
- isBackendApi: hasApiUrlVar
193
- });
194
- }
195
- }
196
- }
197
-
198
- // axios.get("/api/...")
199
- if (t.isMemberExpression(n.callee) && t.isIdentifier(n.callee.object, { name: "axios" })) {
200
- const method = t.isIdentifier(n.callee.property) ? n.callee.property.name : "call";
201
- const a0 = n.arguments[0];
202
- if (a0 && t.isStringLiteral(a0)) {
203
- const routeValue = a0.value;
204
- // Only track Next.js API routes (starting with /api/)
205
- // External API calls (like /content/blog) are handled by backend, not validated here
206
- if (routeValue.startsWith('/api/')) {
207
- pushClaim(out, {
208
- type: CLAIM_TYPES.HTTP_CALL,
209
- value: `${method.toUpperCase()} ${routeValue}`,
210
- criticality: CRITICALITY.HARD,
211
- pointer: locPtr(fileRel, n),
212
- reason: "axios call"
213
- });
214
- }
215
- }
216
- }
217
-
218
- // apiRequest("/api/...") - check if it's the apiRequest helper
219
- if (t.isIdentifier(n.callee, { name: "apiRequest" }) && n.arguments[0]) {
220
- const a0 = n.arguments[0];
221
- if (t.isStringLiteral(a0)) {
222
- const routeValue = a0.value;
223
- // Only track Next.js API routes (starting with /api/)
224
- // External API calls (like /content/blog) go to backend API, not Next.js routes
225
- if (routeValue.startsWith('/api/')) {
226
- pushClaim(out, {
227
- type: CLAIM_TYPES.HTTP_CALL,
228
- value: routeValue,
229
- criticality: CRITICALITY.HARD,
230
- pointer: locPtr(fileRel, n),
231
- reason: "apiRequest call"
232
- });
233
- }
234
- }
235
- }
236
-
237
- // toast.success("Saved")
238
- if (
239
- t.isMemberExpression(n.callee) &&
240
- t.isIdentifier(n.callee.object, { name: "toast" }) &&
241
- t.isIdentifier(n.callee.property, { name: "success" })
242
- ) {
243
- const msg = n.arguments[0] && t.isStringLiteral(n.arguments[0]) ? n.arguments[0].value : "toast.success";
244
- pushClaim(out, {
245
- type: CLAIM_TYPES.UI_SUCCESS,
246
- value: msg,
247
- criticality: CRITICALITY.SOFT,
248
- pointer: locPtr(fileRel, n),
249
- reason: "success UI signal"
250
- });
251
- }
252
- }
253
- });
254
-
255
- // 3) auth-ish keyword scan (cheap but effective)
256
- const lines = code.split(/\r?\n/);
257
- for (let i = 0; i < lines.length; i++) {
258
- const line = lines[i];
259
- if (AUTH_HINTS.some((rx) => rx.test(line))) {
260
- pushClaim(out, {
261
- type: CLAIM_TYPES.AUTH,
262
- value: line.trim().slice(0, 140),
263
- criticality: CRITICALITY.HARD,
264
- pointer: `${fileRel}:${i + 1}-${i + 1}`,
265
- reason: "auth/role/scope hint"
266
- });
267
- }
268
- if (SUCCESS_UI.some((rx) => rx.test(line))) {
269
- pushClaim(out, {
270
- type: CLAIM_TYPES.UI_SUCCESS,
271
- value: line.trim().slice(0, 140),
272
- criticality: CRITICALITY.SOFT,
273
- pointer: `${fileRel}:${i + 1}-${i + 1}`,
274
- reason: "success UI hint"
275
- });
276
- }
277
- }
278
-
279
- delete out._dedupe;
280
- return out;
281
- }
282
-
283
- function extractClaims({ repoRoot, changedFilesAbs }) {
284
- const files = changedFilesAbs.filter((f) => fs.existsSync(f));
285
- const perFile = files.map((fileAbs) => extractClaimsFromFile({ repoRoot, fileAbs }));
286
-
287
- // Flatten + dedupe across files
288
- const dedupe = new Set();
289
- const claims = [];
290
- for (const f of perFile) {
291
- for (const c of f.claims) {
292
- const k = `${c.type}|${c.value}`;
293
- if (!dedupe.has(k)) {
294
- dedupe.add(k);
295
- claims.push({ ...c, file: f.fileRel, domain: f.domain });
296
- }
297
- }
298
- }
299
-
300
- return { claims, perFile };
301
- }
302
-
303
- module.exports = { extractClaims, extractClaimsFromFile };
@@ -1,24 +0,0 @@
1
- /**
2
- * Claim Patterns
3
- *
4
- * Regex patterns for detecting claims in code.
5
- */
6
-
7
- const ROUTE_LIKE = [
8
- /\/api\/[a-zA-Z0-9_\/\-]+/g,
9
- /\/health\/[a-zA-Z0-9_\/\-]+/g
10
- ];
11
-
12
- const AUTH_HINTS = [
13
- /\b(admin|owner|staff|superadmin|root)\b/i,
14
- /\b(role|roles|scope|scopes|permission|permissions)\b/i,
15
- /\b(auth|authorize|authorization|requireAuth|requireRole|rbac)\b/i
16
- ];
17
-
18
- const SUCCESS_UI = [
19
- /\b(success|saved|updated|complete|done)\b/i,
20
- /\btoast\.(success|info)\b/i,
21
- /\benqueueSnackbar\b/i
22
- ];
23
-
24
- module.exports = { ROUTE_LIKE, AUTH_HINTS, SUCCESS_UI };
@@ -1,151 +0,0 @@
1
- /**
2
- * Critic Module
3
- *
4
- * Entry point for the Critic LLM judge.
5
- * The "savage" that evaluates proposal quality.
6
- *
7
- * Usage:
8
- * const { critic } = require('./critic');
9
- *
10
- * // Configure with LLM client
11
- * critic.setClient(async (params) => {
12
- * return await callOpenAI(params);
13
- * });
14
- *
15
- * // Evaluate a proposal
16
- * const verdict = await critic.evaluate({
17
- * proposal,
18
- * validationResults,
19
- * riskScore,
20
- * simulationResult,
21
- * realityState,
22
- * });
23
- */
24
-
25
- "use strict";
26
-
27
- const {
28
- CriticJudge,
29
- createJudge,
30
- defaultJudge,
31
- } = require("./judge");
32
-
33
- const {
34
- CRITIC_SYSTEM_PROMPT,
35
- EVALUATION_PROMPT_TEMPLATE,
36
- VAGUENESS_CHECK_PROMPT,
37
- ASSUMPTION_VERIFICATION_PROMPT,
38
- buildEvaluationPrompt,
39
- buildVaguenessPrompt,
40
- buildVerificationPrompt,
41
- parseCriticResponse,
42
- } = require("./prompts");
43
-
44
- /**
45
- * Critic singleton interface
46
- */
47
- const critic = {
48
- /**
49
- * Set the LLM client for the default judge
50
- * @param {Function} client - LLM client function
51
- */
52
- setClient(client) {
53
- defaultJudge.setClient(client);
54
- },
55
-
56
- /**
57
- * Check if critic is available
58
- * @returns {boolean} Is available
59
- */
60
- isAvailable() {
61
- return defaultJudge.isAvailable();
62
- },
63
-
64
- /**
65
- * Evaluate a proposal
66
- * @param {Object} params - Evaluation parameters
67
- * @returns {Promise<Object>} Critic verdict
68
- */
69
- async evaluate(params) {
70
- return defaultJudge.evaluate(params);
71
- },
72
-
73
- /**
74
- * Check for vagueness
75
- * @param {Object} proposal - Proposal to check
76
- * @returns {Promise<Object>} Vagueness analysis
77
- */
78
- async checkVagueness(proposal) {
79
- return defaultJudge.checkVagueness(proposal);
80
- },
81
-
82
- /**
83
- * Verify assumptions
84
- * @param {Array} assumptions - Assumptions to verify
85
- * @param {Object} realityState - Repository state
86
- * @returns {Promise<Object>} Verification results
87
- */
88
- async verifyAssumptions(assumptions, realityState) {
89
- return defaultJudge.verifyAssumptions(assumptions, realityState);
90
- },
91
-
92
- /**
93
- * Create a new judge instance
94
- * @param {Object} options - Configuration
95
- * @returns {CriticJudge} New judge instance
96
- */
97
- createJudge(options) {
98
- return createJudge(options);
99
- },
100
-
101
- /**
102
- * Get the system prompt
103
- * @returns {string} System prompt
104
- */
105
- getSystemPrompt() {
106
- return CRITIC_SYSTEM_PROMPT;
107
- },
108
-
109
- /**
110
- * Build an evaluation prompt
111
- * @param {Object} data - Prompt data
112
- * @returns {string} Filled prompt
113
- */
114
- buildPrompt(data) {
115
- return buildEvaluationPrompt(data);
116
- },
117
-
118
- /**
119
- * Parse a critic response
120
- * @param {string} response - LLM response
121
- * @returns {Object} Parsed verdict
122
- */
123
- parseResponse(response) {
124
- return parseCriticResponse(response);
125
- },
126
-
127
- /**
128
- * Quick rule-based evaluation (no LLM)
129
- * @param {Object} params - Evaluation params
130
- * @returns {Object} Verdict
131
- */
132
- quickEvaluate(params) {
133
- return defaultJudge.ruleBasedEvaluation(params);
134
- },
135
- };
136
-
137
- module.exports = {
138
- critic,
139
- CriticJudge,
140
- createJudge,
141
- defaultJudge,
142
- // Prompt exports
143
- CRITIC_SYSTEM_PROMPT,
144
- EVALUATION_PROMPT_TEMPLATE,
145
- VAGUENESS_CHECK_PROMPT,
146
- ASSUMPTION_VERIFICATION_PROMPT,
147
- buildEvaluationPrompt,
148
- buildVaguenessPrompt,
149
- buildVerificationPrompt,
150
- parseCriticResponse,
151
- };