vibecheck-ai 2.0.2 → 5.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/bin/.generated +25 -0
- package/bin/_deprecations.js +463 -0
- package/bin/_router.js +46 -0
- package/bin/cli-hygiene.js +241 -0
- package/bin/dev/run-v2-torture.js +30 -0
- package/bin/registry.js +656 -0
- package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
- package/bin/runners/REPORT_AUDIT.md +64 -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 +513 -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-enhanced.js +2525 -0
- package/bin/runners/context/generators/cursor.js +514 -0
- package/bin/runners/context/generators/mcp.js +169 -0
- package/bin/runners/context/generators/windsurf.js +180 -0
- package/bin/runners/context/git-context.js +304 -0
- package/bin/runners/context/index.js +1110 -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 +1264 -0
- package/bin/runners/context/security-scanner.js +541 -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 +336 -0
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -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 +303 -0
- package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
- package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
- package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
- package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
- package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
- package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -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 +127 -0
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -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/index.js +200 -0
- package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
- package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
- package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
- package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
- package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
- package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
- package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
- package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
- package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -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/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +451 -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 +79 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -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/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
- package/bin/runners/lib/agent-firewall/session/index.js +26 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
- package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/ai-bridge.js +416 -0
- package/bin/runners/lib/analysis-core.js +309 -0
- package/bin/runners/lib/analyzers.js +2500 -0
- package/bin/runners/lib/api-client.js +269 -0
- package/bin/runners/lib/approve-output.js +235 -0
- package/bin/runners/lib/artifact-envelope.js +540 -0
- package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
- package/bin/runners/lib/audit-bridge.js +391 -0
- package/bin/runners/lib/auth-shared.js +977 -0
- package/bin/runners/lib/auth-truth.js +193 -0
- package/bin/runners/lib/auth.js +215 -0
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/backup.js +62 -0
- package/bin/runners/lib/billing.js +107 -0
- package/bin/runners/lib/checkpoint.js +941 -0
- package/bin/runners/lib/claims.js +118 -0
- package/bin/runners/lib/classify-output.js +204 -0
- package/bin/runners/lib/cleanup/engine.js +571 -0
- package/bin/runners/lib/cleanup/index.js +53 -0
- package/bin/runners/lib/cleanup/output.js +375 -0
- package/bin/runners/lib/cleanup/rules.js +1060 -0
- package/bin/runners/lib/cli-output.js +400 -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 +202 -0
- package/bin/runners/lib/contracts/env-contract.js +181 -0
- package/bin/runners/lib/contracts/external-contract.js +206 -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 +199 -0
- package/bin/runners/lib/contracts.js +804 -0
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/detect.js +89 -0
- package/bin/runners/lib/detectors-v2.js +622 -0
- package/bin/runners/lib/doctor/autofix.js +254 -0
- package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
- package/bin/runners/lib/doctor/failure-signatures.js +526 -0
- package/bin/runners/lib/doctor/fix-script.js +336 -0
- package/bin/runners/lib/doctor/index.js +37 -0
- package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
- package/bin/runners/lib/doctor/modules/index.js +105 -0
- package/bin/runners/lib/doctor/modules/network.js +250 -0
- package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
- package/bin/runners/lib/doctor/modules/project.js +312 -0
- package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
- package/bin/runners/lib/doctor/modules/runtime.js +224 -0
- package/bin/runners/lib/doctor/modules/security.js +350 -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/safe-repair.js +384 -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-output.js +226 -0
- package/bin/runners/lib/doctor-v2.js +608 -0
- package/bin/runners/lib/drift.js +425 -0
- package/bin/runners/lib/enforcement.js +72 -0
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -0
- package/bin/runners/lib/enterprise-init.js +942 -0
- package/bin/runners/lib/entitlements-v2.js +265 -0
- package/bin/runners/lib/entitlements.generated.js +0 -0
- package/bin/runners/lib/entitlements.js +340 -0
- package/bin/runners/lib/env-resolver.js +417 -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 +368 -0
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +684 -0
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/extractors/client-calls.js +990 -0
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
- package/bin/runners/lib/extractors/fastify-routes.js +426 -0
- package/bin/runners/lib/extractors/index.js +363 -0
- package/bin/runners/lib/extractors/next-routes.js +524 -0
- package/bin/runners/lib/extractors/proof-graph.js +431 -0
- package/bin/runners/lib/extractors/route-matcher.js +451 -0
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
- package/bin/runners/lib/extractors/ui-bindings.js +547 -0
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/findings-schema.js +281 -0
- package/bin/runners/lib/fingerprint.js +377 -0
- package/bin/runners/lib/firewall-prompt.js +50 -0
- package/bin/runners/lib/fix-output.js +228 -0
- package/bin/runners/lib/global-flags.js +250 -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/help-formatter.js +413 -0
- package/bin/runners/lib/html-proof-report.js +913 -0
- package/bin/runners/lib/html-report.js +650 -0
- package/bin/runners/lib/init-wizard.js +601 -0
- package/bin/runners/lib/interactive-menu.js +1496 -0
- package/bin/runners/lib/json-output.js +76 -0
- package/bin/runners/lib/llm.js +75 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/meter.js +61 -0
- package/bin/runners/lib/missions/briefing.js +427 -0
- package/bin/runners/lib/missions/checkpoint.js +753 -0
- package/bin/runners/lib/missions/evidence.js +126 -0
- package/bin/runners/lib/missions/hardening.js +851 -0
- package/bin/runners/lib/missions/plan.js +648 -0
- package/bin/runners/lib/missions/safety-gates.js +645 -0
- package/bin/runners/lib/missions/schema.js +478 -0
- package/bin/runners/lib/missions/templates.js +317 -0
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/packs/bundle.js +675 -0
- package/bin/runners/lib/packs/evidence-pack.js +671 -0
- package/bin/runners/lib/packs/pack-factory.js +837 -0
- package/bin/runners/lib/packs/permissions-pack.js +686 -0
- package/bin/runners/lib/packs/proof-graph-pack.js +779 -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/policy.js +295 -0
- package/bin/runners/lib/polish/accessibility.js +62 -0
- package/bin/runners/lib/polish/analyzer.js +93 -0
- package/bin/runners/lib/polish/backend.js +87 -0
- package/bin/runners/lib/polish/configuration.js +83 -0
- package/bin/runners/lib/polish/documentation.js +83 -0
- package/bin/runners/lib/polish/frontend.js +817 -0
- package/bin/runners/lib/polish/index.js +27 -0
- package/bin/runners/lib/polish/infrastructure.js +80 -0
- package/bin/runners/lib/polish/internationalization.js +85 -0
- package/bin/runners/lib/polish/libraries.js +180 -0
- package/bin/runners/lib/polish/observability.js +75 -0
- package/bin/runners/lib/polish/performance.js +64 -0
- package/bin/runners/lib/polish/privacy.js +110 -0
- package/bin/runners/lib/polish/resilience.js +92 -0
- package/bin/runners/lib/polish/security.js +78 -0
- package/bin/runners/lib/polish/seo.js +71 -0
- package/bin/runners/lib/polish/styles.js +62 -0
- package/bin/runners/lib/polish/utils.js +104 -0
- package/bin/runners/lib/preflight.js +142 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/prove-output.js +220 -0
- package/bin/runners/lib/reality/correlation-detectors.js +359 -0
- package/bin/runners/lib/reality/index.js +318 -0
- package/bin/runners/lib/reality/request-hashing.js +416 -0
- package/bin/runners/lib/reality/request-mapper.js +453 -0
- package/bin/runners/lib/reality/safety-rails.js +463 -0
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
- package/bin/runners/lib/reality/toast-detector.js +393 -0
- package/bin/runners/lib/reality-findings.js +84 -0
- package/bin/runners/lib/reality-output.js +231 -0
- package/bin/runners/lib/receipts.js +179 -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 +626 -0
- package/bin/runners/lib/report-html.js +1233 -0
- package/bin/runners/lib/report-output.js +366 -0
- package/bin/runners/lib/report-templates.js +967 -0
- package/bin/runners/lib/report.js +135 -0
- package/bin/runners/lib/route-detection.js +1209 -0
- package/bin/runners/lib/route-truth.js +1322 -0
- package/bin/runners/lib/safelist/index.js +96 -0
- package/bin/runners/lib/safelist/integration.js +334 -0
- package/bin/runners/lib/safelist/matcher.js +696 -0
- package/bin/runners/lib/safelist/schema.js +948 -0
- package/bin/runners/lib/safelist/store.js +438 -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/scan-output.js +631 -0
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schema-validator.js +350 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/contracts.schema.json +160 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/finding.schema.json +100 -0
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
- package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
- package/bin/runners/lib/schemas/validator.js +465 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -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/ship-gate.js +832 -0
- package/bin/runners/lib/ship-manifest.js +1153 -0
- package/bin/runners/lib/ship-output-enterprise.js +239 -0
- package/bin/runners/lib/ship-output.js +1128 -0
- package/bin/runners/lib/snippets.js +67 -0
- package/bin/runners/lib/status-output.js +340 -0
- package/bin/runners/lib/terminal-ui.js +356 -0
- package/bin/runners/lib/truth.js +1691 -0
- package/bin/runners/lib/ui.js +562 -0
- package/bin/runners/lib/unified-cli-output.js +947 -0
- package/bin/runners/lib/unified-output.js +197 -0
- package/bin/runners/lib/upsell.js +410 -0
- package/bin/runners/lib/usage.js +153 -0
- package/bin/runners/lib/validate-patch.js +156 -0
- package/bin/runners/lib/verdict-engine.js +628 -0
- package/bin/runners/lib/verification.js +345 -0
- package/bin/runners/lib/why-tree.js +650 -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 +229 -0
- package/bin/runners/runAgent.d.ts +5 -0
- package/bin/runners/runAgent.js +161 -0
- package/bin/runners/runAllowlist.js +418 -0
- package/bin/runners/runApprove.js +320 -0
- package/bin/runners/runAudit.js +692 -0
- package/bin/runners/runAuth.js +731 -0
- package/bin/runners/runCI.js +353 -0
- package/bin/runners/runCheckpoint.js +530 -0
- package/bin/runners/runClassify.js +928 -0
- package/bin/runners/runCleanup.js +343 -0
- package/bin/runners/runContext.d.ts +4 -0
- package/bin/runners/runContext.js +175 -0
- package/bin/runners/runDoctor.js +877 -0
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewall.js +134 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runFirewallHook.js +56 -0
- package/bin/runners/runFix.js +1355 -0
- package/bin/runners/runForge.js +451 -0
- package/bin/runners/runGuard.js +262 -0
- package/bin/runners/runInit.js +1927 -0
- package/bin/runners/runIntent.js +906 -0
- package/bin/runners/runKickoff.js +878 -0
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runLaunch.js +2000 -0
- package/bin/runners/runLink.js +785 -0
- package/bin/runners/runMcp.js +1875 -0
- package/bin/runners/runPacks.js +2089 -0
- package/bin/runners/runPolish.d.ts +4 -0
- package/bin/runners/runPolish.js +390 -0
- package/bin/runners/runPromptFirewall.js +211 -0
- package/bin/runners/runProve.js +1411 -0
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +2260 -0
- package/bin/runners/runReport.js +726 -0
- package/bin/runners/runRuntime.js +110 -0
- package/bin/runners/runSafelist.js +1190 -0
- package/bin/runners/runScan.js +688 -0
- package/bin/runners/runShield.js +1282 -0
- package/bin/runners/runShip.js +1660 -0
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/runners/runTruth.js +101 -0
- package/bin/runners/runValidate.js +179 -0
- package/bin/runners/runWatch.js +478 -0
- package/bin/runners/utils.js +360 -0
- package/bin/scan.js +617 -0
- package/bin/vibecheck.js +1617 -0
- package/dist/guardrail/index.d.ts +2405 -0
- package/dist/guardrail/index.js +9747 -0
- package/dist/guardrail/index.js.map +1 -0
- package/dist/scanner/index.d.ts +282 -0
- package/dist/scanner/index.js +3395 -0
- package/dist/scanner/index.js.map +1 -0
- package/package.json +123 -104
- package/README.md +0 -491
- package/dist/index.js +0 -99711
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,1355 @@
|
|
|
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
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
8
|
+
* ENTERPRISE EDITION - World-Class Terminal Experience
|
|
9
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
10
|
+
*
|
|
11
|
+
* TIER ENFORCEMENT:
|
|
12
|
+
* - FREE/STARTER: --plan-only mode only
|
|
13
|
+
* - PRO: Full fix with --apply patches
|
|
14
|
+
*
|
|
15
|
+
* Key features:
|
|
16
|
+
* - Reality Firewall prompt prevents LLM hallucinations
|
|
17
|
+
* - Patch validator ensures no drift
|
|
18
|
+
* - Backup/restore for safe rollback
|
|
19
|
+
* - Progress detector stops on stagnation
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const path = require('path');
|
|
23
|
+
const fs = require('fs');
|
|
24
|
+
const { execSync } = require('child_process');
|
|
25
|
+
const { shipCore } = require('./runShip');
|
|
26
|
+
const { planMissions, getMissionStats } = require('./lib/missions/plan');
|
|
27
|
+
const { templateForMissionType } = require('./lib/missions/templates');
|
|
28
|
+
const { expandEvidence } = require('./lib/missions/evidence');
|
|
29
|
+
const { buildRealityFirewall } = require('./lib/firewall-prompt');
|
|
30
|
+
const { generatePatchJson } = require('./lib/llm');
|
|
31
|
+
const { applyUnifiedDiff } = require('./lib/patch');
|
|
32
|
+
const { backupFiles, restoreBackup } = require('./lib/backup');
|
|
33
|
+
const { validatePatchResponse, parseDiffTouchedFiles } = require('./lib/validate-patch');
|
|
34
|
+
const { buildSharePack } = require('./lib/share-pack');
|
|
35
|
+
const { parseGlobalFlags, shouldShowBanner } = require('./lib/global-flags');
|
|
36
|
+
const { EXIT, verdictToExitCode } = require('./lib/exit-codes');
|
|
37
|
+
|
|
38
|
+
// Entitlements enforcement
|
|
39
|
+
const entitlements = require('./lib/entitlements-v2');
|
|
40
|
+
const upsell = require('./lib/upsell');
|
|
41
|
+
|
|
42
|
+
// Mission Control output formatter
|
|
43
|
+
const { formatFixOutput } = require('./lib/fix-output');
|
|
44
|
+
|
|
45
|
+
// Fix Missions V2 - New components
|
|
46
|
+
const { updateMissionStatus, MISSION_STATUS, isSafeToAutoApply } = require('./lib/missions/schema');
|
|
47
|
+
const {
|
|
48
|
+
createCheckpoint,
|
|
49
|
+
rollbackToCheckpoint,
|
|
50
|
+
rollbackMission,
|
|
51
|
+
markCheckpointApplied,
|
|
52
|
+
markCheckpointFailed,
|
|
53
|
+
listCheckpoints,
|
|
54
|
+
getMissionHistory,
|
|
55
|
+
cleanupOldCheckpoints,
|
|
56
|
+
} = require('./lib/missions/checkpoint');
|
|
57
|
+
const {
|
|
58
|
+
runPreFlightGates,
|
|
59
|
+
runPostFlightGates,
|
|
60
|
+
shouldAutoApply,
|
|
61
|
+
DEFAULT_THRESHOLDS,
|
|
62
|
+
} = require('./lib/missions/safety-gates');
|
|
63
|
+
const {
|
|
64
|
+
formatAllBriefings,
|
|
65
|
+
formatMissionSummary,
|
|
66
|
+
formatMissionResult,
|
|
67
|
+
formatFinalSummary,
|
|
68
|
+
formatMissionBriefing,
|
|
69
|
+
colors: briefingColors,
|
|
70
|
+
ICONS: briefingIcons,
|
|
71
|
+
} = require('./lib/missions/briefing');
|
|
72
|
+
const {
|
|
73
|
+
initAuditTrail,
|
|
74
|
+
getAuditTrail,
|
|
75
|
+
circuitBreakerAllows,
|
|
76
|
+
circuitBreakerSuccess,
|
|
77
|
+
circuitBreakerFailure,
|
|
78
|
+
circuitBreakerReset,
|
|
79
|
+
circuitBreakerStatus,
|
|
80
|
+
safeExecute,
|
|
81
|
+
ExecutionError,
|
|
82
|
+
} = require('./lib/missions/hardening');
|
|
83
|
+
|
|
84
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
85
|
+
// ADVANCED TERMINAL - ANSI CODES & UTILITIES
|
|
86
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
87
|
+
|
|
88
|
+
const c = {
|
|
89
|
+
reset: '\x1b[0m',
|
|
90
|
+
bold: '\x1b[1m',
|
|
91
|
+
dim: '\x1b[2m',
|
|
92
|
+
italic: '\x1b[3m',
|
|
93
|
+
underline: '\x1b[4m',
|
|
94
|
+
blink: '\x1b[5m',
|
|
95
|
+
inverse: '\x1b[7m',
|
|
96
|
+
hidden: '\x1b[8m',
|
|
97
|
+
strike: '\x1b[9m',
|
|
98
|
+
// Colors
|
|
99
|
+
black: '\x1b[30m',
|
|
100
|
+
red: '\x1b[31m',
|
|
101
|
+
green: '\x1b[32m',
|
|
102
|
+
yellow: '\x1b[33m',
|
|
103
|
+
blue: '\x1b[34m',
|
|
104
|
+
magenta: '\x1b[35m',
|
|
105
|
+
cyan: '\x1b[36m',
|
|
106
|
+
white: '\x1b[37m',
|
|
107
|
+
// Bright colors
|
|
108
|
+
gray: '\x1b[90m',
|
|
109
|
+
brightRed: '\x1b[91m',
|
|
110
|
+
brightGreen: '\x1b[92m',
|
|
111
|
+
brightYellow: '\x1b[93m',
|
|
112
|
+
brightBlue: '\x1b[94m',
|
|
113
|
+
brightMagenta: '\x1b[95m',
|
|
114
|
+
brightCyan: '\x1b[96m',
|
|
115
|
+
brightWhite: '\x1b[97m',
|
|
116
|
+
// Background
|
|
117
|
+
bgBlack: '\x1b[40m',
|
|
118
|
+
bgRed: '\x1b[41m',
|
|
119
|
+
bgGreen: '\x1b[42m',
|
|
120
|
+
bgYellow: '\x1b[43m',
|
|
121
|
+
bgBlue: '\x1b[44m',
|
|
122
|
+
bgMagenta: '\x1b[45m',
|
|
123
|
+
bgCyan: '\x1b[46m',
|
|
124
|
+
bgWhite: '\x1b[47m',
|
|
125
|
+
bgBrightBlack: '\x1b[100m',
|
|
126
|
+
bgBrightRed: '\x1b[101m',
|
|
127
|
+
bgBrightGreen: '\x1b[102m',
|
|
128
|
+
bgBrightYellow: '\x1b[103m',
|
|
129
|
+
// Cursor control
|
|
130
|
+
cursorUp: (n = 1) => `\x1b[${n}A`,
|
|
131
|
+
cursorDown: (n = 1) => `\x1b[${n}B`,
|
|
132
|
+
cursorRight: (n = 1) => `\x1b[${n}C`,
|
|
133
|
+
cursorLeft: (n = 1) => `\x1b[${n}D`,
|
|
134
|
+
clearLine: '\x1b[2K',
|
|
135
|
+
clearScreen: '\x1b[2J',
|
|
136
|
+
saveCursor: '\x1b[s',
|
|
137
|
+
restoreCursor: '\x1b[u',
|
|
138
|
+
hideCursor: '\x1b[?25l',
|
|
139
|
+
showCursor: '\x1b[?25h',
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// 256-color / True color support
|
|
143
|
+
const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
144
|
+
const bgRgb = (r, g, b) => `\x1b[48;2;${r};${g};${b}m`;
|
|
145
|
+
|
|
146
|
+
// Premium color palette
|
|
147
|
+
const colors = {
|
|
148
|
+
// Gradients for banner
|
|
149
|
+
gradient1: rgb(255, 150, 50), // Orange
|
|
150
|
+
gradient2: rgb(255, 120, 80), // Coral
|
|
151
|
+
gradient3: rgb(255, 100, 100), // Salmon
|
|
152
|
+
gradient4: rgb(255, 80, 120), // Pink
|
|
153
|
+
gradient5: rgb(255, 60, 150), // Hot pink
|
|
154
|
+
gradient6: rgb(200, 50, 200), // Magenta
|
|
155
|
+
|
|
156
|
+
// Status colors
|
|
157
|
+
shipGreen: rgb(0, 255, 150),
|
|
158
|
+
warnAmber: rgb(255, 200, 0),
|
|
159
|
+
blockRed: rgb(255, 80, 80),
|
|
160
|
+
|
|
161
|
+
// UI colors
|
|
162
|
+
accent: rgb(255, 150, 50),
|
|
163
|
+
accentAlt: rgb(255, 180, 80),
|
|
164
|
+
muted: rgb(120, 120, 140),
|
|
165
|
+
subtle: rgb(80, 80, 100),
|
|
166
|
+
highlight: rgb(255, 255, 255),
|
|
167
|
+
|
|
168
|
+
// Mission colors
|
|
169
|
+
mission: rgb(255, 150, 50),
|
|
170
|
+
prompt: rgb(100, 200, 255),
|
|
171
|
+
patch: rgb(150, 255, 150),
|
|
172
|
+
rollback: rgb(255, 150, 150),
|
|
173
|
+
|
|
174
|
+
// Severity colors
|
|
175
|
+
critical: rgb(255, 60, 60),
|
|
176
|
+
high: rgb(255, 120, 60),
|
|
177
|
+
medium: rgb(255, 200, 60),
|
|
178
|
+
low: rgb(100, 200, 255),
|
|
179
|
+
info: rgb(150, 150, 180),
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
183
|
+
// PREMIUM BANNER
|
|
184
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
185
|
+
|
|
186
|
+
const FIX_BANNER = `
|
|
187
|
+
${rgb(255, 150, 50)} ███████╗██╗██╗ ██╗${c.reset}
|
|
188
|
+
${rgb(255, 130, 70)} ██╔════╝██║╚██╗██╔╝${c.reset}
|
|
189
|
+
${rgb(255, 110, 90)} █████╗ ██║ ╚███╔╝ ${c.reset}
|
|
190
|
+
${rgb(255, 90, 110)} ██╔══╝ ██║ ██╔██╗ ${c.reset}
|
|
191
|
+
${rgb(255, 70, 130)} ██║ ██║██╔╝ ██╗${c.reset}
|
|
192
|
+
${rgb(255, 50, 150)} ╚═╝ ╚═╝╚═╝ ╚═╝${c.reset}
|
|
193
|
+
`;
|
|
194
|
+
|
|
195
|
+
const BANNER_FULL = `
|
|
196
|
+
${rgb(255, 150, 50)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${c.reset}
|
|
197
|
+
${rgb(255, 140, 60)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${c.reset}
|
|
198
|
+
${rgb(255, 130, 70)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${c.reset}
|
|
199
|
+
${rgb(255, 120, 80)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${c.reset}
|
|
200
|
+
${rgb(255, 100, 100)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${c.reset}
|
|
201
|
+
${rgb(255, 80, 120)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${c.reset}
|
|
202
|
+
|
|
203
|
+
${c.dim} ┌─────────────────────────────────────────────────────────────────────┐${c.reset}
|
|
204
|
+
${c.dim} │${c.reset} ${rgb(255, 150, 50)}🔧${c.reset} ${c.bold}FIX${c.reset} ${c.dim}•${c.reset} ${rgb(200, 200, 200)}Mission Control${c.reset} ${c.dim}•${c.reset} ${rgb(150, 150, 150)}Reality Firewall${c.reset} ${c.dim}•${c.reset} ${rgb(100, 100, 100)}Auto Patch${c.reset} ${c.dim}│${c.reset}
|
|
205
|
+
${c.dim} └─────────────────────────────────────────────────────────────────────┘${c.reset}
|
|
206
|
+
`;
|
|
207
|
+
|
|
208
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
209
|
+
// TERMINAL UTILITIES
|
|
210
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
211
|
+
|
|
212
|
+
const BOX = {
|
|
213
|
+
topLeft: '╭', topRight: '╮', bottomLeft: '╰', bottomRight: '╯',
|
|
214
|
+
horizontal: '─', vertical: '│',
|
|
215
|
+
teeRight: '├', teeLeft: '┤', teeDown: '┬', teeUp: '┴',
|
|
216
|
+
cross: '┼',
|
|
217
|
+
// Double line variants
|
|
218
|
+
dTopLeft: '╔', dTopRight: '╗', dBottomLeft: '╚', dBottomRight: '╝',
|
|
219
|
+
dHorizontal: '═', dVertical: '║',
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const ICONS = {
|
|
223
|
+
wrench: '🔧',
|
|
224
|
+
check: '✓',
|
|
225
|
+
cross: '✗',
|
|
226
|
+
warning: '⚠',
|
|
227
|
+
error: '✗',
|
|
228
|
+
info: 'ℹ',
|
|
229
|
+
arrow: '→',
|
|
230
|
+
bullet: '•',
|
|
231
|
+
star: '★',
|
|
232
|
+
sparkle: '✨',
|
|
233
|
+
fire: '🔥',
|
|
234
|
+
lock: '🔐',
|
|
235
|
+
key: '🔑',
|
|
236
|
+
link: '🔗',
|
|
237
|
+
graph: '📊',
|
|
238
|
+
map: '🗺️',
|
|
239
|
+
doc: '📄',
|
|
240
|
+
folder: '📁',
|
|
241
|
+
clock: '⏱',
|
|
242
|
+
target: '🎯',
|
|
243
|
+
shield: '🛡️',
|
|
244
|
+
bug: '🐛',
|
|
245
|
+
lightning: '⚡',
|
|
246
|
+
package: '📦',
|
|
247
|
+
route: '🛤️',
|
|
248
|
+
env: '🌍',
|
|
249
|
+
auth: '🔒',
|
|
250
|
+
money: '💰',
|
|
251
|
+
ghost: '👻',
|
|
252
|
+
dead: '💀',
|
|
253
|
+
mission: '🎯',
|
|
254
|
+
prompt: '📝',
|
|
255
|
+
patch: '🩹',
|
|
256
|
+
rollback: '↩️',
|
|
257
|
+
ship: '🚀',
|
|
258
|
+
robot: '🤖',
|
|
259
|
+
brain: '🧠',
|
|
260
|
+
loop: '🔄',
|
|
261
|
+
stop: '🛑',
|
|
262
|
+
gear: '⚙️',
|
|
263
|
+
rocket: '🚀',
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
267
|
+
const SPINNER_DOTS = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
|
|
268
|
+
const SPINNER_GEARS = ['◐', '◓', '◑', '◒'];
|
|
269
|
+
|
|
270
|
+
let spinnerIndex = 0;
|
|
271
|
+
let spinnerInterval = null;
|
|
272
|
+
let spinnerStartTime = null;
|
|
273
|
+
|
|
274
|
+
function formatDuration(ms) {
|
|
275
|
+
if (ms < 1000) return `${ms}ms`;
|
|
276
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
|
|
277
|
+
return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function formatNumber(num) {
|
|
281
|
+
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function truncate(str, len) {
|
|
285
|
+
if (!str) return '';
|
|
286
|
+
if (str.length <= len) return str;
|
|
287
|
+
return str.slice(0, len - 3) + '...';
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function padCenter(str, width) {
|
|
291
|
+
const padding = Math.max(0, width - str.length);
|
|
292
|
+
const left = Math.floor(padding / 2);
|
|
293
|
+
const right = padding - left;
|
|
294
|
+
return ' '.repeat(left) + str + ' '.repeat(right);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function progressBar(percent, width = 30, opts = {}) {
|
|
298
|
+
const filled = Math.round((percent / 100) * width);
|
|
299
|
+
const empty = width - filled;
|
|
300
|
+
|
|
301
|
+
let filledColor;
|
|
302
|
+
if (opts.color) {
|
|
303
|
+
filledColor = opts.color;
|
|
304
|
+
} else if (percent >= 80) {
|
|
305
|
+
filledColor = colors.shipGreen;
|
|
306
|
+
} else if (percent >= 50) {
|
|
307
|
+
filledColor = colors.warnAmber;
|
|
308
|
+
} else {
|
|
309
|
+
filledColor = colors.blockRed;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const filledChar = opts.filled || '█';
|
|
313
|
+
const emptyChar = opts.empty || '░';
|
|
314
|
+
|
|
315
|
+
return `${filledColor}${filledChar.repeat(filled)}${c.dim}${emptyChar.repeat(empty)}${c.reset}`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function startSpinner(message, style = 'dots') {
|
|
319
|
+
const frames = style === 'gears' ? SPINNER_GEARS :
|
|
320
|
+
style === 'dots' ? SPINNER_DOTS : SPINNER_FRAMES;
|
|
321
|
+
spinnerStartTime = Date.now();
|
|
322
|
+
process.stdout.write(c.hideCursor);
|
|
323
|
+
|
|
324
|
+
spinnerInterval = setInterval(() => {
|
|
325
|
+
const elapsed = formatDuration(Date.now() - spinnerStartTime);
|
|
326
|
+
process.stdout.write(`\r${c.clearLine} ${colors.accent}${frames[spinnerIndex]}${c.reset} ${message} ${c.dim}${elapsed}${c.reset}`);
|
|
327
|
+
spinnerIndex = (spinnerIndex + 1) % frames.length;
|
|
328
|
+
}, 80);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function stopSpinner(message, success = true) {
|
|
332
|
+
if (spinnerInterval) {
|
|
333
|
+
clearInterval(spinnerInterval);
|
|
334
|
+
spinnerInterval = null;
|
|
335
|
+
}
|
|
336
|
+
const elapsed = spinnerStartTime ? formatDuration(Date.now() - spinnerStartTime) : '';
|
|
337
|
+
const icon = success ? `${colors.shipGreen}${ICONS.check}${c.reset}` : `${colors.blockRed}${ICONS.cross}${c.reset}`;
|
|
338
|
+
process.stdout.write(`\r${c.clearLine} ${icon} ${message} ${c.dim}${elapsed}${c.reset}\n`);
|
|
339
|
+
process.stdout.write(c.showCursor);
|
|
340
|
+
spinnerStartTime = null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function printBanner(compact = false) {
|
|
344
|
+
console.log(compact ? FIX_BANNER : BANNER_FULL);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function printDivider(char = '─', width = 69, color = c.dim) {
|
|
348
|
+
console.log(`${color} ${char.repeat(width)}${c.reset}`);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function printSection(title, icon = '◆') {
|
|
352
|
+
console.log();
|
|
353
|
+
console.log(` ${colors.accent}${icon}${c.reset} ${c.bold}${title}${c.reset}`);
|
|
354
|
+
printDivider();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function printSubSection(title) {
|
|
358
|
+
console.log();
|
|
359
|
+
console.log(` ${c.dim}${BOX.teeRight}${BOX.horizontal}${c.reset} ${c.bold}${title}${c.reset}`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
363
|
+
// MISSION STATUS CARDS
|
|
364
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
365
|
+
|
|
366
|
+
function getMissionIcon(missionType) {
|
|
367
|
+
const icons = {
|
|
368
|
+
'REMOVE_OWNER_MODE': ICONS.lock,
|
|
369
|
+
'FIX_STRIPE_WEBHOOKS': ICONS.money,
|
|
370
|
+
'ENFORCE_PAID_SURFACE': ICONS.shield,
|
|
371
|
+
'ADD_SERVER_AUTH': ICONS.auth,
|
|
372
|
+
'FIX_MISSING_ROUTE': ICONS.route,
|
|
373
|
+
'FIX_FAKE_SUCCESS': ICONS.ghost,
|
|
374
|
+
'FIX_ENV_CONTRACT': ICONS.env,
|
|
375
|
+
'FIX_DEAD_UI': ICONS.dead,
|
|
376
|
+
// New enhanced mission types
|
|
377
|
+
'FIX_EMPTY_CATCH': ICONS.bug,
|
|
378
|
+
'FIX_TEST_KEYS': ICONS.key,
|
|
379
|
+
'FIX_MOCK_DOMAINS': ICONS.link,
|
|
380
|
+
'FIX_PLACEHOLDER_DATA': ICONS.doc,
|
|
381
|
+
'FIX_HARDCODED_SECRETS': ICONS.lock,
|
|
382
|
+
'FIX_SIMULATED_BILLING': ICONS.money,
|
|
383
|
+
'FIX_SILENT_FALLBACK': ICONS.warning,
|
|
384
|
+
'SYNC_CONTRACTS': ICONS.graph,
|
|
385
|
+
'FIX_ROUTE_DRIFT': ICONS.route,
|
|
386
|
+
'FIX_AUTH_DRIFT': ICONS.shield,
|
|
387
|
+
};
|
|
388
|
+
return icons[missionType] || ICONS.mission;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function getMissionColor(missionType) {
|
|
392
|
+
const colorMap = {
|
|
393
|
+
'REMOVE_OWNER_MODE': colors.critical,
|
|
394
|
+
'FIX_STRIPE_WEBHOOKS': colors.high,
|
|
395
|
+
'ENFORCE_PAID_SURFACE': colors.high,
|
|
396
|
+
'ADD_SERVER_AUTH': colors.medium,
|
|
397
|
+
'FIX_MISSING_ROUTE': colors.medium,
|
|
398
|
+
'FIX_FAKE_SUCCESS': colors.medium,
|
|
399
|
+
'FIX_ENV_CONTRACT': colors.low,
|
|
400
|
+
'FIX_DEAD_UI': colors.low,
|
|
401
|
+
// New enhanced mission types
|
|
402
|
+
'FIX_EMPTY_CATCH': colors.high,
|
|
403
|
+
'FIX_TEST_KEYS': colors.critical,
|
|
404
|
+
'FIX_MOCK_DOMAINS': colors.critical,
|
|
405
|
+
'FIX_PLACEHOLDER_DATA': colors.medium,
|
|
406
|
+
'FIX_HARDCODED_SECRETS': colors.critical,
|
|
407
|
+
'FIX_SIMULATED_BILLING': colors.critical,
|
|
408
|
+
'FIX_SILENT_FALLBACK': colors.high,
|
|
409
|
+
'SYNC_CONTRACTS': colors.medium,
|
|
410
|
+
'FIX_ROUTE_DRIFT': colors.medium,
|
|
411
|
+
'FIX_AUTH_DRIFT': colors.critical,
|
|
412
|
+
};
|
|
413
|
+
return colorMap[missionType] || colors.accent;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function printMissionCard(mission, step, totalSteps, status = 'pending') {
|
|
417
|
+
const w = 66;
|
|
418
|
+
const icon = getMissionIcon(mission.type);
|
|
419
|
+
const missionColor = getMissionColor(mission.type);
|
|
420
|
+
|
|
421
|
+
const statusConfig = {
|
|
422
|
+
pending: { icon: '○', color: c.dim, label: 'PENDING' },
|
|
423
|
+
running: { icon: '◐', color: colors.accent, label: 'RUNNING' },
|
|
424
|
+
success: { icon: '●', color: colors.shipGreen, label: 'SUCCESS' },
|
|
425
|
+
failed: { icon: '●', color: colors.blockRed, label: 'FAILED' },
|
|
426
|
+
skipped: { icon: '○', color: colors.warnAmber, label: 'SKIPPED' },
|
|
427
|
+
rollback: { icon: '↩', color: colors.rollback, label: 'ROLLBACK' },
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
const s = statusConfig[status] || statusConfig.pending;
|
|
431
|
+
|
|
432
|
+
console.log();
|
|
433
|
+
console.log(` ${c.dim}${BOX.topLeft}${BOX.horizontal.repeat(w)}${BOX.topRight}${c.reset}`);
|
|
434
|
+
|
|
435
|
+
// Header row
|
|
436
|
+
const stepLabel = `Step ${step}/${totalSteps}`;
|
|
437
|
+
const headerLeft = `${icon} ${mission.type}`;
|
|
438
|
+
const headerPadding = w - headerLeft.length - stepLabel.length - 4;
|
|
439
|
+
console.log(` ${c.dim}${BOX.vertical}${c.reset} ${missionColor}${c.bold}${headerLeft}${c.reset}${' '.repeat(Math.max(1, headerPadding))}${c.dim}${stepLabel}${c.reset} ${c.dim}${BOX.vertical}${c.reset}`);
|
|
440
|
+
|
|
441
|
+
// Status row
|
|
442
|
+
const statusLine = `${s.icon} ${s.label}`;
|
|
443
|
+
console.log(` ${c.dim}${BOX.vertical}${c.reset} ${s.color}${statusLine}${c.reset}${' '.repeat(w - statusLine.length - 2)} ${c.dim}${BOX.vertical}${c.reset}`);
|
|
444
|
+
|
|
445
|
+
// Title row
|
|
446
|
+
if (mission.title) {
|
|
447
|
+
const title = truncate(mission.title, w - 4);
|
|
448
|
+
console.log(` ${c.dim}${BOX.vertical}${c.reset} ${title}${' '.repeat(w - title.length - 2)} ${c.dim}${BOX.vertical}${c.reset}`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
console.log(` ${c.dim}${BOX.bottomLeft}${BOX.horizontal.repeat(w)}${BOX.bottomRight}${c.reset}`);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function printMissionSummary(missions) {
|
|
455
|
+
printSection(`MISSION PLAN (${missions.length} missions)`, ICONS.target);
|
|
456
|
+
console.log();
|
|
457
|
+
|
|
458
|
+
for (let i = 0; i < missions.length; i++) {
|
|
459
|
+
const m = missions[i];
|
|
460
|
+
const icon = getMissionIcon(m.type);
|
|
461
|
+
const color = getMissionColor(m.type);
|
|
462
|
+
const targets = m.targetFindingIds?.length || 0;
|
|
463
|
+
|
|
464
|
+
console.log(` ${color}${icon}${c.reset} ${c.bold}${i + 1}.${c.reset} ${m.type.padEnd(24)} ${c.dim}(${targets} finding${targets !== 1 ? 's' : ''})${c.reset}`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function printLoopHeader(maxSteps, stagnationLimit) {
|
|
469
|
+
console.log();
|
|
470
|
+
console.log(` ${bgRgb(80, 40, 20)}${c.bold} ${ICONS.loop} LOOP MODE ${c.reset}`);
|
|
471
|
+
console.log(` ${c.dim}Max steps: ${maxSteps} • Stagnation limit: ${stagnationLimit}${c.reset}`);
|
|
472
|
+
console.log();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function ensureDir(p) {
|
|
476
|
+
fs.mkdirSync(p, { recursive: true });
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function nowStamp() {
|
|
480
|
+
const d = new Date();
|
|
481
|
+
const z = (n) => String(n).padStart(2, "0");
|
|
482
|
+
return `${d.getFullYear()}${z(d.getMonth()+1)}${z(d.getDate())}_${z(d.getHours())}${z(d.getMinutes())}${z(d.getSeconds())}`;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function truthpackSummary(truthpack) {
|
|
486
|
+
return {
|
|
487
|
+
routes: {
|
|
488
|
+
serverCount: truthpack?.routes?.server?.length || 0,
|
|
489
|
+
clientRefsCount: truthpack?.routes?.clientRefs?.length || 0,
|
|
490
|
+
gaps: truthpack?.routes?.gaps?.length || 0
|
|
491
|
+
},
|
|
492
|
+
env: {
|
|
493
|
+
used: truthpack?.env?.vars?.length || 0,
|
|
494
|
+
declared: truthpack?.env?.declared?.length || 0
|
|
495
|
+
},
|
|
496
|
+
auth: {
|
|
497
|
+
middlewareCount: truthpack?.auth?.nextMiddleware?.length || 0,
|
|
498
|
+
matcherCount: truthpack?.auth?.nextMatcherPatterns?.length || 0,
|
|
499
|
+
fastifySignals: truthpack?.auth?.fastify?.signalTypes || []
|
|
500
|
+
},
|
|
501
|
+
billing: truthpack?.billing?.summary || {},
|
|
502
|
+
enforcement: {
|
|
503
|
+
checked: truthpack?.enforcement?.checkedCount || 0,
|
|
504
|
+
missing: truthpack?.enforcement?.missingCount || 0
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function score(findings) {
|
|
510
|
+
let s = 0;
|
|
511
|
+
for (const f of findings || []) s += (f.severity === "BLOCK" ? 10 : f.severity === "WARN" ? 3 : 0);
|
|
512
|
+
return s;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function allowedFilesForMission({ mission, targetFindings, truthpack }) {
|
|
516
|
+
const allow = new Set();
|
|
517
|
+
|
|
518
|
+
for (const f of targetFindings) {
|
|
519
|
+
for (const ev of (f.evidence || [])) {
|
|
520
|
+
if (ev.file) allow.add(ev.file);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const type = mission?.type;
|
|
525
|
+
if (type === "FIX_ENV_CONTRACT") {
|
|
526
|
+
[".env.example",".env.template",".env.sample",".env"].forEach(p => allow.add(p));
|
|
527
|
+
}
|
|
528
|
+
if (type === "ADD_SERVER_AUTH") {
|
|
529
|
+
(truthpack?.auth?.nextMiddleware || []).forEach(mw => mw.file && allow.add(mw.file));
|
|
530
|
+
}
|
|
531
|
+
if (type === "FIX_STRIPE_WEBHOOKS") {
|
|
532
|
+
(truthpack?.billing?.webhookCandidates || []).forEach(w => w.file && allow.add(w.file));
|
|
533
|
+
}
|
|
534
|
+
if (type === "ENFORCE_PAID_SURFACE") {
|
|
535
|
+
(truthpack?.enforcement?.checks || []).forEach(c => c.handler && allow.add(c.handler));
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return Array.from(allow).filter(Boolean);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async function runFix(args) {
|
|
542
|
+
const opts = parseArgs(args);
|
|
543
|
+
const startTime = Date.now();
|
|
544
|
+
|
|
545
|
+
if (opts.help) {
|
|
546
|
+
printHelp();
|
|
547
|
+
return 0;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const root = path.resolve(opts.path || process.cwd());
|
|
551
|
+
const projectName = path.basename(root);
|
|
552
|
+
|
|
553
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
554
|
+
// FIX MISSIONS V2 - Initialize hardening components
|
|
555
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
556
|
+
|
|
557
|
+
// Initialize audit trail
|
|
558
|
+
const auditDir = path.join(root, '.vibecheck', 'logs');
|
|
559
|
+
initAuditTrail(auditDir);
|
|
560
|
+
const audit = getAuditTrail();
|
|
561
|
+
|
|
562
|
+
// Generate session ID for tracking
|
|
563
|
+
const sessionId = `fix_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
564
|
+
process.env.VIBECHECK_SESSION_ID = sessionId;
|
|
565
|
+
|
|
566
|
+
audit.info('fix_session_start', {
|
|
567
|
+
sessionId,
|
|
568
|
+
projectName,
|
|
569
|
+
root,
|
|
570
|
+
args: args.filter(a => !a.includes('key') && !a.includes('token')), // Filter sensitive args
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// Check circuit breaker
|
|
574
|
+
if (!circuitBreakerAllows()) {
|
|
575
|
+
const status = circuitBreakerStatus();
|
|
576
|
+
console.log(` ${colors.blockRed}${ICONS.stop}${c.reset} Circuit breaker is open - too many recent failures`);
|
|
577
|
+
console.log(` ${c.dim}Failures: ${status.failures}, Last failure: ${new Date(status.lastFailure).toISOString()}${c.reset}`);
|
|
578
|
+
console.log(` ${c.dim}Wait ${Math.ceil((status.resetTimeout - (Date.now() - status.lastFailure)) / 1000)}s or use --force to override${c.reset}`);
|
|
579
|
+
|
|
580
|
+
if (!opts.force) {
|
|
581
|
+
audit.warn('circuit_breaker_blocked', { status });
|
|
582
|
+
return EXIT.BLOCKING;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
audit.warn('circuit_breaker_override', { status });
|
|
586
|
+
circuitBreakerReset();
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Print banner
|
|
590
|
+
printBanner();
|
|
591
|
+
console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
|
|
592
|
+
console.log(` ${c.dim}Path:${c.reset} ${root}`);
|
|
593
|
+
console.log(` ${c.dim}Session:${c.reset} ${c.dim}${sessionId}${c.reset}`);
|
|
594
|
+
console.log();
|
|
595
|
+
|
|
596
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
597
|
+
// FIX MISSIONS V2 - Handle special modes first
|
|
598
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
599
|
+
|
|
600
|
+
// Handle --list-checkpoints
|
|
601
|
+
if (opts.listCheckpoints) {
|
|
602
|
+
const checkpoints = listCheckpoints(root);
|
|
603
|
+
if (checkpoints.length === 0) {
|
|
604
|
+
console.log(` ${c.dim}No checkpoints found${c.reset}`);
|
|
605
|
+
} else {
|
|
606
|
+
console.log(` ${colors.accent}${ICONS.mission}${c.reset} ${c.bold}CHECKPOINTS${c.reset} ${c.dim}(${checkpoints.length})${c.reset}`);
|
|
607
|
+
console.log();
|
|
608
|
+
for (const cp of checkpoints.slice(0, 10)) {
|
|
609
|
+
const age = Math.round((Date.now() - new Date(cp.createdAt).getTime()) / 1000 / 60);
|
|
610
|
+
console.log(` ${ICONS.check} ${cp.id}`);
|
|
611
|
+
console.log(` ${c.dim}Mission: ${cp.missionType} • ${cp.files} files • ${age}m ago${c.reset}`);
|
|
612
|
+
}
|
|
613
|
+
if (checkpoints.length > 10) {
|
|
614
|
+
console.log(` ${c.dim}... and ${checkpoints.length - 10} more${c.reset}`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
console.log();
|
|
618
|
+
return 0;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Handle --cleanup-checkpoints
|
|
622
|
+
if (opts.cleanupCheckpoints) {
|
|
623
|
+
startSpinner('Cleaning up old checkpoints...', 'dots');
|
|
624
|
+
const result = cleanupOldCheckpoints(root);
|
|
625
|
+
stopSpinner(`Cleaned up ${result.count} checkpoints`, true);
|
|
626
|
+
return 0;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Handle --rollback
|
|
630
|
+
if (opts.rollback) {
|
|
631
|
+
const missionId = opts.rollback;
|
|
632
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolling back mission: ${c.bold}${missionId}${c.reset}`);
|
|
633
|
+
|
|
634
|
+
const result = rollbackMission(root, missionId);
|
|
635
|
+
|
|
636
|
+
if (result.ok) {
|
|
637
|
+
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Rollback successful`);
|
|
638
|
+
if (result.restored.length > 0) {
|
|
639
|
+
console.log(` ${c.dim}Restored: ${result.restored.length} files${c.reset}`);
|
|
640
|
+
}
|
|
641
|
+
if (result.deleted.length > 0) {
|
|
642
|
+
console.log(` ${c.dim}Deleted: ${result.deleted.length} files${c.reset}`);
|
|
643
|
+
}
|
|
644
|
+
return 0;
|
|
645
|
+
} else {
|
|
646
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Rollback failed: ${result.error}`);
|
|
647
|
+
return EXIT.INTERNAL_ERROR;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// TIER ENFORCEMENT: Check if --apply is allowed
|
|
652
|
+
if (opts.apply || opts.autopilot) {
|
|
653
|
+
const access = await entitlements.enforce("fix.apply_patches", {
|
|
654
|
+
projectPath: root,
|
|
655
|
+
silent: false,
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
if (!access.allowed) {
|
|
659
|
+
console.log();
|
|
660
|
+
console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} ${c.bold}Feature requires upgrade${c.reset}`);
|
|
661
|
+
console.log(` ${c.dim}Tip: Run ${colors.accent}vibecheck fix --prompt-only${c.reset}${c.dim} to generate fix prompts (FREE)${c.reset}`);
|
|
662
|
+
console.log();
|
|
663
|
+
return entitlements.EXIT_FEATURE_NOT_ALLOWED;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const outDir = path.join(root, ".vibecheck", "missions", nowStamp());
|
|
668
|
+
ensureDir(outDir);
|
|
669
|
+
|
|
670
|
+
// First ship check
|
|
671
|
+
startSpinner('Analyzing codebase...', 'gears');
|
|
672
|
+
const first = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
673
|
+
stopSpinner('Codebase analyzed', true);
|
|
674
|
+
|
|
675
|
+
if (first.verdict === "SHIP") {
|
|
676
|
+
// Mission Control output
|
|
677
|
+
if (!opts.json && !opts.quiet) {
|
|
678
|
+
console.log(formatFixOutput({
|
|
679
|
+
missions: [],
|
|
680
|
+
verdict: first.verdict,
|
|
681
|
+
beforeVerdict: first.verdict,
|
|
682
|
+
afterVerdict: first.verdict,
|
|
683
|
+
appliedMissions: 0,
|
|
684
|
+
totalMissions: 0,
|
|
685
|
+
duration: 0,
|
|
686
|
+
success: true,
|
|
687
|
+
}, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
|
|
688
|
+
}
|
|
689
|
+
return 0;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// Plan missions with enhanced options
|
|
693
|
+
startSpinner('Planning fix missions...', 'gears');
|
|
694
|
+
const missions = planMissions(first.report.findings, {
|
|
695
|
+
maxMissions: opts.maxMissions || 8,
|
|
696
|
+
truthpack: first.truthpack,
|
|
697
|
+
maxBlastRadius: opts.maxBlast,
|
|
698
|
+
minConfidence: opts.minConfidence,
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
// Filter to specific mission if requested
|
|
702
|
+
let targetMissions = missions;
|
|
703
|
+
if (opts.mission) {
|
|
704
|
+
targetMissions = missions.filter(m => m.id === opts.mission || m.id.includes(opts.mission));
|
|
705
|
+
if (targetMissions.length === 0) {
|
|
706
|
+
stopSpinner('Mission not found', false);
|
|
707
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} No mission found with ID: ${opts.mission}`);
|
|
708
|
+
console.log(` ${c.dim}Available missions:${c.reset}`);
|
|
709
|
+
for (const m of missions.slice(0, 5)) {
|
|
710
|
+
console.log(` ${c.dim}${m.id} - ${m.type}${c.reset}`);
|
|
711
|
+
}
|
|
712
|
+
return EXIT.BLOCKING;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
fs.writeFileSync(path.join(outDir, "missions.json"), JSON.stringify({ missions: targetMissions, fromVerdict: first.verdict }, null, 2));
|
|
717
|
+
stopSpinner(`Planned ${targetMissions.length} missions`, true);
|
|
718
|
+
|
|
719
|
+
// Get mission stats
|
|
720
|
+
const stats = getMissionStats(targetMissions);
|
|
721
|
+
|
|
722
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
723
|
+
// FIX MISSIONS V2 - Plan-only mode with full briefings
|
|
724
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
725
|
+
|
|
726
|
+
if (opts.planOnly) {
|
|
727
|
+
// Show full mission briefings
|
|
728
|
+
const gateOptions = {
|
|
729
|
+
minConfidence: opts.minConfidence,
|
|
730
|
+
maxBlastRadius: opts.maxBlast,
|
|
731
|
+
force: opts.force,
|
|
732
|
+
allowDirty: opts.allowDirty,
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
console.log(formatAllBriefings(root, targetMissions, gateOptions));
|
|
736
|
+
|
|
737
|
+
// Save briefings to file
|
|
738
|
+
fs.writeFileSync(
|
|
739
|
+
path.join(outDir, "briefings.txt"),
|
|
740
|
+
formatAllBriefings(root, targetMissions, gateOptions).replace(/\x1b\[[0-9;]*m/g, ''),
|
|
741
|
+
"utf8"
|
|
742
|
+
);
|
|
743
|
+
console.log(` ${c.dim}${ICONS.folder} Briefings saved: ${colors.accent}${path.relative(root, path.join(outDir, "briefings.txt"))}${c.reset}`);
|
|
744
|
+
console.log();
|
|
745
|
+
|
|
746
|
+
return 0;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Show mission summary
|
|
750
|
+
printMissionSummary(targetMissions);
|
|
751
|
+
console.log();
|
|
752
|
+
console.log(` ${c.dim}${ICONS.folder} Mission pack: ${colors.accent}${path.relative(root, outDir)}${c.reset}`);
|
|
753
|
+
console.log();
|
|
754
|
+
|
|
755
|
+
if (!opts.loop && !opts.promptOnly && !opts.apply) {
|
|
756
|
+
printSection('NEXT STEPS', ICONS.arrow);
|
|
757
|
+
console.log();
|
|
758
|
+
console.log(` ${c.bold}Choose a mode:${c.reset}`);
|
|
759
|
+
console.log();
|
|
760
|
+
console.log(` ${colors.accent}${ICONS.prompt}${c.reset} ${c.bold}vibecheck fix --plan-only${c.reset}`);
|
|
761
|
+
console.log(` ${c.dim}Full mission briefings with safety gates ${c.green}(FREE)${c.reset}${c.dim}${c.reset}`);
|
|
762
|
+
console.log();
|
|
763
|
+
console.log(` ${colors.accent}${ICONS.prompt}${c.reset} ${c.bold}vibecheck fix --prompt-only${c.reset}`);
|
|
764
|
+
console.log(` ${c.dim}Generate LLM prompts, no edits ${c.green}(FREE)${c.reset}${c.dim}${c.reset}`);
|
|
765
|
+
console.log();
|
|
766
|
+
|
|
767
|
+
// Check if apply features are available
|
|
768
|
+
const applyAccess = await entitlements.checkCommand("fix.apply_patches", { projectPath: root });
|
|
769
|
+
if (applyAccess.allowed) {
|
|
770
|
+
console.log(` ${colors.patch}${ICONS.patch}${c.reset} ${c.bold}vibecheck fix --apply${c.reset}`);
|
|
771
|
+
console.log(` ${c.dim}Apply patches from LLM ${c.green}(PRO)${c.reset}${c.dim}${c.reset}`);
|
|
772
|
+
console.log();
|
|
773
|
+
console.log(` ${colors.mission}${ICONS.robot}${c.reset} ${c.bold}vibecheck fix --autopilot --apply${c.reset}`);
|
|
774
|
+
console.log(` ${c.dim}Loop until SHIP or stuck ${c.green}(PRO)${c.reset}${c.dim}${c.reset}`);
|
|
775
|
+
console.log();
|
|
776
|
+
} else {
|
|
777
|
+
console.log(` ${c.dim}${ICONS.lock}${c.reset} ${c.dim}vibecheck fix --apply${c.reset} ${c.dim}(PRO tier required)${c.reset}`);
|
|
778
|
+
console.log(` ${c.dim}Automatically apply LLM-generated patches${c.reset}`);
|
|
779
|
+
console.log();
|
|
780
|
+
console.log(` ${c.dim}${ICONS.lock}${c.reset} ${c.dim}vibecheck fix --loop --apply${c.reset} ${c.dim}(PRO tier required)${c.reset}`);
|
|
781
|
+
console.log(` ${c.dim}Automated fix loop until SHIP${c.reset}`);
|
|
782
|
+
console.log();
|
|
783
|
+
console.log(upsell.formatEarnedUpsell({
|
|
784
|
+
cmd: "fix",
|
|
785
|
+
withheldArtifact: "apply",
|
|
786
|
+
upgradeTier: applyAccess.requiredTier || "pro",
|
|
787
|
+
why: "Apply patches automatically",
|
|
788
|
+
}));
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
return 0;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
let stagnant = 0;
|
|
795
|
+
const maxSteps = opts.maxSteps || 10;
|
|
796
|
+
const stagnationLimit = opts.stagnationLimit || 2;
|
|
797
|
+
|
|
798
|
+
// Show autopilot header if in autopilot mode
|
|
799
|
+
if (opts.autopilot) {
|
|
800
|
+
printLoopHeader(maxSteps, stagnationLimit);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Track execution summary for V2
|
|
804
|
+
const executionSummary = {
|
|
805
|
+
total: targetMissions.length,
|
|
806
|
+
completed: 0,
|
|
807
|
+
failed: 0,
|
|
808
|
+
rolledBack: 0,
|
|
809
|
+
skipped: 0,
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
for (let step = 1; step <= maxSteps; step++) {
|
|
813
|
+
const before = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
814
|
+
|
|
815
|
+
if (before.verdict === "SHIP") {
|
|
816
|
+
const duration = Date.now() - startTime;
|
|
817
|
+
|
|
818
|
+
// Generate share bundle if requested
|
|
819
|
+
if (opts.share) {
|
|
820
|
+
try {
|
|
821
|
+
startSpinner('Generating share bundle...', 'dots');
|
|
822
|
+
const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
|
|
823
|
+
stopSpinner('Share bundle generated', true);
|
|
824
|
+
} catch (e) {
|
|
825
|
+
stopSpinner('Share bundle failed', false);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Mission Control output
|
|
830
|
+
if (!opts.json && !opts.quiet) {
|
|
831
|
+
console.log(formatFixOutput({
|
|
832
|
+
missions: targetMissions,
|
|
833
|
+
verdict: before.verdict,
|
|
834
|
+
beforeVerdict: first.verdict,
|
|
835
|
+
afterVerdict: before.verdict,
|
|
836
|
+
appliedMissions: step - 1,
|
|
837
|
+
totalMissions: targetMissions.length,
|
|
838
|
+
duration,
|
|
839
|
+
success: true,
|
|
840
|
+
}, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
return 0;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
const ids = new Set(before.report.findings.map(f => f.id));
|
|
847
|
+
const mission = targetMissions.find(m => m.objective?.targetFindingIds?.some(id => ids.has(id)) || m.targetFindingIds?.some(id => ids.has(id)));
|
|
848
|
+
if (!mission) {
|
|
849
|
+
printSection('COMPLETE', ICONS.check);
|
|
850
|
+
console.log();
|
|
851
|
+
console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} No remaining planned mission matches current findings.`);
|
|
852
|
+
console.log(` ${c.dim}All planned missions completed or findings resolved.${c.reset}`);
|
|
853
|
+
console.log();
|
|
854
|
+
return 0;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
858
|
+
// FIX MISSIONS V2 - Pre-flight safety gates
|
|
859
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
860
|
+
|
|
861
|
+
const gateOptions = {
|
|
862
|
+
minConfidence: opts.minConfidence,
|
|
863
|
+
maxBlastRadius: opts.maxBlast,
|
|
864
|
+
force: opts.force,
|
|
865
|
+
allowDirty: opts.allowDirty,
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
const preFlightResults = runPreFlightGates(root, mission, gateOptions);
|
|
869
|
+
|
|
870
|
+
if (!preFlightResults.ok && !opts.force) {
|
|
871
|
+
console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} Mission ${mission.id} skipped: pre-flight gates failed`);
|
|
872
|
+
for (const result of preFlightResults.results.filter(r => !r.pass)) {
|
|
873
|
+
console.log(` ${c.dim}${ICONS.cross} ${result.gate}: ${result.reason}${c.reset}`);
|
|
874
|
+
}
|
|
875
|
+
executionSummary.skipped++;
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// Save before proof
|
|
880
|
+
fs.writeFileSync(
|
|
881
|
+
path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_before_ship.json`),
|
|
882
|
+
JSON.stringify(before.report, null, 2),
|
|
883
|
+
"utf8"
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
const targetFindingIds = mission.objective?.targetFindingIds || mission.targetFindingIds || [];
|
|
887
|
+
const targetFindings = before.report.findings.filter(f => targetFindingIds.includes(f.id));
|
|
888
|
+
|
|
889
|
+
// Show mission card
|
|
890
|
+
printMissionCard(mission, step, maxSteps, 'running');
|
|
891
|
+
|
|
892
|
+
// Use mission template + auto-expanded evidence
|
|
893
|
+
const template = templateForMissionType(mission.type);
|
|
894
|
+
const expanded = await expandEvidence({
|
|
895
|
+
repoRoot: root,
|
|
896
|
+
truthpack: before.truthpack,
|
|
897
|
+
mission,
|
|
898
|
+
targetFindings
|
|
899
|
+
});
|
|
900
|
+
const allowedFiles = expanded.allowedFiles;
|
|
901
|
+
const snippets = expanded.snippets;
|
|
902
|
+
|
|
903
|
+
const prompt = buildRealityFirewall({
|
|
904
|
+
truthpackSummary: truthpackSummary(before.truthpack),
|
|
905
|
+
mission,
|
|
906
|
+
template,
|
|
907
|
+
findings: targetFindings,
|
|
908
|
+
fileSnippets: snippets,
|
|
909
|
+
allowedFiles
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
const promptPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_prompt.txt`);
|
|
913
|
+
fs.writeFileSync(promptPath, prompt, "utf8");
|
|
914
|
+
|
|
915
|
+
console.log(` ${ICONS.prompt} Prompt: ${c.dim}${path.relative(root, promptPath)}${c.reset}`);
|
|
916
|
+
|
|
917
|
+
if (opts.promptOnly) {
|
|
918
|
+
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Prompt generated`);
|
|
919
|
+
if (!opts.loop) return 0;
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// Generate patch via LLM
|
|
924
|
+
startSpinner('Generating patch via LLM...', 'dots');
|
|
925
|
+
let patchJson;
|
|
926
|
+
try {
|
|
927
|
+
patchJson = await generatePatchJson(prompt);
|
|
928
|
+
stopSpinner('Patch generated', true);
|
|
929
|
+
} catch (e) {
|
|
930
|
+
stopSpinner('LLM failed', false);
|
|
931
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} ${e.message}`);
|
|
932
|
+
return EXIT.INTERNAL_ERROR;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
const respPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_response.json`);
|
|
936
|
+
fs.writeFileSync(respPath, JSON.stringify(patchJson, null, 2), "utf8");
|
|
937
|
+
|
|
938
|
+
// Validate patch
|
|
939
|
+
const v = validatePatchResponse({
|
|
940
|
+
repoRoot: root,
|
|
941
|
+
patchJson,
|
|
942
|
+
mission,
|
|
943
|
+
truthpack: before.truthpack,
|
|
944
|
+
allowedFiles,
|
|
945
|
+
limits: { maxEdits: 6, maxFiles: 6, maxChangedLines: 400 }
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
if (!v.ok) {
|
|
949
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Patch rejected by validator`);
|
|
950
|
+
for (const e of v.errors) {
|
|
951
|
+
console.log(` ${c.dim}${ICONS.bullet}${c.reset} ${e}`);
|
|
952
|
+
}
|
|
953
|
+
if (v.warnings.length) {
|
|
954
|
+
for (const w of v.warnings) {
|
|
955
|
+
console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} ${w}`);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return EXIT.BLOCKING;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (v.warnings.length) {
|
|
962
|
+
for (const w of v.warnings) {
|
|
963
|
+
console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} ${w}`);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
if (!opts.apply) {
|
|
968
|
+
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Patch generated (not applied)`);
|
|
969
|
+
console.log(` ${c.dim}Re-run with --apply to apply diffs${c.reset}`);
|
|
970
|
+
return 0;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
974
|
+
// FIX MISSIONS V2 - Apply patch with checkpoint-based rollback
|
|
975
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
976
|
+
|
|
977
|
+
// Determine files to touch
|
|
978
|
+
const touchedFiles = new Set();
|
|
979
|
+
for (const ed of patchJson.edits) {
|
|
980
|
+
for (const f of parseDiffTouchedFiles(ed.diff)) touchedFiles.add(f);
|
|
981
|
+
}
|
|
982
|
+
const touchedList = Array.from(touchedFiles);
|
|
983
|
+
|
|
984
|
+
// Create checkpoint before applying (V2)
|
|
985
|
+
let checkpoint;
|
|
986
|
+
try {
|
|
987
|
+
checkpoint = createCheckpoint(root, mission, touchedList);
|
|
988
|
+
mission.safety = mission.safety || {};
|
|
989
|
+
mission.safety.checkpointId = checkpoint.id;
|
|
990
|
+
console.log(` ${briefingColors.info}${briefingIcons.checkpoint}${c.reset} Checkpoint: ${c.dim}${checkpoint.id}${c.reset}`);
|
|
991
|
+
} catch (e) {
|
|
992
|
+
// Fall back to simple backup
|
|
993
|
+
const backupRoot = path.join(outDir, `backup_step_${String(step).padStart(2,"0")}`);
|
|
994
|
+
backupFiles(root, touchedList, backupRoot);
|
|
995
|
+
checkpoint = { id: null, backupRoot };
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// Apply patches
|
|
999
|
+
let applyFailed = false;
|
|
1000
|
+
for (const ed of patchJson.edits) {
|
|
1001
|
+
const res = applyUnifiedDiff(root, ed.diff);
|
|
1002
|
+
if (!res.ok) {
|
|
1003
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Patch apply failed: ${res.error}`);
|
|
1004
|
+
applyFailed = true;
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
console.log(` ${colors.patch}${ICONS.patch}${c.reset} Applied: ${c.dim}${ed.path}${c.reset}`);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// Handle apply failure - rollback
|
|
1011
|
+
if (applyFailed) {
|
|
1012
|
+
if (checkpoint.id) {
|
|
1013
|
+
const rollbackResult = rollbackToCheckpoint(root, checkpoint.id);
|
|
1014
|
+
markCheckpointFailed(root, checkpoint.id, 'Patch apply failed');
|
|
1015
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolled back via checkpoint`);
|
|
1016
|
+
} else if (checkpoint.backupRoot) {
|
|
1017
|
+
restoreBackup(root, checkpoint.backupRoot);
|
|
1018
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Restored from backup`);
|
|
1019
|
+
}
|
|
1020
|
+
executionSummary.failed++;
|
|
1021
|
+
circuitBreakerFailure();
|
|
1022
|
+
audit.error('mission_apply_failed', { missionId: mission.id, step });
|
|
1023
|
+
return EXIT.INTERNAL_ERROR;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// Verify fix
|
|
1027
|
+
startSpinner('Verifying fix...', 'dots');
|
|
1028
|
+
const after = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
1029
|
+
|
|
1030
|
+
const verdictColor = after.verdict === 'SHIP' ? colors.shipGreen :
|
|
1031
|
+
after.verdict === 'WARN' ? colors.warnAmber : colors.blockRed;
|
|
1032
|
+
stopSpinner(`Verdict: ${after.verdict}`, after.verdict === 'SHIP');
|
|
1033
|
+
console.log(` ${verdictColor}${ICONS.bullet}${c.reset} ${after.verdict}`);
|
|
1034
|
+
|
|
1035
|
+
// Save after proof
|
|
1036
|
+
fs.writeFileSync(
|
|
1037
|
+
path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_after_ship.json`),
|
|
1038
|
+
JSON.stringify(after.report, null, 2),
|
|
1039
|
+
"utf8"
|
|
1040
|
+
);
|
|
1041
|
+
|
|
1042
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1043
|
+
// FIX MISSIONS V2 - Post-flight safety gates
|
|
1044
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1045
|
+
|
|
1046
|
+
const postFlightResults = runPostFlightGates(root, mission, before, after, {
|
|
1047
|
+
runTests: !opts.skipTests,
|
|
1048
|
+
testCommand: opts.testCommand,
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
const beforeScore = score(before.report.findings);
|
|
1052
|
+
const afterScore = score(after.report.findings);
|
|
1053
|
+
const targetStillThere = targetFindingIds.some(id => after.report.findings.some(f => f.id === id));
|
|
1054
|
+
const improved = (afterScore < beforeScore) || (!targetStillThere) || postFlightResults.ok;
|
|
1055
|
+
|
|
1056
|
+
if (!improved || postFlightResults.shouldRollback) {
|
|
1057
|
+
console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} ${postFlightResults.shouldRollback ? 'Post-flight gates failed' : 'No measurable progress'}`);
|
|
1058
|
+
|
|
1059
|
+
// Show failed gates
|
|
1060
|
+
for (const result of postFlightResults.results.filter(r => !r.pass)) {
|
|
1061
|
+
console.log(` ${c.dim}${ICONS.cross} ${result.gate}: ${result.reason}${c.reset}`);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// Rollback
|
|
1065
|
+
if (checkpoint.id) {
|
|
1066
|
+
const rollbackResult = rollbackToCheckpoint(root, checkpoint.id);
|
|
1067
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolled back via checkpoint`);
|
|
1068
|
+
} else if (checkpoint.backupRoot) {
|
|
1069
|
+
restoreBackup(root, checkpoint.backupRoot);
|
|
1070
|
+
console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Restored from backup`);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
executionSummary.rolledBack++;
|
|
1074
|
+
circuitBreakerFailure();
|
|
1075
|
+
audit.warn('mission_rolled_back', {
|
|
1076
|
+
missionId: mission.id,
|
|
1077
|
+
step,
|
|
1078
|
+
reason: postFlightResults.shouldRollback ? 'post_flight_failed' : 'no_progress',
|
|
1079
|
+
failedGates: postFlightResults.results.filter(r => !r.pass).map(r => r.gate),
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
stagnant += 1;
|
|
1083
|
+
|
|
1084
|
+
if (!opts.autopilot || stagnant >= stagnationLimit) {
|
|
1085
|
+
printSection('STAGNATION', ICONS.stop);
|
|
1086
|
+
console.log();
|
|
1087
|
+
console.log(` ${colors.blockRed}${ICONS.stop}${c.reset} Stopping: stagnation limit reached (${stagnant}/${stagnationLimit})`);
|
|
1088
|
+
console.log();
|
|
1089
|
+
|
|
1090
|
+
// Show final summary
|
|
1091
|
+
executionSummary.verdict = after.verdict;
|
|
1092
|
+
executionSummary.duration = Date.now() - startTime;
|
|
1093
|
+
console.log(formatFinalSummary(executionSummary));
|
|
1094
|
+
|
|
1095
|
+
audit.error('fix_session_stagnation', {
|
|
1096
|
+
sessionId,
|
|
1097
|
+
stagnant,
|
|
1098
|
+
stagnationLimit,
|
|
1099
|
+
duration: Date.now() - startTime,
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
return EXIT.BLOCKING;
|
|
1103
|
+
}
|
|
1104
|
+
continue;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// Success - mark checkpoint as applied
|
|
1108
|
+
if (checkpoint.id) {
|
|
1109
|
+
markCheckpointApplied(root, checkpoint.id);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Progress confirmed`);
|
|
1113
|
+
console.log(formatMissionResult(mission, {
|
|
1114
|
+
success: true,
|
|
1115
|
+
findings: { before: beforeScore, after: afterScore }
|
|
1116
|
+
}));
|
|
1117
|
+
|
|
1118
|
+
executionSummary.completed++;
|
|
1119
|
+
circuitBreakerSuccess();
|
|
1120
|
+
audit.info('mission_completed', {
|
|
1121
|
+
missionId: mission.id,
|
|
1122
|
+
step,
|
|
1123
|
+
beforeScore,
|
|
1124
|
+
afterScore,
|
|
1125
|
+
improvement: beforeScore - afterScore,
|
|
1126
|
+
});
|
|
1127
|
+
|
|
1128
|
+
stagnant = 0;
|
|
1129
|
+
if (!opts.autopilot) {
|
|
1130
|
+
audit.info('fix_session_end', {
|
|
1131
|
+
sessionId,
|
|
1132
|
+
duration: Date.now() - startTime,
|
|
1133
|
+
result: 'success_single_mission',
|
|
1134
|
+
});
|
|
1135
|
+
return 0;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// Max steps reached
|
|
1140
|
+
const duration = Date.now() - startTime;
|
|
1141
|
+
const lastShip = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
|
|
1142
|
+
|
|
1143
|
+
// Generate share bundle if requested
|
|
1144
|
+
if (opts.share) {
|
|
1145
|
+
try {
|
|
1146
|
+
startSpinner('Generating share bundle...', 'dots');
|
|
1147
|
+
const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
|
|
1148
|
+
stopSpinner('Share bundle generated', true);
|
|
1149
|
+
} catch (e) {
|
|
1150
|
+
stopSpinner('Share bundle failed', false);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
// Mission Control output
|
|
1155
|
+
if (!opts.json && !opts.quiet) {
|
|
1156
|
+
console.log(formatFixOutput({
|
|
1157
|
+
missions: targetMissions,
|
|
1158
|
+
verdict: lastShip.verdict,
|
|
1159
|
+
beforeVerdict: first.verdict,
|
|
1160
|
+
afterVerdict: lastShip.verdict,
|
|
1161
|
+
appliedMissions: maxSteps,
|
|
1162
|
+
totalMissions: targetMissions.length,
|
|
1163
|
+
duration,
|
|
1164
|
+
success: false,
|
|
1165
|
+
}, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
|
|
1166
|
+
|
|
1167
|
+
// V2 Final summary
|
|
1168
|
+
executionSummary.verdict = lastShip.verdict;
|
|
1169
|
+
executionSummary.duration = duration;
|
|
1170
|
+
console.log(formatFinalSummary(executionSummary));
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// Flush audit trail
|
|
1174
|
+
audit.info('fix_session_end', {
|
|
1175
|
+
sessionId,
|
|
1176
|
+
duration,
|
|
1177
|
+
result: 'max_steps_reached',
|
|
1178
|
+
executionSummary,
|
|
1179
|
+
verdict: lastShip.verdict,
|
|
1180
|
+
});
|
|
1181
|
+
audit.flush();
|
|
1182
|
+
|
|
1183
|
+
return EXIT.WARNINGS; // Max steps reached, incomplete
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1187
|
+
// NOTE: Legacy rule-based fix functions (showFixPlan, applyFixes, etc.) were removed.
|
|
1188
|
+
// The fix command now uses the mission-based system exclusively, which provides:
|
|
1189
|
+
// - LLM-generated patches with Reality Firewall prompt
|
|
1190
|
+
// - Automatic backup/restore on failure
|
|
1191
|
+
// - Progress detection and stagnation handling
|
|
1192
|
+
// - Integration with ship verification
|
|
1193
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1194
|
+
|
|
1195
|
+
function parseArgs(args) {
|
|
1196
|
+
// Parse global flags first
|
|
1197
|
+
const { flags: globalFlags, cleanArgs } = parseGlobalFlags(args);
|
|
1198
|
+
|
|
1199
|
+
const opts = {
|
|
1200
|
+
...globalFlags, // Merge global flags (json, verbose, noBanner, quiet, ci, help, etc.)
|
|
1201
|
+
path: globalFlags.path || process.cwd(),
|
|
1202
|
+
apply: false,
|
|
1203
|
+
promptOnly: false,
|
|
1204
|
+
planOnly: false,
|
|
1205
|
+
loop: false,
|
|
1206
|
+
share: false,
|
|
1207
|
+
maxMissions: 8,
|
|
1208
|
+
maxSteps: 10,
|
|
1209
|
+
stagnationLimit: 2,
|
|
1210
|
+
fastifyEntry: null,
|
|
1211
|
+
// Fix Missions V2 - New options
|
|
1212
|
+
rollback: null, // Mission ID to rollback
|
|
1213
|
+
mission: null, // Specific mission ID to run
|
|
1214
|
+
force: false, // Override safety gates
|
|
1215
|
+
minConfidence: DEFAULT_THRESHOLDS.minConfidence,
|
|
1216
|
+
maxBlast: DEFAULT_THRESHOLDS.maxBlastRadius,
|
|
1217
|
+
allowDirty: false, // Allow uncommitted changes
|
|
1218
|
+
skipTests: true, // Skip post-flight tests
|
|
1219
|
+
listCheckpoints: false,
|
|
1220
|
+
cleanupCheckpoints: false,
|
|
1221
|
+
// Note: help comes from globalFlags, don't override it here
|
|
1222
|
+
};
|
|
1223
|
+
|
|
1224
|
+
// Parse command-specific args from cleanArgs
|
|
1225
|
+
for (let i = 0; i < cleanArgs.length; i++) {
|
|
1226
|
+
const arg = cleanArgs[i];
|
|
1227
|
+
if (arg === '--apply') opts.apply = true;
|
|
1228
|
+
else if (arg === '--prompt-only') opts.promptOnly = true;
|
|
1229
|
+
else if (arg === '--plan-only') opts.planOnly = true;
|
|
1230
|
+
else if (arg === '--autopilot') opts.autopilot = true;
|
|
1231
|
+
else if (arg === '--share') opts.share = true;
|
|
1232
|
+
else if (arg === '--max-missions') opts.maxMissions = Number(cleanArgs[++i]) || 8;
|
|
1233
|
+
else if (arg === '--max-steps') opts.maxSteps = Number(cleanArgs[++i]) || 10;
|
|
1234
|
+
else if (arg === '--stagnation-limit') opts.stagnationLimit = Number(cleanArgs[++i]) || 2;
|
|
1235
|
+
else if (arg === '--fastify-entry') opts.fastifyEntry = cleanArgs[++i];
|
|
1236
|
+
else if (arg === '--path' || arg === '-p') opts.path = cleanArgs[++i];
|
|
1237
|
+
else if (arg === '--help' || arg === '-h') opts.help = true;
|
|
1238
|
+
// Fix Missions V2 - New flags
|
|
1239
|
+
else if (arg === '--rollback') opts.rollback = cleanArgs[++i];
|
|
1240
|
+
else if (arg === '--mission') opts.mission = cleanArgs[++i];
|
|
1241
|
+
else if (arg === '--force') opts.force = true;
|
|
1242
|
+
else if (arg === '--min-confidence') opts.minConfidence = Number(cleanArgs[++i]) || DEFAULT_THRESHOLDS.minConfidence;
|
|
1243
|
+
else if (arg === '--max-blast') opts.maxBlast = Number(cleanArgs[++i]) || DEFAULT_THRESHOLDS.maxBlastRadius;
|
|
1244
|
+
else if (arg === '--allow-dirty') opts.allowDirty = true;
|
|
1245
|
+
else if (arg === '--run-tests') opts.skipTests = false;
|
|
1246
|
+
else if (arg === '--list-checkpoints') opts.listCheckpoints = true;
|
|
1247
|
+
else if (arg === '--cleanup-checkpoints') opts.cleanupCheckpoints = true;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
return opts;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function printHelp(showBanner = true) {
|
|
1254
|
+
if (showBanner && shouldShowBanner({})) {
|
|
1255
|
+
console.log(BANNER_FULL);
|
|
1256
|
+
}
|
|
1257
|
+
console.log(`
|
|
1258
|
+
${c.bold}Usage:${c.reset} vibecheck fix (f) [options]
|
|
1259
|
+
|
|
1260
|
+
${c.bold}Mission Control V2${c.reset} — "Missions, not chaos" - Surgical fixes with safety gates.
|
|
1261
|
+
|
|
1262
|
+
${c.bold}Modes:${c.reset}
|
|
1263
|
+
${colors.accent}vibecheck fix${c.reset} ${c.dim}Plan missions (no changes) ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
|
|
1264
|
+
${colors.accent}vibecheck fix --plan-only${c.reset} ${c.dim}Full mission briefings ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
|
|
1265
|
+
${colors.accent}vibecheck fix --prompt-only${c.reset} ${c.dim}Generate LLM prompts ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
|
|
1266
|
+
${colors.accent}vibecheck fix --apply${c.reset} ${c.dim}Apply patches from LLM ${c.yellow}(PRO)${c.reset}${c.dim}${c.reset}
|
|
1267
|
+
${colors.accent}vibecheck fix --autopilot --apply${c.reset} ${c.dim}Loop until SHIP or stuck ${c.yellow}(PRO)${c.reset}${c.dim}${c.reset}
|
|
1268
|
+
|
|
1269
|
+
${c.bold}Core Options:${c.reset}
|
|
1270
|
+
${colors.accent}--plan-only${c.reset} Show full mission briefings with safety gates
|
|
1271
|
+
${colors.accent}--prompt-only${c.reset} Generate mission prompts only ${c.dim}(no edits)${c.reset}
|
|
1272
|
+
${colors.accent}--apply${c.reset} Apply patches returned by the model ${c.dim}(PRO tier)${c.reset}
|
|
1273
|
+
${colors.accent}--autopilot${c.reset} Loop: fix → verify → fix until SHIP ${c.dim}(PRO tier)${c.reset}
|
|
1274
|
+
${colors.accent}--share${c.reset} Generate share bundle after fix ${c.dim}(PRO tier)${c.reset}
|
|
1275
|
+
|
|
1276
|
+
${c.bold}Mission Selection:${c.reset}
|
|
1277
|
+
${colors.accent}--mission <id>${c.reset} Run specific mission only (e.g., M_abc123)
|
|
1278
|
+
${colors.accent}--max-missions <n>${c.reset} Max missions to plan ${c.dim}(default: 8)${c.reset}
|
|
1279
|
+
|
|
1280
|
+
${c.bold}Safety Gates (V2):${c.reset}
|
|
1281
|
+
${colors.accent}--force${c.reset} Override safety gates for critical missions
|
|
1282
|
+
${colors.accent}--min-confidence <n>${c.reset} Min confidence threshold ${c.dim}(default: 0.6)${c.reset}
|
|
1283
|
+
${colors.accent}--max-blast <n>${c.reset} Max files per mission ${c.dim}(default: 10)${c.reset}
|
|
1284
|
+
${colors.accent}--allow-dirty${c.reset} Allow uncommitted git changes
|
|
1285
|
+
${colors.accent}--run-tests${c.reset} Run tests in post-flight gates
|
|
1286
|
+
|
|
1287
|
+
${c.bold}Rollback & Checkpoints (V2):${c.reset}
|
|
1288
|
+
${colors.accent}--rollback <id>${c.reset} Rollback a mission by ID
|
|
1289
|
+
${colors.accent}--list-checkpoints${c.reset} List all checkpoints
|
|
1290
|
+
${colors.accent}--cleanup-checkpoints${c.reset} Clean up old checkpoints
|
|
1291
|
+
|
|
1292
|
+
${c.bold}Autopilot Options:${c.reset}
|
|
1293
|
+
${colors.accent}--max-steps <n>${c.reset} Max autopilot steps ${c.dim}(default: 10)${c.reset}
|
|
1294
|
+
${colors.accent}--stagnation-limit${c.reset} Stop after N non-improving steps ${c.dim}(default: 2)${c.reset}
|
|
1295
|
+
|
|
1296
|
+
${c.bold}Other Options:${c.reset}
|
|
1297
|
+
${colors.accent}--fastify-entry${c.reset} Fastify entry file ${c.dim}(e.g. src/server.ts)${c.reset}
|
|
1298
|
+
${colors.accent}--path, -p${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
|
|
1299
|
+
${colors.accent}--help, -h${c.reset} Show this help
|
|
1300
|
+
|
|
1301
|
+
${c.bold}Safety Features:${c.reset}
|
|
1302
|
+
${colors.shipGreen}${ICONS.shield}${c.reset} Reality Firewall prompt prevents LLM hallucinations
|
|
1303
|
+
${colors.shipGreen}${ICONS.check}${c.reset} Patch validator ensures no drift (files, routes, env)
|
|
1304
|
+
${colors.shipGreen}${ICONS.rollback}${c.reset} Backup/restore for automatic rollback on failure
|
|
1305
|
+
${colors.shipGreen}${ICONS.stop}${c.reset} Progress detector stops on stagnation
|
|
1306
|
+
|
|
1307
|
+
${c.bold}Mission Types:${c.reset}
|
|
1308
|
+
${c.dim}Security & Auth:${c.reset}
|
|
1309
|
+
${colors.critical}${ICONS.lock}${c.reset} REMOVE_OWNER_MODE ${c.dim}Delete backdoor env bypass${c.reset}
|
|
1310
|
+
${colors.critical}${ICONS.lock}${c.reset} FIX_HARDCODED_SECRETS ${c.dim}Move secrets to env vars${c.reset}
|
|
1311
|
+
${colors.critical}${ICONS.key}${c.reset} FIX_TEST_KEYS ${c.dim}Replace test API keys${c.reset}
|
|
1312
|
+
${colors.critical}${ICONS.shield}${c.reset} FIX_AUTH_DRIFT ${c.dim}Restore removed auth patterns${c.reset}
|
|
1313
|
+
${colors.medium}${ICONS.auth}${c.reset} ADD_SERVER_AUTH ${c.dim}Add auth to sensitive endpoints${c.reset}
|
|
1314
|
+
|
|
1315
|
+
${c.dim}Billing & Payments:${c.reset}
|
|
1316
|
+
${colors.high}${ICONS.money}${c.reset} FIX_STRIPE_WEBHOOKS ${c.dim}Add signature verification + idempotency${c.reset}
|
|
1317
|
+
${colors.high}${ICONS.shield}${c.reset} ENFORCE_PAID_SURFACE ${c.dim}Add server-side entitlement checks${c.reset}
|
|
1318
|
+
${colors.critical}${ICONS.money}${c.reset} FIX_SIMULATED_BILLING ${c.dim}Replace fake billing with real${c.reset}
|
|
1319
|
+
|
|
1320
|
+
${c.dim}Reality & Data:${c.reset}
|
|
1321
|
+
${colors.critical}${ICONS.link}${c.reset} FIX_MOCK_DOMAINS ${c.dim}Replace localhost/mock URLs${c.reset}
|
|
1322
|
+
${colors.medium}${ICONS.ghost}${c.reset} FIX_FAKE_SUCCESS ${c.dim}Gate success UI on network result${c.reset}
|
|
1323
|
+
${colors.medium}${ICONS.doc}${c.reset} FIX_PLACEHOLDER_DATA ${c.dim}Replace lorem ipsum with real data${c.reset}
|
|
1324
|
+
${colors.high}${ICONS.warning}${c.reset} FIX_SILENT_FALLBACK ${c.dim}Make failures visible${c.reset}
|
|
1325
|
+
|
|
1326
|
+
${c.dim}Code Quality:${c.reset}
|
|
1327
|
+
${colors.high}${ICONS.bug}${c.reset} FIX_EMPTY_CATCH ${c.dim}Add error handling to catch blocks${c.reset}
|
|
1328
|
+
${colors.medium}${ICONS.route}${c.reset} FIX_MISSING_ROUTE ${c.dim}Wire client refs to server routes${c.reset}
|
|
1329
|
+
${colors.low}${ICONS.env}${c.reset} FIX_ENV_CONTRACT ${c.dim}Add missing env vars to templates${c.reset}
|
|
1330
|
+
${colors.low}${ICONS.dead}${c.reset} FIX_DEAD_UI ${c.dim}Make UI actions functional${c.reset}
|
|
1331
|
+
|
|
1332
|
+
${c.bold}LLM Configuration:${c.reset}
|
|
1333
|
+
${c.dim}Set these environment variables:${c.reset}
|
|
1334
|
+
${colors.accent}VIBECHECK_LLM_BASE_URL${c.reset} ${c.dim}API endpoint${c.reset}
|
|
1335
|
+
${colors.accent}VIBECHECK_LLM_API_KEY${c.reset} ${c.dim}Your API key${c.reset}
|
|
1336
|
+
${colors.accent}VIBECHECK_LLM_MODEL${c.reset} ${c.dim}Model name (default: gpt-4.1-mini)${c.reset}
|
|
1337
|
+
|
|
1338
|
+
${c.bold}Exit Codes:${c.reset}
|
|
1339
|
+
${colors.shipGreen}0${c.reset} SHIP achieved or no fixes needed
|
|
1340
|
+
${colors.warnAmber}1${c.reset} Fix failed or stagnation limit reached
|
|
1341
|
+
${colors.blockRed}2${c.reset} Configuration or validation error
|
|
1342
|
+
|
|
1343
|
+
${c.bold}Examples:${c.reset}
|
|
1344
|
+
${c.dim}# Plan missions (see what would be fixed)${c.reset}
|
|
1345
|
+
vibecheck fix
|
|
1346
|
+
|
|
1347
|
+
${c.dim}# Generate prompts for manual LLM use${c.reset}
|
|
1348
|
+
vibecheck fix --prompt-only
|
|
1349
|
+
|
|
1350
|
+
${c.dim}# Full loop with share bundle (PRO tier)${c.reset}
|
|
1351
|
+
vibecheck fix --loop --apply --share
|
|
1352
|
+
`);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
module.exports = { runFix };
|