vibecheck-ai 2.0.1 → 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,832 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ship Gate - The Final Arbiter
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* ONE VERDICT: SHIP / WARN / BLOCK - BACKED BY EVIDENCE
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* The Ship Gate orchestrates three verification layers:
|
|
9
|
+
*
|
|
10
|
+
* 1. AUDIT - Static analysis findings (truthpack, analyzers)
|
|
11
|
+
* 2. REALITY - Runtime verification (browser testing)
|
|
12
|
+
* 3. SHIELD - Agent firewall status (intent enforcement)
|
|
13
|
+
*
|
|
14
|
+
* Each layer contributes evidence. The gate combines them into a final verdict.
|
|
15
|
+
*
|
|
16
|
+
* Key guarantees:
|
|
17
|
+
* - DETERMINISTIC: Same repo state → same verdict
|
|
18
|
+
* - EVIDENCE-BACKED: Every verdict has a "why tree"
|
|
19
|
+
* - CI-READY: Exit codes, receipts, badges
|
|
20
|
+
*
|
|
21
|
+
* @module ship-gate
|
|
22
|
+
* @version 1.1.0 - Hardened
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
"use strict";
|
|
26
|
+
|
|
27
|
+
const fs = require("fs");
|
|
28
|
+
const path = require("path");
|
|
29
|
+
|
|
30
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
31
|
+
// ERROR TYPES
|
|
32
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
33
|
+
|
|
34
|
+
class GateError extends Error {
|
|
35
|
+
constructor(message, code, details = {}) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "GateError";
|
|
38
|
+
this.code = code;
|
|
39
|
+
this.details = details;
|
|
40
|
+
this.recoverable = true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class ConfigurationError extends GateError {
|
|
45
|
+
constructor(message, field) {
|
|
46
|
+
super(message, "CONFIG_ERROR", { field });
|
|
47
|
+
this.name = "ConfigurationError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class EvaluationError extends GateError {
|
|
52
|
+
constructor(message, phase, cause) {
|
|
53
|
+
super(message, "EVAL_ERROR", { phase, cause: cause?.message });
|
|
54
|
+
this.name = "EvaluationError";
|
|
55
|
+
this.cause = cause;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Lazy imports for performance
|
|
60
|
+
let _shipManifest = null;
|
|
61
|
+
let _verdictEngine = null;
|
|
62
|
+
let _truth = null;
|
|
63
|
+
let _analyzers = null;
|
|
64
|
+
|
|
65
|
+
function getShipManifest() {
|
|
66
|
+
if (!_shipManifest) {
|
|
67
|
+
_shipManifest = require("./ship-manifest");
|
|
68
|
+
}
|
|
69
|
+
return _shipManifest;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getVerdictEngine() {
|
|
73
|
+
if (!_verdictEngine) {
|
|
74
|
+
_verdictEngine = require("./verdict-engine");
|
|
75
|
+
}
|
|
76
|
+
return _verdictEngine;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getTruth() {
|
|
80
|
+
if (!_truth) {
|
|
81
|
+
_truth = require("./truth");
|
|
82
|
+
}
|
|
83
|
+
return _truth;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function getAnalyzers() {
|
|
87
|
+
if (!_analyzers) {
|
|
88
|
+
_analyzers = require("./analyzers");
|
|
89
|
+
}
|
|
90
|
+
return _analyzers;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
94
|
+
// GATE CONFIGURATION
|
|
95
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
96
|
+
|
|
97
|
+
const DEFAULT_CONFIG = {
|
|
98
|
+
// Verdict rules
|
|
99
|
+
blockOn: {
|
|
100
|
+
auditBlockers: true, // Block if audit finds BLOCK-severity issues
|
|
101
|
+
realityFailures: true, // Block if reality tests fail
|
|
102
|
+
shieldViolations: false, // Block if shield has violations (default: warn only)
|
|
103
|
+
dirtyWorkingTree: false, // Block if git working tree is dirty
|
|
104
|
+
coverageThreshold: 0, // Block if route coverage below this %
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
// Warn rules
|
|
108
|
+
warnOn: {
|
|
109
|
+
auditWarnings: true, // Warn on WARN-severity issues
|
|
110
|
+
staletruthpack: true, // Warn if truthpack is stale (>1hr old)
|
|
111
|
+
noReality: true, // Warn if no reality tests ran
|
|
112
|
+
observeMode: true, // Warn if shield is in observe mode
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
// Strict mode (warnings become blockers)
|
|
116
|
+
strict: false,
|
|
117
|
+
|
|
118
|
+
// Score calculation
|
|
119
|
+
scoring: {
|
|
120
|
+
baseScore: 100,
|
|
121
|
+
blockerPenalty: 15,
|
|
122
|
+
warningPenalty: 5,
|
|
123
|
+
infoPenalty: 1,
|
|
124
|
+
realityBonus: 10, // Bonus for passing reality tests
|
|
125
|
+
shieldBonus: 5, // Bonus for shield in enforce mode
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
130
|
+
// SHIP GATE ORCHESTRATOR
|
|
131
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* ShipGate - The orchestrator class
|
|
135
|
+
*
|
|
136
|
+
* Usage:
|
|
137
|
+
* const gate = new ShipGate(repoRoot, config);
|
|
138
|
+
* const result = await gate.evaluate();
|
|
139
|
+
* // result.verdict === "SHIP" | "WARN" | "BLOCK"
|
|
140
|
+
*/
|
|
141
|
+
class ShipGate {
|
|
142
|
+
/**
|
|
143
|
+
* Create a new ShipGate instance.
|
|
144
|
+
*
|
|
145
|
+
* @param {string} repoRoot - Repository root path
|
|
146
|
+
* @param {Object} config - Gate configuration
|
|
147
|
+
* @throws {ConfigurationError} If configuration is invalid
|
|
148
|
+
*/
|
|
149
|
+
constructor(repoRoot, config = {}) {
|
|
150
|
+
// Validate and set repo root
|
|
151
|
+
this.repoRoot = this._validateRepoRoot(repoRoot);
|
|
152
|
+
|
|
153
|
+
// Merge and validate config
|
|
154
|
+
this.config = this._validateConfig({ ...DEFAULT_CONFIG, ...config });
|
|
155
|
+
|
|
156
|
+
// Timing
|
|
157
|
+
this.startTime = Date.now();
|
|
158
|
+
this.timeoutMs = 5 * 60 * 1000; // 5 minute timeout
|
|
159
|
+
|
|
160
|
+
// Evidence collectors
|
|
161
|
+
this.evidence = {
|
|
162
|
+
audit: null,
|
|
163
|
+
reality: null,
|
|
164
|
+
shield: null,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// Findings from all sources
|
|
168
|
+
this.findings = [];
|
|
169
|
+
|
|
170
|
+
// Verdict tracking
|
|
171
|
+
this.blockReasons = [];
|
|
172
|
+
this.warnReasons = [];
|
|
173
|
+
this.passReasons = [];
|
|
174
|
+
|
|
175
|
+
// Error tracking
|
|
176
|
+
this.errors = [];
|
|
177
|
+
this.warnings = [];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Validate repository root path
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
_validateRepoRoot(repoRoot) {
|
|
185
|
+
const root = repoRoot || process.cwd();
|
|
186
|
+
|
|
187
|
+
if (typeof root !== "string" || !root.trim()) {
|
|
188
|
+
throw new ConfigurationError("repoRoot must be a non-empty string", "repoRoot");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Prevent null byte injection
|
|
192
|
+
if (root.includes("\0")) {
|
|
193
|
+
throw new ConfigurationError("repoRoot contains invalid characters", "repoRoot");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const resolved = path.resolve(root);
|
|
197
|
+
|
|
198
|
+
// Check if directory exists
|
|
199
|
+
try {
|
|
200
|
+
const stats = fs.statSync(resolved);
|
|
201
|
+
if (!stats.isDirectory()) {
|
|
202
|
+
throw new ConfigurationError(`repoRoot is not a directory: ${resolved}`, "repoRoot");
|
|
203
|
+
}
|
|
204
|
+
} catch (err) {
|
|
205
|
+
if (err instanceof ConfigurationError) throw err;
|
|
206
|
+
throw new ConfigurationError(`repoRoot does not exist: ${resolved}`, "repoRoot");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return resolved;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Validate gate configuration
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
216
|
+
_validateConfig(config) {
|
|
217
|
+
if (!config || typeof config !== "object") {
|
|
218
|
+
return { ...DEFAULT_CONFIG };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Ensure nested objects exist
|
|
222
|
+
const validated = {
|
|
223
|
+
blockOn: { ...DEFAULT_CONFIG.blockOn, ...(config.blockOn || {}) },
|
|
224
|
+
warnOn: { ...DEFAULT_CONFIG.warnOn, ...(config.warnOn || {}) },
|
|
225
|
+
strict: Boolean(config.strict),
|
|
226
|
+
scoring: { ...DEFAULT_CONFIG.scoring, ...(config.scoring || {}) },
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Validate scoring values are numbers
|
|
230
|
+
for (const [key, value] of Object.entries(validated.scoring)) {
|
|
231
|
+
validated.scoring[key] = Math.max(0, Number(value) || 0);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return validated;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Check if gate has timed out
|
|
239
|
+
* @private
|
|
240
|
+
*/
|
|
241
|
+
_checkTimeout() {
|
|
242
|
+
if (Date.now() - this.startTime > this.timeoutMs) {
|
|
243
|
+
throw new EvaluationError(
|
|
244
|
+
`Gate evaluation timed out after ${Math.round(this.timeoutMs / 1000)}s`,
|
|
245
|
+
"timeout"
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Safe wrapper for async operations
|
|
252
|
+
* @private
|
|
253
|
+
*/
|
|
254
|
+
async _safeAsync(fn, phase, fallback = null) {
|
|
255
|
+
try {
|
|
256
|
+
this._checkTimeout();
|
|
257
|
+
return await fn();
|
|
258
|
+
} catch (err) {
|
|
259
|
+
this.errors.push({
|
|
260
|
+
phase,
|
|
261
|
+
message: err.message,
|
|
262
|
+
code: err.code,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
if (process.env.DEBUG || process.env.VIBECHECK_DEBUG) {
|
|
266
|
+
console.error(`[ShipGate] ${phase} failed:`, err.message);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return fallback;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Run the full gate evaluation.
|
|
275
|
+
*
|
|
276
|
+
* @param {Object} options - Evaluation options
|
|
277
|
+
* @returns {Object} Gate result with verdict, evidence, manifest
|
|
278
|
+
* @throws {EvaluationError} If evaluation fails critically
|
|
279
|
+
*/
|
|
280
|
+
async evaluate(options = {}) {
|
|
281
|
+
const safeOptions = options || {};
|
|
282
|
+
const {
|
|
283
|
+
skipAudit = false,
|
|
284
|
+
skipReality = false,
|
|
285
|
+
skipShield = false,
|
|
286
|
+
truthpack = null,
|
|
287
|
+
realityReport = null,
|
|
288
|
+
shieldStatus = null,
|
|
289
|
+
} = safeOptions;
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
// Phase 1: Collect evidence from each layer
|
|
293
|
+
if (!skipAudit) {
|
|
294
|
+
this.evidence.audit = truthpack || await this._safeAsync(
|
|
295
|
+
() => this.collectAuditEvidence(),
|
|
296
|
+
"audit",
|
|
297
|
+
null
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (!skipReality) {
|
|
302
|
+
this.evidence.reality = realityReport || await this._safeAsync(
|
|
303
|
+
() => Promise.resolve(this.loadRealityEvidence()),
|
|
304
|
+
"reality",
|
|
305
|
+
null
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (!skipShield) {
|
|
310
|
+
this.evidence.shield = shieldStatus || await this._safeAsync(
|
|
311
|
+
() => Promise.resolve(this.loadShieldEvidence()),
|
|
312
|
+
"shield",
|
|
313
|
+
null
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Phase 2: Run analyzers and collect findings
|
|
318
|
+
await this._safeAsync(
|
|
319
|
+
() => this.collectFindings(),
|
|
320
|
+
"analyzers"
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
// Phase 3: Compute verdict
|
|
324
|
+
const verdict = this.computeVerdict();
|
|
325
|
+
|
|
326
|
+
// Phase 4: Calculate score
|
|
327
|
+
const score = this.calculateScore(verdict);
|
|
328
|
+
|
|
329
|
+
// Phase 5: Generate manifest
|
|
330
|
+
const shipManifest = getShipManifest();
|
|
331
|
+
if (!shipManifest) {
|
|
332
|
+
throw new EvaluationError("Ship manifest module not available", "manifest");
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const { generateShipManifest, writeShipManifest } = shipManifest;
|
|
336
|
+
|
|
337
|
+
let manifest;
|
|
338
|
+
try {
|
|
339
|
+
manifest = generateShipManifest({
|
|
340
|
+
repoRoot: this.repoRoot,
|
|
341
|
+
verdict,
|
|
342
|
+
score,
|
|
343
|
+
findings: this.findings,
|
|
344
|
+
truthpack: this.evidence.audit,
|
|
345
|
+
realityReport: this.evidence.reality,
|
|
346
|
+
shieldStatus: this.evidence.shield,
|
|
347
|
+
durationMs: Date.now() - this.startTime,
|
|
348
|
+
});
|
|
349
|
+
} catch (err) {
|
|
350
|
+
throw new EvaluationError(`Manifest generation failed: ${err.message}`, "manifest", err);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Phase 6: Write artifacts (non-fatal if fails)
|
|
354
|
+
let artifactPaths = {};
|
|
355
|
+
try {
|
|
356
|
+
artifactPaths = writeShipManifest(this.repoRoot, manifest);
|
|
357
|
+
} catch (err) {
|
|
358
|
+
this.errors.push({
|
|
359
|
+
phase: "artifacts",
|
|
360
|
+
message: err.message,
|
|
361
|
+
});
|
|
362
|
+
// Continue without failing - verdict is still valid
|
|
363
|
+
artifactPaths = {
|
|
364
|
+
manifest: null,
|
|
365
|
+
receipt: null,
|
|
366
|
+
githubOutput: null,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return this._buildResult(verdict, score, manifest, artifactPaths);
|
|
371
|
+
|
|
372
|
+
} catch (err) {
|
|
373
|
+
// If we get here, something critical failed
|
|
374
|
+
// Return a BLOCK verdict with error info
|
|
375
|
+
if (err instanceof GateError) {
|
|
376
|
+
throw err;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
throw new EvaluationError(
|
|
380
|
+
`Gate evaluation failed: ${err.message}`,
|
|
381
|
+
"unknown",
|
|
382
|
+
err
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Build the final result object
|
|
389
|
+
* @private
|
|
390
|
+
*/
|
|
391
|
+
_buildResult(verdict, score, manifest, artifactPaths) {
|
|
392
|
+
const blockerCount = this.findings.filter(f => f.severity === "BLOCK").length;
|
|
393
|
+
const warningCount = this.findings.filter(f => f.severity === "WARN").length;
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
// Core verdict
|
|
397
|
+
verdict,
|
|
398
|
+
score,
|
|
399
|
+
canShip: verdict === "SHIP",
|
|
400
|
+
exitCode: manifest?.verdict?.exitCode ?? 2,
|
|
401
|
+
|
|
402
|
+
// Evidence summary
|
|
403
|
+
evidence: {
|
|
404
|
+
audit: {
|
|
405
|
+
ran: this.evidence.audit !== null,
|
|
406
|
+
findings: this.findings.length,
|
|
407
|
+
blockers: blockerCount,
|
|
408
|
+
warnings: warningCount,
|
|
409
|
+
},
|
|
410
|
+
reality: {
|
|
411
|
+
ran: this.evidence.reality !== null,
|
|
412
|
+
actions: Math.max(0, this.evidence.reality?.actions?.length || 0),
|
|
413
|
+
requests: Math.max(0, this.evidence.reality?.requests?.length || 0),
|
|
414
|
+
},
|
|
415
|
+
shield: {
|
|
416
|
+
ran: this.evidence.shield !== null,
|
|
417
|
+
mode: this.evidence.shield?.mode || "unknown",
|
|
418
|
+
enforcing: this.evidence.shield?.mode === "enforce",
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
// Why tree (top 3 blockers/warnings)
|
|
423
|
+
whyTree: manifest?.evidence?.whyTree || {
|
|
424
|
+
summary: blockerCount > 0 ? `${blockerCount} blocker(s)` : "Unknown",
|
|
425
|
+
topIssues: [],
|
|
426
|
+
fixMissions: [],
|
|
427
|
+
},
|
|
428
|
+
|
|
429
|
+
// Full findings (limited)
|
|
430
|
+
findings: this.findings.slice(0, 100),
|
|
431
|
+
|
|
432
|
+
// Errors encountered during evaluation
|
|
433
|
+
errors: this.errors.length > 0 ? this.errors : undefined,
|
|
434
|
+
|
|
435
|
+
// Manifest and artifacts
|
|
436
|
+
manifest,
|
|
437
|
+
artifactPaths,
|
|
438
|
+
|
|
439
|
+
// Timing
|
|
440
|
+
durationMs: Date.now() - this.startTime,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Collect audit evidence (truthpack and findings)
|
|
446
|
+
*/
|
|
447
|
+
async collectAuditEvidence() {
|
|
448
|
+
const { buildTruthpackSmart, detectFastifyEntry } = getTruth();
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
const fastifyEntry = detectFastifyEntry(this.repoRoot);
|
|
452
|
+
const truthpack = await buildTruthpackSmart({
|
|
453
|
+
repoRoot: this.repoRoot,
|
|
454
|
+
fastifyEntry,
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
return truthpack;
|
|
458
|
+
} catch (err) {
|
|
459
|
+
this.warnReasons.push(`Truthpack generation failed: ${err.message}`);
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Load reality evidence from disk
|
|
466
|
+
*/
|
|
467
|
+
loadRealityEvidence() {
|
|
468
|
+
const realityPath = path.join(this.repoRoot, ".vibecheck", "reality", "last_reality.json");
|
|
469
|
+
|
|
470
|
+
if (!fs.existsSync(realityPath)) {
|
|
471
|
+
if (this.config.warnOn.noReality) {
|
|
472
|
+
this.warnReasons.push("No reality tests found. Run 'vibecheck reality' for runtime verification.");
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
const report = JSON.parse(fs.readFileSync(realityPath, "utf8"));
|
|
479
|
+
|
|
480
|
+
// Check freshness (warn if older than 1 hour)
|
|
481
|
+
const age = Date.now() - new Date(report.meta?.timestamp || 0).getTime();
|
|
482
|
+
if (age > 3600000 && this.config.warnOn.staletruthpack) {
|
|
483
|
+
this.warnReasons.push("Reality report is older than 1 hour. Consider re-running 'vibecheck reality'.");
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return report;
|
|
487
|
+
} catch {
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Load shield evidence from disk
|
|
494
|
+
*/
|
|
495
|
+
loadShieldEvidence() {
|
|
496
|
+
const policyPath = path.join(this.repoRoot, ".vibecheck", "policy.json");
|
|
497
|
+
const statusPath = path.join(this.repoRoot, ".vibecheck", "shield-status.json");
|
|
498
|
+
|
|
499
|
+
let status = {
|
|
500
|
+
mode: "observe",
|
|
501
|
+
locked: false,
|
|
502
|
+
installed: false,
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// Load policy
|
|
506
|
+
if (fs.existsSync(policyPath)) {
|
|
507
|
+
try {
|
|
508
|
+
const policy = JSON.parse(fs.readFileSync(policyPath, "utf8"));
|
|
509
|
+
status.mode = policy.mode || "observe";
|
|
510
|
+
} catch {
|
|
511
|
+
// Use defaults
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Load status
|
|
516
|
+
if (fs.existsSync(statusPath)) {
|
|
517
|
+
try {
|
|
518
|
+
const savedStatus = JSON.parse(fs.readFileSync(statusPath, "utf8"));
|
|
519
|
+
status = { ...status, ...savedStatus };
|
|
520
|
+
} catch {
|
|
521
|
+
// Use defaults
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Check for observe mode warning
|
|
526
|
+
if (status.mode === "observe" && this.config.warnOn.observeMode) {
|
|
527
|
+
this.warnReasons.push("Shield is in OBSERVE mode. Run 'vibecheck shield enforce' for full protection.");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return status;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Collect findings from all analyzers with timeout and error handling
|
|
535
|
+
*/
|
|
536
|
+
async collectFindings() {
|
|
537
|
+
const truthpack = this.evidence.audit;
|
|
538
|
+
const allFindings = [];
|
|
539
|
+
|
|
540
|
+
// Get analyzers module
|
|
541
|
+
const analyzers = getAnalyzers();
|
|
542
|
+
if (!analyzers) {
|
|
543
|
+
this.warnings.push("Analyzers module not available");
|
|
544
|
+
this.findings = [];
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Define analyzer functions with safety wrappers
|
|
549
|
+
const safeAnalyzer = (fn, name) => async () => {
|
|
550
|
+
try {
|
|
551
|
+
this._checkTimeout();
|
|
552
|
+
const result = fn();
|
|
553
|
+
return Array.isArray(result) ? result : [];
|
|
554
|
+
} catch (err) {
|
|
555
|
+
this.errors.push({
|
|
556
|
+
phase: `analyzer:${name}`,
|
|
557
|
+
message: err.message,
|
|
558
|
+
});
|
|
559
|
+
return [];
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// Build analyzer list based on what's available
|
|
564
|
+
const analyzerList = [];
|
|
565
|
+
|
|
566
|
+
// Truthpack-based analyzers (only if truthpack available)
|
|
567
|
+
if (truthpack) {
|
|
568
|
+
if (analyzers.findMissingRoutes) {
|
|
569
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findMissingRoutes(truthpack), "missingRoutes"));
|
|
570
|
+
}
|
|
571
|
+
if (analyzers.findEnvGaps) {
|
|
572
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findEnvGaps(truthpack), "envGaps"));
|
|
573
|
+
}
|
|
574
|
+
if (analyzers.findGhostAuth) {
|
|
575
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findGhostAuth(truthpack, this.repoRoot), "ghostAuth"));
|
|
576
|
+
}
|
|
577
|
+
if (analyzers.findStripeWebhookViolations) {
|
|
578
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findStripeWebhookViolations(truthpack), "stripeWebhook"));
|
|
579
|
+
}
|
|
580
|
+
if (analyzers.findPaidSurfaceNotEnforced) {
|
|
581
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findPaidSurfaceNotEnforced(truthpack), "paidSurface"));
|
|
582
|
+
}
|
|
583
|
+
if (analyzers.findMethodMismatch) {
|
|
584
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findMethodMismatch(truthpack), "methodMismatch"));
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// File-based analyzers (always run)
|
|
589
|
+
if (analyzers.findFakeSuccess) {
|
|
590
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findFakeSuccess(this.repoRoot), "fakeSuccess"));
|
|
591
|
+
}
|
|
592
|
+
if (analyzers.findOptimisticNoRollback) {
|
|
593
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findOptimisticNoRollback(this.repoRoot), "optimisticNoRollback"));
|
|
594
|
+
}
|
|
595
|
+
if (analyzers.findSilentCatch) {
|
|
596
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findSilentCatch(this.repoRoot), "silentCatch"));
|
|
597
|
+
}
|
|
598
|
+
if (analyzers.findDeadUI) {
|
|
599
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findDeadUI(this.repoRoot), "deadUI"));
|
|
600
|
+
}
|
|
601
|
+
if (analyzers.findOwnerModeBypass) {
|
|
602
|
+
analyzerList.push(safeAnalyzer(() => analyzers.findOwnerModeBypass(this.repoRoot), "ownerModeBypass"));
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Run analyzers with Promise.allSettled to handle individual failures
|
|
606
|
+
if (analyzerList.length > 0) {
|
|
607
|
+
const results = await Promise.allSettled(analyzerList.map(fn => fn()));
|
|
608
|
+
|
|
609
|
+
for (const result of results) {
|
|
610
|
+
if (result.status === "fulfilled" && Array.isArray(result.value)) {
|
|
611
|
+
allFindings.push(...result.value);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Add reality findings if available
|
|
617
|
+
if (this.evidence.reality) {
|
|
618
|
+
try {
|
|
619
|
+
const { findingsFromReality } = require("./reality-findings");
|
|
620
|
+
if (typeof findingsFromReality === "function") {
|
|
621
|
+
const realityFindings = findingsFromReality(this.repoRoot);
|
|
622
|
+
if (Array.isArray(realityFindings)) {
|
|
623
|
+
allFindings.push(...realityFindings);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
} catch {
|
|
627
|
+
// Reality findings module not available - not an error
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Deduplicate, validate, and store
|
|
632
|
+
this.findings = this.deduplicateFindings(allFindings)
|
|
633
|
+
.filter(f => f && typeof f === "object")
|
|
634
|
+
.slice(0, 1000); // Limit total findings
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Deduplicate findings by fingerprint
|
|
639
|
+
*/
|
|
640
|
+
deduplicateFindings(findings) {
|
|
641
|
+
const seen = new Set();
|
|
642
|
+
const deduped = [];
|
|
643
|
+
|
|
644
|
+
for (const f of findings) {
|
|
645
|
+
const key = f.fingerprint || `${f.category}:${f.title}:${f.evidence?.[0]?.file}`;
|
|
646
|
+
if (!seen.has(key)) {
|
|
647
|
+
seen.add(key);
|
|
648
|
+
deduped.push(f);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
return deduped;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Compute final verdict from all evidence
|
|
657
|
+
*/
|
|
658
|
+
computeVerdict() {
|
|
659
|
+
const { blockOn, warnOn, strict } = this.config;
|
|
660
|
+
|
|
661
|
+
// Count findings by severity
|
|
662
|
+
const blockers = this.findings.filter(f => f.severity === "BLOCK");
|
|
663
|
+
const warnings = this.findings.filter(f => f.severity === "WARN");
|
|
664
|
+
|
|
665
|
+
// Check block conditions
|
|
666
|
+
if (blockOn.auditBlockers && blockers.length > 0) {
|
|
667
|
+
this.blockReasons.push(...blockers.map(b => b.title || b.message));
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (blockOn.realityFailures && this.evidence.reality?.failures?.length > 0) {
|
|
671
|
+
this.blockReasons.push(...this.evidence.reality.failures.map(f => `Reality: ${f}`));
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
if (blockOn.shieldViolations && this.evidence.shield?.violations?.length > 0) {
|
|
675
|
+
this.blockReasons.push(...this.evidence.shield.violations.map(v => `Shield: ${v}`));
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Check repo state
|
|
679
|
+
const { generateRepoFingerprint } = getShipManifest();
|
|
680
|
+
const repoFP = generateRepoFingerprint(this.repoRoot);
|
|
681
|
+
|
|
682
|
+
if (blockOn.dirtyWorkingTree && repoFP.isDirty) {
|
|
683
|
+
this.blockReasons.push("Working tree has uncommitted changes");
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// Check warn conditions
|
|
687
|
+
if (warnOn.auditWarnings && warnings.length > 0) {
|
|
688
|
+
this.warnReasons.push(...warnings.slice(0, 5).map(w => w.title || w.message));
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Apply strict mode
|
|
692
|
+
if (strict && this.warnReasons.length > 0) {
|
|
693
|
+
this.blockReasons.push("Strict mode: warnings treated as blockers");
|
|
694
|
+
this.blockReasons.push(...this.warnReasons);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Determine verdict
|
|
698
|
+
if (this.blockReasons.length > 0) {
|
|
699
|
+
return "BLOCK";
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (this.warnReasons.length > 0) {
|
|
703
|
+
return "WARN";
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
this.passReasons.push("All checks passed");
|
|
707
|
+
return "SHIP";
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Calculate score based on findings and bonuses
|
|
712
|
+
*/
|
|
713
|
+
calculateScore(verdict) {
|
|
714
|
+
const { scoring } = this.config;
|
|
715
|
+
let score = scoring.baseScore;
|
|
716
|
+
|
|
717
|
+
// Apply penalties
|
|
718
|
+
for (const f of this.findings) {
|
|
719
|
+
switch (f.severity) {
|
|
720
|
+
case "BLOCK":
|
|
721
|
+
score -= scoring.blockerPenalty;
|
|
722
|
+
break;
|
|
723
|
+
case "WARN":
|
|
724
|
+
score -= scoring.warningPenalty;
|
|
725
|
+
break;
|
|
726
|
+
case "INFO":
|
|
727
|
+
score -= scoring.infoPenalty;
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// Apply bonuses
|
|
733
|
+
if (this.evidence.reality && !this.evidence.reality.failures?.length) {
|
|
734
|
+
score += scoring.realityBonus;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
if (this.evidence.shield?.mode === "enforce") {
|
|
738
|
+
score += scoring.shieldBonus;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Clamp to 0-100
|
|
742
|
+
return Math.max(0, Math.min(100, score));
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
747
|
+
// QUICK GATE FUNCTION
|
|
748
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Quick gate evaluation (one-liner API)
|
|
752
|
+
*
|
|
753
|
+
* @param {Object} options - Gate options
|
|
754
|
+
* @returns {Object} Gate result
|
|
755
|
+
*/
|
|
756
|
+
async function evaluateShipGate(options = {}) {
|
|
757
|
+
const {
|
|
758
|
+
repoRoot = process.cwd(),
|
|
759
|
+
strict = false,
|
|
760
|
+
...rest
|
|
761
|
+
} = options;
|
|
762
|
+
|
|
763
|
+
const gate = new ShipGate(repoRoot, { strict });
|
|
764
|
+
return gate.evaluate(rest);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
768
|
+
// CACHING SYSTEM
|
|
769
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Check if we can use a cached verdict.
|
|
773
|
+
* Cache is valid if repo fingerprint hasn't changed.
|
|
774
|
+
*/
|
|
775
|
+
function checkVerdictCache(repoRoot) {
|
|
776
|
+
const { loadShipManifest, generateRepoFingerprint } = getShipManifest();
|
|
777
|
+
|
|
778
|
+
const cached = loadShipManifest(repoRoot);
|
|
779
|
+
if (!cached) {
|
|
780
|
+
return { valid: false, reason: "No cached manifest" };
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
const currentFP = generateRepoFingerprint(repoRoot);
|
|
784
|
+
|
|
785
|
+
if (cached.repo.fingerprint !== currentFP.fingerprint) {
|
|
786
|
+
return {
|
|
787
|
+
valid: false,
|
|
788
|
+
reason: "Repo state changed",
|
|
789
|
+
cached: cached.repo.fingerprint,
|
|
790
|
+
current: currentFP.fingerprint,
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Check age (default max: 1 hour)
|
|
795
|
+
const age = Date.now() - new Date(cached.meta.generatedAt).getTime();
|
|
796
|
+
if (age > 3600000) {
|
|
797
|
+
return {
|
|
798
|
+
valid: false,
|
|
799
|
+
reason: "Cache expired (>1 hour old)",
|
|
800
|
+
age,
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return {
|
|
805
|
+
valid: true,
|
|
806
|
+
manifest: cached,
|
|
807
|
+
age,
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
812
|
+
// EXPORTS
|
|
813
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
814
|
+
|
|
815
|
+
module.exports = {
|
|
816
|
+
// Main class
|
|
817
|
+
ShipGate,
|
|
818
|
+
|
|
819
|
+
// Quick function
|
|
820
|
+
evaluateShipGate,
|
|
821
|
+
|
|
822
|
+
// Caching
|
|
823
|
+
checkVerdictCache,
|
|
824
|
+
|
|
825
|
+
// Configuration
|
|
826
|
+
DEFAULT_CONFIG,
|
|
827
|
+
|
|
828
|
+
// Error classes
|
|
829
|
+
GateError,
|
|
830
|
+
ConfigurationError,
|
|
831
|
+
EvaluationError,
|
|
832
|
+
};
|