@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
|
@@ -1,55 +1,96 @@
|
|
|
1
1
|
// tools/challenge-spec-helpers.ts — Concurrency, risk, and spec-reader helpers for challenge-spec
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { readSpecTechnicalSection } from '../engine/spec-format/read-technical-section.js';
|
|
4
|
-
|
|
4
|
+
import { hasAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../engine/text-signal-boundaries.js';
|
|
5
|
+
// Bare keyword matches (counter, status, draft, ...) are common in unrelated
|
|
6
|
+
// prose (variable names, file paths, section headers, bug narratives). They
|
|
7
|
+
// only ground a race-condition/shared-state finding when the spec content
|
|
8
|
+
// also affirms an explicit concurrency context — otherwise they are boilerplate.
|
|
9
|
+
const CONCURRENCY_CONTEXT_PATTERN = /\b(?:concurrent(?:ly)?|simultaneous(?:ly)?|in\s+parallel|parallel\s+writes?|race\s+condition|multiple\s+users?|at\s+the\s+same\s+time|two\s+users|shared\s+state|atomic(?:ally)?|thread-safe|synchroniz(?:e|es|ed|ing|ation)|multiple\s+(?:tabs|devices|requests|clients))\b/i;
|
|
10
|
+
const AUTH_PATTERN = /\b(?:login|auth)\b/i;
|
|
11
|
+
const LIST_SEARCH_PATTERN = /\b(?:list|search|feed)\b/i;
|
|
12
|
+
const WRITE_PATTERN = /\b(?:submit|create|update)\b/i;
|
|
13
|
+
const COUNTER_PATTERN = /\b(?:counter|increment|balance|stock|quantity|vote)\b/i;
|
|
14
|
+
const STATUS_PATTERN = /\bstatus\b/i;
|
|
15
|
+
const TRANSITION_PATTERN = /\b(?:update|transition)\b/i;
|
|
16
|
+
const FILE_PATTERN = /\b(?:file|upload|resource)\b/i;
|
|
17
|
+
const SESSION_PATTERN = /\b(?:session|cart|draft)\b/i;
|
|
18
|
+
const CACHE_PATTERN = /\b(?:cache|global|config)\b/i;
|
|
19
|
+
/** Grounded, boundary-aware, negation-aware match against contract prose only. */
|
|
20
|
+
function affirms(content, pattern) {
|
|
21
|
+
return hasAffirmedMatch(content, pattern);
|
|
22
|
+
}
|
|
5
23
|
export function generateConcurrencyAnalysis(_spec, content, _knowledge) {
|
|
6
|
-
|
|
24
|
+
// Drop frontmatter, code fences, and quoted/backticked examples before
|
|
25
|
+
// keyword inference — mirrors detectChallengeCapabilities so this generator
|
|
26
|
+
// reads the same "contract prose" the capability gate already reads.
|
|
27
|
+
const contract = stripMetaAnalysisText(stripNonContractText(content));
|
|
7
28
|
const hotPaths = [];
|
|
8
29
|
const raceConditions = [];
|
|
9
30
|
const sharedState = [];
|
|
10
31
|
const recommendations = [];
|
|
11
|
-
|
|
12
|
-
|
|
32
|
+
let suppressedCount = 0;
|
|
33
|
+
// Hot paths are informational only (they do not feed overallRisk), so a
|
|
34
|
+
// plain boundary-aware match is sufficient here — no context gate needed.
|
|
35
|
+
if (affirms(contract, AUTH_PATTERN)) {
|
|
13
36
|
hotPaths.push('Authentication endpoint (high-frequency, shared session state)');
|
|
14
37
|
}
|
|
15
|
-
if (
|
|
38
|
+
if (affirms(contract, LIST_SEARCH_PATTERN)) {
|
|
16
39
|
hotPaths.push('List/search endpoints (high read frequency)');
|
|
17
40
|
}
|
|
18
|
-
if (
|
|
41
|
+
if (affirms(contract, WRITE_PATTERN)) {
|
|
19
42
|
hotPaths.push('Write endpoints (mutation-heavy, lock-prone)');
|
|
20
43
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
lower.includes('balance') ||
|
|
25
|
-
lower.includes('stock') ||
|
|
26
|
-
lower.includes('quantity') ||
|
|
27
|
-
lower.includes('vote')) {
|
|
44
|
+
const hasConcurrencyContext = affirms(contract, CONCURRENCY_CONTEXT_PATTERN);
|
|
45
|
+
const counterMatched = affirms(contract, COUNTER_PATTERN);
|
|
46
|
+
if (counterMatched && hasConcurrencyContext) {
|
|
28
47
|
raceConditions.push('Counter/balance updates may lose increments under concurrent writes');
|
|
29
48
|
recommendations.push('Use database-level atomic increments (UPDATE SET count = count + 1) instead of read-modify-write');
|
|
30
49
|
}
|
|
31
|
-
if (
|
|
50
|
+
else if (counterMatched) {
|
|
51
|
+
suppressedCount += 1;
|
|
52
|
+
}
|
|
53
|
+
const statusMatched = affirms(contract, STATUS_PATTERN) && affirms(contract, TRANSITION_PATTERN);
|
|
54
|
+
if (statusMatched && hasConcurrencyContext) {
|
|
32
55
|
raceConditions.push('Status transitions may conflict when two users update simultaneously');
|
|
33
56
|
recommendations.push('Use optimistic locking (version column) or pessimistic locking (SELECT FOR UPDATE)');
|
|
34
57
|
}
|
|
35
|
-
if (
|
|
58
|
+
else if (statusMatched) {
|
|
59
|
+
suppressedCount += 1;
|
|
60
|
+
}
|
|
61
|
+
const fileMatched = affirms(contract, FILE_PATTERN);
|
|
62
|
+
if (fileMatched && hasConcurrencyContext) {
|
|
36
63
|
raceConditions.push('Concurrent file writes to same resource may corrupt data');
|
|
37
64
|
recommendations.push('Use advisory locks or rename-and-swap pattern for file operations');
|
|
38
65
|
}
|
|
39
|
-
|
|
40
|
-
|
|
66
|
+
else if (fileMatched) {
|
|
67
|
+
suppressedCount += 1;
|
|
68
|
+
}
|
|
69
|
+
const sessionMatched = affirms(contract, SESSION_PATTERN);
|
|
70
|
+
if (sessionMatched && hasConcurrencyContext) {
|
|
41
71
|
sharedState.push('User session state (may be accessed from multiple tabs/devices)');
|
|
42
72
|
}
|
|
43
|
-
if (
|
|
73
|
+
else if (sessionMatched) {
|
|
74
|
+
suppressedCount += 1;
|
|
75
|
+
}
|
|
76
|
+
const cacheMatched = affirms(contract, CACHE_PATTERN);
|
|
77
|
+
if (cacheMatched && hasConcurrencyContext) {
|
|
44
78
|
sharedState.push('Global cache or configuration (requires synchronized access)');
|
|
45
79
|
}
|
|
46
|
-
|
|
80
|
+
else if (cacheMatched) {
|
|
81
|
+
suppressedCount += 1;
|
|
82
|
+
}
|
|
83
|
+
// General recommendations — only emitted once a race condition is actually
|
|
84
|
+
// grounded, otherwise a formatting-only spec would still surface generic
|
|
85
|
+
// "use database transactions" boilerplate (SPEC-1350 AC1).
|
|
47
86
|
if (raceConditions.length === 0) {
|
|
48
87
|
recommendations.push('No obvious race conditions detected, but test concurrent scenarios in integration tests');
|
|
49
88
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
else {
|
|
90
|
+
recommendations.push('Use database transactions for multi-step operations');
|
|
91
|
+
recommendations.push('Implement idempotency keys for all mutation endpoints');
|
|
92
|
+
}
|
|
93
|
+
return { hotPaths, raceConditions, sharedState, recommendations, suppressedCount };
|
|
53
94
|
}
|
|
54
95
|
// --- Scalability and risk ---
|
|
55
96
|
export function buildScalabilityAssessment(spec, knowledge, scenarios) {
|
|
@@ -19,6 +19,7 @@ import { analyzeMinimalImplementation, loadMinimalImplementationPolicy, } from '
|
|
|
19
19
|
import { detectChallengeCapabilities, } from './challenge-spec/scenarios-utils.js';
|
|
20
20
|
import { collectCapabilityScenarios } from './challenge-spec/scenario-collector.js';
|
|
21
21
|
import { buildChallengeReport, parseChallengeResolutionEvidence, } from './challenge-spec/challenge-report.js';
|
|
22
|
+
import { extractListItems, findMarkdownSectionRange, } from '../engine/spec-format/markdown-sections.js';
|
|
22
23
|
const ALL_FOCUS_AREAS = [
|
|
23
24
|
'failures',
|
|
24
25
|
'concurrency',
|
|
@@ -150,11 +151,10 @@ export async function handleChallengeSpec(args, server) {
|
|
|
150
151
|
failureScenarios.push(...collectCapabilityScenarios({ spec, specContent, knowledge, focusAreas, capabilities }));
|
|
151
152
|
// SPEC-612: Check for contradictions between outOfScope and acceptance criteria
|
|
152
153
|
if (spec.outOfScope !== undefined && spec.outOfScope.length > 0) {
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
.
|
|
157
|
-
.filter((line) => line.length > 0);
|
|
154
|
+
const criteriaRange = findMarkdownSectionRange(specContent, 'Acceptance Criteria');
|
|
155
|
+
const criteriaTexts = criteriaRange === null
|
|
156
|
+
? []
|
|
157
|
+
: extractListItems(specContent.slice(criteriaRange.contentStart, criteriaRange.end));
|
|
158
158
|
const contradictionResult = checkScopeContradictions(spec.outOfScope, criteriaTexts);
|
|
159
159
|
for (const c of contradictionResult.contradictions) {
|
|
160
160
|
failureScenarios.push({
|
|
@@ -171,9 +171,24 @@ export async function handleChallengeSpec(args, server) {
|
|
|
171
171
|
// SPEC-615 AC3: Check criteria against prior decisions for technology contradictions
|
|
172
172
|
await runPriorDecisionContradictions(projectId, spec.title, spec.tags, specContent, failureScenarios);
|
|
173
173
|
// 6. Generate concurrency analysis
|
|
174
|
-
const
|
|
174
|
+
const concurrencyResult = focusAreas.includes('concurrency') && capabilities.concurrency
|
|
175
175
|
? generateConcurrencyAnalysis(spec, specContent, knowledge)
|
|
176
|
-
: {
|
|
176
|
+
: {
|
|
177
|
+
hotPaths: [],
|
|
178
|
+
raceConditions: [],
|
|
179
|
+
sharedState: [],
|
|
180
|
+
recommendations: [],
|
|
181
|
+
suppressedCount: 0,
|
|
182
|
+
};
|
|
183
|
+
// SPEC-1350: concurrency candidates that matched a domain keyword but lacked
|
|
184
|
+
// a corroborating concurrency context are suppressed before risk/summary math.
|
|
185
|
+
const concurrencySuppressedCount = concurrencyResult.suppressedCount;
|
|
186
|
+
const concurrencyAnalysis = {
|
|
187
|
+
hotPaths: concurrencyResult.hotPaths,
|
|
188
|
+
raceConditions: concurrencyResult.raceConditions,
|
|
189
|
+
sharedState: concurrencyResult.sharedState,
|
|
190
|
+
recommendations: concurrencyResult.recommendations,
|
|
191
|
+
};
|
|
177
192
|
// Unsupported domain templates are removed before prioritization and risk calculation.
|
|
178
193
|
const actionableFailureScenarios = failureScenarios.filter((scenario) => isScenarioSupportedByCapabilities(scenario, capabilities));
|
|
179
194
|
const suppressedScenarioCount = failureScenarios.length - actionableFailureScenarios.length;
|
|
@@ -219,7 +234,7 @@ export async function handleChallengeSpec(args, server) {
|
|
|
219
234
|
summary: {
|
|
220
235
|
totalScenarios: failureScenarios.length,
|
|
221
236
|
actionableScenarios: failureScenariosScored.length,
|
|
222
|
-
suppressedLowRelevanceScenarios: suppressedScenarioCount,
|
|
237
|
+
suppressedLowRelevanceScenarios: suppressedScenarioCount + concurrencySuppressedCount,
|
|
223
238
|
shownByDefault: 3,
|
|
224
239
|
mustAddressBeforeCoding: prioritizedSummary,
|
|
225
240
|
criticalImpact: actionableFailureScenarios.filter((s) => s.impact === 'critical').length,
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
// tools/check-readiness.ts — Completeness checkpoint tool (SPEC-039, SPEC-314, SPEC-716)
|
|
2
2
|
import { specStore } from '../storage/index.js';
|
|
3
|
-
import { checkSpecReadiness } from '../engine/readiness-checker.js';
|
|
4
|
-
import { scoreSpecQuality } from '../engine/spec-quality-scorer.js';
|
|
5
3
|
import { buildCheckReadinessSummary } from '../engine/human-summary.js';
|
|
6
4
|
import { validateSpecFormat } from '../core/spec-validator.js';
|
|
7
5
|
import { resolveProjectId } from './resolve-project-id.js';
|
|
@@ -9,6 +7,7 @@ import { resolveProjectId } from './resolve-project-id.js';
|
|
|
9
7
|
const MAX_VISIBLE_BLOCKERS = 8;
|
|
10
8
|
const MAX_VISIBLE_WARNINGS = 8;
|
|
11
9
|
const MAX_VISIBLE_RECOMMENDATIONS = 5;
|
|
10
|
+
const CANONICAL_CRITERIA_MISSING = 'CANONICAL_CRITERIA_MISSING';
|
|
12
11
|
function formatScore(score) {
|
|
13
12
|
if (score >= 90) {
|
|
14
13
|
return `${score}/100 (Excellent)`;
|
|
@@ -21,6 +20,23 @@ function formatScore(score) {
|
|
|
21
20
|
}
|
|
22
21
|
return `${score}/100 (Not Ready)`;
|
|
23
22
|
}
|
|
23
|
+
function canonicalReadinessFailure(validationResult) {
|
|
24
|
+
const metrics = validationResult.metrics;
|
|
25
|
+
if (metrics === undefined || metrics.criteriaCount === 0) {
|
|
26
|
+
return CANONICAL_CRITERIA_MISSING;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function createFailClosedReport(specId, mode) {
|
|
31
|
+
return {
|
|
32
|
+
specId,
|
|
33
|
+
score: 0,
|
|
34
|
+
ready: false,
|
|
35
|
+
mode,
|
|
36
|
+
issues: { score: 0, breakdown: {}, blockers: [], warnings: [] },
|
|
37
|
+
recommendations: [],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
24
40
|
function formatReport(report) {
|
|
25
41
|
const lines = [];
|
|
26
42
|
lines.push(`# Readiness Report — ${report.specId}`);
|
|
@@ -109,20 +125,15 @@ export async function handleCheckReadiness(args) {
|
|
|
109
125
|
isError: true,
|
|
110
126
|
};
|
|
111
127
|
}
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
//
|
|
116
|
-
const [report, qualityReport, validationResult] = await Promise.all([
|
|
117
|
-
checkSpecReadiness(spec, mode),
|
|
118
|
-
scoreSpecQuality(spec),
|
|
119
|
-
validateSpecFormat(spec, { readinessMode: mode, skipQuality: true }),
|
|
120
|
-
]);
|
|
121
|
-
// SPEC-716: Ground ready flag in unified ValidationResult.
|
|
128
|
+
// validateSpecFormat owns the readiness and quality evaluation so the response
|
|
129
|
+
// cannot combine separately computed evidence from different reads of spec.md.
|
|
130
|
+
const validationResult = await validateSpecFormat(spec, { readinessMode: mode });
|
|
131
|
+
// SPEC-716: Ground ready flag in unified SpecValidationResult.
|
|
122
132
|
// Only non-file-access errors from validateSpecFormat are surfaced in the
|
|
123
133
|
// report — MISSING_FRONTMATTER due to file-not-found is best-effort since
|
|
124
134
|
// the readiness checker already handles missing files gracefully.
|
|
125
135
|
const vr = validationResult;
|
|
136
|
+
const report = vr.readinessReport ?? createFailClosedReport(spec.id, mode);
|
|
126
137
|
const hardFormatErrors = vr.errors.filter((e) => e.code !== 'MISSING_FRONTMATTER' && !(e.code === 'READINESS_CHECK_FAILED'));
|
|
127
138
|
const hardFormatMessages = hardFormatErrors.map((e) => e.message);
|
|
128
139
|
const formatWarnings = vr.warnings
|
|
@@ -142,11 +153,24 @@ export async function handleCheckReadiness(args) {
|
|
|
142
153
|
// Ground ready: only false if BOTH readiness report and format gate agree
|
|
143
154
|
// (or format has hard non-file errors)
|
|
144
155
|
report.ready = report.ready && hardFormatErrors.length === 0;
|
|
156
|
+
const canonicalFailure = canonicalReadinessFailure(vr);
|
|
157
|
+
if (canonicalFailure !== null) {
|
|
158
|
+
const target = mode === 'strict' ? report.issues.blockers : report.issues.warnings;
|
|
159
|
+
if (!target.includes(canonicalFailure)) {
|
|
160
|
+
target.push(canonicalFailure);
|
|
161
|
+
}
|
|
162
|
+
if (!report.recommendations.includes(`Resolve ${canonicalFailure} before implementation.`)) {
|
|
163
|
+
report.recommendations.push(`Resolve ${canonicalFailure} before implementation.`);
|
|
164
|
+
}
|
|
165
|
+
// Lenient mode is advisory, but it must not present a contradictory
|
|
166
|
+
// canonical validation result as an implementation-ready pass.
|
|
167
|
+
report.ready = false;
|
|
168
|
+
}
|
|
145
169
|
// SPEC-612: recommend adding outOfScope items when none are declared
|
|
146
170
|
if (spec.outOfScope === undefined || spec.outOfScope.length === 0) {
|
|
147
171
|
report.recommendations.push('Add outOfScope items to the spec frontmatter to declare explicit scope boundaries (SPEC-612). This reduces scope creep during implementation.');
|
|
148
172
|
}
|
|
149
|
-
const qualityScore = qualityReport
|
|
173
|
+
const qualityScore = vr.qualityReport?.score;
|
|
150
174
|
const formatted = formatReport(report);
|
|
151
175
|
const humanSummary = buildCheckReadinessSummary(report.score, report.issues.blockers.length);
|
|
152
176
|
return {
|
|
@@ -161,7 +185,7 @@ export async function handleCheckReadiness(args) {
|
|
|
161
185
|
mode: report.mode,
|
|
162
186
|
issues: report.issues,
|
|
163
187
|
recommendations: report.recommendations,
|
|
164
|
-
qualityScore,
|
|
188
|
+
...(qualityScore === undefined ? {} : { qualityScore }),
|
|
165
189
|
humanSummary,
|
|
166
190
|
validationResult: vr,
|
|
167
191
|
},
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import { readTelemetryConfig, writeTelemetryConfig, TELEMETRY_CONSENT_VERSION, } from '../engine/telemetry/index.js';
|
|
2
2
|
import { compactResult, compactError, formatKeyValue } from './output-formatter.js';
|
|
3
|
+
function isLoopbackHost(hostname) {
|
|
4
|
+
return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';
|
|
5
|
+
}
|
|
6
|
+
function isTelemetryConfigured() {
|
|
7
|
+
const endpoint = process.env.PLANU_TELEMETRY_ENDPOINT?.trim();
|
|
8
|
+
const token = process.env.PLANU_TELEMETRY_TOKEN?.trim();
|
|
9
|
+
if (!endpoint || !token) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const parsed = new URL(endpoint);
|
|
14
|
+
return (parsed.username === '' &&
|
|
15
|
+
parsed.password === '' &&
|
|
16
|
+
(parsed.protocol === 'https:' ||
|
|
17
|
+
(parsed.protocol === 'http:' && isLoopbackHost(parsed.hostname))));
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
3
23
|
export async function handleConfigureTelemetry(input) {
|
|
4
24
|
try {
|
|
5
25
|
const existing = await readTelemetryConfig();
|
|
6
26
|
const enabled = existing?.enabled === true && existing.consentVersion === TELEMETRY_CONSENT_VERSION;
|
|
27
|
+
const configured = isTelemetryConfigured();
|
|
7
28
|
if (input.action === 'status') {
|
|
8
29
|
const observatoryStatus = existing?.enableObservatory === true
|
|
9
30
|
? ' Observatory: ENABLED (cross-project insights active).'
|
|
@@ -11,9 +32,12 @@ export async function handleConfigureTelemetry(input) {
|
|
|
11
32
|
const result = {
|
|
12
33
|
action: 'status',
|
|
13
34
|
enabled,
|
|
35
|
+
configured,
|
|
14
36
|
consentVersion: existing?.consentVersion,
|
|
15
37
|
message: (enabled
|
|
16
|
-
?
|
|
38
|
+
? configured
|
|
39
|
+
? 'Telemetry is ENABLED and configured. Anonymous usage events may be sent to help improve Planu.'
|
|
40
|
+
: 'Telemetry consent is ENABLED, but delivery is inactive: configure valid PLANU_TELEMETRY_ENDPOINT and PLANU_TELEMETRY_TOKEN values.'
|
|
17
41
|
: 'Telemetry is DISABLED. No data is being collected.') + observatoryStatus,
|
|
18
42
|
};
|
|
19
43
|
return compactResult(formatKeyValue(result));
|
|
@@ -31,8 +55,11 @@ export async function handleConfigureTelemetry(input) {
|
|
|
31
55
|
const result = {
|
|
32
56
|
action: 'enable',
|
|
33
57
|
enabled: true,
|
|
58
|
+
configured,
|
|
34
59
|
consentVersion: TELEMETRY_CONSENT_VERSION,
|
|
35
|
-
message:
|
|
60
|
+
message: (configured
|
|
61
|
+
? 'Telemetry ENABLED and configured. Only anonymous usage data is collected — '
|
|
62
|
+
: 'Telemetry consent ENABLED, but delivery is inactive until valid PLANU_TELEMETRY_ENDPOINT and PLANU_TELEMETRY_TOKEN values are configured. ') +
|
|
36
63
|
'no paths, emails, identifiers, source content, or raw errors. ' +
|
|
37
64
|
'Run configure_telemetry with action=disable to opt out anytime.' +
|
|
38
65
|
observatoryNote,
|
|
@@ -49,6 +76,7 @@ export async function handleConfigureTelemetry(input) {
|
|
|
49
76
|
const result = {
|
|
50
77
|
action: 'disable',
|
|
51
78
|
enabled: false,
|
|
79
|
+
configured,
|
|
52
80
|
consentVersion: existing?.consentVersion,
|
|
53
81
|
message: 'Telemetry DISABLED. No usage data will be sent.',
|
|
54
82
|
};
|
|
@@ -13,4 +13,11 @@ export declare function buildSpecContext(params: CreateSpecInput): Promise<{
|
|
|
13
13
|
export declare function buildSplitResult(splitSuggestion: ReturnType<typeof analyzeSplit>, experienceLevel: string | undefined): Record<string, unknown> | undefined;
|
|
14
14
|
/** Infer meaningful tags from title and description when no tags were provided. */
|
|
15
15
|
export declare function inferTagsFromContent(title: string, description: string, type?: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* SPEC-1351: Recompute the next spec id from a fresh store + filesystem scan.
|
|
18
|
+
* Called once (unlocked) during prepare to pick a candidate id, and again
|
|
19
|
+
* inside the exclusive create-spec write lock immediately before persisting
|
|
20
|
+
* so the id actually written can never collide under concurrency.
|
|
21
|
+
*/
|
|
22
|
+
export declare function computeNextSpecId(projectPath: string, projectId: string): Promise<string>;
|
|
16
23
|
//# sourceMappingURL=spec-builder.d.ts.map
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
// tools/create-spec/spec-builder.ts — Builds the Spec object and estimation (SPEC-461: lean format).
|
|
3
3
|
// Extracted from create-spec.ts to keep file sizes within limits.
|
|
4
4
|
import { hashProjectPath, knowledgeStore, specStore, globalStore } from '../../storage/index.js';
|
|
5
|
-
import { getCurrentTier } from '../license-gate.js';
|
|
6
|
-
import { checkLimits } from '../../engine/license-validator.js';
|
|
7
5
|
import { inferDifficulty, calculateEstimation } from '../../engine/estimator.js';
|
|
8
6
|
import { analyzeSplit, formatSplitSuggestion } from '../../engine/spec-splitter.js';
|
|
9
7
|
import { isLegacyLocation, getSpecFileNames } from '../../engine/planu-config-writer.js';
|
|
@@ -25,19 +23,13 @@ export async function buildSpecContext(params) {
|
|
|
25
23
|
const projectId = hashProjectPath(projectPath);
|
|
26
24
|
const knowledge = await knowledgeStore.getKnowledge(projectId);
|
|
27
25
|
const existingSpecs = await specStore.listSpecs(projectId);
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
/* v8 ignore stop */
|
|
37
|
-
// Generate spec ID: combine store IDs + filesystem IDs for global max
|
|
38
|
-
const fsSpecIds = await scanFilesystemSpecIds(projectPath);
|
|
39
|
-
const allSpecs = [...existingSpecs, ...fsSpecIds.map((id) => ({ id }))];
|
|
40
|
-
const specId = generateSpecId(allSpecs);
|
|
26
|
+
// Generate spec ID: combine store IDs + filesystem IDs for global max.
|
|
27
|
+
// SPEC-1351: this snapshot read is NOT locked — under concurrency two callers
|
|
28
|
+
// can compute the same "next" id here. create-spec.ts re-derives the id via
|
|
29
|
+
// computeNextSpecId() again inside its exclusive per-project write lock right
|
|
30
|
+
// before persisting, so a stale id computed here is only ever a starting
|
|
31
|
+
// candidate, never the value that actually gets written to disk.
|
|
32
|
+
const specId = await computeNextSpecId(projectPath, projectId);
|
|
41
33
|
const slug = slugify(title);
|
|
42
34
|
// Check for duplicate title
|
|
43
35
|
const duplicate = existingSpecs.find((s) => slugify(s.title) === slug);
|
|
@@ -220,6 +212,18 @@ function buildTags(tags, feature, _title, _description, _type) {
|
|
|
220
212
|
const result = feature ? [...new Set([...explicitTags, slugify(feature)])] : explicitTags;
|
|
221
213
|
return [...new Set(result)];
|
|
222
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* SPEC-1351: Recompute the next spec id from a fresh store + filesystem scan.
|
|
217
|
+
* Called once (unlocked) during prepare to pick a candidate id, and again
|
|
218
|
+
* inside the exclusive create-spec write lock immediately before persisting
|
|
219
|
+
* so the id actually written can never collide under concurrency.
|
|
220
|
+
*/
|
|
221
|
+
export async function computeNextSpecId(projectPath, projectId) {
|
|
222
|
+
const existingSpecs = await specStore.listSpecs(projectId);
|
|
223
|
+
const fsSpecIds = await scanFilesystemSpecIds(projectPath);
|
|
224
|
+
const allSpecs = [...existingSpecs, ...fsSpecIds.map((id) => ({ id }))];
|
|
225
|
+
return generateSpecId(allSpecs);
|
|
226
|
+
}
|
|
223
227
|
/* v8 ignore start -- filesystem scanning is best-effort, tested via integration */
|
|
224
228
|
/** Scan filesystem for SPEC-XXX directories to find max ID globally. */
|
|
225
229
|
async function scanFilesystemSpecIds(projectPath) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CreateSpecInput, ToolResult } from '../types/index.js';
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
export declare function resolveGroundedVerificationCommands(projectPath: string, testPaths: string[]): Promise<string[]>;
|
|
3
4
|
export declare function handleCreateSpec(inputParams: CreateSpecInput, server?: McpServer): Promise<ToolResult>;
|
|
4
5
|
//# sourceMappingURL=create-spec.d.ts.map
|