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,941 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkpoint System - Time Machine for Fearless Experimentation
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* "Checkpoint is the time machine. Let users experiment fearlessly."
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Delta storage (only modified files, not full repo)
|
|
10
|
+
* - Git-aware (captures branch, commit, dirty state)
|
|
11
|
+
* - Manifest with "why" (auto vs manual, command context)
|
|
12
|
+
* - Storage-aware with auto-cleanup
|
|
13
|
+
* - Fast create/restore operations
|
|
14
|
+
*
|
|
15
|
+
* Storage Model:
|
|
16
|
+
* ~/.vibecheck/checkpoints/
|
|
17
|
+
* ├── index.json # Checkpoint registry
|
|
18
|
+
* └── CP_<timestamp>_<hash>/
|
|
19
|
+
* ├── manifest.json # What, why, when
|
|
20
|
+
* ├── files/ # Changed files (delta storage)
|
|
21
|
+
* │ └── <relative-path>.bak
|
|
22
|
+
* └── metadata.json # Git state, env info
|
|
23
|
+
*
|
|
24
|
+
* @module lib/checkpoint
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const fs = require("fs");
|
|
28
|
+
const path = require("path");
|
|
29
|
+
const os = require("os");
|
|
30
|
+
const crypto = require("crypto");
|
|
31
|
+
const { execSync } = require("child_process");
|
|
32
|
+
|
|
33
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
34
|
+
// CONSTANTS
|
|
35
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
|
+
|
|
37
|
+
const CHECKPOINT_DIR = path.join(os.homedir(), ".vibecheck", "checkpoints");
|
|
38
|
+
const INDEX_FILE = "index.json";
|
|
39
|
+
const MANIFEST_FILE = "manifest.json";
|
|
40
|
+
const METADATA_FILE = "metadata.json";
|
|
41
|
+
const FILES_DIR = "files";
|
|
42
|
+
|
|
43
|
+
/** Max checkpoints to keep (default) */
|
|
44
|
+
const DEFAULT_MAX_CHECKPOINTS = 20;
|
|
45
|
+
|
|
46
|
+
/** Max total storage size in bytes (100MB default) */
|
|
47
|
+
const DEFAULT_MAX_STORAGE_BYTES = 100 * 1024 * 1024;
|
|
48
|
+
|
|
49
|
+
/** Checkpoint ID prefix */
|
|
50
|
+
const CHECKPOINT_PREFIX = "CP";
|
|
51
|
+
|
|
52
|
+
/** Auto-checkpoint reasons */
|
|
53
|
+
const AUTO_REASONS = {
|
|
54
|
+
FIX_APPLY: "fix --apply",
|
|
55
|
+
FIX_MISSION: "fix mission",
|
|
56
|
+
POLISH_APPLY: "polish --apply",
|
|
57
|
+
SHIELD_ENFORCE: "shield enforce",
|
|
58
|
+
FORGE_OVERWRITE: "forge overwrite",
|
|
59
|
+
MANUAL: "manual",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
63
|
+
// STORAGE MANAGEMENT
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Ensure checkpoint directory exists.
|
|
68
|
+
*/
|
|
69
|
+
function ensureCheckpointDir() {
|
|
70
|
+
if (!fs.existsSync(CHECKPOINT_DIR)) {
|
|
71
|
+
fs.mkdirSync(CHECKPOINT_DIR, { recursive: true, mode: 0o700 });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get checkpoint index path.
|
|
77
|
+
*/
|
|
78
|
+
function getIndexPath() {
|
|
79
|
+
return path.join(CHECKPOINT_DIR, INDEX_FILE);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Read checkpoint index.
|
|
84
|
+
* @returns {object}
|
|
85
|
+
*/
|
|
86
|
+
function readIndex() {
|
|
87
|
+
ensureCheckpointDir();
|
|
88
|
+
const indexPath = getIndexPath();
|
|
89
|
+
|
|
90
|
+
if (!fs.existsSync(indexPath)) {
|
|
91
|
+
return {
|
|
92
|
+
version: 1,
|
|
93
|
+
checkpoints: [],
|
|
94
|
+
settings: {
|
|
95
|
+
maxCheckpoints: DEFAULT_MAX_CHECKPOINTS,
|
|
96
|
+
maxStorageBytes: DEFAULT_MAX_STORAGE_BYTES,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
return JSON.parse(fs.readFileSync(indexPath, "utf8"));
|
|
103
|
+
} catch {
|
|
104
|
+
return {
|
|
105
|
+
version: 1,
|
|
106
|
+
checkpoints: [],
|
|
107
|
+
settings: {
|
|
108
|
+
maxCheckpoints: DEFAULT_MAX_CHECKPOINTS,
|
|
109
|
+
maxStorageBytes: DEFAULT_MAX_STORAGE_BYTES,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Write checkpoint index.
|
|
117
|
+
* @param {object} index
|
|
118
|
+
*/
|
|
119
|
+
function writeIndex(index) {
|
|
120
|
+
ensureCheckpointDir();
|
|
121
|
+
fs.writeFileSync(getIndexPath(), JSON.stringify(index, null, 2), { mode: 0o600 });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Generate checkpoint ID.
|
|
126
|
+
* @param {string} [tag]
|
|
127
|
+
* @returns {string}
|
|
128
|
+
*/
|
|
129
|
+
function generateCheckpointId(tag) {
|
|
130
|
+
const timestamp = Date.now();
|
|
131
|
+
const hash = crypto.randomBytes(4).toString("hex");
|
|
132
|
+
const base = `${CHECKPOINT_PREFIX}_${timestamp}_${hash}`;
|
|
133
|
+
return tag ? `${base}_${sanitizeTag(tag)}` : base;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Sanitize tag for filesystem.
|
|
138
|
+
* @param {string} tag
|
|
139
|
+
* @returns {string}
|
|
140
|
+
*/
|
|
141
|
+
function sanitizeTag(tag) {
|
|
142
|
+
return tag
|
|
143
|
+
.toLowerCase()
|
|
144
|
+
.replace(/[^a-z0-9-_]/g, "-")
|
|
145
|
+
.replace(/-+/g, "-")
|
|
146
|
+
.slice(0, 32);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get checkpoint directory path.
|
|
151
|
+
* @param {string} checkpointId
|
|
152
|
+
* @returns {string}
|
|
153
|
+
*/
|
|
154
|
+
function getCheckpointPath(checkpointId) {
|
|
155
|
+
return path.join(CHECKPOINT_DIR, checkpointId);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Calculate directory size recursively.
|
|
160
|
+
* @param {string} dir
|
|
161
|
+
* @returns {number}
|
|
162
|
+
*/
|
|
163
|
+
function getDirectorySize(dir) {
|
|
164
|
+
if (!fs.existsSync(dir)) return 0;
|
|
165
|
+
|
|
166
|
+
let size = 0;
|
|
167
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
168
|
+
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
const fullPath = path.join(dir, entry.name);
|
|
171
|
+
if (entry.isDirectory()) {
|
|
172
|
+
size += getDirectorySize(fullPath);
|
|
173
|
+
} else {
|
|
174
|
+
try {
|
|
175
|
+
size += fs.statSync(fullPath).size;
|
|
176
|
+
} catch {
|
|
177
|
+
// Skip inaccessible files
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return size;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get total checkpoint storage size.
|
|
187
|
+
* @returns {number}
|
|
188
|
+
*/
|
|
189
|
+
function getTotalStorageSize() {
|
|
190
|
+
return getDirectorySize(CHECKPOINT_DIR);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
194
|
+
// GIT INTEGRATION
|
|
195
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Get current git state.
|
|
199
|
+
* @param {string} cwd
|
|
200
|
+
* @returns {object|null}
|
|
201
|
+
*/
|
|
202
|
+
function getGitState(cwd) {
|
|
203
|
+
try {
|
|
204
|
+
// Check if in git repo
|
|
205
|
+
execSync("git rev-parse --git-dir", { cwd, stdio: "pipe" });
|
|
206
|
+
|
|
207
|
+
const branch = execSync("git branch --show-current", { cwd, encoding: "utf8" }).trim();
|
|
208
|
+
const commit = execSync("git rev-parse HEAD", { cwd, encoding: "utf8" }).trim().slice(0, 8);
|
|
209
|
+
const dirty = execSync("git status --porcelain", { cwd, encoding: "utf8" }).trim().length > 0;
|
|
210
|
+
|
|
211
|
+
let stashCount = 0;
|
|
212
|
+
try {
|
|
213
|
+
const stashList = execSync("git stash list", { cwd, encoding: "utf8" });
|
|
214
|
+
stashCount = stashList.split("\n").filter(Boolean).length;
|
|
215
|
+
} catch {
|
|
216
|
+
// No stash
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
branch,
|
|
221
|
+
commit,
|
|
222
|
+
dirty,
|
|
223
|
+
stashCount,
|
|
224
|
+
timestamp: new Date().toISOString(),
|
|
225
|
+
};
|
|
226
|
+
} catch {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get list of modified files from git.
|
|
233
|
+
* @param {string} cwd
|
|
234
|
+
* @returns {string[]}
|
|
235
|
+
*/
|
|
236
|
+
function getGitModifiedFiles(cwd) {
|
|
237
|
+
try {
|
|
238
|
+
const output = execSync("git status --porcelain", { cwd, encoding: "utf8" });
|
|
239
|
+
return output
|
|
240
|
+
.split("\n")
|
|
241
|
+
.filter(Boolean)
|
|
242
|
+
.map(line => line.slice(3).trim())
|
|
243
|
+
.filter(f => !f.includes(" -> ")); // Exclude renames for now
|
|
244
|
+
} catch {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
250
|
+
// CHECKPOINT CREATION
|
|
251
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Create a checkpoint.
|
|
255
|
+
*
|
|
256
|
+
* @param {object} options
|
|
257
|
+
* @param {string} options.cwd - Working directory
|
|
258
|
+
* @param {string[]} options.files - Files to checkpoint (relative paths)
|
|
259
|
+
* @param {string} options.reason - Why checkpoint was created
|
|
260
|
+
* @param {string} [options.tag] - Optional tag
|
|
261
|
+
* @param {string} [options.command] - Command that triggered checkpoint
|
|
262
|
+
* @param {object} [options.context] - Additional context
|
|
263
|
+
* @returns {object} - Checkpoint info
|
|
264
|
+
*/
|
|
265
|
+
function createCheckpoint({
|
|
266
|
+
cwd = process.cwd(),
|
|
267
|
+
files = [],
|
|
268
|
+
reason = AUTO_REASONS.MANUAL,
|
|
269
|
+
tag,
|
|
270
|
+
command,
|
|
271
|
+
context = {},
|
|
272
|
+
}) {
|
|
273
|
+
ensureCheckpointDir();
|
|
274
|
+
|
|
275
|
+
const checkpointId = generateCheckpointId(tag);
|
|
276
|
+
const checkpointPath = getCheckpointPath(checkpointId);
|
|
277
|
+
const filesPath = path.join(checkpointPath, FILES_DIR);
|
|
278
|
+
|
|
279
|
+
// Create checkpoint directory
|
|
280
|
+
fs.mkdirSync(filesPath, { recursive: true, mode: 0o700 });
|
|
281
|
+
|
|
282
|
+
// Get git state
|
|
283
|
+
const gitState = getGitState(cwd);
|
|
284
|
+
|
|
285
|
+
// If no files specified, get modified files from git
|
|
286
|
+
let filesToBackup = files.length > 0 ? files : getGitModifiedFiles(cwd);
|
|
287
|
+
|
|
288
|
+
// Filter to only existing files
|
|
289
|
+
filesToBackup = filesToBackup.filter(f => {
|
|
290
|
+
const fullPath = path.isAbsolute(f) ? f : path.join(cwd, f);
|
|
291
|
+
return fs.existsSync(fullPath) && fs.statSync(fullPath).isFile();
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Backup files
|
|
295
|
+
const backedUpFiles = [];
|
|
296
|
+
let totalSize = 0;
|
|
297
|
+
|
|
298
|
+
for (const file of filesToBackup) {
|
|
299
|
+
try {
|
|
300
|
+
const fullPath = path.isAbsolute(file) ? file : path.join(cwd, file);
|
|
301
|
+
const relativePath = path.isAbsolute(file) ? path.relative(cwd, file) : file;
|
|
302
|
+
const backupPath = path.join(filesPath, relativePath.replace(/[/\\]/g, "__"));
|
|
303
|
+
|
|
304
|
+
// Copy file
|
|
305
|
+
fs.copyFileSync(fullPath, backupPath);
|
|
306
|
+
|
|
307
|
+
const stats = fs.statSync(backupPath);
|
|
308
|
+
totalSize += stats.size;
|
|
309
|
+
|
|
310
|
+
backedUpFiles.push({
|
|
311
|
+
original: relativePath,
|
|
312
|
+
backup: path.basename(backupPath),
|
|
313
|
+
size: stats.size,
|
|
314
|
+
hash: hashFile(fullPath),
|
|
315
|
+
});
|
|
316
|
+
} catch (err) {
|
|
317
|
+
// Skip files that can't be backed up
|
|
318
|
+
console.warn(`Warning: Could not backup ${file}: ${err.message}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Create manifest
|
|
323
|
+
const manifest = {
|
|
324
|
+
id: checkpointId,
|
|
325
|
+
version: 1,
|
|
326
|
+
created: new Date().toISOString(),
|
|
327
|
+
reason,
|
|
328
|
+
tag: tag || null,
|
|
329
|
+
command: command || null,
|
|
330
|
+
context,
|
|
331
|
+
files: backedUpFiles,
|
|
332
|
+
totalSize,
|
|
333
|
+
cwd,
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
fs.writeFileSync(
|
|
337
|
+
path.join(checkpointPath, MANIFEST_FILE),
|
|
338
|
+
JSON.stringify(manifest, null, 2),
|
|
339
|
+
{ mode: 0o600 }
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
// Create metadata
|
|
343
|
+
const metadata = {
|
|
344
|
+
git: gitState,
|
|
345
|
+
env: {
|
|
346
|
+
platform: process.platform,
|
|
347
|
+
nodeVersion: process.version,
|
|
348
|
+
user: os.userInfo().username,
|
|
349
|
+
hostname: os.hostname(),
|
|
350
|
+
},
|
|
351
|
+
created: new Date().toISOString(),
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
fs.writeFileSync(
|
|
355
|
+
path.join(checkpointPath, METADATA_FILE),
|
|
356
|
+
JSON.stringify(metadata, null, 2),
|
|
357
|
+
{ mode: 0o600 }
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
// Update index
|
|
361
|
+
const index = readIndex();
|
|
362
|
+
index.checkpoints.unshift({
|
|
363
|
+
id: checkpointId,
|
|
364
|
+
created: manifest.created,
|
|
365
|
+
reason,
|
|
366
|
+
tag: tag || null,
|
|
367
|
+
fileCount: backedUpFiles.length,
|
|
368
|
+
totalSize,
|
|
369
|
+
command: command || null,
|
|
370
|
+
});
|
|
371
|
+
writeIndex(index);
|
|
372
|
+
|
|
373
|
+
// Auto-cleanup if needed
|
|
374
|
+
autoCleanup();
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
id: checkpointId,
|
|
378
|
+
path: checkpointPath,
|
|
379
|
+
files: backedUpFiles.length,
|
|
380
|
+
size: totalSize,
|
|
381
|
+
tag,
|
|
382
|
+
reason,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Hash file contents.
|
|
388
|
+
* @param {string} filePath
|
|
389
|
+
* @returns {string}
|
|
390
|
+
*/
|
|
391
|
+
function hashFile(filePath) {
|
|
392
|
+
try {
|
|
393
|
+
const content = fs.readFileSync(filePath);
|
|
394
|
+
return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
395
|
+
} catch {
|
|
396
|
+
return "unknown";
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
401
|
+
// CHECKPOINT RESTORATION
|
|
402
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Restore a checkpoint.
|
|
406
|
+
*
|
|
407
|
+
* @param {string} checkpointId - Checkpoint ID or "latest"
|
|
408
|
+
* @param {object} options
|
|
409
|
+
* @param {boolean} [options.dryRun] - Preview without restoring
|
|
410
|
+
* @param {string[]} [options.onlyFiles] - Only restore specific files
|
|
411
|
+
* @returns {object} - Restore result
|
|
412
|
+
*/
|
|
413
|
+
function restoreCheckpoint(checkpointId, { dryRun = false, onlyFiles = [] } = {}) {
|
|
414
|
+
const index = readIndex();
|
|
415
|
+
|
|
416
|
+
// Handle "latest"
|
|
417
|
+
if (checkpointId === "latest") {
|
|
418
|
+
if (index.checkpoints.length === 0) {
|
|
419
|
+
throw new Error("No checkpoints available");
|
|
420
|
+
}
|
|
421
|
+
checkpointId = index.checkpoints[0].id;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Handle tag lookup
|
|
425
|
+
if (!checkpointId.startsWith(CHECKPOINT_PREFIX)) {
|
|
426
|
+
const found = index.checkpoints.find(c => c.tag === checkpointId);
|
|
427
|
+
if (found) {
|
|
428
|
+
checkpointId = found.id;
|
|
429
|
+
} else {
|
|
430
|
+
throw new Error(`Checkpoint not found: ${checkpointId}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const checkpointPath = getCheckpointPath(checkpointId);
|
|
435
|
+
|
|
436
|
+
if (!fs.existsSync(checkpointPath)) {
|
|
437
|
+
throw new Error(`Checkpoint not found: ${checkpointId}`);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Read manifest
|
|
441
|
+
const manifestPath = path.join(checkpointPath, MANIFEST_FILE);
|
|
442
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
443
|
+
const filesPath = path.join(checkpointPath, FILES_DIR);
|
|
444
|
+
|
|
445
|
+
const results = {
|
|
446
|
+
id: checkpointId,
|
|
447
|
+
restored: [],
|
|
448
|
+
skipped: [],
|
|
449
|
+
errors: [],
|
|
450
|
+
dryRun,
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
for (const file of manifest.files) {
|
|
454
|
+
// Filter by onlyFiles if specified
|
|
455
|
+
if (onlyFiles.length > 0 && !onlyFiles.includes(file.original)) {
|
|
456
|
+
results.skipped.push({ file: file.original, reason: "not in filter" });
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const backupPath = path.join(filesPath, file.backup);
|
|
461
|
+
const targetPath = path.join(manifest.cwd, file.original);
|
|
462
|
+
|
|
463
|
+
if (!fs.existsSync(backupPath)) {
|
|
464
|
+
results.errors.push({ file: file.original, reason: "backup file missing" });
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (dryRun) {
|
|
469
|
+
results.restored.push({
|
|
470
|
+
file: file.original,
|
|
471
|
+
action: fs.existsSync(targetPath) ? "overwrite" : "create",
|
|
472
|
+
});
|
|
473
|
+
} else {
|
|
474
|
+
try {
|
|
475
|
+
// Ensure directory exists
|
|
476
|
+
const targetDir = path.dirname(targetPath);
|
|
477
|
+
if (!fs.existsSync(targetDir)) {
|
|
478
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Copy file back
|
|
482
|
+
fs.copyFileSync(backupPath, targetPath);
|
|
483
|
+
|
|
484
|
+
results.restored.push({
|
|
485
|
+
file: file.original,
|
|
486
|
+
action: "restored",
|
|
487
|
+
});
|
|
488
|
+
} catch (err) {
|
|
489
|
+
results.errors.push({ file: file.original, reason: err.message });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return results;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
498
|
+
// CHECKPOINT LISTING & INFO
|
|
499
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* List all checkpoints.
|
|
503
|
+
* @param {object} [options]
|
|
504
|
+
* @param {number} [options.limit]
|
|
505
|
+
* @returns {object[]}
|
|
506
|
+
*/
|
|
507
|
+
function listCheckpoints({ limit } = {}) {
|
|
508
|
+
const index = readIndex();
|
|
509
|
+
let checkpoints = index.checkpoints;
|
|
510
|
+
|
|
511
|
+
if (limit && limit > 0) {
|
|
512
|
+
checkpoints = checkpoints.slice(0, limit);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return checkpoints.map(cp => ({
|
|
516
|
+
...cp,
|
|
517
|
+
age: getAge(cp.created),
|
|
518
|
+
sizeFormatted: formatBytes(cp.totalSize),
|
|
519
|
+
}));
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Get checkpoint details.
|
|
524
|
+
* @param {string} checkpointId
|
|
525
|
+
* @returns {object|null}
|
|
526
|
+
*/
|
|
527
|
+
function getCheckpoint(checkpointId) {
|
|
528
|
+
const index = readIndex();
|
|
529
|
+
|
|
530
|
+
// Handle tag lookup
|
|
531
|
+
if (!checkpointId.startsWith(CHECKPOINT_PREFIX)) {
|
|
532
|
+
const found = index.checkpoints.find(c => c.tag === checkpointId);
|
|
533
|
+
if (found) {
|
|
534
|
+
checkpointId = found.id;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const checkpointPath = getCheckpointPath(checkpointId);
|
|
539
|
+
|
|
540
|
+
if (!fs.existsSync(checkpointPath)) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
try {
|
|
545
|
+
const manifest = JSON.parse(
|
|
546
|
+
fs.readFileSync(path.join(checkpointPath, MANIFEST_FILE), "utf8")
|
|
547
|
+
);
|
|
548
|
+
const metadata = JSON.parse(
|
|
549
|
+
fs.readFileSync(path.join(checkpointPath, METADATA_FILE), "utf8")
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
return {
|
|
553
|
+
...manifest,
|
|
554
|
+
metadata,
|
|
555
|
+
age: getAge(manifest.created),
|
|
556
|
+
sizeFormatted: formatBytes(manifest.totalSize),
|
|
557
|
+
};
|
|
558
|
+
} catch {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Get latest checkpoint.
|
|
565
|
+
* @returns {object|null}
|
|
566
|
+
*/
|
|
567
|
+
function getLatestCheckpoint() {
|
|
568
|
+
const index = readIndex();
|
|
569
|
+
if (index.checkpoints.length === 0) return null;
|
|
570
|
+
return getCheckpoint(index.checkpoints[0].id);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
574
|
+
// CHECKPOINT DIFF
|
|
575
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Compare checkpoint with current state.
|
|
579
|
+
* @param {string} checkpointId
|
|
580
|
+
* @returns {object}
|
|
581
|
+
*/
|
|
582
|
+
function diffCheckpoint(checkpointId) {
|
|
583
|
+
const checkpoint = getCheckpoint(checkpointId);
|
|
584
|
+
|
|
585
|
+
if (!checkpoint) {
|
|
586
|
+
throw new Error(`Checkpoint not found: ${checkpointId}`);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const filesPath = path.join(getCheckpointPath(checkpoint.id), FILES_DIR);
|
|
590
|
+
const results = {
|
|
591
|
+
id: checkpoint.id,
|
|
592
|
+
created: checkpoint.created,
|
|
593
|
+
changes: [],
|
|
594
|
+
summary: { modified: 0, deleted: 0, unchanged: 0 },
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
for (const file of checkpoint.files) {
|
|
598
|
+
const backupPath = path.join(filesPath, file.backup);
|
|
599
|
+
const currentPath = path.join(checkpoint.cwd, file.original);
|
|
600
|
+
|
|
601
|
+
if (!fs.existsSync(currentPath)) {
|
|
602
|
+
results.changes.push({
|
|
603
|
+
file: file.original,
|
|
604
|
+
status: "deleted",
|
|
605
|
+
checkpointHash: file.hash,
|
|
606
|
+
currentHash: null,
|
|
607
|
+
});
|
|
608
|
+
results.summary.deleted++;
|
|
609
|
+
} else {
|
|
610
|
+
const currentHash = hashFile(currentPath);
|
|
611
|
+
if (currentHash === file.hash) {
|
|
612
|
+
results.changes.push({
|
|
613
|
+
file: file.original,
|
|
614
|
+
status: "unchanged",
|
|
615
|
+
hash: file.hash,
|
|
616
|
+
});
|
|
617
|
+
results.summary.unchanged++;
|
|
618
|
+
} else {
|
|
619
|
+
results.changes.push({
|
|
620
|
+
file: file.original,
|
|
621
|
+
status: "modified",
|
|
622
|
+
checkpointHash: file.hash,
|
|
623
|
+
currentHash,
|
|
624
|
+
});
|
|
625
|
+
results.summary.modified++;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return results;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
634
|
+
// CHECKPOINT DELETION & CLEANUP
|
|
635
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Delete a checkpoint.
|
|
639
|
+
* @param {string} checkpointId
|
|
640
|
+
* @returns {boolean}
|
|
641
|
+
*/
|
|
642
|
+
function deleteCheckpoint(checkpointId) {
|
|
643
|
+
const index = readIndex();
|
|
644
|
+
|
|
645
|
+
// Handle tag lookup
|
|
646
|
+
if (!checkpointId.startsWith(CHECKPOINT_PREFIX)) {
|
|
647
|
+
const found = index.checkpoints.find(c => c.tag === checkpointId);
|
|
648
|
+
if (found) {
|
|
649
|
+
checkpointId = found.id;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
const checkpointPath = getCheckpointPath(checkpointId);
|
|
654
|
+
|
|
655
|
+
if (!fs.existsSync(checkpointPath)) {
|
|
656
|
+
return false;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Remove directory recursively
|
|
660
|
+
fs.rmSync(checkpointPath, { recursive: true, force: true });
|
|
661
|
+
|
|
662
|
+
// Update index
|
|
663
|
+
index.checkpoints = index.checkpoints.filter(c => c.id !== checkpointId);
|
|
664
|
+
writeIndex(index);
|
|
665
|
+
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Prune old checkpoints.
|
|
671
|
+
* @param {object} options
|
|
672
|
+
* @param {number} [options.keep] - Number to keep
|
|
673
|
+
* @param {number} [options.olderThanDays] - Delete older than N days
|
|
674
|
+
* @returns {object}
|
|
675
|
+
*/
|
|
676
|
+
function pruneCheckpoints({ keep, olderThanDays } = {}) {
|
|
677
|
+
const index = readIndex();
|
|
678
|
+
const results = { deleted: [], kept: [] };
|
|
679
|
+
|
|
680
|
+
let toDelete = [];
|
|
681
|
+
|
|
682
|
+
if (keep !== undefined && keep >= 0) {
|
|
683
|
+
// Keep N most recent
|
|
684
|
+
toDelete = index.checkpoints.slice(keep);
|
|
685
|
+
} else if (olderThanDays !== undefined && olderThanDays > 0) {
|
|
686
|
+
// Delete older than N days
|
|
687
|
+
const cutoff = Date.now() - (olderThanDays * 24 * 60 * 60 * 1000);
|
|
688
|
+
toDelete = index.checkpoints.filter(c => new Date(c.created).getTime() < cutoff);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
for (const cp of toDelete) {
|
|
692
|
+
if (deleteCheckpoint(cp.id)) {
|
|
693
|
+
results.deleted.push(cp.id);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Re-read index after deletions
|
|
698
|
+
const newIndex = readIndex();
|
|
699
|
+
results.kept = newIndex.checkpoints.map(c => c.id);
|
|
700
|
+
|
|
701
|
+
return results;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Auto-cleanup based on settings.
|
|
706
|
+
*/
|
|
707
|
+
function autoCleanup() {
|
|
708
|
+
const index = readIndex();
|
|
709
|
+
const settings = index.settings || {
|
|
710
|
+
maxCheckpoints: DEFAULT_MAX_CHECKPOINTS,
|
|
711
|
+
maxStorageBytes: DEFAULT_MAX_STORAGE_BYTES,
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
// Check count limit
|
|
715
|
+
if (index.checkpoints.length > settings.maxCheckpoints) {
|
|
716
|
+
pruneCheckpoints({ keep: settings.maxCheckpoints });
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Check storage limit
|
|
720
|
+
const totalSize = getTotalStorageSize();
|
|
721
|
+
if (totalSize > settings.maxStorageBytes) {
|
|
722
|
+
// Delete oldest checkpoints until under limit
|
|
723
|
+
const newIndex = readIndex();
|
|
724
|
+
while (newIndex.checkpoints.length > 1 && getTotalStorageSize() > settings.maxStorageBytes) {
|
|
725
|
+
const oldest = newIndex.checkpoints[newIndex.checkpoints.length - 1];
|
|
726
|
+
deleteCheckpoint(oldest.id);
|
|
727
|
+
newIndex.checkpoints = newIndex.checkpoints.slice(0, -1);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
733
|
+
// AUTO-CHECKPOINT INTEGRATION
|
|
734
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Create auto-checkpoint before risky operation.
|
|
738
|
+
* Returns checkpoint ID for rollback reference.
|
|
739
|
+
*
|
|
740
|
+
* @param {object} options
|
|
741
|
+
* @param {string} options.command - Command name (fix, polish, shield, forge)
|
|
742
|
+
* @param {string} options.reason - Specific reason
|
|
743
|
+
* @param {string[]} options.files - Files to be modified
|
|
744
|
+
* @param {object} [options.context] - Additional context
|
|
745
|
+
* @returns {object}
|
|
746
|
+
*/
|
|
747
|
+
function autoCheckpoint({ command, reason, files, context = {} }) {
|
|
748
|
+
return createCheckpoint({
|
|
749
|
+
cwd: process.cwd(),
|
|
750
|
+
files,
|
|
751
|
+
reason: `auto:${command}`,
|
|
752
|
+
command,
|
|
753
|
+
context: {
|
|
754
|
+
...context,
|
|
755
|
+
auto: true,
|
|
756
|
+
timestamp: new Date().toISOString(),
|
|
757
|
+
},
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Rollback to checkpoint (alias for restore).
|
|
763
|
+
* @param {string} checkpointId
|
|
764
|
+
* @returns {object}
|
|
765
|
+
*/
|
|
766
|
+
function rollback(checkpointId) {
|
|
767
|
+
return restoreCheckpoint(checkpointId, { dryRun: false });
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Register a mission checkpoint in the global checkpoint index.
|
|
772
|
+
* This bridges the mission checkpoint system with the CLI checkpoint system.
|
|
773
|
+
*
|
|
774
|
+
* @param {object} missionCheckpoint - Checkpoint from mission system
|
|
775
|
+
* @param {string} repoRoot - Repository root
|
|
776
|
+
*/
|
|
777
|
+
function registerMissionCheckpoint(missionCheckpoint, repoRoot) {
|
|
778
|
+
try {
|
|
779
|
+
const index = readIndex();
|
|
780
|
+
|
|
781
|
+
// Check if already registered
|
|
782
|
+
const exists = index.checkpoints.some(c => c.id === missionCheckpoint.id);
|
|
783
|
+
if (exists) return;
|
|
784
|
+
|
|
785
|
+
index.checkpoints.unshift({
|
|
786
|
+
id: missionCheckpoint.id,
|
|
787
|
+
created: missionCheckpoint.createdAt || new Date().toISOString(),
|
|
788
|
+
reason: `auto:fix mission ${missionCheckpoint.missionId || ""}`,
|
|
789
|
+
tag: null,
|
|
790
|
+
fileCount: missionCheckpoint.snapshots?.length || 0,
|
|
791
|
+
totalSize: missionCheckpoint.snapshots?.reduce((sum, s) => sum + (s.size || 0), 0) || 0,
|
|
792
|
+
command: "fix --apply",
|
|
793
|
+
missionId: missionCheckpoint.missionId,
|
|
794
|
+
repoRoot,
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
writeIndex(index);
|
|
798
|
+
} catch {
|
|
799
|
+
// Non-critical - mission checkpoint still works
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Bulk restore from mission checkpoint.
|
|
805
|
+
* Used when user wants to restore from a fix mission checkpoint via CLI.
|
|
806
|
+
*
|
|
807
|
+
* @param {string} checkpointId - Mission checkpoint ID
|
|
808
|
+
* @param {string} repoRoot - Repository root
|
|
809
|
+
* @returns {object}
|
|
810
|
+
*/
|
|
811
|
+
function restoreMissionCheckpoint(checkpointId, repoRoot) {
|
|
812
|
+
try {
|
|
813
|
+
// Try mission checkpoint system first
|
|
814
|
+
const missionCheckpointModule = require("./missions/checkpoint");
|
|
815
|
+
const result = missionCheckpointModule.rollbackToCheckpoint(repoRoot, checkpointId);
|
|
816
|
+
return {
|
|
817
|
+
id: checkpointId,
|
|
818
|
+
restored: result.restored || [],
|
|
819
|
+
errors: result.errors || [],
|
|
820
|
+
dryRun: false,
|
|
821
|
+
source: "mission",
|
|
822
|
+
};
|
|
823
|
+
} catch {
|
|
824
|
+
// Fall back to standard checkpoint
|
|
825
|
+
return restoreCheckpoint(checkpointId);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
830
|
+
// HELPERS
|
|
831
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* Format bytes to human readable.
|
|
835
|
+
* @param {number} bytes
|
|
836
|
+
* @returns {string}
|
|
837
|
+
*/
|
|
838
|
+
function formatBytes(bytes) {
|
|
839
|
+
if (bytes === 0) return "0 B";
|
|
840
|
+
const k = 1024;
|
|
841
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
842
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
843
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Get age string from ISO date.
|
|
848
|
+
* @param {string} isoDate
|
|
849
|
+
* @returns {string}
|
|
850
|
+
*/
|
|
851
|
+
function getAge(isoDate) {
|
|
852
|
+
const ms = Date.now() - new Date(isoDate).getTime();
|
|
853
|
+
const seconds = Math.floor(ms / 1000);
|
|
854
|
+
const minutes = Math.floor(seconds / 60);
|
|
855
|
+
const hours = Math.floor(minutes / 60);
|
|
856
|
+
const days = Math.floor(hours / 24);
|
|
857
|
+
|
|
858
|
+
if (days > 0) return `${days}d ago`;
|
|
859
|
+
if (hours > 0) return `${hours}h ago`;
|
|
860
|
+
if (minutes > 0) return `${minutes}m ago`;
|
|
861
|
+
return "just now";
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Get storage status.
|
|
866
|
+
* @returns {object}
|
|
867
|
+
*/
|
|
868
|
+
function getStorageStatus() {
|
|
869
|
+
const index = readIndex();
|
|
870
|
+
const totalSize = getTotalStorageSize();
|
|
871
|
+
const settings = index.settings || {
|
|
872
|
+
maxCheckpoints: DEFAULT_MAX_CHECKPOINTS,
|
|
873
|
+
maxStorageBytes: DEFAULT_MAX_STORAGE_BYTES,
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
return {
|
|
877
|
+
checkpointCount: index.checkpoints.length,
|
|
878
|
+
maxCheckpoints: settings.maxCheckpoints,
|
|
879
|
+
totalSize,
|
|
880
|
+
totalSizeFormatted: formatBytes(totalSize),
|
|
881
|
+
maxSize: settings.maxStorageBytes,
|
|
882
|
+
maxSizeFormatted: formatBytes(settings.maxStorageBytes),
|
|
883
|
+
usagePercent: Math.round((totalSize / settings.maxStorageBytes) * 100),
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Update settings.
|
|
889
|
+
* @param {object} newSettings
|
|
890
|
+
*/
|
|
891
|
+
function updateSettings(newSettings) {
|
|
892
|
+
const index = readIndex();
|
|
893
|
+
index.settings = { ...index.settings, ...newSettings };
|
|
894
|
+
writeIndex(index);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
898
|
+
// EXPORTS
|
|
899
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
900
|
+
|
|
901
|
+
module.exports = {
|
|
902
|
+
// Constants
|
|
903
|
+
AUTO_REASONS,
|
|
904
|
+
CHECKPOINT_PREFIX,
|
|
905
|
+
CHECKPOINT_DIR,
|
|
906
|
+
|
|
907
|
+
// Core operations
|
|
908
|
+
createCheckpoint,
|
|
909
|
+
restoreCheckpoint,
|
|
910
|
+
deleteCheckpoint,
|
|
911
|
+
|
|
912
|
+
// Listing & info
|
|
913
|
+
listCheckpoints,
|
|
914
|
+
getCheckpoint,
|
|
915
|
+
getLatestCheckpoint,
|
|
916
|
+
diffCheckpoint,
|
|
917
|
+
|
|
918
|
+
// Cleanup
|
|
919
|
+
pruneCheckpoints,
|
|
920
|
+
autoCleanup,
|
|
921
|
+
|
|
922
|
+
// Auto-integration
|
|
923
|
+
autoCheckpoint,
|
|
924
|
+
rollback,
|
|
925
|
+
|
|
926
|
+
// Mission integration
|
|
927
|
+
registerMissionCheckpoint,
|
|
928
|
+
restoreMissionCheckpoint,
|
|
929
|
+
|
|
930
|
+
// Status & settings
|
|
931
|
+
getStorageStatus,
|
|
932
|
+
updateSettings,
|
|
933
|
+
|
|
934
|
+
// Helpers
|
|
935
|
+
formatBytes,
|
|
936
|
+
getAge,
|
|
937
|
+
getCheckpointPath,
|
|
938
|
+
ensureCheckpointDir,
|
|
939
|
+
readIndex,
|
|
940
|
+
writeIndex,
|
|
941
|
+
};
|