@planu/cli 4.14.1 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +82 -0
- package/LICENSE +55 -12
- package/README.md +10 -2
- package/dist/cli/commands/install.d.ts +1 -12
- package/dist/cli/commands/install.js +9 -65
- package/dist/cli/commands/job.js +4 -3
- package/dist/cli/commands/spec.js +12 -3
- package/dist/cli/commands/validate.js +2 -2
- package/dist/cli/router.js +1 -3
- package/dist/config/environment-schema.json +1 -3
- package/dist/config/official-sdd-tools.d.ts +4 -0
- package/dist/config/official-sdd-tools.js +35 -0
- package/dist/config/product-public.d.ts +139 -3
- package/dist/config/product-public.js +8 -1
- package/dist/config/product-public.json +7 -36
- package/dist/config/registries/hosts/codex.json +20 -363
- package/dist/config/release-policy.json +84 -2
- package/dist/config/runtime-policy.json +12 -1
- package/dist/config/skill-templates/planu-resume-work.md +2 -2
- package/dist/core/index.d.ts +1 -1
- package/dist/core/spec-validator.d.ts +4 -4
- package/dist/core/spec-validator.js +33 -19
- package/dist/engine/abortable-process-runner.d.ts +20 -2
- package/dist/engine/abortable-process-runner.js +243 -74
- package/dist/engine/ambiguity-scorer.js +4 -26
- package/dist/engine/auth/scope-mapper.js +1 -7
- package/dist/engine/autopilot/state-updater.js +4 -4
- package/dist/engine/cascade-hooks/hooks/review-enricher.hook.js +9 -6
- package/dist/engine/cascade-hooks/state-drift-detector.d.ts +3 -3
- package/dist/engine/cascade-hooks/state-drift-detector.js +1 -1
- package/dist/engine/ci-generator/planu-config.js +1 -7
- package/dist/engine/clarification-gate/gate.d.ts +3 -3
- package/dist/engine/code-scanner/layer-scanner.js +6 -22
- package/dist/engine/core-bridge.d.ts +3 -3
- package/dist/engine/cost-guardrails.d.ts +1 -1
- package/dist/engine/cost-guardrails.js +1 -1
- package/dist/engine/criterion-identity.d.ts +1 -0
- package/dist/engine/criterion-identity.js +7 -0
- package/dist/engine/dashboard/data-loader.js +2 -7
- package/dist/engine/dashboard/templates-layout.js +0 -3
- package/dist/engine/dashboard/templates-project.js +1 -13
- package/dist/engine/docs-site-generator/data-collector.d.ts +1 -1
- package/dist/engine/docs-site-generator/data-collector.js +7 -28
- package/dist/engine/docs-site-generator/tools-renderer.js +3 -10
- package/dist/engine/evidence-gates/artifact-reader.d.ts +12 -1
- package/dist/engine/evidence-gates/artifact-reader.js +174 -4
- package/dist/engine/evidence-gates/evidence-autofill.d.ts +10 -0
- package/dist/engine/evidence-gates/evidence-autofill.js +148 -0
- package/dist/engine/evidence-gates/evidence-skeletons.d.ts +19 -0
- package/dist/engine/evidence-gates/evidence-skeletons.js +69 -0
- package/dist/engine/evidence-gates/lifecycle-gate.js +4 -3
- package/dist/engine/evidence-gates/reconciliation-freshness.d.ts +11 -0
- package/dist/engine/evidence-gates/reconciliation-freshness.js +72 -0
- package/dist/engine/evidence-index/done-drift.d.ts +1 -1
- package/dist/engine/evidence-index/done-drift.js +40 -18
- package/dist/engine/execution/context.js +3 -0
- package/dist/engine/execution/durable-job-heartbeat-runtime.d.ts +4 -0
- package/dist/engine/execution/durable-job-heartbeat-runtime.js +400 -0
- package/dist/engine/execution/job-runtime.d.ts +30 -0
- package/dist/engine/execution/job-runtime.js +114 -6
- package/dist/engine/execution/operation-journal.js +10 -4
- package/dist/engine/execution/public-job-sanitizer.d.ts +4 -0
- package/dist/engine/execution/public-job-sanitizer.js +31 -0
- package/dist/engine/execution/validate-job-executor.d.ts +12 -1
- package/dist/engine/execution/validate-job-executor.js +549 -86
- package/dist/engine/execution/validate-job-payload.js +107 -50
- package/dist/engine/execution/validate-job-recovery.js +1 -1
- package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
- package/dist/engine/execution/validate-worker-runtime.js +90 -2
- package/dist/engine/execution/validate-worker-thread.js +17 -24
- package/dist/engine/handoff-artifacts/schemas.d.ts +2 -1
- package/dist/engine/handoff-artifacts/schemas.js +33 -0
- package/dist/engine/handoff-packager.d.ts +19 -0
- package/dist/engine/handoff-packager.js +415 -13
- package/dist/engine/hooks/effort-configurator.js +1 -1
- package/dist/engine/impact-detector/test-break-predictor.js +3 -3
- package/dist/engine/impact-detector/tool-registration.js +1 -1
- package/dist/engine/implementation-contract/renderer.js +23 -8
- package/dist/engine/lifecycle-reconciliation-io.d.ts +11 -0
- package/dist/engine/lifecycle-reconciliation-io.js +180 -0
- package/dist/engine/lifecycle-reconciliation.d.ts +16 -0
- package/dist/engine/lifecycle-reconciliation.js +406 -0
- package/dist/engine/local-first/tool-classification.js +2 -0
- package/dist/engine/macos-keychain-native-port.d.ts +5 -0
- package/dist/engine/macos-keychain-native-port.js +19 -7
- package/dist/engine/migrations/remove-commercial-state.d.ts +3 -0
- package/dist/engine/migrations/remove-commercial-state.js +343 -0
- package/dist/engine/minimality/policy-loader.js +247 -6
- package/dist/engine/network-policy.js +1 -0
- package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-arm64.node.sbom.json +20 -20
- package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-x64.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +20 -20
- package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +20 -20
- package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +20 -20
- package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +20 -20
- package/dist/engine/readiness-checker.d.ts +1 -16
- package/dist/engine/readiness-checker.js +27 -88
- package/dist/engine/reverse-engineer/api-detector.js +2 -13
- package/dist/engine/reverse-engineer/complexity-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/config-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/dependency-graph.js +2 -13
- package/dist/engine/reverse-engineer/test-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/walk-ignore.d.ts +3 -0
- package/dist/engine/reverse-engineer/walk-ignore.js +26 -0
- package/dist/engine/runtime-policy.d.ts +2 -0
- package/dist/engine/runtime-policy.js +42 -5
- package/dist/engine/runtime-security/rate-limiter.js +0 -1
- package/dist/engine/safety/contained-project-file.d.ts +3 -0
- package/dist/engine/safety/contained-project-file.js +23 -0
- package/dist/engine/scope-boundaries/contradiction-checker.js +63 -1
- package/dist/engine/scope-boundaries/scope-validator.js +45 -7
- package/dist/engine/session/checkpoint-writer.js +0 -9
- package/dist/engine/spec-format/acceptance-criteria.d.ts +6 -2
- package/dist/engine/spec-format/acceptance-criteria.js +82 -22
- package/dist/engine/spec-format/markdown-sections.d.ts +14 -0
- package/dist/engine/spec-format/markdown-sections.js +105 -0
- package/dist/engine/spec-format/read-technical-section.js +33 -5
- package/dist/engine/spec-format/technical-md-populator.js +3 -2
- package/dist/engine/spec-format/text-fences.js +20 -2
- package/dist/engine/spec-format/unified-spec-builder.d.ts +7 -0
- package/dist/engine/spec-format/unified-spec-builder.js +202 -0
- package/dist/engine/spec-migrator/canonical-deduplicator.d.ts +18 -0
- package/dist/engine/spec-migrator/canonical-deduplicator.js +479 -0
- package/dist/engine/spec-migrator/filesystem-import.d.ts +4 -8
- package/dist/engine/spec-migrator/filesystem-import.js +121 -14
- package/dist/engine/spec-migrator/frontmatter-parser.js +32 -15
- package/dist/engine/spec-migrator/index.d.ts +1 -0
- package/dist/engine/spec-migrator/index.js +1 -0
- package/dist/engine/spec-state-machine/transition-spec.d.ts +6 -1
- package/dist/engine/spec-state-machine/transition-spec.js +10 -1
- package/dist/engine/spec-state-syncer.js +1 -1
- package/dist/engine/technical-enricher/index.js +16 -8
- package/dist/engine/technical-enricher/render-enriched.d.ts +1 -0
- package/dist/engine/technical-enricher/render-enriched.js +42 -14
- package/dist/engine/telemetry/health-checker.js +53 -17
- package/dist/engine/telemetry/telemetry-client.js +26 -8
- package/dist/engine/text-signal-boundaries.d.ts +2 -0
- package/dist/engine/text-signal-boundaries.js +25 -2
- package/dist/engine/time/relative-date.d.ts +3 -0
- package/dist/engine/time/relative-date.js +16 -0
- package/dist/engine/timing/budget.d.ts +11 -0
- package/dist/engine/timing/budget.js +31 -9
- package/dist/engine/token-optimizer/analytics.d.ts +1 -1
- package/dist/engine/token-optimizer/analytics.js +5 -6
- package/dist/engine/usage-tracker/core.d.ts +2 -2
- package/dist/engine/usage-tracker/core.js +1 -2
- package/dist/engine/usage-tracker/index.d.ts +0 -3
- package/dist/engine/usage-tracker/index.js +0 -3
- package/dist/engine/usage-tracker/stats.d.ts +2 -2
- package/dist/engine/usage-tracker/stats.js +1 -28
- package/dist/engine/validation/durable-validation.d.ts +1 -1
- package/dist/engine/validation/durable-validation.js +3 -82
- package/dist/engine/validation/validation-freshness.d.ts +11 -1
- package/dist/engine/validation/validation-freshness.js +231 -91
- package/dist/engine/validation/validation-receipt.d.ts +9 -6
- package/dist/engine/validation/validation-receipt.js +84 -24
- package/dist/engine/validation/validation-source-digest.d.ts +2 -0
- package/dist/engine/validation/validation-source-digest.js +86 -0
- package/dist/engine/validation/validation-submission.d.ts +5 -4
- package/dist/engine/validation/validation-submission.js +25 -11
- package/dist/engine/validation/validation-worktree.d.ts +21 -0
- package/dist/engine/validation/validation-worktree.js +260 -0
- package/dist/engine/validation-impact-planner.d.ts +14 -2
- package/dist/engine/validation-impact-planner.js +0 -3
- package/dist/engine/validator/dor-dod.d.ts +1 -0
- package/dist/engine/validator/dor-dod.js +5 -3
- package/dist/engine/validator/extractors.d.ts +1 -5
- package/dist/engine/validator/extractors.js +24 -69
- package/dist/engine/validator/spec-compliance-runner.d.ts +12 -24
- package/dist/engine/validator/spec-compliance-runner.js +429 -211
- package/dist/engine/validator.js +35 -22
- package/dist/index.js +4 -16
- package/dist/resources/usage-stats-resource.js +2 -18
- package/dist/security/adapters/linux-secret-service.js +7 -3
- package/dist/security/adapters/windows-credential-manager.js +6 -4
- package/dist/server/routes/specs.js +13 -1
- package/dist/storage/base-store.d.ts +1 -1
- package/dist/storage/base-store.js +1 -1
- package/dist/storage/feedback-remote.d.ts +2 -3
- package/dist/storage/feedback-remote.js +45 -31
- package/dist/storage/global-store.d.ts +1 -17
- package/dist/storage/global-store.js +1 -42
- package/dist/storage/index.d.ts +0 -2
- package/dist/storage/index.js +0 -2
- package/dist/storage/migrations/canonical-storage.js +124 -11
- package/dist/storage/runtime-db.d.ts +9 -0
- package/dist/storage/runtime-db.js +64 -8
- package/dist/storage/spec-store.d.ts +14 -2
- package/dist/storage/spec-store.js +104 -14
- package/dist/storage/status-store/atomic-status-write.d.ts +5 -0
- package/dist/storage/status-store/atomic-status-write.js +57 -0
- package/dist/storage/status-store/file-lock.js +30 -11
- package/dist/storage/status-store/self-healing.js +3 -3
- package/dist/storage/status-store/version-sync.d.ts +2 -1
- package/dist/storage/status-store/version-sync.js +35 -40
- package/dist/storage/usage-store.d.ts +1 -5
- package/dist/storage/usage-store.js +0 -35
- package/dist/tools/auto-update-handler.d.ts +3 -3
- package/dist/tools/auto-update-handler.js +3 -3
- package/dist/tools/challenge-spec/resilience-challenge-scenarios.d.ts +2 -1
- package/dist/tools/challenge-spec/resilience-challenge-scenarios.js +10 -7
- package/dist/tools/challenge-spec/scenario-collector.js +1 -1
- package/dist/tools/challenge-spec/scenarios-data.js +1 -1
- package/dist/tools/challenge-spec/scenarios-utils.d.ts +1 -1
- package/dist/tools/challenge-spec/scenarios-utils.js +35 -11
- package/dist/tools/challenge-spec-helpers.d.ts +10 -1
- package/dist/tools/challenge-spec-helpers.js +63 -22
- package/dist/tools/challenge-spec.js +23 -8
- package/dist/tools/check-readiness.js +38 -14
- package/dist/tools/configure-telemetry.js +30 -2
- package/dist/tools/create-spec/spec-builder.d.ts +7 -0
- package/dist/tools/create-spec/spec-builder.js +19 -15
- package/dist/tools/create-spec.d.ts +1 -0
- package/dist/tools/create-spec.js +584 -309
- package/dist/tools/git/branch-ops.d.ts +1 -1
- package/dist/tools/git/branch-ops.js +3 -2
- package/dist/tools/init-project/handler.js +10 -12
- package/dist/tools/init-project/host-assets-writer.js +26 -1
- package/dist/tools/init-project/lint-scaffolder.d.ts +3 -3
- package/dist/tools/init-project/migration-runner.d.ts +2 -4
- package/dist/tools/init-project/migration-runner.js +3 -2
- package/dist/tools/init-project/portable-index-reconciler.d.ts +4 -0
- package/dist/tools/init-project/portable-index-reconciler.js +14 -0
- package/dist/tools/init-project/result-builder.js +1 -3
- package/dist/tools/jobs/handlers.js +38 -6
- package/dist/tools/list-specs.js +5 -26
- package/dist/tools/merge-risk-handler.js +2 -2
- package/dist/tools/package-handoff.js +2 -0
- package/dist/tools/reconcile-spec.js +0 -27
- package/dist/tools/register-agent-squad-tools.js +2 -2
- package/dist/tools/register-platform-tools/design-stack-tools.js +11 -11
- package/dist/tools/register-platform-tools/lifecycle-infra-tools.js +7 -7
- package/dist/tools/register-sdd-tools.d.ts +1 -1
- package/dist/tools/register-sdd-tools.js +2 -29
- package/dist/tools/register-spec-tools/analysis-tools.js +8 -8
- package/dist/tools/register-spec-tools/core-spec-tools.js +29 -19
- package/dist/tools/safe-handler.d.ts +5 -13
- package/dist/tools/safe-handler.js +7 -23
- package/dist/tools/schemas/index.d.ts +1 -1
- package/dist/tools/schemas/index.js +1 -1
- package/dist/tools/schemas/output-schemas.d.ts +0 -23
- package/dist/tools/schemas/output-schemas.js +0 -28
- package/dist/tools/schemas/spec.d.ts +4 -0
- package/dist/tools/schemas/spec.js +3 -0
- package/dist/tools/schemas/validate-output-schema.d.ts +11 -0
- package/dist/tools/schemas/validate-output-schema.js +7 -0
- package/dist/tools/spec-prompt-handler.js +3 -3
- package/dist/tools/sync-spec-state-handler.d.ts +1 -1
- package/dist/tools/sync-spec-state-handler.js +50 -2
- package/dist/tools/tool-entry.d.ts +4 -4
- package/dist/tools/tool-entry.js +3 -3
- package/dist/tools/tool-registry/core-tools.js +31 -15
- package/dist/tools/tool-registry/group-infra.js +27 -110
- package/dist/tools/tool-registry/group-quality-compliance.js +26 -26
- package/dist/tools/tool-registry/inventory.d.ts +2 -0
- package/dist/tools/tool-registry/inventory.js +2 -0
- package/dist/tools/tool-registry-helpers.d.ts +3 -3
- package/dist/tools/tool-registry-helpers.js +3 -3
- package/dist/tools/tool-usage-report/registered-tools.d.ts +1 -1
- package/dist/tools/tool-usage-report/registered-tools.js +3 -15
- package/dist/tools/update-status/approval-gates.js +3 -0
- package/dist/tools/update-status/batch.d.ts +6 -2
- package/dist/tools/update-status/batch.js +58 -1
- package/dist/tools/update-status/dod-gates.d.ts +16 -1
- package/dist/tools/update-status/dod-gates.js +191 -1
- package/dist/tools/update-status/done-receipt-verifier.d.ts +8 -0
- package/dist/tools/update-status/done-receipt-verifier.js +75 -27
- package/dist/tools/update-status/evidence-gate.d.ts +4 -0
- package/dist/tools/update-status/evidence-gate.js +103 -3
- package/dist/tools/update-status/file-sync.d.ts +4 -3
- package/dist/tools/update-status/file-sync.js +57 -6
- package/dist/tools/update-status/index.d.ts +25 -1
- package/dist/tools/update-status/index.js +292 -78
- package/dist/tools/update-status/response-builder.js +3 -3
- package/dist/tools/update-status/side-effects.d.ts +2 -0
- package/dist/tools/update-status/side-effects.js +2 -2
- package/dist/tools/update-status/transition-guard.js +45 -16
- package/dist/tools/update-status-actions.d.ts +4 -2
- package/dist/tools/update-status-actions.js +16 -14
- package/dist/tools/usage-report.js +1 -16
- package/dist/tools/usage-stats.js +1 -18
- package/dist/tools/usage-tracking.d.ts +4 -0
- package/dist/tools/usage-tracking.js +20 -0
- package/dist/tools/validate-lint.d.ts +1 -0
- package/dist/tools/validate-lint.js +1 -1
- package/dist/tools/validate.d.ts +2 -1
- package/dist/tools/validate.js +114 -34
- package/dist/tools/workspace-dashboard-handler.js +38 -0
- package/dist/transports/http-transport.js +6 -8
- package/dist/transports/mcp-types.d.ts +0 -2
- package/dist/transports/session-context.js +1 -1
- package/dist/types/cascade-hooks.d.ts +1 -1
- package/dist/types/ci.d.ts +0 -4
- package/dist/types/clarification-token.d.ts +1 -1
- package/dist/types/claude-code-runtime.d.ts +0 -27
- package/dist/types/commercial-migration.d.ts +17 -0
- package/dist/types/commercial-migration.js +2 -0
- package/dist/types/common/primitives.d.ts +0 -2
- package/dist/types/core-bridge.d.ts +4 -10
- package/dist/types/dashboard.d.ts +3 -7
- package/dist/types/docs.d.ts +0 -1
- package/dist/types/durable-job.d.ts +4 -4
- package/dist/types/durable-validation.d.ts +100 -2
- package/dist/types/durable-validation.js +165 -1
- package/dist/types/errors/structured-error.d.ts +3 -3
- package/dist/types/estimation.d.ts +2 -0
- package/dist/types/evidence-autofill.d.ts +34 -0
- package/dist/types/evidence-autofill.js +2 -0
- package/dist/types/evidence-gates.d.ts +9 -1
- package/dist/types/execution.d.ts +2 -0
- package/dist/types/gemini-integration.d.ts +0 -11
- package/dist/types/handoff-artifacts.d.ts +41 -0
- package/dist/types/hooks-advanced.d.ts +0 -13
- package/dist/types/impact-detection.d.ts +2 -2
- package/dist/types/index.d.ts +3 -6
- package/dist/types/index.js +2 -5
- package/dist/types/kiro-integration.d.ts +0 -6
- package/dist/types/network-policy.d.ts +1 -1
- package/dist/types/project/lint-scaffolder.d.ts +1 -1
- package/dist/types/runtime-policy.d.ts +11 -0
- package/dist/types/session-safeguard.d.ts +0 -31
- package/dist/types/spec/canonical-repair.d.ts +81 -0
- package/dist/types/spec/canonical-repair.js +2 -0
- package/dist/types/spec/core.d.ts +20 -0
- package/dist/types/spec/index.d.ts +1 -0
- package/dist/types/spec/index.js +1 -0
- package/dist/types/spec/inputs.d.ts +35 -1
- package/dist/types/spec-format.d.ts +25 -1
- package/dist/types/telemetry.d.ts +4 -1
- package/dist/types/transition-log.d.ts +1 -1
- package/dist/types/transport.d.ts +0 -2
- package/dist/types/usage.d.ts +1 -36
- package/dist/types/usage.js +1 -1
- package/dist/types/validate-worker.d.ts +6 -0
- package/dist/types/validation-receipt.d.ts +1 -1
- package/dist/types/validation.d.ts +10 -4
- package/package.json +17 -12
- package/planu-native.json +1 -1
- package/planu-plugin.json +23 -40
- package/scripts/lib/pending-release-file.mjs +93 -0
- package/src/i18n/messages/en.json +0 -41
- package/src/i18n/messages/es.json +0 -41
- package/src/i18n/messages/pt.json +0 -41
- package/dist/cli/commands/activate.d.ts +0 -14
- package/dist/cli/commands/activate.js +0 -174
- package/dist/config/license-plans.json +0 -251
- package/dist/config/product-public.ts +0 -148
- package/dist/config/server-instructions.ts +0 -121
- package/dist/config/version-defaults.ts +0 -76
- package/dist/config/version.ts +0 -21
- package/dist/engine/ai-integration/gemini/settings-generator.d.ts +0 -4
- package/dist/engine/ai-integration/gemini/settings-generator.js +0 -195
- package/dist/engine/ai-integration/kiro/hooks-generator.d.ts +0 -6
- package/dist/engine/ai-integration/kiro/hooks-generator.js +0 -75
- package/dist/engine/hooks/full-spectrum-generator.d.ts +0 -32
- package/dist/engine/hooks/full-spectrum-generator.js +0 -117
- package/dist/engine/license-validator/config-loader.d.ts +0 -5
- package/dist/engine/license-validator/config-loader.js +0 -16
- package/dist/engine/license-validator/core.d.ts +0 -15
- package/dist/engine/license-validator/core.js +0 -151
- package/dist/engine/license-validator/fingerprint.d.ts +0 -3
- package/dist/engine/license-validator/fingerprint.js +0 -17
- package/dist/engine/license-validator/lemon-squeezy.d.ts +0 -5
- package/dist/engine/license-validator/lemon-squeezy.js +0 -55
- package/dist/engine/license-validator.d.ts +0 -5
- package/dist/engine/license-validator.js +0 -6
- package/dist/engine/product-intelligence/index.d.ts +0 -7
- package/dist/engine/product-intelligence/index.js +0 -211
- package/dist/engine/session/auto-save.d.ts +0 -18
- package/dist/engine/session/auto-save.js +0 -98
- package/dist/engine/session/context-snapshot.d.ts +0 -8
- package/dist/engine/session/context-snapshot.js +0 -49
- package/dist/engine/session/memory-sync.d.ts +0 -12
- package/dist/engine/session/memory-sync.js +0 -34
- package/dist/engine/session/session-diff.d.ts +0 -11
- package/dist/engine/session/session-diff.js +0 -42
- package/dist/engine/session/session-merge.d.ts +0 -12
- package/dist/engine/session/session-merge.js +0 -55
- package/dist/engine/session-safeguard/checkpoint-runner.d.ts +0 -4
- package/dist/engine/session-safeguard/checkpoint-runner.js +0 -70
- package/dist/engine/session-safeguard/learnings-buffer.d.ts +0 -15
- package/dist/engine/session-safeguard/learnings-buffer.js +0 -91
- package/dist/engine/session-safeguard/precompaction-drain.d.ts +0 -10
- package/dist/engine/session-safeguard/precompaction-drain.js +0 -82
- package/dist/engine/session-safeguard/unpushed-detector.d.ts +0 -7
- package/dist/engine/session-safeguard/unpushed-detector.js +0 -59
- package/dist/engine/spec-changelog/core.d.ts +0 -16
- package/dist/engine/spec-changelog/core.js +0 -176
- package/dist/engine/spec-changelog/diff.d.ts +0 -18
- package/dist/engine/spec-changelog/diff.js +0 -121
- package/dist/engine/spec-changelog/index.d.ts +0 -3
- package/dist/engine/spec-changelog/index.js +0 -4
- package/dist/engine/trial-engine.d.ts +0 -5
- package/dist/engine/trial-engine.js +0 -14
- package/dist/engine/usage-tracker/rate-check.d.ts +0 -7
- package/dist/engine/usage-tracker/rate-check.js +0 -18
- package/dist/engine/usage-tracker/rate-limiter.d.ts +0 -14
- package/dist/engine/usage-tracker/rate-limiter.js +0 -73
- package/dist/engine/usage-tracker/trial.d.ts +0 -27
- package/dist/engine/usage-tracker/trial.js +0 -49
- package/dist/engine/webhook/event-handlers.d.ts +0 -25
- package/dist/engine/webhook/event-handlers.js +0 -89
- package/dist/engine/webhook/index.d.ts +0 -4
- package/dist/engine/webhook/index.js +0 -5
- package/dist/engine/webhook/server.d.ts +0 -12
- package/dist/engine/webhook/server.js +0 -249
- package/dist/engine/webhook/signature.d.ts +0 -16
- package/dist/engine/webhook/signature.js +0 -49
- package/dist/storage/license-store.d.ts +0 -6
- package/dist/storage/license-store.js +0 -63
- package/dist/storage/session-store.d.ts +0 -20
- package/dist/storage/session-store.js +0 -136
- package/dist/tools/activate-license.d.ts +0 -6
- package/dist/tools/activate-license.js +0 -132
- package/dist/tools/checkpoint-handler.d.ts +0 -3
- package/dist/tools/checkpoint-handler.js +0 -130
- package/dist/tools/export-session.d.ts +0 -3
- package/dist/tools/export-session.js +0 -90
- package/dist/tools/license-gate.d.ts +0 -18
- package/dist/tools/license-gate.js +0 -222
- package/dist/tools/license-status.d.ts +0 -3
- package/dist/tools/license-status.js +0 -93
- package/dist/tools/list-sessions.d.ts +0 -3
- package/dist/tools/list-sessions.js +0 -46
- package/dist/tools/planu-session-checkpoint.d.ts +0 -6
- package/dist/tools/planu-session-checkpoint.js +0 -42
- package/dist/tools/restore-session.d.ts +0 -3
- package/dist/tools/restore-session.js +0 -71
- package/dist/tools/spec-history.d.ts +0 -3
- package/dist/tools/spec-history.js +0 -59
- package/dist/tools/webhook.d.ts +0 -6
- package/dist/tools/webhook.js +0 -150
- package/dist/types/changelog.d.ts +0 -49
- package/dist/types/changelog.js +0 -3
- package/dist/types/licensing.d.ts +0 -109
- package/dist/types/licensing.js +0 -4
- package/dist/types/product-intelligence.d.ts +0 -60
- package/dist/types/product-intelligence.js +0 -3
- package/dist/types/session.d.ts +0 -84
- package/dist/types/session.js +0 -3
- package/dist/types/webhook.d.ts +0 -62
- package/dist/types/webhook.js +0 -4
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { detectUnpushedCommits } from './unpushed-detector.js';
|
|
2
|
-
import { flushBuffer } from './learnings-buffer.js';
|
|
3
|
-
import { safeAutopush } from './autopush.js';
|
|
4
|
-
const WARN_UNPUSHED_HOURS = 2;
|
|
5
|
-
/** Regenerate session-context.md (fire-and-forget, best-effort). */
|
|
6
|
-
async function regenerateSessionContext(projectPath) {
|
|
7
|
-
try {
|
|
8
|
-
const { generateSessionContext } = await import('../session-context-generator.js');
|
|
9
|
-
const { resolveProjectIdOrAutoDetect } = await import('../../tools/resolve-project-id.js');
|
|
10
|
-
const resolved = await resolveProjectIdOrAutoDetect({ projectPath });
|
|
11
|
-
if (!resolved.ok) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
await generateSessionContext(projectPath, resolved.projectId);
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
/** Build the human-readable summary line for checkpoint output. */
|
|
22
|
-
function buildHumanSummary(sessionContextRefreshed, learningsFlushed, unpushed, pushed) {
|
|
23
|
-
const parts = [];
|
|
24
|
-
if (sessionContextRefreshed) {
|
|
25
|
-
parts.push('session-context.md refreshed');
|
|
26
|
-
}
|
|
27
|
-
if (learningsFlushed > 0) {
|
|
28
|
-
parts.push(`${String(learningsFlushed)} learning(s) flushed to MEMORY.md`);
|
|
29
|
-
}
|
|
30
|
-
if (pushed !== undefined) {
|
|
31
|
-
if (pushed.pushed) {
|
|
32
|
-
parts.push(`autopush: ${String(pushed.commitsPushed)} commit(s) pushed to ${pushed.ref}`);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
parts.push(`autopush skipped (${pushed.reason})`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else if (unpushed && unpushed.oldestAgeHours >= WARN_UNPUSHED_HOURS) {
|
|
39
|
-
parts.push(`WARNING: ${String(unpushed.count)} commit(s) unpushed for ${String(unpushed.oldestAgeHours)}h on branch ${unpushed.branch}. Run git push or enable autopush.`);
|
|
40
|
-
}
|
|
41
|
-
return parts.length > 0 ? parts.join('; ') : 'Checkpoint complete — nothing to do.';
|
|
42
|
-
}
|
|
43
|
-
/** Run a full session checkpoint: regen context, flush buffer, detect/push unpushed. */
|
|
44
|
-
export async function runCheckpoint(options) {
|
|
45
|
-
const { projectPath, dryRun = false, autopush = false, autopushBranches } = options;
|
|
46
|
-
// This runner backs the explicit checkpoint tool, so refresh even when the
|
|
47
|
-
// file mtime is recent: package releases can change semantic state instantly.
|
|
48
|
-
const sessionContextRefreshed = dryRun ? false : await regenerateSessionContext(projectPath);
|
|
49
|
-
// Flush learnings buffer
|
|
50
|
-
let learningsFlushed = 0;
|
|
51
|
-
if (!dryRun) {
|
|
52
|
-
learningsFlushed = await flushBuffer(projectPath).catch(() => 0);
|
|
53
|
-
}
|
|
54
|
-
// Detect unpushed commits
|
|
55
|
-
const unpushedCommits = await detectUnpushedCommits(projectPath);
|
|
56
|
-
// Autopush if configured
|
|
57
|
-
let pushed;
|
|
58
|
-
if (autopush && !dryRun) {
|
|
59
|
-
pushed = await safeAutopush(projectPath, autopushBranches);
|
|
60
|
-
}
|
|
61
|
-
const humanSummary = buildHumanSummary(sessionContextRefreshed, learningsFlushed, unpushedCommits, pushed);
|
|
62
|
-
return {
|
|
63
|
-
sessionContextRefreshed,
|
|
64
|
-
learningsFlushed,
|
|
65
|
-
unpushedCommits,
|
|
66
|
-
...(pushed !== undefined ? { pushed } : {}),
|
|
67
|
-
humanSummary,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
//# sourceMappingURL=checkpoint-runner.js.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { LearningsBuffer, LearningEntry } from '../../types/index.js';
|
|
2
|
-
/** Read the learnings buffer for a project (best-effort, returns empty on miss). */
|
|
3
|
-
export declare function readBuffer(projectPath: string): Promise<LearningsBuffer>;
|
|
4
|
-
/**
|
|
5
|
-
* Append an entry under the shared transactional lease authority.
|
|
6
|
-
*/
|
|
7
|
-
export declare function appendToBuffer(projectPath: string, entry: LearningEntry): Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* Flush all entries in the learnings buffer to MEMORY.md.
|
|
10
|
-
* Appends under an existing section or creates a new one.
|
|
11
|
-
* Clears the buffer after successful write.
|
|
12
|
-
* Returns the number of entries flushed.
|
|
13
|
-
*/
|
|
14
|
-
export declare function flushBuffer(projectPath: string): Promise<number>;
|
|
15
|
-
//# sourceMappingURL=learnings-buffer.d.ts.map
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
// engine/session-safeguard/learnings-buffer.ts — SPEC-585: Append/flush learnings buffer
|
|
2
|
-
import { readFile, mkdir } from 'node:fs/promises';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { hashProjectPath, projectDataDir } from '../../storage/base-store.js';
|
|
6
|
-
import { acquireLock, releaseLock } from '../safety/file-mutex.js';
|
|
7
|
-
import { atomicWriteFile } from '../safety/atomic-write-file.js';
|
|
8
|
-
import { assertNoObsoleteFileLock } from '../safety/obsolete-lock-guard.js';
|
|
9
|
-
const BUFFER_VERSION = 1;
|
|
10
|
-
const LOCK_TIMEOUT_MS = 10_000;
|
|
11
|
-
function bufferPath(projectPath) {
|
|
12
|
-
const hash = hashProjectPath(projectPath);
|
|
13
|
-
return join(projectDataDir(hash), 'learnings-buffer.json');
|
|
14
|
-
}
|
|
15
|
-
function claudeMemoryPath(projectPath) {
|
|
16
|
-
const projectKey = projectPath.replaceAll('\\', '-').replaceAll('/', '-');
|
|
17
|
-
return join(homedir(), '.claude', 'projects', projectKey, 'memory', 'MEMORY.md');
|
|
18
|
-
}
|
|
19
|
-
function emptyBuffer() {
|
|
20
|
-
return { version: BUFFER_VERSION, entries: [] };
|
|
21
|
-
}
|
|
22
|
-
/** Read the learnings buffer for a project (best-effort, returns empty on miss). */
|
|
23
|
-
export async function readBuffer(projectPath) {
|
|
24
|
-
try {
|
|
25
|
-
const raw = await readFile(bufferPath(projectPath), 'utf-8');
|
|
26
|
-
return JSON.parse(raw);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
return emptyBuffer();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/** Write the buffer to disk, creating parent dirs as needed. */
|
|
33
|
-
async function writeBuffer(projectPath, buffer) {
|
|
34
|
-
const path = bufferPath(projectPath);
|
|
35
|
-
await mkdir(join(path, '..'), { recursive: true });
|
|
36
|
-
await atomicWriteFile(path, JSON.stringify(buffer, null, 2));
|
|
37
|
-
}
|
|
38
|
-
async function withBufferLock(projectPath, operation) {
|
|
39
|
-
await assertNoObsoleteFileLock(`${bufferPath(projectPath)}.lock`, 'learnings buffer');
|
|
40
|
-
const handle = await acquireLock(bufferPath(projectPath), LOCK_TIMEOUT_MS);
|
|
41
|
-
try {
|
|
42
|
-
return await operation();
|
|
43
|
-
}
|
|
44
|
-
finally {
|
|
45
|
-
await releaseLock(handle);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Append an entry under the shared transactional lease authority.
|
|
50
|
-
*/
|
|
51
|
-
export async function appendToBuffer(projectPath, entry) {
|
|
52
|
-
await withBufferLock(projectPath, async () => {
|
|
53
|
-
const buffer = await readBuffer(projectPath);
|
|
54
|
-
buffer.entries.push(entry);
|
|
55
|
-
await writeBuffer(projectPath, buffer);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
/** Build the markdown bullet for an entry to append to MEMORY.md. */
|
|
59
|
-
function entryToMarkdown(entry) {
|
|
60
|
-
const label = `[${entry.category}/${entry.source}]`;
|
|
61
|
-
return `- ${label} ${entry.content} _(${entry.timestamp.slice(0, 10)})_`;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Flush all entries in the learnings buffer to MEMORY.md.
|
|
65
|
-
* Appends under an existing section or creates a new one.
|
|
66
|
-
* Clears the buffer after successful write.
|
|
67
|
-
* Returns the number of entries flushed.
|
|
68
|
-
*/
|
|
69
|
-
export async function flushBuffer(projectPath) {
|
|
70
|
-
return withBufferLock(projectPath, async () => {
|
|
71
|
-
const buffer = await readBuffer(projectPath);
|
|
72
|
-
if (buffer.entries.length === 0) {
|
|
73
|
-
return 0;
|
|
74
|
-
}
|
|
75
|
-
const memoryPath = claudeMemoryPath(projectPath);
|
|
76
|
-
let existing = '';
|
|
77
|
-
try {
|
|
78
|
-
existing = await readFile(memoryPath, 'utf-8');
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
/* file may not exist */
|
|
82
|
-
}
|
|
83
|
-
const bullets = buffer.entries.map(entryToMarkdown).join('\n');
|
|
84
|
-
const section = `\n\n## Session Learnings (auto-flushed ${new Date().toISOString().slice(0, 10)})\n\n${bullets}\n`;
|
|
85
|
-
await mkdir(join(memoryPath, '..'), { recursive: true });
|
|
86
|
-
await atomicWriteFile(memoryPath, existing + section);
|
|
87
|
-
await writeBuffer(projectPath, emptyBuffer());
|
|
88
|
-
return buffer.entries.length;
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
//# sourceMappingURL=learnings-buffer.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { PrecompactionDrainReport, PrecompactionDrainOptions } from '../../types/claude-code-runtime.js';
|
|
2
|
-
/**
|
|
3
|
-
* Drain learnings buffer to MEMORY.md fragments, autopush unpushed commits,
|
|
4
|
-
* and write session-context.md — all before context compaction completes.
|
|
5
|
-
*
|
|
6
|
-
* Every operation is best-effort: a failure in one step does not prevent
|
|
7
|
-
* the others from running. The drain report captures all outcomes.
|
|
8
|
-
*/
|
|
9
|
-
export declare function runPrecompactionDrain(projectPath: string, options?: PrecompactionDrainOptions): Promise<PrecompactionDrainReport>;
|
|
10
|
-
//# sourceMappingURL=precompaction-drain.d.ts.map
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// engine/session-safeguard/precompaction-drain.ts — SPEC-587
|
|
2
|
-
// Runs when PreCompaction fires: drains learnings buffer, autopushes commits,
|
|
3
|
-
// writes session-context.md — all before context compaction completes.
|
|
4
|
-
import { flushBuffer } from './learnings-buffer.js';
|
|
5
|
-
import { safeAutopush } from './autopush.js';
|
|
6
|
-
/**
|
|
7
|
-
* Regenerate session-context.md (best-effort, resolves projectId automatically).
|
|
8
|
-
* Returns true when successfully written.
|
|
9
|
-
*/
|
|
10
|
-
async function writeSessionContext(projectPath) {
|
|
11
|
-
try {
|
|
12
|
-
const { generateSessionContext } = await import('../session-context-generator.js');
|
|
13
|
-
const { resolveProjectIdOrAutoDetect } = await import('../../tools/resolve-project-id.js');
|
|
14
|
-
const resolved = await resolveProjectIdOrAutoDetect({ projectPath });
|
|
15
|
-
if (!resolved.ok) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
await generateSessionContext(projectPath, resolved.projectId);
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Drain learnings buffer to MEMORY.md fragments, autopush unpushed commits,
|
|
27
|
-
* and write session-context.md — all before context compaction completes.
|
|
28
|
-
*
|
|
29
|
-
* Every operation is best-effort: a failure in one step does not prevent
|
|
30
|
-
* the others from running. The drain report captures all outcomes.
|
|
31
|
-
*/
|
|
32
|
-
export async function runPrecompactionDrain(projectPath, options = {}) {
|
|
33
|
-
const { dryRun = false, autopushBranches } = options;
|
|
34
|
-
// 1. Drain learnings buffer to MEMORY.md fragments
|
|
35
|
-
let learningsFlushed = 0;
|
|
36
|
-
if (!dryRun) {
|
|
37
|
-
learningsFlushed = await flushBuffer(projectPath).catch(() => 0);
|
|
38
|
-
}
|
|
39
|
-
// 2. Autopush unpushed commits (best-effort)
|
|
40
|
-
let autopushResult;
|
|
41
|
-
if (!dryRun) {
|
|
42
|
-
const result = await safeAutopush(projectPath, autopushBranches).catch((err) => {
|
|
43
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
44
|
-
return { pushed: false, reason: msg };
|
|
45
|
-
});
|
|
46
|
-
autopushResult = result.pushed
|
|
47
|
-
? { pushed: true, ref: result.ref, commitsPushed: result.commitsPushed }
|
|
48
|
-
: { pushed: false, reason: result.reason };
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
autopushResult = { pushed: false, reason: 'dry-run' };
|
|
52
|
-
}
|
|
53
|
-
// 3. Write session-context.md
|
|
54
|
-
let sessionContextWritten = false;
|
|
55
|
-
if (!dryRun) {
|
|
56
|
-
sessionContextWritten = await writeSessionContext(projectPath);
|
|
57
|
-
}
|
|
58
|
-
// Build human summary
|
|
59
|
-
const parts = [];
|
|
60
|
-
if (learningsFlushed > 0) {
|
|
61
|
-
parts.push(`${String(learningsFlushed)} learning(s) flushed to MEMORY.md`);
|
|
62
|
-
}
|
|
63
|
-
if (autopushResult.pushed) {
|
|
64
|
-
parts.push(`autopush: ${String(autopushResult.commitsPushed)} commit(s) pushed to ${autopushResult.ref}`);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
parts.push(`autopush skipped (${autopushResult.reason})`);
|
|
68
|
-
}
|
|
69
|
-
if (sessionContextWritten) {
|
|
70
|
-
parts.push('session-context.md written');
|
|
71
|
-
}
|
|
72
|
-
const humanSummary = parts.length > 0
|
|
73
|
-
? `PreCompaction drain: ${parts.join('; ')}`
|
|
74
|
-
: 'PreCompaction drain: nothing to do';
|
|
75
|
-
return {
|
|
76
|
-
learningsFlushed,
|
|
77
|
-
sessionContextWritten,
|
|
78
|
-
autopushResult,
|
|
79
|
-
humanSummary,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=precompaction-drain.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { UnpushedCommitInfo } from '../../types/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Detect unpushed commits on the current branch.
|
|
4
|
-
* Returns null when not a git repo, detached HEAD, or no upstream configured.
|
|
5
|
-
*/
|
|
6
|
-
export declare function detectUnpushedCommits(projectPath: string): Promise<UnpushedCommitInfo | null>;
|
|
7
|
-
//# sourceMappingURL=unpushed-detector.d.ts.map
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// engine/session-safeguard/unpushed-detector.ts — SPEC-585: Detect unpushed commits with age
|
|
2
|
-
import { execFile } from 'node:child_process';
|
|
3
|
-
import { promisify } from 'node:util';
|
|
4
|
-
const execFileAsync = promisify(execFile);
|
|
5
|
-
const MS_PER_HOUR = 3_600_000;
|
|
6
|
-
/** Return the current branch name or null if not in a git repo / detached HEAD. */
|
|
7
|
-
async function getBranch(projectPath) {
|
|
8
|
-
try {
|
|
9
|
-
const { stdout } = await execFileAsync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
10
|
-
cwd: projectPath,
|
|
11
|
-
});
|
|
12
|
-
const branch = stdout.trim();
|
|
13
|
-
return branch && branch !== 'HEAD' ? branch : null;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* List unpushed commits as Unix timestamps (author date, seconds).
|
|
21
|
-
* Returns empty array when no upstream or no commits ahead.
|
|
22
|
-
*/
|
|
23
|
-
async function getUnpushedTimestamps(projectPath, branch) {
|
|
24
|
-
try {
|
|
25
|
-
const { stdout } = await execFileAsync('git', ['log', `origin/${branch}..HEAD`, '--format=%at'], { cwd: projectPath });
|
|
26
|
-
return stdout
|
|
27
|
-
.trim()
|
|
28
|
-
.split('\n')
|
|
29
|
-
.filter(Boolean)
|
|
30
|
-
.map((line) => parseInt(line, 10))
|
|
31
|
-
.filter((n) => !isNaN(n));
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Detect unpushed commits on the current branch.
|
|
39
|
-
* Returns null when not a git repo, detached HEAD, or no upstream configured.
|
|
40
|
-
*/
|
|
41
|
-
export async function detectUnpushedCommits(projectPath) {
|
|
42
|
-
const branch = await getBranch(projectPath);
|
|
43
|
-
if (!branch) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const timestamps = await getUnpushedTimestamps(projectPath, branch);
|
|
47
|
-
if (timestamps.length === 0) {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
const nowMs = Date.now();
|
|
51
|
-
const oldestTimestampMs = Math.min(...timestamps) * 1000;
|
|
52
|
-
const oldestAgeHours = Math.round((nowMs - oldestTimestampMs) / MS_PER_HOUR);
|
|
53
|
-
return {
|
|
54
|
-
count: timestamps.length,
|
|
55
|
-
branch,
|
|
56
|
-
oldestAgeHours,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
//# sourceMappingURL=unpushed-detector.js.map
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { SpecChangelogEntry, SpecChangelogData, AppendChangelogOptions, ReadChangelogOptions } from '../../types/index.js';
|
|
2
|
-
/** Format a single changelog entry as Markdown. */
|
|
3
|
-
export declare function formatEntry(entry: SpecChangelogEntry, specId: string): string;
|
|
4
|
-
/** Parse the timestamp from the first entry in a CHANGELOG.md content. */
|
|
5
|
-
export declare function parseFirstEntryTimestamp(content: string): string | null;
|
|
6
|
-
/** Parse changelog entries from a CHANGELOG.md content string. */
|
|
7
|
-
export declare function parseChangelogEntries(content: string, specId: string): SpecChangelogEntry[];
|
|
8
|
-
/** Read the CHANGELOG.md for a spec directory. Returns null if not found. */
|
|
9
|
-
export declare function readChangelog(options: ReadChangelogOptions): Promise<SpecChangelogData | null>;
|
|
10
|
-
/** Read only the timestamp of the last (most recent) changelog entry. Optimized for list_specs. */
|
|
11
|
-
export declare function readLastModifiedTimestamp(specDir: string): Promise<string | null>;
|
|
12
|
-
/** Append a new entry to the CHANGELOG.md for a spec. Creates the file if it doesn't exist. */
|
|
13
|
-
export declare function appendChangelogEntry(options: AppendChangelogOptions): Promise<boolean>;
|
|
14
|
-
/** Format a relative date string (e.g. "hace 2 dias") for a timestamp. */
|
|
15
|
-
export declare function formatRelativeDate(timestamp: string): string;
|
|
16
|
-
//# sourceMappingURL=core.d.ts.map
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// engine/spec-changelog/core.ts — Changelog entry creation and persistence
|
|
2
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
const CHANGELOG_FILENAME = 'CHANGELOG.md';
|
|
5
|
-
const CHANGELOG_VERSION_COMMENT = '<!-- changelog-version: 1 -->';
|
|
6
|
-
/** Format a single changelog entry as Markdown. */
|
|
7
|
-
export function formatEntry(entry, specId) {
|
|
8
|
-
const lines = [];
|
|
9
|
-
lines.push(`## ${entry.timestamp} — ${entry.type}`);
|
|
10
|
-
lines.push('');
|
|
11
|
-
lines.push(`**Tool**: ${entry.triggeredBy}`);
|
|
12
|
-
lines.push(`**Descripcion**: ${entry.description}`);
|
|
13
|
-
lines.push('');
|
|
14
|
-
if (entry.before !== undefined && entry.after !== undefined) {
|
|
15
|
-
if (entry.type === 'status_changed') {
|
|
16
|
-
lines.push(`**Antes**: ${entry.before.status} | **Despues**: ${entry.after.status}`);
|
|
17
|
-
lines.push(`**Progreso**: ${entry.before.completedCount}/${entry.before.criteriaCount} → ${entry.after.completedCount}/${entry.after.criteriaCount}`);
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
lines.push(`**Criterios antes**: ${entry.before.criteriaCount} | **Criterios despues**: ${entry.after.criteriaCount}`);
|
|
21
|
-
if (entry.type === 'progress_updated') {
|
|
22
|
-
lines.push(`**Progreso**: ${entry.before.completedCount}/${entry.before.criteriaCount} → ${entry.after.completedCount}/${entry.after.criteriaCount}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
lines.push('');
|
|
26
|
-
}
|
|
27
|
-
if (entry.diff !== undefined) {
|
|
28
|
-
const { added, removed, modified } = entry.diff;
|
|
29
|
-
const hasCriteriaChanges = added.length > 0 || removed.length > 0 || modified.length > 0;
|
|
30
|
-
if (hasCriteriaChanges) {
|
|
31
|
-
lines.push('### Criterios modificados');
|
|
32
|
-
for (const item of added) {
|
|
33
|
-
lines.push(`\u2795 ${item}`);
|
|
34
|
-
}
|
|
35
|
-
for (const item of removed) {
|
|
36
|
-
lines.push(`\u2796 ${item}`);
|
|
37
|
-
}
|
|
38
|
-
for (const item of modified) {
|
|
39
|
-
lines.push(`\u270f\ufe0f ${item.after} (antes: ${item.before})`);
|
|
40
|
-
}
|
|
41
|
-
lines.push('');
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
lines.push('---');
|
|
45
|
-
lines.push('');
|
|
46
|
-
void specId; // referenced in header externally
|
|
47
|
-
return lines.join('\n');
|
|
48
|
-
}
|
|
49
|
-
/** Build the full CHANGELOG.md header for a spec. */
|
|
50
|
-
function buildHeader(specId, specTitle) {
|
|
51
|
-
const title = specTitle ? `${specId}: ${specTitle}` : specId;
|
|
52
|
-
return [CHANGELOG_VERSION_COMMENT, '', `# Changelog — ${title}`, '', ''].join('\n');
|
|
53
|
-
}
|
|
54
|
-
/** Parse the timestamp from the first entry in a CHANGELOG.md content. */
|
|
55
|
-
export function parseFirstEntryTimestamp(content) {
|
|
56
|
-
// Matches lines like: ## 2026-03-04T14:23:00Z — reconciled
|
|
57
|
-
const match = /^## (\d{4}-\d{2}-\d{2}T[\d:.]+Z) —/m.exec(content);
|
|
58
|
-
return match?.[1] ?? null;
|
|
59
|
-
}
|
|
60
|
-
/** Parse changelog entries from a CHANGELOG.md content string. */
|
|
61
|
-
export function parseChangelogEntries(content, specId) {
|
|
62
|
-
const entries = [];
|
|
63
|
-
// Split on section headers: ## <timestamp> — <type>
|
|
64
|
-
const sectionRegex = /^## (\d{4}-\d{2}-\d{2}T[\d:.]+Z) — (\w+)/gm;
|
|
65
|
-
const matches = [...content.matchAll(sectionRegex)];
|
|
66
|
-
for (const match of matches) {
|
|
67
|
-
const timestamp = match[1];
|
|
68
|
-
const type = match[2];
|
|
69
|
-
if (timestamp === undefined || type === undefined) {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const sectionStart = match.index;
|
|
73
|
-
const nextIdx = matches.indexOf(match) + 1;
|
|
74
|
-
const nextMatch = nextIdx < matches.length ? matches[nextIdx] : undefined;
|
|
75
|
-
const sectionEnd = nextMatch?.index ?? content.length;
|
|
76
|
-
const sectionContent = content.slice(sectionStart, sectionEnd);
|
|
77
|
-
// Extract tool name
|
|
78
|
-
const toolMatch = /\*\*Tool\*\*: (.+)/.exec(sectionContent);
|
|
79
|
-
const triggeredBy = toolMatch?.[1]?.trim() ?? 'unknown';
|
|
80
|
-
// Extract description
|
|
81
|
-
const descMatch = /\*\*Descripcion\*\*: (.+)/.exec(sectionContent);
|
|
82
|
-
const description = descMatch?.[1]?.trim() ?? '';
|
|
83
|
-
entries.push({
|
|
84
|
-
timestamp,
|
|
85
|
-
type: type,
|
|
86
|
-
description,
|
|
87
|
-
triggeredBy,
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
void specId;
|
|
91
|
-
return entries;
|
|
92
|
-
}
|
|
93
|
-
/** Read the CHANGELOG.md for a spec directory. Returns null if not found. */
|
|
94
|
-
export async function readChangelog(options) {
|
|
95
|
-
const { specDir, specId } = options;
|
|
96
|
-
const filePath = join(specDir, CHANGELOG_FILENAME);
|
|
97
|
-
try {
|
|
98
|
-
const content = await readFile(filePath, 'utf-8');
|
|
99
|
-
const entries = parseChangelogEntries(content, specId);
|
|
100
|
-
return { specId, entries };
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/** Read only the timestamp of the last (most recent) changelog entry. Optimized for list_specs. */
|
|
107
|
-
export async function readLastModifiedTimestamp(specDir) {
|
|
108
|
-
const filePath = join(specDir, CHANGELOG_FILENAME);
|
|
109
|
-
try {
|
|
110
|
-
const content = await readFile(filePath, 'utf-8');
|
|
111
|
-
return parseFirstEntryTimestamp(content);
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/** Append a new entry to the CHANGELOG.md for a spec. Creates the file if it doesn't exist. */
|
|
118
|
-
export async function appendChangelogEntry(options) {
|
|
119
|
-
const { specDir, specId, entry } = options;
|
|
120
|
-
const filePath = join(specDir, CHANGELOG_FILENAME);
|
|
121
|
-
try {
|
|
122
|
-
let existingContent = '';
|
|
123
|
-
let hasHeader = false;
|
|
124
|
-
try {
|
|
125
|
-
existingContent = await readFile(filePath, 'utf-8');
|
|
126
|
-
hasHeader = existingContent.includes(CHANGELOG_VERSION_COMMENT);
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
// File doesn't exist yet — will create fresh
|
|
130
|
-
}
|
|
131
|
-
const entryMarkdown = formatEntry(entry, specId);
|
|
132
|
-
let newContent;
|
|
133
|
-
if (!hasHeader) {
|
|
134
|
-
newContent = buildHeader(specId) + entryMarkdown + existingContent;
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
// Insert after the header block (after the # Changelog line)
|
|
138
|
-
const insertAfterPattern = /^# Changelog[^\n]*\n\n/m;
|
|
139
|
-
const match = insertAfterPattern.exec(existingContent);
|
|
140
|
-
if (match) {
|
|
141
|
-
const insertAt = match.index + match[0].length;
|
|
142
|
-
newContent =
|
|
143
|
-
existingContent.slice(0, insertAt) + entryMarkdown + existingContent.slice(insertAt);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
// Fallback: append after existing content
|
|
147
|
-
newContent = existingContent + entryMarkdown;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
await writeFile(filePath, newContent, 'utf-8');
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
console.error(`[spec-changelog] Failed to write CHANGELOG.md for ${specId}:`, error);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/** Format a relative date string (e.g. "hace 2 dias") for a timestamp. */
|
|
159
|
-
export function formatRelativeDate(timestamp) {
|
|
160
|
-
const date = new Date(timestamp);
|
|
161
|
-
const now = new Date();
|
|
162
|
-
const diffMs = now.getTime() - date.getTime();
|
|
163
|
-
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
164
|
-
if (diffDays === 0) {
|
|
165
|
-
return 'hoy';
|
|
166
|
-
}
|
|
167
|
-
if (diffDays === 1) {
|
|
168
|
-
return 'hace 1 dia';
|
|
169
|
-
}
|
|
170
|
-
if (diffDays <= 30) {
|
|
171
|
-
return `hace ${diffDays} dias`;
|
|
172
|
-
}
|
|
173
|
-
// Older than 30 days: return ISO date portion
|
|
174
|
-
return timestamp.slice(0, 10);
|
|
175
|
-
}
|
|
176
|
-
//# sourceMappingURL=core.js.map
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { CriteriaDiff } from '../../types/index.js';
|
|
2
|
-
/** Normalize a criteria text for comparison (trim, collapse whitespace). */
|
|
3
|
-
export declare function normalizeCriteriaText(text: string): string;
|
|
4
|
-
/**
|
|
5
|
-
* Compute a simple similarity score (0–1) between two strings.
|
|
6
|
-
* Uses character bigram overlap.
|
|
7
|
-
*/
|
|
8
|
-
export declare function similarityScore(a: string, b: string): number;
|
|
9
|
-
/**
|
|
10
|
-
* Compute semantic diff between two sets of criteria texts.
|
|
11
|
-
* Returns added, removed, and modified criteria.
|
|
12
|
-
*/
|
|
13
|
-
export declare function computeCriteriaDiff(before: string[], after: string[]): CriteriaDiff;
|
|
14
|
-
/**
|
|
15
|
-
* Returns true if the diff contains any actual changes.
|
|
16
|
-
*/
|
|
17
|
-
export declare function hasDiffChanges(diff: CriteriaDiff): boolean;
|
|
18
|
-
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
// engine/spec-changelog/diff.ts — Semantic diff calculation for spec criteria
|
|
2
|
-
/** Normalize a criteria text for comparison (trim, collapse whitespace). */
|
|
3
|
-
export function normalizeCriteriaText(text) {
|
|
4
|
-
return text
|
|
5
|
-
.replace(/^#+\s+/, '') // remove markdown headers
|
|
6
|
-
.replace(/\*\*/g, '') // remove bold markers
|
|
7
|
-
.replace(/\s+/g, ' ') // collapse whitespace
|
|
8
|
-
.trim()
|
|
9
|
-
.toLowerCase();
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Compute a simple similarity score (0–1) between two strings.
|
|
13
|
-
* Uses character bigram overlap.
|
|
14
|
-
*/
|
|
15
|
-
export function similarityScore(a, b) {
|
|
16
|
-
if (a.length === 0 && b.length === 0) {
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
if (a === b) {
|
|
20
|
-
return 1;
|
|
21
|
-
}
|
|
22
|
-
if (a.length === 0 || b.length === 0) {
|
|
23
|
-
return 0;
|
|
24
|
-
}
|
|
25
|
-
const buildBigrams = (str) => {
|
|
26
|
-
const bigrams = new Set();
|
|
27
|
-
for (let i = 0; i < str.length - 1; i++) {
|
|
28
|
-
bigrams.add(str.slice(i, i + 2));
|
|
29
|
-
}
|
|
30
|
-
return bigrams;
|
|
31
|
-
};
|
|
32
|
-
const bigramsA = buildBigrams(a);
|
|
33
|
-
const bigramsB = buildBigrams(b);
|
|
34
|
-
let intersection = 0;
|
|
35
|
-
for (const bigram of bigramsA) {
|
|
36
|
-
if (bigramsB.has(bigram)) {
|
|
37
|
-
intersection++;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const total = bigramsA.size + bigramsB.size;
|
|
41
|
-
// Single-char strings produce no bigrams — fall back to exact match
|
|
42
|
-
if (total === 0) {
|
|
43
|
-
return a === b ? 1 : 0;
|
|
44
|
-
}
|
|
45
|
-
return (2 * intersection) / total;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Compute semantic diff between two sets of criteria texts.
|
|
49
|
-
* Returns added, removed, and modified criteria.
|
|
50
|
-
*/
|
|
51
|
-
export function computeCriteriaDiff(before, after) {
|
|
52
|
-
const normalizedBefore = before.map(normalizeCriteriaText);
|
|
53
|
-
const normalizedAfter = after.map(normalizeCriteriaText);
|
|
54
|
-
const SIMILARITY_THRESHOLD = 0.6;
|
|
55
|
-
const matchedBeforeIndices = new Set();
|
|
56
|
-
const matchedAfterIndices = new Set();
|
|
57
|
-
const modified = [];
|
|
58
|
-
// Find modifications: pairs with high similarity but not identical
|
|
59
|
-
for (let i = 0; i < normalizedBefore.length; i++) {
|
|
60
|
-
const nb = normalizedBefore[i];
|
|
61
|
-
/* v8 ignore next 2 — noUncheckedIndexedAccess guard; array built with .map() so never undefined */
|
|
62
|
-
if (nb === undefined) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
let bestScore = 0;
|
|
66
|
-
let bestJ = -1;
|
|
67
|
-
for (let j = 0; j < normalizedAfter.length; j++) {
|
|
68
|
-
if (matchedAfterIndices.has(j)) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
const na = normalizedAfter[j];
|
|
72
|
-
/* v8 ignore next 2 — noUncheckedIndexedAccess guard; array built with .map() so never undefined */
|
|
73
|
-
if (na === undefined) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
const score = similarityScore(nb, na);
|
|
77
|
-
if (score > bestScore) {
|
|
78
|
-
bestScore = score;
|
|
79
|
-
bestJ = j;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (bestScore >= SIMILARITY_THRESHOLD && bestJ !== -1) {
|
|
83
|
-
matchedBeforeIndices.add(i);
|
|
84
|
-
matchedAfterIndices.add(bestJ);
|
|
85
|
-
const beforeText = before[i];
|
|
86
|
-
const afterText = after[bestJ];
|
|
87
|
-
// Only report as modified if texts actually differ
|
|
88
|
-
if (beforeText !== undefined && afterText !== undefined && beforeText !== afterText) {
|
|
89
|
-
modified.push({ before: beforeText, after: afterText });
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Removed: unmatched before items
|
|
94
|
-
const removed = [];
|
|
95
|
-
for (let i = 0; i < before.length; i++) {
|
|
96
|
-
if (!matchedBeforeIndices.has(i)) {
|
|
97
|
-
const text = before[i];
|
|
98
|
-
if (text !== undefined) {
|
|
99
|
-
removed.push(text);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// Added: unmatched after items
|
|
104
|
-
const added = [];
|
|
105
|
-
for (let j = 0; j < after.length; j++) {
|
|
106
|
-
if (!matchedAfterIndices.has(j)) {
|
|
107
|
-
const text = after[j];
|
|
108
|
-
if (text !== undefined) {
|
|
109
|
-
added.push(text);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return { added, removed, modified };
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Returns true if the diff contains any actual changes.
|
|
117
|
-
*/
|
|
118
|
-
export function hasDiffChanges(diff) {
|
|
119
|
-
return diff.added.length > 0 || diff.removed.length > 0 || diff.modified.length > 0;
|
|
120
|
-
}
|
|
121
|
-
//# sourceMappingURL=diff.js.map
|