@vibecheckai/cli 2.8.2 → 3.0.0
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/README.md +8 -8
- package/bin/_deprecations.js +35 -0
- package/bin/_router.js +46 -0
- package/bin/cli-hygiene.js +241 -0
- package/bin/guardrail.js +834 -0
- package/bin/runners/cli-utils.js +1070 -0
- package/bin/runners/context/ai-task-decomposer.js +337 -0
- package/bin/runners/context/analyzer.js +462 -0
- package/bin/runners/context/api-contracts.js +427 -0
- package/bin/runners/context/context-diff.js +342 -0
- package/bin/runners/context/context-pruner.js +291 -0
- package/bin/runners/context/dependency-graph.js +414 -0
- package/bin/runners/context/generators/claude.js +107 -0
- package/bin/runners/context/generators/codex.js +108 -0
- package/bin/runners/context/generators/copilot.js +119 -0
- package/bin/runners/context/generators/cursor.js +514 -0
- package/bin/runners/context/generators/mcp.js +151 -0
- package/bin/runners/context/generators/windsurf.js +180 -0
- package/bin/runners/context/git-context.js +302 -0
- package/bin/runners/context/index.js +1042 -0
- package/bin/runners/context/insights.js +173 -0
- package/bin/runners/context/mcp-server/generate-rules.js +337 -0
- package/bin/runners/context/mcp-server/index.js +1176 -0
- package/bin/runners/context/mcp-server/package.json +24 -0
- package/bin/runners/context/memory.js +200 -0
- package/bin/runners/context/monorepo.js +215 -0
- package/bin/runners/context/multi-repo-federation.js +404 -0
- package/bin/runners/context/patterns.js +253 -0
- package/bin/runners/context/proof-context.js +972 -0
- package/bin/runners/context/security-scanner.js +303 -0
- package/bin/runners/context/semantic-search.js +350 -0
- package/bin/runners/context/shared.js +264 -0
- package/bin/runners/context/team-conventions.js +310 -0
- package/bin/runners/lib/ai-bridge.js +416 -0
- package/bin/runners/lib/analysis-core.js +271 -0
- package/bin/runners/lib/analyzers.js +541 -0
- package/bin/runners/lib/audit-bridge.js +391 -0
- package/bin/runners/lib/auth-truth.js +193 -0
- package/bin/runners/lib/auth.js +215 -0
- package/bin/runners/lib/backup.js +62 -0
- package/bin/runners/lib/billing.js +107 -0
- package/bin/runners/lib/claims.js +118 -0
- package/bin/runners/lib/cli-ui.js +540 -0
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +165 -0
- package/bin/runners/lib/contracts/auth-contract.js +194 -0
- package/bin/runners/lib/contracts/env-contract.js +178 -0
- package/bin/runners/lib/contracts/external-contract.js +198 -0
- package/bin/runners/lib/contracts/guard.js +168 -0
- package/bin/runners/lib/contracts/index.js +89 -0
- package/bin/runners/lib/contracts/plan-validator.js +311 -0
- package/bin/runners/lib/contracts/route-contract.js +192 -0
- package/bin/runners/lib/detect.js +89 -0
- package/bin/runners/lib/doctor/autofix.js +254 -0
- package/bin/runners/lib/doctor/index.js +37 -0
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
- package/bin/runners/lib/doctor/modules/index.js +46 -0
- package/bin/runners/lib/doctor/modules/network.js +250 -0
- package/bin/runners/lib/doctor/modules/project.js +312 -0
- package/bin/runners/lib/doctor/modules/runtime.js +224 -0
- package/bin/runners/lib/doctor/modules/security.js +348 -0
- package/bin/runners/lib/doctor/modules/system.js +213 -0
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
- package/bin/runners/lib/doctor/reporter.js +262 -0
- package/bin/runners/lib/doctor/service.js +262 -0
- package/bin/runners/lib/doctor/types.js +113 -0
- package/bin/runners/lib/doctor/ui.js +263 -0
- package/bin/runners/lib/doctor-enhanced.js +233 -0
- package/bin/runners/lib/doctor-v2.js +608 -0
- package/bin/runners/lib/enforcement.js +72 -0
- package/bin/runners/lib/enterprise-detect.js +603 -0
- package/bin/runners/lib/enterprise-init.js +942 -0
- package/bin/runners/lib/entitlements-v2.js +381 -0
- package/bin/runners/lib/entitlements.generated.js +0 -0
- package/bin/runners/lib/entitlements.js +332 -0
- package/bin/runners/lib/env-template.js +66 -0
- package/bin/runners/lib/env.js +189 -0
- package/bin/runners/lib/error-handler.js +320 -0
- package/bin/runners/lib/firewall-prompt.js +50 -0
- package/bin/runners/lib/graph/graph-builder.js +265 -0
- package/bin/runners/lib/graph/html-renderer.js +413 -0
- package/bin/runners/lib/graph/index.js +32 -0
- package/bin/runners/lib/graph/runtime-collector.js +215 -0
- package/bin/runners/lib/graph/static-extractor.js +518 -0
- package/bin/runners/lib/init-wizard.js +308 -0
- package/bin/runners/lib/json-output.js +76 -0
- package/bin/runners/lib/llm.js +75 -0
- package/bin/runners/lib/meter.js +61 -0
- package/bin/runners/lib/missions/evidence.js +126 -0
- package/bin/runners/lib/missions/plan.js +69 -0
- package/bin/runners/lib/missions/templates.js +147 -0
- package/bin/runners/lib/patch.js +40 -0
- package/bin/runners/lib/permissions/auth-model.js +213 -0
- package/bin/runners/lib/permissions/idor-prover.js +205 -0
- package/bin/runners/lib/permissions/index.js +45 -0
- package/bin/runners/lib/permissions/matrix-builder.js +198 -0
- package/bin/runners/lib/pkgjson.js +28 -0
- package/bin/runners/lib/preflight.js +142 -0
- package/bin/runners/lib/reality-findings.js +84 -0
- package/bin/runners/lib/redact.js +29 -0
- package/bin/runners/lib/replay/capsule-manager.js +154 -0
- package/bin/runners/lib/replay/index.js +263 -0
- package/bin/runners/lib/replay/player.js +348 -0
- package/bin/runners/lib/replay/recorder.js +331 -0
- package/bin/runners/lib/report-engine.js +447 -0
- package/bin/runners/lib/report-html.js +1117 -0
- package/bin/runners/lib/report-templates.js +964 -0
- package/bin/runners/lib/route-detection.js +1140 -0
- package/bin/runners/lib/route-truth.js +477 -0
- package/bin/runners/lib/sandbox/index.js +59 -0
- package/bin/runners/lib/sandbox/proof-chain.js +399 -0
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
- package/bin/runners/lib/sandbox/worktree.js +174 -0
- package/bin/runners/lib/scan-cache.js +330 -0
- package/bin/runners/lib/scan-output-schema.js +344 -0
- package/bin/runners/lib/score-history.js +282 -0
- package/bin/runners/lib/security-bridge.js +249 -0
- package/bin/runners/lib/server-usage.js +513 -0
- package/bin/runners/lib/share-pack.js +239 -0
- package/bin/runners/lib/snippets.js +67 -0
- package/bin/runners/lib/truth.js +667 -0
- package/bin/runners/lib/unified-output.js +189 -0
- package/bin/runners/lib/validate-patch.js +156 -0
- package/bin/runners/lib/verification.js +345 -0
- package/bin/runners/reality/engine.js +917 -0
- package/bin/runners/reality/flows.js +122 -0
- package/bin/runners/reality/report.js +378 -0
- package/bin/runners/reality/session.js +193 -0
- package/bin/runners/runAIAgent.js +2 -0
- package/bin/runners/runAudit.js +2 -0
- package/bin/runners/runAuth.js +106 -0
- package/bin/runners/runAutopilot.js +2 -0
- package/bin/runners/runBadge.js +2 -0
- package/bin/runners/runCertify.js +2 -0
- package/bin/runners/runClaimVerifier.js +483 -0
- package/bin/runners/runContext.js +56 -0
- package/bin/runners/runContextCompiler.js +385 -0
- package/bin/runners/runCtx.js +187 -0
- package/bin/runners/runCtxGuard.js +176 -0
- package/bin/runners/runCtxSync.js +116 -0
- package/bin/runners/runDashboard.js +10 -0
- package/bin/runners/runDoctor.js +245 -0
- package/bin/runners/runEnhancedShip.js +2 -0
- package/bin/runners/runFix.js +735 -0
- package/bin/runners/runFixPacks.js +2 -0
- package/bin/runners/runGate.js +17 -0
- package/bin/runners/runGraph.js +283 -0
- package/bin/runners/runInit.js +260 -0
- package/bin/runners/runInitGha.js +101 -0
- package/bin/runners/runInstall.js +76 -0
- package/bin/runners/runInteractive.js +388 -0
- package/bin/runners/runLaunch.js +2 -0
- package/bin/runners/runMcp.js +19 -0
- package/bin/runners/runMdc.js +2 -0
- package/bin/runners/runMissionGenerator.js +282 -0
- package/bin/runners/runNaturalLanguage.js +3 -0
- package/bin/runners/runPR.js +96 -0
- package/bin/runners/runPermissions.js +290 -0
- package/bin/runners/runPromptFirewall.js +211 -0
- package/bin/runners/runProof.js +2 -0
- package/bin/runners/runProve.js +392 -0
- package/bin/runners/runReality.js +489 -0
- package/bin/runners/runRealitySniff.js +2 -0
- package/bin/runners/runReplay.js +469 -0
- package/bin/runners/runReport.js +478 -0
- package/bin/runners/runScan.js +835 -0
- package/bin/runners/runShare.js +34 -0
- package/bin/runners/runShip.js +1062 -0
- package/bin/runners/runStatus.js +136 -0
- package/bin/runners/runTruthpack.js +634 -0
- package/bin/runners/runUpgrade.js +2 -0
- package/bin/runners/runValidate.js +2 -0
- package/bin/runners/runVerifyAgentOutput.js +2 -0
- package/bin/runners/runWatch.js +230 -0
- package/bin/runners/utils.js +360 -0
- package/bin/scan.js +612 -0
- package/bin/vibecheck.js +834 -0
- package/package.json +11 -11
- package/dist/autopatch/verified-autopatch.d.ts +0 -111
- package/dist/autopatch/verified-autopatch.d.ts.map +0 -1
- package/dist/autopatch/verified-autopatch.js +0 -503
- package/dist/autopatch/verified-autopatch.js.map +0 -1
- package/dist/bundles/index.js +0 -8
- package/dist/bundles/vibecheck-core.js +0 -25799
- package/dist/bundles/vibecheck-security.js +0 -208693
- package/dist/bundles/vibecheck-ship.js +0 -2318
- package/dist/commands/baseline.d.ts +0 -7
- package/dist/commands/baseline.d.ts.map +0 -1
- package/dist/commands/baseline.js +0 -79
- package/dist/commands/baseline.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -13
- package/dist/commands/cache.d.ts.map +0 -1
- package/dist/commands/cache.js +0 -165
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/checkpoint.d.ts +0 -8
- package/dist/commands/checkpoint.d.ts.map +0 -1
- package/dist/commands/checkpoint.js +0 -35
- package/dist/commands/checkpoint.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -17
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -226
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/evidence.d.ts +0 -45
- package/dist/commands/evidence.d.ts.map +0 -1
- package/dist/commands/evidence.js +0 -197
- package/dist/commands/evidence.js.map +0 -1
- package/dist/commands/explain.d.ts +0 -8
- package/dist/commands/explain.d.ts.map +0 -1
- package/dist/commands/explain.js +0 -52
- package/dist/commands/explain.js.map +0 -1
- package/dist/commands/fix-consolidated.d.ts +0 -19
- package/dist/commands/fix-consolidated.d.ts.map +0 -1
- package/dist/commands/fix-consolidated.js +0 -165
- package/dist/commands/fix-consolidated.js.map +0 -1
- package/dist/commands/index.d.ts +0 -8
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js +0 -15
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/init.d.ts +0 -8
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -125
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/launcher.d.ts +0 -10
- package/dist/commands/launcher.d.ts.map +0 -1
- package/dist/commands/launcher.js +0 -174
- package/dist/commands/launcher.js.map +0 -1
- package/dist/commands/on.d.ts +0 -8
- package/dist/commands/on.d.ts.map +0 -1
- package/dist/commands/on.js +0 -123
- package/dist/commands/on.js.map +0 -1
- package/dist/commands/replay.d.ts +0 -8
- package/dist/commands/replay.d.ts.map +0 -1
- package/dist/commands/replay.js +0 -52
- package/dist/commands/replay.js.map +0 -1
- package/dist/commands/scan-consolidated.d.ts +0 -61
- package/dist/commands/scan-consolidated.d.ts.map +0 -1
- package/dist/commands/scan-consolidated.js +0 -243
- package/dist/commands/scan-consolidated.js.map +0 -1
- package/dist/commands/scan-secrets.d.ts +0 -47
- package/dist/commands/scan-secrets.d.ts.map +0 -1
- package/dist/commands/scan-secrets.js +0 -225
- package/dist/commands/scan-secrets.js.map +0 -1
- package/dist/commands/scan-vulnerabilities-enhanced.d.ts +0 -41
- package/dist/commands/scan-vulnerabilities-enhanced.d.ts.map +0 -1
- package/dist/commands/scan-vulnerabilities-enhanced.js +0 -368
- package/dist/commands/scan-vulnerabilities-enhanced.js.map +0 -1
- package/dist/commands/scan-vulnerabilities-osv.d.ts +0 -58
- package/dist/commands/scan-vulnerabilities-osv.d.ts.map +0 -1
- package/dist/commands/scan-vulnerabilities-osv.js +0 -722
- package/dist/commands/scan-vulnerabilities-osv.js.map +0 -1
- package/dist/commands/scan-vulnerabilities.d.ts +0 -32
- package/dist/commands/scan-vulnerabilities.d.ts.map +0 -1
- package/dist/commands/scan-vulnerabilities.js +0 -283
- package/dist/commands/scan-vulnerabilities.js.map +0 -1
- package/dist/commands/secrets-allowlist.d.ts +0 -7
- package/dist/commands/secrets-allowlist.d.ts.map +0 -1
- package/dist/commands/secrets-allowlist.js +0 -85
- package/dist/commands/secrets-allowlist.js.map +0 -1
- package/dist/commands/ship-consolidated.d.ts +0 -58
- package/dist/commands/ship-consolidated.d.ts.map +0 -1
- package/dist/commands/ship-consolidated.js +0 -515
- package/dist/commands/ship-consolidated.js.map +0 -1
- package/dist/commands/stats.d.ts +0 -8
- package/dist/commands/stats.d.ts.map +0 -1
- package/dist/commands/stats.js +0 -134
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/upgrade.d.ts +0 -8
- package/dist/commands/upgrade.d.ts.map +0 -1
- package/dist/commands/upgrade.js +0 -30
- package/dist/commands/upgrade.js.map +0 -1
- package/dist/fix/applicator.d.ts +0 -44
- package/dist/fix/applicator.d.ts.map +0 -1
- package/dist/fix/applicator.js +0 -144
- package/dist/fix/applicator.js.map +0 -1
- package/dist/fix/backup.d.ts +0 -38
- package/dist/fix/backup.d.ts.map +0 -1
- package/dist/fix/backup.js +0 -154
- package/dist/fix/backup.js.map +0 -1
- package/dist/fix/engine.d.ts +0 -55
- package/dist/fix/engine.d.ts.map +0 -1
- package/dist/fix/engine.js +0 -285
- package/dist/fix/engine.js.map +0 -1
- package/dist/fix/index.d.ts +0 -5
- package/dist/fix/index.d.ts.map +0 -1
- package/dist/fix/index.js +0 -12
- package/dist/fix/index.js.map +0 -1
- package/dist/fix/interactive.d.ts +0 -22
- package/dist/fix/interactive.d.ts.map +0 -1
- package/dist/fix/interactive.js +0 -172
- package/dist/fix/interactive.js.map +0 -1
- package/dist/formatters/index.d.ts +0 -6
- package/dist/formatters/index.d.ts.map +0 -1
- package/dist/formatters/index.js +0 -11
- package/dist/formatters/index.js.map +0 -1
- package/dist/formatters/sarif-enhanced.d.ts +0 -78
- package/dist/formatters/sarif-enhanced.d.ts.map +0 -1
- package/dist/formatters/sarif-enhanced.js +0 -144
- package/dist/formatters/sarif-enhanced.js.map +0 -1
- package/dist/formatters/sarif-v2.d.ts +0 -121
- package/dist/formatters/sarif-v2.d.ts.map +0 -1
- package/dist/formatters/sarif-v2.js +0 -356
- package/dist/formatters/sarif-v2.js.map +0 -1
- package/dist/formatters/sarif.d.ts +0 -72
- package/dist/formatters/sarif.d.ts.map +0 -1
- package/dist/formatters/sarif.js +0 -146
- package/dist/formatters/sarif.js.map +0 -1
- package/dist/index.d.ts +0 -61
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -4388
- package/dist/index.js.map +0 -1
- package/dist/init/ci-generator.d.ts +0 -18
- package/dist/init/ci-generator.d.ts.map +0 -1
- package/dist/init/ci-generator.js +0 -317
- package/dist/init/ci-generator.js.map +0 -1
- package/dist/init/detect-framework.d.ts +0 -15
- package/dist/init/detect-framework.d.ts.map +0 -1
- package/dist/init/detect-framework.js +0 -301
- package/dist/init/detect-framework.js.map +0 -1
- package/dist/init/hooks-installer.d.ts +0 -22
- package/dist/init/hooks-installer.d.ts.map +0 -1
- package/dist/init/hooks-installer.js +0 -310
- package/dist/init/hooks-installer.js.map +0 -1
- package/dist/init/index.d.ts +0 -8
- package/dist/init/index.d.ts.map +0 -1
- package/dist/init/index.js +0 -22
- package/dist/init/index.js.map +0 -1
- package/dist/init/templates.d.ts +0 -402
- package/dist/init/templates.d.ts.map +0 -1
- package/dist/init/templates.js +0 -240
- package/dist/init/templates.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -12
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -42
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/telemetry.d.ts +0 -40
- package/dist/mcp/telemetry.d.ts.map +0 -1
- package/dist/mcp/telemetry.js +0 -98
- package/dist/mcp/telemetry.js.map +0 -1
- package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts +0 -32
- package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts.map +0 -1
- package/dist/reality/no-dead-buttons/button-sweep-generator.js +0 -236
- package/dist/reality/no-dead-buttons/button-sweep-generator.js.map +0 -1
- package/dist/reality/no-dead-buttons/index.d.ts +0 -11
- package/dist/reality/no-dead-buttons/index.d.ts.map +0 -1
- package/dist/reality/no-dead-buttons/index.js +0 -18
- package/dist/reality/no-dead-buttons/index.js.map +0 -1
- package/dist/reality/no-dead-buttons/static-scanner.d.ts +0 -34
- package/dist/reality/no-dead-buttons/static-scanner.d.ts.map +0 -1
- package/dist/reality/no-dead-buttons/static-scanner.js +0 -230
- package/dist/reality/no-dead-buttons/static-scanner.js.map +0 -1
- package/dist/reality/reality-graph.d.ts +0 -192
- package/dist/reality/reality-graph.d.ts.map +0 -1
- package/dist/reality/reality-graph.js +0 -600
- package/dist/reality/reality-graph.js.map +0 -1
- package/dist/reality/reality-runner.d.ts +0 -89
- package/dist/reality/reality-runner.d.ts.map +0 -1
- package/dist/reality/reality-runner.js +0 -540
- package/dist/reality/reality-runner.js.map +0 -1
- package/dist/reality/receipt-generator.d.ts +0 -152
- package/dist/reality/receipt-generator.d.ts.map +0 -1
- package/dist/reality/receipt-generator.js +0 -495
- package/dist/reality/receipt-generator.js.map +0 -1
- package/dist/reality/runtime-tracer.d.ts +0 -75
- package/dist/reality/runtime-tracer.d.ts.map +0 -1
- package/dist/reality/runtime-tracer.js +0 -109
- package/dist/reality/runtime-tracer.js.map +0 -1
- package/dist/runtime/auth-utils.d.ts +0 -43
- package/dist/runtime/auth-utils.d.ts.map +0 -1
- package/dist/runtime/auth-utils.js +0 -130
- package/dist/runtime/auth-utils.js.map +0 -1
- package/dist/runtime/client.d.ts +0 -74
- package/dist/runtime/client.d.ts.map +0 -1
- package/dist/runtime/client.js +0 -222
- package/dist/runtime/client.js.map +0 -1
- package/dist/runtime/creds.d.ts +0 -48
- package/dist/runtime/creds.d.ts.map +0 -1
- package/dist/runtime/creds.js +0 -245
- package/dist/runtime/creds.js.map +0 -1
- package/dist/runtime/exit-codes.d.ts +0 -49
- package/dist/runtime/exit-codes.d.ts.map +0 -1
- package/dist/runtime/exit-codes.js +0 -93
- package/dist/runtime/exit-codes.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -9
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -25
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/json-output.d.ts +0 -42
- package/dist/runtime/json-output.d.ts.map +0 -1
- package/dist/runtime/json-output.js +0 -59
- package/dist/runtime/json-output.js.map +0 -1
- package/dist/runtime/semver.d.ts +0 -37
- package/dist/runtime/semver.d.ts.map +0 -1
- package/dist/runtime/semver.js +0 -110
- package/dist/runtime/semver.js.map +0 -1
- package/dist/scan/dead-ui-detector.d.ts +0 -48
- package/dist/scan/dead-ui-detector.d.ts.map +0 -1
- package/dist/scan/dead-ui-detector.js +0 -170
- package/dist/scan/dead-ui-detector.js.map +0 -1
- package/dist/scan/playwright-sweep.d.ts +0 -40
- package/dist/scan/playwright-sweep.d.ts.map +0 -1
- package/dist/scan/playwright-sweep.js +0 -216
- package/dist/scan/playwright-sweep.js.map +0 -1
- package/dist/scan/proof-bundle.d.ts +0 -25
- package/dist/scan/proof-bundle.d.ts.map +0 -1
- package/dist/scan/proof-bundle.js +0 -203
- package/dist/scan/proof-bundle.js.map +0 -1
- package/dist/scan/proof-graph.d.ts +0 -59
- package/dist/scan/proof-graph.d.ts.map +0 -1
- package/dist/scan/proof-graph.js +0 -64
- package/dist/scan/proof-graph.js.map +0 -1
- package/dist/scan/reality-sniff.d.ts +0 -56
- package/dist/scan/reality-sniff.d.ts.map +0 -1
- package/dist/scan/reality-sniff.js +0 -200
- package/dist/scan/reality-sniff.js.map +0 -1
- package/dist/scan/structural-verifier.d.ts +0 -20
- package/dist/scan/structural-verifier.d.ts.map +0 -1
- package/dist/scan/structural-verifier.js +0 -112
- package/dist/scan/structural-verifier.js.map +0 -1
- package/dist/scan/verification-engine.d.ts +0 -47
- package/dist/scan/verification-engine.d.ts.map +0 -1
- package/dist/scan/verification-engine.js +0 -141
- package/dist/scan/verification-engine.js.map +0 -1
- package/dist/scanner/baseline.d.ts +0 -52
- package/dist/scanner/baseline.d.ts.map +0 -1
- package/dist/scanner/baseline.js +0 -85
- package/dist/scanner/baseline.js.map +0 -1
- package/dist/scanner/incremental.d.ts +0 -30
- package/dist/scanner/incremental.d.ts.map +0 -1
- package/dist/scanner/incremental.js +0 -82
- package/dist/scanner/incremental.js.map +0 -1
- package/dist/scanner/parallel.d.ts +0 -43
- package/dist/scanner/parallel.d.ts.map +0 -1
- package/dist/scanner/parallel.js +0 -99
- package/dist/scanner/parallel.js.map +0 -1
- package/dist/standalone.d.ts +0 -1
- package/dist/standalone.d.ts.map +0 -1
- package/dist/standalone.js +0 -1
- package/dist/standalone.js.map +0 -1
- package/dist/truth-pack/index.d.ts +0 -102
- package/dist/truth-pack/index.d.ts.map +0 -1
- package/dist/truth-pack/index.js +0 -694
- package/dist/truth-pack/index.js.map +0 -1
- package/dist/ui/frame.d.ts +0 -68
- package/dist/ui/frame.d.ts.map +0 -1
- package/dist/ui/frame.js +0 -165
- package/dist/ui/frame.js.map +0 -1
- package/dist/ui/index.d.ts +0 -5
- package/dist/ui/index.d.ts.map +0 -1
- package/dist/ui/index.js +0 -16
- package/dist/ui/index.js.map +0 -1
- package/dist/ui.d.ts +0 -36
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js +0 -45
- package/dist/ui.js.map +0 -1
|
@@ -0,0 +1,735 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibecheck fix - Fix Missions v1
|
|
3
|
+
*
|
|
4
|
+
* Generates surgical "mission prompts", runs them sequentially,
|
|
5
|
+
* applies patches (optional), and re-verifies by re-running ship.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - Reality Firewall prompt prevents LLM hallucinations
|
|
9
|
+
* - Patch validator ensures no drift
|
|
10
|
+
* - Backup/restore for safe rollback
|
|
11
|
+
* - Progress detector stops on stagnation
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const { shipCore } = require('./runShip');
|
|
17
|
+
const { planMissions } = require('./lib/missions/plan');
|
|
18
|
+
const { templateForMissionType } = require('./lib/missions/templates');
|
|
19
|
+
const { expandEvidence } = require('./lib/missions/evidence');
|
|
20
|
+
const { buildRealityFirewall } = require('./lib/firewall-prompt');
|
|
21
|
+
const { generatePatchJson } = require('./lib/llm');
|
|
22
|
+
const { applyUnifiedDiff } = require('./lib/patch');
|
|
23
|
+
const { backupFiles, restoreBackup } = require('./lib/backup');
|
|
24
|
+
const { validatePatchResponse, parseDiffTouchedFiles } = require('./lib/validate-patch');
|
|
25
|
+
const { buildSharePack } = require('./lib/share-pack');
|
|
26
|
+
|
|
27
|
+
const c = {
|
|
28
|
+
reset: '\x1b[0m',
|
|
29
|
+
bold: '\x1b[1m',
|
|
30
|
+
dim: '\x1b[2m',
|
|
31
|
+
green: '\x1b[32m',
|
|
32
|
+
yellow: '\x1b[33m',
|
|
33
|
+
cyan: '\x1b[36m',
|
|
34
|
+
red: '\x1b[31m',
|
|
35
|
+
blue: '\x1b[34m',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function ensureDir(p) {
|
|
39
|
+
fs.mkdirSync(p, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function nowStamp() {
|
|
43
|
+
const d = new Date();
|
|
44
|
+
const z = (n) => String(n).padStart(2, "0");
|
|
45
|
+
return `${d.getFullYear()}${z(d.getMonth()+1)}${z(d.getDate())}_${z(d.getHours())}${z(d.getMinutes())}${z(d.getSeconds())}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function truthpackSummary(truthpack) {
|
|
49
|
+
return {
|
|
50
|
+
routes: {
|
|
51
|
+
serverCount: truthpack?.routes?.server?.length || 0,
|
|
52
|
+
clientRefsCount: truthpack?.routes?.clientRefs?.length || 0,
|
|
53
|
+
gaps: truthpack?.routes?.gaps?.length || 0
|
|
54
|
+
},
|
|
55
|
+
env: {
|
|
56
|
+
used: truthpack?.env?.vars?.length || 0,
|
|
57
|
+
declared: truthpack?.env?.declared?.length || 0
|
|
58
|
+
},
|
|
59
|
+
auth: {
|
|
60
|
+
middlewareCount: truthpack?.auth?.nextMiddleware?.length || 0,
|
|
61
|
+
matcherCount: truthpack?.auth?.nextMatcherPatterns?.length || 0,
|
|
62
|
+
fastifySignals: truthpack?.auth?.fastify?.signalTypes || []
|
|
63
|
+
},
|
|
64
|
+
billing: truthpack?.billing?.summary || {},
|
|
65
|
+
enforcement: {
|
|
66
|
+
checked: truthpack?.enforcement?.checkedCount || 0,
|
|
67
|
+
missing: truthpack?.enforcement?.missingCount || 0
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function score(findings) {
|
|
73
|
+
let s = 0;
|
|
74
|
+
for (const f of findings || []) s += (f.severity === "BLOCK" ? 10 : f.severity === "WARN" ? 3 : 0);
|
|
75
|
+
return s;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function allowedFilesForMission({ mission, targetFindings, truthpack }) {
|
|
79
|
+
const allow = new Set();
|
|
80
|
+
|
|
81
|
+
for (const f of targetFindings) {
|
|
82
|
+
for (const ev of (f.evidence || [])) {
|
|
83
|
+
if (ev.file) allow.add(ev.file);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const type = mission?.type;
|
|
88
|
+
if (type === "FIX_ENV_CONTRACT") {
|
|
89
|
+
[".env.example",".env.template",".env.sample",".env"].forEach(p => allow.add(p));
|
|
90
|
+
}
|
|
91
|
+
if (type === "ADD_SERVER_AUTH") {
|
|
92
|
+
(truthpack?.auth?.nextMiddleware || []).forEach(mw => mw.file && allow.add(mw.file));
|
|
93
|
+
}
|
|
94
|
+
if (type === "FIX_STRIPE_WEBHOOKS") {
|
|
95
|
+
(truthpack?.billing?.webhookCandidates || []).forEach(w => w.file && allow.add(w.file));
|
|
96
|
+
}
|
|
97
|
+
if (type === "ENFORCE_PAID_SURFACE") {
|
|
98
|
+
(truthpack?.enforcement?.checks || []).forEach(c => c.handler && allow.add(c.handler));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return Array.from(allow).filter(Boolean);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function runFix(args) {
|
|
105
|
+
const opts = parseArgs(args);
|
|
106
|
+
|
|
107
|
+
if (opts.help) {
|
|
108
|
+
printHelp();
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const root = path.resolve(opts.path || process.cwd());
|
|
113
|
+
const outDir = path.join(root, ".vibecheck", "missions", nowStamp());
|
|
114
|
+
ensureDir(outDir);
|
|
115
|
+
|
|
116
|
+
// First ship check (no meter consumption)
|
|
117
|
+
const first = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
118
|
+
|
|
119
|
+
if (first.verdict === "SHIP") {
|
|
120
|
+
console.log(`${c.green}✅ Already SHIP. No fixes needed.${c.reset}`);
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const missions = planMissions(first.report.findings, { maxMissions: opts.maxMissions || 8 });
|
|
125
|
+
fs.writeFileSync(path.join(outDir, "missions.json"), JSON.stringify({ missions, fromVerdict: first.verdict }, null, 2));
|
|
126
|
+
|
|
127
|
+
console.log(`\n${c.cyan}${c.bold}🛠 vibecheck fix${c.reset}`);
|
|
128
|
+
console.log(`Planned missions: ${missions.length}`);
|
|
129
|
+
console.log(`Mission pack: ${path.relative(root, outDir)}`);
|
|
130
|
+
|
|
131
|
+
if (!opts.autopilot && !opts.promptOnly && !opts.apply) {
|
|
132
|
+
console.log(`\n${c.bold}Run one of:${c.reset}`);
|
|
133
|
+
console.log(` ${c.cyan}vibecheck fix --prompt-only${c.reset} (generate perfect prompts, no edits)`);
|
|
134
|
+
console.log(` ${c.cyan}vibecheck fix --apply${c.reset} (apply patches from the model)`);
|
|
135
|
+
console.log(` ${c.cyan}vibecheck fix --autopilot --apply${c.reset} (loop until SHIP or stuck)`);
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let stagnant = 0;
|
|
140
|
+
const maxSteps = opts.maxSteps || 10;
|
|
141
|
+
const stagnationLimit = opts.stagnationLimit || 2;
|
|
142
|
+
|
|
143
|
+
for (let step = 1; step <= maxSteps; step++) {
|
|
144
|
+
const before = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
145
|
+
|
|
146
|
+
if (before.verdict === "SHIP") {
|
|
147
|
+
console.log(`\n${c.green}✅ SHIP achieved in ${step - 1} steps.${c.reset}`);
|
|
148
|
+
|
|
149
|
+
// Generate share bundle if requested
|
|
150
|
+
if (opts.share) {
|
|
151
|
+
try {
|
|
152
|
+
const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
|
|
153
|
+
console.log(`\n📦 Share bundle: ${path.relative(root, shareResult.outputDir)}`);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
console.log(`${c.yellow}⚠️ Share bundle failed: ${e.message}${c.reset}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const ids = new Set(before.report.findings.map(f => f.id));
|
|
163
|
+
const mission = missions.find(m => m.targetFindingIds.some(id => ids.has(id)));
|
|
164
|
+
if (!mission) {
|
|
165
|
+
console.log(`\n${c.yellow}⚠️ No remaining planned mission matches current findings. Stopping.${c.reset}`);
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Save before proof
|
|
170
|
+
fs.writeFileSync(
|
|
171
|
+
path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_before_ship.json`),
|
|
172
|
+
JSON.stringify(before.report, null, 2),
|
|
173
|
+
"utf8"
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const targetFindings = before.report.findings.filter(f => mission.targetFindingIds.includes(f.id));
|
|
177
|
+
|
|
178
|
+
// Use mission template + auto-expanded evidence
|
|
179
|
+
const template = templateForMissionType(mission.type);
|
|
180
|
+
const expanded = await expandEvidence({
|
|
181
|
+
repoRoot: root,
|
|
182
|
+
truthpack: before.truthpack,
|
|
183
|
+
mission,
|
|
184
|
+
targetFindings
|
|
185
|
+
});
|
|
186
|
+
const allowedFiles = expanded.allowedFiles;
|
|
187
|
+
const snippets = expanded.snippets;
|
|
188
|
+
|
|
189
|
+
const prompt = buildRealityFirewall({
|
|
190
|
+
truthpackSummary: truthpackSummary(before.truthpack),
|
|
191
|
+
mission,
|
|
192
|
+
template,
|
|
193
|
+
findings: targetFindings,
|
|
194
|
+
fileSnippets: snippets,
|
|
195
|
+
allowedFiles
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const promptPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_prompt.txt`);
|
|
199
|
+
fs.writeFileSync(promptPath, prompt, "utf8");
|
|
200
|
+
|
|
201
|
+
console.log(`\nStep ${step}/${maxSteps}: ${mission.title}`);
|
|
202
|
+
console.log(`Prompt: ${path.relative(root, promptPath)}`);
|
|
203
|
+
|
|
204
|
+
if (opts.promptOnly) {
|
|
205
|
+
if (!opts.autopilot) return 0;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let patchJson;
|
|
210
|
+
try {
|
|
211
|
+
patchJson = await generatePatchJson(prompt);
|
|
212
|
+
} catch (e) {
|
|
213
|
+
console.log(`${c.red}❌ LLM failed: ${e.message}${c.reset}`);
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const respPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_response.json`);
|
|
218
|
+
fs.writeFileSync(respPath, JSON.stringify(patchJson, null, 2), "utf8");
|
|
219
|
+
|
|
220
|
+
const v = validatePatchResponse({
|
|
221
|
+
repoRoot: root,
|
|
222
|
+
patchJson,
|
|
223
|
+
mission,
|
|
224
|
+
truthpack: before.truthpack,
|
|
225
|
+
allowedFiles,
|
|
226
|
+
limits: { maxEdits: 6, maxFiles: 6, maxChangedLines: 400 }
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
if (!v.ok) {
|
|
230
|
+
console.log(`${c.red}❌ Patch rejected by validator.${c.reset}`);
|
|
231
|
+
for (const e of v.errors) console.log(` - ${e}`);
|
|
232
|
+
if (v.warnings.length) {
|
|
233
|
+
console.log("Warnings:");
|
|
234
|
+
for (const w of v.warnings) console.log(` - ${w}`);
|
|
235
|
+
}
|
|
236
|
+
return 1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (v.warnings.length) {
|
|
240
|
+
console.log(`${c.yellow}⚠️ Validator warnings:${c.reset}`);
|
|
241
|
+
for (const w of v.warnings) console.log(` - ${w}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!opts.apply) {
|
|
245
|
+
console.log(`${c.green}✅ Patch generated (not applied). Re-run with --apply to apply diffs.${c.reset}`);
|
|
246
|
+
return 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const touchedFiles = new Set();
|
|
250
|
+
for (const ed of patchJson.edits) {
|
|
251
|
+
for (const f of parseDiffTouchedFiles(ed.diff)) touchedFiles.add(f);
|
|
252
|
+
}
|
|
253
|
+
const touchedList = Array.from(touchedFiles);
|
|
254
|
+
|
|
255
|
+
const backupRoot = path.join(outDir, `backup_step_${String(step).padStart(2,"0")}`);
|
|
256
|
+
backupFiles(root, touchedList, backupRoot);
|
|
257
|
+
|
|
258
|
+
for (const ed of patchJson.edits) {
|
|
259
|
+
const res = applyUnifiedDiff(root, ed.diff);
|
|
260
|
+
if (!res.ok) {
|
|
261
|
+
console.log(`${c.red}❌ Patch apply failed: ${res.error}${c.reset}`);
|
|
262
|
+
restoreBackup(root, backupRoot);
|
|
263
|
+
console.log(`${c.yellow}↩️ Restored from backup.${c.reset}`);
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
console.log(`${c.green}✅ Applied edit targeting: ${ed.path}${c.reset}`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const after = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
270
|
+
console.log(`Verify verdict: ${after.verdict}`);
|
|
271
|
+
|
|
272
|
+
// Save after proof
|
|
273
|
+
fs.writeFileSync(
|
|
274
|
+
path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_after_ship.json`),
|
|
275
|
+
JSON.stringify(after.report, null, 2),
|
|
276
|
+
"utf8"
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const beforeScore = score(before.report.findings);
|
|
280
|
+
const afterScore = score(after.report.findings);
|
|
281
|
+
const targetStillThere = mission.targetFindingIds.some(id => after.report.findings.some(f => f.id === id));
|
|
282
|
+
const improved = (afterScore < beforeScore) || (!targetStillThere);
|
|
283
|
+
|
|
284
|
+
if (!improved) {
|
|
285
|
+
console.log(`${c.red}❌ No measurable progress. Rolling back.${c.reset}`);
|
|
286
|
+
restoreBackup(root, backupRoot);
|
|
287
|
+
console.log(`${c.yellow}↩️ Restored from backup.${c.reset}`);
|
|
288
|
+
stagnant += 1;
|
|
289
|
+
if (!opts.autopilot || stagnant >= stagnationLimit) {
|
|
290
|
+
console.log(`${c.red}🛑 Stopping: stagnation limit reached (${stagnant}/${stagnationLimit}).${c.reset}`);
|
|
291
|
+
return 1;
|
|
292
|
+
}
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
stagnant = 0;
|
|
297
|
+
if (!opts.autopilot) return 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
console.log(`\n${c.yellow}⚠️ Max steps reached (${maxSteps}).${c.reset}`);
|
|
301
|
+
|
|
302
|
+
// Generate share bundle if requested
|
|
303
|
+
if (opts.share) {
|
|
304
|
+
try {
|
|
305
|
+
const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
|
|
306
|
+
console.log(`\n📦 Share bundle: ${path.relative(root, shareResult.outputDir)}`);
|
|
307
|
+
} catch (e) {
|
|
308
|
+
console.log(`${c.yellow}⚠️ Share bundle failed: ${e.message}${c.reset}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return 1;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Show Fix Plan (default behavior - no changes applied)
|
|
317
|
+
*/
|
|
318
|
+
async function showFixPlan(projectPath, opts) {
|
|
319
|
+
console.log(`\n${c.cyan}${c.bold}📋 FIX PLAN${c.reset}\n`);
|
|
320
|
+
console.log(`${c.dim}This shows what CAN be fixed. No changes will be made.${c.reset}`);
|
|
321
|
+
console.log(`${c.dim}Use --apply to apply changes (requires clean git state).${c.reset}\n`);
|
|
322
|
+
|
|
323
|
+
const scanResult = await loadLatestScan(projectPath);
|
|
324
|
+
if (!scanResult) {
|
|
325
|
+
console.error(`${c.red}Error:${c.reset} No scan results found. Run 'vibecheck scan' first.\n`);
|
|
326
|
+
return EXIT_CODES.MISCONFIG;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Filter to fixable findings
|
|
330
|
+
const fixable = scanResult.findings.filter(f => {
|
|
331
|
+
const ruleId = f.ruleId || '';
|
|
332
|
+
return f.autofixAvailable && ALLOWED_FIX_TYPES.includes(ruleId);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
if (fixable.length === 0) {
|
|
336
|
+
console.log(`${c.green}✓${c.reset} No mechanical fixes available.\n`);
|
|
337
|
+
console.log(`${c.dim}All remaining issues require manual intervention.${c.reset}\n`);
|
|
338
|
+
return EXIT_CODES.PASS;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
console.log(`${c.bold}Fixable Issues (${fixable.length}):${c.reset}\n`);
|
|
342
|
+
|
|
343
|
+
for (const finding of fixable) {
|
|
344
|
+
const patch = generatePatchPreview(projectPath, finding);
|
|
345
|
+
|
|
346
|
+
console.log(`${c.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
347
|
+
console.log(`${c.bold}${finding.id?.full || finding.id}${c.reset} - ${finding.ruleId}`);
|
|
348
|
+
console.log(`${c.dim}File:${c.reset} ${finding.file}:${finding.line}`);
|
|
349
|
+
console.log(`${c.dim}Why:${c.reset} ${finding.message || finding.description}`);
|
|
350
|
+
console.log(`${c.dim}Evidence:${c.reset} ${finding.evidence?.[0]?.snippet || 'See file'}`);
|
|
351
|
+
console.log('');
|
|
352
|
+
console.log(`${c.bold}Proposed Change:${c.reset}`);
|
|
353
|
+
console.log(patch.preview);
|
|
354
|
+
console.log('');
|
|
355
|
+
console.log(`${c.dim}Risk:${c.reset} ${patch.risk}`);
|
|
356
|
+
console.log(`${c.dim}Verification:${c.reset} Re-run scan to confirm no regression`);
|
|
357
|
+
console.log('');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
console.log(`${c.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
361
|
+
console.log(`\n${c.bold}To apply these fixes:${c.reset}`);
|
|
362
|
+
console.log(` ${c.cyan}vibecheck fix --apply${c.reset}\n`);
|
|
363
|
+
console.log(`${c.dim}This will:${c.reset}`);
|
|
364
|
+
console.log(` 1. Check for clean git state`);
|
|
365
|
+
console.log(` 2. Create branch: vibecheck/fix-<timestamp>`);
|
|
366
|
+
console.log(` 3. Apply patches with structured commits`);
|
|
367
|
+
console.log(` 4. Re-run scan to verify no regression\n`);
|
|
368
|
+
|
|
369
|
+
return EXIT_CODES.PASS;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Apply fixes with proof-gating
|
|
374
|
+
*/
|
|
375
|
+
async function applyFixes(projectPath, opts) {
|
|
376
|
+
console.log(`\n${c.cyan}${c.bold}🔧 APPLYING FIXES${c.reset}\n`);
|
|
377
|
+
|
|
378
|
+
// Step 1: Check git state
|
|
379
|
+
if (!isGitClean(projectPath)) {
|
|
380
|
+
console.error(`${c.red}Error:${c.reset} Git working directory is not clean.`);
|
|
381
|
+
console.error(`${c.dim}Commit or stash your changes before applying fixes.${c.reset}\n`);
|
|
382
|
+
return EXIT_CODES.MISCONFIG;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const scanResult = await loadLatestScan(projectPath);
|
|
386
|
+
if (!scanResult) {
|
|
387
|
+
console.error(`${c.red}Error:${c.reset} No scan results found. Run 'vibecheck scan' first.\n`);
|
|
388
|
+
return EXIT_CODES.MISCONFIG;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const fixable = scanResult.findings.filter(f => {
|
|
392
|
+
const ruleId = f.ruleId || '';
|
|
393
|
+
return f.autofixAvailable && ALLOWED_FIX_TYPES.includes(ruleId);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
if (fixable.length === 0) {
|
|
397
|
+
console.log(`${c.green}✓${c.reset} No fixes to apply.\n`);
|
|
398
|
+
return EXIT_CODES.PASS;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Step 2: Create branch
|
|
402
|
+
const branchName = `vibecheck/fix-${Date.now()}`;
|
|
403
|
+
try {
|
|
404
|
+
execSync(`git checkout -b ${branchName}`, { cwd: projectPath, stdio: 'pipe' });
|
|
405
|
+
console.log(`${c.green}✓${c.reset} Created branch: ${branchName}\n`);
|
|
406
|
+
} catch (err) {
|
|
407
|
+
console.error(`${c.red}Error:${c.reset} Failed to create branch: ${err.message}\n`);
|
|
408
|
+
return EXIT_CODES.INTERNAL;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Step 3: Apply fixes
|
|
412
|
+
let applied = 0;
|
|
413
|
+
let failed = 0;
|
|
414
|
+
|
|
415
|
+
for (const finding of fixable) {
|
|
416
|
+
try {
|
|
417
|
+
const result = await applyAutofix(projectPath, finding, opts);
|
|
418
|
+
if (result) {
|
|
419
|
+
applied++;
|
|
420
|
+
|
|
421
|
+
// Commit with structured message
|
|
422
|
+
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`;
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
execSync(`git add "${finding.file}"`, { cwd: projectPath, stdio: 'pipe' });
|
|
426
|
+
execSync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { cwd: projectPath, stdio: 'pipe' });
|
|
427
|
+
} catch {
|
|
428
|
+
// File might not have changed, continue
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
console.log(`${c.green}✓${c.reset} Fixed: ${finding.id?.full || finding.id}`);
|
|
432
|
+
} else {
|
|
433
|
+
failed++;
|
|
434
|
+
console.log(`${c.yellow}⚠${c.reset} Skipped: ${finding.id?.full || finding.id}`);
|
|
435
|
+
}
|
|
436
|
+
} catch (error) {
|
|
437
|
+
failed++;
|
|
438
|
+
console.log(`${c.red}✗${c.reset} Error: ${finding.id?.full || finding.id} - ${error.message}`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
console.log('');
|
|
443
|
+
console.log(`${c.bold}Summary:${c.reset}`);
|
|
444
|
+
console.log(` Applied: ${c.green}${applied}${c.reset}`);
|
|
445
|
+
console.log(` Skipped: ${c.yellow}${failed}${c.reset}`);
|
|
446
|
+
console.log('');
|
|
447
|
+
|
|
448
|
+
// Step 4: Re-run scan to verify
|
|
449
|
+
console.log(`${c.dim}Verifying fixes...${c.reset}\n`);
|
|
450
|
+
|
|
451
|
+
try {
|
|
452
|
+
const { runScan } = require('./runScan');
|
|
453
|
+
const verifyResult = await runScan(['--json', '--path', projectPath]);
|
|
454
|
+
|
|
455
|
+
if (verifyResult === 0 || verifyResult === EXIT_CODES.PASS) {
|
|
456
|
+
console.log(`${c.green}✓${c.reset} Verification passed - no regressions\n`);
|
|
457
|
+
} else {
|
|
458
|
+
console.log(`${c.yellow}⚠${c.reset} Verification found issues - review before merging\n`);
|
|
459
|
+
}
|
|
460
|
+
} catch {
|
|
461
|
+
console.log(`${c.dim}Run 'vibecheck scan' to verify manually.${c.reset}\n`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
console.log(`${c.bold}Rollback:${c.reset}`);
|
|
465
|
+
console.log(` ${c.cyan}git checkout main && git branch -D ${branchName}${c.reset}\n`);
|
|
466
|
+
|
|
467
|
+
return applied > 0 ? EXIT_CODES.PASS : EXIT_CODES.FAIL;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Check if git working directory is clean
|
|
472
|
+
*/
|
|
473
|
+
function isGitClean(projectPath) {
|
|
474
|
+
try {
|
|
475
|
+
const status = execSync('git status --porcelain', { cwd: projectPath, encoding: 'utf8' });
|
|
476
|
+
return status.trim() === '';
|
|
477
|
+
} catch {
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Generate patch preview for a finding
|
|
484
|
+
*/
|
|
485
|
+
function generatePatchPreview(projectPath, finding) {
|
|
486
|
+
const filePath = path.join(projectPath, finding.file);
|
|
487
|
+
|
|
488
|
+
if (!fs.existsSync(filePath)) {
|
|
489
|
+
return { preview: ` ${c.red}File not found${c.reset}`, risk: 'N/A' };
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
493
|
+
const lines = content.split('\n');
|
|
494
|
+
const lineIndex = finding.line - 1;
|
|
495
|
+
|
|
496
|
+
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
497
|
+
return { preview: ` ${c.red}Invalid line number${c.reset}`, risk: 'N/A' };
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const before = lines[lineIndex];
|
|
501
|
+
let after = before;
|
|
502
|
+
let risk = 'Low';
|
|
503
|
+
|
|
504
|
+
// Generate preview based on rule type
|
|
505
|
+
switch (finding.ruleId) {
|
|
506
|
+
case 'empty-catch':
|
|
507
|
+
after = before.replace(/catch\s*(?:\(([^)]*)\))?\s*\{\s*\}/, (m, v) => {
|
|
508
|
+
const varName = v || 'err';
|
|
509
|
+
return `catch (${varName}) { console.error('Error:', ${varName}); throw ${varName}; }`;
|
|
510
|
+
});
|
|
511
|
+
risk = 'Low - adds proper error handling';
|
|
512
|
+
break;
|
|
513
|
+
case 'dangerous-default':
|
|
514
|
+
after = before.replace(/\s*(\|\||\?\?)\s*['"][^'"]*['"]/, '');
|
|
515
|
+
risk = 'Medium - removes fallback (may require env var)';
|
|
516
|
+
break;
|
|
517
|
+
case 'placeholder-value':
|
|
518
|
+
after = before.replace(/(CHANGEME|REPLACE_ME|YOUR_\w+|INSERT_\w+)/g, "/* TODO: Replace $1 */ ''");
|
|
519
|
+
risk = 'Low - flags for manual replacement';
|
|
520
|
+
break;
|
|
521
|
+
default:
|
|
522
|
+
return { preview: ` ${c.dim}No preview available${c.reset}`, risk: 'Unknown' };
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return {
|
|
526
|
+
preview: ` ${c.red}- ${before.trim()}${c.reset}\n ${c.green}+ ${after.trim()}${c.reset}`,
|
|
527
|
+
risk,
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
async function applyAutofix(projectPath, finding, options) {
|
|
532
|
+
const filePath = path.join(projectPath, finding.file);
|
|
533
|
+
|
|
534
|
+
if (!fs.existsSync(filePath)) {
|
|
535
|
+
throw new Error(`File not found: ${finding.file}`);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
539
|
+
const lines = content.split('\n');
|
|
540
|
+
const lineIndex = finding.line - 1;
|
|
541
|
+
|
|
542
|
+
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
543
|
+
throw new Error(`Invalid line number: ${finding.line}`);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
let newContent = content;
|
|
547
|
+
const ruleId = finding.ruleId;
|
|
548
|
+
|
|
549
|
+
// Apply fixes based on rule type
|
|
550
|
+
switch (ruleId) {
|
|
551
|
+
case 'empty-catch':
|
|
552
|
+
newContent = fixEmptyCatch(lines, lineIndex, filePath);
|
|
553
|
+
break;
|
|
554
|
+
case 'dangerous-default':
|
|
555
|
+
newContent = fixDangerousDefault(lines, lineIndex, filePath);
|
|
556
|
+
break;
|
|
557
|
+
case 'placeholder-value':
|
|
558
|
+
newContent = fixPlaceholderValue(lines, lineIndex, filePath);
|
|
559
|
+
break;
|
|
560
|
+
default:
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (newContent !== content) {
|
|
565
|
+
if (!options.dryRun) {
|
|
566
|
+
fs.writeFileSync(filePath, newContent, 'utf8');
|
|
567
|
+
}
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function fixEmptyCatch(lines, lineIndex, filePath) {
|
|
575
|
+
const line = lines[lineIndex];
|
|
576
|
+
const newLines = [...lines];
|
|
577
|
+
|
|
578
|
+
// Find the catch block
|
|
579
|
+
if (line.includes('catch') && line.includes('{')) {
|
|
580
|
+
// Simple case: catch {} on one line
|
|
581
|
+
if (line.match(/catch\s*(?:\([^)]*\))?\s*\{\s*\}/)) {
|
|
582
|
+
const indent = line.match(/^(\s*)/)?.[1] || '';
|
|
583
|
+
newLines[lineIndex] = line.replace(
|
|
584
|
+
/catch\s*(?:\(([^)]*)\))?\s*\{\s*\}/,
|
|
585
|
+
(match, errVar) => {
|
|
586
|
+
const varName = errVar || 'err';
|
|
587
|
+
return `catch (${varName}) {\n${indent} console.error('Error:', ${varName});\n${indent} throw ${varName};\n${indent}}`;
|
|
588
|
+
}
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return newLines.join('\n');
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function fixDangerousDefault(lines, lineIndex, filePath) {
|
|
597
|
+
const line = lines[lineIndex];
|
|
598
|
+
const newLines = [...lines];
|
|
599
|
+
|
|
600
|
+
// Remove dangerous default
|
|
601
|
+
if (line.includes('process.env.') && (line.includes('||') || line.includes('??'))) {
|
|
602
|
+
newLines[lineIndex] = line.replace(
|
|
603
|
+
/\s*(\|\||\?\?)\s*['"][^'"]*['"]/,
|
|
604
|
+
''
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return newLines.join('\n');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function fixPlaceholderValue(lines, lineIndex, filePath) {
|
|
612
|
+
const line = lines[lineIndex];
|
|
613
|
+
const newLines = [...lines];
|
|
614
|
+
|
|
615
|
+
// Replace placeholder with TODO comment
|
|
616
|
+
newLines[lineIndex] = line.replace(
|
|
617
|
+
/(CHANGEME|REPLACE_ME|YOUR_[A-Z0-9_]+|INSERT_[A-Z0-9_]+)/g,
|
|
618
|
+
(match) => `/* TODO: Replace ${match} */ ''`
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
return newLines.join('\n');
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
async function loadLatestScan(projectPath) {
|
|
625
|
+
const scanDir = path.join(projectPath, '.vibecheck', 'reality-sniff', 'scans');
|
|
626
|
+
|
|
627
|
+
if (!fs.existsSync(scanDir)) {
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
try {
|
|
632
|
+
const files = fs.readdirSync(scanDir)
|
|
633
|
+
.filter(f => f.endsWith('.json'))
|
|
634
|
+
.map(f => ({
|
|
635
|
+
name: f,
|
|
636
|
+
path: path.join(scanDir, f),
|
|
637
|
+
mtime: fs.statSync(path.join(scanDir, f)).mtime,
|
|
638
|
+
}))
|
|
639
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
640
|
+
|
|
641
|
+
if (files.length === 0) {
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const content = fs.readFileSync(files[0].path, 'utf8');
|
|
646
|
+
return JSON.parse(content);
|
|
647
|
+
} catch {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function parseArgs(args) {
|
|
653
|
+
const opts = {
|
|
654
|
+
path: process.cwd(),
|
|
655
|
+
apply: false,
|
|
656
|
+
promptOnly: false,
|
|
657
|
+
autopilot: false,
|
|
658
|
+
share: false,
|
|
659
|
+
maxMissions: 8,
|
|
660
|
+
maxSteps: 10,
|
|
661
|
+
stagnationLimit: 2,
|
|
662
|
+
fastifyEntry: null,
|
|
663
|
+
help: false,
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
for (let i = 0; i < args.length; i++) {
|
|
667
|
+
const arg = args[i];
|
|
668
|
+
if (arg === '--apply') opts.apply = true;
|
|
669
|
+
else if (arg === '--prompt-only') opts.promptOnly = true;
|
|
670
|
+
else if (arg === '--autopilot') opts.autopilot = true;
|
|
671
|
+
else if (arg === '--share') opts.share = true;
|
|
672
|
+
else if (arg === '--max-missions') opts.maxMissions = Number(args[++i]) || 8;
|
|
673
|
+
else if (arg === '--max-steps') opts.maxSteps = Number(args[++i]) || 10;
|
|
674
|
+
else if (arg === '--stagnation-limit') opts.stagnationLimit = Number(args[++i]) || 2;
|
|
675
|
+
else if (arg === '--fastify-entry') opts.fastifyEntry = args[++i];
|
|
676
|
+
else if (arg === '--path' || arg === '-p') opts.path = args[++i];
|
|
677
|
+
else if (arg === '--help' || arg === '-h') opts.help = true;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return opts;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
function printHelp() {
|
|
684
|
+
console.log(`
|
|
685
|
+
${c.cyan}${c.bold}🛠 vibecheck fix${c.reset} - Fix Missions v1
|
|
686
|
+
|
|
687
|
+
Generate surgical fix prompts, apply patches, and verify with ship.
|
|
688
|
+
|
|
689
|
+
${c.bold}USAGE${c.reset}
|
|
690
|
+
vibecheck fix ${c.dim}# Plan missions (no changes)${c.reset}
|
|
691
|
+
vibecheck fix --prompt-only ${c.dim}# Generate perfect prompts${c.reset}
|
|
692
|
+
vibecheck fix --apply ${c.dim}# Apply patches from LLM${c.reset}
|
|
693
|
+
vibecheck fix --autopilot --apply ${c.dim}# Loop until SHIP or stuck${c.reset}
|
|
694
|
+
|
|
695
|
+
${c.bold}OPTIONS${c.reset}
|
|
696
|
+
--prompt-only Generate mission prompts only (no edits)
|
|
697
|
+
--apply Apply patches returned by the model (requires git)
|
|
698
|
+
--autopilot Loop: fix → verify → fix until SHIP or stuck
|
|
699
|
+
--max-missions <n> Max missions to plan (default: 8)
|
|
700
|
+
--max-steps <n> Max autopilot steps (default: 10)
|
|
701
|
+
--stagnation-limit Stop after N non-improving steps (default: 2)
|
|
702
|
+
--fastify-entry Fastify entry file (e.g. src/server.ts)
|
|
703
|
+
--path, -p Project path (default: current directory)
|
|
704
|
+
--help, -h Show this help
|
|
705
|
+
|
|
706
|
+
${c.bold}SAFETY FEATURES${c.reset}
|
|
707
|
+
• Reality Firewall prompt prevents LLM hallucinations
|
|
708
|
+
• Patch validator ensures no drift (files, routes, env)
|
|
709
|
+
• Backup/restore for automatic rollback on failure
|
|
710
|
+
• Progress detector stops on stagnation
|
|
711
|
+
|
|
712
|
+
${c.bold}MISSION TYPES${c.reset}
|
|
713
|
+
• REMOVE_OWNER_MODE Delete backdoor env bypass
|
|
714
|
+
• FIX_STRIPE_WEBHOOKS Add signature verification + idempotency
|
|
715
|
+
• ENFORCE_PAID_SURFACE Add server-side entitlement checks
|
|
716
|
+
• ADD_SERVER_AUTH Add auth to sensitive endpoints
|
|
717
|
+
• FIX_MISSING_ROUTE Wire client refs to server routes
|
|
718
|
+
• FIX_FAKE_SUCCESS Gate success UI on network result
|
|
719
|
+
• FIX_ENV_CONTRACT Add missing env vars to templates
|
|
720
|
+
|
|
721
|
+
${c.bold}LLM CONFIGURATION${c.reset}
|
|
722
|
+
Set these environment variables:
|
|
723
|
+
• VIBECHECK_LLM_BASE_URL ${c.dim}(e.g. https://api.openai.com/v1/chat/completions)${c.reset}
|
|
724
|
+
• VIBECHECK_LLM_API_KEY ${c.dim}(your API key)${c.reset}
|
|
725
|
+
• VIBECHECK_LLM_MODEL ${c.dim}(default: gpt-4.1-mini)${c.reset}
|
|
726
|
+
|
|
727
|
+
${c.bold}EXAMPLES${c.reset}
|
|
728
|
+
vibecheck fix ${c.dim}# Plan missions${c.reset}
|
|
729
|
+
vibecheck fix --prompt-only ${c.dim}# Generate prompts${c.reset}
|
|
730
|
+
vibecheck fix --apply ${c.dim}# Apply patches${c.reset}
|
|
731
|
+
vibecheck fix --autopilot --apply ${c.dim}# Full autopilot${c.reset}
|
|
732
|
+
`);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
module.exports = { runFix };
|