@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.
- package/bin/registry.js +154 -338
- package/bin/runners/context/generators/mcp.js +13 -15
- package/bin/runners/context/proof-context.js +1 -248
- package/bin/runners/lib/analysis-core.js +180 -198
- package/bin/runners/lib/analyzers.js +223 -1669
- package/bin/runners/lib/cli-output.js +210 -242
- package/bin/runners/lib/detectors-v2.js +785 -547
- package/bin/runners/lib/entitlements-v2.js +458 -96
- package/bin/runners/lib/error-handler.js +9 -16
- package/bin/runners/lib/global-flags.js +0 -37
- package/bin/runners/lib/route-truth.js +322 -1167
- package/bin/runners/lib/scan-output.js +469 -448
- package/bin/runners/lib/ship-output.js +27 -280
- package/bin/runners/lib/terminal-ui.js +733 -231
- package/bin/runners/lib/truth.js +321 -1004
- package/bin/runners/lib/unified-output.js +158 -162
- package/bin/runners/lib/upsell.js +204 -104
- package/bin/runners/runAllowlist.js +324 -0
- package/bin/runners/runAuth.js +95 -324
- package/bin/runners/runCheckpoint.js +21 -39
- package/bin/runners/runContext.js +24 -136
- package/bin/runners/runDoctor.js +67 -115
- package/bin/runners/runEvidencePack.js +219 -0
- package/bin/runners/runFix.js +5 -6
- package/bin/runners/runGuard.js +118 -212
- package/bin/runners/runInit.js +2 -14
- package/bin/runners/runInstall.js +281 -0
- package/bin/runners/runLabs.js +341 -0
- package/bin/runners/runMcp.js +52 -130
- package/bin/runners/runPolish.js +20 -43
- package/bin/runners/runProve.js +3 -13
- package/bin/runners/runReality.js +0 -14
- package/bin/runners/runReport.js +2 -3
- package/bin/runners/runScan.js +44 -511
- package/bin/runners/runShip.js +14 -28
- package/bin/runners/runValidate.js +2 -19
- package/bin/runners/runWatch.js +54 -118
- package/bin/vibecheck.js +41 -148
- package/mcp-server/ARCHITECTURE.md +339 -0
- package/mcp-server/__tests__/cache.test.ts +313 -0
- package/mcp-server/__tests__/executor.test.ts +239 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
- package/mcp-server/__tests__/ids.test.ts +345 -0
- package/mcp-server/__tests__/integration/tools.test.ts +410 -0
- package/mcp-server/__tests__/registry.test.ts +365 -0
- package/mcp-server/__tests__/sandbox.test.ts +323 -0
- package/mcp-server/__tests__/schemas.test.ts +372 -0
- package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
- package/mcp-server/examples/doctor.request.json +14 -0
- package/mcp-server/examples/doctor.response.json +53 -0
- package/mcp-server/examples/error.response.json +15 -0
- package/mcp-server/examples/scan.request.json +14 -0
- package/mcp-server/examples/scan.response.json +108 -0
- package/mcp-server/handlers/tool-handler.ts +671 -0
- package/mcp-server/index-v3.ts +293 -0
- package/mcp-server/index.js +1072 -1573
- package/mcp-server/index.old.js +4137 -0
- package/mcp-server/lib/cache.ts +341 -0
- package/mcp-server/lib/errors.ts +346 -0
- package/mcp-server/lib/executor.ts +792 -0
- package/mcp-server/lib/ids.ts +238 -0
- package/mcp-server/lib/logger.ts +368 -0
- package/mcp-server/lib/metrics.ts +365 -0
- package/mcp-server/lib/sandbox.ts +337 -0
- package/mcp-server/lib/validator.ts +229 -0
- package/mcp-server/package-lock.json +165 -0
- package/mcp-server/package.json +32 -7
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/registry/tools.json +476 -0
- package/mcp-server/schemas/error-envelope.schema.json +125 -0
- package/mcp-server/schemas/finding.schema.json +167 -0
- package/mcp-server/schemas/report-artifact.schema.json +88 -0
- package/mcp-server/schemas/run-request.schema.json +75 -0
- package/mcp-server/schemas/verdict.schema.json +168 -0
- package/mcp-server/tier-auth.d.ts +71 -0
- package/mcp-server/tier-auth.js +371 -183
- package/mcp-server/truth-context.js +90 -131
- package/mcp-server/truth-firewall-tools.js +1000 -1611
- package/mcp-server/tsconfig.json +34 -0
- package/mcp-server/vibecheck-tools.js +2 -2
- package/mcp-server/vitest.config.ts +16 -0
- package/package.json +3 -4
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
- package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
- package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
- package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
- package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
- package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
- package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
- package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
- package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
- package/bin/runners/lib/agent-firewall/logger.js +0 -141
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
- package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
- package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
- package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
- package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
- package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
- package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
- package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
- package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
- package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
- package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
- package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
- package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
- package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
- package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
- package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
- package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
- package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
- package/bin/runners/lib/api-client.js +0 -269
- package/bin/runners/lib/authority-badge.js +0 -425
- package/bin/runners/lib/engines/accessibility-engine.js +0 -190
- package/bin/runners/lib/engines/api-consistency-engine.js +0 -162
- package/bin/runners/lib/engines/ast-cache.js +0 -99
- package/bin/runners/lib/engines/code-quality-engine.js +0 -255
- package/bin/runners/lib/engines/console-logs-engine.js +0 -115
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -268
- package/bin/runners/lib/engines/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
- package/bin/runners/lib/engines/empty-catch-engine.js +0 -150
- package/bin/runners/lib/engines/file-filter.js +0 -131
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
- package/bin/runners/lib/engines/mock-data-engine.js +0 -272
- package/bin/runners/lib/engines/parallel-processor.js +0 -71
- package/bin/runners/lib/engines/performance-issues-engine.js +0 -265
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -243
- package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
- package/bin/runners/lib/engines/type-aware-engine.js +0 -152
- package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
- package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
- package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -15
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -139
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
- package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
- package/bin/runners/lib/exit-codes.js +0 -275
- package/bin/runners/lib/fingerprint.js +0 -377
- package/bin/runners/lib/help-formatter.js +0 -413
- package/bin/runners/lib/logger.js +0 -38
- package/bin/runners/lib/ship-output-enterprise.js +0 -239
- package/bin/runners/lib/unified-cli-output.js +0 -604
- package/bin/runners/runAgent.d.ts +0 -5
- package/bin/runners/runAgent.js +0 -161
- package/bin/runners/runApprove.js +0 -1200
- package/bin/runners/runClassify.js +0 -859
- package/bin/runners/runContext.d.ts +0 -4
- package/bin/runners/runFirewall.d.ts +0 -5
- package/bin/runners/runFirewall.js +0 -134
- package/bin/runners/runFirewallHook.d.ts +0 -5
- package/bin/runners/runFirewallHook.js +0 -56
- package/bin/runners/runPolish.d.ts +0 -4
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runTruth.d.ts +0 -5
- package/bin/runners/runTruth.js +0 -101
- package/mcp-server/HARDENING_SUMMARY.md +0 -299
- package/mcp-server/agent-firewall-interceptor.js +0 -500
- package/mcp-server/authority-tools.js +0 -569
- package/mcp-server/conductor/conflict-resolver.js +0 -588
- package/mcp-server/conductor/execution-planner.js +0 -544
- package/mcp-server/conductor/index.js +0 -377
- package/mcp-server/conductor/lock-manager.js +0 -615
- package/mcp-server/conductor/request-queue.js +0 -550
- package/mcp-server/conductor/session-manager.js +0 -500
- package/mcp-server/conductor/tools.js +0 -510
- package/mcp-server/lib/api-client.cjs +0 -13
- package/mcp-server/lib/logger.cjs +0 -30
- package/mcp-server/logger.js +0 -173
- package/mcp-server/tools-v3.js +0 -706
- package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI Output Utilities -
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - 🛡️ Atomic file writes (no corruption on crash)
|
|
7
|
-
* - 🔄 Automatic "latest" symlinking for easy debugging
|
|
8
|
-
* - 🕵️ Deep CI/Git context extraction
|
|
9
|
-
* - 🛑 Beautiful Crash Reporting (matches UI style)
|
|
10
|
-
* - 🧹 Automatic Log Rotation
|
|
2
|
+
* CLI Output Utilities - World-Class Consistency
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized JSON output, run ID generation,
|
|
5
|
+
* and artifact management for all CLI commands.
|
|
11
6
|
*/
|
|
12
7
|
|
|
13
8
|
"use strict";
|
|
@@ -15,154 +10,50 @@
|
|
|
15
10
|
const fs = require("fs");
|
|
16
11
|
const path = require("path");
|
|
17
12
|
const crypto = require("crypto");
|
|
18
|
-
const os = require("os");
|
|
19
|
-
const childProcess = require("child_process");
|
|
20
|
-
const chalk = require("chalk"); // Added for premium error reporting
|
|
21
|
-
|
|
22
|
-
// Re-export exit codes for backward compatibility
|
|
23
|
-
const { EXIT, verdictToExitCode } = require("./exit-codes");
|
|
24
|
-
|
|
25
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
26
|
-
// CONFIGURATION
|
|
27
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
28
|
-
|
|
29
|
-
const CONFIG = {
|
|
30
|
-
DIR_NAME: ".vibecheck",
|
|
31
|
-
MAX_RETAINED_RUNS: 50, // Keep last 50 runs, delete older
|
|
32
|
-
WIDTH: 76,
|
|
33
|
-
};
|
|
34
13
|
|
|
35
14
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
15
|
// RUN ID GENERATION
|
|
37
16
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
38
17
|
|
|
39
18
|
/**
|
|
40
|
-
* Generate a unique
|
|
41
|
-
* Format: YYYY-MM-DD-HHmm-UUID
|
|
19
|
+
* Generate a unique run ID for tracking
|
|
42
20
|
*/
|
|
43
21
|
function generateRunId() {
|
|
44
|
-
|
|
45
|
-
const uuid = crypto.randomUUID().slice(0, 8);
|
|
46
|
-
return `${date}-${uuid}`;
|
|
22
|
+
return crypto.randomUUID();
|
|
47
23
|
}
|
|
48
24
|
|
|
49
25
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
50
|
-
//
|
|
51
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
52
|
-
|
|
53
|
-
function getSystemContext() {
|
|
54
|
-
return {
|
|
55
|
-
platform: os.platform(),
|
|
56
|
-
arch: os.arch(),
|
|
57
|
-
node: process.version,
|
|
58
|
-
cpus: os.cpus().length,
|
|
59
|
-
memory: Math.round(os.totalmem() / 1024 / 1024 / 1024) + 'GB',
|
|
60
|
-
cwd: process.cwd(),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function getGitContext() {
|
|
65
|
-
try {
|
|
66
|
-
const commit = childProcess.execSync('git rev-parse --short HEAD', { stdio: 'pipe' }).toString().trim();
|
|
67
|
-
const branch = childProcess.execSync('git rev-parse --abbrev-ref HEAD', { stdio: 'pipe' }).toString().trim();
|
|
68
|
-
const isDirty = childProcess.execSync('git status --porcelain', { stdio: 'pipe' }).toString().trim().length > 0;
|
|
69
|
-
return { commit, branch, isDirty };
|
|
70
|
-
} catch (e) {
|
|
71
|
-
return null; // Not a git repo
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function getCiContext() {
|
|
76
|
-
if (process.env.GITHUB_ACTIONS) return { provider: 'GitHub Actions', runId: process.env.GITHUB_RUN_ID };
|
|
77
|
-
if (process.env.GITLAB_CI) return { provider: 'GitLab CI', jobId: process.env.CI_JOB_ID };
|
|
78
|
-
if (process.env.JENKINS_URL) return { provider: 'Jenkins', buildUrl: process.env.BUILD_URL };
|
|
79
|
-
if (process.env.CI) return { provider: 'Generic CI' };
|
|
80
|
-
return { provider: null };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
84
|
-
// FILESYSTEM OPS (Atomic & Safe)
|
|
26
|
+
// OUTPUT DIRECTORY MANAGEMENT
|
|
85
27
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
86
28
|
|
|
87
29
|
/**
|
|
88
|
-
*
|
|
30
|
+
* Get run directory paths
|
|
89
31
|
*/
|
|
90
|
-
function safeWriteJson(filePath, data) {
|
|
91
|
-
const tempPath = `${filePath}.tmp.${crypto.randomUUID().slice(0, 6)}`;
|
|
92
|
-
try {
|
|
93
|
-
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
|
|
94
|
-
fs.renameSync(tempPath, filePath); // Atomic operation
|
|
95
|
-
} catch (err) {
|
|
96
|
-
try { fs.unlinkSync(tempPath); } catch (e) {} // Cleanup
|
|
97
|
-
throw err;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function updateSymlink(target, linkPath) {
|
|
102
|
-
try {
|
|
103
|
-
if (fs.existsSync(linkPath)) fs.unlinkSync(linkPath);
|
|
104
|
-
// 'junction' type is required for Windows to not require Admin
|
|
105
|
-
fs.symlinkSync(target, linkPath, 'junction');
|
|
106
|
-
} catch (e) {
|
|
107
|
-
// Ignore symlink errors (often permissions)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Cleanup old runs to save disk space (Log Rotation)
|
|
113
|
-
*/
|
|
114
|
-
function rotateLogs(runsDir) {
|
|
115
|
-
try {
|
|
116
|
-
if (!fs.existsSync(runsDir)) return;
|
|
117
|
-
|
|
118
|
-
const runs = fs.readdirSync(runsDir)
|
|
119
|
-
.map(name => ({ name, path: path.join(runsDir, name) }))
|
|
120
|
-
.filter(item => fs.statSync(item.path).isDirectory() && item.name !== 'latest')
|
|
121
|
-
.sort((a, b) => b.name.localeCompare(a.name)); // Newest first
|
|
122
|
-
|
|
123
|
-
if (runs.length > CONFIG.MAX_RETAINED_RUNS) {
|
|
124
|
-
const toDelete = runs.slice(CONFIG.MAX_RETAINED_RUNS);
|
|
125
|
-
toDelete.forEach(run => fs.rmSync(run.path, { recursive: true, force: true }));
|
|
126
|
-
}
|
|
127
|
-
} catch (e) {
|
|
128
|
-
// Non-blocking cleanup failure
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
133
|
-
// OUTPUT DIRECTORY MANAGEMENT
|
|
134
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
135
|
-
|
|
136
32
|
function getRunPaths(runId, projectPath = process.cwd()) {
|
|
137
|
-
const
|
|
138
|
-
const runDir = path.join(baseDir, "runs", runId);
|
|
139
|
-
const latestLink = path.join(baseDir, "runs", "latest");
|
|
33
|
+
const runDir = path.join(projectPath, ".vibecheck", "runs", runId);
|
|
140
34
|
const artifactsDir = path.join(runDir, "artifacts");
|
|
141
35
|
|
|
142
36
|
// Ensure directories exist
|
|
143
|
-
fs.mkdirSync(
|
|
144
|
-
|
|
145
|
-
// Update 'latest' symlink for easy debugging
|
|
146
|
-
updateSymlink(runDir, latestLink);
|
|
37
|
+
if (!fs.existsSync(runDir)) fs.mkdirSync(runDir, { recursive: true });
|
|
38
|
+
if (!fs.existsSync(artifactsDir)) fs.mkdirSync(artifactsDir, { recursive: true });
|
|
147
39
|
|
|
148
|
-
// Trigger cleanup async (don't block the CLI)
|
|
149
|
-
setTimeout(() => rotateLogs(path.join(baseDir, "runs")), 100).unref();
|
|
150
|
-
|
|
151
40
|
return {
|
|
152
41
|
runDir,
|
|
153
42
|
artifactsDir,
|
|
154
43
|
manifestPath: path.join(runDir, "manifest.json"),
|
|
155
44
|
commandPath: path.join(runDir, "command.json"),
|
|
156
|
-
crashPath: path.join(runDir, "crash.json"),
|
|
157
45
|
};
|
|
158
46
|
}
|
|
159
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Save artifact to run directory
|
|
50
|
+
*/
|
|
160
51
|
function saveArtifact(runId, name, data, type = "json") {
|
|
161
52
|
const { artifactsDir } = getRunPaths(runId);
|
|
162
53
|
const artifactPath = path.join(artifactsDir, `${name}.${type}`);
|
|
163
54
|
|
|
164
55
|
if (type === "json") {
|
|
165
|
-
|
|
56
|
+
fs.writeFileSync(artifactPath, JSON.stringify(data, null, 2));
|
|
166
57
|
} else {
|
|
167
58
|
fs.writeFileSync(artifactPath, data);
|
|
168
59
|
}
|
|
@@ -174,6 +65,9 @@ function saveArtifact(runId, name, data, type = "json") {
|
|
|
174
65
|
// JSON OUTPUT SCHEMA
|
|
175
66
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
176
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Create standardized JSON output
|
|
70
|
+
*/
|
|
177
71
|
function createJsonOutput(options) {
|
|
178
72
|
const {
|
|
179
73
|
runId,
|
|
@@ -188,71 +82,84 @@ function createJsonOutput(options) {
|
|
|
188
82
|
artifacts = [],
|
|
189
83
|
} = options;
|
|
190
84
|
|
|
191
|
-
|
|
85
|
+
const output = {
|
|
86
|
+
runId,
|
|
87
|
+
command,
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
duration: startTime ? Date.now() - new Date(startTime).getTime() : null,
|
|
90
|
+
exitCode,
|
|
91
|
+
verdict,
|
|
92
|
+
result,
|
|
192
93
|
meta: {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
system: getSystemContext(),
|
|
197
|
-
git: getGitContext(),
|
|
198
|
-
ci: getCiContext(),
|
|
94
|
+
tier,
|
|
95
|
+
version,
|
|
96
|
+
path: projectPath,
|
|
199
97
|
},
|
|
200
|
-
run: {
|
|
201
|
-
id: runId,
|
|
202
|
-
command,
|
|
203
|
-
durationMs: startTime ? Date.now() - new Date(startTime).getTime() : 0,
|
|
204
|
-
exitCode,
|
|
205
|
-
verdict,
|
|
206
|
-
},
|
|
207
|
-
// The actual data payload
|
|
208
|
-
data: result,
|
|
209
|
-
// Links to files created
|
|
210
98
|
artifacts: artifacts.map(art => ({
|
|
211
99
|
type: art.type,
|
|
212
|
-
|
|
213
|
-
path: path.relative(projectPath, art.path), // Relative for portability
|
|
100
|
+
path: path.relative(projectPath, art.path),
|
|
214
101
|
description: art.description,
|
|
215
102
|
})),
|
|
216
103
|
};
|
|
104
|
+
|
|
105
|
+
return output;
|
|
217
106
|
}
|
|
218
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Write JSON output to file or stdout
|
|
110
|
+
*/
|
|
219
111
|
function writeJsonOutput(output, outputPath) {
|
|
220
112
|
const jsonString = JSON.stringify(output, null, 2);
|
|
221
113
|
|
|
222
114
|
if (outputPath) {
|
|
223
|
-
|
|
224
|
-
safeWriteJson(outputPath, output);
|
|
115
|
+
fs.writeFileSync(outputPath, jsonString);
|
|
225
116
|
return outputPath;
|
|
226
117
|
} else {
|
|
227
|
-
|
|
228
|
-
process.stdout.write(jsonString + '\n');
|
|
118
|
+
console.log(jsonString);
|
|
229
119
|
return null;
|
|
230
120
|
}
|
|
231
121
|
}
|
|
232
122
|
|
|
233
123
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
234
|
-
//
|
|
124
|
+
// VERDCT MAPPING
|
|
235
125
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
236
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Map exit codes to verdict strings
|
|
129
|
+
*/
|
|
237
130
|
function exitCodeToVerdict(exitCode) {
|
|
238
|
-
|
|
239
|
-
0: "SHIP"
|
|
240
|
-
1: "WARN"
|
|
241
|
-
2: "BLOCK"
|
|
242
|
-
3: "FEATURE_DENIED"
|
|
243
|
-
4: "INVALID_INPUT"
|
|
244
|
-
5: "INTERNAL_ERROR"
|
|
245
|
-
|
|
246
|
-
|
|
131
|
+
switch (exitCode) {
|
|
132
|
+
case 0: return "SHIP";
|
|
133
|
+
case 1: return "WARN";
|
|
134
|
+
case 2: return "BLOCK";
|
|
135
|
+
case 3: return "FEATURE_DENIED";
|
|
136
|
+
case 4: return "INVALID_INPUT";
|
|
137
|
+
case 5: return "INTERNAL_ERROR";
|
|
138
|
+
default: return "UNKNOWN";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Map verdict to exit code
|
|
144
|
+
*/
|
|
145
|
+
function verdictToExitCode(verdict) {
|
|
146
|
+
switch (verdict?.toUpperCase()) {
|
|
147
|
+
case "SHIP": return 0;
|
|
148
|
+
case "WARN": return 1;
|
|
149
|
+
case "BLOCK": return 2;
|
|
150
|
+
case "FEATURE_DENIED": return 3;
|
|
151
|
+
case "INVALID_INPUT": return 4;
|
|
152
|
+
case "INTERNAL_ERROR": return 5;
|
|
153
|
+
default: return 5;
|
|
154
|
+
}
|
|
247
155
|
}
|
|
248
156
|
|
|
249
157
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
250
|
-
// COMMAND WRAPPER
|
|
158
|
+
// COMMAND WRAPPER
|
|
251
159
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
252
160
|
|
|
253
161
|
/**
|
|
254
|
-
* Wrap a command runner with
|
|
255
|
-
* telemetry, and crash protection.
|
|
162
|
+
* Wrap a command runner with standard output handling
|
|
256
163
|
*/
|
|
257
164
|
async function withStandardOutput(commandFn, options = {}) {
|
|
258
165
|
const {
|
|
@@ -261,88 +168,104 @@ async function withStandardOutput(commandFn, options = {}) {
|
|
|
261
168
|
runId = generateRunId(),
|
|
262
169
|
json = false,
|
|
263
170
|
output = null,
|
|
171
|
+
ci = false,
|
|
172
|
+
verbose = false,
|
|
264
173
|
tier = "free",
|
|
265
174
|
version = "1.0.0",
|
|
266
175
|
} = options;
|
|
267
176
|
|
|
177
|
+
// Initialize paths
|
|
268
178
|
const paths = getRunPaths(runId);
|
|
269
179
|
const artifacts = [];
|
|
270
180
|
|
|
271
|
-
// Artifact helper injected into the command
|
|
272
|
-
const artifactSaver = (name, data, type = 'json') => {
|
|
273
|
-
try {
|
|
274
|
-
const artifactPath = saveArtifact(runId, name, data, type);
|
|
275
|
-
artifacts.push({ type, path: artifactPath, description: name });
|
|
276
|
-
return artifactPath;
|
|
277
|
-
} catch (e) {
|
|
278
|
-
console.error(chalk.yellow(`⚠️ Warning: Failed to save artifact ${name}: ${e.message}`));
|
|
279
|
-
return null;
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
|
|
283
181
|
try {
|
|
284
|
-
//
|
|
182
|
+
// Run the command
|
|
285
183
|
const result = await commandFn({
|
|
286
184
|
runId,
|
|
287
185
|
paths,
|
|
288
|
-
saveArtifact:
|
|
186
|
+
saveArtifact: (name, data, type) => {
|
|
187
|
+
const artifactPath = saveArtifact(runId, name, data, type);
|
|
188
|
+
artifacts.push({
|
|
189
|
+
type,
|
|
190
|
+
path: artifactPath,
|
|
191
|
+
description: `${name} artifact`,
|
|
192
|
+
});
|
|
193
|
+
return artifactPath;
|
|
194
|
+
},
|
|
289
195
|
});
|
|
290
196
|
|
|
291
|
-
//
|
|
292
|
-
const exitCode = typeof result === "number" ? result :
|
|
197
|
+
// Extract exit code and verdict
|
|
198
|
+
const exitCode = typeof result === "number" ? result : result.exitCode || 0;
|
|
293
199
|
const verdict = result.verdict || exitCodeToVerdict(exitCode);
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const outputObj = createJsonOutput({
|
|
297
|
-
runId, command, startTime, exitCode, verdict,
|
|
298
|
-
result: resultData, tier, version, artifacts
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
// 1. Always save to internal history
|
|
302
|
-
safeWriteJson(paths.commandPath, outputObj);
|
|
303
|
-
|
|
304
|
-
// 2. If JSON requested by user, print/write it
|
|
200
|
+
|
|
201
|
+
// Create JSON output if requested
|
|
305
202
|
if (json) {
|
|
306
|
-
|
|
203
|
+
const jsonOutput = createJsonOutput({
|
|
204
|
+
runId,
|
|
205
|
+
command,
|
|
206
|
+
startTime,
|
|
207
|
+
exitCode,
|
|
208
|
+
verdict,
|
|
209
|
+
result: typeof result === "object" ? result : {},
|
|
210
|
+
tier,
|
|
211
|
+
version,
|
|
212
|
+
artifacts,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
writeJsonOutput(jsonOutput, output);
|
|
307
216
|
}
|
|
308
|
-
|
|
217
|
+
|
|
218
|
+
// Save command output to run directory
|
|
219
|
+
const commandOutput = {
|
|
220
|
+
exitCode,
|
|
221
|
+
verdict,
|
|
222
|
+
result: typeof result === "object" ? result : {},
|
|
223
|
+
artifacts,
|
|
224
|
+
};
|
|
225
|
+
fs.writeFileSync(paths.commandPath, JSON.stringify(commandOutput, null, 2));
|
|
226
|
+
|
|
227
|
+
// Update stable pointer
|
|
228
|
+
const lastPath = path.join(process.cwd(), ".vibecheck", "last", `${command}.json`);
|
|
229
|
+
if (!fs.existsSync(path.dirname(lastPath))) {
|
|
230
|
+
fs.mkdirSync(path.dirname(lastPath), { recursive: true });
|
|
231
|
+
}
|
|
232
|
+
fs.writeFileSync(lastPath, JSON.stringify(commandOutput, null, 2));
|
|
233
|
+
|
|
309
234
|
return exitCode;
|
|
310
|
-
|
|
311
235
|
} catch (error) {
|
|
312
|
-
//
|
|
236
|
+
// Handle errors consistently
|
|
313
237
|
const exitCode = error.exitCode || 5;
|
|
314
238
|
const verdict = "INTERNAL_ERROR";
|
|
315
239
|
|
|
316
|
-
const errorData = {
|
|
317
|
-
message: error.message,
|
|
318
|
-
stack: error.stack,
|
|
319
|
-
code: error.code || 'UNKNOWN',
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
const outputObj = createJsonOutput({
|
|
323
|
-
runId, command, startTime, exitCode, verdict,
|
|
324
|
-
result: { error: errorData }, tier, version, artifacts
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Save crash report to disk
|
|
328
|
-
safeWriteJson(paths.crashPath, outputObj);
|
|
329
|
-
safeWriteJson(paths.commandPath, outputObj);
|
|
330
|
-
|
|
331
240
|
if (json) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
241
|
+
const jsonOutput = createJsonOutput({
|
|
242
|
+
runId,
|
|
243
|
+
command,
|
|
244
|
+
startTime,
|
|
245
|
+
exitCode,
|
|
246
|
+
verdict,
|
|
247
|
+
result: {
|
|
248
|
+
error: error.message,
|
|
249
|
+
stack: error.stack,
|
|
250
|
+
},
|
|
251
|
+
tier,
|
|
252
|
+
version,
|
|
253
|
+
artifacts,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
writeJsonOutput(jsonOutput, output);
|
|
343
257
|
}
|
|
344
|
-
|
|
345
|
-
|
|
258
|
+
|
|
259
|
+
// Save error to run directory
|
|
260
|
+
const commandOutput = {
|
|
261
|
+
exitCode,
|
|
262
|
+
verdict,
|
|
263
|
+
error: error.message,
|
|
264
|
+
artifacts,
|
|
265
|
+
};
|
|
266
|
+
fs.writeFileSync(paths.commandPath, JSON.stringify(commandOutput, null, 2));
|
|
267
|
+
|
|
268
|
+
throw error;
|
|
346
269
|
}
|
|
347
270
|
}
|
|
348
271
|
|
|
@@ -350,10 +273,13 @@ async function withStandardOutput(commandFn, options = {}) {
|
|
|
350
273
|
// STANDARD FLAGS PARSER
|
|
351
274
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
352
275
|
|
|
276
|
+
/**
|
|
277
|
+
* Parse standard CLI flags
|
|
278
|
+
*/
|
|
353
279
|
function parseStandardFlags(args) {
|
|
354
280
|
const flags = {
|
|
355
281
|
json: false,
|
|
356
|
-
ci:
|
|
282
|
+
ci: false,
|
|
357
283
|
path: process.cwd(),
|
|
358
284
|
output: null,
|
|
359
285
|
verbose: false,
|
|
@@ -361,40 +287,82 @@ function parseStandardFlags(args) {
|
|
|
361
287
|
help: false,
|
|
362
288
|
version: false,
|
|
363
289
|
debug: false,
|
|
290
|
+
quiet: false,
|
|
364
291
|
};
|
|
365
292
|
|
|
366
|
-
const parsed =
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
293
|
+
const parsed = args.filter(arg => {
|
|
294
|
+
switch (arg) {
|
|
295
|
+
case "--json":
|
|
296
|
+
case "-j":
|
|
297
|
+
flags.json = true;
|
|
298
|
+
return false;
|
|
299
|
+
case "--ci":
|
|
300
|
+
flags.ci = true;
|
|
301
|
+
return false;
|
|
302
|
+
case "--verbose":
|
|
303
|
+
case "-v":
|
|
304
|
+
flags.verbose = true;
|
|
305
|
+
return false;
|
|
306
|
+
case "--strict":
|
|
307
|
+
flags.strict = true;
|
|
308
|
+
return false;
|
|
309
|
+
case "--help":
|
|
310
|
+
case "-h":
|
|
311
|
+
flags.help = true;
|
|
312
|
+
return false;
|
|
313
|
+
case "--version":
|
|
314
|
+
case "-V":
|
|
315
|
+
flags.version = true;
|
|
316
|
+
return false;
|
|
317
|
+
case "--debug":
|
|
318
|
+
case "-d":
|
|
319
|
+
flags.debug = true;
|
|
320
|
+
return false;
|
|
321
|
+
case "--quiet":
|
|
322
|
+
case "-q":
|
|
323
|
+
flags.quiet = true;
|
|
324
|
+
return false;
|
|
325
|
+
default:
|
|
326
|
+
if (arg.startsWith("--path=")) {
|
|
327
|
+
flags.path = arg.split("=")[1];
|
|
328
|
+
return false;
|
|
329
|
+
} else if (arg.startsWith("-p")) {
|
|
330
|
+
const idx = args.indexOf(arg);
|
|
331
|
+
if (idx < args.length - 1) {
|
|
332
|
+
flags.path = args[idx + 1];
|
|
333
|
+
args.splice(idx, 2);
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
} else if (arg.startsWith("--output=")) {
|
|
337
|
+
flags.output = arg.split("=")[1];
|
|
338
|
+
return false;
|
|
339
|
+
} else if (arg.startsWith("-o")) {
|
|
340
|
+
const idx = args.indexOf(arg);
|
|
341
|
+
if (idx < args.length - 1) {
|
|
342
|
+
flags.output = args[idx + 1];
|
|
343
|
+
args.splice(idx, 2);
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
384
350
|
|
|
385
351
|
return { flags, parsed };
|
|
386
352
|
}
|
|
387
353
|
|
|
354
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
355
|
+
// EXPORTS
|
|
356
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
357
|
+
|
|
388
358
|
module.exports = {
|
|
389
359
|
generateRunId,
|
|
390
360
|
getRunPaths,
|
|
391
361
|
saveArtifact,
|
|
392
362
|
createJsonOutput,
|
|
393
363
|
writeJsonOutput,
|
|
394
|
-
exitCodeToVerdict,
|
|
395
|
-
// Re-exported from exit-codes.js
|
|
364
|
+
exitCodeToVerdict,
|
|
396
365
|
verdictToExitCode,
|
|
397
|
-
EXIT,
|
|
398
366
|
withStandardOutput,
|
|
399
367
|
parseStandardFlags,
|
|
400
|
-
};
|
|
368
|
+
};
|