@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,8 @@
|
|
|
1
|
-
import type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs,
|
|
1
|
+
import type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs, NativeVectorSearchResult, VectorNode, ProjectGraphSourceFileRs, TsRelationRs, GraphNodeInputRs, GraphEdgeInputRs, AffectedNodeRs, ShortestPathResultRs, CompactGraphSliceRs, CompactGraphEdgesRs, ProjectGraphLimitsPolicyRs, ResolvedProjectGraphLimitsRs, NativeRuntimeHandshake, NativeRuntimeCompatibility, NativeArtifactManifest, NativeLoadDiagnostic } from '../types/core-bridge.js';
|
|
2
2
|
import type { MacOSKeychainNativePort } from '../types/security.js';
|
|
3
3
|
import { negotiateNativeRuntime, NATIVE_CAPABILITY_ABI, NATIVE_NODE_API_ABI, NATIVE_PROTOCOL_ABI, RUNTIME_STORAGE_SCHEMA } from './native-runtime-handshake.js';
|
|
4
4
|
export { negotiateNativeRuntime, NATIVE_CAPABILITY_ABI, NATIVE_NODE_API_ABI, NATIVE_PROTOCOL_ABI, RUNTIME_STORAGE_SCHEMA, };
|
|
5
|
-
export type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs,
|
|
5
|
+
export type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs, NativeVectorSearchResult, VectorNode, ProjectGraphSourceFileRs, TsRelationRs, GraphNodeInputRs, GraphEdgeInputRs, AffectedNodeRs, ShortestPathResultRs, CompactGraphSliceRs, CompactGraphEdgesRs, ProjectGraphLimitsPolicyRs, ResolvedProjectGraphLimitsRs, NativeRuntimeHandshake, NativeRuntimeCompatibility, NativeArtifactManifest, NativeLoadDiagnostic as LoadDiagnostic, };
|
|
6
6
|
export declare function currentNativePackageName(): string | null;
|
|
7
7
|
/** Main-thread port for async Keychain calls; never accepts override or unverified native code. */
|
|
8
8
|
export declare function requireMacOSKeychainNativePort(): MacOSKeychainNativePort;
|
|
@@ -23,7 +23,7 @@ export declare function fastScanSpecs(rootPath: string): SpecBriefRs[] | null;
|
|
|
23
23
|
export declare function fastVerifyGapsChain(filePath: string): GapsLogChainResultRs;
|
|
24
24
|
export declare function fastAppendGapEntry(filePath: string, id: string, timestamp: string, specId: string, description: string, severity: string, affectedSpecs: string[]): string;
|
|
25
25
|
export declare function fastCosineSimilarity(v1: number[], v2: number[]): number;
|
|
26
|
-
export declare function fastHnswSearchFlat(query: number[], nodes: VectorNode[], topK: number):
|
|
26
|
+
export declare function fastHnswSearchFlat(query: number[], nodes: VectorNode[], topK: number): NativeVectorSearchResult[];
|
|
27
27
|
export declare function fastHmacSign(secret: string, data: string): string;
|
|
28
28
|
export declare function fastHmacVerify(secret: string, data: string, signature: string): boolean;
|
|
29
29
|
export declare function fastScanProjectGraphSources(rootPath: string, policy: ProjectGraphLimitsPolicyRs, overrides?: Partial<ResolvedProjectGraphLimitsRs>): ProjectGraphSourceFileRs[];
|
|
@@ -9,7 +9,7 @@ export declare function computeBudgetStatus(budget: SpecBudget): SpecBudgetStatu
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function formatBudgetMessage(status: SpecBudgetStatus): string;
|
|
11
11
|
/**
|
|
12
|
-
* Enforces budget limits before executing a
|
|
12
|
+
* Enforces engineering budget limits before executing a governed tool.
|
|
13
13
|
* - If no budget is configured for the spec → no-op (pass through).
|
|
14
14
|
* - If budget is exhausted → throws an Error to block tool execution.
|
|
15
15
|
* - If warning threshold is reached → logs a warning but allows execution.
|
|
@@ -38,7 +38,7 @@ export function formatBudgetMessage(status) {
|
|
|
38
38
|
return msg;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* Enforces budget limits before executing a
|
|
41
|
+
* Enforces engineering budget limits before executing a governed tool.
|
|
42
42
|
* - If no budget is configured for the spec → no-op (pass through).
|
|
43
43
|
* - If budget is exhausted → throws an Error to block tool execution.
|
|
44
44
|
* - If warning threshold is reached → logs a warning but allows execution.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CriterionIdentity, CriterionIdentityOptions } from '../types/criterion-identity.js';
|
|
2
2
|
export type { CriterionIdentity, CriterionIdentityOptions } from '../types/criterion-identity.js';
|
|
3
|
+
export declare function hasExplicitCriterionId(value: string): boolean;
|
|
3
4
|
export declare function normalizeCriterionText(value: string): string;
|
|
4
5
|
export declare function createCriterionIdentity(value: string, options?: CriterionIdentityOptions): CriterionIdentity;
|
|
5
6
|
export declare function criterionIdentitiesMatch(left: CriterionIdentity, right: CriterionIdentity): boolean;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
const CRITERION_ID_PREFIX = /^(AC|AB)\s*-?\s*(\d+)\b\s*[:.)-]?\s*/i;
|
|
3
|
+
export function hasExplicitCriterionId(value) {
|
|
4
|
+
const stripped = value
|
|
5
|
+
.normalize('NFKC')
|
|
6
|
+
.replace(/^[-*+]\s*\[[ xX]\]\s*/, '')
|
|
7
|
+
.trim();
|
|
8
|
+
return CRITERION_ID_PREFIX.test(stripped);
|
|
9
|
+
}
|
|
3
10
|
export function normalizeCriterionText(value) {
|
|
4
11
|
return value
|
|
5
12
|
.normalize('NFKC')
|
|
@@ -324,18 +324,13 @@ export async function loadUsageStats() {
|
|
|
324
324
|
const raw = await readJsonFile(usageFile);
|
|
325
325
|
if (!raw) {
|
|
326
326
|
return {
|
|
327
|
-
tier: 'unknown',
|
|
328
327
|
callsToday: 0,
|
|
329
|
-
dailyLimit: null,
|
|
330
|
-
trialDaysLeft: null,
|
|
331
328
|
isAvailable: false,
|
|
332
329
|
};
|
|
333
330
|
}
|
|
331
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
334
332
|
return {
|
|
335
|
-
|
|
336
|
-
callsToday: raw.callsToday ?? 0,
|
|
337
|
-
dailyLimit: raw.dailyLimit ?? null,
|
|
338
|
-
trialDaysLeft: raw.trialDaysLeft ?? null,
|
|
333
|
+
callsToday: (raw.events ?? []).filter((event) => event.timestamp?.startsWith(today)).length,
|
|
339
334
|
isAvailable: true,
|
|
340
335
|
};
|
|
341
336
|
}
|
|
@@ -194,9 +194,6 @@ function getPageStyles() {
|
|
|
194
194
|
.usage-panel { background: var(--surface); border: 1px solid var(--border);
|
|
195
195
|
border-radius: var(--radius); padding: 1rem; margin-top: 1.5rem; }
|
|
196
196
|
.usage-panel h3 { font-size: 0.9rem; font-weight: 600; margin-bottom: 0.75rem; color: var(--text-muted); }
|
|
197
|
-
.usage-tier { font-size: 1.1rem; font-weight: 700; color: var(--accent); }
|
|
198
|
-
.trial-warning { color: #f59e0b; font-size: 0.82rem; margin-top: 0.35rem; }
|
|
199
|
-
.trial-critical { color: #ef4444; font-weight: 600; }
|
|
200
197
|
.status-indicator.updating { color: #f59e0b; }
|
|
201
198
|
.shortcuts-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.7);
|
|
202
199
|
z-index: 1000; align-items: center; justify-content: center; }
|
|
@@ -30,21 +30,9 @@ function renderUsagePanel(usage) {
|
|
|
30
30
|
<div style="color:var(--text-muted);font-size:0.85rem">Sin datos de uso disponibles</div>
|
|
31
31
|
</div>`;
|
|
32
32
|
}
|
|
33
|
-
const tierLabel = usage.tier.charAt(0).toUpperCase() + usage.tier.slice(1);
|
|
34
|
-
const limitLabel = usage.dailyLimit !== null ? String(usage.dailyLimit) : '∞';
|
|
35
|
-
const callsLabel = `${usage.callsToday} / ${limitLabel}`;
|
|
36
|
-
let trialHtml = '';
|
|
37
|
-
if (usage.trialDaysLeft !== null) {
|
|
38
|
-
const isCritical = usage.trialDaysLeft <= 3;
|
|
39
|
-
trialHtml = `<div class="trial-warning ${isCritical ? 'trial-critical' : ''}">
|
|
40
|
-
Trial: ${usage.trialDaysLeft} día${usage.trialDaysLeft !== 1 ? 's' : ''} restante${usage.trialDaysLeft !== 1 ? 's' : ''}
|
|
41
|
-
</div>`;
|
|
42
|
-
}
|
|
43
33
|
return `<div class="usage-panel">
|
|
44
34
|
<h3>Uso</h3>
|
|
45
|
-
<div
|
|
46
|
-
<div style="font-size:0.82rem;color:var(--text-muted);margin-top:0.35rem">Llamadas hoy: ${escapeHtml(callsLabel)}</div>
|
|
47
|
-
${trialHtml}
|
|
35
|
+
<div style="font-size:0.82rem;color:var(--text-muted);margin-top:0.35rem">Llamadas hoy: ${String(usage.callsToday)}</div>
|
|
48
36
|
</div>`;
|
|
49
37
|
}
|
|
50
38
|
/** Render the health metrics panel */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DocSpecSummary, ToolEntry, ProjectMetrics } from '../../types/docs.js';
|
|
2
2
|
export declare function collectSpecs(projectPath: string): Promise<DocSpecSummary[]>;
|
|
3
|
-
export declare function collectTools(
|
|
3
|
+
export declare function collectTools(_projectPath: string): ToolEntry[];
|
|
4
4
|
export declare function collectMetrics(projectPath: string): Promise<ProjectMetrics>;
|
|
5
5
|
//# sourceMappingURL=data-collector.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @crash-shield-ignore-file — config/cache reader for Planu-controlled JSON; writer is this codebase, shape guaranteed by build/seed.
|
|
2
2
|
// SPEC-093: Data collector for docs site generator
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
4
3
|
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
5
4
|
import { join } from 'node:path';
|
|
5
|
+
import { readCanonicalToolNames } from '../../config/official-sdd-tools.js';
|
|
6
6
|
import { parseFrontmatter } from '../frontmatter-parser.js';
|
|
7
7
|
const SDD_PHASES = {
|
|
8
8
|
Initialize: ['init_project', 'init_constitution', 'set_locale'],
|
|
@@ -225,33 +225,12 @@ export async function collectSpecs(projectPath) {
|
|
|
225
225
|
});
|
|
226
226
|
return results;
|
|
227
227
|
}
|
|
228
|
-
export function collectTools(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
catch {
|
|
235
|
-
return [];
|
|
236
|
-
}
|
|
237
|
-
const entries = [];
|
|
238
|
-
for (const tool of plans.freeTools ?? []) {
|
|
239
|
-
entries.push({
|
|
240
|
-
name: tool,
|
|
241
|
-
description: tool.replace(/_/g, ' '),
|
|
242
|
-
phase: findPhaseForTool(tool),
|
|
243
|
-
tier: 'free',
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
for (const tool of plans.proTools ?? []) {
|
|
247
|
-
entries.push({
|
|
248
|
-
name: tool,
|
|
249
|
-
description: tool.replace(/_/g, ' '),
|
|
250
|
-
phase: findPhaseForTool(tool),
|
|
251
|
-
tier: 'pro',
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
return entries;
|
|
228
|
+
export function collectTools(_projectPath) {
|
|
229
|
+
return readCanonicalToolNames().map((tool) => ({
|
|
230
|
+
name: tool,
|
|
231
|
+
description: tool.replaceAll('_', ' '),
|
|
232
|
+
phase: findPhaseForTool(tool),
|
|
233
|
+
}));
|
|
255
234
|
}
|
|
256
235
|
async function countLinesInDir(dirPath) {
|
|
257
236
|
let total = 0;
|
|
@@ -11,18 +11,11 @@ function groupByPhase(tools) {
|
|
|
11
11
|
}
|
|
12
12
|
return groups;
|
|
13
13
|
}
|
|
14
|
-
function renderTierBadge(tier) {
|
|
15
|
-
const cls = tier === 'free' ? 'badge-free' : 'badge-pro';
|
|
16
|
-
const label = tier === 'free' ? 'Free' : 'Pro';
|
|
17
|
-
return `<span class="tier-badge ${cls}">${label}</span>`;
|
|
18
|
-
}
|
|
19
14
|
export function renderToolsCatalog(tools) {
|
|
20
|
-
const freeCount = tools.filter((t) => t.tier === 'free').length;
|
|
21
|
-
const proCount = tools.filter((t) => t.tier === 'pro').length;
|
|
22
15
|
if (tools.length === 0) {
|
|
23
16
|
return `<div class="tools-catalog">
|
|
24
17
|
<div class="tools-summary">
|
|
25
|
-
<p>Total: 0
|
|
18
|
+
<p>Total: 0</p>
|
|
26
19
|
</div>
|
|
27
20
|
<p class="empty">No tools found.</p>
|
|
28
21
|
</div>`;
|
|
@@ -34,7 +27,7 @@ export function renderToolsCatalog(tools) {
|
|
|
34
27
|
.map((tool) => {
|
|
35
28
|
const searchable = `${tool.name} ${tool.description}`.toLowerCase();
|
|
36
29
|
return ` <div class="tool-card" data-searchable="${searchable}">
|
|
37
|
-
<h3>${tool.name}
|
|
30
|
+
<h3>${tool.name}</h3>
|
|
38
31
|
<p>${tool.description}</p>
|
|
39
32
|
</div>`;
|
|
40
33
|
})
|
|
@@ -47,7 +40,7 @@ ${cards}
|
|
|
47
40
|
.join('\n');
|
|
48
41
|
return `<div class="tools-catalog">
|
|
49
42
|
<div class="tools-summary">
|
|
50
|
-
<p>Total: ${String(tools.length)}
|
|
43
|
+
<p>Total: ${String(tools.length)}</p>
|
|
51
44
|
</div>
|
|
52
45
|
${sections}
|
|
53
46
|
</div>`;
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import type { Spec } from '../../types/spec/core.js';
|
|
2
|
-
import type { EvidenceArtifacts } from '../../types/evidence-gates.js';
|
|
2
|
+
import type { EvidenceArtifacts, TraceabilityMatrixEvidence } from '../../types/evidence-gates.js';
|
|
3
3
|
/** Digest of canonical artifact content; the provenance envelope is excluded. */
|
|
4
4
|
export declare function evidenceArtifactDigest(artifact: unknown): string;
|
|
5
5
|
export declare function evidenceArtifactCollectionDigest(artifacts: readonly {
|
|
6
6
|
kind: string;
|
|
7
7
|
provenance?: unknown;
|
|
8
8
|
}[]): string;
|
|
9
|
+
/** Verify legacy test-backed evidence without admitting prose-only traceability rows. */
|
|
10
|
+
export declare function traceabilityRowHasCurrentTestEvidence(row: TraceabilityMatrixEvidence['rows'][number], args: {
|
|
11
|
+
projectPath: string;
|
|
12
|
+
}): boolean;
|
|
13
|
+
/** Verify strict command evidence against current repository inputs and the validation ledger. */
|
|
14
|
+
export declare function traceabilityRowHasCurrentCommandEvidence(row: TraceabilityMatrixEvidence['rows'][number], args: {
|
|
15
|
+
projectId: string;
|
|
16
|
+
projectPath: string;
|
|
17
|
+
}): boolean;
|
|
9
18
|
export declare function readEvidenceArtifacts(args: {
|
|
10
19
|
spec: Spec;
|
|
11
20
|
projectId: string;
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import { technologyValue } from '../technology-registry.js';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { lstatSync, realpathSync } from 'node:fs';
|
|
3
4
|
import { createHash } from 'node:crypto';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
+
import { isAbsolute, join, relative, resolve } from 'node:path';
|
|
5
6
|
import { z } from 'zod';
|
|
6
7
|
import { projectDataDir } from '../../storage/base-store.js';
|
|
8
|
+
import { computeValidationEvidenceIdentity, computeValidationEvidenceKey, normalizeValidationCommand, readMatchingValidationEvidence, } from '../validation-evidence-ledger.js';
|
|
9
|
+
import { VALIDATION_COMMANDS } from '../validation-impact-planner.js';
|
|
7
10
|
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
8
11
|
const SPEC_ID = /^SPEC-[1-9]\d*$/u;
|
|
9
12
|
const ISSUER_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
13
|
+
const EVIDENCE_KEY = /^[a-f0-9]{64}$/u;
|
|
14
|
+
const ValidationGateCapabilitySchema = z.enum([
|
|
15
|
+
'typecheck',
|
|
16
|
+
'lint',
|
|
17
|
+
'test-related',
|
|
18
|
+
'test-full',
|
|
19
|
+
'contract',
|
|
20
|
+
'coverage',
|
|
21
|
+
'migration',
|
|
22
|
+
'fault-injection',
|
|
23
|
+
'security',
|
|
24
|
+
'native',
|
|
25
|
+
'website',
|
|
26
|
+
'reproducibility',
|
|
27
|
+
]);
|
|
10
28
|
const ProvenanceSchema = z
|
|
11
29
|
.object({
|
|
12
30
|
receiptId: z.string().regex(DIGEST),
|
|
@@ -69,6 +87,16 @@ const TraceabilityMatrixSchema = z
|
|
|
69
87
|
changedFiles: z.array(z.string().min(1)).max(200),
|
|
70
88
|
validationEvidence: z.string().optional(),
|
|
71
89
|
reviewerEvidence: z.string().optional(),
|
|
90
|
+
commandEvidence: z
|
|
91
|
+
.object({
|
|
92
|
+
capability: ValidationGateCapabilitySchema,
|
|
93
|
+
command: z.string().min(1),
|
|
94
|
+
scope: z.array(z.string().min(1)).min(1).max(200),
|
|
95
|
+
relevantPaths: z.array(z.string().min(1)).min(1).max(200).optional(),
|
|
96
|
+
evidenceKey: z.string().regex(EVIDENCE_KEY),
|
|
97
|
+
})
|
|
98
|
+
.strict()
|
|
99
|
+
.optional(),
|
|
72
100
|
})
|
|
73
101
|
.strict())
|
|
74
102
|
.max(1000),
|
|
@@ -118,10 +146,95 @@ export function evidenceArtifactCollectionDigest(artifacts) {
|
|
|
118
146
|
.map((artifact) => ({ kind: artifact.kind, digest: evidenceArtifactDigest(artifact) }))
|
|
119
147
|
.sort((left, right) => left.kind.localeCompare(right.kind)));
|
|
120
148
|
}
|
|
149
|
+
function safeRepositoryPath(path) {
|
|
150
|
+
const normalized = path.trim().replaceAll('\\', '/').replace(/^\.\//u, '');
|
|
151
|
+
return (normalized.length > 0 &&
|
|
152
|
+
!normalized.startsWith('/') &&
|
|
153
|
+
!/^[A-Za-z]:/u.test(normalized) &&
|
|
154
|
+
normalized
|
|
155
|
+
.split('/')
|
|
156
|
+
.every((segment) => segment.length > 0 && segment !== '.' && segment !== '..'));
|
|
157
|
+
}
|
|
158
|
+
function repositoryEvidencePathsAreCurrent(row, projectPath, additionalPaths = []) {
|
|
159
|
+
let repositoryRoot;
|
|
160
|
+
try {
|
|
161
|
+
repositoryRoot = realpathSync(projectPath);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
const paths = [
|
|
167
|
+
...row.changedFiles,
|
|
168
|
+
...(row.testEvidence ?? []),
|
|
169
|
+
...(row.contractEvidence ?? []),
|
|
170
|
+
...additionalPaths,
|
|
171
|
+
];
|
|
172
|
+
return (paths.length > 0 &&
|
|
173
|
+
paths.every((path) => {
|
|
174
|
+
if (!safeRepositoryPath(path)) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
const candidate = resolve(repositoryRoot, path);
|
|
178
|
+
try {
|
|
179
|
+
if (lstatSync(candidate).isSymbolicLink()) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
const realPath = realpathSync(candidate);
|
|
183
|
+
const relativePath = relative(repositoryRoot, realPath);
|
|
184
|
+
return (relativePath.length > 0 &&
|
|
185
|
+
relativePath.split(/[\\/]/u)[0] !== '..' &&
|
|
186
|
+
!isAbsolute(relativePath));
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
function isExecutableTestPath(path) {
|
|
194
|
+
return /(?:^|\/)[^/]+\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(path.replaceAll('\\', '/'));
|
|
195
|
+
}
|
|
196
|
+
/** Verify legacy test-backed evidence without admitting prose-only traceability rows. */
|
|
197
|
+
export function traceabilityRowHasCurrentTestEvidence(row, args) {
|
|
198
|
+
return (row.commandEvidence === undefined &&
|
|
199
|
+
row.changedFiles.length > 0 &&
|
|
200
|
+
(row.testEvidence?.length ?? 0) > 0 &&
|
|
201
|
+
row.testEvidence?.every(isExecutableTestPath) === true &&
|
|
202
|
+
Boolean(row.validationEvidence?.trim()) &&
|
|
203
|
+
Boolean(row.reviewerEvidence?.trim()) &&
|
|
204
|
+
repositoryEvidencePathsAreCurrent(row, args.projectPath));
|
|
205
|
+
}
|
|
206
|
+
/** Verify strict command evidence against current repository inputs and the validation ledger. */
|
|
207
|
+
export function traceabilityRowHasCurrentCommandEvidence(row, args) {
|
|
208
|
+
const evidence = row.commandEvidence;
|
|
209
|
+
const expectedCommand = evidence
|
|
210
|
+
? VALIDATION_COMMANDS[evidence.capability]
|
|
211
|
+
: undefined;
|
|
212
|
+
if (!evidence ||
|
|
213
|
+
!expectedCommand ||
|
|
214
|
+
normalizeValidationCommand(evidence.command) !== normalizeValidationCommand(expectedCommand)) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
const repositoryPaths = [...(evidence.relevantPaths ?? [])];
|
|
218
|
+
if (row.changedFiles.length === 0 ||
|
|
219
|
+
!repositoryEvidencePathsAreCurrent(row, args.projectPath, repositoryPaths) ||
|
|
220
|
+
evidence.scope.some((path) => !safeRepositoryPath(path))) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
const input = {
|
|
224
|
+
projectPath: args.projectPath,
|
|
225
|
+
capability: evidence.capability,
|
|
226
|
+
command: evidence.command,
|
|
227
|
+
scope: evidence.scope,
|
|
228
|
+
...(evidence.relevantPaths === undefined ? {} : { relevantPaths: evidence.relevantPaths }),
|
|
229
|
+
};
|
|
230
|
+
const currentKey = computeValidationEvidenceKey(computeValidationEvidenceIdentity(input));
|
|
231
|
+
return (currentKey === evidence.evidenceKey &&
|
|
232
|
+
readMatchingValidationEvidence(args.projectId, input)?.status === 'passed');
|
|
233
|
+
}
|
|
121
234
|
const ARTIFACT_HINTS = {
|
|
122
235
|
'Discovery evidence': 'Expected discovery.json with { version: 1, rules: string[], examples: [{ rule, example }], openQuestions: [{ question, status, resolution? }], outOfScope: string[], glossary: [{ term, meaning }] }.',
|
|
123
236
|
'Task plan evidence': 'Expected task-plan.json with { version: 1, tasks: [{ id, title, acceptanceCriteria: string[], status: "pending"|"doing"|"done" }] }. Acceptance criteria may be full text or stable IDs such as AC1 when they map to the canonical criteria order.',
|
|
124
|
-
'Traceability matrix evidence': 'Expected traceability-matrix.json with { version: 1, rows: [{ acceptanceCriterion, scenario?, testEvidence?, contractEvidence?, manualEvidence?, changedFiles: string[], validationEvidence?, reviewerEvidence
|
|
237
|
+
'Traceability matrix evidence': 'Expected traceability-matrix.json with { version: 1, rows: [{ acceptanceCriterion, scenario?, testEvidence?, contractEvidence?, manualEvidence?, changedFiles: string[], validationEvidence?, reviewerEvidence?, commandEvidence?: { capability, command, scope, relevantPaths?, evidenceKey } }] }.',
|
|
125
238
|
'contract-validation-api.json': 'Expected filename contract-validation-api.json with { version: 1, kind: "api", passed: boolean, reportPath?, summary? }.',
|
|
126
239
|
'contract-validation-graphql.json': 'Expected filename contract-validation-graphql.json with { version: 1, kind: "graphql", passed: boolean, reportPath?, summary? }.',
|
|
127
240
|
'contract-validation-event.json': 'Expected filename contract-validation-event.json with { version: 1, kind: "event", passed: boolean, reportPath?, summary? }.',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { evidenceArtifactCollectionDigest, evidenceArtifactDigest } from './artifact-reader.js';
|
|
2
|
-
import { hasAnyAffirmedMatch } from '../text-signal-boundaries.js';
|
|
2
|
+
import { hasAnyAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../text-signal-boundaries.js';
|
|
3
3
|
import { createCriterionIdentity } from '../criterion-identity.js';
|
|
4
4
|
const CONTRACT_HINTS = {
|
|
5
5
|
api: [
|
|
@@ -10,7 +10,8 @@ const CONTRACT_HINTS = {
|
|
|
10
10
|
],
|
|
11
11
|
graphql: [/\b(?:graphql|gql)\s+(?:api|schema|resolver|contract)\b/i, /\bschema\.graphql\b/i],
|
|
12
12
|
event: [
|
|
13
|
-
/\
|
|
13
|
+
/\bevent\s+(?:contract|schema|producer|consumer|handler|queue|topic)\b/i,
|
|
14
|
+
/\bmessage\s+(?:schema|producer|consumer|handler|queue|topic)\b/i,
|
|
14
15
|
/\b(?:message\s+broker|kafka|rabbitmq|pubsub|webhook\s+(?:delivery|contract|payload))\b/i,
|
|
15
16
|
],
|
|
16
17
|
ui: [/\b(?:ui|component|screen|design)\s+contract\b/i],
|
|
@@ -76,7 +77,7 @@ function provenanceIssues(artifacts, context) {
|
|
|
76
77
|
});
|
|
77
78
|
}
|
|
78
79
|
export function inferRequiredContractEvidence(spec, criteria) {
|
|
79
|
-
const text =
|
|
80
|
+
const text = stripMetaAnalysisText(stripNonContractText([spec.title, ...spec.tags, ...criteria].join('\n')));
|
|
80
81
|
const required = [];
|
|
81
82
|
for (const [kind, patterns] of Object.entries(CONTRACT_HINTS)) {
|
|
82
83
|
if (hasAnyAffirmedMatch(text, [...patterns])) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns only project-relative IDs. Old evidence is rejected cumulatively: a
|
|
3
|
+
* later receipt cannot revive a digest superseded by an earlier receipt.
|
|
4
|
+
*/
|
|
5
|
+
export declare function checkReconciliationFreshness(args: {
|
|
6
|
+
projectId: string;
|
|
7
|
+
specId: string;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
artifactId: string;
|
|
10
|
+
}[]>;
|
|
11
|
+
//# sourceMappingURL=reconciliation-freshness.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { lstat, readFile, readdir } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { projectDataDir } from '../../storage/base-store.js';
|
|
5
|
+
import { readCommittedReconciliations } from '../lifecycle-reconciliation.js';
|
|
6
|
+
const BASE_ARTIFACTS = [
|
|
7
|
+
'spec.lock.json',
|
|
8
|
+
'review_feedback.md',
|
|
9
|
+
'task-plan.json',
|
|
10
|
+
'implementation-report.json',
|
|
11
|
+
'validation-report.json',
|
|
12
|
+
'traceability-matrix.json',
|
|
13
|
+
'context-package.json',
|
|
14
|
+
];
|
|
15
|
+
function sha256(bytes) {
|
|
16
|
+
return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns only project-relative IDs. Old evidence is rejected cumulatively: a
|
|
20
|
+
* later receipt cannot revive a digest superseded by an earlier receipt.
|
|
21
|
+
*/
|
|
22
|
+
export async function checkReconciliationFreshness(args) {
|
|
23
|
+
const receipts = await readCommittedReconciliations(args.projectId, args.specId);
|
|
24
|
+
const tombstones = new Set(receipts.flatMap((receipt) => receipt.supersededArtifacts.flatMap((artifact) => artifact.sha256 ? [`${artifact.artifactId}\0${artifact.sha256}`] : [])));
|
|
25
|
+
if (tombstones.size === 0) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const root = projectDataDir(args.projectId);
|
|
29
|
+
const handoff = join(root, 'handoffs', args.specId);
|
|
30
|
+
const candidates = [
|
|
31
|
+
...BASE_ARTIFACTS.map((name) => ({
|
|
32
|
+
artifactId: `handoffs/${args.specId}/${name}`,
|
|
33
|
+
path: join(handoff, name),
|
|
34
|
+
})),
|
|
35
|
+
{ artifactId: `handoffs/${args.specId}.md`, path: join(root, 'handoffs', `${args.specId}.md`) },
|
|
36
|
+
];
|
|
37
|
+
try {
|
|
38
|
+
const names = await readdir(handoff);
|
|
39
|
+
for (const artifactName of names) {
|
|
40
|
+
if (/^contract-validation-[A-Za-z0-9_-]+\.json$/u.test(artifactName)) {
|
|
41
|
+
candidates.push({
|
|
42
|
+
artifactId: `handoffs/${args.specId}/${artifactName}`,
|
|
43
|
+
path: join(handoff, artifactName),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const stale = [];
|
|
54
|
+
for (const candidate of candidates) {
|
|
55
|
+
try {
|
|
56
|
+
const stat = await lstat(candidate.path);
|
|
57
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (tombstones.has(`${candidate.artifactId}\0${sha256(await readFile(candidate.path))}`)) {
|
|
61
|
+
stale.push({ artifactId: candidate.artifactId });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return stale;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=reconciliation-freshness.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EvidenceGateIssue, SpecEvidenceIndex } from '../../types/index.js';
|
|
2
2
|
export declare function checkDoneDriftContract(args: {
|
|
3
3
|
index: SpecEvidenceIndex;
|
|
4
|
-
|
|
4
|
+
approvedScopePaths: readonly string[];
|
|
5
5
|
}): EvidenceGateIssue[];
|
|
6
6
|
//# sourceMappingURL=done-drift.d.ts.map
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { normalizeChangedFilePath } from '../handoff-packager.js';
|
|
2
|
+
function normalizedChangedFile(value) {
|
|
3
|
+
const normalized = normalizeChangedFilePath(value);
|
|
4
|
+
return normalized.status === 'valid' ? normalized.path : null;
|
|
5
|
+
}
|
|
1
6
|
export function checkDoneDriftContract(args) {
|
|
2
7
|
const issues = [];
|
|
3
8
|
const uncovered = args.index.criteria.filter((entry) => {
|
|
@@ -14,33 +19,50 @@ export function checkDoneDriftContract(args) {
|
|
|
14
19
|
}
|
|
15
20
|
const staleOrInvalid = args.index.criteria.flatMap((entry) => entry.evidence
|
|
16
21
|
.filter((record) => record.status === 'stale' || record.status === 'invalid')
|
|
17
|
-
.map((record) =>
|
|
22
|
+
.map((record) => {
|
|
23
|
+
if (record.kind !== 'changed-file') {
|
|
24
|
+
return `${entry.criterion}: ${record.value} (${record.status})`;
|
|
25
|
+
}
|
|
26
|
+
const normalized = normalizedChangedFile(record.value);
|
|
27
|
+
return normalized
|
|
28
|
+
? `${entry.criterion}: ${normalized} (${record.status})`
|
|
29
|
+
: `${entry.criterion}: invalid changed-file (${record.status})`;
|
|
30
|
+
}));
|
|
18
31
|
if (staleOrInvalid.length > 0) {
|
|
19
32
|
issues.push({
|
|
20
33
|
code: 'done_drift_stale_evidence',
|
|
21
34
|
message: `Done drift check found stale or invalid evidence: ${staleOrInvalid.join('; ')}`,
|
|
22
35
|
});
|
|
23
36
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
const approvedScopePaths = args.approvedScopePaths.flatMap((path) => {
|
|
38
|
+
const normalized = normalizedChangedFile(path);
|
|
39
|
+
return normalized ? [normalized] : [];
|
|
40
|
+
});
|
|
41
|
+
const approved = new Set(approvedScopePaths);
|
|
42
|
+
const unapproved = args.index.criteria.flatMap((entry) => {
|
|
43
|
+
const hasScopeAmendment = entry.evidence.some((record) => record.kind === 'reviewer' && /scope amendment|approved scope/i.test(record.value));
|
|
44
|
+
if (hasScopeAmendment) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
return entry.evidence.flatMap((record) => {
|
|
48
|
+
if (record.kind !== 'changed-file' ||
|
|
49
|
+
(record.status !== 'valid' && record.status !== 'missing')) {
|
|
29
50
|
return [];
|
|
30
51
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
52
|
+
const normalized = normalizedChangedFile(record.value);
|
|
53
|
+
return normalized && approved.has(normalized)
|
|
54
|
+
? []
|
|
55
|
+
: [`${entry.criterion}: ${normalized ?? 'invalid changed-file path'}`];
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
if (unapproved.length > 0) {
|
|
59
|
+
const approvedHint = approvedScopePaths.length > 0
|
|
60
|
+
? ` Approved canonical paths: ${approvedScopePaths.join(', ')}.`
|
|
61
|
+
: ' No approved canonical paths were found in the approved spec.';
|
|
62
|
+
issues.push({
|
|
63
|
+
code: 'done_drift_unapproved_scope',
|
|
64
|
+
message: `Done drift check found changed files outside approved canonical scope: ${unapproved.join('; ')}.${approvedHint} Add the file to approved canonical ownership or include reviewerEvidence with an approved scope amendment.`,
|
|
34
65
|
});
|
|
35
|
-
if (unapproved.length > 0) {
|
|
36
|
-
const groundedHint = args.groundedTechnicalPaths.length > 0
|
|
37
|
-
? ` Grounded technical paths: ${args.groundedTechnicalPaths.join(', ')}.`
|
|
38
|
-
: ' No grounded technical paths were found in the approved spec.';
|
|
39
|
-
issues.push({
|
|
40
|
-
code: 'done_drift_unapproved_scope',
|
|
41
|
-
message: `Done drift check found changed files outside grounded spec scope: ${unapproved.join('; ')}.${groundedHint} Add the file to approved technical references or include reviewerEvidence with an approved scope amendment.`,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
66
|
}
|
|
45
67
|
return issues;
|
|
46
68
|
}
|
|
@@ -102,6 +102,7 @@ export function createChildCancellationScope(requestedMs) {
|
|
|
102
102
|
const normalizedMs = Number.isFinite(requestedMs) ? Math.max(0, requestedMs) : 0;
|
|
103
103
|
const timeoutMs = Math.max(0, Math.min(normalizedMs, parentRemaining));
|
|
104
104
|
const controller = new AbortController();
|
|
105
|
+
let deadlineElapsed = false;
|
|
105
106
|
const abortFromParent = () => {
|
|
106
107
|
controller.abort(parent?.signal.reason ?? new ExecutionCancelledError());
|
|
107
108
|
};
|
|
@@ -112,12 +113,14 @@ export function createChildCancellationScope(requestedMs) {
|
|
|
112
113
|
parent?.signal.addEventListener('abort', abortFromParent, { once: true });
|
|
113
114
|
}
|
|
114
115
|
const timer = setTimeout(() => {
|
|
116
|
+
deadlineElapsed = true;
|
|
115
117
|
controller.abort(new ExecutionCancelledError(`Execution budget elapsed after ${String(timeoutMs)}ms`));
|
|
116
118
|
}, timeoutMs);
|
|
117
119
|
timer.unref();
|
|
118
120
|
return {
|
|
119
121
|
signal: controller.signal,
|
|
120
122
|
timeoutMs,
|
|
123
|
+
didDeadlineElapse: () => deadlineElapsed,
|
|
121
124
|
dispose: () => {
|
|
122
125
|
clearTimeout(timer);
|
|
123
126
|
parent?.signal.removeEventListener('abort', abortFromParent);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DurableJobHeartbeatController, DurableJobHeartbeatRuntimeOptions, DurableJobHeartbeatStartInput } from '../../types/durable-validation.js';
|
|
2
|
+
/** Start one autonomous, fenced heartbeat and wait for its typed ready acknowledgement. */
|
|
3
|
+
export declare function createDurableJobHeartbeat(input: DurableJobHeartbeatStartInput, options?: DurableJobHeartbeatRuntimeOptions): Promise<DurableJobHeartbeatController>;
|
|
4
|
+
//# sourceMappingURL=durable-job-heartbeat-runtime.d.ts.map
|