@vibecheckai/cli 3.2.2 → 3.2.4
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.
- package/bin/.generated +25 -25
- package/bin/dev/run-v2-torture.js +30 -30
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -121
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +117 -28
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +23 -14
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +72 -1
- package/bin/runners/lib/agent-firewall/interceptor/base.js +2 -2
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +6 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +34 -3
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +29 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +12 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +21 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/analyzers.js +606 -325
- package/bin/runners/lib/auth-truth.js +193 -193
- package/bin/runners/lib/backup.js +62 -62
- package/bin/runners/lib/billing.js +107 -107
- package/bin/runners/lib/claims.js +118 -118
- package/bin/runners/lib/cli-ui.js +540 -540
- package/bin/runners/lib/contracts/auth-contract.js +202 -202
- package/bin/runners/lib/contracts/env-contract.js +181 -181
- package/bin/runners/lib/contracts/external-contract.js +206 -206
- package/bin/runners/lib/contracts/guard.js +168 -168
- package/bin/runners/lib/contracts/index.js +89 -89
- package/bin/runners/lib/contracts/plan-validator.js +311 -311
- package/bin/runners/lib/contracts/route-contract.js +199 -199
- package/bin/runners/lib/contracts.js +804 -804
- package/bin/runners/lib/detect.js +89 -89
- package/bin/runners/lib/doctor/autofix.js +254 -254
- package/bin/runners/lib/doctor/index.js +37 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
- package/bin/runners/lib/doctor/modules/index.js +46 -46
- package/bin/runners/lib/doctor/modules/network.js +250 -250
- package/bin/runners/lib/doctor/modules/project.js +312 -312
- package/bin/runners/lib/doctor/modules/runtime.js +224 -224
- package/bin/runners/lib/doctor/modules/security.js +348 -348
- package/bin/runners/lib/doctor/modules/system.js +213 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
- package/bin/runners/lib/doctor/reporter.js +262 -262
- package/bin/runners/lib/doctor/service.js +262 -262
- package/bin/runners/lib/doctor/types.js +113 -113
- package/bin/runners/lib/doctor/ui.js +263 -263
- package/bin/runners/lib/doctor-v2.js +608 -608
- package/bin/runners/lib/drift.js +425 -425
- package/bin/runners/lib/enforcement.js +72 -72
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -603
- package/bin/runners/lib/enterprise-init.js +942 -942
- package/bin/runners/lib/env-resolver.js +417 -417
- package/bin/runners/lib/env-template.js +66 -66
- package/bin/runners/lib/env.js +189 -189
- package/bin/runners/lib/extractors/client-calls.js +990 -990
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
- package/bin/runners/lib/extractors/fastify-routes.js +426 -426
- package/bin/runners/lib/extractors/index.js +363 -363
- package/bin/runners/lib/extractors/next-routes.js +524 -524
- package/bin/runners/lib/extractors/proof-graph.js +431 -431
- package/bin/runners/lib/extractors/route-matcher.js +451 -451
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
- package/bin/runners/lib/extractors/ui-bindings.js +547 -547
- package/bin/runners/lib/findings-schema.js +281 -281
- package/bin/runners/lib/firewall-prompt.js +50 -50
- package/bin/runners/lib/global-flags.js +213 -213
- package/bin/runners/lib/graph/graph-builder.js +265 -265
- package/bin/runners/lib/graph/html-renderer.js +413 -413
- package/bin/runners/lib/graph/index.js +32 -32
- package/bin/runners/lib/graph/runtime-collector.js +215 -215
- package/bin/runners/lib/graph/static-extractor.js +518 -518
- package/bin/runners/lib/html-report.js +650 -650
- package/bin/runners/lib/interactive-menu.js +1496 -1496
- package/bin/runners/lib/llm.js +75 -75
- package/bin/runners/lib/meter.js +61 -61
- package/bin/runners/lib/missions/evidence.js +126 -126
- package/bin/runners/lib/patch.js +40 -40
- package/bin/runners/lib/permissions/auth-model.js +213 -213
- package/bin/runners/lib/permissions/idor-prover.js +205 -205
- package/bin/runners/lib/permissions/index.js +45 -45
- package/bin/runners/lib/permissions/matrix-builder.js +198 -198
- package/bin/runners/lib/pkgjson.js +28 -28
- package/bin/runners/lib/policy.js +295 -295
- package/bin/runners/lib/preflight.js +142 -142
- package/bin/runners/lib/reality/correlation-detectors.js +359 -359
- package/bin/runners/lib/reality/index.js +318 -318
- package/bin/runners/lib/reality/request-hashing.js +416 -416
- package/bin/runners/lib/reality/request-mapper.js +453 -453
- package/bin/runners/lib/reality/safety-rails.js +463 -463
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
- package/bin/runners/lib/reality/toast-detector.js +393 -393
- package/bin/runners/lib/reality-findings.js +84 -84
- package/bin/runners/lib/receipts.js +179 -179
- package/bin/runners/lib/redact.js +29 -29
- package/bin/runners/lib/replay/capsule-manager.js +154 -154
- package/bin/runners/lib/replay/index.js +263 -263
- package/bin/runners/lib/replay/player.js +348 -348
- package/bin/runners/lib/replay/recorder.js +331 -331
- package/bin/runners/lib/report-output.js +187 -187
- package/bin/runners/lib/report.js +135 -135
- package/bin/runners/lib/route-detection.js +1140 -1140
- package/bin/runners/lib/sandbox/index.js +59 -59
- package/bin/runners/lib/sandbox/proof-chain.js +399 -399
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
- package/bin/runners/lib/sandbox/worktree.js +174 -174
- package/bin/runners/lib/scan-output.js +525 -190
- package/bin/runners/lib/schema-validator.js +350 -350
- package/bin/runners/lib/schemas/contracts.schema.json +160 -160
- package/bin/runners/lib/schemas/finding.schema.json +100 -100
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
- package/bin/runners/lib/schemas/validator.js +438 -438
- package/bin/runners/lib/score-history.js +282 -282
- package/bin/runners/lib/share-pack.js +239 -239
- package/bin/runners/lib/snippets.js +67 -67
- package/bin/runners/lib/status-output.js +253 -253
- package/bin/runners/lib/terminal-ui.js +351 -271
- package/bin/runners/lib/upsell.js +510 -510
- package/bin/runners/lib/usage.js +153 -153
- package/bin/runners/lib/validate-patch.js +156 -156
- package/bin/runners/lib/verdict-engine.js +628 -628
- package/bin/runners/reality/engine.js +917 -917
- package/bin/runners/reality/flows.js +122 -122
- package/bin/runners/reality/report.js +378 -378
- package/bin/runners/reality/session.js +193 -193
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runProve.js +8 -0
- package/bin/runners/runReality.js +14 -0
- package/bin/runners/runScan.js +17 -1
- package/bin/runners/runTruth.js +15 -3
- package/mcp-server/tier-auth.js +4 -4
- package/mcp-server/tools/index.js +72 -72
- package/package.json +1 -1
|
@@ -1,399 +1,399 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Proof Chain
|
|
3
|
-
* Runs verification stages in sandbox before accepting patches
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
const { execSync } = require("child_process");
|
|
9
|
-
const fs = require("fs");
|
|
10
|
-
const path = require("path");
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Proof chain stages
|
|
14
|
-
*/
|
|
15
|
-
const PROOF_LEVELS = {
|
|
16
|
-
fast: ["static"],
|
|
17
|
-
balanced: ["static", "build"],
|
|
18
|
-
paranoid: ["static", "build", "reality"]
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Run proof chain in sandbox
|
|
23
|
-
*/
|
|
24
|
-
async function runProofChain(sandboxPath, options = {}) {
|
|
25
|
-
const level = options.level || "balanced";
|
|
26
|
-
const stages = PROOF_LEVELS[level] || PROOF_LEVELS.balanced;
|
|
27
|
-
|
|
28
|
-
const results = {
|
|
29
|
-
level,
|
|
30
|
-
stages: [],
|
|
31
|
-
passed: true,
|
|
32
|
-
duration: 0
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const startTime = Date.now();
|
|
36
|
-
|
|
37
|
-
for (const stage of stages) {
|
|
38
|
-
const stageResult = await runStage(sandboxPath, stage, options);
|
|
39
|
-
results.stages.push(stageResult);
|
|
40
|
-
|
|
41
|
-
if (!stageResult.passed) {
|
|
42
|
-
results.passed = false;
|
|
43
|
-
results.failedAt = stage;
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
results.duration = Date.now() - startTime;
|
|
49
|
-
return results;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Run individual proof stage
|
|
54
|
-
*/
|
|
55
|
-
async function runStage(sandboxPath, stage, options) {
|
|
56
|
-
const startTime = Date.now();
|
|
57
|
-
|
|
58
|
-
switch (stage) {
|
|
59
|
-
case "static":
|
|
60
|
-
return runStaticProof(sandboxPath, options);
|
|
61
|
-
case "build":
|
|
62
|
-
return runBuildProof(sandboxPath, options);
|
|
63
|
-
case "reality":
|
|
64
|
-
return runRealityProof(sandboxPath, options);
|
|
65
|
-
default:
|
|
66
|
-
return { stage, passed: true, skipped: true, duration: 0 };
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Static proof: ship + contracts guard
|
|
72
|
-
*/
|
|
73
|
-
async function runStaticProof(sandboxPath, options) {
|
|
74
|
-
const result = {
|
|
75
|
-
stage: "static",
|
|
76
|
-
passed: true,
|
|
77
|
-
checks: [],
|
|
78
|
-
duration: 0
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const startTime = Date.now();
|
|
82
|
-
|
|
83
|
-
// Run vibecheck ship in sandbox
|
|
84
|
-
try {
|
|
85
|
-
const vibecheckBin = path.join(__dirname, "..", "..", "..", "vibecheck.js");
|
|
86
|
-
const output = execSync(`node "${vibecheckBin}" ship --json`, {
|
|
87
|
-
cwd: sandboxPath,
|
|
88
|
-
encoding: "utf8",
|
|
89
|
-
timeout: 30000,
|
|
90
|
-
stdio: "pipe",
|
|
91
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" }
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Parse verdict from output
|
|
95
|
-
const verdictMatch = output.match(/Verdict:\s*(SHIP|WARN|BLOCK)/i);
|
|
96
|
-
const verdict = verdictMatch ? verdictMatch[1].toUpperCase() : "UNKNOWN";
|
|
97
|
-
|
|
98
|
-
result.checks.push({
|
|
99
|
-
name: "ship",
|
|
100
|
-
passed: verdict !== "BLOCK",
|
|
101
|
-
verdict,
|
|
102
|
-
output: output.slice(-500)
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
if (verdict === "BLOCK") {
|
|
106
|
-
result.passed = false;
|
|
107
|
-
result.reason = "Ship verdict is BLOCK";
|
|
108
|
-
}
|
|
109
|
-
} catch (e) {
|
|
110
|
-
result.checks.push({
|
|
111
|
-
name: "ship",
|
|
112
|
-
passed: false,
|
|
113
|
-
error: e.message
|
|
114
|
-
});
|
|
115
|
-
result.passed = false;
|
|
116
|
-
result.reason = `Ship check failed: ${e.message}`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Run contracts guard if contracts exist
|
|
120
|
-
const contractsDir = path.join(sandboxPath, ".vibecheck", "contracts");
|
|
121
|
-
if (fs.existsSync(contractsDir)) {
|
|
122
|
-
try {
|
|
123
|
-
const vibecheckBin = path.join(__dirname, "..", "..", "..", "vibecheck.js");
|
|
124
|
-
const output = execSync(`node "${vibecheckBin}" ctx guard --json`, {
|
|
125
|
-
cwd: sandboxPath,
|
|
126
|
-
encoding: "utf8",
|
|
127
|
-
timeout: 30000,
|
|
128
|
-
stdio: "pipe",
|
|
129
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" }
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
result.checks.push({
|
|
133
|
-
name: "contracts",
|
|
134
|
-
passed: true,
|
|
135
|
-
output: output.slice(-500)
|
|
136
|
-
});
|
|
137
|
-
} catch (e) {
|
|
138
|
-
// Check if it's a BLOCK
|
|
139
|
-
if (e.status === 2) {
|
|
140
|
-
result.checks.push({
|
|
141
|
-
name: "contracts",
|
|
142
|
-
passed: false,
|
|
143
|
-
error: "Contract violations found"
|
|
144
|
-
});
|
|
145
|
-
result.passed = false;
|
|
146
|
-
result.reason = "Contract guard failed";
|
|
147
|
-
} else {
|
|
148
|
-
result.checks.push({
|
|
149
|
-
name: "contracts",
|
|
150
|
-
passed: true,
|
|
151
|
-
warning: e.message
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
result.duration = Date.now() - startTime;
|
|
158
|
-
return result;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Build proof: typecheck + build + targeted tests
|
|
163
|
-
*/
|
|
164
|
-
async function runBuildProof(sandboxPath, options) {
|
|
165
|
-
const result = {
|
|
166
|
-
stage: "build",
|
|
167
|
-
passed: true,
|
|
168
|
-
checks: [],
|
|
169
|
-
duration: 0
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
const startTime = Date.now();
|
|
173
|
-
|
|
174
|
-
// Detect package manager
|
|
175
|
-
const pm = detectPackageManager(sandboxPath);
|
|
176
|
-
|
|
177
|
-
// Check for TypeScript
|
|
178
|
-
const tsconfigPath = path.join(sandboxPath, "tsconfig.json");
|
|
179
|
-
if (fs.existsSync(tsconfigPath)) {
|
|
180
|
-
try {
|
|
181
|
-
execSync(`${pm} run typecheck 2>&1 || npx tsc --noEmit 2>&1`, {
|
|
182
|
-
cwd: sandboxPath,
|
|
183
|
-
encoding: "utf8",
|
|
184
|
-
timeout: 60000,
|
|
185
|
-
stdio: "pipe"
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
result.checks.push({
|
|
189
|
-
name: "typecheck",
|
|
190
|
-
passed: true
|
|
191
|
-
});
|
|
192
|
-
} catch (e) {
|
|
193
|
-
// TypeScript errors
|
|
194
|
-
result.checks.push({
|
|
195
|
-
name: "typecheck",
|
|
196
|
-
passed: false,
|
|
197
|
-
error: e.stdout?.slice(-500) || e.message
|
|
198
|
-
});
|
|
199
|
-
result.passed = false;
|
|
200
|
-
result.reason = "TypeScript errors";
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Try to run build
|
|
205
|
-
const pkgPath = path.join(sandboxPath, "package.json");
|
|
206
|
-
if (fs.existsSync(pkgPath)) {
|
|
207
|
-
try {
|
|
208
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
209
|
-
|
|
210
|
-
if (pkg.scripts?.build) {
|
|
211
|
-
execSync(`${pm} run build`, {
|
|
212
|
-
cwd: sandboxPath,
|
|
213
|
-
encoding: "utf8",
|
|
214
|
-
timeout: 120000,
|
|
215
|
-
stdio: "pipe"
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
result.checks.push({
|
|
219
|
-
name: "build",
|
|
220
|
-
passed: true
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
} catch (e) {
|
|
224
|
-
result.checks.push({
|
|
225
|
-
name: "build",
|
|
226
|
-
passed: false,
|
|
227
|
-
error: e.message?.slice(-500)
|
|
228
|
-
});
|
|
229
|
-
result.passed = false;
|
|
230
|
-
result.reason = "Build failed";
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Run targeted tests if changed files have test files
|
|
235
|
-
if (options.changedFiles?.length) {
|
|
236
|
-
const testFiles = findRelatedTests(sandboxPath, options.changedFiles);
|
|
237
|
-
|
|
238
|
-
if (testFiles.length > 0) {
|
|
239
|
-
try {
|
|
240
|
-
const testCmd = `${pm} test -- ${testFiles.join(" ")}`;
|
|
241
|
-
execSync(testCmd, {
|
|
242
|
-
cwd: sandboxPath,
|
|
243
|
-
encoding: "utf8",
|
|
244
|
-
timeout: 120000,
|
|
245
|
-
stdio: "pipe"
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
result.checks.push({
|
|
249
|
-
name: "tests",
|
|
250
|
-
passed: true,
|
|
251
|
-
files: testFiles
|
|
252
|
-
});
|
|
253
|
-
} catch (e) {
|
|
254
|
-
result.checks.push({
|
|
255
|
-
name: "tests",
|
|
256
|
-
passed: false,
|
|
257
|
-
files: testFiles,
|
|
258
|
-
error: e.message?.slice(-500)
|
|
259
|
-
});
|
|
260
|
-
result.passed = false;
|
|
261
|
-
result.reason = "Tests failed";
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
result.duration = Date.now() - startTime;
|
|
267
|
-
return result;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Reality proof: run reality checks on critical paths
|
|
272
|
-
*/
|
|
273
|
-
async function runRealityProof(sandboxPath, options) {
|
|
274
|
-
const result = {
|
|
275
|
-
stage: "reality",
|
|
276
|
-
passed: true,
|
|
277
|
-
checks: [],
|
|
278
|
-
duration: 0
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
const startTime = Date.now();
|
|
282
|
-
|
|
283
|
-
if (!options.url) {
|
|
284
|
-
result.checks.push({
|
|
285
|
-
name: "reality",
|
|
286
|
-
passed: true,
|
|
287
|
-
skipped: true,
|
|
288
|
-
reason: "No URL provided"
|
|
289
|
-
});
|
|
290
|
-
result.duration = Date.now() - startTime;
|
|
291
|
-
return result;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Run vibecheck reality
|
|
295
|
-
try {
|
|
296
|
-
const vibecheckBin = path.join(__dirname, "..", "..", "..", "vibecheck.js");
|
|
297
|
-
const cmd = `node "${vibecheckBin}" reality --url ${options.url} --max-pages 5 --max-depth 1`;
|
|
298
|
-
|
|
299
|
-
execSync(cmd, {
|
|
300
|
-
cwd: sandboxPath,
|
|
301
|
-
encoding: "utf8",
|
|
302
|
-
timeout: 120000,
|
|
303
|
-
stdio: "pipe",
|
|
304
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" }
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
result.checks.push({
|
|
308
|
-
name: "reality",
|
|
309
|
-
passed: true
|
|
310
|
-
});
|
|
311
|
-
} catch (e) {
|
|
312
|
-
if (e.status === 2) {
|
|
313
|
-
result.checks.push({
|
|
314
|
-
name: "reality",
|
|
315
|
-
passed: false,
|
|
316
|
-
error: "Reality check found blocking issues"
|
|
317
|
-
});
|
|
318
|
-
result.passed = false;
|
|
319
|
-
result.reason = "Reality check failed";
|
|
320
|
-
} else {
|
|
321
|
-
result.checks.push({
|
|
322
|
-
name: "reality",
|
|
323
|
-
passed: true,
|
|
324
|
-
warning: e.message
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
result.duration = Date.now() - startTime;
|
|
330
|
-
return result;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Detect package manager
|
|
335
|
-
*/
|
|
336
|
-
function detectPackageManager(repoRoot) {
|
|
337
|
-
if (fs.existsSync(path.join(repoRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
338
|
-
if (fs.existsSync(path.join(repoRoot, "yarn.lock"))) return "yarn";
|
|
339
|
-
return "npm";
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Find test files related to changed files
|
|
344
|
-
*/
|
|
345
|
-
function findRelatedTests(repoRoot, changedFiles) {
|
|
346
|
-
const testFiles = [];
|
|
347
|
-
|
|
348
|
-
for (const file of changedFiles) {
|
|
349
|
-
// Look for .test.ts, .spec.ts variants
|
|
350
|
-
const base = file.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
351
|
-
const testVariants = [
|
|
352
|
-
`${base}.test.ts`,
|
|
353
|
-
`${base}.test.tsx`,
|
|
354
|
-
`${base}.test.js`,
|
|
355
|
-
`${base}.spec.ts`,
|
|
356
|
-
`${base}.spec.tsx`,
|
|
357
|
-
`${base}.spec.js`
|
|
358
|
-
];
|
|
359
|
-
|
|
360
|
-
for (const variant of testVariants) {
|
|
361
|
-
const testPath = path.join(repoRoot, variant);
|
|
362
|
-
if (fs.existsSync(testPath)) {
|
|
363
|
-
testFiles.push(variant);
|
|
364
|
-
break;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// Also check __tests__ directory
|
|
369
|
-
const dir = path.dirname(file);
|
|
370
|
-
const name = path.basename(file).replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
371
|
-
const testsDir = path.join(repoRoot, dir, "__tests__");
|
|
372
|
-
|
|
373
|
-
if (fs.existsSync(testsDir)) {
|
|
374
|
-
const testVariants = [
|
|
375
|
-
`${name}.test.ts`,
|
|
376
|
-
`${name}.test.tsx`,
|
|
377
|
-
`${name}.test.js`
|
|
378
|
-
];
|
|
379
|
-
|
|
380
|
-
for (const variant of testVariants) {
|
|
381
|
-
const testPath = path.join(testsDir, variant);
|
|
382
|
-
if (fs.existsSync(testPath)) {
|
|
383
|
-
testFiles.push(path.join(dir, "__tests__", variant));
|
|
384
|
-
break;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return [...new Set(testFiles)];
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
module.exports = {
|
|
394
|
-
runProofChain,
|
|
395
|
-
runStaticProof,
|
|
396
|
-
runBuildProof,
|
|
397
|
-
runRealityProof,
|
|
398
|
-
PROOF_LEVELS
|
|
399
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Proof Chain
|
|
3
|
+
* Runs verification stages in sandbox before accepting patches
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const { execSync } = require("child_process");
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Proof chain stages
|
|
14
|
+
*/
|
|
15
|
+
const PROOF_LEVELS = {
|
|
16
|
+
fast: ["static"],
|
|
17
|
+
balanced: ["static", "build"],
|
|
18
|
+
paranoid: ["static", "build", "reality"]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Run proof chain in sandbox
|
|
23
|
+
*/
|
|
24
|
+
async function runProofChain(sandboxPath, options = {}) {
|
|
25
|
+
const level = options.level || "balanced";
|
|
26
|
+
const stages = PROOF_LEVELS[level] || PROOF_LEVELS.balanced;
|
|
27
|
+
|
|
28
|
+
const results = {
|
|
29
|
+
level,
|
|
30
|
+
stages: [],
|
|
31
|
+
passed: true,
|
|
32
|
+
duration: 0
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const startTime = Date.now();
|
|
36
|
+
|
|
37
|
+
for (const stage of stages) {
|
|
38
|
+
const stageResult = await runStage(sandboxPath, stage, options);
|
|
39
|
+
results.stages.push(stageResult);
|
|
40
|
+
|
|
41
|
+
if (!stageResult.passed) {
|
|
42
|
+
results.passed = false;
|
|
43
|
+
results.failedAt = stage;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
results.duration = Date.now() - startTime;
|
|
49
|
+
return results;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Run individual proof stage
|
|
54
|
+
*/
|
|
55
|
+
async function runStage(sandboxPath, stage, options) {
|
|
56
|
+
const startTime = Date.now();
|
|
57
|
+
|
|
58
|
+
switch (stage) {
|
|
59
|
+
case "static":
|
|
60
|
+
return runStaticProof(sandboxPath, options);
|
|
61
|
+
case "build":
|
|
62
|
+
return runBuildProof(sandboxPath, options);
|
|
63
|
+
case "reality":
|
|
64
|
+
return runRealityProof(sandboxPath, options);
|
|
65
|
+
default:
|
|
66
|
+
return { stage, passed: true, skipped: true, duration: 0 };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Static proof: ship + contracts guard
|
|
72
|
+
*/
|
|
73
|
+
async function runStaticProof(sandboxPath, options) {
|
|
74
|
+
const result = {
|
|
75
|
+
stage: "static",
|
|
76
|
+
passed: true,
|
|
77
|
+
checks: [],
|
|
78
|
+
duration: 0
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const startTime = Date.now();
|
|
82
|
+
|
|
83
|
+
// Run vibecheck ship in sandbox
|
|
84
|
+
try {
|
|
85
|
+
const vibecheckBin = path.join(__dirname, "..", "..", "..", "vibecheck.js");
|
|
86
|
+
const output = execSync(`node "${vibecheckBin}" ship --json`, {
|
|
87
|
+
cwd: sandboxPath,
|
|
88
|
+
encoding: "utf8",
|
|
89
|
+
timeout: 30000,
|
|
90
|
+
stdio: "pipe",
|
|
91
|
+
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" }
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Parse verdict from output
|
|
95
|
+
const verdictMatch = output.match(/Verdict:\s*(SHIP|WARN|BLOCK)/i);
|
|
96
|
+
const verdict = verdictMatch ? verdictMatch[1].toUpperCase() : "UNKNOWN";
|
|
97
|
+
|
|
98
|
+
result.checks.push({
|
|
99
|
+
name: "ship",
|
|
100
|
+
passed: verdict !== "BLOCK",
|
|
101
|
+
verdict,
|
|
102
|
+
output: output.slice(-500)
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (verdict === "BLOCK") {
|
|
106
|
+
result.passed = false;
|
|
107
|
+
result.reason = "Ship verdict is BLOCK";
|
|
108
|
+
}
|
|
109
|
+
} catch (e) {
|
|
110
|
+
result.checks.push({
|
|
111
|
+
name: "ship",
|
|
112
|
+
passed: false,
|
|
113
|
+
error: e.message
|
|
114
|
+
});
|
|
115
|
+
result.passed = false;
|
|
116
|
+
result.reason = `Ship check failed: ${e.message}`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Run contracts guard if contracts exist
|
|
120
|
+
const contractsDir = path.join(sandboxPath, ".vibecheck", "contracts");
|
|
121
|
+
if (fs.existsSync(contractsDir)) {
|
|
122
|
+
try {
|
|
123
|
+
const vibecheckBin = path.join(__dirname, "..", "..", "..", "vibecheck.js");
|
|
124
|
+
const output = execSync(`node "${vibecheckBin}" ctx guard --json`, {
|
|
125
|
+
cwd: sandboxPath,
|
|
126
|
+
encoding: "utf8",
|
|
127
|
+
timeout: 30000,
|
|
128
|
+
stdio: "pipe",
|
|
129
|
+
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" }
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
result.checks.push({
|
|
133
|
+
name: "contracts",
|
|
134
|
+
passed: true,
|
|
135
|
+
output: output.slice(-500)
|
|
136
|
+
});
|
|
137
|
+
} catch (e) {
|
|
138
|
+
// Check if it's a BLOCK
|
|
139
|
+
if (e.status === 2) {
|
|
140
|
+
result.checks.push({
|
|
141
|
+
name: "contracts",
|
|
142
|
+
passed: false,
|
|
143
|
+
error: "Contract violations found"
|
|
144
|
+
});
|
|
145
|
+
result.passed = false;
|
|
146
|
+
result.reason = "Contract guard failed";
|
|
147
|
+
} else {
|
|
148
|
+
result.checks.push({
|
|
149
|
+
name: "contracts",
|
|
150
|
+
passed: true,
|
|
151
|
+
warning: e.message
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
result.duration = Date.now() - startTime;
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Build proof: typecheck + build + targeted tests
|
|
163
|
+
*/
|
|
164
|
+
async function runBuildProof(sandboxPath, options) {
|
|
165
|
+
const result = {
|
|
166
|
+
stage: "build",
|
|
167
|
+
passed: true,
|
|
168
|
+
checks: [],
|
|
169
|
+
duration: 0
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const startTime = Date.now();
|
|
173
|
+
|
|
174
|
+
// Detect package manager
|
|
175
|
+
const pm = detectPackageManager(sandboxPath);
|
|
176
|
+
|
|
177
|
+
// Check for TypeScript
|
|
178
|
+
const tsconfigPath = path.join(sandboxPath, "tsconfig.json");
|
|
179
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
180
|
+
try {
|
|
181
|
+
execSync(`${pm} run typecheck 2>&1 || npx tsc --noEmit 2>&1`, {
|
|
182
|
+
cwd: sandboxPath,
|
|
183
|
+
encoding: "utf8",
|
|
184
|
+
timeout: 60000,
|
|
185
|
+
stdio: "pipe"
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
result.checks.push({
|
|
189
|
+
name: "typecheck",
|
|
190
|
+
passed: true
|
|
191
|
+
});
|
|
192
|
+
} catch (e) {
|
|
193
|
+
// TypeScript errors
|
|
194
|
+
result.checks.push({
|
|
195
|
+
name: "typecheck",
|
|
196
|
+
passed: false,
|
|
197
|
+
error: e.stdout?.slice(-500) || e.message
|
|
198
|
+
});
|
|
199
|
+
result.passed = false;
|
|
200
|
+
result.reason = "TypeScript errors";
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Try to run build
|
|
205
|
+
const pkgPath = path.join(sandboxPath, "package.json");
|
|
206
|
+
if (fs.existsSync(pkgPath)) {
|
|
207
|
+
try {
|
|
208
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
209
|
+
|
|
210
|
+
if (pkg.scripts?.build) {
|
|
211
|
+
execSync(`${pm} run build`, {
|
|
212
|
+
cwd: sandboxPath,
|
|
213
|
+
encoding: "utf8",
|
|
214
|
+
timeout: 120000,
|
|
215
|
+
stdio: "pipe"
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
result.checks.push({
|
|
219
|
+
name: "build",
|
|
220
|
+
passed: true
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
} catch (e) {
|
|
224
|
+
result.checks.push({
|
|
225
|
+
name: "build",
|
|
226
|
+
passed: false,
|
|
227
|
+
error: e.message?.slice(-500)
|
|
228
|
+
});
|
|
229
|
+
result.passed = false;
|
|
230
|
+
result.reason = "Build failed";
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Run targeted tests if changed files have test files
|
|
235
|
+
if (options.changedFiles?.length) {
|
|
236
|
+
const testFiles = findRelatedTests(sandboxPath, options.changedFiles);
|
|
237
|
+
|
|
238
|
+
if (testFiles.length > 0) {
|
|
239
|
+
try {
|
|
240
|
+
const testCmd = `${pm} test -- ${testFiles.join(" ")}`;
|
|
241
|
+
execSync(testCmd, {
|
|
242
|
+
cwd: sandboxPath,
|
|
243
|
+
encoding: "utf8",
|
|
244
|
+
timeout: 120000,
|
|
245
|
+
stdio: "pipe"
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
result.checks.push({
|
|
249
|
+
name: "tests",
|
|
250
|
+
passed: true,
|
|
251
|
+
files: testFiles
|
|
252
|
+
});
|
|
253
|
+
} catch (e) {
|
|
254
|
+
result.checks.push({
|
|
255
|
+
name: "tests",
|
|
256
|
+
passed: false,
|
|
257
|
+
files: testFiles,
|
|
258
|
+
error: e.message?.slice(-500)
|
|
259
|
+
});
|
|
260
|
+
result.passed = false;
|
|
261
|
+
result.reason = "Tests failed";
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
result.duration = Date.now() - startTime;
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Reality proof: run reality checks on critical paths
|
|
272
|
+
*/
|
|
273
|
+
async function runRealityProof(sandboxPath, options) {
|
|
274
|
+
const result = {
|
|
275
|
+
stage: "reality",
|
|
276
|
+
passed: true,
|
|
277
|
+
checks: [],
|
|
278
|
+
duration: 0
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const startTime = Date.now();
|
|
282
|
+
|
|
283
|
+
if (!options.url) {
|
|
284
|
+
result.checks.push({
|
|
285
|
+
name: "reality",
|
|
286
|
+
passed: true,
|
|
287
|
+
skipped: true,
|
|
288
|
+
reason: "No URL provided"
|
|
289
|
+
});
|
|
290
|
+
result.duration = Date.now() - startTime;
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Run vibecheck reality
|
|
295
|
+
try {
|
|
296
|
+
const vibecheckBin = path.join(__dirname, "..", "..", "..", "vibecheck.js");
|
|
297
|
+
const cmd = `node "${vibecheckBin}" reality --url ${options.url} --max-pages 5 --max-depth 1`;
|
|
298
|
+
|
|
299
|
+
execSync(cmd, {
|
|
300
|
+
cwd: sandboxPath,
|
|
301
|
+
encoding: "utf8",
|
|
302
|
+
timeout: 120000,
|
|
303
|
+
stdio: "pipe",
|
|
304
|
+
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" }
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
result.checks.push({
|
|
308
|
+
name: "reality",
|
|
309
|
+
passed: true
|
|
310
|
+
});
|
|
311
|
+
} catch (e) {
|
|
312
|
+
if (e.status === 2) {
|
|
313
|
+
result.checks.push({
|
|
314
|
+
name: "reality",
|
|
315
|
+
passed: false,
|
|
316
|
+
error: "Reality check found blocking issues"
|
|
317
|
+
});
|
|
318
|
+
result.passed = false;
|
|
319
|
+
result.reason = "Reality check failed";
|
|
320
|
+
} else {
|
|
321
|
+
result.checks.push({
|
|
322
|
+
name: "reality",
|
|
323
|
+
passed: true,
|
|
324
|
+
warning: e.message
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
result.duration = Date.now() - startTime;
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Detect package manager
|
|
335
|
+
*/
|
|
336
|
+
function detectPackageManager(repoRoot) {
|
|
337
|
+
if (fs.existsSync(path.join(repoRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
338
|
+
if (fs.existsSync(path.join(repoRoot, "yarn.lock"))) return "yarn";
|
|
339
|
+
return "npm";
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Find test files related to changed files
|
|
344
|
+
*/
|
|
345
|
+
function findRelatedTests(repoRoot, changedFiles) {
|
|
346
|
+
const testFiles = [];
|
|
347
|
+
|
|
348
|
+
for (const file of changedFiles) {
|
|
349
|
+
// Look for .test.ts, .spec.ts variants
|
|
350
|
+
const base = file.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
351
|
+
const testVariants = [
|
|
352
|
+
`${base}.test.ts`,
|
|
353
|
+
`${base}.test.tsx`,
|
|
354
|
+
`${base}.test.js`,
|
|
355
|
+
`${base}.spec.ts`,
|
|
356
|
+
`${base}.spec.tsx`,
|
|
357
|
+
`${base}.spec.js`
|
|
358
|
+
];
|
|
359
|
+
|
|
360
|
+
for (const variant of testVariants) {
|
|
361
|
+
const testPath = path.join(repoRoot, variant);
|
|
362
|
+
if (fs.existsSync(testPath)) {
|
|
363
|
+
testFiles.push(variant);
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Also check __tests__ directory
|
|
369
|
+
const dir = path.dirname(file);
|
|
370
|
+
const name = path.basename(file).replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
371
|
+
const testsDir = path.join(repoRoot, dir, "__tests__");
|
|
372
|
+
|
|
373
|
+
if (fs.existsSync(testsDir)) {
|
|
374
|
+
const testVariants = [
|
|
375
|
+
`${name}.test.ts`,
|
|
376
|
+
`${name}.test.tsx`,
|
|
377
|
+
`${name}.test.js`
|
|
378
|
+
];
|
|
379
|
+
|
|
380
|
+
for (const variant of testVariants) {
|
|
381
|
+
const testPath = path.join(testsDir, variant);
|
|
382
|
+
if (fs.existsSync(testPath)) {
|
|
383
|
+
testFiles.push(path.join(dir, "__tests__", variant));
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return [...new Set(testFiles)];
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
module.exports = {
|
|
394
|
+
runProofChain,
|
|
395
|
+
runStaticProof,
|
|
396
|
+
runBuildProof,
|
|
397
|
+
runRealityProof,
|
|
398
|
+
PROOF_LEVELS
|
|
399
|
+
};
|