@planu/cli 4.13.0 → 4.14.1
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/CHANGELOG.md +29 -0
- package/README.md +24 -24
- package/dist/cli/commands/inspect.d.ts +4 -0
- package/dist/cli/commands/inspect.js +144 -0
- package/dist/cli/commands/install.d.ts +19 -1
- package/dist/cli/commands/install.js +145 -43
- package/dist/cli/commands/job.d.ts +3 -0
- package/dist/cli/commands/job.js +119 -0
- package/dist/cli/commands/offline.d.ts +15 -0
- package/dist/cli/commands/offline.js +132 -0
- package/dist/cli/commands/serve.js +4 -0
- package/dist/cli/commands/spec.js +1 -1
- package/dist/cli/commands/storage.d.ts +3 -0
- package/dist/cli/commands/storage.js +102 -0
- package/dist/cli/commands/uninstall.d.ts +10 -0
- package/dist/cli/commands/uninstall.js +93 -7
- package/dist/cli/commands/validate.js +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/router.js +9 -1
- package/dist/config/crash-shield-framework-rules.json +93 -0
- package/dist/config/environment-schema.json +149 -0
- package/dist/config/hardcode-exceptions.json +4 -0
- package/dist/config/license-plans.json +7 -0
- package/dist/config/native-release-public-key.pem +3 -0
- package/dist/config/native-targets.json +87 -0
- package/dist/config/product-public.d.ts +89 -0
- package/dist/config/product-public.js +140 -0
- package/dist/config/product-public.json +312 -0
- package/dist/config/product-public.ts +148 -0
- package/dist/config/release-compatibility.json +13 -0
- package/dist/config/release-policy.json +26 -0
- package/dist/config/runtime-policy.json +44 -0
- package/dist/config/skill-templates/planu-validate.md +7 -4
- package/dist/config/subagent-templates/planu-spec-implementer.md +7 -3
- package/dist/config/subagent-templates/planu-validator.md +10 -5
- package/dist/config/technology-registry.json +120 -0
- package/dist/config/version.js +7 -8
- package/dist/config/version.ts +10 -7
- package/dist/engine/abortable-process-runner.js +40 -9
- package/dist/engine/advanced-testing/accessibility-checker.js +12 -14
- package/dist/engine/advanced-testing/mutation-advisor.js +3 -4
- package/dist/engine/advanced-testing/property-based.js +2 -3
- package/dist/engine/advanced-testing/test-data-advisor.js +2 -3
- package/dist/engine/agent-generator.js +2 -1
- package/dist/engine/agent-handoff-store.js +2 -1
- package/dist/engine/agent-prompt-generator.js +7 -5
- package/dist/engine/agent-telemetry.js +2 -1
- package/dist/engine/ai-integration/gemini/extensions-advisor.js +41 -9
- package/dist/engine/ambiguity-detector.js +12 -11
- package/dist/engine/analyzer/db-engine.js +2 -3
- package/dist/engine/analyzer/detectors.js +13 -14
- package/dist/engine/analyzer/env-setup.js +9 -10
- package/dist/engine/analyzer-env-scanner/env-example.js +7 -8
- package/dist/engine/api-spec-generator/graphql-parser.js +2 -2
- package/dist/engine/api-validation/graphql-schema-validator.js +2 -1
- package/dist/engine/api-validation/openapi-impl-validator.js +6 -7
- package/dist/engine/architecture-detector.js +10 -8
- package/dist/engine/auth/config.d.ts +1 -1
- package/dist/engine/auth/config.js +4 -3
- package/dist/engine/auto-updater/atomic-upgrade.d.ts +8 -0
- package/dist/engine/auto-updater/atomic-upgrade.js +381 -0
- package/dist/engine/auto-updater/config-detector.js +9 -3
- package/dist/engine/auto-updater/config-patcher.d.ts +0 -4
- package/dist/engine/auto-updater/config-patcher.js +10 -15
- package/dist/engine/auto-updater/index.d.ts +3 -1
- package/dist/engine/auto-updater/index.js +44 -30
- package/dist/engine/auto-updater/npm-registry.js +10 -2
- package/dist/engine/auto-updater/release-verifier.d.ts +3 -0
- package/dist/engine/auto-updater/release-verifier.js +112 -0
- package/dist/engine/auto-updater/upgrade-lock.d.ts +6 -0
- package/dist/engine/auto-updater/upgrade-lock.js +28 -0
- package/dist/engine/auto-updater/upgrade-trust-state.d.ts +7 -0
- package/dist/engine/auto-updater/upgrade-trust-state.js +59 -0
- package/dist/engine/autopilot/audit-logger.js +2 -5
- package/dist/engine/best-practices-library.js +2 -1
- package/dist/engine/browser-validator.js +2 -1
- package/dist/engine/build-tool-detector.js +3 -2
- package/dist/engine/ci-generator/context-builders.js +7 -5
- package/dist/engine/ci-generator/stack-detector.js +0 -2
- package/dist/engine/ci-generator/yaml-builder.js +0 -2
- package/dist/engine/claude-config-auditor/rules-auditor.js +4 -3
- package/dist/engine/code-transforms/typescript/ast-utils.js +2 -3
- package/dist/engine/complexity-budget/trivial-detector.js +2 -1
- package/dist/engine/compliance-test-generator/index.js +7 -2
- package/dist/engine/compliance-test-generator/test-formatter.js +2 -2
- package/dist/engine/config-health/mcp-config-checker.js +2 -1
- package/dist/engine/config-health/ts-checker-scripts.js +4 -3
- package/dist/engine/config-health/ts-checker.js +3 -2
- package/dist/engine/convention-injector.js +5 -7
- package/dist/engine/convention-scanner/convention-parser.js +3 -2
- package/dist/engine/core-bridge-duplicate-blocks.d.ts +3 -0
- package/dist/engine/core-bridge-duplicate-blocks.js +57 -0
- package/dist/engine/core-bridge-gaps.d.ts +4 -0
- package/dist/engine/core-bridge-gaps.js +75 -0
- package/dist/engine/core-bridge.d.ts +9 -9
- package/dist/engine/core-bridge.js +196 -283
- package/dist/engine/cost-tracking/ledger.js +2 -5
- package/dist/engine/coverage-gap-analyzer.js +10 -1
- package/dist/engine/crash-shield/detectors/framework-detector.d.ts +2 -0
- package/dist/engine/crash-shield/detectors/framework-detector.js +110 -192
- package/dist/engine/crash-shield/detectors/typescript-detector.js +2 -1
- package/dist/engine/dashboard/data-loader.js +2 -1
- package/dist/engine/data-projects-gc/gc-runner.d.ts +7 -0
- package/dist/engine/data-projects-gc/gc-runner.js +113 -3
- package/dist/engine/data-projects-gc/scanner.js +5 -1
- package/dist/engine/decision-store.js +11 -14
- package/dist/engine/deleter/core.js +5 -5
- package/dist/engine/dep-auditor/abandonment-data.js +2 -1
- package/dist/engine/dep-auditor/abandonment-registry.js +3 -1
- package/dist/engine/dep-auditor/cve-fetcher.js +3 -0
- package/dist/engine/dep-auditor/dep-duplicates-detector.js +36 -4
- package/dist/engine/dep-auditor/license-registry.js +2 -0
- package/dist/engine/dependency-evaluator.d.ts +14 -0
- package/dist/engine/dependency-evaluator.js +81 -0
- package/dist/engine/deploy/providers/fly.js +7 -7
- package/dist/engine/deploy/providers/netlify.js +7 -7
- package/dist/engine/deploy/providers/railway.js +10 -12
- package/dist/engine/deploy/providers/vercel.js +7 -9
- package/dist/engine/deprecation-scanner/pattern-loader.js +0 -2
- package/dist/engine/desktop-detector.js +2 -3
- package/dist/engine/detect-duplication.js +2 -1
- package/dist/engine/detectors/advanced-framework-detector/css-state-detector.js +2 -1
- package/dist/engine/detectors/advanced-framework-detector/legacy-detector.js +2 -3
- package/dist/engine/detectors/advanced-framework-detector/modern-detector.js +3 -4
- package/dist/engine/detectors/agent-framework-detector.js +3 -2
- package/dist/engine/detectors/ai-native-detector.js +4 -6
- package/dist/engine/detectors/cache-db-detector.js +4 -3
- package/dist/engine/detectors/cicd-detector.js +4 -3
- package/dist/engine/detectors/deployment-detector.js +11 -12
- package/dist/engine/detectors/frontend-perf-detector.js +14 -9
- package/dist/engine/detectors/library-detector-multilang-a.js +16 -3
- package/dist/engine/detectors/library-detector-node.js +14 -4
- package/dist/engine/detectors/library-detector-python.js +7 -1
- package/dist/engine/detectors/library-detector.js +0 -2
- package/dist/engine/detectors/llm-detector/provider-maps.js +3 -2
- package/dist/engine/detectors/mcp-candidate-detector.js +12 -16
- package/dist/engine/detectors/mfe-detector.js +6 -7
- package/dist/engine/detectors/monitoring-detector.js +4 -3
- package/dist/engine/detectors/otel-detector.js +3 -2
- package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -2
- package/dist/engine/detectors/otel-ecosystem-detectors.js +4 -3
- package/dist/engine/detectors/platform-specialty-detector.js +3 -5
- package/dist/engine/detectors/template-engine-detector.js +3 -4
- package/dist/engine/doc-generator/builders.js +2 -3
- package/dist/engine/doc-generator/mobile-distribution-guide.js +13 -17
- package/dist/engine/doc-generator/portal/dirty-flag-map.d.ts +2 -2
- package/dist/engine/doc-generator/portal/portal-regenerator.js +3 -47
- package/dist/engine/domain-detector.js +3 -6
- package/dist/engine/dynamic-knowledge/knowledge-cache.js +3 -4
- package/dist/engine/dynamic-knowledge/knowledge-merger.js +17 -2
- package/dist/engine/dynamic-knowledge/web-researcher.js +15 -14
- package/dist/engine/dynamic-migration-detector/manifest-readers-extended.js +0 -2
- package/dist/engine/e2e-test-generator.js +4 -3
- package/dist/engine/ecosystem-absorber/knowledge-cache.js +2 -1
- package/dist/engine/ecosystem-absorber/platform-crawler.js +2 -2
- package/dist/engine/escalator/retry-counter.js +2 -1
- package/dist/engine/evidence-gates/artifact-reader.d.ts +6 -0
- package/dist/engine/evidence-gates/artifact-reader.js +105 -21
- package/dist/engine/evidence-gates/lifecycle-gate.d.ts +2 -1
- package/dist/engine/evidence-gates/lifecycle-gate.js +54 -0
- package/dist/engine/execution/context.d.ts +19 -0
- package/dist/engine/execution/context.js +127 -0
- package/dist/engine/execution/deadline-io.d.ts +21 -0
- package/dist/engine/execution/deadline-io.js +45 -0
- package/dist/engine/execution/job-executor.d.ts +16 -0
- package/dist/engine/execution/job-executor.js +140 -0
- package/dist/engine/execution/job-runtime.d.ts +78 -0
- package/dist/engine/execution/job-runtime.js +220 -0
- package/dist/engine/execution/native-relevance-scorer.d.ts +6 -0
- package/dist/engine/execution/native-relevance-scorer.js +64 -0
- package/dist/engine/execution/native-worker-dispatch.d.ts +3 -0
- package/dist/engine/execution/native-worker-dispatch.js +46 -0
- package/dist/engine/execution/native-worker-protocol.d.ts +6 -0
- package/dist/engine/execution/native-worker-protocol.js +33 -0
- package/dist/engine/execution/native-worker-runtime.d.ts +4 -0
- package/dist/engine/execution/native-worker-runtime.js +177 -0
- package/dist/engine/execution/native-worker-thread.d.ts +2 -0
- package/dist/engine/execution/native-worker-thread.js +66 -0
- package/dist/engine/execution/operation-journal.d.ts +66 -0
- package/dist/engine/execution/operation-journal.js +260 -0
- package/dist/engine/execution/outbox-worker.d.ts +31 -0
- package/dist/engine/execution/outbox-worker.js +192 -0
- package/dist/engine/execution/validate-job-executor.d.ts +24 -0
- package/dist/engine/execution/validate-job-executor.js +342 -0
- package/dist/engine/execution/validate-job-payload.d.ts +5 -0
- package/dist/engine/execution/validate-job-payload.js +87 -0
- package/dist/engine/execution/validate-job-recovery.d.ts +4 -0
- package/dist/engine/execution/validate-job-recovery.js +47 -0
- package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
- package/dist/engine/execution/validate-worker-runtime.js +100 -0
- package/dist/engine/execution/validate-worker-thread.d.ts +2 -0
- package/dist/engine/execution/validate-worker-thread.js +71 -0
- package/dist/engine/execution-plan/desktop-distribution.js +3 -7
- package/dist/engine/execution-plan/mobile-distribution.js +4 -9
- package/dist/engine/execution-plan/phases.js +4 -5
- package/dist/engine/execution-plan/plan-utils.js +8 -5
- package/dist/engine/facilitate/context-loader.js +3 -9
- package/dist/engine/figma/code-connect-fetcher.js +9 -8
- package/dist/engine/filesystem-watcher/index.d.ts +3 -3
- package/dist/engine/filesystem-watcher/index.js +5 -5
- package/dist/engine/framework-detector.js +14 -15
- package/dist/engine/git/planu-autocommit.js +8 -7
- package/dist/engine/git/repository-probe.d.ts +3 -0
- package/dist/engine/git/repository-probe.js +13 -0
- package/dist/engine/global-rules-manager.js +2 -2
- package/dist/engine/handoff-artifacts/io.js +2 -3
- package/dist/engine/handoff-artifacts/schemas/red-tests-handoff.js +8 -1
- package/dist/engine/handoff-artifacts/schemas.d.ts +4 -0
- package/dist/engine/handoff-artifacts/schemas.js +5 -0
- package/dist/engine/hook-generator/stack-hook-templates.js +4 -4
- package/dist/engine/hooks/config-loader.js +1 -1
- package/dist/engine/hooks/context-injector.js +4 -7
- package/dist/engine/hooks/file-watcher.js +1 -14
- package/dist/engine/hooks-reconciler.js +6 -4
- package/dist/engine/infrastructure/component-mapper.js +5 -7
- package/dist/engine/infrastructure/docker-compose-generator.js +8 -10
- package/dist/engine/infrastructure/index.js +6 -3
- package/dist/engine/infrastructure/kubernetes-generator.js +2 -2
- package/dist/engine/infrastructure/railway-generator.js +10 -8
- package/dist/engine/infrastructure/signal-detector.js +6 -8
- package/dist/engine/infrastructure/terraform-generator.js +6 -8
- package/dist/engine/legal-compliance/detector.js +3 -2
- package/dist/engine/local-first/storage-advisor.js +5 -6
- package/dist/engine/macos-keychain-native-port.d.ts +5 -0
- package/dist/engine/macos-keychain-native-port.js +26 -0
- package/dist/engine/marketplace-fetcher/cache.js +3 -1
- package/dist/engine/mcp-config/mcp-config-writer.d.ts +2 -2
- package/dist/engine/mcp-config/mcp-config-writer.js +10 -8
- package/dist/engine/migration/db-migrator.js +2 -5
- package/dist/engine/migration/equivalence-mapper.js +12 -13
- package/dist/engine/migration/service-catalogs.js +6 -7
- package/dist/engine/migration/service-migrator-catalogs.js +6 -7
- package/dist/engine/mobile-detector-ios.js +2 -3
- package/dist/engine/mobile-detector.js +16 -4
- package/dist/engine/model-router/complexity-analyzer.js +4 -7
- package/dist/engine/multi-agent-review/security-analyzer.js +3 -1
- package/dist/engine/multi-app-detector/app-type.js +26 -21
- package/dist/engine/multi-app-detector/core.js +3 -2
- package/dist/engine/multi-teammate-review/disagreement-counter.js +2 -1
- package/dist/engine/multi-teammate-review/panel-orchestrator.js +0 -2
- package/dist/engine/mutation-config-generator.js +10 -7
- package/dist/engine/native-capability-policy.d.ts +4 -0
- package/dist/engine/native-capability-policy.js +24 -0
- package/dist/engine/native-platform.d.ts +3 -0
- package/dist/engine/native-platform.js +44 -0
- package/dist/engine/native-runtime-handshake.d.ts +20 -0
- package/dist/engine/native-runtime-handshake.js +230 -0
- package/dist/engine/network-policy.d.ts +27 -0
- package/dist/engine/network-policy.js +174 -0
- package/dist/engine/next-spec-resolver/dependency-filter.js +2 -22
- package/dist/engine/nfr-profile-detector.js +12 -16
- package/dist/engine/nli-keywords.js +8 -9
- package/dist/engine/oauth/config-guard.js +4 -5
- package/dist/engine/observability/local-execution-spans.d.ts +15 -0
- package/dist/engine/observability/local-execution-spans.js +63 -0
- package/dist/engine/orchestrator/runtime.js +0 -1
- package/dist/engine/package-registry.js +2 -6
- package/dist/engine/performance-analyzer.js +2 -5
- package/dist/engine/permissions-merger/stack-detectors.js +5 -5
- package/dist/engine/planu-core.darwin-arm64.node.manifest.json +39 -0
- package/dist/engine/planu-core.darwin-arm64.node.sbom.json +1310 -0
- package/dist/engine/planu-core.darwin-x64.node.manifest.json +39 -0
- package/dist/engine/planu-core.darwin-x64.node.sbom.json +1310 -0
- package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +38 -0
- package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +1310 -0
- package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +38 -0
- package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +1310 -0
- package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +38 -0
- package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +1310 -0
- package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +38 -0
- package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +1310 -0
- package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +38 -0
- package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +1310 -0
- package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +38 -0
- package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +1310 -0
- package/dist/engine/platform-detector/desktop.js +15 -2
- package/dist/engine/platform-detector/extensions.js +2 -1
- package/dist/engine/platform-detector/games.js +2 -1
- package/dist/engine/platform-detector.js +3 -2
- package/dist/engine/platform-engineering/idp-detector.js +2 -1
- package/dist/engine/plugin-installer/stack-matcher.js +9 -17
- package/dist/engine/plugins/lifecycle.js +6 -2
- package/dist/engine/prior-decisions/contradiction-detector.js +60 -30
- package/dist/engine/project-dna/stack-detector.js +15 -17
- package/dist/engine/project-graph/builder.js +11 -0
- package/dist/engine/project-graph/cache.js +1 -1
- package/dist/engine/project-graph/freshness-projection.d.ts +16 -0
- package/dist/engine/project-graph/freshness-projection.js +95 -0
- package/dist/engine/project-graph/index.d.ts +1 -0
- package/dist/engine/project-graph/index.js +1 -0
- package/dist/engine/project-graph/query.js +15 -25
- package/dist/engine/project-health-checker.js +3 -4
- package/dist/engine/project-scanner/stack-detector.js +17 -17
- package/dist/engine/property-test-generator.js +2 -3
- package/dist/engine/qa-gate.d.ts +1 -0
- package/dist/engine/qa-gate.js +6 -4
- package/dist/engine/quality-gates/gate-catalog.js +47 -46
- package/dist/engine/quality-gates/gate-injector.js +9 -4
- package/dist/engine/registry/core.js +0 -2
- package/dist/engine/registry/loader.js +9 -12
- package/dist/engine/registry/matcher.js +129 -24
- package/dist/engine/resilience-detector/concurrency-detector.js +4 -4
- package/dist/engine/resilience-detector/middleware-detector.js +11 -13
- package/dist/engine/resilience-detector/validation-detector.js +17 -4
- package/dist/engine/reverse-engineer/config-analyzer.js +9 -8
- package/dist/engine/reverse-engineer/orchestrator.js +5 -9
- package/dist/engine/reverse-engineer/test-file-parser.js +6 -3
- package/dist/engine/rules-generator/index.js +6 -5
- package/dist/engine/runtime-policy.d.ts +7 -0
- package/dist/engine/runtime-policy.js +101 -0
- package/dist/engine/runtime-security/checkers/content-security.js +21 -6
- package/dist/engine/runtime-security/checkers/file-permissions.js +0 -2
- package/dist/engine/safety/atomic-write-file.js +20 -9
- package/dist/engine/safety/atomic-writer.js +10 -3
- package/dist/engine/safety/cross-process-lock.d.ts +3 -40
- package/dist/engine/safety/cross-process-lock.js +268 -272
- package/dist/engine/safety/file-mutex.d.ts +2 -9
- package/dist/engine/safety/file-mutex.js +155 -87
- package/dist/engine/safety/health-monitor.js +15 -6
- package/dist/engine/safety/lock-lease-store.d.ts +79 -0
- package/dist/engine/safety/lock-lease-store.js +372 -0
- package/dist/engine/safety/lock-scavenger.d.ts +2 -5
- package/dist/engine/safety/lock-scavenger.js +158 -76
- package/dist/engine/safety/lock-staleness.js +4 -1
- package/dist/engine/safety/obsolete-lock-guard.d.ts +8 -0
- package/dist/engine/safety/obsolete-lock-guard.js +31 -0
- package/dist/engine/safety/transaction.js +3 -3
- package/dist/engine/sandbox/index.js +2 -1
- package/dist/engine/sandbox/runner-detect.js +3 -2
- package/dist/engine/sandbox/runner-docker.js +4 -3
- package/dist/engine/scan-project/module-discoverer.js +3 -2
- package/dist/engine/schema-generator.js +16 -9
- package/dist/engine/security-analyzer/criteria-generator.js +2 -3
- package/dist/engine/self-healing/healer.js +4 -4
- package/dist/engine/session-safeguard/learnings-buffer.d.ts +1 -2
- package/dist/engine/session-safeguard/learnings-buffer.js +42 -65
- package/dist/engine/shared-agent-memory.js +66 -74
- package/dist/engine/skill-adapter/command-rewriter.js +3 -2
- package/dist/engine/skill-adapter/index.js +3 -3
- package/dist/engine/skill-adapter/placeholder-map.js +3 -2
- package/dist/engine/skill-bootstrap/stack-matcher.js +47 -48
- package/dist/engine/skill-generation/stack-content-generator.js +0 -2
- package/dist/engine/skill-generator/workflow-skill-generator.js +2 -1
- package/dist/engine/skill-registry/ttl-refresh.js +3 -1
- package/dist/engine/skills/skills-fetcher.js +3 -6
- package/dist/engine/skills-reconciler.js +19 -39
- package/dist/engine/spec-coverage/test-finder.js +7 -6
- package/dist/engine/spec-diff-engine.js +3 -3
- package/dist/engine/spec-generator/api-key-resolver.d.ts +1 -1
- package/dist/engine/spec-generator/api-key-resolver.js +3 -24
- package/dist/engine/spec-generators/issue-extractor.js +9 -3
- package/dist/engine/spec-migrator/drift-detector.js +5 -13
- package/dist/engine/spec-migrator/filesystem-import.js +14 -10
- package/dist/engine/spec-migrator/planu-canonical-policy.js +10 -1
- package/dist/engine/spec-migrator/strict-planu-cleanup.js +24 -25
- package/dist/engine/spec-registry/adapter.d.ts +0 -5
- package/dist/engine/spec-registry/adapter.js +45 -46
- package/dist/engine/spec-registry/client.js +2 -0
- package/dist/engine/spec-source-sync.js +3 -2
- package/dist/engine/spec-templates/custom-loader.js +2 -3
- package/dist/engine/spec-templates/templates-domain-specific.js +8 -5
- package/dist/engine/spec-templates/templates-perf-integration.js +2 -3
- package/dist/engine/stack-auditor/manifest-reader.js +0 -2
- package/dist/engine/staleness/stale-implementing.js +7 -7
- package/dist/engine/tdd-scaffold-generator.js +24 -11
- package/dist/engine/teammate-router/green-phase-verifier.js +2 -1
- package/dist/engine/teammate-router/red-phase-verifier.js +2 -1
- package/dist/engine/technology-registry.d.ts +11 -0
- package/dist/engine/technology-registry.js +142 -0
- package/dist/engine/telemetry/error-reporter.d.ts +1 -2
- package/dist/engine/telemetry/error-reporter.js +11 -18
- package/dist/engine/telemetry/health-checker.js +5 -14
- package/dist/engine/telemetry/index.d.ts +0 -1
- package/dist/engine/telemetry/index.js +0 -1
- package/dist/engine/telemetry/stance.js +3 -2
- package/dist/engine/telemetry/telemetry-client.d.ts +1 -5
- package/dist/engine/telemetry/telemetry-client.js +45 -29
- package/dist/engine/telemetry/telemetry-store.d.ts +3 -3
- package/dist/engine/telemetry/telemetry-store.js +30 -23
- package/dist/engine/test-framework-detector/detectors.js +8 -8
- package/dist/engine/test-framework-detector/strategy.js +8 -9
- package/dist/engine/test-generators/agent-test-templates.js +2 -3
- package/dist/engine/test-generators/contract-test-generator.d.ts +1 -1
- package/dist/engine/test-generators/contract-test-generator.js +9 -202
- package/dist/engine/test-generators/platform-test-templates-b.js +2 -3
- package/dist/engine/test-generators/platform-test-templates.js +2 -5
- package/dist/engine/test-mocks-generator.js +4 -3
- package/dist/engine/test-plan-generator.js +30 -12
- package/dist/engine/test-scaffold-generator/advanced-scaffold.js +4 -5
- package/dist/engine/test-scaffold-generator/unit-scaffold.js +5 -6
- package/dist/engine/timing/budget.d.ts +6 -17
- package/dist/engine/timing/budget.js +80 -64
- package/dist/engine/tool-groups/group-manager.js +3 -3
- package/dist/engine/universal-rules/installer.js +1 -1
- package/dist/engine/universal-rules/rules/planu-modes.js +2 -0
- package/dist/engine/universal-rules/rules/planu-release-policy.js +1 -0
- package/dist/engine/update-notifier.js +8 -5
- package/dist/engine/validation/approved-spec-portability.d.ts +12 -0
- package/dist/engine/validation/approved-spec-portability.js +107 -0
- package/dist/engine/validation/durable-validation.d.ts +36 -0
- package/dist/engine/validation/durable-validation.js +335 -0
- package/dist/engine/validation/validation-freshness.d.ts +36 -0
- package/dist/engine/validation/validation-freshness.js +427 -0
- package/dist/engine/validation/validation-receipt-codec.d.ts +13 -0
- package/dist/engine/validation/validation-receipt-codec.js +182 -0
- package/dist/engine/validation/validation-receipt.d.ts +59 -0
- package/dist/engine/validation/validation-receipt.js +282 -0
- package/dist/engine/validation/validation-source-policy.d.ts +4 -0
- package/dist/engine/validation/validation-source-policy.js +16 -0
- package/dist/engine/validation/validation-submission.d.ts +36 -0
- package/dist/engine/validation/validation-submission.js +128 -0
- package/dist/engine/validation-evidence-ledger.js +41 -0
- package/dist/engine/validation-impact-planner.js +25 -9
- package/dist/engine/validator/spec-compliance-runner.d.ts +1 -1
- package/dist/engine/validator/spec-compliance-runner.js +17 -8
- package/dist/engine/validator/validation-report-writer.js +1 -1
- package/dist/engine/validator.js +2 -1
- package/dist/engine/verify-integrations/index.js +1 -1
- package/dist/engine/version-resolver.js +5 -6
- package/dist/engine/web-fetcher/stack-advisor.js +156 -92
- package/dist/engine/web-fetcher/stack-detector.js +114 -54
- package/dist/engine/workspace-manager.js +3 -2
- package/dist/errors/classified-degradation.d.ts +3 -0
- package/dist/errors/classified-degradation.js +10 -0
- package/dist/errors/degradation-sink.d.ts +3 -0
- package/dist/errors/degradation-sink.js +5 -0
- package/dist/errors/error-taxonomy.d.ts +12 -0
- package/dist/errors/error-taxonomy.js +62 -0
- package/dist/hosts/claude-code/ux/mcp-prompts.js +10 -4
- package/dist/hosts/claude-code/ux/mcp-resources.js +4 -2
- package/dist/hosts/codex/config-scaffold.js +4 -3
- package/dist/hosts/gemini/config-scaffold.js +2 -1
- package/dist/hosts/gemini/multimodal-spec-flow.js +7 -4
- package/dist/index.js +21 -6
- package/dist/resources/patterns.js +3 -1
- package/dist/resources/specs.js +3 -1
- package/dist/resources/templates.js +3 -1
- package/dist/security/adapters/environment.d.ts +12 -0
- package/dist/security/adapters/environment.js +25 -0
- package/dist/security/adapters/linux-secret-service.d.ts +8 -0
- package/dist/security/adapters/linux-secret-service.js +60 -0
- package/dist/security/adapters/macos-keychain.d.ts +18 -0
- package/dist/security/adapters/macos-keychain.js +90 -0
- package/dist/security/adapters/windows-credential-manager.d.ts +8 -0
- package/dist/security/adapters/windows-credential-manager.js +58 -0
- package/dist/security/redactor.d.ts +5 -0
- package/dist/security/redactor.js +58 -0
- package/dist/security/secret-field.d.ts +5 -0
- package/dist/security/secret-field.js +17 -0
- package/dist/security/secret-migration.d.ts +3 -0
- package/dist/security/secret-migration.js +123 -0
- package/dist/security/secret-provider.d.ts +23 -0
- package/dist/security/secret-provider.js +145 -0
- package/dist/security/secure-json.d.ts +3 -0
- package/dist/security/secure-json.js +29 -0
- package/dist/storage/api-surfaces-store.js +2 -2
- package/dist/storage/approval-operation-lock.d.ts +1 -1
- package/dist/storage/approval-operation-lock.js +5 -3
- package/dist/storage/audit-trail-store.d.ts +1 -1
- package/dist/storage/audit-trail-store.js +48 -62
- package/dist/storage/autopilot-log-store.js +12 -5
- package/dist/storage/base-store.d.ts +8 -8
- package/dist/storage/base-store.js +57 -20
- package/dist/storage/checkpoint-store.js +5 -2
- package/dist/storage/comments-store.js +2 -2
- package/dist/storage/compliance-audit-store.js +5 -2
- package/dist/storage/compliance-gate-config-store.js +7 -4
- package/dist/storage/compliance-store.js +2 -2
- package/dist/storage/context-profile-store.js +2 -2
- package/dist/storage/crash-shield-store.js +8 -4
- package/dist/storage/feedback-store.js +10 -6
- package/dist/storage/figma-store.js +8 -4
- package/dist/storage/file-mutex.js +9 -1
- package/dist/storage/gaps-log.js +7 -4
- package/dist/storage/global-projects-store.js +4 -2
- package/dist/storage/ideas-store.js +2 -2
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/knowledge-store/knowledge.js +27 -33
- package/dist/storage/lessons-store.js +2 -2
- package/dist/storage/license-store.js +13 -41
- package/dist/storage/migrations/canonical-storage.d.ts +15 -0
- package/dist/storage/migrations/canonical-storage.js +599 -0
- package/dist/storage/oauth-store.js +36 -8
- package/dist/storage/path-resolver.js +16 -3
- package/dist/storage/pr-store.js +2 -2
- package/dist/storage/project-drift-store.js +20 -8
- package/dist/storage/project-identity.d.ts +32 -0
- package/dist/storage/project-identity.js +194 -0
- package/dist/storage/project-resolver.js +14 -7
- package/dist/storage/release-notes-store.js +2 -6
- package/dist/storage/runtime-db.d.ts +186 -0
- package/dist/storage/runtime-db.js +1054 -0
- package/dist/storage/schema-registry.d.ts +5 -0
- package/dist/storage/schema-registry.js +74 -0
- package/dist/storage/sentry-store.js +20 -9
- package/dist/storage/session-state-store.js +12 -5
- package/dist/storage/session-store.js +12 -4
- package/dist/storage/skill-registry-storage.d.ts +1 -1
- package/dist/storage/skill-registry-storage.js +13 -11
- package/dist/storage/slack-store.js +10 -5
- package/dist/storage/spec-store.js +31 -24
- package/dist/storage/status-store/file-lock.js +31 -9
- package/dist/storage/status-store/self-healing.js +10 -5
- package/dist/storage/status-store/version-sync.js +8 -6
- package/dist/storage/steering-store.js +2 -2
- package/dist/storage/storage-bundle.d.ts +5 -0
- package/dist/storage/storage-bundle.js +117 -0
- package/dist/storage/storage-catalog-validation.d.ts +3 -0
- package/dist/storage/storage-catalog-validation.js +20 -0
- package/dist/storage/storage-catalog.d.ts +25 -0
- package/dist/storage/storage-catalog.js +390 -0
- package/dist/storage/storage-layout.d.ts +24 -0
- package/dist/storage/storage-layout.js +101 -0
- package/dist/storage/storybook-store.js +2 -2
- package/dist/storage/supabase-store.js +24 -6
- package/dist/storage/tdd-policy-store.js +8 -6
- package/dist/storage/tech-debt-store.js +3 -3
- package/dist/storage/technology-selection-store.d.ts +1 -1
- package/dist/storage/technology-selection-store.js +6 -3
- package/dist/storage/token-cache-store.js +3 -3
- package/dist/storage/token-ledger-store.js +13 -8
- package/dist/storage/transition-log.js +7 -4
- package/dist/storage/trash-store.js +15 -6
- package/dist/storage/vector-store/migrator.js +7 -2
- package/dist/storage/vector-store/sqlite-adapter.js +4 -1
- package/dist/storage/webhook-server-store.js +2 -2
- package/dist/tools/api-spec-generator-handler.js +3 -2
- package/dist/tools/auto-update-handler.d.ts +1 -1
- package/dist/tools/auto-update-handler.js +1 -1
- package/dist/tools/browser-validate-handler.js +2 -1
- package/dist/tools/challenge-spec/platform-challenge-scenarios-b.js +8 -5
- package/dist/tools/challenge-spec/scenarios-desktop.js +8 -3
- package/dist/tools/challenge-spec/scenarios-failure.js +7 -2
- package/dist/tools/challenge-spec/security-challenge-scenarios.js +3 -3
- package/dist/tools/clarify-requirements/multiple-choice.js +53 -41
- package/dist/tools/comments-handler.js +2 -3
- package/dist/tools/compliance-test-handler.js +2 -2
- package/dist/tools/configure-telemetry.js +11 -11
- package/dist/tools/create-spec/auto-pipeline.js +13 -1
- package/dist/tools/create-spec/autopilot-analyzer.d.ts +1 -1
- package/dist/tools/create-spec/autopilot-analyzer.js +2 -4
- package/dist/tools/create-spec/mcp-tool-contract.d.ts +10 -4
- package/dist/tools/create-spec/mcp-tool-contract.js +7 -36
- package/dist/tools/create-spec/post-creation.d.ts +2 -1
- package/dist/tools/create-spec/post-creation.js +56 -54
- package/dist/tools/create-spec/relevance-scorer.d.ts +1 -1
- package/dist/tools/create-spec/relevance-scorer.js +17 -1
- package/dist/tools/create-spec/spec-builder.js +2 -12
- package/dist/tools/create-spec/spec-created-outbox-consumer.d.ts +14 -0
- package/dist/tools/create-spec/spec-created-outbox-consumer.js +176 -0
- package/dist/tools/create-spec.js +385 -520
- package/dist/tools/define-ui-contract/agent-interaction-contract.js +2 -4
- package/dist/tools/define-ui-contract-desktop/desktop-contract.js +12 -4
- package/dist/tools/define-ui-contract-desktop/native-contract.js +7 -3
- package/dist/tools/define-ui-contract-extensions.js +2 -3
- package/dist/tools/define-ui-contract-mobile.js +5 -9
- package/dist/tools/define-ui-contract-web/component-tree.js +4 -3
- package/dist/tools/define-ui-contract.js +7 -4
- package/dist/tools/deploy/deploy-spec.js +2 -4
- package/dist/tools/deploy/deploy-status.js +2 -4
- package/dist/tools/design-schema/nosql-category-schemas.js +2 -3
- package/dist/tools/design-schema-sql/migrations.js +3 -2
- package/dist/tools/design-schema-sql/tables.js +4 -1
- package/dist/tools/design-schema.js +4 -3
- package/dist/tools/feedback-handler.js +2 -4
- package/dist/tools/gc-data-projects.js +5 -5
- package/dist/tools/generate-execution-plan.js +3 -4
- package/dist/tools/generate-sub-agent.js +2 -1
- package/dist/tools/generate-tests/generators/a11y-tests-generator.js +5 -4
- package/dist/tools/generate-tests/generators/advanced-testing-generator.js +5 -4
- package/dist/tools/generate-tests/generators/concurrency-test-generator/js-templates.js +9 -4
- package/dist/tools/generate-tests/generators/concurrency-test-generator.js +8 -4
- package/dist/tools/generate-tests/generators/database/detectors.js +9 -3
- package/dist/tools/generate-tests/generators/database/index.js +2 -4
- package/dist/tools/generate-tests/generators/event-test-generator.js +5 -4
- package/dist/tools/generate-tests/generators/game-tests-generator.js +2 -1
- package/dist/tools/generate-tests/generators/graphql-test-generator.js +11 -5
- package/dist/tools/generate-tests/generators/grpc-test-generator.js +2 -3
- package/dist/tools/generate-tests/generators/llm-security-test-generator.js +4 -3
- package/dist/tools/generate-tests/generators/local-first-test-generator.js +4 -3
- package/dist/tools/generate-tests/generators/mcp-tests-generator.js +11 -9
- package/dist/tools/generate-tests/generators/microservices/index.js +2 -3
- package/dist/tools/generate-tests/generators/otel-test-generator.js +6 -3
- package/dist/tools/generate-tests/generators/security/detectors.js +2 -5
- package/dist/tools/generate-tests/generators/security/index.js +2 -4
- package/dist/tools/generate-tests/generators/supply-chain-test-generator.js +2 -3
- package/dist/tools/generate-tests/generators/visual-regression-generator.js +14 -17
- package/dist/tools/generate-tests/generators/websocket-test-generator.js +2 -3
- package/dist/tools/generate-tests/test-helpers.js +11 -12
- package/dist/tools/generate-tests-content.js +4 -3
- package/dist/tools/generate-tests.js +7 -4
- package/dist/tools/git/git-helpers.d.ts +0 -2
- package/dist/tools/git/git-helpers.js +7 -7
- package/dist/tools/github-pr-handler.js +10 -3
- package/dist/tools/heal-spec-docs.js +6 -53
- package/dist/tools/hook-generator-handler.js +6 -6
- package/dist/tools/init-constitution/platform-principles.js +4 -2
- package/dist/tools/init-project/agents-md-writer.js +14 -5
- package/dist/tools/init-project/claude-md-generator.js +19 -12
- package/dist/tools/init-project/handler.js +165 -73
- package/dist/tools/init-project/host-assets-writer.d.ts +1 -1
- package/dist/tools/init-project/host-assets-writer.js +4 -2
- package/dist/tools/init-project/lifecycle-helpers.js +3 -5
- package/dist/tools/init-project/lint-scaffolder.js +6 -2
- package/dist/tools/init-project/migration-runner.d.ts +10 -1
- package/dist/tools/init-project/migration-runner.js +68 -3
- package/dist/tools/init-project/per-client-files-writer.js +14 -4
- package/dist/tools/init-project/rules-generator.js +10 -2
- package/dist/tools/init-project/scaffold-writer.d.ts +1 -1
- package/dist/tools/init-project/scaffold-writer.js +17 -15
- package/dist/tools/jobs/handlers.d.ts +15 -0
- package/dist/tools/jobs/handlers.js +126 -0
- package/dist/tools/list-specs.js +35 -34
- package/dist/tools/manage-plugins-handler.js +17 -9
- package/dist/tools/migrate-tech/advanced-handlers.js +3 -2
- package/dist/tools/migrate-tech/build-tool-handlers.js +3 -2
- package/dist/tools/migrate-tech/core-handlers.js +5 -2
- package/dist/tools/migrate-tech/data-handlers.js +6 -3
- package/dist/tools/migrate-tech-advanced/rollback-handlers.js +3 -2
- package/dist/tools/migrate-tech-advanced/service-handlers.js +5 -2
- package/dist/tools/oauth-handler.js +7 -1
- package/dist/tools/register-sdd-tools.d.ts +1 -1
- package/dist/tools/register-sdd-tools.js +5 -0
- package/dist/tools/register-spec-tools/core-spec-tools.js +31 -0
- package/dist/tools/registry/auth.js +13 -5
- package/dist/tools/registry/publish.js +7 -4
- package/dist/tools/resolve-project-path.d.ts +2 -2
- package/dist/tools/resolve-project-path.js +7 -7
- package/dist/tools/reverse-engineer/analyzer.js +14 -14
- package/dist/tools/rollback-release.js +3 -2
- package/dist/tools/safe-handler.js +295 -171
- package/dist/tools/schema-generator-handler.js +2 -1
- package/dist/tools/schemas/output-schemas.d.ts +88 -82
- package/dist/tools/schemas/output-schemas.js +12 -94
- package/dist/tools/schemas/plugins-schemas.js +0 -2
- package/dist/tools/schemas/registry.js +0 -2
- package/dist/tools/schemas/skill-registry-schemas.js +0 -2
- package/dist/tools/schemas/validate-output-schema.d.ts +256 -0
- package/dist/tools/schemas/validate-output-schema.js +212 -0
- package/dist/tools/sentry-handler.js +6 -1
- package/dist/tools/skill-bootstrap-handler.js +7 -4
- package/dist/tools/status-handler.js +4 -0
- package/dist/tools/storage-bundle-handler.d.ts +9 -0
- package/dist/tools/storage-bundle-handler.js +29 -0
- package/dist/tools/storage-paths-handler.d.ts +9 -0
- package/dist/tools/storage-paths-handler.js +17 -0
- package/dist/tools/suggest-mcp-server.js +11 -5
- package/dist/tools/suggest-mcps.js +29 -9
- package/dist/tools/suggest-tooling/advanced-testing-catalog.js +4 -5
- package/dist/tools/suggest-tooling/build-tool-catalog.js +2 -1
- package/dist/tools/suggest-tooling/css-framework-catalog.js +13 -7
- package/dist/tools/suggest-tooling/framework-catalog.js +3 -5
- package/dist/tools/suggest-tooling/frontend-perf-catalog.js +2 -6
- package/dist/tools/suggest-tooling/handler.js +10 -4
- package/dist/tools/suggest-tooling/hypermedia-catalog.js +11 -3
- package/dist/tools/suggest-tooling/linting-catalog.js +4 -7
- package/dist/tools/suggest-tooling/llm-security-catalog.js +2 -1
- package/dist/tools/suggest-tooling/local-first-catalog.js +7 -5
- package/dist/tools/suggest-tooling/observability-catalog.js +3 -4
- package/dist/tools/suggest-tooling/otel-catalog.js +4 -1
- package/dist/tools/suggest-tooling/resilience-catalog.js +16 -5
- package/dist/tools/suggest-tooling/skills-catalog.js +10 -9
- package/dist/tools/suggest-tooling/supply-chain-catalog.js +2 -3
- package/dist/tools/supabase-handler.js +2 -1
- package/dist/tools/token-intelligence-handler.js +2 -2
- package/dist/tools/token-recording.js +2 -2
- package/dist/tools/token-savings-handler.js +2 -2
- package/dist/tools/tool-registry/core-tools.js +131 -0
- package/dist/tools/tool-registry/group-infra.js +10 -12
- package/dist/tools/tool-registry/group-quality-compliance.js +5 -12
- package/dist/tools/update-status/approval-gates.d.ts +13 -0
- package/dist/tools/update-status/approval-gates.js +81 -0
- package/dist/tools/update-status/batch.js +4 -2
- package/dist/tools/update-status/dod-gates.d.ts +6 -24
- package/dist/tools/update-status/dod-gates.js +60 -135
- package/dist/tools/update-status/done-receipt-verifier.d.ts +15 -0
- package/dist/tools/update-status/done-receipt-verifier.js +145 -0
- package/dist/tools/update-status/evidence-gate.js +154 -2
- package/dist/tools/update-status/file-sync.js +23 -12
- package/dist/tools/update-status/gate-harness.d.ts +7 -0
- package/dist/tools/update-status/gate-harness.js +8 -0
- package/dist/tools/update-status/index.js +228 -325
- package/dist/tools/update-status/qa-gate.d.ts +1 -1
- package/dist/tools/update-status/qa-gate.js +2 -2
- package/dist/tools/update-status/side-effects.js +30 -37
- package/dist/tools/update-status/transition-guard.d.ts +4 -2
- package/dist/tools/update-status/transition-guard.js +57 -10
- package/dist/tools/update-status-convention-gate.js +24 -23
- package/dist/tools/update-status-reconcile.js +2 -2
- package/dist/tools/validate-api-contract-handler.js +3 -3
- package/dist/tools/validate-lint.js +20 -13
- package/dist/tools/validate.d.ts +3 -1
- package/dist/tools/validate.js +213 -5
- package/dist/transports/http-transport.js +84 -61
- package/dist/transports/middleware/with-telemetry.js +3 -2
- package/dist/types/abortable-process.d.ts +2 -0
- package/dist/types/advanced-framework.js +0 -2
- package/dist/types/atomic-upgrade.d.ts +71 -0
- package/dist/types/atomic-upgrade.js +2 -0
- package/dist/types/ci.js +0 -2
- package/dist/types/core-bridge.d.ts +78 -1
- package/dist/types/crash-shield-framework-rules.d.ts +24 -0
- package/dist/types/crash-shield-framework-rules.js +2 -0
- package/dist/types/data-gc.d.ts +16 -0
- package/dist/types/deploy.js +0 -2
- package/dist/types/durable-job.d.ts +78 -0
- package/dist/types/durable-job.js +2 -0
- package/dist/types/durable-validation.d.ts +60 -0
- package/dist/types/durable-validation.js +2 -0
- package/dist/types/estimation.d.ts +2 -0
- package/dist/types/evidence-gates.d.ts +9 -1
- package/dist/types/execution.d.ts +43 -0
- package/dist/types/handoff-artifacts.d.ts +2 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/infrastructure.js +0 -2
- package/dist/types/lifecycle.js +0 -2
- package/dist/types/migration/canonical-storage.d.ts +37 -0
- package/dist/types/migration/canonical-storage.js +2 -0
- package/dist/types/migration/index.d.ts +1 -1
- package/dist/types/native-worker.d.ts +48 -0
- package/dist/types/native-worker.js +2 -0
- package/dist/types/network-policy.d.ts +12 -0
- package/dist/types/network-policy.js +2 -0
- package/dist/types/oauth.js +0 -2
- package/dist/types/observability.d.ts +32 -0
- package/dist/types/outbox-worker.d.ts +35 -0
- package/dist/types/outbox-worker.js +11 -0
- package/dist/types/permissions-config.d.ts +0 -27
- package/dist/types/permissions-config.js +0 -2
- package/dist/types/plugin-install.d.ts +0 -11
- package/dist/types/plugin-install.js +0 -2
- package/dist/types/portal.d.ts +1 -0
- package/dist/types/product-public.d.ts +75 -0
- package/dist/types/product-public.js +2 -0
- package/dist/types/project/inputs.d.ts +2 -0
- package/dist/types/project/mfe-detection.js +0 -2
- package/dist/types/project/platform-mobile.js +0 -2
- package/dist/types/project/platform-specialty.js +0 -2
- package/dist/types/project-knowledge-graph.d.ts +7 -0
- package/dist/types/runtime-database.d.ts +10 -0
- package/dist/types/runtime-database.js +2 -0
- package/dist/types/runtime-policy.d.ts +40 -0
- package/dist/types/runtime-policy.js +2 -0
- package/dist/types/safety.d.ts +4 -5
- package/dist/types/schema-registry.d.ts +12 -0
- package/dist/types/schema-registry.js +2 -0
- package/dist/types/security.d.ts +52 -0
- package/dist/types/skill-registry.js +0 -2
- package/dist/types/spec/inputs.d.ts +2 -0
- package/dist/types/spec-lock-v2.d.ts +13 -7
- package/dist/types/spec-lock-v2.js +1 -1
- package/dist/types/spec-registry.js +0 -2
- package/dist/types/storage-bundle.d.ts +13 -0
- package/dist/types/storage-bundle.js +2 -0
- package/dist/types/storage-catalog.d.ts +18 -0
- package/dist/types/storage-catalog.js +2 -0
- package/dist/types/team-planner.js +0 -2
- package/dist/types/technology-registry.d.ts +35 -0
- package/dist/types/technology-registry.js +2 -0
- package/dist/types/technology-symbols.generated.d.ts +117 -0
- package/dist/types/technology-symbols.generated.js +2 -0
- package/dist/types/telemetry.d.ts +3 -3
- package/dist/types/transport.d.ts +2 -0
- package/dist/types/validate-worker.d.ts +44 -0
- package/dist/types/validate-worker.js +2 -0
- package/dist/types/validation-evidence.d.ts +1 -1
- package/dist/types/validation-receipt.d.ts +104 -0
- package/dist/types/validation-receipt.js +2 -0
- package/package.json +31 -20
- package/planu-native.json +1 -1
- package/planu-plugin.json +1 -1
- package/dist/engine/telemetry/geo-resolver.d.ts +0 -9
- package/dist/engine/telemetry/geo-resolver.js +0 -43
- package/dist/storage/data-dir-discovery.d.ts +0 -31
- package/dist/storage/data-dir-discovery.js +0 -140
- package/dist/storage/migrations/cwd-to-absolute.d.ts +0 -25
- package/dist/storage/migrations/cwd-to-absolute.js +0 -281
- package/dist/tools/create-spec/adapters/prior-decisions-hint.d.ts +0 -14
- package/dist/tools/create-spec/adapters/prior-decisions-hint.js +0 -30
- package/dist/tools/init-project/ancestor-data-detector.d.ts +0 -22
- package/dist/tools/init-project/ancestor-data-detector.js +0 -81
- package/dist/tools/update-status/force-done-audit.d.ts +0 -2
- package/dist/tools/update-status/force-done-audit.js +0 -23
- package/dist/types/migration/cwd-to-absolute.d.ts +0 -8
- package/dist/types/migration/cwd-to-absolute.js +0 -3
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { readFile, rm } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute } from 'node:path';
|
|
3
|
+
import { atomicWriteFile } from '../safety/atomic-write-file.js';
|
|
4
|
+
import { readInstallationManifest, } from '../../cli/commands/install.js';
|
|
5
|
+
import { buildPinnedEntry } from './config-patcher.js';
|
|
6
|
+
import { stageAndVerifyRelease } from './release-verifier.js';
|
|
7
|
+
import { assertVersionNotQuarantined, markUpgradeVerified, quarantineUpgradeVersion, readUpgradeTrustState, upgradeTrustStatePath, } from './upgrade-trust-state.js';
|
|
8
|
+
import { withUpgradeLock } from './upgrade-lock.js';
|
|
9
|
+
import { redactFailureMessage, reportClassifiedDegradation, } from '../../errors/classified-degradation.js';
|
|
10
|
+
const PACKAGE_PREFIX = '@planu/cli@';
|
|
11
|
+
const EXACT_VERSION = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
12
|
+
export class UpgradeInterruptionError extends Error {
|
|
13
|
+
constructor(message = 'Simulated process interruption during upgrade') {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'UpgradeInterruptionError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function upgradeJournalPath(manifestPath) {
|
|
19
|
+
return `${manifestPath}.upgrade-journal.json`;
|
|
20
|
+
}
|
|
21
|
+
// eslint-disable-next-line complexity -- every persisted journal field is fail-closed
|
|
22
|
+
function parseJournal(raw, manifestPath) {
|
|
23
|
+
const parsed = JSON.parse(raw);
|
|
24
|
+
const adapterPaths = parsed.adapters?.map((item) => item.configPath) ?? [];
|
|
25
|
+
if (parsed.schemaVersion !== 2 ||
|
|
26
|
+
!['prepared', 'switching', 'trust-switched', 'committed'].includes(parsed.state ?? '') ||
|
|
27
|
+
parsed.manifestPath !== manifestPath ||
|
|
28
|
+
!EXACT_VERSION.test(parsed.previousVersion ?? '') ||
|
|
29
|
+
!EXACT_VERSION.test(parsed.targetVersion ?? '') ||
|
|
30
|
+
typeof parsed.originalManifest !== 'string' ||
|
|
31
|
+
parsed.trustStatePath !== upgradeTrustStatePath(manifestPath) ||
|
|
32
|
+
(parsed.originalTrustState !== null && typeof parsed.originalTrustState !== 'string') ||
|
|
33
|
+
!Array.isArray(parsed.adapters) ||
|
|
34
|
+
parsed.adapters.some((item) => !isAbsolute(item.configPath) || typeof item.original !== 'string') ||
|
|
35
|
+
new Set(adapterPaths).size !== adapterPaths.length ||
|
|
36
|
+
!Array.isArray(parsed.switchedPaths) ||
|
|
37
|
+
parsed.switchedPaths.some((path) => !adapterPaths.includes(path)) ||
|
|
38
|
+
typeof parsed.updatedAt !== 'string') {
|
|
39
|
+
throw new Error('[Planu upgrade] Persisted upgrade journal is unsafe or corrupt');
|
|
40
|
+
}
|
|
41
|
+
return parsed;
|
|
42
|
+
}
|
|
43
|
+
async function writeJournal(path, journal, writeFile) {
|
|
44
|
+
await writeFile(path, `${JSON.stringify(journal, null, 2)}\n`);
|
|
45
|
+
}
|
|
46
|
+
async function readUpgradeFile(path, code, message) {
|
|
47
|
+
try {
|
|
48
|
+
return await readFile(path, 'utf8');
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
/* reliability-optional: UPGRADE_FILE_READ_FAILED */
|
|
52
|
+
reportClassifiedDegradation(code, error);
|
|
53
|
+
throw new Error(message, { cause: error });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function recoverInterruptedUpgradeLocked(manifestPath, assertFence, dependencies = {}) {
|
|
57
|
+
const path = upgradeJournalPath(manifestPath);
|
|
58
|
+
const raw = await readFile(path, 'utf8').catch((error) => {
|
|
59
|
+
if (error.code === 'ENOENT') {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
/* reliability-optional: UPGRADE_JOURNAL_READ_FAILED */
|
|
63
|
+
reportClassifiedDegradation('UPGRADE_JOURNAL_READ_FAILED', error);
|
|
64
|
+
throw new Error('[Planu upgrade] Persisted upgrade journal is unreadable');
|
|
65
|
+
});
|
|
66
|
+
if (raw === null) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const journal = parseJournal(raw, manifestPath);
|
|
70
|
+
if (journal.state === 'committed') {
|
|
71
|
+
await assertFence();
|
|
72
|
+
await rm(path, { force: true });
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const writeFile = dependencies.writeFile ??
|
|
76
|
+
((target, content) => atomicWriteFile(target, content, { mode: 0o600 }));
|
|
77
|
+
for (const adapter of journal.adapters) {
|
|
78
|
+
await assertFence();
|
|
79
|
+
await writeFile(adapter.configPath, adapter.original);
|
|
80
|
+
}
|
|
81
|
+
await assertFence();
|
|
82
|
+
await writeFile(manifestPath, journal.originalManifest);
|
|
83
|
+
await assertFence();
|
|
84
|
+
if (journal.originalTrustState === null) {
|
|
85
|
+
await rm(journal.trustStatePath, { force: true });
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
await writeFile(journal.trustStatePath, journal.originalTrustState);
|
|
89
|
+
}
|
|
90
|
+
await rm(path, { force: true });
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
export async function recoverInterruptedUpgrade(manifestPath, dependencies = {}) {
|
|
94
|
+
return withUpgradeLock(manifestPath, (assertFence) => recoverInterruptedUpgradeLocked(manifestPath, assertFence, dependencies));
|
|
95
|
+
}
|
|
96
|
+
function exactConfiguredVersion(record, config) {
|
|
97
|
+
if (typeof config !== 'object' || config === null || Array.isArray(config)) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const root = config;
|
|
101
|
+
let command;
|
|
102
|
+
let args;
|
|
103
|
+
if (record.format === 'zed') {
|
|
104
|
+
const servers = root.context_servers;
|
|
105
|
+
const planu = servers?.planu;
|
|
106
|
+
const commandEntry = planu?.command;
|
|
107
|
+
command = commandEntry?.path;
|
|
108
|
+
args = commandEntry?.args;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const servers = root.mcpServers;
|
|
112
|
+
const planu = servers?.planu;
|
|
113
|
+
command = planu?.command;
|
|
114
|
+
args = planu?.args;
|
|
115
|
+
}
|
|
116
|
+
if (command !== 'npx' || !Array.isArray(args)) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const packageArgs = args.filter((arg) => typeof arg === 'string' && arg.startsWith(PACKAGE_PREFIX));
|
|
120
|
+
return packageArgs.length === 1 ? (packageArgs[0]?.slice(PACKAGE_PREFIX.length) ?? null) : null;
|
|
121
|
+
}
|
|
122
|
+
function buildUpdatedConfig(record, raw, version) {
|
|
123
|
+
let parsed;
|
|
124
|
+
try {
|
|
125
|
+
parsed = JSON.parse(raw);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
throw new Error('[Planu upgrade] An inventoried adapter contains invalid JSON', {
|
|
129
|
+
cause: error,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (exactConfiguredVersion(record, parsed) !== record.version) {
|
|
133
|
+
throw new Error('[Planu upgrade] An inventoried adapter no longer matches the verified inventory version');
|
|
134
|
+
}
|
|
135
|
+
const root = parsed;
|
|
136
|
+
const entry = buildPinnedEntry(version);
|
|
137
|
+
if (record.format === 'zed') {
|
|
138
|
+
const servers = root.context_servers ?? {};
|
|
139
|
+
root.context_servers = {
|
|
140
|
+
...servers,
|
|
141
|
+
planu: { command: { path: entry.command, args: entry.args } },
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
const servers = root.mcpServers ?? {};
|
|
146
|
+
root.mcpServers = { ...servers, planu: entry };
|
|
147
|
+
}
|
|
148
|
+
return `${JSON.stringify(root, null, 2)}\n`;
|
|
149
|
+
}
|
|
150
|
+
async function prepareAdapters(installations, version) {
|
|
151
|
+
const seen = new Set();
|
|
152
|
+
const prepared = [];
|
|
153
|
+
for (const record of installations) {
|
|
154
|
+
if (seen.has(record.configPath)) {
|
|
155
|
+
throw new Error('[Planu upgrade] Installation inventory contains a duplicate adapter');
|
|
156
|
+
}
|
|
157
|
+
seen.add(record.configPath);
|
|
158
|
+
const original = await readUpgradeFile(record.configPath, 'UPGRADE_ADAPTER_READ_FAILED', '[Planu upgrade] An inventoried adapter is unreadable');
|
|
159
|
+
prepared.push({ record, original, updated: buildUpdatedConfig(record, original, version) });
|
|
160
|
+
}
|
|
161
|
+
return prepared;
|
|
162
|
+
}
|
|
163
|
+
async function inject(dependencies, context) {
|
|
164
|
+
await dependencies.faultInjector?.(context);
|
|
165
|
+
}
|
|
166
|
+
async function rollback(prepared, manifestPath, originalManifest, trustStatePath, originalTrustState, writeFile, assertFence) {
|
|
167
|
+
const failures = [];
|
|
168
|
+
for (const adapter of prepared) {
|
|
169
|
+
try {
|
|
170
|
+
await writeFile(adapter.record.configPath, adapter.original);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
/* reliability-cleanup: ADAPTER_ROLLBACK_FAILURE — aggregate failure throws below */
|
|
174
|
+
reportClassifiedDegradation('ADAPTER_ROLLBACK_FAILURE', error);
|
|
175
|
+
failures.push(`adapter rollback: ${redactFailureMessage(error)}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
await writeFile(manifestPath, originalManifest);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
/* reliability-cleanup: MANIFEST_ROLLBACK_FAILURE — aggregate failure throws below */
|
|
183
|
+
reportClassifiedDegradation('MANIFEST_ROLLBACK_FAILURE', error);
|
|
184
|
+
failures.push(`manifest rollback: ${redactFailureMessage(error)}`);
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
if (originalTrustState === null) {
|
|
188
|
+
await assertFence();
|
|
189
|
+
await rm(trustStatePath, { force: true });
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
await writeFile(trustStatePath, originalTrustState);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
/* reliability-cleanup: TRUST_ROLLBACK_FAILURE — aggregate failure throws below */
|
|
197
|
+
reportClassifiedDegradation('TRUST_ROLLBACK_FAILURE', error);
|
|
198
|
+
failures.push(`trust rollback: ${redactFailureMessage(error)}`);
|
|
199
|
+
}
|
|
200
|
+
if (failures.length > 0) {
|
|
201
|
+
throw new Error(`Global rollback was incomplete: ${failures.join('; ')}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// eslint-disable-next-line max-lines-per-function -- one ordered transaction keeps journal and rollback phases auditable
|
|
205
|
+
async function upgradeInventoriedAdaptersLocked(manifestPath, version, dependencies, assertFence) {
|
|
206
|
+
if (!EXACT_VERSION.test(version)) {
|
|
207
|
+
throw new Error(`Upgrade target must be an exact semantic version: ${version}`);
|
|
208
|
+
}
|
|
209
|
+
await recoverInterruptedUpgradeLocked(manifestPath, assertFence, dependencies);
|
|
210
|
+
const originalManifest = await readUpgradeFile(manifestPath, 'UPGRADE_MANIFEST_READ_FAILED', '[Planu upgrade] Installation inventory is unreadable');
|
|
211
|
+
const trustPath = upgradeTrustStatePath(manifestPath);
|
|
212
|
+
const originalTrustState = await readFile(trustPath, 'utf8').catch((error) => {
|
|
213
|
+
if (error.code === 'ENOENT') {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
/* reliability-optional: UPGRADE_TRUST_READ_FAILED */
|
|
217
|
+
reportClassifiedDegradation('UPGRADE_TRUST_READ_FAILED', error);
|
|
218
|
+
throw new Error('[Planu upgrade] Last-known-good trust state is unreadable');
|
|
219
|
+
});
|
|
220
|
+
let manifest;
|
|
221
|
+
try {
|
|
222
|
+
manifest = readInstallationManifest(manifestPath);
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
/* reliability-optional: UPGRADE_MANIFEST_PARSE_FAILED */
|
|
226
|
+
reportClassifiedDegradation('UPGRADE_MANIFEST_PARSE_FAILED', error);
|
|
227
|
+
throw new Error('[Planu upgrade] Installation inventory is invalid', {
|
|
228
|
+
cause: error,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
if (manifest.installations.length === 0) {
|
|
232
|
+
throw new Error('Cannot upgrade: installation inventory is empty.');
|
|
233
|
+
}
|
|
234
|
+
const versions = new Set(manifest.installations.map((record) => record.version));
|
|
235
|
+
if (versions.size !== 1) {
|
|
236
|
+
throw new Error('Cannot establish a single previously verified version from the inventory.');
|
|
237
|
+
}
|
|
238
|
+
const previousVersion = manifest.installations[0]?.version;
|
|
239
|
+
if (previousVersion === undefined || !EXACT_VERSION.test(previousVersion)) {
|
|
240
|
+
throw new Error('Cannot establish the previously verified version.');
|
|
241
|
+
}
|
|
242
|
+
const trustState = await readUpgradeTrustState(manifestPath);
|
|
243
|
+
if (trustState !== null && trustState.lastKnownGoodVersion !== previousVersion) {
|
|
244
|
+
throw new Error(`Cannot upgrade: inventory ${previousVersion} differs from last-known-good ${trustState.lastKnownGoodVersion}.`);
|
|
245
|
+
}
|
|
246
|
+
assertVersionNotQuarantined(trustState, version);
|
|
247
|
+
const prepared = await prepareAdapters(manifest.installations, version);
|
|
248
|
+
const now = dependencies.now ?? (() => new Date());
|
|
249
|
+
let verification;
|
|
250
|
+
try {
|
|
251
|
+
verification = await (dependencies.stageAndVerify ?? stageAndVerifyRelease)(version);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
await assertFence();
|
|
255
|
+
await quarantineUpgradeVersion(manifestPath, previousVersion, version, 'verification-failed', now());
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
if (verification.version !== version) {
|
|
259
|
+
await assertFence();
|
|
260
|
+
await quarantineUpgradeVersion(manifestPath, previousVersion, version, 'verification-failed', now());
|
|
261
|
+
throw new Error(`Release verifier returned ${verification.version}; expected exact target ${version}.`);
|
|
262
|
+
}
|
|
263
|
+
await inject(dependencies, { phase: 'after-runtime-verification', switchedAdapters: 0 });
|
|
264
|
+
const writeFile = dependencies.writeFile ??
|
|
265
|
+
((path, content) => atomicWriteFile(path, content, { mode: 0o600 }));
|
|
266
|
+
const fencedWriteFile = async (path, content) => {
|
|
267
|
+
await assertFence();
|
|
268
|
+
await writeFile(path, content);
|
|
269
|
+
};
|
|
270
|
+
let switchedAdapters = 0;
|
|
271
|
+
const journalPath = upgradeJournalPath(manifestPath);
|
|
272
|
+
let journal = {
|
|
273
|
+
schemaVersion: 2,
|
|
274
|
+
state: 'prepared',
|
|
275
|
+
manifestPath,
|
|
276
|
+
previousVersion,
|
|
277
|
+
targetVersion: version,
|
|
278
|
+
originalManifest,
|
|
279
|
+
trustStatePath: trustPath,
|
|
280
|
+
originalTrustState,
|
|
281
|
+
adapters: prepared.map((adapter) => ({
|
|
282
|
+
configPath: adapter.record.configPath,
|
|
283
|
+
original: adapter.original,
|
|
284
|
+
})),
|
|
285
|
+
switchedPaths: [],
|
|
286
|
+
updatedAt: now().toISOString(),
|
|
287
|
+
};
|
|
288
|
+
await writeJournal(journalPath, journal, fencedWriteFile);
|
|
289
|
+
try {
|
|
290
|
+
for (const adapter of prepared) {
|
|
291
|
+
await inject(dependencies, {
|
|
292
|
+
phase: 'before-adapter-switch',
|
|
293
|
+
adapter: adapter.record,
|
|
294
|
+
switchedAdapters,
|
|
295
|
+
});
|
|
296
|
+
await fencedWriteFile(adapter.record.configPath, adapter.updated);
|
|
297
|
+
switchedAdapters += 1;
|
|
298
|
+
journal = {
|
|
299
|
+
...journal,
|
|
300
|
+
state: 'switching',
|
|
301
|
+
switchedPaths: [...journal.switchedPaths, adapter.record.configPath],
|
|
302
|
+
updatedAt: now().toISOString(),
|
|
303
|
+
};
|
|
304
|
+
await writeJournal(journalPath, journal, fencedWriteFile);
|
|
305
|
+
await inject(dependencies, {
|
|
306
|
+
phase: 'after-adapter-switch',
|
|
307
|
+
adapter: adapter.record,
|
|
308
|
+
switchedAdapters,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
await inject(dependencies, { phase: 'before-manifest-switch', switchedAdapters });
|
|
312
|
+
const installedAt = now().toISOString();
|
|
313
|
+
const updatedManifest = {
|
|
314
|
+
...manifest,
|
|
315
|
+
updatedAt: installedAt,
|
|
316
|
+
installations: manifest.installations.map((record) => ({
|
|
317
|
+
...record,
|
|
318
|
+
version,
|
|
319
|
+
offline: false,
|
|
320
|
+
installedAt,
|
|
321
|
+
})),
|
|
322
|
+
};
|
|
323
|
+
await fencedWriteFile(manifestPath, `${JSON.stringify(updatedManifest, null, 2)}\n`);
|
|
324
|
+
await inject(dependencies, { phase: 'after-manifest-switch', switchedAdapters });
|
|
325
|
+
await assertFence();
|
|
326
|
+
await markUpgradeVerified(manifestPath, version, verification.verifiedAt);
|
|
327
|
+
journal = {
|
|
328
|
+
...journal,
|
|
329
|
+
state: 'trust-switched',
|
|
330
|
+
updatedAt: installedAt,
|
|
331
|
+
};
|
|
332
|
+
await writeJournal(journalPath, journal, fencedWriteFile);
|
|
333
|
+
await inject(dependencies, { phase: 'after-trust-switch', switchedAdapters });
|
|
334
|
+
journal = {
|
|
335
|
+
...journal,
|
|
336
|
+
state: 'committed',
|
|
337
|
+
updatedAt: installedAt,
|
|
338
|
+
};
|
|
339
|
+
await writeJournal(journalPath, journal, fencedWriteFile);
|
|
340
|
+
await assertFence();
|
|
341
|
+
await rm(journalPath, { force: true });
|
|
342
|
+
return {
|
|
343
|
+
previousVersion,
|
|
344
|
+
version,
|
|
345
|
+
switchedAdapters,
|
|
346
|
+
manifest: updatedManifest,
|
|
347
|
+
verification,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
if (error instanceof UpgradeInterruptionError) {
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
await rollback(prepared, manifestPath, originalManifest, trustPath, originalTrustState, fencedWriteFile, assertFence);
|
|
356
|
+
await assertFence();
|
|
357
|
+
await rm(journalPath, { force: true });
|
|
358
|
+
}
|
|
359
|
+
catch (rollbackError) {
|
|
360
|
+
/* reliability-cleanup: UPGRADE_ROLLBACK_INCOMPLETE */
|
|
361
|
+
reportClassifiedDegradation('UPGRADE_ROLLBACK_INCOMPLETE', rollbackError);
|
|
362
|
+
throw new AggregateError([new Error(redactFailureMessage(error)), new Error(redactFailureMessage(rollbackError))], `Upgrade to ${version} failed and global rollback was incomplete.`, { cause: rollbackError });
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
await assertFence();
|
|
366
|
+
await quarantineUpgradeVersion(manifestPath, previousVersion, version, 'activation-failed', now());
|
|
367
|
+
}
|
|
368
|
+
catch (quarantineError) {
|
|
369
|
+
/* reliability-cleanup: UPGRADE_QUARANTINE_FAILED */
|
|
370
|
+
reportClassifiedDegradation('UPGRADE_QUARANTINE_FAILED', quarantineError);
|
|
371
|
+
throw new AggregateError([new Error(redactFailureMessage(error)), new Error(redactFailureMessage(quarantineError))], `Upgrade to ${version} rolled back but quarantine persistence failed.`, { cause: quarantineError });
|
|
372
|
+
}
|
|
373
|
+
reportClassifiedDegradation('UPGRADE_ACTIVATION_FAILED', error);
|
|
374
|
+
const symptom = new Error(`Upgrade to ${version} failed; all adapters restored to ${previousVersion}.`);
|
|
375
|
+
throw symptom;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
export async function upgradeInventoriedAdapters(manifestPath, version, dependencies = {}) {
|
|
379
|
+
return withUpgradeLock(manifestPath, (assertFence) => upgradeInventoriedAdaptersLocked(manifestPath, version, dependencies, assertFence));
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=atomic-upgrade.js.map
|
|
@@ -5,6 +5,7 @@ import { readFile } from 'node:fs/promises';
|
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { PLANU_VERSION } from '../../config/version.js';
|
|
8
|
+
import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
9
10
|
// Config path resolution
|
|
10
11
|
// ---------------------------------------------------------------------------
|
|
@@ -34,8 +35,11 @@ export async function findMcpConfig() {
|
|
|
34
35
|
await readFile(candidate.path, 'utf-8');
|
|
35
36
|
return { configPath: candidate.path, configType: candidate.type };
|
|
36
37
|
}
|
|
37
|
-
catch {
|
|
38
|
-
|
|
38
|
+
catch (error) {
|
|
39
|
+
/* reliability-optional: MCP_CONFIG_CANDIDATE_UNREADABLE */
|
|
40
|
+
if (error.code !== 'ENOENT') {
|
|
41
|
+
reportClassifiedDegradation('MCP_CONFIG_CANDIDATE_UNREADABLE', error);
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
return { configPath: null, configType: null };
|
|
@@ -84,7 +88,9 @@ export async function detectPlanuInstall() {
|
|
|
84
88
|
const raw = await readFile(location.configPath, 'utf-8');
|
|
85
89
|
config = JSON.parse(raw);
|
|
86
90
|
}
|
|
87
|
-
catch {
|
|
91
|
+
catch (error) {
|
|
92
|
+
/* reliability-optional: MCP_CONFIG_PARSE_FAILED */
|
|
93
|
+
reportClassifiedDegradation('MCP_CONFIG_PARSE_FAILED', error);
|
|
88
94
|
return {
|
|
89
95
|
method: 'unknown',
|
|
90
96
|
currentVersion: PLANU_VERSION,
|
|
@@ -14,10 +14,6 @@ export declare function patchPlanuEntry(configPath: string, newEntry: McpServerE
|
|
|
14
14
|
backupPath: string;
|
|
15
15
|
previousEntry: McpServerEntry | null;
|
|
16
16
|
}>;
|
|
17
|
-
/**
|
|
18
|
-
* Returns the standard npx @latest entry for Planu.
|
|
19
|
-
*/
|
|
20
|
-
export declare function buildNpxLatestEntry(): McpServerEntry;
|
|
21
17
|
/**
|
|
22
18
|
* Returns an npx entry pinned to a specific version.
|
|
23
19
|
*/
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
// engine/auto-updater/config-patcher.ts — Patches the MCP config file to enable auto-update.
|
|
3
3
|
// SPEC-443
|
|
4
4
|
// Creates a backup before any modification. Restores backup on write failure.
|
|
5
|
-
import { readFile
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
7
|
+
import { atomicWriteFile } from '../safety/atomic-write-file.js';
|
|
6
8
|
export const PLANU_MCP_STARTUP_TIMEOUT_SEC = 120;
|
|
7
9
|
// ---------------------------------------------------------------------------
|
|
8
10
|
// Helpers
|
|
@@ -11,7 +13,7 @@ function dateStr() {
|
|
|
11
13
|
return new Date().toISOString().slice(0, 10);
|
|
12
14
|
}
|
|
13
15
|
function backupPathFor(configPath) {
|
|
14
|
-
return configPath.replace(/\.json$/, `.backup-${dateStr()}.json`);
|
|
16
|
+
return configPath.replace(/\.json$/, `.backup-${dateStr()}-${randomUUID()}.json`);
|
|
15
17
|
}
|
|
16
18
|
// ---------------------------------------------------------------------------
|
|
17
19
|
// Patch operations
|
|
@@ -39,7 +41,7 @@ export async function patchPlanuEntry(configPath, newEntry) {
|
|
|
39
41
|
const previousEntry = config.mcpServers?.planu ?? null;
|
|
40
42
|
// Create backup BEFORE modifying anything
|
|
41
43
|
const backupPath = backupPathFor(configPath);
|
|
42
|
-
await
|
|
44
|
+
await atomicWriteFile(backupPath, raw, { mode: 0o600 });
|
|
43
45
|
// Patch
|
|
44
46
|
const updated = {
|
|
45
47
|
...config,
|
|
@@ -49,29 +51,22 @@ export async function patchPlanuEntry(configPath, newEntry) {
|
|
|
49
51
|
},
|
|
50
52
|
};
|
|
51
53
|
try {
|
|
52
|
-
await
|
|
54
|
+
await atomicWriteFile(configPath, JSON.stringify(updated, null, 2) + '\n', { mode: 0o600 });
|
|
53
55
|
}
|
|
54
56
|
catch (writeErr) {
|
|
55
57
|
// Restore from backup
|
|
56
|
-
await
|
|
58
|
+
await atomicWriteFile(configPath, raw, { mode: 0o600 });
|
|
57
59
|
throw new Error(`Failed to write updated config to ${configPath}. Restored original from backup. Error: ${String(writeErr)}`, { cause: writeErr });
|
|
58
60
|
}
|
|
59
61
|
return { backupPath, previousEntry };
|
|
60
62
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Returns the standard npx @latest entry for Planu.
|
|
63
|
-
*/
|
|
64
|
-
export function buildNpxLatestEntry() {
|
|
65
|
-
return {
|
|
66
|
-
command: 'npx',
|
|
67
|
-
args: ['-y', '@planu/cli@latest'],
|
|
68
|
-
startup_timeout_sec: PLANU_MCP_STARTUP_TIMEOUT_SEC,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
63
|
/**
|
|
72
64
|
* Returns an npx entry pinned to a specific version.
|
|
73
65
|
*/
|
|
74
66
|
export function buildPinnedEntry(version) {
|
|
67
|
+
if (!/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/.test(version)) {
|
|
68
|
+
throw new Error(`[Planu] Refusing non-exact CLI version: ${version}`);
|
|
69
|
+
}
|
|
75
70
|
return {
|
|
76
71
|
command: 'npx',
|
|
77
72
|
args: ['-y', `@planu/cli@${version}`],
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { EnableAutoUpdateResult, PinVersionResult, UpdateCheckResult } from '../../types/auto-update.js';
|
|
2
|
+
export { upgradeInventoriedAdapters } from './atomic-upgrade.js';
|
|
3
|
+
export { stageAndVerifyRelease } from './release-verifier.js';
|
|
2
4
|
/**
|
|
3
5
|
* Checks the current install info and npm registry for update availability.
|
|
4
6
|
*/
|
|
5
7
|
export declare function checkForUpdates(): Promise<UpdateCheckResult>;
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
9
|
+
* Resolves a verified release and pins the MCP config to that exact version.
|
|
8
10
|
* If confirm is false (default), returns a preview of changes without applying.
|
|
9
11
|
* If confirm is true, applies the change immediately.
|
|
10
12
|
*/
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
// engine/auto-updater/index.ts — Public API for the auto-updater engine.
|
|
2
2
|
// SPEC-443
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
3
4
|
import { detectPlanuInstall } from './config-detector.js';
|
|
4
|
-
import {
|
|
5
|
+
import { buildPinnedEntry } from './config-patcher.js';
|
|
5
6
|
import { fetchLatestVersion } from './npm-registry.js';
|
|
6
7
|
import { PLANU_VERSION } from '../../config/version.js';
|
|
8
|
+
import { resolveStorageLayout } from '../../storage/storage-layout.js';
|
|
9
|
+
import { upgradeInventoriedAdapters } from './atomic-upgrade.js';
|
|
10
|
+
export { upgradeInventoriedAdapters } from './atomic-upgrade.js';
|
|
11
|
+
export { stageAndVerifyRelease } from './release-verifier.js';
|
|
7
12
|
// ---------------------------------------------------------------------------
|
|
8
13
|
// check_update_status
|
|
9
14
|
// ---------------------------------------------------------------------------
|
|
@@ -16,20 +21,21 @@ export async function checkForUpdates() {
|
|
|
16
21
|
fetchLatestVersion(),
|
|
17
22
|
]);
|
|
18
23
|
const isUpToDate = latestVersion === null ? true : latestVersion === installInfo.currentVersion;
|
|
19
|
-
|
|
24
|
+
// Legacy @latest entries are detected but never considered a safe active mode.
|
|
25
|
+
const autoUpdateActive = false;
|
|
20
26
|
let updateCommand;
|
|
21
|
-
if (
|
|
27
|
+
if (installInfo.method === 'npx-latest') {
|
|
22
28
|
updateCommand =
|
|
23
|
-
'
|
|
29
|
+
'Legacy unpinned entry detected; run enable_auto_update to pin an exact release.';
|
|
24
30
|
}
|
|
25
31
|
else if (installInfo.method === 'global') {
|
|
26
|
-
updateCommand =
|
|
32
|
+
updateCommand = `npm install -g @planu/cli@${latestVersion ?? PLANU_VERSION}`;
|
|
27
33
|
}
|
|
28
34
|
else if (installInfo.method === 'local-path') {
|
|
29
35
|
updateCommand = 'Update your local installation and rebuild.';
|
|
30
36
|
}
|
|
31
37
|
else {
|
|
32
|
-
updateCommand = 'Run enable_auto_update to
|
|
38
|
+
updateCommand = 'Run enable_auto_update to resolve and pin the latest verified version.';
|
|
33
39
|
}
|
|
34
40
|
return {
|
|
35
41
|
currentVersion: installInfo.currentVersion,
|
|
@@ -44,11 +50,19 @@ export async function checkForUpdates() {
|
|
|
44
50
|
// enable_auto_update
|
|
45
51
|
// ---------------------------------------------------------------------------
|
|
46
52
|
/**
|
|
47
|
-
*
|
|
53
|
+
* Resolves a verified release and pins the MCP config to that exact version.
|
|
48
54
|
* If confirm is false (default), returns a preview of changes without applying.
|
|
49
55
|
* If confirm is true, applies the change immediately.
|
|
50
56
|
*/
|
|
51
57
|
export async function enableAutoUpdate(confirm, overrideConfigPath) {
|
|
58
|
+
if (process.env.PLANU_OFFLINE === '1') {
|
|
59
|
+
throw new Error('Auto-update is unavailable while PLANU_OFFLINE=1. Pin an installed version.');
|
|
60
|
+
}
|
|
61
|
+
const latestVersion = await fetchLatestVersion();
|
|
62
|
+
if (latestVersion === null) {
|
|
63
|
+
throw new Error('Could not resolve an exact Planu version; no config changes were made.');
|
|
64
|
+
}
|
|
65
|
+
const resolvedEntry = buildPinnedEntry(latestVersion);
|
|
52
66
|
let installInfo;
|
|
53
67
|
if (overrideConfigPath !== undefined) {
|
|
54
68
|
// Build a minimal install info using the override path
|
|
@@ -62,21 +76,11 @@ export async function enableAutoUpdate(confirm, overrideConfigPath) {
|
|
|
62
76
|
else {
|
|
63
77
|
installInfo = await detectPlanuInstall();
|
|
64
78
|
}
|
|
65
|
-
if (installInfo.method === 'npx-latest') {
|
|
66
|
-
return {
|
|
67
|
-
configPath: installInfo.configPath ?? '(unknown)',
|
|
68
|
-
previousEntry: installInfo.mcpEntry,
|
|
69
|
-
newEntry: buildNpxLatestEntry(),
|
|
70
|
-
backupPath: '',
|
|
71
|
-
alreadyOptimal: true,
|
|
72
|
-
message: 'Auto-update is already active. Planu uses npx @planu/cli@latest — it updates automatically on each Claude session start.',
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
79
|
if (installInfo.configPath === null) {
|
|
76
80
|
throw new Error('Could not find MCP config file (~/.claude.json or Claude Desktop config). ' +
|
|
77
81
|
'Please specify the path manually using the configPath parameter.');
|
|
78
82
|
}
|
|
79
|
-
const newEntry =
|
|
83
|
+
const newEntry = resolvedEntry;
|
|
80
84
|
if (!confirm) {
|
|
81
85
|
return {
|
|
82
86
|
configPath: installInfo.configPath,
|
|
@@ -85,20 +89,27 @@ export async function enableAutoUpdate(confirm, overrideConfigPath) {
|
|
|
85
89
|
backupPath: '',
|
|
86
90
|
alreadyOptimal: false,
|
|
87
91
|
message: `Preview: The planu entry in ${installInfo.configPath} will be updated to use ` +
|
|
88
|
-
`"command": "npx", "args": ["-y", "@planu/cli
|
|
92
|
+
`"command": "npx", "args": ["-y", "@planu/cli@${latestVersion}"]. ` +
|
|
89
93
|
'Call enable_auto_update with confirm=true to apply.',
|
|
90
94
|
};
|
|
91
95
|
}
|
|
92
|
-
|
|
96
|
+
if (overrideConfigPath !== undefined) {
|
|
97
|
+
throw new Error('Direct config-path updates are not recoverable. Run planu install to inventory the adapter first.');
|
|
98
|
+
}
|
|
99
|
+
const manifestPath = resolveStorageLayout().installationManifest;
|
|
100
|
+
if (!existsSync(manifestPath)) {
|
|
101
|
+
throw new Error('Auto-update requires an installation inventory and last-known-good rollback target. Run planu install first.');
|
|
102
|
+
}
|
|
103
|
+
const upgraded = await upgradeInventoriedAdapters(manifestPath, latestVersion);
|
|
93
104
|
return {
|
|
94
105
|
configPath: installInfo.configPath,
|
|
95
|
-
previousEntry,
|
|
106
|
+
previousEntry: installInfo.mcpEntry,
|
|
96
107
|
newEntry,
|
|
97
|
-
backupPath,
|
|
108
|
+
backupPath: '',
|
|
98
109
|
alreadyOptimal: false,
|
|
99
|
-
message: `
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
message: `Verified version ${latestVersion} staged and smoke-tested. ` +
|
|
111
|
+
`${String(upgraded.switchedAdapters)} inventoried adapter(s) switched atomically; ` +
|
|
112
|
+
`global rollback target was ${upgraded.previousVersion}. Restart your AI tools to activate.`,
|
|
102
113
|
};
|
|
103
114
|
}
|
|
104
115
|
// ---------------------------------------------------------------------------
|
|
@@ -113,7 +124,6 @@ export async function pinVersion(version, confirm) {
|
|
|
113
124
|
if (installInfo.configPath === null) {
|
|
114
125
|
throw new Error('Could not find MCP config file. Please ensure Claude Code or Claude Desktop is configured.');
|
|
115
126
|
}
|
|
116
|
-
const pinnedEntry = buildPinnedEntry(version);
|
|
117
127
|
if (!confirm) {
|
|
118
128
|
return {
|
|
119
129
|
configPath: installInfo.configPath,
|
|
@@ -124,14 +134,18 @@ export async function pinVersion(version, confirm) {
|
|
|
124
134
|
'To return to auto-update, call enable_auto_update.',
|
|
125
135
|
};
|
|
126
136
|
}
|
|
127
|
-
const
|
|
137
|
+
const manifestPath = resolveStorageLayout().installationManifest;
|
|
138
|
+
if (!existsSync(manifestPath)) {
|
|
139
|
+
throw new Error('Pinning requires an installation inventory and last-known-good rollback target. Run planu install first.');
|
|
140
|
+
}
|
|
141
|
+
await upgradeInventoriedAdapters(manifestPath, version);
|
|
128
142
|
return {
|
|
129
143
|
configPath: installInfo.configPath,
|
|
130
144
|
pinnedVersion: version,
|
|
131
|
-
backupPath,
|
|
145
|
+
backupPath: '',
|
|
132
146
|
message: `Version pinned to @planu/cli@${version} in ${installInfo.configPath}. ` +
|
|
133
|
-
|
|
134
|
-
'Restart
|
|
147
|
+
'The previously verified release remains available for rollback. ' +
|
|
148
|
+
'Restart your AI tools to activate. To return to auto-update, call enable_auto_update.',
|
|
135
149
|
};
|
|
136
150
|
}
|
|
137
151
|
//# sourceMappingURL=index.js.map
|