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,753 @@
|
|
|
1
|
+
// bin/runners/lib/missions/checkpoint.js
|
|
2
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
3
|
+
// MISSION CHECKPOINTS - Named checkpoints for instant rollback
|
|
4
|
+
// Each mission gets a checkpoint before execution for safe, reversible operations
|
|
5
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const {
|
|
12
|
+
CheckpointError,
|
|
13
|
+
RollbackError,
|
|
14
|
+
ValidationError,
|
|
15
|
+
isValidMissionId,
|
|
16
|
+
isValidCheckpointId,
|
|
17
|
+
isValidFilePath,
|
|
18
|
+
safeReadFile,
|
|
19
|
+
safeWriteFile,
|
|
20
|
+
safeReadJson,
|
|
21
|
+
safeWriteJson,
|
|
22
|
+
getAuditTrail,
|
|
23
|
+
} = require('./hardening');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Checkpoint directory within .vibecheck
|
|
27
|
+
*/
|
|
28
|
+
const CHECKPOINT_DIR = '.vibecheck/checkpoints/missions';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Mission history file
|
|
32
|
+
*/
|
|
33
|
+
const HISTORY_FILE = '.vibecheck/checkpoints/mission-history.json';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Generate a checkpoint ID for a mission
|
|
37
|
+
* @param {string} missionId - Mission ID
|
|
38
|
+
* @returns {string} Checkpoint ID
|
|
39
|
+
*/
|
|
40
|
+
function generateCheckpointId(missionId) {
|
|
41
|
+
const timestamp = Date.now().toString(36);
|
|
42
|
+
return `cp_${missionId}_${timestamp}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Ensure directory exists
|
|
47
|
+
* @param {string} dir - Directory path
|
|
48
|
+
*/
|
|
49
|
+
function ensureDir(dir) {
|
|
50
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get git status for checkpoint metadata
|
|
55
|
+
* @param {string} repoRoot - Repository root
|
|
56
|
+
* @returns {object} Git status info
|
|
57
|
+
*/
|
|
58
|
+
function getGitStatus(repoRoot) {
|
|
59
|
+
try {
|
|
60
|
+
const status = execSync('git status --porcelain', {
|
|
61
|
+
cwd: repoRoot,
|
|
62
|
+
encoding: 'utf8',
|
|
63
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
64
|
+
}).trim();
|
|
65
|
+
|
|
66
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
67
|
+
cwd: repoRoot,
|
|
68
|
+
encoding: 'utf8',
|
|
69
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
70
|
+
}).trim();
|
|
71
|
+
|
|
72
|
+
const commit = execSync('git rev-parse HEAD', {
|
|
73
|
+
cwd: repoRoot,
|
|
74
|
+
encoding: 'utf8',
|
|
75
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
76
|
+
}).trim();
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
branch,
|
|
80
|
+
commit,
|
|
81
|
+
dirty: status.length > 0,
|
|
82
|
+
changes: status.split('\n').filter(Boolean).length,
|
|
83
|
+
};
|
|
84
|
+
} catch (e) {
|
|
85
|
+
return { branch: 'unknown', commit: 'unknown', dirty: false, changes: 0 };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create a hash of file contents
|
|
91
|
+
* @param {string} content - File content
|
|
92
|
+
* @returns {string} SHA256 hash
|
|
93
|
+
*/
|
|
94
|
+
function hashContent(content) {
|
|
95
|
+
return crypto.createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Create a checkpoint before a mission
|
|
100
|
+
* @param {string} repoRoot - Repository root
|
|
101
|
+
* @param {object} mission - Mission object
|
|
102
|
+
* @param {string[]} files - Files to snapshot
|
|
103
|
+
* @returns {object} Checkpoint object
|
|
104
|
+
* @throws {CheckpointError} If checkpoint creation fails
|
|
105
|
+
*/
|
|
106
|
+
function createCheckpoint(repoRoot, mission, files) {
|
|
107
|
+
const audit = getAuditTrail();
|
|
108
|
+
|
|
109
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
110
|
+
// INPUT VALIDATION
|
|
111
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
112
|
+
|
|
113
|
+
if (!repoRoot || typeof repoRoot !== 'string') {
|
|
114
|
+
throw new ValidationError('repoRoot is required and must be a string', 'repoRoot', repoRoot);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!fs.existsSync(repoRoot)) {
|
|
118
|
+
throw new ValidationError('repoRoot does not exist', 'repoRoot', repoRoot);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!mission || typeof mission !== 'object') {
|
|
122
|
+
throw new ValidationError('mission is required and must be an object', 'mission', mission);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!mission.id) {
|
|
126
|
+
throw new ValidationError('mission.id is required', 'mission.id', null);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!Array.isArray(files)) {
|
|
130
|
+
throw new ValidationError('files must be an array', 'files', files);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate and sanitize file paths
|
|
134
|
+
const validFiles = files.filter(f => {
|
|
135
|
+
if (!isValidFilePath(f)) {
|
|
136
|
+
audit.warn('checkpoint_invalid_file_skipped', { file: f, missionId: mission.id });
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
143
|
+
// CHECKPOINT CREATION
|
|
144
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
145
|
+
|
|
146
|
+
const checkpointId = generateCheckpointId(mission.id);
|
|
147
|
+
const checkpointDir = path.join(repoRoot, CHECKPOINT_DIR, checkpointId);
|
|
148
|
+
|
|
149
|
+
audit.info('checkpoint_create_start', { checkpointId, missionId: mission.id, fileCount: validFiles.length });
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
ensureDir(checkpointDir);
|
|
153
|
+
} catch (e) {
|
|
154
|
+
throw new CheckpointError(`Failed to create checkpoint directory: ${e.message}`, 'create', checkpointId, { dir: checkpointDir });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Snapshot files
|
|
158
|
+
const snapshots = [];
|
|
159
|
+
const errors = [];
|
|
160
|
+
|
|
161
|
+
for (const relPath of validFiles) {
|
|
162
|
+
const absPath = path.join(repoRoot, relPath);
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
if (fs.existsSync(absPath)) {
|
|
166
|
+
const stats = fs.statSync(absPath);
|
|
167
|
+
|
|
168
|
+
// Skip directories
|
|
169
|
+
if (stats.isDirectory()) {
|
|
170
|
+
audit.warn('checkpoint_skip_directory', { path: relPath });
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Skip files that are too large (5MB max for checkpoints)
|
|
175
|
+
const MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
176
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
177
|
+
audit.warn('checkpoint_skip_large_file', { path: relPath, size: stats.size });
|
|
178
|
+
snapshots.push({
|
|
179
|
+
path: relPath,
|
|
180
|
+
existed: true,
|
|
181
|
+
hash: null,
|
|
182
|
+
size: stats.size,
|
|
183
|
+
skipped: true,
|
|
184
|
+
reason: 'File too large',
|
|
185
|
+
});
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const content = fs.readFileSync(absPath, 'utf8');
|
|
190
|
+
const hash = hashContent(content);
|
|
191
|
+
|
|
192
|
+
// Save snapshot
|
|
193
|
+
const snapshotPath = path.join(checkpointDir, relPath);
|
|
194
|
+
ensureDir(path.dirname(snapshotPath));
|
|
195
|
+
fs.writeFileSync(snapshotPath, content, 'utf8');
|
|
196
|
+
|
|
197
|
+
snapshots.push({
|
|
198
|
+
path: relPath,
|
|
199
|
+
existed: true,
|
|
200
|
+
hash,
|
|
201
|
+
size: content.length,
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
// File doesn't exist - record this so we can delete it on rollback
|
|
205
|
+
snapshots.push({
|
|
206
|
+
path: relPath,
|
|
207
|
+
existed: false,
|
|
208
|
+
hash: null,
|
|
209
|
+
size: 0,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
} catch (e) {
|
|
213
|
+
errors.push({ path: relPath, error: e.message });
|
|
214
|
+
audit.error('checkpoint_file_error', { path: relPath, error: e.message });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// If too many errors, fail the checkpoint
|
|
219
|
+
if (errors.length > validFiles.length / 2) {
|
|
220
|
+
// Clean up partial checkpoint
|
|
221
|
+
try {
|
|
222
|
+
fs.rmSync(checkpointDir, { recursive: true, force: true });
|
|
223
|
+
} catch (e) {
|
|
224
|
+
// Ignore cleanup errors
|
|
225
|
+
}
|
|
226
|
+
throw new CheckpointError(`Too many file errors: ${errors.length}/${validFiles.length} failed`, 'create', checkpointId, { errors });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Create checkpoint metadata
|
|
230
|
+
const checkpoint = {
|
|
231
|
+
id: checkpointId,
|
|
232
|
+
missionId: mission.id,
|
|
233
|
+
missionType: mission.type,
|
|
234
|
+
createdAt: new Date().toISOString(),
|
|
235
|
+
gitStatus: getGitStatus(repoRoot),
|
|
236
|
+
snapshots,
|
|
237
|
+
files: validFiles.length,
|
|
238
|
+
successfulSnapshots: snapshots.filter(s => !s.skipped).length,
|
|
239
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// Save checkpoint metadata
|
|
243
|
+
const metadataPath = path.join(checkpointDir, '_checkpoint.json');
|
|
244
|
+
const writeResult = safeWriteJson(metadataPath, checkpoint);
|
|
245
|
+
|
|
246
|
+
if (!writeResult.ok) {
|
|
247
|
+
throw new CheckpointError(`Failed to write checkpoint metadata: ${writeResult.error}`, 'create', checkpointId);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Update mission history
|
|
251
|
+
addToHistory(repoRoot, {
|
|
252
|
+
checkpointId,
|
|
253
|
+
missionId: mission.id,
|
|
254
|
+
missionType: mission.type,
|
|
255
|
+
missionTitle: mission.objective?.title || mission.title,
|
|
256
|
+
createdAt: checkpoint.createdAt,
|
|
257
|
+
status: 'created',
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
audit.info('checkpoint_create_success', {
|
|
261
|
+
checkpointId,
|
|
262
|
+
missionId: mission.id,
|
|
263
|
+
snapshotCount: snapshots.length,
|
|
264
|
+
errorCount: errors.length,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return checkpoint;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Rollback to a checkpoint
|
|
272
|
+
* @param {string} repoRoot - Repository root
|
|
273
|
+
* @param {string} checkpointId - Checkpoint ID
|
|
274
|
+
* @returns {object} Rollback result
|
|
275
|
+
*/
|
|
276
|
+
function rollbackToCheckpoint(repoRoot, checkpointId) {
|
|
277
|
+
const audit = getAuditTrail();
|
|
278
|
+
|
|
279
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
280
|
+
// INPUT VALIDATION
|
|
281
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
282
|
+
|
|
283
|
+
if (!repoRoot || typeof repoRoot !== 'string') {
|
|
284
|
+
return {
|
|
285
|
+
ok: false,
|
|
286
|
+
error: 'repoRoot is required',
|
|
287
|
+
restored: [],
|
|
288
|
+
deleted: [],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (!checkpointId || typeof checkpointId !== 'string') {
|
|
293
|
+
return {
|
|
294
|
+
ok: false,
|
|
295
|
+
error: 'checkpointId is required',
|
|
296
|
+
restored: [],
|
|
297
|
+
deleted: [],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
302
|
+
// CHECKPOINT VALIDATION
|
|
303
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
304
|
+
|
|
305
|
+
const checkpointDir = path.join(repoRoot, CHECKPOINT_DIR, checkpointId);
|
|
306
|
+
const metadataPath = path.join(checkpointDir, '_checkpoint.json');
|
|
307
|
+
|
|
308
|
+
if (!fs.existsSync(checkpointDir)) {
|
|
309
|
+
audit.warn('rollback_checkpoint_not_found', { checkpointId });
|
|
310
|
+
return {
|
|
311
|
+
ok: false,
|
|
312
|
+
error: `Checkpoint not found: ${checkpointId}`,
|
|
313
|
+
restored: [],
|
|
314
|
+
deleted: [],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const metadataResult = safeReadJson(metadataPath);
|
|
319
|
+
if (!metadataResult.ok) {
|
|
320
|
+
audit.error('rollback_metadata_read_failed', { checkpointId, error: metadataResult.error });
|
|
321
|
+
return {
|
|
322
|
+
ok: false,
|
|
323
|
+
error: `Checkpoint metadata corrupted: ${metadataResult.error}`,
|
|
324
|
+
restored: [],
|
|
325
|
+
deleted: [],
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const checkpoint = metadataResult.data;
|
|
330
|
+
|
|
331
|
+
// Validate checkpoint structure
|
|
332
|
+
if (!checkpoint.snapshots || !Array.isArray(checkpoint.snapshots)) {
|
|
333
|
+
audit.error('rollback_invalid_checkpoint', { checkpointId });
|
|
334
|
+
return {
|
|
335
|
+
ok: false,
|
|
336
|
+
error: 'Checkpoint has invalid structure (missing snapshots)',
|
|
337
|
+
restored: [],
|
|
338
|
+
deleted: [],
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
audit.info('rollback_start', {
|
|
343
|
+
checkpointId,
|
|
344
|
+
missionId: checkpoint.missionId,
|
|
345
|
+
snapshotCount: checkpoint.snapshots.length,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
349
|
+
// ROLLBACK EXECUTION
|
|
350
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
351
|
+
|
|
352
|
+
const restored = [];
|
|
353
|
+
const deleted = [];
|
|
354
|
+
const errors = [];
|
|
355
|
+
const skipped = [];
|
|
356
|
+
|
|
357
|
+
for (const snapshot of checkpoint.snapshots) {
|
|
358
|
+
// Skip invalid paths
|
|
359
|
+
if (!snapshot.path || !isValidFilePath(snapshot.path)) {
|
|
360
|
+
skipped.push({ path: snapshot.path, reason: 'Invalid path' });
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Skip snapshots that were skipped during creation
|
|
365
|
+
if (snapshot.skipped) {
|
|
366
|
+
skipped.push({ path: snapshot.path, reason: snapshot.reason || 'Skipped during checkpoint' });
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const absPath = path.join(repoRoot, snapshot.path);
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
if (snapshot.existed) {
|
|
374
|
+
// Restore file from snapshot
|
|
375
|
+
const snapshotPath = path.join(checkpointDir, snapshot.path);
|
|
376
|
+
if (fs.existsSync(snapshotPath)) {
|
|
377
|
+
ensureDir(path.dirname(absPath));
|
|
378
|
+
fs.copyFileSync(snapshotPath, absPath);
|
|
379
|
+
|
|
380
|
+
// Verify restoration
|
|
381
|
+
const restoredContent = fs.readFileSync(absPath, 'utf8');
|
|
382
|
+
const restoredHash = hashContent(restoredContent);
|
|
383
|
+
|
|
384
|
+
if (snapshot.hash && restoredHash !== snapshot.hash) {
|
|
385
|
+
audit.warn('rollback_hash_mismatch', { path: snapshot.path });
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
restored.push(snapshot.path);
|
|
389
|
+
} else {
|
|
390
|
+
errors.push(`Snapshot missing: ${snapshot.path}`);
|
|
391
|
+
audit.error('rollback_snapshot_missing', { path: snapshot.path, checkpointId });
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
// File didn't exist before - delete it if it exists now
|
|
395
|
+
if (fs.existsSync(absPath)) {
|
|
396
|
+
fs.rmSync(absPath, { force: true });
|
|
397
|
+
deleted.push(snapshot.path);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
} catch (e) {
|
|
401
|
+
errors.push(`Failed to restore ${snapshot.path}: ${e.message}`);
|
|
402
|
+
audit.error('rollback_file_error', { path: snapshot.path, error: e.message });
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Update history
|
|
407
|
+
updateHistoryStatus(repoRoot, checkpointId, 'rolled_back');
|
|
408
|
+
|
|
409
|
+
const success = errors.length === 0;
|
|
410
|
+
|
|
411
|
+
audit.info('rollback_complete', {
|
|
412
|
+
checkpointId,
|
|
413
|
+
success,
|
|
414
|
+
restored: restored.length,
|
|
415
|
+
deleted: deleted.length,
|
|
416
|
+
errors: errors.length,
|
|
417
|
+
skipped: skipped.length,
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
ok: success,
|
|
422
|
+
checkpointId,
|
|
423
|
+
missionId: checkpoint.missionId,
|
|
424
|
+
restored,
|
|
425
|
+
deleted,
|
|
426
|
+
skipped,
|
|
427
|
+
errors,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Rollback a mission by its ID
|
|
433
|
+
* Finds the most recent checkpoint for the mission and rolls back
|
|
434
|
+
* @param {string} repoRoot - Repository root
|
|
435
|
+
* @param {string} missionId - Mission ID
|
|
436
|
+
* @returns {object} Rollback result
|
|
437
|
+
*/
|
|
438
|
+
function rollbackMission(repoRoot, missionId) {
|
|
439
|
+
const audit = getAuditTrail();
|
|
440
|
+
|
|
441
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
442
|
+
// INPUT VALIDATION
|
|
443
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
444
|
+
|
|
445
|
+
if (!repoRoot || typeof repoRoot !== 'string') {
|
|
446
|
+
return {
|
|
447
|
+
ok: false,
|
|
448
|
+
error: 'repoRoot is required',
|
|
449
|
+
restored: [],
|
|
450
|
+
deleted: [],
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (!missionId || typeof missionId !== 'string') {
|
|
455
|
+
return {
|
|
456
|
+
ok: false,
|
|
457
|
+
error: 'missionId is required',
|
|
458
|
+
restored: [],
|
|
459
|
+
deleted: [],
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
audit.info('rollback_mission_start', { missionId });
|
|
464
|
+
|
|
465
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
466
|
+
// FIND CHECKPOINT
|
|
467
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
468
|
+
|
|
469
|
+
const history = loadHistory(repoRoot);
|
|
470
|
+
|
|
471
|
+
// Find most recent checkpoint for this mission
|
|
472
|
+
const missionCheckpoints = history
|
|
473
|
+
.filter(h => h.missionId === missionId && h.status !== 'rolled_back')
|
|
474
|
+
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
|
475
|
+
|
|
476
|
+
if (missionCheckpoints.length === 0) {
|
|
477
|
+
audit.warn('rollback_mission_no_checkpoint', { missionId });
|
|
478
|
+
return {
|
|
479
|
+
ok: false,
|
|
480
|
+
error: `No checkpoint found for mission: ${missionId}`,
|
|
481
|
+
restored: [],
|
|
482
|
+
deleted: [],
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const checkpointId = missionCheckpoints[0].checkpointId;
|
|
487
|
+
audit.debug('rollback_mission_using_checkpoint', { missionId, checkpointId });
|
|
488
|
+
|
|
489
|
+
return rollbackToCheckpoint(repoRoot, checkpointId);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Delete a checkpoint
|
|
494
|
+
* @param {string} repoRoot - Repository root
|
|
495
|
+
* @param {string} checkpointId - Checkpoint ID
|
|
496
|
+
* @returns {object} Delete result
|
|
497
|
+
*/
|
|
498
|
+
function deleteCheckpoint(repoRoot, checkpointId) {
|
|
499
|
+
const checkpointDir = path.join(repoRoot, CHECKPOINT_DIR, checkpointId);
|
|
500
|
+
|
|
501
|
+
if (!fs.existsSync(checkpointDir)) {
|
|
502
|
+
return { ok: false, error: `Checkpoint not found: ${checkpointId}` };
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
try {
|
|
506
|
+
fs.rmSync(checkpointDir, { recursive: true, force: true });
|
|
507
|
+
updateHistoryStatus(repoRoot, checkpointId, 'deleted');
|
|
508
|
+
return { ok: true, checkpointId };
|
|
509
|
+
} catch (e) {
|
|
510
|
+
return { ok: false, error: e.message };
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* List all checkpoints
|
|
516
|
+
* @param {string} repoRoot - Repository root
|
|
517
|
+
* @returns {object[]} Array of checkpoint metadata
|
|
518
|
+
*/
|
|
519
|
+
function listCheckpoints(repoRoot) {
|
|
520
|
+
const baseDir = path.join(repoRoot, CHECKPOINT_DIR);
|
|
521
|
+
|
|
522
|
+
if (!fs.existsSync(baseDir)) {
|
|
523
|
+
return [];
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const checkpoints = [];
|
|
527
|
+
const dirs = fs.readdirSync(baseDir, { withFileTypes: true });
|
|
528
|
+
|
|
529
|
+
for (const dir of dirs) {
|
|
530
|
+
if (!dir.isDirectory() || dir.name.startsWith('.')) continue;
|
|
531
|
+
|
|
532
|
+
const metadataPath = path.join(baseDir, dir.name, '_checkpoint.json');
|
|
533
|
+
if (fs.existsSync(metadataPath)) {
|
|
534
|
+
try {
|
|
535
|
+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
536
|
+
checkpoints.push(metadata);
|
|
537
|
+
} catch (e) {
|
|
538
|
+
// Skip invalid checkpoints
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Sort by creation date, newest first
|
|
544
|
+
return checkpoints.sort((a, b) =>
|
|
545
|
+
new Date(b.createdAt) - new Date(a.createdAt)
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Get checkpoint by ID
|
|
551
|
+
* @param {string} repoRoot - Repository root
|
|
552
|
+
* @param {string} checkpointId - Checkpoint ID
|
|
553
|
+
* @returns {object|null} Checkpoint metadata or null
|
|
554
|
+
*/
|
|
555
|
+
function getCheckpoint(repoRoot, checkpointId) {
|
|
556
|
+
const metadataPath = path.join(repoRoot, CHECKPOINT_DIR, checkpointId, '_checkpoint.json');
|
|
557
|
+
|
|
558
|
+
if (!fs.existsSync(metadataPath)) {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Get checkpoints for a specific mission
|
|
567
|
+
* @param {string} repoRoot - Repository root
|
|
568
|
+
* @param {string} missionId - Mission ID
|
|
569
|
+
* @returns {object[]} Array of checkpoints for the mission
|
|
570
|
+
*/
|
|
571
|
+
function getCheckpointsForMission(repoRoot, missionId) {
|
|
572
|
+
return listCheckpoints(repoRoot).filter(cp => cp.missionId === missionId);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Load mission history
|
|
577
|
+
* @param {string} repoRoot - Repository root
|
|
578
|
+
* @returns {object[]} History entries
|
|
579
|
+
*/
|
|
580
|
+
function loadHistory(repoRoot) {
|
|
581
|
+
const historyPath = path.join(repoRoot, HISTORY_FILE);
|
|
582
|
+
|
|
583
|
+
if (!fs.existsSync(historyPath)) {
|
|
584
|
+
return [];
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
try {
|
|
588
|
+
return JSON.parse(fs.readFileSync(historyPath, 'utf8'));
|
|
589
|
+
} catch (e) {
|
|
590
|
+
return [];
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Add entry to mission history
|
|
596
|
+
* @param {string} repoRoot - Repository root
|
|
597
|
+
* @param {object} entry - History entry
|
|
598
|
+
*/
|
|
599
|
+
function addToHistory(repoRoot, entry) {
|
|
600
|
+
const history = loadHistory(repoRoot);
|
|
601
|
+
history.push(entry);
|
|
602
|
+
|
|
603
|
+
// Keep only last 100 entries
|
|
604
|
+
const trimmed = history.slice(-100);
|
|
605
|
+
|
|
606
|
+
const historyPath = path.join(repoRoot, HISTORY_FILE);
|
|
607
|
+
ensureDir(path.dirname(historyPath));
|
|
608
|
+
fs.writeFileSync(historyPath, JSON.stringify(trimmed, null, 2), 'utf8');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Update history entry status
|
|
613
|
+
* @param {string} repoRoot - Repository root
|
|
614
|
+
* @param {string} checkpointId - Checkpoint ID
|
|
615
|
+
* @param {string} status - New status
|
|
616
|
+
*/
|
|
617
|
+
function updateHistoryStatus(repoRoot, checkpointId, status) {
|
|
618
|
+
const history = loadHistory(repoRoot);
|
|
619
|
+
|
|
620
|
+
for (const entry of history) {
|
|
621
|
+
if (entry.checkpointId === checkpointId) {
|
|
622
|
+
entry.status = status;
|
|
623
|
+
entry.updatedAt = new Date().toISOString();
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const historyPath = path.join(repoRoot, HISTORY_FILE);
|
|
628
|
+
fs.writeFileSync(historyPath, JSON.stringify(history, null, 2), 'utf8');
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Get mission history
|
|
633
|
+
* @param {string} repoRoot - Repository root
|
|
634
|
+
* @param {object} options - Filter options
|
|
635
|
+
* @returns {object[]} Filtered history entries
|
|
636
|
+
*/
|
|
637
|
+
function getMissionHistory(repoRoot, options = {}) {
|
|
638
|
+
const { missionId, missionType, status, limit = 50 } = options;
|
|
639
|
+
let history = loadHistory(repoRoot);
|
|
640
|
+
|
|
641
|
+
if (missionId) {
|
|
642
|
+
history = history.filter(h => h.missionId === missionId);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (missionType) {
|
|
646
|
+
history = history.filter(h => h.missionType === missionType);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (status) {
|
|
650
|
+
history = history.filter(h => h.status === status);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Sort by creation date, newest first
|
|
654
|
+
history.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
|
655
|
+
|
|
656
|
+
return history.slice(0, limit);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Clean up old checkpoints
|
|
661
|
+
* @param {string} repoRoot - Repository root
|
|
662
|
+
* @param {object} options - Cleanup options
|
|
663
|
+
* @returns {object} Cleanup result
|
|
664
|
+
*/
|
|
665
|
+
function cleanupOldCheckpoints(repoRoot, options = {}) {
|
|
666
|
+
const { maxAge = 7 * 24 * 60 * 60 * 1000, maxCount = 50 } = options; // 7 days default
|
|
667
|
+
const checkpoints = listCheckpoints(repoRoot);
|
|
668
|
+
const now = Date.now();
|
|
669
|
+
const deleted = [];
|
|
670
|
+
|
|
671
|
+
// Delete checkpoints older than maxAge
|
|
672
|
+
for (const cp of checkpoints) {
|
|
673
|
+
const age = now - new Date(cp.createdAt).getTime();
|
|
674
|
+
if (age > maxAge) {
|
|
675
|
+
const result = deleteCheckpoint(repoRoot, cp.id);
|
|
676
|
+
if (result.ok) deleted.push(cp.id);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// If still over maxCount, delete oldest
|
|
681
|
+
const remaining = listCheckpoints(repoRoot);
|
|
682
|
+
if (remaining.length > maxCount) {
|
|
683
|
+
const toDelete = remaining.slice(maxCount);
|
|
684
|
+
for (const cp of toDelete) {
|
|
685
|
+
const result = deleteCheckpoint(repoRoot, cp.id);
|
|
686
|
+
if (result.ok) deleted.push(cp.id);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
return { deleted, count: deleted.length };
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Mark checkpoint as applied (mission completed successfully)
|
|
695
|
+
* @param {string} repoRoot - Repository root
|
|
696
|
+
* @param {string} checkpointId - Checkpoint ID
|
|
697
|
+
*/
|
|
698
|
+
function markCheckpointApplied(repoRoot, checkpointId) {
|
|
699
|
+
updateHistoryStatus(repoRoot, checkpointId, 'applied');
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Mark checkpoint as failed
|
|
704
|
+
* @param {string} repoRoot - Repository root
|
|
705
|
+
* @param {string} checkpointId - Checkpoint ID
|
|
706
|
+
* @param {string} reason - Failure reason
|
|
707
|
+
*/
|
|
708
|
+
function markCheckpointFailed(repoRoot, checkpointId, reason) {
|
|
709
|
+
const history = loadHistory(repoRoot);
|
|
710
|
+
|
|
711
|
+
for (const entry of history) {
|
|
712
|
+
if (entry.checkpointId === checkpointId) {
|
|
713
|
+
entry.status = 'failed';
|
|
714
|
+
entry.failureReason = reason;
|
|
715
|
+
entry.updatedAt = new Date().toISOString();
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const historyPath = path.join(repoRoot, HISTORY_FILE);
|
|
720
|
+
fs.writeFileSync(historyPath, JSON.stringify(history, null, 2), 'utf8');
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
module.exports = {
|
|
724
|
+
// Core functions
|
|
725
|
+
createCheckpoint,
|
|
726
|
+
rollbackToCheckpoint,
|
|
727
|
+
rollbackMission,
|
|
728
|
+
deleteCheckpoint,
|
|
729
|
+
|
|
730
|
+
// Query functions
|
|
731
|
+
listCheckpoints,
|
|
732
|
+
getCheckpoint,
|
|
733
|
+
getCheckpointsForMission,
|
|
734
|
+
|
|
735
|
+
// History functions
|
|
736
|
+
getMissionHistory,
|
|
737
|
+
loadHistory,
|
|
738
|
+
|
|
739
|
+
// Status updates
|
|
740
|
+
markCheckpointApplied,
|
|
741
|
+
markCheckpointFailed,
|
|
742
|
+
|
|
743
|
+
// Maintenance
|
|
744
|
+
cleanupOldCheckpoints,
|
|
745
|
+
|
|
746
|
+
// Utilities
|
|
747
|
+
generateCheckpointId,
|
|
748
|
+
getGitStatus,
|
|
749
|
+
|
|
750
|
+
// Constants
|
|
751
|
+
CHECKPOINT_DIR,
|
|
752
|
+
HISTORY_FILE,
|
|
753
|
+
};
|