@planu/cli 5.3.67 → 5.3.69
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 +92 -0
- package/dist/.planu-build.json +1 -1
- package/dist/cli/commands/install.d.ts +2 -15
- package/dist/config/release-policy.json +2 -2
- package/dist/core/shared/fs.d.ts +11 -0
- package/dist/core/shared/fs.js +90 -0
- package/dist/core/shared/strings.d.ts +3 -0
- package/dist/core/shared/strings.js +13 -0
- package/dist/engine/actuals/git-analyzer.js +1 -1
- package/dist/engine/actuals/progress-parser.js +1 -3
- package/dist/engine/agent-handoff-store.js +1 -0
- package/dist/engine/agent-squad/dispatcher.js +1 -0
- package/dist/engine/agent-telemetry.js +1 -0
- package/dist/engine/auth/config.js +1 -0
- package/dist/engine/auto-updater/atomic-upgrade.js +1 -0
- package/dist/engine/auto-updater/index.js +1 -0
- package/dist/engine/autopilot/action-registry.js +20 -0
- package/dist/engine/autopilot/audit-logger.js +1 -0
- package/dist/engine/autopilot/bootstrap.js +9 -2
- package/dist/engine/autopilot/complete-loop.js +4 -0
- package/dist/engine/autopilot/crash-shield-rate-limiter.js +1 -0
- package/dist/engine/autopilot/event-bus.js +1 -0
- package/dist/engine/autopilot/state-updater.js +6 -0
- package/dist/engine/browser-validator.js +1 -3
- package/dist/engine/build-tool-detector.js +1 -8
- package/dist/engine/bundle-installer.js +2 -10
- package/dist/engine/cascade-hooks/core/append-releases.js +1 -0
- package/dist/engine/cascade-hooks/core/write-session-json.js +2 -2
- package/dist/engine/cascade-hooks/hooks/dispatch-hook-event.hook.d.ts +3 -1
- package/dist/engine/cascade-hooks/hooks/dispatch-hook-event.hook.js +12 -3
- package/dist/engine/cascade-hooks/hooks/estimate-calibration.hook.js +1 -0
- package/dist/engine/cascade-hooks/hooks/housekeeping-on-done.hook.js +2 -0
- package/dist/engine/cascade-hooks/hooks/implementing-kickoff.hook.js +5 -1
- package/dist/engine/cascade-hooks/hooks/lesson-drift.hook.js +1 -0
- package/dist/engine/cascade-hooks/hooks/orchestration-plan.hook.js +1 -0
- package/dist/engine/cascade-hooks/hooks/session-context.hook.js +4 -2
- package/dist/engine/cascade-hooks/hooks/slack-notify.hook.js +1 -0
- package/dist/engine/cascade-hooks/hooks/status-json.hook.js +2 -0
- package/dist/engine/cascade-hooks/hooks/velocity-profile.hook.js +2 -0
- package/dist/engine/cascade-hooks/runner.js +2 -0
- package/dist/engine/cascade-hooks/state-drift-detector.js +2 -0
- package/dist/engine/checkpoint/checkpoint-manager.js +2 -0
- package/dist/engine/checkpoint/policy-engine.js +1 -0
- package/dist/engine/ci-generator/stack-detector.js +2 -10
- package/dist/engine/clarification-gate/token-store.js +1 -0
- package/dist/engine/claude-config-auditor/claudemd-auditor.js +2 -10
- package/dist/engine/claude-config-auditor/settings-auditor.js +2 -10
- package/dist/engine/client-detection.js +2 -10
- package/dist/engine/compliance/auto-remediator.js +1 -0
- package/dist/engine/compliance/evidence-builder.d.ts +2 -2
- package/dist/engine/compliance/framework-catalog.d.ts +6 -6
- package/dist/engine/compliance/gap-analyzer.d.ts +2 -2
- package/dist/engine/config-health/build-tool-checker.js +1 -9
- package/dist/engine/config-health/ci-commands-collector.d.ts +2 -1
- package/dist/engine/config-health/ci-commands-collector.js +2 -9
- package/dist/engine/config-health/go-checker.js +1 -9
- package/dist/engine/config-health/mcp-config-checker.js +2 -10
- package/dist/engine/config-health/python-checker.js +1 -9
- package/dist/engine/config-health/rust-checker.js +1 -9
- package/dist/engine/config-health/ts-checker-scripts.js +1 -9
- package/dist/engine/config-health/ts-checker.js +1 -9
- package/dist/engine/context-artifacts/store.js +1 -0
- package/dist/engine/context-md-generator.js +1 -0
- package/dist/engine/context-orchestrator/index.js +2 -0
- package/dist/engine/convention-scanner/convention-parser.js +2 -9
- package/dist/engine/cost-guardrails.js +1 -0
- package/dist/engine/cost-tracking/ledger.js +1 -0
- package/dist/engine/criterion-identity.js +1 -1
- package/dist/engine/dashboard/data-loader.js +1 -0
- package/dist/engine/dashboard/drift-score.js +2 -0
- package/dist/engine/dashboard/spec-updater.d.ts +3 -1
- package/dist/engine/dashboard/spec-updater.js +9 -2
- package/dist/engine/dashboard/templates-layout.d.ts +2 -2
- package/dist/engine/dashboard/templates-layout.js +2 -9
- package/dist/engine/data-projects-gc/gc-runner.js +2 -4
- package/dist/engine/deleter/audit-logger.js +1 -0
- package/dist/engine/deleter/core.js +6 -0
- package/dist/engine/deleter/trash-manager.js +1 -0
- package/dist/engine/desktop-detector.js +1 -9
- package/dist/engine/detection-utils.d.ts +2 -1
- package/dist/engine/detection-utils.js +3 -10
- package/dist/engine/detectors/advanced-framework-detector/helpers.d.ts +3 -2
- package/dist/engine/detectors/advanced-framework-detector/helpers.js +3 -17
- package/dist/engine/detectors/cicd-detector.js +2 -10
- package/dist/engine/detectors/css-framework-detector.js +2 -10
- package/dist/engine/detectors/deployment-detector.js +3 -12
- package/dist/engine/detectors/frontend-perf-detector.js +2 -10
- package/dist/engine/detectors/gitops-detector.js +3 -11
- package/dist/engine/detectors/idp-detector.js +1 -3
- package/dist/engine/detectors/k3s-detector.js +3 -11
- package/dist/engine/detectors/llm-detector/file-readers.d.ts +2 -1
- package/dist/engine/detectors/llm-detector/file-readers.js +2 -9
- package/dist/engine/detectors/mfe-detector.js +5 -13
- package/dist/engine/detectors/monitoring-detector.js +2 -11
- package/dist/engine/detectors/monorepo-detector.d.ts +1 -0
- package/dist/engine/detectors/monorepo-detector.js +1 -10
- package/dist/engine/detectors/nomad-detector.js +3 -11
- package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -1
- package/dist/engine/detectors/otel-ecosystem-detectors.js +2 -10
- package/dist/engine/doc-generator/executive-summary/html-template.js +1 -7
- package/dist/engine/doc-generator/executive-summary/section-builders.js +1 -7
- package/dist/engine/doc-generator/per-spec-report/mermaid-renderer.js +1 -7
- package/dist/engine/doc-generator/per-spec-report/spec-section-builders.js +1 -7
- package/dist/engine/doc-generator/per-spec-report/technical-report.js +1 -7
- package/dist/engine/doc-generator/portal/analytics-page.js +1 -7
- package/dist/engine/doc-generator/portal/architecture-page.js +1 -7
- package/dist/engine/doc-generator/portal/changelog-page.js +1 -7
- package/dist/engine/doc-generator/portal/decision-page.js +1 -7
- package/dist/engine/doc-generator/portal/decision-timeline-builder.js +1 -7
- package/dist/engine/doc-generator/portal/kanban-view-builder.js +1 -7
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.js +1 -7
- package/dist/engine/doc-generator/portal/portal-landing-cards.js +1 -7
- package/dist/engine/doc-generator/portal/portal-navbar.js +1 -7
- package/dist/engine/doc-generator/portal/portal-page-detector.d.ts +3 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.js +1 -10
- package/dist/engine/doc-generator/portal/portal-regenerator.js +2 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.js +1 -7
- package/dist/engine/doc-generator/portal/risk-page.js +1 -7
- package/dist/engine/doc-generator/portal/roadmap-page.js +1 -7
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js +1 -7
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js +1 -7
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js +2 -8
- package/dist/engine/doc-generator/proposal/proposal-section-builders.js +1 -7
- package/dist/engine/docs-site-generator/html-templates.js +1 -7
- package/dist/engine/docs-site-generator/markdown-renderer.js +1 -7
- package/dist/engine/drift/violation-resolver.js +2 -0
- package/dist/engine/dynamic-knowledge/knowledge-cache.js +1 -0
- package/dist/engine/ecosystem-absorber/knowledge-cache.js +1 -0
- package/dist/engine/edge-db-detector.js +1 -10
- package/dist/engine/escalator/retry-counter.js +1 -0
- package/dist/engine/evidence-gates/artifact-reader.js +1 -0
- package/dist/engine/evidence-gates/evidence-autofill.js +1 -0
- package/dist/engine/evidence-gates/evidence-skeletons.js +1 -0
- package/dist/engine/evidence-gates/reconciliation-freshness.js +1 -0
- package/dist/engine/execution/durable-job-heartbeat-runtime.js +1 -0
- package/dist/engine/execution/job-runtime.js +2 -0
- package/dist/engine/execution/validate-job-executor.d.ts +1 -1
- package/dist/engine/execution/validate-job-executor.js +3 -0
- package/dist/engine/execution/validate-job-payload.js +1 -0
- package/dist/engine/execution/validate-worker-thread.js +1 -0
- package/dist/engine/facilitate/context-loader.js +1 -0
- package/dist/engine/figma/change-detector.d.ts +1 -8
- package/dist/engine/figma/code-connect-fetcher.d.ts +1 -7
- package/dist/engine/figma/design-enricher.d.ts +1 -17
- package/dist/engine/figma/design-enricher.js +0 -1
- package/dist/engine/figma/e2e-generator.d.ts +1 -23
- package/dist/engine/figma/flow-analyzer.d.ts +1 -11
- package/dist/engine/figma/frame-extractor.d.ts +1 -11
- package/dist/engine/figma/frame-extractor.js +3 -0
- package/dist/engine/figma/multi-file-manager.d.ts +1 -6
- package/dist/engine/figma/spec-generator.js +2 -0
- package/dist/engine/figma/thumbnail-fetcher.d.ts +1 -1
- package/dist/engine/figma/token-extractor.d.ts +1 -6
- package/dist/engine/figma/token-extractor.js +0 -1
- package/dist/engine/figma/version-tracker.d.ts +1 -7
- package/dist/engine/figma/version-tracker.js +0 -1
- package/dist/engine/figma/visual-qa.d.ts +5 -19
- package/dist/engine/figma/visual-qa.js +1 -2
- package/dist/engine/figma/webhook-manager.d.ts +1 -7
- package/dist/engine/frontmatter-sha/reseal.js +1 -0
- package/dist/engine/frontmatter-sha/verify-terminal.js +1 -0
- package/dist/engine/git-hook-injector.js +2 -10
- package/dist/engine/github/quality-dimensions.js +1 -3
- package/dist/engine/global-rules-manager.js +2 -3
- package/dist/engine/handoff-artifacts/implementation-review-reader.js +1 -0
- package/dist/engine/handoff-artifacts/io.js +2 -0
- package/dist/engine/handoff-packager.js +2 -1
- package/dist/engine/health/auto-fixer.js +1 -0
- package/dist/engine/hooks/context-injector.js +1 -0
- package/dist/engine/hooks-reconciler.js +1 -8
- package/dist/engine/impact-detector/index.js +2 -9
- package/dist/engine/implementation-contract/common.js +1 -3
- package/dist/engine/implementation-contract/evaluator.js +1 -3
- package/dist/engine/keyword-matcher/boundary.d.ts +2 -7
- package/dist/engine/keyword-matcher/boundary.js +2 -14
- package/dist/engine/lifecycle-reconciliation-io.js +1 -0
- package/dist/engine/lifecycle-reconciliation.js +3 -0
- package/dist/engine/local-first/detector.js +1 -9
- package/dist/engine/marketplace-fetcher/cache.js +2 -0
- package/dist/engine/marketplace-fetcher/index.js +1 -0
- package/dist/engine/mcp-config/mcp-config-writer.js +2 -10
- package/dist/engine/migrations/remove-commercial-state.js +2 -0
- package/dist/engine/mobile-detector-shared.d.ts +1 -1
- package/dist/engine/mobile-detector-shared.js +2 -9
- package/dist/engine/multi-channel-notifier.js +1 -0
- package/dist/engine/multi-teammate-review/disagreement-counter.js +1 -0
- package/dist/engine/multi-teammate-review/panel-orchestrator.js +1 -0
- package/dist/engine/onboarding-engine.js +1 -9
- package/dist/engine/permissions-merger/stack-detectors.js +2 -10
- package/dist/engine/pii-detector/core.js +1 -3
- package/dist/engine/platform-engineering/dx-analyzer.js +1 -10
- package/dist/engine/platform-engineering/idp-detector.js +2 -10
- package/dist/engine/project-dna/ai-tool-detector.js +2 -10
- package/dist/engine/project-dna/stack-detector.js +2 -10
- package/dist/engine/project-graph/builder.js +11 -2
- package/dist/engine/project-graph/cache.d.ts +5 -2
- package/dist/engine/project-graph/cache.js +174 -34
- package/dist/engine/project-graph/extractors/decision-store-extractor.js +1 -0
- package/dist/engine/project-graph/freshness-projection.js +3 -0
- package/dist/engine/project-graph/query.js +14 -11
- package/dist/engine/project-health-checker.js +2 -6
- package/dist/engine/provider-adapters/shared/spec-loader.js +1 -0
- package/dist/engine/quality-gates/gate-evaluator.js +1 -3
- package/dist/engine/react-detector.js +6 -14
- package/dist/engine/reconcile/apply-changes.js +1 -3
- package/dist/engine/registry/core.js +1 -0
- package/dist/engine/registry/loader.js +2 -0
- package/dist/engine/release/postmortem-generator.js +1 -0
- package/dist/engine/release/rollback-runner.d.ts +2 -2
- package/dist/engine/release/stuck-spec-detector.js +7 -0
- package/dist/engine/release-pipeline/release-spec-closer.js +3 -0
- package/dist/engine/rules-reconciler.d.ts +1 -1
- package/dist/engine/rules-reconciler.js +2 -9
- package/dist/engine/safety/atomic-writer.js +1 -0
- package/dist/engine/safety/cross-process-lock.js +2 -0
- package/dist/engine/safety/file-mutex.js +1 -0
- package/dist/engine/safety/lock-lease-store.js +1 -0
- package/dist/engine/safety/lock-scavenger.js +2 -0
- package/dist/engine/saga/transition-cascade.js +3 -0
- package/dist/engine/scan-project/index.js +1 -0
- package/dist/engine/scan-project/module-discoverer.js +1 -9
- package/dist/engine/schema-parity-auditor/handler-checker.js +1 -3
- package/dist/engine/schema-parity-auditor/index.js +1 -3
- package/dist/engine/schema-parity-auditor/type-checker.js +1 -3
- package/dist/engine/self-healing/strategies/coverage-fix.js +2 -10
- package/dist/engine/session-context-generator.d.ts +8 -0
- package/dist/engine/session-context-generator.js +33 -23
- package/dist/engine/session-state/session-artifact-refresher.d.ts +7 -0
- package/dist/engine/session-state/session-artifact-refresher.js +140 -0
- package/dist/engine/session-state/writer.d.ts +3 -0
- package/dist/engine/session-state/writer.js +35 -17
- package/dist/engine/shared-agent-memory.js +1 -0
- package/dist/engine/skill-adapter/index.js +3 -0
- package/dist/engine/skill-bootstrap/registry-fetcher.js +1 -0
- package/dist/engine/skill-bootstrap/skill-writer.js +2 -9
- package/dist/engine/skill-bootstrap/stack-matcher.js +1 -9
- package/dist/engine/skill-discovery/multi-agent-writer.d.ts +1 -0
- package/dist/engine/skill-discovery/multi-agent-writer.js +1 -9
- package/dist/engine/skill-generator/workflow-skill-generator.js +1 -0
- package/dist/engine/skill-registry/ttl-refresh.js +2 -0
- package/dist/engine/spec-audit/index.js +2 -0
- package/dist/engine/spec-audit/report-writer.js +1 -0
- package/dist/engine/spec-coverage/core.js +1 -0
- package/dist/engine/spec-decomposer/analyzer.js +1 -11
- package/dist/engine/spec-dependency-graph/dot-exporter.d.ts +1 -1
- package/dist/engine/spec-dependency-graph/graph-builder.d.ts +1 -20
- package/dist/engine/spec-dependency-graph/superseded-set.d.ts +1 -1
- package/dist/engine/spec-diff-engine.js +1 -7
- package/dist/engine/spec-format/read-technical-section.js +1 -3
- package/dist/engine/spec-format/replace-section.js +1 -3
- package/dist/engine/spec-format/spec-id.d.ts +9 -1
- package/dist/engine/spec-format/spec-id.js +24 -3
- package/dist/engine/spec-format/unified-spec-builder.js +1 -3
- package/dist/engine/spec-migrator/canonical-deduplicator.js +2 -0
- package/dist/engine/spec-observability/tracker.js +1 -0
- package/dist/engine/spec-registry/adapter.js +2 -10
- package/dist/engine/spec-registry/validator.d.ts +1 -0
- package/dist/engine/spec-registry/validator.js +1 -9
- package/dist/engine/spec-state-machine/transition-spec.js +1 -0
- package/dist/engine/spec-templates/custom-loader.js +1 -0
- package/dist/engine/stack-auditor/build-tool-auditor.js +1 -9
- package/dist/engine/staleness/stale-implementing.js +5 -14
- package/dist/engine/status-reconciler/index.js +4 -1
- package/dist/engine/structural-memory/helpers.js +1 -0
- package/dist/engine/supply-chain/slsa-checker.js +1 -9
- package/dist/engine/tdd-enforcer/stub-artifact-path.js +1 -0
- package/dist/engine/telemetry/health-checker.js +1 -0
- package/dist/engine/telemetry/telemetry-store.js +1 -0
- package/dist/engine/token-optimizer/response-cache.js +1 -3
- package/dist/engine/tool-groups/group-manager.js +2 -0
- package/dist/engine/update-notifier.js +1 -0
- package/dist/engine/validation/approved-spec-portability.js +1 -0
- package/dist/engine/validation/durable-validation.js +1 -0
- package/dist/engine/validation/validation-freshness.js +2 -0
- package/dist/engine/validation/validation-receipt.js +1 -0
- package/dist/engine/validation/validation-submission.d.ts +1 -1
- package/dist/engine/validation-evidence-ledger.js +1 -0
- package/dist/engine/validator/deep-code-checker.js +1 -3
- package/dist/engine/validator/executable-evidence.d.ts +1 -14
- package/dist/engine/validator/scope-resolver.d.ts +2 -2
- package/dist/engine/validator/spec-compliance-runner.d.ts +1 -31
- package/dist/engine/validator/validation-report-writer.js +1 -1
- package/dist/engine/validator.d.ts +1 -1
- package/dist/engine/validator.js +1 -0
- package/dist/engine/velocity/measure-velocity.js +2 -0
- package/dist/engine/version-resolver.js +1 -0
- package/dist/engine/workers/handlers/auto-drift.js +3 -0
- package/dist/engine/workspace-manager.js +4 -0
- package/dist/hosts/gemini/config-scaffold.js +2 -10
- package/dist/storage/approval-operation-lock.js +1 -0
- package/dist/storage/auto-promoter-config-store.js +1 -0
- package/dist/storage/autopilot-log-store.js +1 -0
- package/dist/storage/base-store.js +1 -0
- package/dist/storage/checkpoint-store.js +1 -0
- package/dist/storage/feedback-remote.js +1 -0
- package/dist/storage/gaps-log.js +1 -0
- package/dist/storage/global-projects-store.d.ts +17 -0
- package/dist/storage/global-projects-store.js +47 -0
- package/dist/storage/global-store.js +1 -0
- package/dist/storage/knowledge-store/sessions.js +2 -0
- package/dist/storage/migrations/canonical-storage.js +42 -18
- package/dist/storage/project-drift-store.js +1 -0
- package/dist/storage/project-identity.d.ts +27 -0
- package/dist/storage/project-identity.js +132 -2
- package/dist/storage/project-resolver.js +1 -17
- package/dist/storage/runtime-db.d.ts +2 -20
- package/dist/storage/runtime-db.js +2 -9
- package/dist/storage/semantic-index-store.js +1 -0
- package/dist/storage/sentry-store.js +1 -0
- package/dist/storage/session-state-store.js +1 -0
- package/dist/storage/spec-store.d.ts +31 -3
- package/dist/storage/spec-store.js +146 -5
- package/dist/storage/status-store/atomic-status-write.js +1 -0
- package/dist/storage/status-store/file-lock.js +1 -0
- package/dist/storage/status-store/self-healing.js +1 -0
- package/dist/storage/storage-bundle.d.ts +12 -2
- package/dist/storage/supabase-store.js +1 -0
- package/dist/storage/technology-selection-store.js +1 -0
- package/dist/storage/trash-store.d.ts +2 -4
- package/dist/storage/trash-store.js +2 -15
- package/dist/storage/vector-store/json-fallback.js +1 -0
- package/dist/storage/vector-store/migrator.js +1 -0
- package/dist/storage/vector-store/sqlite-adapter.js +1 -0
- package/dist/tools/audit-claude-config.js +1 -10
- package/dist/tools/challenge-spec-helpers.d.ts +1 -1
- package/dist/tools/challenge-spec-helpers.js +7 -2
- package/dist/tools/challenge-spec.js +11 -6
- package/dist/tools/check-readiness.js +121 -24
- package/dist/tools/clarify-requirements/multiple-choice.d.ts +3 -3
- package/dist/tools/configure-oauth-handler.js +1 -0
- package/dist/tools/create-spec-helpers.d.ts +1 -3
- package/dist/tools/create-spec-helpers.js +1 -8
- package/dist/tools/create-spec.js +1 -13
- package/dist/tools/dashboard.js +5 -0
- package/dist/tools/generate-execution-plan.js +10 -6
- package/dist/tools/github-pr-handler.js +1 -0
- package/dist/tools/github-release-handler.d.ts +1 -0
- package/dist/tools/github-release-handler.js +4 -3
- package/dist/tools/graph-specs.d.ts +1 -1
- package/dist/tools/heal-spec-docs.js +1 -3
- package/dist/tools/init-project/git-setup.d.ts +2 -2
- package/dist/tools/init-project/host-assets-writer.js +2 -10
- package/dist/tools/init-project/lifecycle-helpers.d.ts +2 -2
- package/dist/tools/init-project/lint-scaffolder.js +2 -10
- package/dist/tools/init-project/stack-detector.d.ts +2 -2
- package/dist/tools/reconcile-interactive-question-hooks.d.ts +2 -2
- package/dist/tools/register-sdd-tools.js +1 -0
- package/dist/tools/safe-handler.js +1 -0
- package/dist/tools/schemas/spec-id.d.ts +1 -6
- package/dist/tools/schemas/spec-id.js +1 -16
- package/dist/tools/tool-entry.d.ts +2 -2
- package/dist/tools/tool-entry.js +1 -1
- package/dist/tools/tool-registry/core-tools.d.ts +2 -2
- package/dist/tools/tool-registry/deprecated-stubs.d.ts +3 -3
- package/dist/tools/tool-registry/deprecated-stubs.js +1 -1
- package/dist/tools/triage-request.d.ts +2 -2
- package/dist/tools/update-status/approval-gates.d.ts +2 -2
- package/dist/tools/update-status/approval-gates.js +1 -0
- package/dist/tools/update-status/dod-gates.d.ts +1 -1
- package/dist/tools/update-status/done-receipt-verifier.d.ts +1 -1
- package/dist/tools/update-status/evidence-gate.js +5 -5
- package/dist/tools/update-status/file-sync.js +11 -39
- package/dist/tools/update-status/index.js +1 -1
- package/dist/tools/update-status/side-effects.js +5 -0
- package/dist/tools/update-status/transition-guard.d.ts +1 -1
- package/dist/tools/update-status/transition-guard.js +40 -8
- package/dist/tools/update-status-actions.js +28 -40
- package/dist/tools/validate-graph-coverage.js +14 -2
- package/dist/tools/validate.js +2 -0
- package/dist/transports/middleware/types.d.ts +3 -3
- package/dist/types/atomic-upgrade.d.ts +1 -1
- package/dist/types/cascade-hooks.d.ts +3 -0
- package/dist/types/cross-repo-search.d.ts +2 -0
- package/dist/types/dashboard.d.ts +4 -1
- package/dist/types/durable-job.d.ts +20 -0
- package/dist/types/durable-job.js +9 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/installation.d.ts +16 -0
- package/dist/types/installation.js +2 -0
- package/dist/types/project-knowledge-graph.d.ts +11 -0
- package/dist/types/session-checkpoint.d.ts +16 -0
- package/dist/types/spec-dependency-graph.d.ts +21 -0
- package/dist/types/spec-dependency-graph.js +2 -0
- package/dist/types/validation-evidence.d.ts +45 -0
- package/package.json +2 -2
- package/planu-plugin.json +1 -1
- package/dist/types/storage-bundle.d.ts +0 -13
- package/dist/types/storage-bundle.js +0 -2
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// to the prior status.
|
|
6
6
|
import { runSaga } from './cascade-saga.js';
|
|
7
7
|
import { transitionSpec } from '../spec-state-machine/transition-spec.js';
|
|
8
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
8
9
|
import { appendTransitionEvent } from '../../storage/transition-log.js';
|
|
9
10
|
// ---------------------------------------------------------------------------
|
|
10
11
|
// Step definitions
|
|
@@ -30,6 +31,7 @@ function buildCascadeSteps(_ctx) {
|
|
|
30
31
|
if (!c.projectPath) {
|
|
31
32
|
return null; // No project path — Slack config unavailable
|
|
32
33
|
}
|
|
34
|
+
// eslint-disable-next-line no-restricted-syntax -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
33
35
|
const { getSlackConfig } = await import('../../storage/slack-store.js');
|
|
34
36
|
const slackConfig = await getSlackConfig(c.projectPath).catch(() => null);
|
|
35
37
|
if (!slackConfig?.webhookUrl) {
|
|
@@ -100,6 +102,7 @@ function buildCascadeSteps(_ctx) {
|
|
|
100
102
|
// Errors are NOT caught here — the saga catches them and records a warning
|
|
101
103
|
// because critical:false. The try/catch is intentionally absent.
|
|
102
104
|
run: async (c) => {
|
|
105
|
+
// eslint-disable-next-line no-restricted-syntax -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
103
106
|
const { dispatchFeedbackEvent } = await import('../../tools/learn.js');
|
|
104
107
|
await dispatchFeedbackEvent(c.projectId, {
|
|
105
108
|
type: 'validate',
|
|
@@ -9,6 +9,7 @@ import { calculateProjectHealth } from './health-scorer.js';
|
|
|
9
9
|
import { generateProjectOverview } from './overview-generator.js';
|
|
10
10
|
import { generateTeamPlan } from './team-planner.js';
|
|
11
11
|
import { runDeepAnalysis } from '../reverse-engineer/index.js';
|
|
12
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
12
13
|
import { createSpec, listSpecs } from '../../storage/spec-store.js';
|
|
13
14
|
// Re-export submodules for barrel access
|
|
14
15
|
export { discoverModules } from './module-discoverer.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { technologyValue } from '../technology-registry.js';
|
|
2
|
+
import { fileExists } from '../../core/shared/fs.js';
|
|
2
3
|
// engine/scan-project/module-discoverer.ts — Detects module boundaries in a project (SPEC-134)
|
|
3
4
|
// Language-agnostic: supports monorepo, package-based, framework-based, and directory-based detection.
|
|
4
5
|
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
@@ -108,15 +109,6 @@ async function getSubdirs(dirPath) {
|
|
|
108
109
|
return subdirs;
|
|
109
110
|
}
|
|
110
111
|
/** Checks if a file exists at the given path */
|
|
111
|
-
async function fileExists(filePath) {
|
|
112
|
-
try {
|
|
113
|
-
await stat(filePath);
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
112
|
/** Reads a file safely, returns empty string on error */
|
|
121
113
|
async function safeRead(filePath) {
|
|
122
114
|
try {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// engine/schema-parity-auditor/handler-checker.ts — Checks handler files for safe access patterns
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { glob } from 'glob';
|
|
4
|
+
import { escapeRegex } from '../../core/shared/strings.js';
|
|
4
5
|
/**
|
|
5
6
|
* Finds the handler file for a given tool registration file.
|
|
6
7
|
* Convention: register-foo-tools.ts → foo-handler.ts (or similar).
|
|
@@ -50,7 +51,4 @@ export function checkHandlerContent(fieldName, handlerFile, content) {
|
|
|
50
51
|
hasIfCheck,
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
|
-
function escapeRegex(str) {
|
|
54
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
55
|
-
}
|
|
56
54
|
//# sourceMappingURL=handler-checker.js.map
|
|
@@ -4,6 +4,7 @@ import { glob } from 'glob';
|
|
|
4
4
|
import { scanZodOptionalFields } from './zod-scanner.js';
|
|
5
5
|
import { checkTypeOptional } from './type-checker.js';
|
|
6
6
|
import { findHandlerFile, checkHandlerAccess } from './handler-checker.js';
|
|
7
|
+
import { escapeRegex } from '../../core/shared/strings.js';
|
|
7
8
|
/**
|
|
8
9
|
* Default type values to use when auto-fixing handlers.
|
|
9
10
|
* Maps Zod base type → default value string.
|
|
@@ -112,7 +113,4 @@ async function fixTypeFile(fieldName, typeFile, dryRun) {
|
|
|
112
113
|
preview: dryRun ? `- ${fieldName}: → ${fieldName}?:` : undefined,
|
|
113
114
|
};
|
|
114
115
|
}
|
|
115
|
-
function escapeRegex(str) {
|
|
116
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
117
|
-
}
|
|
118
116
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// engine/schema-parity-auditor/type-checker.ts — Checks TypeScript types for optional mark
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { glob } from 'glob';
|
|
4
|
+
import { escapeRegex } from '../../core/shared/strings.js';
|
|
4
5
|
/**
|
|
5
6
|
* Checks whether a given fieldName has an optional mark ("?") in any TypeScript type
|
|
6
7
|
* file under projectPath/src/types/.
|
|
@@ -40,7 +41,4 @@ export function checkFieldInContent(fieldName, filePath, content) {
|
|
|
40
41
|
}
|
|
41
42
|
return { found: false, hasOptionalMark: false, typeFile: '' };
|
|
42
43
|
}
|
|
43
|
-
function escapeRegex(str) {
|
|
44
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
45
|
-
}
|
|
46
44
|
//# sourceMappingURL=type-checker.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// engine/self-healing/strategies/coverage-fix.ts — SPEC-474: Coverage fix strategy
|
|
2
|
-
import { readFile, writeFile, mkdir
|
|
2
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
3
3
|
import { join, dirname, basename, relative } from 'node:path';
|
|
4
|
+
import { fileExists } from '../../../core/shared/fs.js';
|
|
4
5
|
/**
|
|
5
6
|
* Reads coverage/coverage-final.json and returns files with 0% statement coverage.
|
|
6
7
|
*/
|
|
@@ -74,15 +75,6 @@ describe('${moduleName}', () => {
|
|
|
74
75
|
/**
|
|
75
76
|
* Checks whether a file already exists on the filesystem.
|
|
76
77
|
*/
|
|
77
|
-
async function fileExists(path) {
|
|
78
|
-
try {
|
|
79
|
-
await access(path);
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
78
|
/**
|
|
87
79
|
* Scaffolds a single test file for an uncovered source file.
|
|
88
80
|
* Returns the relative test path on success, or null if skipped/failed.
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import type { Spec } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* SPEC-1320: Renders session-context.md content from a supplied active-spec snapshot.
|
|
4
|
+
* Pure aside from reading project version and recent lessons — no file write.
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildSessionContextContent(projectPath: string, allSpecs: Spec[], activeSpecs: Spec[]): Promise<string>;
|
|
7
|
+
/** Absolute path to a project's generated session-context.md. */
|
|
8
|
+
export declare function sessionContextPath(projectPath: string): string;
|
|
1
9
|
/**
|
|
2
10
|
* Auto-generates `planu/session-context.md` for a project.
|
|
3
11
|
* Entirely best-effort: never throws, never blocks the caller.
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Writes planu/session-context.md so any LLM (Cursor, Windsurf, Aider…) can pick up project state.
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
5
6
|
import { specStore, lessonsStore } from '../storage/index.js';
|
|
6
7
|
import { stableWriteGeneratedFile, stripSessionMarkdownVolatileFields, } from './generated-artifact-writer.js';
|
|
8
|
+
import { deriveActiveSpecSnapshot } from './session-state/writer.js';
|
|
7
9
|
/** Reads the `version` field from the project's package.json, or returns 'unknown'. */
|
|
8
10
|
async function readProjectVersion(projectPath) {
|
|
9
11
|
try {
|
|
@@ -46,10 +48,7 @@ function getPendingApproved(specs) {
|
|
|
46
48
|
}
|
|
47
49
|
/** Returns active in-progress specs ordered by most recently updated first. */
|
|
48
50
|
function getActiveSpecs(specs) {
|
|
49
|
-
return specs
|
|
50
|
-
.filter((s) => s.status === 'implementing' || s.status === 'review')
|
|
51
|
-
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
|
52
|
-
.slice(0, 5);
|
|
51
|
+
return deriveActiveSpecSnapshot(specs);
|
|
53
52
|
}
|
|
54
53
|
/** Fetches the last 3 lessons for the project via lessonsStore (best-effort). */
|
|
55
54
|
async function fetchRecentLessons(projectPath) {
|
|
@@ -126,32 +125,43 @@ function buildMarkdown(params) {
|
|
|
126
125
|
'*Generated by [Planu](https://planu.dev) — The complete SDD stack for AI agents*',
|
|
127
126
|
].join('\n');
|
|
128
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* SPEC-1320: Renders session-context.md content from a supplied active-spec snapshot.
|
|
130
|
+
* Pure aside from reading project version and recent lessons — no file write.
|
|
131
|
+
*/
|
|
132
|
+
export async function buildSessionContextContent(projectPath, allSpecs, activeSpecs) {
|
|
133
|
+
const [version, lessons] = await Promise.all([
|
|
134
|
+
readProjectVersion(projectPath),
|
|
135
|
+
fetchRecentLessons(projectPath),
|
|
136
|
+
]);
|
|
137
|
+
const done = getRecentlyDone(allSpecs);
|
|
138
|
+
const approved = getPendingApproved(allSpecs);
|
|
139
|
+
return buildMarkdown({
|
|
140
|
+
version,
|
|
141
|
+
activeCount: activeSpecs.length,
|
|
142
|
+
doneCount: allSpecs.filter((s) => s.status === 'done').length,
|
|
143
|
+
approvedCount: approved.length,
|
|
144
|
+
activeRows: buildActiveRows(activeSpecs),
|
|
145
|
+
doneRows: buildDoneRows(done),
|
|
146
|
+
approvedRows: buildApprovedRows(approved),
|
|
147
|
+
lessonsContent: buildLessonsSection(lessons),
|
|
148
|
+
generatedAt: new Date().toISOString(),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/** Absolute path to a project's generated session-context.md. */
|
|
152
|
+
export function sessionContextPath(projectPath) {
|
|
153
|
+
return join(projectPath, 'planu', 'session-context.md');
|
|
154
|
+
}
|
|
129
155
|
/**
|
|
130
156
|
* Auto-generates `planu/session-context.md` for a project.
|
|
131
157
|
* Entirely best-effort: never throws, never blocks the caller.
|
|
132
158
|
*/
|
|
133
159
|
export async function generateSessionContext(projectPath, projectId) {
|
|
134
160
|
try {
|
|
135
|
-
const
|
|
136
|
-
readProjectVersion(projectPath),
|
|
137
|
-
specStore.listSpecs(projectId),
|
|
138
|
-
fetchRecentLessons(projectPath),
|
|
139
|
-
]);
|
|
161
|
+
const allSpecs = await specStore.listSpecs(projectId);
|
|
140
162
|
const active = getActiveSpecs(allSpecs);
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const content = buildMarkdown({
|
|
144
|
-
version,
|
|
145
|
-
activeCount: active.length,
|
|
146
|
-
doneCount: allSpecs.filter((s) => s.status === 'done').length,
|
|
147
|
-
approvedCount: approved.length,
|
|
148
|
-
activeRows: buildActiveRows(active),
|
|
149
|
-
doneRows: buildDoneRows(done),
|
|
150
|
-
approvedRows: buildApprovedRows(approved),
|
|
151
|
-
lessonsContent: buildLessonsSection(lessons),
|
|
152
|
-
generatedAt: new Date().toISOString(),
|
|
153
|
-
});
|
|
154
|
-
const contextPath = join(projectPath, 'planu', 'session-context.md');
|
|
163
|
+
const content = await buildSessionContextContent(projectPath, allSpecs, active);
|
|
164
|
+
const contextPath = sessionContextPath(projectPath);
|
|
155
165
|
const writeResult = await stableWriteGeneratedFile(contextPath, content, {
|
|
156
166
|
equivalence: stripSessionMarkdownVolatileFields,
|
|
157
167
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RefreshSessionArtifactsResult, SessionArtifactRefreshFailureCode } from '../../types/index.js';
|
|
2
|
+
export declare class SessionArtifactRefreshError extends Error {
|
|
3
|
+
readonly code: SessionArtifactRefreshFailureCode;
|
|
4
|
+
constructor(code: SessionArtifactRefreshFailureCode);
|
|
5
|
+
}
|
|
6
|
+
export declare function refreshSessionArtifacts(projectPath: string, projectId: string): Promise<RefreshSessionArtifactsResult>;
|
|
7
|
+
//# sourceMappingURL=session-artifact-refresher.d.ts.map
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { readFile, writeFile, rename, unlink, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
5
|
+
import { specStore } from '../../storage/index.js';
|
|
6
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
7
|
+
import { withFileLock } from '../../storage/file-mutex.js';
|
|
8
|
+
import { stableJsonStringify, stripRootUpdatedAt, stripSessionMarkdownVolatileFields, withFinalNewline, } from '../generated-artifact-writer.js';
|
|
9
|
+
import { buildSessionContextContent, sessionContextPath } from '../session-context-generator.js';
|
|
10
|
+
import { buildSessionIndexPatch, deriveActiveSpecSnapshot, rootFile } from './writer.js';
|
|
11
|
+
export class SessionArtifactRefreshError extends Error {
|
|
12
|
+
code;
|
|
13
|
+
constructor(code) {
|
|
14
|
+
super(`session-artifact-refresh-failed:${code}`);
|
|
15
|
+
this.name = 'SessionArtifactRefreshError';
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.stack = undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function isEnoent(err) {
|
|
21
|
+
return err instanceof Error && err.code === 'ENOENT';
|
|
22
|
+
}
|
|
23
|
+
async function prepareArtifact(finalPath, content, equivalence) {
|
|
24
|
+
const next = withFinalNewline(content);
|
|
25
|
+
let previous;
|
|
26
|
+
try {
|
|
27
|
+
previous = await readFile(finalPath, 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (!isEnoent(err)) {
|
|
31
|
+
throw new SessionArtifactRefreshError('STAGE_WRITE_FAILED');
|
|
32
|
+
}
|
|
33
|
+
previous = null;
|
|
34
|
+
}
|
|
35
|
+
let changed = true;
|
|
36
|
+
if (previous !== null) {
|
|
37
|
+
const stableNewline = previous.endsWith('\n') && !previous.endsWith('\n\n');
|
|
38
|
+
if (previous === next || (stableNewline && equivalence(previous) === equivalence(next))) {
|
|
39
|
+
changed = false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
finalPath,
|
|
44
|
+
content: next,
|
|
45
|
+
tmpPath: `${finalPath}.tmp.${process.pid.toString()}.${randomBytes(4).toString('hex')}`,
|
|
46
|
+
changed,
|
|
47
|
+
previous,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function cleanupTmp(artifacts) {
|
|
51
|
+
await Promise.all(artifacts.map((artifact) => unlink(artifact.tmpPath).catch(() => {
|
|
52
|
+
/* best-effort cleanup */
|
|
53
|
+
})));
|
|
54
|
+
}
|
|
55
|
+
async function restorePrevious(artifact) {
|
|
56
|
+
try {
|
|
57
|
+
if (artifact.previous === null) {
|
|
58
|
+
await unlink(artifact.finalPath);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
await writeFile(artifact.finalPath, artifact.previous, 'utf-8');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
/* best-effort rollback */
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function commitPair(sessionJson, sessionContext) {
|
|
69
|
+
const staged = [sessionJson, sessionContext].filter((artifact) => artifact.changed);
|
|
70
|
+
if (staged.length === 0) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
await mkdir(dirname(sessionJson.finalPath), { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
throw new SessionArtifactRefreshError('STAGE_WRITE_FAILED');
|
|
78
|
+
}
|
|
79
|
+
const writeOutcomes = await Promise.allSettled(staged.map((artifact) => writeFile(artifact.tmpPath, artifact.content, 'utf-8')));
|
|
80
|
+
const anyWriteFailed = writeOutcomes.some((outcome) => outcome.status === 'rejected');
|
|
81
|
+
if (anyWriteFailed) {
|
|
82
|
+
await cleanupTmp(staged);
|
|
83
|
+
throw new SessionArtifactRefreshError('STAGE_WRITE_FAILED');
|
|
84
|
+
}
|
|
85
|
+
const committed = [];
|
|
86
|
+
try {
|
|
87
|
+
for (const artifact of staged) {
|
|
88
|
+
await rename(artifact.tmpPath, artifact.finalPath);
|
|
89
|
+
committed.push(artifact);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
await Promise.all(committed.map((artifact) => restorePrevious(artifact)));
|
|
94
|
+
await cleanupTmp(staged.filter((artifact) => !committed.includes(artifact)));
|
|
95
|
+
throw new SessionArtifactRefreshError('COMMIT_FAILED');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function refreshLocked(projectPath, projectId) {
|
|
99
|
+
const allSpecs = await specStore.listSpecs(projectId);
|
|
100
|
+
const activeSpecs = deriveActiveSpecSnapshot(allSpecs);
|
|
101
|
+
const sessionJsonPath = rootFile(projectPath);
|
|
102
|
+
const contextMdPath = sessionContextPath(projectPath);
|
|
103
|
+
let existingIndex = { activeSpecs: [], updatedAt: '' };
|
|
104
|
+
try {
|
|
105
|
+
existingIndex = JSON.parse(await readFile(sessionJsonPath, 'utf-8'));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* start fresh */
|
|
109
|
+
}
|
|
110
|
+
const nextIndex = buildSessionIndexPatch(existingIndex, allSpecs);
|
|
111
|
+
const sessionContextContent = await buildSessionContextContent(projectPath, allSpecs, activeSpecs);
|
|
112
|
+
const sessionJsonArtifact = await prepareArtifact(sessionJsonPath, stableJsonStringify(nextIndex), stripRootUpdatedAt);
|
|
113
|
+
const sessionContextArtifact = await prepareArtifact(contextMdPath, sessionContextContent, stripSessionMarkdownVolatileFields);
|
|
114
|
+
try {
|
|
115
|
+
await commitPair(sessionJsonArtifact, sessionContextArtifact);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
if (err instanceof SessionArtifactRefreshError) {
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
throw new SessionArtifactRefreshError('UNEXPECTED_FAILURE');
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
activeSpecIds: nextIndex.activeSpecs,
|
|
125
|
+
sessionJsonWritten: sessionJsonArtifact.changed,
|
|
126
|
+
sessionContextWritten: sessionContextArtifact.changed,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export async function refreshSessionArtifacts(projectPath, projectId) {
|
|
130
|
+
try {
|
|
131
|
+
return await withFileLock(`session-artifacts:${projectPath}`, () => refreshLocked(projectPath, projectId));
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err instanceof SessionArtifactRefreshError) {
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
throw new SessionArtifactRefreshError('UNEXPECTED_FAILURE');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=session-artifact-refresher.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SpecSessionState, SessionIndex, Spec } from '../../types/index.js';
|
|
2
|
+
export declare function rootFile(projectPath: string): string;
|
|
2
3
|
/**
|
|
3
4
|
* SPEC-633: Write per-spec session state and update root session.json index.
|
|
4
5
|
* Best-effort — never throws.
|
|
@@ -6,6 +7,8 @@ import type { SpecSessionState, SessionIndex, Spec } from '../../types/index.js'
|
|
|
6
7
|
export declare function writeSpecSessionState(projectPath: string, specId: string, specTitle: string, lastAction: string, testsStatus?: SpecSessionState['testsStatus'], contextUsage?: number): Promise<void>;
|
|
7
8
|
/** SPEC-656: Compute epicProgress map from all project specs. Tags shared by >=3 specs are epics. */
|
|
8
9
|
export declare function computeEpicProgress(specs: Spec[]): Record<string, string>;
|
|
10
|
+
export declare function deriveActiveSpecSnapshot(specs: Spec[]): Spec[];
|
|
11
|
+
export declare function buildSessionIndexPatch(existingIndex: SessionIndex, specs: Spec[]): SessionIndex;
|
|
9
12
|
/**
|
|
10
13
|
* SPEC-656: Update epicProgress in root session.json after any status change.
|
|
11
14
|
* Best-effort — never throws.
|
|
@@ -12,7 +12,7 @@ function stateDir(projectPath) {
|
|
|
12
12
|
function specFile(projectPath, specId) {
|
|
13
13
|
return join(stateDir(projectPath), `session-${specId}.json`);
|
|
14
14
|
}
|
|
15
|
-
function rootFile(projectPath) {
|
|
15
|
+
export function rootFile(projectPath) {
|
|
16
16
|
return join(projectPath, 'planu', ROOT_SESSION);
|
|
17
17
|
}
|
|
18
18
|
function getModifiedFiles(projectPath) {
|
|
@@ -123,13 +123,39 @@ export function computeEpicProgress(specs) {
|
|
|
123
123
|
}
|
|
124
124
|
return progress;
|
|
125
125
|
}
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
const ACTIVE_SPEC_LIMIT = 5;
|
|
127
|
+
export function deriveActiveSpecSnapshot(specs) {
|
|
128
|
+
const sorted = specs
|
|
128
129
|
.filter((spec) => spec.status === 'implementing' || spec.status === 'review')
|
|
129
|
-
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
130
|
+
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt) || b.id.localeCompare(a.id));
|
|
131
|
+
const seenIds = new Set();
|
|
132
|
+
const deduped = [];
|
|
133
|
+
for (const spec of sorted) {
|
|
134
|
+
if (seenIds.has(spec.id)) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
seenIds.add(spec.id);
|
|
138
|
+
deduped.push(spec);
|
|
139
|
+
}
|
|
140
|
+
return deduped.slice(0, ACTIVE_SPEC_LIMIT);
|
|
141
|
+
}
|
|
142
|
+
function reconcileActiveSpecIds(specs) {
|
|
143
|
+
return deriveActiveSpecSnapshot(specs).map((spec) => spec.id);
|
|
144
|
+
}
|
|
145
|
+
export function buildSessionIndexPatch(existingIndex, specs) {
|
|
146
|
+
const epicProgress = computeEpicProgress(specs);
|
|
147
|
+
const next = {
|
|
148
|
+
...existingIndex,
|
|
149
|
+
activeSpecs: reconcileActiveSpecIds(specs),
|
|
150
|
+
updatedAt: new Date().toISOString(),
|
|
151
|
+
};
|
|
152
|
+
if (Object.keys(epicProgress).length === 0) {
|
|
153
|
+
delete next.epicProgress;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
next.epicProgress = epicProgress;
|
|
157
|
+
}
|
|
158
|
+
return next;
|
|
133
159
|
}
|
|
134
160
|
/**
|
|
135
161
|
* SPEC-656: Update epicProgress in root session.json after any status change.
|
|
@@ -137,7 +163,6 @@ function reconcileActiveSpecIds(existing, specs) {
|
|
|
137
163
|
*/
|
|
138
164
|
export async function updateEpicProgressInSession(projectPath, specs) {
|
|
139
165
|
try {
|
|
140
|
-
const epicProgress = computeEpicProgress(specs);
|
|
141
166
|
const filePath = rootFile(projectPath);
|
|
142
167
|
let existingContent = null;
|
|
143
168
|
let index = { activeSpecs: [], updatedAt: '' };
|
|
@@ -148,15 +173,8 @@ export async function updateEpicProgressInSession(projectPath, specs) {
|
|
|
148
173
|
catch {
|
|
149
174
|
/* start fresh */
|
|
150
175
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
delete index.epicProgress;
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
index.epicProgress = epicProgress;
|
|
157
|
-
}
|
|
158
|
-
index.updatedAt = new Date().toISOString();
|
|
159
|
-
await stableWriteGeneratedFile(filePath, stableJsonStringify(index), {
|
|
176
|
+
const next = buildSessionIndexPatch(index, specs);
|
|
177
|
+
await stableWriteGeneratedFile(filePath, stableJsonStringify(next), {
|
|
160
178
|
equivalence: stripRootUpdatedAt,
|
|
161
179
|
existingContent,
|
|
162
180
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// engine/shared-agent-memory.ts — SPEC-689
|
|
2
2
|
import { readFile, mkdir, rename } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
4
5
|
import { hashProjectPath, projectDataDir } from '../storage/base-store.js';
|
|
5
6
|
import { acquireLock, releaseLock } from '../engine/safety/file-mutex.js';
|
|
6
7
|
import { atomicWriteFile } from '../engine/safety/atomic-write-file.js';
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
// Replaces placeholders and rewrites commands based on ProjectKnowledge.
|
|
3
3
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
5
6
|
import { readSkillRegistry, writeSkillRegistryEntry, } from '../../storage/skill-registry-storage.js';
|
|
6
7
|
import { PLACEHOLDER_MAP } from './placeholder-map.js';
|
|
7
8
|
import { rewritePackageManagerCommands, rewriteTestRunnerCommands } from './command-rewriter.js';
|
|
9
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
8
10
|
import { hashProjectPath } from '../../storage/base-store.js';
|
|
11
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
9
12
|
import { resolveStorageLayout } from '../../storage/storage-layout.js';
|
|
10
13
|
export { PLACEHOLDER_MAP } from './placeholder-map.js';
|
|
11
14
|
export { rewritePackageManagerCommands, rewriteTestRunnerCommands } from './command-rewriter.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
1
2
|
import { getSkillBootstrapConfig } from '../../storage/skill-bootstrap-store.js';
|
|
2
3
|
import { detectProjectStack, matchTechsToAvailable } from './stack-matcher.js';
|
|
3
4
|
const FETCH_TIMEOUT_MS = 5000;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// engine/skill-bootstrap/skill-writer.ts — SPEC-439: Write skills to target AI tool files
|
|
2
|
-
import {
|
|
2
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
4
|
import { assertEnglishOnlyArtifactText } from '../spec-language/english-only.js';
|
|
5
|
+
import { readFileOrNull as readFileSafe } from '../../core/shared/fs.js';
|
|
5
6
|
const AUTO_SECTION_HEADER = '## Auto-installed Skills (Planu)';
|
|
6
7
|
function targetToRelativePath(target) {
|
|
7
8
|
switch (target) {
|
|
@@ -23,14 +24,6 @@ function targetToRelativePath(target) {
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
async function readFileSafe(filePath) {
|
|
27
|
-
try {
|
|
28
|
-
return await readFile(filePath, 'utf-8');
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
27
|
export function formatSkillsForTarget(skills, target) {
|
|
35
28
|
if (target === 'cursorrules' || target === 'windsurfrules' || target === 'clinerules') {
|
|
36
29
|
return skills.map((s) => s.content).join('\n\n');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { technologyValue } from '../technology-registry.js';
|
|
2
2
|
// engine/skill-bootstrap/stack-matcher.ts — SPEC-439: Detect project stack and match to skills
|
|
3
|
-
import { readFile } from 'node:fs/promises';
|
|
4
3
|
import { join } from 'node:path';
|
|
4
|
+
import { readFileOrNull as readFileSafe } from '../../core/shared/fs.js';
|
|
5
5
|
const DEP_TO_TECH = {
|
|
6
6
|
// Frontend frameworks
|
|
7
7
|
next: technologyValue('technology-nextjs-c93379'),
|
|
@@ -114,14 +114,6 @@ const DEP_TO_TECH = {
|
|
|
114
114
|
sqlalchemy: technologyValue('technology-sqlalchemy-37f268'),
|
|
115
115
|
pydantic: technologyValue('technology-pydantic-636623'),
|
|
116
116
|
};
|
|
117
|
-
async function readFileSafe(filePath) {
|
|
118
|
-
try {
|
|
119
|
-
return await readFile(filePath, 'utf-8');
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
117
|
async function detectFromPackageJson(projectPath) {
|
|
126
118
|
const content = await readFileSafe(join(projectPath, 'package.json'));
|
|
127
119
|
if (!content) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Maps skill content to the file location expected by each supported AI agent/IDE.
|
|
3
3
|
import * as fs from 'node:fs/promises';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
|
+
import { fileExists } from '../../core/shared/fs.js';
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
6
7
|
// Agent path resolvers
|
|
7
8
|
// ---------------------------------------------------------------------------
|
|
@@ -74,15 +75,6 @@ function replaceSection(fileContent, skillName, newSection) {
|
|
|
74
75
|
return (fileContent.slice(0, start) + newSection.trimStart() + fileContent.slice(end + endMarker.length));
|
|
75
76
|
}
|
|
76
77
|
/** Check if a file exists on disk. */
|
|
77
|
-
async function fileExists(filePath) {
|
|
78
|
-
try {
|
|
79
|
-
await fs.access(filePath);
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
78
|
// ---------------------------------------------------------------------------
|
|
87
79
|
// Public API
|
|
88
80
|
// ---------------------------------------------------------------------------
|
|
@@ -6,6 +6,7 @@ import { technologyValue } from '../technology-registry.js';
|
|
|
6
6
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { adaptSkillContent } from '../skill-adapter/index.js';
|
|
9
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
9
10
|
import { writeSkillRegistryEntry } from '../../storage/skill-registry-storage.js';
|
|
10
11
|
import { WORKFLOW_SKILL_DEFINITIONS } from './skill-definitions.js';
|
|
11
12
|
import { hashConventions } from './conventions-hasher.js';
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import { readFile, writeFile, mkdir, appendFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { fetchAnthropicSkillContent } from './anthropic-adapter.js';
|
|
6
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
6
7
|
import { hashProjectPath } from '../../storage/base-store.js';
|
|
8
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
7
9
|
import { resolveStorageLayout } from '../../storage/storage-layout.js';
|
|
8
10
|
const TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
9
11
|
const SKILLS_DIR = '.claude/skills';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// engine/spec-audit/index.ts — SPEC-744
|
|
2
2
|
// Orchestrates the two-tier spec drift audit.
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
4
5
|
import { listSpecs } from '../../storage/spec-store.js';
|
|
6
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
5
7
|
import { hashProjectPath, projectDataDir } from '../../storage/base-store.js';
|
|
6
8
|
import { buildSpecGraph } from '../spec-dependency-graph/graph-builder.js';
|
|
7
9
|
import { getSupersededSet, getSupersededMap } from '../spec-dependency-graph/superseded-set.js';
|
|
@@ -4,6 +4,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import { join, dirname } from 'node:path';
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
import { atomicWriteFile } from '../safety/atomic-write-file.js';
|
|
7
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
7
8
|
import { hashProjectPath, projectDataDir } from '../../storage/base-store.js';
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
9
10
|
// Markdown report
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Coordinates test-finder, criteria-mapper, scoring, and persistence.
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
// eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
|
|
5
6
|
import { readJson, writeJson, projectDataDir } from '../../storage/base-store.js';
|
|
6
7
|
import { findTestFiles, detectTestRunners, readTestFileContent } from './test-finder.js';
|
|
7
8
|
import { extractCriteria, mapTestsToCriterion } from './criteria-mapper.js';
|