@planu/cli 4.14.1 → 5.1.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 +82 -0
- package/LICENSE +55 -12
- package/README.md +10 -2
- package/dist/cli/commands/install.d.ts +1 -12
- package/dist/cli/commands/install.js +9 -65
- package/dist/cli/commands/job.js +4 -3
- package/dist/cli/commands/spec.js +12 -3
- package/dist/cli/commands/validate.js +2 -2
- package/dist/cli/router.js +1 -3
- package/dist/config/environment-schema.json +1 -3
- package/dist/config/official-sdd-tools.d.ts +4 -0
- package/dist/config/official-sdd-tools.js +35 -0
- package/dist/config/product-public.d.ts +139 -3
- package/dist/config/product-public.js +8 -1
- package/dist/config/product-public.json +7 -36
- package/dist/config/registries/hosts/codex.json +20 -363
- package/dist/config/release-policy.json +84 -2
- package/dist/config/runtime-policy.json +12 -1
- package/dist/config/skill-templates/planu-resume-work.md +2 -2
- package/dist/core/index.d.ts +1 -1
- package/dist/core/spec-validator.d.ts +4 -4
- package/dist/core/spec-validator.js +33 -19
- package/dist/engine/abortable-process-runner.d.ts +20 -2
- package/dist/engine/abortable-process-runner.js +243 -74
- package/dist/engine/ambiguity-scorer.js +4 -26
- package/dist/engine/auth/scope-mapper.js +1 -7
- package/dist/engine/autopilot/state-updater.js +4 -4
- package/dist/engine/cascade-hooks/hooks/review-enricher.hook.js +9 -6
- package/dist/engine/cascade-hooks/state-drift-detector.d.ts +3 -3
- package/dist/engine/cascade-hooks/state-drift-detector.js +1 -1
- package/dist/engine/ci-generator/planu-config.js +1 -7
- package/dist/engine/clarification-gate/gate.d.ts +3 -3
- package/dist/engine/code-scanner/layer-scanner.js +6 -22
- package/dist/engine/core-bridge.d.ts +3 -3
- package/dist/engine/cost-guardrails.d.ts +1 -1
- package/dist/engine/cost-guardrails.js +1 -1
- package/dist/engine/criterion-identity.d.ts +1 -0
- package/dist/engine/criterion-identity.js +7 -0
- package/dist/engine/dashboard/data-loader.js +2 -7
- package/dist/engine/dashboard/templates-layout.js +0 -3
- package/dist/engine/dashboard/templates-project.js +1 -13
- package/dist/engine/docs-site-generator/data-collector.d.ts +1 -1
- package/dist/engine/docs-site-generator/data-collector.js +7 -28
- package/dist/engine/docs-site-generator/tools-renderer.js +3 -10
- package/dist/engine/evidence-gates/artifact-reader.d.ts +12 -1
- package/dist/engine/evidence-gates/artifact-reader.js +174 -4
- package/dist/engine/evidence-gates/evidence-autofill.d.ts +10 -0
- package/dist/engine/evidence-gates/evidence-autofill.js +148 -0
- package/dist/engine/evidence-gates/evidence-skeletons.d.ts +19 -0
- package/dist/engine/evidence-gates/evidence-skeletons.js +69 -0
- package/dist/engine/evidence-gates/lifecycle-gate.js +4 -3
- package/dist/engine/evidence-gates/reconciliation-freshness.d.ts +11 -0
- package/dist/engine/evidence-gates/reconciliation-freshness.js +72 -0
- package/dist/engine/evidence-index/done-drift.d.ts +1 -1
- package/dist/engine/evidence-index/done-drift.js +40 -18
- package/dist/engine/execution/context.js +3 -0
- package/dist/engine/execution/durable-job-heartbeat-runtime.d.ts +4 -0
- package/dist/engine/execution/durable-job-heartbeat-runtime.js +400 -0
- package/dist/engine/execution/job-runtime.d.ts +30 -0
- package/dist/engine/execution/job-runtime.js +114 -6
- package/dist/engine/execution/operation-journal.js +10 -4
- package/dist/engine/execution/public-job-sanitizer.d.ts +4 -0
- package/dist/engine/execution/public-job-sanitizer.js +31 -0
- package/dist/engine/execution/validate-job-executor.d.ts +12 -1
- package/dist/engine/execution/validate-job-executor.js +549 -86
- package/dist/engine/execution/validate-job-payload.js +107 -50
- package/dist/engine/execution/validate-job-recovery.js +1 -1
- package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
- package/dist/engine/execution/validate-worker-runtime.js +90 -2
- package/dist/engine/execution/validate-worker-thread.js +17 -24
- package/dist/engine/handoff-artifacts/schemas.d.ts +2 -1
- package/dist/engine/handoff-artifacts/schemas.js +33 -0
- package/dist/engine/handoff-packager.d.ts +19 -0
- package/dist/engine/handoff-packager.js +415 -13
- package/dist/engine/hooks/effort-configurator.js +1 -1
- package/dist/engine/impact-detector/test-break-predictor.js +3 -3
- package/dist/engine/impact-detector/tool-registration.js +1 -1
- package/dist/engine/implementation-contract/renderer.js +23 -8
- package/dist/engine/lifecycle-reconciliation-io.d.ts +11 -0
- package/dist/engine/lifecycle-reconciliation-io.js +180 -0
- package/dist/engine/lifecycle-reconciliation.d.ts +16 -0
- package/dist/engine/lifecycle-reconciliation.js +406 -0
- package/dist/engine/local-first/tool-classification.js +2 -0
- package/dist/engine/macos-keychain-native-port.d.ts +5 -0
- package/dist/engine/macos-keychain-native-port.js +19 -7
- package/dist/engine/migrations/remove-commercial-state.d.ts +3 -0
- package/dist/engine/migrations/remove-commercial-state.js +343 -0
- package/dist/engine/minimality/policy-loader.js +247 -6
- package/dist/engine/network-policy.js +1 -0
- package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-arm64.node.sbom.json +20 -20
- package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-x64.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +20 -20
- package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +20 -20
- package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +20 -20
- package/dist/engine/readiness-checker.d.ts +1 -16
- package/dist/engine/readiness-checker.js +27 -88
- package/dist/engine/reverse-engineer/api-detector.js +2 -13
- package/dist/engine/reverse-engineer/complexity-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/config-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/dependency-graph.js +2 -13
- package/dist/engine/reverse-engineer/test-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/walk-ignore.d.ts +3 -0
- package/dist/engine/reverse-engineer/walk-ignore.js +26 -0
- package/dist/engine/runtime-policy.d.ts +2 -0
- package/dist/engine/runtime-policy.js +42 -5
- package/dist/engine/runtime-security/rate-limiter.js +0 -1
- package/dist/engine/safety/contained-project-file.d.ts +3 -0
- package/dist/engine/safety/contained-project-file.js +23 -0
- package/dist/engine/scope-boundaries/contradiction-checker.js +63 -1
- package/dist/engine/scope-boundaries/scope-validator.js +45 -7
- package/dist/engine/session/checkpoint-writer.js +0 -9
- package/dist/engine/spec-format/acceptance-criteria.d.ts +6 -2
- package/dist/engine/spec-format/acceptance-criteria.js +82 -22
- package/dist/engine/spec-format/markdown-sections.d.ts +14 -0
- package/dist/engine/spec-format/markdown-sections.js +105 -0
- package/dist/engine/spec-format/read-technical-section.js +33 -5
- package/dist/engine/spec-format/technical-md-populator.js +3 -2
- package/dist/engine/spec-format/text-fences.js +20 -2
- package/dist/engine/spec-format/unified-spec-builder.d.ts +7 -0
- package/dist/engine/spec-format/unified-spec-builder.js +202 -0
- package/dist/engine/spec-migrator/canonical-deduplicator.d.ts +18 -0
- package/dist/engine/spec-migrator/canonical-deduplicator.js +479 -0
- package/dist/engine/spec-migrator/filesystem-import.d.ts +4 -8
- package/dist/engine/spec-migrator/filesystem-import.js +121 -14
- package/dist/engine/spec-migrator/frontmatter-parser.js +32 -15
- package/dist/engine/spec-migrator/index.d.ts +1 -0
- package/dist/engine/spec-migrator/index.js +1 -0
- package/dist/engine/spec-state-machine/transition-spec.d.ts +6 -1
- package/dist/engine/spec-state-machine/transition-spec.js +10 -1
- package/dist/engine/spec-state-syncer.js +1 -1
- package/dist/engine/technical-enricher/index.js +16 -8
- package/dist/engine/technical-enricher/render-enriched.d.ts +1 -0
- package/dist/engine/technical-enricher/render-enriched.js +42 -14
- package/dist/engine/telemetry/health-checker.js +53 -17
- package/dist/engine/telemetry/telemetry-client.js +26 -8
- package/dist/engine/text-signal-boundaries.d.ts +2 -0
- package/dist/engine/text-signal-boundaries.js +25 -2
- package/dist/engine/time/relative-date.d.ts +3 -0
- package/dist/engine/time/relative-date.js +16 -0
- package/dist/engine/timing/budget.d.ts +11 -0
- package/dist/engine/timing/budget.js +31 -9
- package/dist/engine/token-optimizer/analytics.d.ts +1 -1
- package/dist/engine/token-optimizer/analytics.js +5 -6
- package/dist/engine/usage-tracker/core.d.ts +2 -2
- package/dist/engine/usage-tracker/core.js +1 -2
- package/dist/engine/usage-tracker/index.d.ts +0 -3
- package/dist/engine/usage-tracker/index.js +0 -3
- package/dist/engine/usage-tracker/stats.d.ts +2 -2
- package/dist/engine/usage-tracker/stats.js +1 -28
- package/dist/engine/validation/durable-validation.d.ts +1 -1
- package/dist/engine/validation/durable-validation.js +3 -82
- package/dist/engine/validation/validation-freshness.d.ts +11 -1
- package/dist/engine/validation/validation-freshness.js +231 -91
- package/dist/engine/validation/validation-receipt.d.ts +9 -6
- package/dist/engine/validation/validation-receipt.js +84 -24
- package/dist/engine/validation/validation-source-digest.d.ts +2 -0
- package/dist/engine/validation/validation-source-digest.js +86 -0
- package/dist/engine/validation/validation-submission.d.ts +5 -4
- package/dist/engine/validation/validation-submission.js +25 -11
- package/dist/engine/validation/validation-worktree.d.ts +21 -0
- package/dist/engine/validation/validation-worktree.js +260 -0
- package/dist/engine/validation-impact-planner.d.ts +14 -2
- package/dist/engine/validation-impact-planner.js +0 -3
- package/dist/engine/validator/dor-dod.d.ts +1 -0
- package/dist/engine/validator/dor-dod.js +5 -3
- package/dist/engine/validator/extractors.d.ts +1 -5
- package/dist/engine/validator/extractors.js +24 -69
- package/dist/engine/validator/spec-compliance-runner.d.ts +12 -24
- package/dist/engine/validator/spec-compliance-runner.js +429 -211
- package/dist/engine/validator.js +35 -22
- package/dist/index.js +4 -16
- package/dist/resources/usage-stats-resource.js +2 -18
- package/dist/security/adapters/linux-secret-service.js +7 -3
- package/dist/security/adapters/windows-credential-manager.js +6 -4
- package/dist/server/routes/specs.js +13 -1
- package/dist/storage/base-store.d.ts +1 -1
- package/dist/storage/base-store.js +1 -1
- package/dist/storage/feedback-remote.d.ts +2 -3
- package/dist/storage/feedback-remote.js +45 -31
- package/dist/storage/global-store.d.ts +1 -17
- package/dist/storage/global-store.js +1 -42
- package/dist/storage/index.d.ts +0 -2
- package/dist/storage/index.js +0 -2
- package/dist/storage/migrations/canonical-storage.js +124 -11
- package/dist/storage/runtime-db.d.ts +9 -0
- package/dist/storage/runtime-db.js +64 -8
- package/dist/storage/spec-store.d.ts +14 -2
- package/dist/storage/spec-store.js +104 -14
- package/dist/storage/status-store/atomic-status-write.d.ts +5 -0
- package/dist/storage/status-store/atomic-status-write.js +57 -0
- package/dist/storage/status-store/file-lock.js +30 -11
- package/dist/storage/status-store/self-healing.js +3 -3
- package/dist/storage/status-store/version-sync.d.ts +2 -1
- package/dist/storage/status-store/version-sync.js +35 -40
- package/dist/storage/usage-store.d.ts +1 -5
- package/dist/storage/usage-store.js +0 -35
- package/dist/tools/auto-update-handler.d.ts +3 -3
- package/dist/tools/auto-update-handler.js +3 -3
- package/dist/tools/challenge-spec/resilience-challenge-scenarios.d.ts +2 -1
- package/dist/tools/challenge-spec/resilience-challenge-scenarios.js +10 -7
- package/dist/tools/challenge-spec/scenario-collector.js +1 -1
- package/dist/tools/challenge-spec/scenarios-data.js +1 -1
- package/dist/tools/challenge-spec/scenarios-utils.d.ts +1 -1
- package/dist/tools/challenge-spec/scenarios-utils.js +35 -11
- package/dist/tools/challenge-spec-helpers.d.ts +10 -1
- package/dist/tools/challenge-spec-helpers.js +63 -22
- package/dist/tools/challenge-spec.js +23 -8
- package/dist/tools/check-readiness.js +38 -14
- package/dist/tools/configure-telemetry.js +30 -2
- package/dist/tools/create-spec/spec-builder.d.ts +7 -0
- package/dist/tools/create-spec/spec-builder.js +19 -15
- package/dist/tools/create-spec.d.ts +1 -0
- package/dist/tools/create-spec.js +584 -309
- package/dist/tools/git/branch-ops.d.ts +1 -1
- package/dist/tools/git/branch-ops.js +3 -2
- package/dist/tools/init-project/handler.js +10 -12
- package/dist/tools/init-project/host-assets-writer.js +26 -1
- package/dist/tools/init-project/lint-scaffolder.d.ts +3 -3
- package/dist/tools/init-project/migration-runner.d.ts +2 -4
- package/dist/tools/init-project/migration-runner.js +3 -2
- package/dist/tools/init-project/portable-index-reconciler.d.ts +4 -0
- package/dist/tools/init-project/portable-index-reconciler.js +14 -0
- package/dist/tools/init-project/result-builder.js +1 -3
- package/dist/tools/jobs/handlers.js +38 -6
- package/dist/tools/list-specs.js +5 -26
- package/dist/tools/merge-risk-handler.js +2 -2
- package/dist/tools/package-handoff.js +2 -0
- package/dist/tools/reconcile-spec.js +0 -27
- package/dist/tools/register-agent-squad-tools.js +2 -2
- package/dist/tools/register-platform-tools/design-stack-tools.js +11 -11
- package/dist/tools/register-platform-tools/lifecycle-infra-tools.js +7 -7
- package/dist/tools/register-sdd-tools.d.ts +1 -1
- package/dist/tools/register-sdd-tools.js +2 -29
- package/dist/tools/register-spec-tools/analysis-tools.js +8 -8
- package/dist/tools/register-spec-tools/core-spec-tools.js +29 -19
- package/dist/tools/safe-handler.d.ts +5 -13
- package/dist/tools/safe-handler.js +7 -23
- package/dist/tools/schemas/index.d.ts +1 -1
- package/dist/tools/schemas/index.js +1 -1
- package/dist/tools/schemas/output-schemas.d.ts +0 -23
- package/dist/tools/schemas/output-schemas.js +0 -28
- package/dist/tools/schemas/spec.d.ts +4 -0
- package/dist/tools/schemas/spec.js +3 -0
- package/dist/tools/schemas/validate-output-schema.d.ts +11 -0
- package/dist/tools/schemas/validate-output-schema.js +7 -0
- package/dist/tools/spec-prompt-handler.js +3 -3
- package/dist/tools/sync-spec-state-handler.d.ts +1 -1
- package/dist/tools/sync-spec-state-handler.js +50 -2
- package/dist/tools/tool-entry.d.ts +4 -4
- package/dist/tools/tool-entry.js +3 -3
- package/dist/tools/tool-registry/core-tools.js +31 -15
- package/dist/tools/tool-registry/group-infra.js +27 -110
- package/dist/tools/tool-registry/group-quality-compliance.js +26 -26
- package/dist/tools/tool-registry/inventory.d.ts +2 -0
- package/dist/tools/tool-registry/inventory.js +2 -0
- package/dist/tools/tool-registry-helpers.d.ts +3 -3
- package/dist/tools/tool-registry-helpers.js +3 -3
- package/dist/tools/tool-usage-report/registered-tools.d.ts +1 -1
- package/dist/tools/tool-usage-report/registered-tools.js +3 -15
- package/dist/tools/update-status/approval-gates.js +3 -0
- package/dist/tools/update-status/batch.d.ts +6 -2
- package/dist/tools/update-status/batch.js +58 -1
- package/dist/tools/update-status/dod-gates.d.ts +16 -1
- package/dist/tools/update-status/dod-gates.js +191 -1
- package/dist/tools/update-status/done-receipt-verifier.d.ts +8 -0
- package/dist/tools/update-status/done-receipt-verifier.js +75 -27
- package/dist/tools/update-status/evidence-gate.d.ts +4 -0
- package/dist/tools/update-status/evidence-gate.js +103 -3
- package/dist/tools/update-status/file-sync.d.ts +4 -3
- package/dist/tools/update-status/file-sync.js +57 -6
- package/dist/tools/update-status/index.d.ts +25 -1
- package/dist/tools/update-status/index.js +292 -78
- package/dist/tools/update-status/response-builder.js +3 -3
- package/dist/tools/update-status/side-effects.d.ts +2 -0
- package/dist/tools/update-status/side-effects.js +2 -2
- package/dist/tools/update-status/transition-guard.js +45 -16
- package/dist/tools/update-status-actions.d.ts +4 -2
- package/dist/tools/update-status-actions.js +16 -14
- package/dist/tools/usage-report.js +1 -16
- package/dist/tools/usage-stats.js +1 -18
- package/dist/tools/usage-tracking.d.ts +4 -0
- package/dist/tools/usage-tracking.js +20 -0
- package/dist/tools/validate-lint.d.ts +1 -0
- package/dist/tools/validate-lint.js +1 -1
- package/dist/tools/validate.d.ts +2 -1
- package/dist/tools/validate.js +114 -34
- package/dist/tools/workspace-dashboard-handler.js +38 -0
- package/dist/transports/http-transport.js +6 -8
- package/dist/transports/mcp-types.d.ts +0 -2
- package/dist/transports/session-context.js +1 -1
- package/dist/types/cascade-hooks.d.ts +1 -1
- package/dist/types/ci.d.ts +0 -4
- package/dist/types/clarification-token.d.ts +1 -1
- package/dist/types/claude-code-runtime.d.ts +0 -27
- package/dist/types/commercial-migration.d.ts +17 -0
- package/dist/types/commercial-migration.js +2 -0
- package/dist/types/common/primitives.d.ts +0 -2
- package/dist/types/core-bridge.d.ts +4 -10
- package/dist/types/dashboard.d.ts +3 -7
- package/dist/types/docs.d.ts +0 -1
- package/dist/types/durable-job.d.ts +4 -4
- package/dist/types/durable-validation.d.ts +100 -2
- package/dist/types/durable-validation.js +165 -1
- package/dist/types/errors/structured-error.d.ts +3 -3
- package/dist/types/estimation.d.ts +2 -0
- package/dist/types/evidence-autofill.d.ts +34 -0
- package/dist/types/evidence-autofill.js +2 -0
- package/dist/types/evidence-gates.d.ts +9 -1
- package/dist/types/execution.d.ts +2 -0
- package/dist/types/gemini-integration.d.ts +0 -11
- package/dist/types/handoff-artifacts.d.ts +41 -0
- package/dist/types/hooks-advanced.d.ts +0 -13
- package/dist/types/impact-detection.d.ts +2 -2
- package/dist/types/index.d.ts +3 -6
- package/dist/types/index.js +2 -5
- package/dist/types/kiro-integration.d.ts +0 -6
- package/dist/types/network-policy.d.ts +1 -1
- package/dist/types/project/lint-scaffolder.d.ts +1 -1
- package/dist/types/runtime-policy.d.ts +11 -0
- package/dist/types/session-safeguard.d.ts +0 -31
- package/dist/types/spec/canonical-repair.d.ts +81 -0
- package/dist/types/spec/canonical-repair.js +2 -0
- package/dist/types/spec/core.d.ts +20 -0
- package/dist/types/spec/index.d.ts +1 -0
- package/dist/types/spec/index.js +1 -0
- package/dist/types/spec/inputs.d.ts +35 -1
- package/dist/types/spec-format.d.ts +25 -1
- package/dist/types/telemetry.d.ts +4 -1
- package/dist/types/transition-log.d.ts +1 -1
- package/dist/types/transport.d.ts +0 -2
- package/dist/types/usage.d.ts +1 -36
- package/dist/types/usage.js +1 -1
- package/dist/types/validate-worker.d.ts +6 -0
- package/dist/types/validation-receipt.d.ts +1 -1
- package/dist/types/validation.d.ts +10 -4
- package/package.json +17 -12
- package/planu-native.json +1 -1
- package/planu-plugin.json +23 -40
- package/scripts/lib/pending-release-file.mjs +93 -0
- package/src/i18n/messages/en.json +0 -41
- package/src/i18n/messages/es.json +0 -41
- package/src/i18n/messages/pt.json +0 -41
- package/dist/cli/commands/activate.d.ts +0 -14
- package/dist/cli/commands/activate.js +0 -174
- package/dist/config/license-plans.json +0 -251
- package/dist/config/product-public.ts +0 -148
- package/dist/config/server-instructions.ts +0 -121
- package/dist/config/version-defaults.ts +0 -76
- package/dist/config/version.ts +0 -21
- package/dist/engine/ai-integration/gemini/settings-generator.d.ts +0 -4
- package/dist/engine/ai-integration/gemini/settings-generator.js +0 -195
- package/dist/engine/ai-integration/kiro/hooks-generator.d.ts +0 -6
- package/dist/engine/ai-integration/kiro/hooks-generator.js +0 -75
- package/dist/engine/hooks/full-spectrum-generator.d.ts +0 -32
- package/dist/engine/hooks/full-spectrum-generator.js +0 -117
- package/dist/engine/license-validator/config-loader.d.ts +0 -5
- package/dist/engine/license-validator/config-loader.js +0 -16
- package/dist/engine/license-validator/core.d.ts +0 -15
- package/dist/engine/license-validator/core.js +0 -151
- package/dist/engine/license-validator/fingerprint.d.ts +0 -3
- package/dist/engine/license-validator/fingerprint.js +0 -17
- package/dist/engine/license-validator/lemon-squeezy.d.ts +0 -5
- package/dist/engine/license-validator/lemon-squeezy.js +0 -55
- package/dist/engine/license-validator.d.ts +0 -5
- package/dist/engine/license-validator.js +0 -6
- package/dist/engine/product-intelligence/index.d.ts +0 -7
- package/dist/engine/product-intelligence/index.js +0 -211
- package/dist/engine/session/auto-save.d.ts +0 -18
- package/dist/engine/session/auto-save.js +0 -98
- package/dist/engine/session/context-snapshot.d.ts +0 -8
- package/dist/engine/session/context-snapshot.js +0 -49
- package/dist/engine/session/memory-sync.d.ts +0 -12
- package/dist/engine/session/memory-sync.js +0 -34
- package/dist/engine/session/session-diff.d.ts +0 -11
- package/dist/engine/session/session-diff.js +0 -42
- package/dist/engine/session/session-merge.d.ts +0 -12
- package/dist/engine/session/session-merge.js +0 -55
- package/dist/engine/session-safeguard/checkpoint-runner.d.ts +0 -4
- package/dist/engine/session-safeguard/checkpoint-runner.js +0 -70
- package/dist/engine/session-safeguard/learnings-buffer.d.ts +0 -15
- package/dist/engine/session-safeguard/learnings-buffer.js +0 -91
- package/dist/engine/session-safeguard/precompaction-drain.d.ts +0 -10
- package/dist/engine/session-safeguard/precompaction-drain.js +0 -82
- package/dist/engine/session-safeguard/unpushed-detector.d.ts +0 -7
- package/dist/engine/session-safeguard/unpushed-detector.js +0 -59
- package/dist/engine/spec-changelog/core.d.ts +0 -16
- package/dist/engine/spec-changelog/core.js +0 -176
- package/dist/engine/spec-changelog/diff.d.ts +0 -18
- package/dist/engine/spec-changelog/diff.js +0 -121
- package/dist/engine/spec-changelog/index.d.ts +0 -3
- package/dist/engine/spec-changelog/index.js +0 -4
- package/dist/engine/trial-engine.d.ts +0 -5
- package/dist/engine/trial-engine.js +0 -14
- package/dist/engine/usage-tracker/rate-check.d.ts +0 -7
- package/dist/engine/usage-tracker/rate-check.js +0 -18
- package/dist/engine/usage-tracker/rate-limiter.d.ts +0 -14
- package/dist/engine/usage-tracker/rate-limiter.js +0 -73
- package/dist/engine/usage-tracker/trial.d.ts +0 -27
- package/dist/engine/usage-tracker/trial.js +0 -49
- package/dist/engine/webhook/event-handlers.d.ts +0 -25
- package/dist/engine/webhook/event-handlers.js +0 -89
- package/dist/engine/webhook/index.d.ts +0 -4
- package/dist/engine/webhook/index.js +0 -5
- package/dist/engine/webhook/server.d.ts +0 -12
- package/dist/engine/webhook/server.js +0 -249
- package/dist/engine/webhook/signature.d.ts +0 -16
- package/dist/engine/webhook/signature.js +0 -49
- package/dist/storage/license-store.d.ts +0 -6
- package/dist/storage/license-store.js +0 -63
- package/dist/storage/session-store.d.ts +0 -20
- package/dist/storage/session-store.js +0 -136
- package/dist/tools/activate-license.d.ts +0 -6
- package/dist/tools/activate-license.js +0 -132
- package/dist/tools/checkpoint-handler.d.ts +0 -3
- package/dist/tools/checkpoint-handler.js +0 -130
- package/dist/tools/export-session.d.ts +0 -3
- package/dist/tools/export-session.js +0 -90
- package/dist/tools/license-gate.d.ts +0 -18
- package/dist/tools/license-gate.js +0 -222
- package/dist/tools/license-status.d.ts +0 -3
- package/dist/tools/license-status.js +0 -93
- package/dist/tools/list-sessions.d.ts +0 -3
- package/dist/tools/list-sessions.js +0 -46
- package/dist/tools/planu-session-checkpoint.d.ts +0 -6
- package/dist/tools/planu-session-checkpoint.js +0 -42
- package/dist/tools/restore-session.d.ts +0 -3
- package/dist/tools/restore-session.js +0 -71
- package/dist/tools/spec-history.d.ts +0 -3
- package/dist/tools/spec-history.js +0 -59
- package/dist/tools/webhook.d.ts +0 -6
- package/dist/tools/webhook.js +0 -150
- package/dist/types/changelog.d.ts +0 -49
- package/dist/types/changelog.js +0 -3
- package/dist/types/licensing.d.ts +0 -109
- package/dist/types/licensing.js +0 -4
- package/dist/types/product-intelligence.d.ts +0 -60
- package/dist/types/product-intelligence.js +0 -3
- package/dist/types/session.d.ts +0 -84
- package/dist/types/session.js +0 -3
- package/dist/types/webhook.d.ts +0 -62
- package/dist/types/webhook.js +0 -4
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { readdir, unlink } from 'node:fs/promises';
|
|
2
|
+
import { basename, dirname } from 'node:path';
|
|
3
|
+
import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
|
|
4
|
+
import { atomicWriteFile } from '../../engine/safety/atomic-write-file.js';
|
|
5
|
+
/** Publish one complete canonical status snapshot with same-directory atomic replacement. */
|
|
6
|
+
export function atomicStatusWrite(statusPath, status) {
|
|
7
|
+
return atomicWriteFile(statusPath, JSON.stringify(status, null, 2));
|
|
8
|
+
}
|
|
9
|
+
function processIsDead(pid) {
|
|
10
|
+
try {
|
|
11
|
+
process.kill(pid, 0);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error.code === 'ESRCH') {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
reportClassifiedDegradation('STATUS_PROCESS_PROBE', error);
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Remove only default atomic-write temporaries whose local owner process is dead. */
|
|
23
|
+
export async function cleanupDeadStatusTemps(statusPath) {
|
|
24
|
+
const directory = dirname(statusPath);
|
|
25
|
+
const prefix = `${basename(statusPath)}.tmp.`;
|
|
26
|
+
let entries;
|
|
27
|
+
try {
|
|
28
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error.code === 'ENOENT') {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
let removed = 0;
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
if (!entry.isFile() || !entry.name.startsWith(prefix)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const ownerPid = /^(\d+)\.[0-9a-f]{8}$/.exec(entry.name.slice(prefix.length))?.[1];
|
|
42
|
+
if (ownerPid === undefined || !processIsDead(Number(ownerPid))) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
await unlink(`${directory}/${entry.name}`);
|
|
47
|
+
removed += 1;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error.code !== 'ENOENT') {
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return removed;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=atomic-status-write.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// storage/status-store/file-lock.ts — SPEC-753: File-lock for status.json / pending.json writes
|
|
2
2
|
//
|
|
3
|
-
// Uses
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
// Uses a local FIFO for fair in-process ordering and the existing SQLite fenced lease for
|
|
4
|
+
// exclusion across CLI, MCP, durable-worker, and background-side-effect processes.
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
import { acquireLock, releaseLock } from '../../engine/safety/file-mutex.js';
|
|
7
|
+
import { cleanupDeadStatusTemps } from './atomic-status-write.js';
|
|
8
8
|
const lockQueues = new Map();
|
|
9
9
|
export const STATUS_LOCK_TIMEOUT_MS = 5_000;
|
|
10
10
|
export const STATUS_LOCK_ERROR_CODE = 'status_lock_timeout';
|
|
@@ -14,11 +14,12 @@ export const STATUS_LOCK_ERROR_CODE = 'status_lock_timeout';
|
|
|
14
14
|
* Throws with code `status_lock_timeout` if the lock is not acquired within 5 s.
|
|
15
15
|
*/
|
|
16
16
|
export async function withStatusLock(filePath, fn) {
|
|
17
|
+
const startedAt = Date.now();
|
|
17
18
|
// Race the wait for the previous lock against the timeout
|
|
18
19
|
const prev = lockQueues.get(filePath) ?? Promise.resolve();
|
|
19
20
|
let release;
|
|
20
|
-
const next = new Promise((
|
|
21
|
-
release =
|
|
21
|
+
const next = new Promise((resolveQueue) => {
|
|
22
|
+
release = resolveQueue;
|
|
22
23
|
});
|
|
23
24
|
lockQueues.set(filePath, next);
|
|
24
25
|
let timeout;
|
|
@@ -52,14 +53,32 @@ export async function withStatusLock(filePath, fn) {
|
|
|
52
53
|
clearTimeout(timeout);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
56
|
+
let lease;
|
|
55
57
|
try {
|
|
58
|
+
const remainingMs = Math.max(1, STATUS_LOCK_TIMEOUT_MS - (Date.now() - startedAt));
|
|
59
|
+
try {
|
|
60
|
+
lease = await acquireLock(resolve(filePath), remainingMs);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const lockError = new Error(`[Planu] ${STATUS_LOCK_ERROR_CODE}: could not acquire cross-process write-lock on ${filePath}`, { cause: error });
|
|
64
|
+
lockError.code = STATUS_LOCK_ERROR_CODE;
|
|
65
|
+
throw lockError;
|
|
66
|
+
}
|
|
67
|
+
await cleanupDeadStatusTemps(resolve(filePath));
|
|
56
68
|
return await fn();
|
|
57
69
|
}
|
|
58
70
|
finally {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
try {
|
|
72
|
+
if (lease) {
|
|
73
|
+
await releaseLock(lease);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
release();
|
|
78
|
+
// Clean up only if no newer lock has been queued
|
|
79
|
+
if (lockQueues.get(filePath) === next) {
|
|
80
|
+
lockQueues.delete(filePath);
|
|
81
|
+
}
|
|
63
82
|
}
|
|
64
83
|
}
|
|
65
84
|
}
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
// a file where a valid JSON document is followed by trailing content from a second
|
|
6
6
|
// partial write — i.e. JSON.parse fails at non-zero offset.
|
|
7
7
|
import { readFile, writeFile, rename, mkdir, readdir } from 'node:fs/promises';
|
|
8
|
-
import { join
|
|
8
|
+
import { join } from 'node:path';
|
|
9
9
|
import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
|
|
10
10
|
import { PLANU_VERSION } from '../../config/version.js';
|
|
11
|
+
import { atomicStatusWrite } from './atomic-status-write.js';
|
|
11
12
|
// ---------------------------------------------------------------------------
|
|
12
13
|
// Helpers
|
|
13
14
|
// ---------------------------------------------------------------------------
|
|
@@ -181,8 +182,7 @@ export async function rebuildStatusFromFrontmatters(params) {
|
|
|
181
182
|
* Use this after `rebuildStatusFromFrontmatters` to persist the rebuild.
|
|
182
183
|
*/
|
|
183
184
|
export async function writeRebuiltStatus(statusPath, status) {
|
|
184
|
-
await
|
|
185
|
-
await writeFile(statusPath, JSON.stringify(status, null, 2), 'utf-8');
|
|
185
|
+
await atomicStatusWrite(statusPath, status);
|
|
186
186
|
}
|
|
187
187
|
// ---------------------------------------------------------------------------
|
|
188
188
|
// Internal: minimal YAML frontmatter parser
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sync the `version` field in status.json with the current runtime.
|
|
3
3
|
* No-op if the version is already current or the file doesn't exist.
|
|
4
|
-
*
|
|
4
|
+
* The snapshot is always revalidated under the cross-process lease because another
|
|
5
|
+
* Planu process may replace it after any local observation.
|
|
5
6
|
*/
|
|
6
7
|
export declare function syncVersionField(statusPath: string, force?: boolean): Promise<{
|
|
7
8
|
synced: boolean;
|
|
@@ -1,57 +1,52 @@
|
|
|
1
1
|
// storage/status-store/version-sync.ts — SPEC-753: Version sync at startup + per-session
|
|
2
2
|
//
|
|
3
3
|
// Ensures status.json.version always reflects the current runtime Planu version.
|
|
4
|
-
import { readFile
|
|
5
|
-
import { dirname } from 'node:path';
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
6
5
|
import { PLANU_VERSION } from '../../config/version.js';
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { atomicStatusWrite } from './atomic-status-write.js';
|
|
7
|
+
import { withStatusLock } from './file-lock.js';
|
|
9
8
|
/**
|
|
10
9
|
* Sync the `version` field in status.json with the current runtime.
|
|
11
10
|
* No-op if the version is already current or the file doesn't exist.
|
|
12
|
-
*
|
|
11
|
+
* The snapshot is always revalidated under the cross-process lease because another
|
|
12
|
+
* Planu process may replace it after any local observation.
|
|
13
13
|
*/
|
|
14
14
|
export async function syncVersionField(statusPath, force = false) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
void force;
|
|
16
|
+
return withStatusLock(statusPath, async () => {
|
|
17
|
+
let raw;
|
|
18
|
+
try {
|
|
19
|
+
raw = await readFile(statusPath, 'utf-8');
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (error.code === 'ENOENT') {
|
|
23
|
+
return { synced: false };
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
const p = JSON.parse(raw);
|
|
30
|
+
if (typeof p !== 'object' || p === null || Array.isArray(p)) {
|
|
31
|
+
return { synced: false };
|
|
32
|
+
}
|
|
33
|
+
parsed = p;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new Error(`Status file is corrupt: ${statusPath}`, { cause: error });
|
|
26
37
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
let parsed;
|
|
30
|
-
try {
|
|
31
|
-
const p = JSON.parse(raw);
|
|
32
|
-
if (typeof p !== 'object' || p === null || Array.isArray(p)) {
|
|
33
|
-
syncedPaths.add(statusPath);
|
|
38
|
+
const currentVersion = typeof parsed.version === 'string' ? parsed.version : undefined;
|
|
39
|
+
if (currentVersion === PLANU_VERSION) {
|
|
34
40
|
return { synced: false };
|
|
35
41
|
}
|
|
36
|
-
parsed =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
const currentVersion = typeof parsed.version === 'string' ? parsed.version : undefined;
|
|
42
|
-
if (currentVersion === PLANU_VERSION) {
|
|
43
|
-
syncedPaths.add(statusPath);
|
|
44
|
-
return { synced: false };
|
|
45
|
-
}
|
|
46
|
-
parsed.version = PLANU_VERSION;
|
|
47
|
-
parsed.updatedAt = new Date().toISOString();
|
|
48
|
-
await mkdir(dirname(statusPath), { recursive: true });
|
|
49
|
-
await writeFile(statusPath, JSON.stringify(parsed, null, 2), 'utf-8');
|
|
50
|
-
syncedPaths.add(statusPath);
|
|
51
|
-
return { synced: true, from: currentVersion, to: PLANU_VERSION };
|
|
42
|
+
parsed.version = PLANU_VERSION;
|
|
43
|
+
parsed.updatedAt = new Date().toISOString();
|
|
44
|
+
await atomicStatusWrite(statusPath, parsed);
|
|
45
|
+
return { synced: true, from: currentVersion, to: PLANU_VERSION };
|
|
46
|
+
});
|
|
52
47
|
}
|
|
53
48
|
/** Clear the session sync cache — TEST USE ONLY. */
|
|
54
49
|
export function clearVersionSyncCache() {
|
|
55
|
-
|
|
50
|
+
// Compatibility no-op: correctness requires revalidating every snapshot under the lease.
|
|
56
51
|
}
|
|
57
52
|
//# sourceMappingURL=version-sync.js.map
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import type { UsageLog, UsageEvent
|
|
1
|
+
import type { UsageLog, UsageEvent } from '../types/index.js';
|
|
2
2
|
export declare function getUsageLog(): Promise<UsageLog>;
|
|
3
3
|
export declare function appendUsageEvent(event: UsageEvent): Promise<void>;
|
|
4
4
|
export declare function rotateUsageLog(): Promise<void>;
|
|
5
|
-
export declare function getTrialState(): Promise<TrialState | null>;
|
|
6
|
-
export declare function ensureTrialState(): Promise<TrialState>;
|
|
7
|
-
export declare function getDailyCallCount(date: string): Promise<number>;
|
|
8
|
-
export declare function getLastCallTimestamp(): Promise<string | null>;
|
|
9
5
|
//# sourceMappingURL=usage-store.d.ts.map
|
|
@@ -10,9 +10,6 @@ const MAX_EVENTS = 10_000;
|
|
|
10
10
|
function usageFile() {
|
|
11
11
|
return `${globalDataDir()}/usage.json`;
|
|
12
12
|
}
|
|
13
|
-
function firstRunFile() {
|
|
14
|
-
return `${globalDataDir()}/first-run.json`;
|
|
15
|
-
}
|
|
16
13
|
// ---------------------------------------------------------------------------
|
|
17
14
|
// Usage log (data/global/usage.json)
|
|
18
15
|
// ---------------------------------------------------------------------------
|
|
@@ -42,36 +39,4 @@ export async function appendUsageEvent(event) {
|
|
|
42
39
|
export async function rotateUsageLog() {
|
|
43
40
|
await withFileLock(usageFile(), rotateUsageLogLocked);
|
|
44
41
|
}
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
// Trial state (data/global/first-run.json)
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
|
-
export async function getTrialState() {
|
|
49
|
-
return readJson(firstRunFile(), null);
|
|
50
|
-
}
|
|
51
|
-
export async function ensureTrialState() {
|
|
52
|
-
const existing = await getTrialState();
|
|
53
|
-
if (existing !== null) {
|
|
54
|
-
return existing;
|
|
55
|
-
}
|
|
56
|
-
const state = { firstRunAt: new Date().toISOString() };
|
|
57
|
-
await writeJson(firstRunFile(), state);
|
|
58
|
-
return state;
|
|
59
|
-
}
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
// Computed helpers (derived from usage.json — no extra file)
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
export async function getDailyCallCount(date) {
|
|
64
|
-
const log = await getUsageLog();
|
|
65
|
-
return log.events.filter((event) => event.timestamp.startsWith(date)).length;
|
|
66
|
-
}
|
|
67
|
-
export async function getLastCallTimestamp() {
|
|
68
|
-
const log = await getUsageLog();
|
|
69
|
-
if (log.events.length === 0) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
const last = log.events[log.events.length - 1];
|
|
73
|
-
/* v8 ignore start -- always defined when length > 0 */
|
|
74
|
-
return last?.timestamp ?? null;
|
|
75
|
-
/* v8 ignore stop */
|
|
76
|
-
}
|
|
77
42
|
//# sourceMappingURL=usage-store.js.map
|
|
@@ -9,17 +9,17 @@ export interface PinVersionInput {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* Checks npm registry and local config for update status.
|
|
12
|
-
*
|
|
12
|
+
* Checks update status without changing local state.
|
|
13
13
|
*/
|
|
14
14
|
export declare function handleCheckUpdateStatus(): Promise<ToolResult>;
|
|
15
15
|
/**
|
|
16
16
|
* Resolves a verified release and pins the MCP config to that exact version.
|
|
17
|
-
*
|
|
17
|
+
* Enables update checks for the local installation.
|
|
18
18
|
*/
|
|
19
19
|
export declare function handleEnableAutoUpdate(args: EnableAutoUpdateInput): Promise<ToolResult>;
|
|
20
20
|
/**
|
|
21
21
|
* Pins Planu to a specific version in the MCP config.
|
|
22
|
-
*
|
|
22
|
+
* Pins the local installation to an explicit version.
|
|
23
23
|
*/
|
|
24
24
|
export declare function handlePinVersion(args: PinVersionInput): Promise<ToolResult>;
|
|
25
25
|
//# sourceMappingURL=auto-update-handler.d.ts.map
|
|
@@ -7,7 +7,7 @@ import { jsonResult, errText } from './response-helpers.js';
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
/**
|
|
9
9
|
* Checks npm registry and local config for update status.
|
|
10
|
-
*
|
|
10
|
+
* Checks update status without changing local state.
|
|
11
11
|
*/
|
|
12
12
|
export async function handleCheckUpdateStatus() {
|
|
13
13
|
try {
|
|
@@ -20,7 +20,7 @@ export async function handleCheckUpdateStatus() {
|
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Resolves a verified release and pins the MCP config to that exact version.
|
|
23
|
-
*
|
|
23
|
+
* Enables update checks for the local installation.
|
|
24
24
|
*/
|
|
25
25
|
export async function handleEnableAutoUpdate(args) {
|
|
26
26
|
const confirm = args.confirm ?? false;
|
|
@@ -35,7 +35,7 @@ export async function handleEnableAutoUpdate(args) {
|
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Pins Planu to a specific version in the MCP config.
|
|
38
|
-
*
|
|
38
|
+
* Pins the local installation to an explicit version.
|
|
39
39
|
*/
|
|
40
40
|
export async function handlePinVersion(args) {
|
|
41
41
|
if (!args.version || args.version.trim() === '') {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { FailureScenario, Spec, ProjectKnowledge } from '../../types/index.js';
|
|
2
|
+
import { type ChallengeCapabilities } from './scenarios-utils.js';
|
|
2
3
|
export { EXTERNAL_CALL_KEYWORDS, VALIDATION_KEYWORDS, RATE_LIMIT_KEYWORDS, CONCURRENCY_KEYWORDS, SAGA_KEYWORDS, hasExternalCallSignal, hasValidationSignal, hasRateLimitSignal, hasConcurrencySignal, hasSagaSignal, generateValidationBoundaryScenarios, generateCascadeFailureScenarios, } from './resilience-challenge-scenarios-a.js';
|
|
3
4
|
export { generateRateLimitBypassScenarios, generateConcurrencyScenarios, generateSagaFailureScenarios, } from './resilience-challenge-scenarios-b.js';
|
|
4
5
|
/**
|
|
5
6
|
* Main entry: generate all SPEC-034 resilience/concurrency challenges for a spec.
|
|
6
7
|
*/
|
|
7
|
-
export declare function generateResilienceChallengeScenarios(spec: Spec, specContent: string, knowledge: ProjectKnowledge): FailureScenario[];
|
|
8
|
+
export declare function generateResilienceChallengeScenarios(spec: Spec, specContent: string, knowledge: ProjectKnowledge, capabilities?: ChallengeCapabilities): FailureScenario[];
|
|
8
9
|
//# sourceMappingURL=resilience-challenge-scenarios.d.ts.map
|
|
@@ -2,32 +2,35 @@
|
|
|
2
2
|
// Barrel re-export for resilience/concurrency challenge scenarios.
|
|
3
3
|
// Signal detectors + validation + cascade: resilience-challenge-scenarios-a.ts
|
|
4
4
|
// Rate limit + concurrency + saga: resilience-challenge-scenarios-b.ts
|
|
5
|
-
import {
|
|
5
|
+
import { generateValidationBoundaryScenarios, generateCascadeFailureScenarios, } from './resilience-challenge-scenarios-a.js';
|
|
6
6
|
import { generateRateLimitBypassScenarios, generateConcurrencyScenarios, generateSagaFailureScenarios, } from './resilience-challenge-scenarios-b.js';
|
|
7
|
+
import { detectChallengeCapabilities } from './scenarios-utils.js';
|
|
7
8
|
export { EXTERNAL_CALL_KEYWORDS, VALIDATION_KEYWORDS, RATE_LIMIT_KEYWORDS, CONCURRENCY_KEYWORDS, SAGA_KEYWORDS, hasExternalCallSignal, hasValidationSignal, hasRateLimitSignal, hasConcurrencySignal, hasSagaSignal, generateValidationBoundaryScenarios, generateCascadeFailureScenarios, } from './resilience-challenge-scenarios-a.js';
|
|
8
9
|
export { generateRateLimitBypassScenarios, generateConcurrencyScenarios, generateSagaFailureScenarios, } from './resilience-challenge-scenarios-b.js';
|
|
9
10
|
/**
|
|
10
11
|
* Main entry: generate all SPEC-034 resilience/concurrency challenges for a spec.
|
|
11
12
|
*/
|
|
12
|
-
export function generateResilienceChallengeScenarios(spec, specContent, knowledge) {
|
|
13
|
+
export function generateResilienceChallengeScenarios(spec, specContent, knowledge, capabilities) {
|
|
13
14
|
const scenarios = [];
|
|
14
|
-
|
|
15
|
+
const resolvedCapabilities = capabilities ?? detectChallengeCapabilities(spec, specContent);
|
|
16
|
+
if (resolvedCapabilities.validation &&
|
|
17
|
+
(resolvedCapabilities.userInput || resolvedCapabilities.networkApi)) {
|
|
15
18
|
scenarios.push(...generateValidationBoundaryScenarios(spec));
|
|
16
19
|
}
|
|
17
|
-
if (
|
|
20
|
+
if (resolvedCapabilities.externalService || resolvedCapabilities.payment) {
|
|
18
21
|
scenarios.push(...generateCascadeFailureScenarios(spec));
|
|
19
22
|
}
|
|
20
|
-
if (
|
|
23
|
+
if (resolvedCapabilities.rateLimit) {
|
|
21
24
|
scenarios.push(...generateRateLimitBypassScenarios(spec));
|
|
22
25
|
}
|
|
23
|
-
if (
|
|
26
|
+
if (resolvedCapabilities.concurrency) {
|
|
24
27
|
// `concurrencyModel` may be present on enriched knowledge objects (ValidationResilienceProfile mixin)
|
|
25
28
|
// but is not declared on the base ProjectKnowledge interface — intentional duck-type access.
|
|
26
29
|
// ProjectKnowledge has no index signature, so `as unknown` intermediate is required.
|
|
27
30
|
const concurrencyModel = knowledge.concurrencyModel;
|
|
28
31
|
scenarios.push(...generateConcurrencyScenarios(spec, concurrencyModel ?? 'unknown'));
|
|
29
32
|
}
|
|
30
|
-
if (
|
|
33
|
+
if (resolvedCapabilities.saga) {
|
|
31
34
|
scenarios.push(...generateSagaFailureScenarios(spec));
|
|
32
35
|
}
|
|
33
36
|
return scenarios;
|
|
@@ -75,7 +75,7 @@ export function collectCapabilityScenarios(input) {
|
|
|
75
75
|
'concurrency',
|
|
76
76
|
'saga',
|
|
77
77
|
])) {
|
|
78
|
-
scenarios.push(...generateResilienceChallengeScenarios(spec, specContent, knowledge));
|
|
78
|
+
scenarios.push(...generateResilienceChallengeScenarios(spec, specContent, knowledge, capabilities));
|
|
79
79
|
}
|
|
80
80
|
const agileConfig = knowledge.agileConfig;
|
|
81
81
|
if (agileConfig?.process === 'xp' && capabilities.xp) {
|
|
@@ -4,7 +4,7 @@ const WRITE_SIGNALS = [
|
|
|
4
4
|
/\b(transaction|persist|database write|save record|create record|update record|delete record)\b/i,
|
|
5
5
|
/\b(order|checkout|submit form|mutation|multi-step write)\b/i,
|
|
6
6
|
];
|
|
7
|
-
const CACHE_SIGNALS = [/\b(cache|real-time|realtime|
|
|
7
|
+
const CACHE_SIGNALS = [/\b(cache|cached|real-time|realtime|websocket|stale data)\b/i];
|
|
8
8
|
const DUPLICATE_OPERATION_SIGNALS = [
|
|
9
9
|
/\b(submit|form|checkout|order|payment|create record|mutation|button click)\b/i,
|
|
10
10
|
/\bduplicate\s+(?:request|submission|operation|record)\b/i,
|
|
@@ -29,5 +29,5 @@ export interface ChallengeCapabilities {
|
|
|
29
29
|
export declare function contentMentions(content: string, keywords: string[]): boolean;
|
|
30
30
|
export declare function detectChallengeCapabilities(spec: Spec, specContent: string): ChallengeCapabilities;
|
|
31
31
|
export declare function hasAnyChallengeCapability(capabilities: ChallengeCapabilities, names: (keyof ChallengeCapabilities)[]): boolean;
|
|
32
|
-
export { hasAffirmedMatch, hasAnyAffirmedMatch, stripNonContractText, } from '../../engine/text-signal-boundaries.js';
|
|
32
|
+
export { hasAffirmedMatch, hasAnyAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../../engine/text-signal-boundaries.js';
|
|
33
33
|
//# sourceMappingURL=scenarios-utils.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// tools/challenge-spec/scenarios-utils.ts — Shared utilities for scenario generators
|
|
2
|
-
import { hasAnyAffirmedMatch } from '../../engine/text-signal-boundaries.js';
|
|
2
|
+
import { hasAnyAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../../engine/text-signal-boundaries.js';
|
|
3
3
|
const CAPABILITY_SIGNALS = {
|
|
4
4
|
networkApi: [
|
|
5
5
|
/(?<!compiler\s)\bapi\b(?!\s+(?:compatibility|surface|package|type))/i,
|
|
@@ -15,7 +15,7 @@ const CAPABILITY_SIGNALS = {
|
|
|
15
15
|
/\b(?:orm|prisma|drizzle|typeorm|sequelize)\b/i,
|
|
16
16
|
],
|
|
17
17
|
authentication: [
|
|
18
|
-
/\b(?:auth(?:entication)?|login|sign[ -]?in|password|jwt|oauth2?|session\s+auth)\b/i,
|
|
18
|
+
/\b(?:auth(?:entication|enticate)?|login|sign[ -]?in|password|jwt|oauth2?|session\s+auth)\b/i,
|
|
19
19
|
],
|
|
20
20
|
authorization: [
|
|
21
21
|
/\b(?:authori[sz]ation|permission|rbac|role-based|access\s+control|resource\s+ownership|tenant)\b/i,
|
|
@@ -26,10 +26,10 @@ const CAPABILITY_SIGNALS = {
|
|
|
26
26
|
/\binputs?\s+(?:are\s+)?validat/i,
|
|
27
27
|
],
|
|
28
28
|
externalService: [
|
|
29
|
-
/\b(?:third-party|external|remote|downstream)\s+(?:service|provider|dependency|system)\b/i,
|
|
29
|
+
/\b(?:third-party|external|remote|downstream)\s+(?:service|provider|dependency|system|api)\b/i,
|
|
30
30
|
/\bwebhook\s+(?:provider|delivery|endpoint|request)\b/i,
|
|
31
31
|
],
|
|
32
|
-
payment: [/\b(?:payment|billing|
|
|
32
|
+
payment: [/\b(?:payment|billing|invoice|stripe|paypal)\b/i],
|
|
33
33
|
fileTransfer: [
|
|
34
34
|
/\b(?:(?:large|binary|uploaded)\s+)?(?:file|image|media|attachment)\s+(?:upload|download|transfer|stream)\b/i,
|
|
35
35
|
/\b(?:upload|download|stream)(?:ed|ing|s)?\s+(?:a\s+)?(?:(?:large|binary)\s+)?(?:file|image|media|attachment)\b/i,
|
|
@@ -43,8 +43,8 @@ const CAPABILITY_SIGNALS = {
|
|
|
43
43
|
],
|
|
44
44
|
dataWrite: [
|
|
45
45
|
/\b(?:database\s+transaction|persist(?:s|ed|ing)?\s+(?:record|entity|data)|write(?:s|ing)?\s+(?:record|entity|database))\b/i,
|
|
46
|
-
/\b(?:state-changing|data\s+mutation|atomic\s+database\s+
|
|
47
|
-
/\b(?:transaction|atomic\s+
|
|
46
|
+
/\b(?:state-changing|data\s+mutation|atomic\s+database\s+writes?)\b/i,
|
|
47
|
+
/\b(?:transaction|atomic\s+writes?|update\s+(?:record|state)|modify\s+(?:record|state))\b/i,
|
|
48
48
|
],
|
|
49
49
|
cache: [/\b(?:cache|caching|cached\s+(?:data|response)|redis)\b/i],
|
|
50
50
|
duplicateOperation: [
|
|
@@ -52,6 +52,7 @@ const CAPABILITY_SIGNALS = {
|
|
|
52
52
|
],
|
|
53
53
|
concurrency: [
|
|
54
54
|
/\b(?:concurren|race\s+condition|shared\s+state|parallel\s+write|atomic\s+increment|optimistic\s+lock)/i,
|
|
55
|
+
/\b(?:shared\b(?:\s+\w+){0,2}\s+(?:cache|resource|pool)|resource\s+(?:lock|pool))\b/i,
|
|
55
56
|
/\b(?:counter|increment|balance|stock|quantity|vote|status\s+(?:update|transition))\b/i,
|
|
56
57
|
/\b(?:file\s+upload|resource\s+manager|search\s+feed|list\s+endpoint|global\s+cache|session\s+state|cart\s+state|draft\s+state)\b/i,
|
|
57
58
|
],
|
|
@@ -76,8 +77,12 @@ const CAPABILITY_SIGNALS = {
|
|
|
76
77
|
agent: [/\b(?:ai\s+agent|agent\s+contract|llm\s+agent|tool\s+call|autonomous\s+agent)\b/i],
|
|
77
78
|
ddd: [/\b(?:domain-driven\s+design|ddd\s+aggregate|aggregate\s+root|bounded\s+context)\b/i],
|
|
78
79
|
xp: [/\b(?:pair\s+programming|extreme\s+programming|xp\s+pair)\b/i],
|
|
79
|
-
validation: [
|
|
80
|
-
|
|
80
|
+
validation: [
|
|
81
|
+
/\b(?:input|payload|request|schema)\s+validat/i,
|
|
82
|
+
/\bvalidat(?:e|es|ed|ing|ion)\b/i,
|
|
83
|
+
/\b(?:zod|joi|json\s+schema)\b/i,
|
|
84
|
+
],
|
|
85
|
+
rateLimit: [/\b(?:rate[ -]?limit(?:ing|ed|s)?|throttl|request\s+quota)\b/i],
|
|
81
86
|
saga: [/\b(?:saga|compensating\s+transaction|distributed\s+transaction)\b/i],
|
|
82
87
|
platform: [
|
|
83
88
|
/\b(?:smart\s+contract|solidity|discord\s+bot|telegram\s+bot|iot\s+device|firmware|infrastructure\s+as\s+code|terraform|machine\s+learning\s+model)\b/i,
|
|
@@ -88,19 +93,38 @@ function keywordPattern(keyword) {
|
|
|
88
93
|
const suffix = /^[a-z0-9]+$/i.test(keyword) && keyword.length > 3 ? '[a-z0-9_-]*' : '';
|
|
89
94
|
return new RegExp(`\\b${escaped}${suffix}\\b`, 'i');
|
|
90
95
|
}
|
|
96
|
+
function whitespaceFlexiblePattern(text) {
|
|
97
|
+
return text
|
|
98
|
+
.trim()
|
|
99
|
+
.split(/\s+/)
|
|
100
|
+
.map((token) => token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
101
|
+
.join('\\s+');
|
|
102
|
+
}
|
|
103
|
+
function stripReaderPrefix(spec, specContent) {
|
|
104
|
+
const readerPrefix = [spec.title, spec.type, spec.scope, spec.target, spec.tags.join(' ')]
|
|
105
|
+
.filter(Boolean)
|
|
106
|
+
.join(' ');
|
|
107
|
+
const prefixPattern = whitespaceFlexiblePattern(readerPrefix);
|
|
108
|
+
if (prefixPattern.length === 0) {
|
|
109
|
+
return specContent;
|
|
110
|
+
}
|
|
111
|
+
return specContent.replace(new RegExp(`^\\s*${prefixPattern}(?=\\s|$)`, 'u'), '').trimStart();
|
|
112
|
+
}
|
|
91
113
|
/** Boundary-aware, affirmative replacement for advisory substring checks. */
|
|
92
114
|
export function contentMentions(content, keywords) {
|
|
93
115
|
return hasAnyAffirmedMatch(content, keywords.map(keywordPattern));
|
|
94
116
|
}
|
|
95
117
|
export function detectChallengeCapabilities(spec, specContent) {
|
|
96
|
-
const
|
|
118
|
+
const contractSource = stripReaderPrefix(spec, specContent);
|
|
119
|
+
const source = contractSource.trim().length > 0 ? contractSource : spec.title;
|
|
120
|
+
const contract = stripMetaAnalysisText(stripNonContractText(source));
|
|
97
121
|
return Object.fromEntries(Object.entries(CAPABILITY_SIGNALS).map(([capability, patterns]) => [
|
|
98
122
|
capability,
|
|
99
|
-
hasAnyAffirmedMatch(
|
|
123
|
+
hasAnyAffirmedMatch(contract, patterns),
|
|
100
124
|
]));
|
|
101
125
|
}
|
|
102
126
|
export function hasAnyChallengeCapability(capabilities, names) {
|
|
103
127
|
return names.some((name) => capabilities[name]);
|
|
104
128
|
}
|
|
105
|
-
export { hasAffirmedMatch, hasAnyAffirmedMatch, stripNonContractText, } from '../../engine/text-signal-boundaries.js';
|
|
129
|
+
export { hasAffirmedMatch, hasAnyAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../../engine/text-signal-boundaries.js';
|
|
106
130
|
//# sourceMappingURL=scenarios-utils.js.map
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { FailureScenario, ConcurrencyAnalysis, RiskLevel, Spec, ProjectKnowledge } from '../types/index.js';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Result of generateConcurrencyAnalysis. `suppressedCount` tracks candidates
|
|
4
|
+
* that matched a domain keyword (counter/status/file/session/cache) but were
|
|
5
|
+
* dropped because the spec content contains no corroborating concurrency
|
|
6
|
+
* context (e.g. "concurrent", "simultaneously", "multiple users") — SPEC-1350.
|
|
7
|
+
*/
|
|
8
|
+
export interface ConcurrencyAnalysisResult extends ConcurrencyAnalysis {
|
|
9
|
+
suppressedCount: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function generateConcurrencyAnalysis(_spec: Spec, content: string, _knowledge: ProjectKnowledge): ConcurrencyAnalysisResult;
|
|
3
12
|
export declare function buildScalabilityAssessment(spec: Spec, knowledge: ProjectKnowledge, scenarios: FailureScenario[]): string;
|
|
4
13
|
export declare function calculateOverallRisk(scenarios: FailureScenario[], concurrency: ConcurrencyAnalysis): RiskLevel;
|
|
5
14
|
export declare function readSpecContent(spec: Spec): Promise<string>;
|