@vibecheckai/cli 3.1.8 → 3.2.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 +106 -116
- package/bin/runners/context/generators/mcp.js +18 -0
- package/bin/runners/context/index.js +72 -4
- package/bin/runners/context/proof-context.js +293 -1
- package/bin/runners/context/security-scanner.js +311 -73
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +214 -0
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
- package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +214 -0
- package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +118 -0
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +142 -0
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +84 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +72 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +143 -0
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +61 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
- package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
- package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
- package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +116 -0
- package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
- package/bin/runners/lib/analysis-core.js +198 -180
- package/bin/runners/lib/analyzers.js +1394 -224
- package/bin/runners/lib/detectors-v2.js +560 -641
- package/bin/runners/lib/entitlements-v2.js +48 -1
- package/bin/runners/lib/evidence-pack.js +678 -0
- package/bin/runners/lib/fingerprint.js +377 -0
- package/bin/runners/lib/html-proof-report.js +913 -0
- package/bin/runners/lib/missions/plan.js +231 -41
- package/bin/runners/lib/missions/templates.js +125 -0
- package/bin/runners/lib/route-truth.js +1167 -322
- package/bin/runners/lib/scan-output.js +558 -235
- package/bin/runners/lib/ship-output.js +901 -641
- package/bin/runners/lib/truth.js +1004 -321
- package/bin/runners/runAgent.js +161 -0
- package/bin/runners/runCheckpoint.js +44 -3
- package/bin/runners/runContext.d.ts +4 -0
- package/bin/runners/runDoctor.js +10 -2
- package/bin/runners/runFirewall.js +134 -0
- package/bin/runners/runFirewallHook.js +56 -0
- package/bin/runners/runFix.js +51 -341
- package/bin/runners/runInit.js +11 -0
- package/bin/runners/runPolish.d.ts +4 -0
- package/bin/runners/runPolish.js +608 -29
- package/bin/runners/runProve.js +210 -25
- package/bin/runners/runReality.js +846 -101
- package/bin/runners/runScan.js +351 -14
- package/bin/runners/runShip.js +19 -3
- package/bin/runners/runTruth.js +89 -0
- package/bin/runners/runWatch.js +14 -1
- package/bin/vibecheck.js +32 -2
- package/mcp-server/agent-firewall-interceptor.js +164 -0
- package/mcp-server/consolidated-tools.js +408 -42
- package/mcp-server/index.js +498 -327
- package/mcp-server/proof-tools.js +571 -0
- package/mcp-server/tier-auth.js +22 -19
- package/mcp-server/tools-v3.js +744 -0
- package/mcp-server/truth-context.js +131 -90
- package/mcp-server/truth-firewall-tools.js +1494 -941
- package/package.json +3 -1
- package/bin/runners/runInstall.js +0 -281
- package/bin/runners/runLabs.js +0 -341
package/bin/runners/runFix.js
CHANGED
|
@@ -330,6 +330,17 @@ function getMissionIcon(missionType) {
|
|
|
330
330
|
'FIX_FAKE_SUCCESS': ICONS.ghost,
|
|
331
331
|
'FIX_ENV_CONTRACT': ICONS.env,
|
|
332
332
|
'FIX_DEAD_UI': ICONS.dead,
|
|
333
|
+
// New enhanced mission types
|
|
334
|
+
'FIX_EMPTY_CATCH': ICONS.bug,
|
|
335
|
+
'FIX_TEST_KEYS': ICONS.key,
|
|
336
|
+
'FIX_MOCK_DOMAINS': ICONS.link,
|
|
337
|
+
'FIX_PLACEHOLDER_DATA': ICONS.doc,
|
|
338
|
+
'FIX_HARDCODED_SECRETS': ICONS.lock,
|
|
339
|
+
'FIX_SIMULATED_BILLING': ICONS.money,
|
|
340
|
+
'FIX_SILENT_FALLBACK': ICONS.warning,
|
|
341
|
+
'SYNC_CONTRACTS': ICONS.graph,
|
|
342
|
+
'FIX_ROUTE_DRIFT': ICONS.route,
|
|
343
|
+
'FIX_AUTH_DRIFT': ICONS.shield,
|
|
333
344
|
};
|
|
334
345
|
return icons[missionType] || ICONS.mission;
|
|
335
346
|
}
|
|
@@ -344,6 +355,17 @@ function getMissionColor(missionType) {
|
|
|
344
355
|
'FIX_FAKE_SUCCESS': colors.medium,
|
|
345
356
|
'FIX_ENV_CONTRACT': colors.low,
|
|
346
357
|
'FIX_DEAD_UI': colors.low,
|
|
358
|
+
// New enhanced mission types
|
|
359
|
+
'FIX_EMPTY_CATCH': colors.high,
|
|
360
|
+
'FIX_TEST_KEYS': colors.critical,
|
|
361
|
+
'FIX_MOCK_DOMAINS': colors.critical,
|
|
362
|
+
'FIX_PLACEHOLDER_DATA': colors.medium,
|
|
363
|
+
'FIX_HARDCODED_SECRETS': colors.critical,
|
|
364
|
+
'FIX_SIMULATED_BILLING': colors.critical,
|
|
365
|
+
'FIX_SILENT_FALLBACK': colors.high,
|
|
366
|
+
'SYNC_CONTRACTS': colors.medium,
|
|
367
|
+
'FIX_ROUTE_DRIFT': colors.medium,
|
|
368
|
+
'FIX_AUTH_DRIFT': colors.critical,
|
|
347
369
|
};
|
|
348
370
|
return colorMap[missionType] || colors.accent;
|
|
349
371
|
}
|
|
@@ -579,7 +601,7 @@ async function runFix(args) {
|
|
|
579
601
|
|
|
580
602
|
// Show autopilot header if in autopilot mode
|
|
581
603
|
if (opts.autopilot) {
|
|
582
|
-
|
|
604
|
+
printLoopHeader(maxSteps, stagnationLimit);
|
|
583
605
|
}
|
|
584
606
|
|
|
585
607
|
for (let step = 1; step <= maxSteps; step++) {
|
|
@@ -801,349 +823,21 @@ async function runFix(args) {
|
|
|
801
823
|
return 1;
|
|
802
824
|
}
|
|
803
825
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
const scanResult = await loadLatestScan(projectPath);
|
|
813
|
-
if (!scanResult) {
|
|
814
|
-
console.error(`${c.red}Error:${c.reset} No scan results found. Run 'vibecheck scan' first.\n`);
|
|
815
|
-
return EXIT_CODES.MISCONFIG;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
// Filter to fixable findings
|
|
819
|
-
const fixable = scanResult.findings.filter(f => {
|
|
820
|
-
const ruleId = f.ruleId || '';
|
|
821
|
-
return f.autofixAvailable && ALLOWED_FIX_TYPES.includes(ruleId);
|
|
822
|
-
});
|
|
823
|
-
|
|
824
|
-
if (fixable.length === 0) {
|
|
825
|
-
console.log(`${c.green}✓${c.reset} No mechanical fixes available.\n`);
|
|
826
|
-
console.log(`${c.dim}All remaining issues require manual intervention.${c.reset}\n`);
|
|
827
|
-
return EXIT_CODES.PASS;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
console.log(`${c.bold}Fixable Issues (${fixable.length}):${c.reset}\n`);
|
|
831
|
-
|
|
832
|
-
for (const finding of fixable) {
|
|
833
|
-
const patch = generatePatchPreview(projectPath, finding);
|
|
834
|
-
|
|
835
|
-
console.log(`${c.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
836
|
-
console.log(`${c.bold}${finding.id?.full || finding.id}${c.reset} - ${finding.ruleId}`);
|
|
837
|
-
console.log(`${c.dim}File:${c.reset} ${finding.file}:${finding.line}`);
|
|
838
|
-
console.log(`${c.dim}Why:${c.reset} ${finding.message || finding.description}`);
|
|
839
|
-
console.log(`${c.dim}Evidence:${c.reset} ${finding.evidence?.[0]?.snippet || 'See file'}`);
|
|
840
|
-
console.log('');
|
|
841
|
-
console.log(`${c.bold}Proposed Change:${c.reset}`);
|
|
842
|
-
console.log(patch.preview);
|
|
843
|
-
console.log('');
|
|
844
|
-
console.log(`${c.dim}Risk:${c.reset} ${patch.risk}`);
|
|
845
|
-
console.log(`${c.dim}Verification:${c.reset} Re-run scan to confirm no regression`);
|
|
846
|
-
console.log('');
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
console.log(`${c.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
850
|
-
console.log(`\n${c.bold}To apply these fixes:${c.reset}`);
|
|
851
|
-
console.log(` ${c.cyan}vibecheck fix --apply${c.reset}\n`);
|
|
852
|
-
console.log(`${c.dim}This will:${c.reset}`);
|
|
853
|
-
console.log(` 1. Check for clean git state`);
|
|
854
|
-
console.log(` 2. Create branch: vibecheck/fix-<timestamp>`);
|
|
855
|
-
console.log(` 3. Apply patches with structured commits`);
|
|
856
|
-
console.log(` 4. Re-run scan to verify no regression\n`);
|
|
857
|
-
|
|
858
|
-
return EXIT_CODES.PASS;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
/**
|
|
862
|
-
* Apply fixes with proof-gating
|
|
863
|
-
*/
|
|
864
|
-
async function applyFixes(projectPath, opts) {
|
|
865
|
-
console.log(`\n${c.cyan}${c.bold}🔧 APPLYING FIXES${c.reset}\n`);
|
|
866
|
-
|
|
867
|
-
// Step 1: Check git state
|
|
868
|
-
if (!isGitClean(projectPath)) {
|
|
869
|
-
console.error(`${c.red}Error:${c.reset} Git working directory is not clean.`);
|
|
870
|
-
console.error(`${c.dim}Commit or stash your changes before applying fixes.${c.reset}\n`);
|
|
871
|
-
return EXIT_CODES.MISCONFIG;
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
const scanResult = await loadLatestScan(projectPath);
|
|
875
|
-
if (!scanResult) {
|
|
876
|
-
console.error(`${c.red}Error:${c.reset} No scan results found. Run 'vibecheck scan' first.\n`);
|
|
877
|
-
return EXIT_CODES.MISCONFIG;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
const fixable = scanResult.findings.filter(f => {
|
|
881
|
-
const ruleId = f.ruleId || '';
|
|
882
|
-
return f.autofixAvailable && ALLOWED_FIX_TYPES.includes(ruleId);
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
if (fixable.length === 0) {
|
|
886
|
-
console.log(`${c.green}✓${c.reset} No fixes to apply.\n`);
|
|
887
|
-
return EXIT_CODES.PASS;
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
// Step 2: Create branch
|
|
891
|
-
const branchName = `vibecheck/fix-${Date.now()}`;
|
|
892
|
-
try {
|
|
893
|
-
execSync(`git checkout -b ${branchName}`, { cwd: projectPath, stdio: 'pipe' });
|
|
894
|
-
console.log(`${c.green}✓${c.reset} Created branch: ${branchName}\n`);
|
|
895
|
-
} catch (err) {
|
|
896
|
-
console.error(`${c.red}Error:${c.reset} Failed to create branch: ${err.message}\n`);
|
|
897
|
-
return EXIT_CODES.INTERNAL;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
// Step 3: Apply fixes
|
|
901
|
-
let applied = 0;
|
|
902
|
-
let failed = 0;
|
|
903
|
-
|
|
904
|
-
for (const finding of fixable) {
|
|
905
|
-
try {
|
|
906
|
-
const result = await applyAutofix(projectPath, finding, opts);
|
|
907
|
-
if (result) {
|
|
908
|
-
applied++;
|
|
909
|
-
|
|
910
|
-
// Commit with structured message
|
|
911
|
-
const commitMsg = `fix(${finding.ruleId}): ${finding.id?.full || finding.id}\n\nFile: ${finding.file}:${finding.line}\nEvidence: ${finding.evidence?.[0]?.snippet || 'See scan results'}\n\nApplied by vibecheck fix --apply`;
|
|
912
|
-
|
|
913
|
-
try {
|
|
914
|
-
execSync(`git add "${finding.file}"`, { cwd: projectPath, stdio: 'pipe' });
|
|
915
|
-
execSync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { cwd: projectPath, stdio: 'pipe' });
|
|
916
|
-
} catch {
|
|
917
|
-
// File might not have changed, continue
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
console.log(`${c.green}✓${c.reset} Fixed: ${finding.id?.full || finding.id}`);
|
|
921
|
-
} else {
|
|
922
|
-
failed++;
|
|
923
|
-
console.log(`${c.yellow}⚠${c.reset} Skipped: ${finding.id?.full || finding.id}`);
|
|
924
|
-
}
|
|
925
|
-
} catch (error) {
|
|
926
|
-
failed++;
|
|
927
|
-
console.log(`${c.red}✗${c.reset} Error: ${finding.id?.full || finding.id} - ${error.message}`);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
console.log('');
|
|
932
|
-
console.log(`${c.bold}Summary:${c.reset}`);
|
|
933
|
-
console.log(` Applied: ${c.green}${applied}${c.reset}`);
|
|
934
|
-
console.log(` Skipped: ${c.yellow}${failed}${c.reset}`);
|
|
935
|
-
console.log('');
|
|
936
|
-
|
|
937
|
-
// Step 4: Re-run scan to verify
|
|
938
|
-
console.log(`${c.dim}Verifying fixes...${c.reset}\n`);
|
|
939
|
-
|
|
940
|
-
try {
|
|
941
|
-
const { runScan } = require('./runScan');
|
|
942
|
-
const verifyResult = await runScan(['--json', '--path', projectPath]);
|
|
943
|
-
|
|
944
|
-
if (verifyResult === 0 || verifyResult === EXIT_CODES.PASS) {
|
|
945
|
-
console.log(`${c.green}✓${c.reset} Verification passed - no regressions\n`);
|
|
946
|
-
} else {
|
|
947
|
-
console.log(`${c.yellow}⚠${c.reset} Verification found issues - review before merging\n`);
|
|
948
|
-
}
|
|
949
|
-
} catch {
|
|
950
|
-
console.log(`${c.dim}Run 'vibecheck scan' to verify manually.${c.reset}\n`);
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
console.log(`${c.bold}Rollback:${c.reset}`);
|
|
954
|
-
console.log(` ${c.cyan}git checkout main && git branch -D ${branchName}${c.reset}\n`);
|
|
955
|
-
|
|
956
|
-
return applied > 0 ? EXIT_CODES.PASS : EXIT_CODES.FAIL;
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
/**
|
|
960
|
-
* Check if git working directory is clean
|
|
961
|
-
*/
|
|
962
|
-
function isGitClean(projectPath) {
|
|
963
|
-
try {
|
|
964
|
-
const status = execSync('git status --porcelain', { cwd: projectPath, encoding: 'utf8' });
|
|
965
|
-
return status.trim() === '';
|
|
966
|
-
} catch {
|
|
967
|
-
return false;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
/**
|
|
972
|
-
* Generate patch preview for a finding
|
|
973
|
-
*/
|
|
974
|
-
function generatePatchPreview(projectPath, finding) {
|
|
975
|
-
const filePath = path.join(projectPath, finding.file);
|
|
976
|
-
|
|
977
|
-
if (!fs.existsSync(filePath)) {
|
|
978
|
-
return { preview: ` ${c.red}File not found${c.reset}`, risk: 'N/A' };
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
982
|
-
const lines = content.split('\n');
|
|
983
|
-
const lineIndex = finding.line - 1;
|
|
984
|
-
|
|
985
|
-
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
986
|
-
return { preview: ` ${c.red}Invalid line number${c.reset}`, risk: 'N/A' };
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
const before = lines[lineIndex];
|
|
990
|
-
let after = before;
|
|
991
|
-
let risk = 'Low';
|
|
992
|
-
|
|
993
|
-
// Generate preview based on rule type
|
|
994
|
-
switch (finding.ruleId) {
|
|
995
|
-
case 'empty-catch':
|
|
996
|
-
after = before.replace(/catch\s*(?:\(([^)]*)\))?\s*\{\s*\}/, (m, v) => {
|
|
997
|
-
const varName = v || 'err';
|
|
998
|
-
return `catch (${varName}) { console.error('Error:', ${varName}); throw ${varName}; }`;
|
|
999
|
-
});
|
|
1000
|
-
risk = 'Low - adds proper error handling';
|
|
1001
|
-
break;
|
|
1002
|
-
case 'dangerous-default':
|
|
1003
|
-
after = before.replace(/\s*(\|\||\?\?)\s*['"][^'"]*['"]/, '');
|
|
1004
|
-
risk = 'Medium - removes fallback (may require env var)';
|
|
1005
|
-
break;
|
|
1006
|
-
case 'placeholder-value':
|
|
1007
|
-
after = before.replace(/(CHANGEME|REPLACE_ME|YOUR_\w+|INSERT_\w+)/g, "/* TODO: Replace $1 */ ''");
|
|
1008
|
-
risk = 'Low - flags for manual replacement';
|
|
1009
|
-
break;
|
|
1010
|
-
default:
|
|
1011
|
-
return { preview: ` ${c.dim}No preview available${c.reset}`, risk: 'Unknown' };
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
return {
|
|
1015
|
-
preview: ` ${c.red}- ${before.trim()}${c.reset}\n ${c.green}+ ${after.trim()}${c.reset}`,
|
|
1016
|
-
risk,
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
async function applyAutofix(projectPath, finding, options) {
|
|
1021
|
-
const filePath = path.join(projectPath, finding.file);
|
|
1022
|
-
|
|
1023
|
-
if (!fs.existsSync(filePath)) {
|
|
1024
|
-
throw new Error(`File not found: ${finding.file}`);
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
1028
|
-
const lines = content.split('\n');
|
|
1029
|
-
const lineIndex = finding.line - 1;
|
|
1030
|
-
|
|
1031
|
-
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
1032
|
-
throw new Error(`Invalid line number: ${finding.line}`);
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
let newContent = content;
|
|
1036
|
-
const ruleId = finding.ruleId;
|
|
1037
|
-
|
|
1038
|
-
// Apply fixes based on rule type
|
|
1039
|
-
switch (ruleId) {
|
|
1040
|
-
case 'empty-catch':
|
|
1041
|
-
newContent = fixEmptyCatch(lines, lineIndex, filePath);
|
|
1042
|
-
break;
|
|
1043
|
-
case 'dangerous-default':
|
|
1044
|
-
newContent = fixDangerousDefault(lines, lineIndex, filePath);
|
|
1045
|
-
break;
|
|
1046
|
-
case 'placeholder-value':
|
|
1047
|
-
newContent = fixPlaceholderValue(lines, lineIndex, filePath);
|
|
1048
|
-
break;
|
|
1049
|
-
default:
|
|
1050
|
-
return false;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
if (newContent !== content) {
|
|
1054
|
-
if (!options.dryRun) {
|
|
1055
|
-
fs.writeFileSync(filePath, newContent, 'utf8');
|
|
1056
|
-
}
|
|
1057
|
-
return true;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
return false;
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
function fixEmptyCatch(lines, lineIndex, filePath) {
|
|
1064
|
-
const line = lines[lineIndex];
|
|
1065
|
-
const newLines = [...lines];
|
|
1066
|
-
|
|
1067
|
-
// Find the catch block
|
|
1068
|
-
if (line.includes('catch') && line.includes('{')) {
|
|
1069
|
-
// Simple case: catch {} on one line
|
|
1070
|
-
if (line.match(/catch\s*(?:\([^)]*\))?\s*\{\s*\}/)) {
|
|
1071
|
-
const indent = line.match(/^(\s*)/)?.[1] || '';
|
|
1072
|
-
newLines[lineIndex] = line.replace(
|
|
1073
|
-
/catch\s*(?:\(([^)]*)\))?\s*\{\s*\}/,
|
|
1074
|
-
(match, errVar) => {
|
|
1075
|
-
const varName = errVar || 'err';
|
|
1076
|
-
return `catch (${varName}) {\n${indent} console.error('Error:', ${varName});\n${indent} throw ${varName};\n${indent}}`;
|
|
1077
|
-
}
|
|
1078
|
-
);
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
return newLines.join('\n');
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
function fixDangerousDefault(lines, lineIndex, filePath) {
|
|
1086
|
-
const line = lines[lineIndex];
|
|
1087
|
-
const newLines = [...lines];
|
|
1088
|
-
|
|
1089
|
-
// Remove dangerous default
|
|
1090
|
-
if (line.includes('process.env.') && (line.includes('||') || line.includes('??'))) {
|
|
1091
|
-
newLines[lineIndex] = line.replace(
|
|
1092
|
-
/\s*(\|\||\?\?)\s*['"][^'"]*['"]/,
|
|
1093
|
-
''
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
return newLines.join('\n');
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
function fixPlaceholderValue(lines, lineIndex, filePath) {
|
|
1101
|
-
const line = lines[lineIndex];
|
|
1102
|
-
const newLines = [...lines];
|
|
1103
|
-
|
|
1104
|
-
// Replace placeholder with TODO comment
|
|
1105
|
-
newLines[lineIndex] = line.replace(
|
|
1106
|
-
/(CHANGEME|REPLACE_ME|YOUR_[A-Z0-9_]+|INSERT_[A-Z0-9_]+)/g,
|
|
1107
|
-
(match) => `/* TODO: Replace ${match} */ ''`
|
|
1108
|
-
);
|
|
1109
|
-
|
|
1110
|
-
return newLines.join('\n');
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
async function loadLatestScan(projectPath) {
|
|
1114
|
-
const scanDir = path.join(projectPath, '.vibecheck', 'reality-sniff', 'scans');
|
|
1115
|
-
|
|
1116
|
-
if (!fs.existsSync(scanDir)) {
|
|
1117
|
-
return null;
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
try {
|
|
1121
|
-
const files = fs.readdirSync(scanDir)
|
|
1122
|
-
.filter(f => f.endsWith('.json'))
|
|
1123
|
-
.map(f => ({
|
|
1124
|
-
name: f,
|
|
1125
|
-
path: path.join(scanDir, f),
|
|
1126
|
-
mtime: fs.statSync(path.join(scanDir, f)).mtime,
|
|
1127
|
-
}))
|
|
1128
|
-
.sort((a, b) => b.mtime - a.mtime);
|
|
1129
|
-
|
|
1130
|
-
if (files.length === 0) {
|
|
1131
|
-
return null;
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
const content = fs.readFileSync(files[0].path, 'utf8');
|
|
1135
|
-
return JSON.parse(content);
|
|
1136
|
-
} catch {
|
|
1137
|
-
return null;
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
826
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
827
|
+
// NOTE: Legacy rule-based fix functions (showFixPlan, applyFixes, etc.) were removed.
|
|
828
|
+
// The fix command now uses the mission-based system exclusively, which provides:
|
|
829
|
+
// - LLM-generated patches with Reality Firewall prompt
|
|
830
|
+
// - Automatic backup/restore on failure
|
|
831
|
+
// - Progress detection and stagnation handling
|
|
832
|
+
// - Integration with ship verification
|
|
833
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1140
834
|
|
|
1141
835
|
function parseArgs(args) {
|
|
1142
836
|
// Parse global flags first
|
|
1143
837
|
const { flags: globalFlags, cleanArgs } = parseGlobalFlags(args);
|
|
1144
838
|
|
|
1145
839
|
const opts = {
|
|
1146
|
-
...globalFlags, // Merge global flags (json, verbose, noBanner, quiet, ci, etc.)
|
|
840
|
+
...globalFlags, // Merge global flags (json, verbose, noBanner, quiet, ci, help, etc.)
|
|
1147
841
|
path: globalFlags.path || process.cwd(),
|
|
1148
842
|
apply: false,
|
|
1149
843
|
promptOnly: false,
|
|
@@ -1153,7 +847,7 @@ function parseArgs(args) {
|
|
|
1153
847
|
maxSteps: 10,
|
|
1154
848
|
stagnationLimit: 2,
|
|
1155
849
|
fastifyEntry: null,
|
|
1156
|
-
|
|
850
|
+
// Note: help comes from globalFlags, don't override it here
|
|
1157
851
|
};
|
|
1158
852
|
|
|
1159
853
|
// Parse command-specific args from cleanArgs
|
|
@@ -1208,13 +902,29 @@ function printHelp(showBanner = true) {
|
|
|
1208
902
|
${colors.shipGreen}${ICONS.stop}${c.reset} Progress detector stops on stagnation
|
|
1209
903
|
|
|
1210
904
|
${c.bold}Mission Types:${c.reset}
|
|
905
|
+
${c.dim}Security & Auth:${c.reset}
|
|
1211
906
|
${colors.critical}${ICONS.lock}${c.reset} REMOVE_OWNER_MODE ${c.dim}Delete backdoor env bypass${c.reset}
|
|
907
|
+
${colors.critical}${ICONS.lock}${c.reset} FIX_HARDCODED_SECRETS ${c.dim}Move secrets to env vars${c.reset}
|
|
908
|
+
${colors.critical}${ICONS.key}${c.reset} FIX_TEST_KEYS ${c.dim}Replace test API keys${c.reset}
|
|
909
|
+
${colors.critical}${ICONS.shield}${c.reset} FIX_AUTH_DRIFT ${c.dim}Restore removed auth patterns${c.reset}
|
|
910
|
+
${colors.medium}${ICONS.auth}${c.reset} ADD_SERVER_AUTH ${c.dim}Add auth to sensitive endpoints${c.reset}
|
|
911
|
+
|
|
912
|
+
${c.dim}Billing & Payments:${c.reset}
|
|
1212
913
|
${colors.high}${ICONS.money}${c.reset} FIX_STRIPE_WEBHOOKS ${c.dim}Add signature verification + idempotency${c.reset}
|
|
1213
914
|
${colors.high}${ICONS.shield}${c.reset} ENFORCE_PAID_SURFACE ${c.dim}Add server-side entitlement checks${c.reset}
|
|
1214
|
-
${colors.
|
|
1215
|
-
|
|
915
|
+
${colors.critical}${ICONS.money}${c.reset} FIX_SIMULATED_BILLING ${c.dim}Replace fake billing with real${c.reset}
|
|
916
|
+
|
|
917
|
+
${c.dim}Reality & Data:${c.reset}
|
|
918
|
+
${colors.critical}${ICONS.link}${c.reset} FIX_MOCK_DOMAINS ${c.dim}Replace localhost/mock URLs${c.reset}
|
|
1216
919
|
${colors.medium}${ICONS.ghost}${c.reset} FIX_FAKE_SUCCESS ${c.dim}Gate success UI on network result${c.reset}
|
|
920
|
+
${colors.medium}${ICONS.doc}${c.reset} FIX_PLACEHOLDER_DATA ${c.dim}Replace lorem ipsum with real data${c.reset}
|
|
921
|
+
${colors.high}${ICONS.warning}${c.reset} FIX_SILENT_FALLBACK ${c.dim}Make failures visible${c.reset}
|
|
922
|
+
|
|
923
|
+
${c.dim}Code Quality:${c.reset}
|
|
924
|
+
${colors.high}${ICONS.bug}${c.reset} FIX_EMPTY_CATCH ${c.dim}Add error handling to catch blocks${c.reset}
|
|
925
|
+
${colors.medium}${ICONS.route}${c.reset} FIX_MISSING_ROUTE ${c.dim}Wire client refs to server routes${c.reset}
|
|
1217
926
|
${colors.low}${ICONS.env}${c.reset} FIX_ENV_CONTRACT ${c.dim}Add missing env vars to templates${c.reset}
|
|
927
|
+
${colors.low}${ICONS.dead}${c.reset} FIX_DEAD_UI ${c.dim}Make UI actions functional${c.reset}
|
|
1218
928
|
|
|
1219
929
|
${c.bold}LLM Configuration:${c.reset}
|
|
1220
930
|
${c.dim}Set these environment variables:${c.reset}
|
package/bin/runners/runInit.js
CHANGED
|
@@ -1054,6 +1054,17 @@ function printNextSteps(options = {}) {
|
|
|
1054
1054
|
console.log();
|
|
1055
1055
|
console.log(` ${c.dim}Full docs:${c.reset} ${colors.info}https://docs.vibecheckai.dev${c.reset}`);
|
|
1056
1056
|
console.log();
|
|
1057
|
+
|
|
1058
|
+
// Upsell box
|
|
1059
|
+
console.log(` ${c.dim}╭────────────────────────────────────────────────────────────╮${c.reset}`);
|
|
1060
|
+
console.log(` ${c.dim}│${c.reset} ${c.dim}│${c.reset}`);
|
|
1061
|
+
console.log(` ${c.dim}│${c.reset} ${colors.accent}⚡ STARTER${c.reset} ${c.dim}•${c.reset} AI-powered fixes, GitHub CI, MCP tools ${c.dim}│${c.reset}`);
|
|
1062
|
+
console.log(` ${c.dim}│${c.reset} ${colors.accent}🏆 PRO${c.reset} ${c.dim}•${c.reset} Runtime proof, verified badges, AI testing ${c.dim}│${c.reset}`);
|
|
1063
|
+
console.log(` ${c.dim}│${c.reset} ${c.dim}│${c.reset}`);
|
|
1064
|
+
console.log(` ${c.dim}│${c.reset} ${colors.info}vibecheck login${c.reset} ${c.dim}to upgrade • vibecheck.dev/pricing${c.reset} ${c.dim}│${c.reset}`);
|
|
1065
|
+
console.log(` ${c.dim}│${c.reset} ${c.dim}│${c.reset}`);
|
|
1066
|
+
console.log(` ${c.dim}╰────────────────────────────────────────────────────────────╯${c.reset}`);
|
|
1067
|
+
console.log();
|
|
1057
1068
|
}
|
|
1058
1069
|
|
|
1059
1070
|
// ═══════════════════════════════════════════════════════════════════════════════
|