@planu/cli 4.14.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- 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 +2 -2
- 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 +1 -1
- 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 +10 -1
- package/dist/engine/evidence-gates/artifact-reader.js +115 -2
- 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/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/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 +10 -10
- package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-x64.node.sbom.json +10 -10
- package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +10 -10
- package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +10 -10
- package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +10 -10
- package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +10 -10
- package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +10 -10
- package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +10 -10
- package/dist/engine/readiness-checker.d.ts +1 -16
- package/dist/engine/readiness-checker.js +27 -88
- 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 +77 -18
- 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/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/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 +27 -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 +10 -0
- 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.js +5 -5
- package/dist/tools/check-readiness.js +1 -1
- package/dist/tools/configure-telemetry.js +30 -2
- package/dist/tools/create-spec/spec-builder.js +0 -11
- package/dist/tools/create-spec.d.ts +1 -0
- package/dist/tools/create-spec.js +444 -239
- 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 +17 -8
- 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 +1 -1
- 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/done-receipt-verifier.js +40 -27
- package/dist/tools/update-status/evidence-gate.js +36 -1
- package/dist/tools/update-status/file-sync.d.ts +2 -1
- package/dist/tools/update-status/file-sync.js +57 -6
- package/dist/tools/update-status/index.d.ts +2 -0
- package/dist/tools/update-status/index.js +95 -58
- 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 +32 -15
- 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/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-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 +2 -6
- package/dist/types/index.js +1 -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 +14 -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 +29 -0
- package/dist/types/spec-format.d.ts +24 -0
- package/dist/types/telemetry.d.ts +4 -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 +2 -2
- package/package.json +16 -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,8 +1,26 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
1
2
|
import type { AbortableProcessOptions, AbortableProcessResult } from '../types/abortable-process.js';
|
|
3
|
+
export declare const PROCESS_TERMINATION_GRACE_MS = 75;
|
|
4
|
+
export declare const PROCESS_TREE_EXTINCTION_TIMEOUT_MS = 1000;
|
|
5
|
+
export declare const PROCESS_CHILD_CLOSE_TIMEOUT_MS = 1000;
|
|
6
|
+
/** Isolates platform-specific process supervision in unit tests without changing host state. */
|
|
7
|
+
export declare function configureAbortableProcessRunnerForTests(options?: {
|
|
8
|
+
platform?: NodeJS.Platform;
|
|
9
|
+
spawnProcess?: typeof spawn;
|
|
10
|
+
isProcessGroupAlive?: (pid: number) => boolean;
|
|
11
|
+
}): void;
|
|
12
|
+
export declare class ProcessTreeTerminationError extends Error {
|
|
13
|
+
readonly code = "PROCESS_TREE_TERMINATION_UNVERIFIED";
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
16
|
+
export declare class ChildProcessCloseTimeoutError extends Error {
|
|
17
|
+
readonly code = "PROCESS_CLOSE_UNOBSERVED";
|
|
18
|
+
constructor();
|
|
19
|
+
}
|
|
2
20
|
/**
|
|
3
21
|
* Runs a validation command in its own process group. Cancellation and timeouts
|
|
4
|
-
* terminate the complete group and settle only after
|
|
5
|
-
*
|
|
22
|
+
* terminate the complete group and settle only after child closure or a bounded,
|
|
23
|
+
* typed close-observation failure, so a cancelled gate cannot publish late evidence.
|
|
6
24
|
*/
|
|
7
25
|
export declare function runAbortableProcess(command: string, args: string[], options: AbortableProcessOptions): Promise<AbortableProcessResult>;
|
|
8
26
|
//# sourceMappingURL=abortable-process-runner.d.ts.map
|
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable max-lines-per-function -- process-tree termination and single-settlement share one ownership boundary. */
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
2
3
|
import { getExecutionSignal, remainingExecutionMs } from './execution/context.js';
|
|
3
|
-
const
|
|
4
|
+
export const PROCESS_TERMINATION_GRACE_MS = 75;
|
|
5
|
+
export const PROCESS_TREE_EXTINCTION_TIMEOUT_MS = 1_000;
|
|
6
|
+
export const PROCESS_CHILD_CLOSE_TIMEOUT_MS = 1_000;
|
|
7
|
+
let platformOverrideForTests;
|
|
8
|
+
let spawnOverrideForTests;
|
|
9
|
+
let processGroupLivenessOverrideForTests;
|
|
10
|
+
/** Isolates platform-specific process supervision in unit tests without changing host state. */
|
|
11
|
+
export function configureAbortableProcessRunnerForTests(options = {}) {
|
|
12
|
+
platformOverrideForTests = options.platform;
|
|
13
|
+
spawnOverrideForTests = options.spawnProcess;
|
|
14
|
+
processGroupLivenessOverrideForTests = options.isProcessGroupAlive;
|
|
15
|
+
}
|
|
16
|
+
function runtimePlatform() {
|
|
17
|
+
return platformOverrideForTests ?? process.platform;
|
|
18
|
+
}
|
|
19
|
+
function spawnProcess(...args) {
|
|
20
|
+
return (spawnOverrideForTests ?? spawn)(...args);
|
|
21
|
+
}
|
|
4
22
|
function operationSignal(signal) {
|
|
5
23
|
const parentSignal = getExecutionSignal();
|
|
6
24
|
if (signal === undefined) {
|
|
@@ -11,29 +29,121 @@ function operationSignal(signal) {
|
|
|
11
29
|
}
|
|
12
30
|
return AbortSignal.any([signal, parentSignal]);
|
|
13
31
|
}
|
|
32
|
+
function immediateAbortResult(reason) {
|
|
33
|
+
return {
|
|
34
|
+
stdout: '',
|
|
35
|
+
stderr: '',
|
|
36
|
+
status: null,
|
|
37
|
+
signal: null,
|
|
38
|
+
error: abortError(reason),
|
|
39
|
+
timedOut: false,
|
|
40
|
+
aborted: true,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function appendOutput(current, chunk, maxBufferBytes) {
|
|
44
|
+
return `${current}${chunk.toString('utf8')}`.slice(-maxBufferBytes);
|
|
45
|
+
}
|
|
46
|
+
function detachOwnedStreams(child, onStdout, onStderr) {
|
|
47
|
+
child.stdout?.removeListener('data', onStdout);
|
|
48
|
+
child.stderr?.removeListener('data', onStderr);
|
|
49
|
+
child.stdout?.destroy();
|
|
50
|
+
child.stderr?.destroy();
|
|
51
|
+
}
|
|
52
|
+
function delay(ms) {
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
const timer = setTimeout(resolve, ms);
|
|
55
|
+
timer.unref();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function processGroupIsAlive(pid) {
|
|
59
|
+
if (processGroupLivenessOverrideForTests !== undefined) {
|
|
60
|
+
return processGroupLivenessOverrideForTests(pid);
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
process.kill(-pid, 0);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return error.code === 'EPERM';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function awaitProcessGroupExtinction(pid) {
|
|
71
|
+
const deadlineAt = Date.now() + PROCESS_TREE_EXTINCTION_TIMEOUT_MS;
|
|
72
|
+
while (processGroupIsAlive(pid) && Date.now() < deadlineAt) {
|
|
73
|
+
await delay(Math.min(10, Math.max(1, deadlineAt - Date.now())));
|
|
74
|
+
}
|
|
75
|
+
return !processGroupIsAlive(pid);
|
|
76
|
+
}
|
|
77
|
+
async function terminateWindowsTree(child, childPid) {
|
|
78
|
+
if (childPid === undefined) {
|
|
79
|
+
child.kill('SIGKILL');
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const taskkill = spawnProcess('taskkill', ['/pid', String(childPid), '/T', '/F'], {
|
|
84
|
+
stdio: 'ignore',
|
|
85
|
+
windowsHide: true,
|
|
86
|
+
});
|
|
87
|
+
const succeeded = await new Promise((resolve) => {
|
|
88
|
+
let settled = false;
|
|
89
|
+
const finish = (value) => {
|
|
90
|
+
if (settled) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
settled = true;
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
resolve(value);
|
|
96
|
+
};
|
|
97
|
+
const timer = setTimeout(() => {
|
|
98
|
+
taskkill.kill('SIGKILL');
|
|
99
|
+
finish(false);
|
|
100
|
+
}, PROCESS_TREE_EXTINCTION_TIMEOUT_MS);
|
|
101
|
+
timer.unref();
|
|
102
|
+
taskkill.once('error', () => {
|
|
103
|
+
finish(false);
|
|
104
|
+
});
|
|
105
|
+
taskkill.once('close', (status) => {
|
|
106
|
+
finish(status === 0);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
if (!succeeded) {
|
|
110
|
+
child.kill('SIGKILL');
|
|
111
|
+
}
|
|
112
|
+
return succeeded;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
child.kill('SIGKILL');
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export class ProcessTreeTerminationError extends Error {
|
|
120
|
+
code = 'PROCESS_TREE_TERMINATION_UNVERIFIED';
|
|
121
|
+
constructor() {
|
|
122
|
+
super('[Planu] PROCESS_TREE_TERMINATION_UNVERIFIED');
|
|
123
|
+
this.name = 'ProcessTreeTerminationError';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export class ChildProcessCloseTimeoutError extends Error {
|
|
127
|
+
code = 'PROCESS_CLOSE_UNOBSERVED';
|
|
128
|
+
constructor() {
|
|
129
|
+
super('[Planu] PROCESS_CLOSE_UNOBSERVED');
|
|
130
|
+
this.name = 'ChildProcessCloseTimeoutError';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
14
133
|
/**
|
|
15
134
|
* Runs a validation command in its own process group. Cancellation and timeouts
|
|
16
|
-
* terminate the complete group and settle only after
|
|
17
|
-
*
|
|
135
|
+
* terminate the complete group and settle only after child closure or a bounded,
|
|
136
|
+
* typed close-observation failure, so a cancelled gate cannot publish late evidence.
|
|
18
137
|
*/
|
|
19
138
|
export function runAbortableProcess(command, args, options) {
|
|
139
|
+
const signal = operationSignal(options.signal);
|
|
140
|
+
if (signal?.aborted === true) {
|
|
141
|
+
return Promise.resolve(immediateAbortResult(signal.reason));
|
|
142
|
+
}
|
|
20
143
|
return new Promise((resolve) => {
|
|
21
|
-
const
|
|
22
|
-
if (signal?.aborted === true) {
|
|
23
|
-
resolve({
|
|
24
|
-
stdout: '',
|
|
25
|
-
stderr: '',
|
|
26
|
-
status: null,
|
|
27
|
-
signal: null,
|
|
28
|
-
error: abortError(signal.reason),
|
|
29
|
-
timedOut: false,
|
|
30
|
-
aborted: true,
|
|
31
|
-
});
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const child = spawn(command, args, {
|
|
144
|
+
const child = spawnProcess(command, args, {
|
|
35
145
|
cwd: options.cwd,
|
|
36
|
-
detached:
|
|
146
|
+
detached: runtimePlatform() !== 'win32',
|
|
37
147
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
38
148
|
});
|
|
39
149
|
let stdout = '';
|
|
@@ -42,53 +152,121 @@ export function runAbortableProcess(command, args, options) {
|
|
|
42
152
|
let timedOut = false;
|
|
43
153
|
let aborted = false;
|
|
44
154
|
let processError;
|
|
45
|
-
let
|
|
46
|
-
let
|
|
155
|
+
let terminationStarted = false;
|
|
156
|
+
let observedTerminationSignal = null;
|
|
157
|
+
let closeResult;
|
|
158
|
+
let terminationResolved = false;
|
|
159
|
+
let processTreeExtinct = false;
|
|
160
|
+
let closeFallbackTimer;
|
|
161
|
+
const childPid = child.pid;
|
|
47
162
|
const parentRemainingMs = remainingExecutionMs();
|
|
48
163
|
const timeoutMs = Math.max(0, Math.min(options.timeoutMs, parentRemainingMs));
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
164
|
+
const onStdout = (chunk) => {
|
|
165
|
+
stdout = appendOutput(stdout, chunk, options.maxBufferBytes);
|
|
166
|
+
};
|
|
167
|
+
const onStderr = (chunk) => {
|
|
168
|
+
stderr = appendOutput(stderr, chunk, options.maxBufferBytes);
|
|
169
|
+
};
|
|
170
|
+
child.stdout?.on('data', onStdout);
|
|
171
|
+
child.stderr?.on('data', onStderr);
|
|
172
|
+
const finish = (status, closeSignal, forced = false) => {
|
|
173
|
+
if (settled) {
|
|
58
174
|
return;
|
|
59
175
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
176
|
+
settled = true;
|
|
177
|
+
clearTimeout(timer);
|
|
178
|
+
if (closeFallbackTimer !== undefined) {
|
|
179
|
+
clearTimeout(closeFallbackTimer);
|
|
180
|
+
closeFallbackTimer = undefined;
|
|
181
|
+
}
|
|
182
|
+
signal?.removeEventListener('abort', onAbort);
|
|
183
|
+
child.removeListener('error', onError);
|
|
184
|
+
child.removeListener('close', onClose);
|
|
185
|
+
if (forced) {
|
|
186
|
+
detachOwnedStreams(child, onStdout, onStderr);
|
|
187
|
+
}
|
|
188
|
+
resolve({
|
|
189
|
+
stdout,
|
|
190
|
+
stderr,
|
|
191
|
+
status,
|
|
192
|
+
signal: closeSignal,
|
|
193
|
+
...(processError ? { error: processError } : {}),
|
|
194
|
+
timedOut,
|
|
195
|
+
aborted,
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
const finishTerminatedProcess = () => {
|
|
199
|
+
if (!terminationResolved) {
|
|
67
200
|
return;
|
|
68
201
|
}
|
|
69
|
-
|
|
70
|
-
|
|
202
|
+
if (!processTreeExtinct) {
|
|
203
|
+
finish(null, observedTerminationSignal, true);
|
|
204
|
+
return;
|
|
71
205
|
}
|
|
72
|
-
|
|
73
|
-
|
|
206
|
+
if (closeResult === undefined) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
finish(closeResult[0], closeResult[1] ?? observedTerminationSignal, true);
|
|
210
|
+
};
|
|
211
|
+
const scheduleCloseFallback = () => {
|
|
212
|
+
if (closeFallbackTimer !== undefined || closeResult !== undefined || !processTreeExtinct) {
|
|
213
|
+
return;
|
|
74
214
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
215
|
+
closeFallbackTimer = setTimeout(() => {
|
|
216
|
+
closeFallbackTimer = undefined;
|
|
217
|
+
if (settled || closeResult !== undefined || !terminationResolved || !processTreeExtinct) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
processError = new ChildProcessCloseTimeoutError();
|
|
221
|
+
finish(null, observedTerminationSignal, true);
|
|
222
|
+
}, PROCESS_CHILD_CLOSE_TIMEOUT_MS);
|
|
223
|
+
closeFallbackTimer.unref();
|
|
224
|
+
};
|
|
225
|
+
const terminateTree = () => {
|
|
226
|
+
if (terminationStarted || settled) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
terminationStarted = true;
|
|
230
|
+
void (async () => {
|
|
231
|
+
if (runtimePlatform() === 'win32') {
|
|
232
|
+
processTreeExtinct = await terminateWindowsTree(child, childPid);
|
|
233
|
+
}
|
|
234
|
+
else if (childPid !== undefined) {
|
|
235
|
+
try {
|
|
236
|
+
process.kill(-childPid, 'SIGTERM');
|
|
237
|
+
observedTerminationSignal = 'SIGTERM';
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
child.kill('SIGTERM');
|
|
241
|
+
}
|
|
242
|
+
await delay(PROCESS_TERMINATION_GRACE_MS);
|
|
243
|
+
if (processGroupIsAlive(childPid)) {
|
|
244
|
+
try {
|
|
245
|
+
process.kill(-childPid, 'SIGKILL');
|
|
246
|
+
observedTerminationSignal = 'SIGKILL';
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
child.kill('SIGKILL');
|
|
250
|
+
observedTerminationSignal = 'SIGKILL';
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
processTreeExtinct = await awaitProcessGroupExtinction(childPid);
|
|
78
254
|
}
|
|
79
|
-
|
|
255
|
+
else {
|
|
80
256
|
child.kill('SIGKILL');
|
|
81
257
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const [status, closeSignal] = deferredClose;
|
|
85
|
-
deferredClose = undefined;
|
|
86
|
-
finish(status, closeSignal);
|
|
258
|
+
if (!processTreeExtinct) {
|
|
259
|
+
processError = new ProcessTreeTerminationError();
|
|
87
260
|
}
|
|
88
|
-
|
|
89
|
-
|
|
261
|
+
terminationResolved = true;
|
|
262
|
+
finishTerminatedProcess();
|
|
263
|
+
scheduleCloseFallback();
|
|
264
|
+
})();
|
|
90
265
|
};
|
|
91
266
|
const onAbort = () => {
|
|
267
|
+
if (terminationStarted || settled) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
92
270
|
aborted = true;
|
|
93
271
|
processError = abortError(signal?.reason);
|
|
94
272
|
terminateTree();
|
|
@@ -101,35 +279,26 @@ export function runAbortableProcess(command, args, options) {
|
|
|
101
279
|
};
|
|
102
280
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
103
281
|
const timer = setTimeout(() => {
|
|
282
|
+
if (terminationStarted || settled) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
104
285
|
timedOut = true;
|
|
105
286
|
processError = new Error(`Process timed out after ${String(timeoutMs)}ms`);
|
|
106
287
|
terminateTree();
|
|
107
288
|
}, timeoutMs);
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
289
|
+
const onError = (error) => {
|
|
290
|
+
processError = error;
|
|
291
|
+
};
|
|
292
|
+
const onClose = (status, closeSignal) => {
|
|
293
|
+
if (terminationStarted) {
|
|
294
|
+
closeResult = [status, closeSignal];
|
|
295
|
+
finishTerminatedProcess();
|
|
114
296
|
return;
|
|
115
297
|
}
|
|
116
|
-
|
|
117
|
-
clearTimeout(timer);
|
|
118
|
-
signal?.removeEventListener('abort', onAbort);
|
|
119
|
-
resolve({
|
|
120
|
-
stdout,
|
|
121
|
-
stderr,
|
|
122
|
-
status,
|
|
123
|
-
signal: closeSignal,
|
|
124
|
-
...(processError ? { error: processError } : {}),
|
|
125
|
-
timedOut,
|
|
126
|
-
aborted,
|
|
127
|
-
});
|
|
298
|
+
finish(status, closeSignal);
|
|
128
299
|
};
|
|
129
|
-
child.on('error',
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
child.on('close', finish);
|
|
300
|
+
child.on('error', onError);
|
|
301
|
+
child.on('close', onClose);
|
|
133
302
|
});
|
|
134
303
|
}
|
|
135
304
|
function abortError(reason) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// engine/ambiguity-scorer.ts — SPEC-632: Detect undefined units and vague triggers in criteria
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import {
|
|
3
|
+
import { extractAcceptanceCriteriaTexts } from './spec-format/acceptance-criteria.js';
|
|
4
4
|
const VAGUE_UNITS = {
|
|
5
5
|
fast: 'No latency target specified (e.g. "< 200ms")',
|
|
6
6
|
slow: 'No latency target specified (e.g. "> 5s")',
|
|
@@ -96,27 +96,6 @@ export function scoreAmbiguity(criteriaLines) {
|
|
|
96
96
|
: [];
|
|
97
97
|
return { score, violations, blockers };
|
|
98
98
|
}
|
|
99
|
-
/** Minimal criteria extractor — same logic as readiness-checker without the full dependency chain. */
|
|
100
|
-
function extractLines(body) {
|
|
101
|
-
const lines = body.split('\n');
|
|
102
|
-
const result = [];
|
|
103
|
-
let inSection = false;
|
|
104
|
-
for (const raw of lines) {
|
|
105
|
-
const line = raw.trim();
|
|
106
|
-
if (/^#{1,6}\s+/.test(line)) {
|
|
107
|
-
inSection = /^#{1,6}\s+(acceptance\s+criteria|criteria|criterios)\b/i.test(line);
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
if (/^- \[[ x]\]/i.test(line) || /^- .*\bgiven\b.*\bwhen\b.*\bthen\b/i.test(line)) {
|
|
111
|
-
result.push(line);
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
if (inSection && /^- \S/.test(line)) {
|
|
115
|
-
result.push(line);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return result;
|
|
119
|
-
}
|
|
120
99
|
/**
|
|
121
100
|
* SPEC-632: Read spec file at path, extract criteria, and return an AmbiguityReport.
|
|
122
101
|
* Returns null if file cannot be read (best-effort, never blocks).
|
|
@@ -124,12 +103,11 @@ function extractLines(body) {
|
|
|
124
103
|
export async function scoreAmbiguityFromPath(specPath) {
|
|
125
104
|
try {
|
|
126
105
|
const raw = await readFile(specPath, 'utf-8');
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
if (lines.length === 0) {
|
|
106
|
+
const criteria = extractAcceptanceCriteriaTexts(raw, { allowLegacyBodyFallback: false });
|
|
107
|
+
if (criteria.length === 0) {
|
|
130
108
|
return null;
|
|
131
109
|
}
|
|
132
|
-
return scoreAmbiguity(
|
|
110
|
+
return scoreAmbiguity(criteria);
|
|
133
111
|
}
|
|
134
112
|
catch {
|
|
135
113
|
return null;
|
|
@@ -15,16 +15,12 @@ export const BUILTIN_SCOPE_MAPPINGS = [
|
|
|
15
15
|
'validate',
|
|
16
16
|
'analyze_spec_dependencies',
|
|
17
17
|
'export_spec',
|
|
18
|
-
'export_session',
|
|
19
|
-
'list_sessions',
|
|
20
18
|
'hook_status',
|
|
21
19
|
'worker_status',
|
|
22
|
-
'webhook_status',
|
|
23
20
|
'token_usage',
|
|
24
21
|
'usage_report',
|
|
25
22
|
'usage_stats',
|
|
26
23
|
'llm_provider_status',
|
|
27
|
-
'license_status',
|
|
28
24
|
'security_report',
|
|
29
25
|
'pr_status',
|
|
30
26
|
'agent_swarm_status',
|
|
@@ -56,8 +52,6 @@ export const BUILTIN_SCOPE_MAPPINGS = [
|
|
|
56
52
|
'configure_llm_providers',
|
|
57
53
|
'start_hooks',
|
|
58
54
|
'stop_hooks',
|
|
59
|
-
'start_webhook',
|
|
60
|
-
'stop_webhook',
|
|
61
55
|
'start_dashboard',
|
|
62
56
|
'stop_dashboard',
|
|
63
57
|
'manage_trash',
|
|
@@ -74,7 +68,7 @@ export const BUILTIN_SCOPE_MAPPINGS = [
|
|
|
74
68
|
},
|
|
75
69
|
{
|
|
76
70
|
scope: 'planu:admin',
|
|
77
|
-
tools: ['configure_auth', '
|
|
71
|
+
tools: ['configure_auth', 'activate_group'],
|
|
78
72
|
},
|
|
79
73
|
];
|
|
80
74
|
/**
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
// engine/autopilot/state-updater.ts — SPEC-459: Auto-update external project status on every status change
|
|
3
3
|
// Fire-and-forget: never blocks the event pipeline, never throws to callers.
|
|
4
4
|
// SPEC-753: File-lock applied to all writes; self-healing on corrupt reads.
|
|
5
|
-
import { readFile
|
|
6
|
-
import { join
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
7
|
import { withStatusLock } from '../../storage/status-store/file-lock.js';
|
|
8
8
|
import { validateStatusJson, rebuildStatusFromFrontmatters, writeRebuiltStatus, } from '../../storage/status-store/self-healing.js';
|
|
9
9
|
import { syncVersionField } from '../../storage/status-store/version-sync.js';
|
|
10
10
|
import { hashProjectPath, projectDataDir } from '../../storage/base-store.js';
|
|
11
|
+
import { atomicStatusWrite } from '../../storage/status-store/atomic-status-write.js';
|
|
11
12
|
const STATUS_FILENAME = 'status.json';
|
|
12
13
|
const MAX_RECENT_CHANGES = 20;
|
|
13
14
|
function getStatusPath(projectPath) {
|
|
@@ -52,8 +53,7 @@ async function loadStatus(projectPath) {
|
|
|
52
53
|
}
|
|
53
54
|
async function saveStatus(projectPath, status) {
|
|
54
55
|
const filePath = getStatusPath(projectPath);
|
|
55
|
-
await
|
|
56
|
-
await writeFile(filePath, JSON.stringify(status, null, 2), 'utf-8');
|
|
56
|
+
await atomicStatusWrite(filePath, status);
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
59
|
* Record a spec status change and recalculate counts.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { reportClassifiedDegradation } from '../../../errors/classified-degradation.js';
|
|
1
2
|
async function handler(ctx) {
|
|
2
3
|
const { projectPath, specId, spec } = ctx;
|
|
3
4
|
if (!projectPath) {
|
|
@@ -7,17 +8,19 @@ async function handler(ctx) {
|
|
|
7
8
|
if (spec.scope === 'trivial') {
|
|
8
9
|
return;
|
|
9
10
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
try {
|
|
12
|
+
const { runTechnicalEnricher } = await import('../../../engine/technical-enricher/index.js');
|
|
13
|
+
await runTechnicalEnricher({ specId, projectPath, specScope: spec.scope });
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
reportClassifiedDegradation('REVIEW_ENRICHER_FAILED', new Error('Technical review enrichment failed'));
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
export const reviewEnricherHook = {
|
|
17
20
|
id: 'review-enricher',
|
|
18
21
|
triggers: ['review'],
|
|
19
22
|
requiresProjectPath: true,
|
|
20
|
-
label: 'Auto-enrich
|
|
23
|
+
label: 'Auto-enrich the bounded Technical spec section on review',
|
|
21
24
|
handler,
|
|
22
25
|
};
|
|
23
26
|
//# sourceMappingURL=review-enricher.hook.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StateFilesDriftReport } from '../../types/cascade-hooks.js';
|
|
2
2
|
/**
|
|
3
3
|
* SPEC-776: Compare in-memory spec counts vs external status.json and
|
|
4
4
|
* recently-done spec vs planu/session-context.md.
|
|
5
|
-
* Returns a
|
|
5
|
+
* Returns a StateFilesDriftReport with any detected mismatches.
|
|
6
6
|
*/
|
|
7
|
-
export declare function verifyStateFiles(projectPath: string): Promise<
|
|
7
|
+
export declare function verifyStateFiles(projectPath: string): Promise<StateFilesDriftReport>;
|
|
8
8
|
//# sourceMappingURL=state-drift-detector.d.ts.map
|
|
@@ -62,7 +62,7 @@ function extractLastDoneSpecFromContext(content) {
|
|
|
62
62
|
/**
|
|
63
63
|
* SPEC-776: Compare in-memory spec counts vs external status.json and
|
|
64
64
|
* recently-done spec vs planu/session-context.md.
|
|
65
|
-
* Returns a
|
|
65
|
+
* Returns a StateFilesDriftReport with any detected mismatches.
|
|
66
66
|
*/
|
|
67
67
|
export async function verifyStateFiles(projectPath) {
|
|
68
68
|
const alerts = [];
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This file configures the Planu CI check workflow behavior.
|
|
5
5
|
*/
|
|
6
6
|
export function generatePlanuConfigYaml(options) {
|
|
7
|
-
const { specsDir, failOnDrift, severityThreshold, postComment, badge, include, exclude
|
|
7
|
+
const { specsDir, failOnDrift, severityThreshold, postComment, badge, include, exclude } = options;
|
|
8
8
|
const lines = ['# .planu.yml — Planu CI configuration', ''];
|
|
9
9
|
// Specs section
|
|
10
10
|
lines.push('specs:');
|
|
@@ -28,12 +28,6 @@ export function generatePlanuConfigYaml(options) {
|
|
|
28
28
|
lines.push(` severity-threshold: ${severityThreshold}`);
|
|
29
29
|
lines.push(` post-comment: ${String(postComment)}`);
|
|
30
30
|
lines.push(` badge: ${String(badge)}`);
|
|
31
|
-
// License section
|
|
32
|
-
if (licenseKeyRef) {
|
|
33
|
-
lines.push('');
|
|
34
|
-
lines.push('license:');
|
|
35
|
-
lines.push(` key: \${${licenseKeyRef}}`);
|
|
36
|
-
}
|
|
37
31
|
lines.push('');
|
|
38
32
|
return lines.join('\n');
|
|
39
33
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export type { GateContext, GateResult };
|
|
1
|
+
import type { ClarificationGateContext, GateResult } from '../../types/clarification-token.js';
|
|
2
|
+
export type { ClarificationGateContext as GateContext, GateResult };
|
|
3
3
|
/**
|
|
4
4
|
* Check whether the tool is allowed to proceed.
|
|
5
5
|
*
|
|
@@ -11,5 +11,5 @@ export type { GateContext, GateResult };
|
|
|
11
11
|
* Fails open: if token storage is unavailable, the gate allows the call
|
|
12
12
|
* to proceed rather than blocking the entire tool.
|
|
13
13
|
*/
|
|
14
|
-
export declare function checkGate(ctx:
|
|
14
|
+
export declare function checkGate(ctx: ClarificationGateContext): Promise<GateResult>;
|
|
15
15
|
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/engine/code-scanner/layer-scanner.ts — Scans the 4 implementation layers (SPEC-441)
|
|
2
|
-
import {
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
3
|
import { join, relative, basename } from 'node:path';
|
|
4
4
|
import { fastFindFilesByExt, fastReadFiles } from '../core-bridge.js';
|
|
5
5
|
/**
|
|
@@ -25,8 +25,8 @@ export async function scanLayers(projectPath, keywords, symbolVariants) {
|
|
|
25
25
|
const symbols = findSymbols(filesToScanForSymbols, symbolVariants);
|
|
26
26
|
// Layer 3: test files matching keywords
|
|
27
27
|
const matchedTests = testFiles.filter((f) => keywords.some((kw) => basename(f).toLowerCase().includes(kw)));
|
|
28
|
-
// Layer 4: registrations in
|
|
29
|
-
const registrations =
|
|
28
|
+
// Layer 4: registrations in canonical registry source files.
|
|
29
|
+
const registrations = findRegistrations(projectPath, srcFiles, keywords);
|
|
30
30
|
return {
|
|
31
31
|
files: matchedFiles.map((f) => relative(projectPath, f)),
|
|
32
32
|
symbols,
|
|
@@ -55,27 +55,11 @@ function findSymbols(files, variants) {
|
|
|
55
55
|
}
|
|
56
56
|
return [...found];
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
function findRegistrations(_projectPath, srcFiles, keywords) {
|
|
59
59
|
const found = new Set();
|
|
60
|
-
|
|
61
|
-
const licensePath = join(projectPath, 'src', 'config', 'license-plans.json');
|
|
62
|
-
try {
|
|
63
|
-
const content = await readFile(licensePath, 'utf8');
|
|
64
|
-
const json = JSON.parse(content);
|
|
65
|
-
const allTools = [...(json.freeTools ?? []), ...(json.proTools ?? [])];
|
|
66
|
-
for (const tool of allTools) {
|
|
67
|
-
if (keywords.some((kw) => tool.includes(kw))) {
|
|
68
|
-
found.add(`license:${tool}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
// not a planu project — skip
|
|
74
|
-
}
|
|
75
|
-
// Check register-*.ts files for registerTool calls matching keywords
|
|
76
|
-
const registerFiles = srcFiles.filter((f) => /register.*\.ts$/.test(f));
|
|
60
|
+
const registerFiles = srcFiles.filter((f) => /register.*\.ts$|tool-registry\/.*\.ts$/.test(f));
|
|
77
61
|
if (registerFiles.length > 0) {
|
|
78
|
-
const REGISTER_RE = /registerTool\s*\(\s*['"]([^'"]+)['"]/g;
|
|
62
|
+
const REGISTER_RE = /(?:registerTool\s*\(\s*|name:\s*)['"]([^'"]+)['"]/g;
|
|
79
63
|
for (const file of fastReadFiles(registerFiles)) {
|
|
80
64
|
let match;
|
|
81
65
|
while ((match = REGISTER_RE.exec(file.content)) !== null) {
|