@planu/cli 0.89.0 → 0.90.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/dist/cli/commands/activate.d.ts +14 -0
- package/dist/cli/commands/activate.d.ts.map +1 -0
- package/dist/cli/commands/activate.js +174 -0
- package/dist/cli/commands/activate.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +16 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +162 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/install.d.ts +48 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +348 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +10 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +133 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/router.d.ts.map +1 -1
- package/dist/cli/router.js +9 -1
- package/dist/cli/router.js.map +1 -1
- package/dist/config/license-plans.json +2 -1
- package/dist/engine/agent-generator.test.d.ts +2 -0
- package/dist/engine/agent-generator.test.d.ts.map +1 -0
- package/dist/engine/agent-generator.test.js +556 -0
- package/dist/engine/agent-generator.test.js.map +1 -0
- package/dist/engine/analyzer.test.d.ts +2 -0
- package/dist/engine/analyzer.test.d.ts.map +1 -0
- package/dist/engine/analyzer.test.js +1461 -0
- package/dist/engine/analyzer.test.js.map +1 -0
- package/dist/engine/auditor.test.d.ts +2 -0
- package/dist/engine/auditor.test.d.ts.map +1 -0
- package/dist/engine/auditor.test.js +2075 -0
- package/dist/engine/auditor.test.js.map +1 -0
- package/dist/engine/doc-generator.test.d.ts +2 -0
- package/dist/engine/doc-generator.test.d.ts.map +1 -0
- package/dist/engine/doc-generator.test.js +961 -0
- package/dist/engine/doc-generator.test.js.map +1 -0
- package/dist/engine/estimator.test.d.ts +2 -0
- package/dist/engine/estimator.test.d.ts.map +1 -0
- package/dist/engine/estimator.test.js +334 -0
- package/dist/engine/estimator.test.js.map +1 -0
- package/dist/engine/skill-generator.test.d.ts +2 -0
- package/dist/engine/skill-generator.test.d.ts.map +1 -0
- package/dist/engine/skill-generator.test.js +742 -0
- package/dist/engine/skill-generator.test.js.map +1 -0
- package/dist/engine/spec-migrator/filesystem-import.d.ts +14 -0
- package/dist/engine/spec-migrator/filesystem-import.d.ts.map +1 -0
- package/dist/engine/spec-migrator/filesystem-import.js +96 -0
- package/dist/engine/spec-migrator/filesystem-import.js.map +1 -0
- package/dist/engine/spec-migrator/flatten-specs.d.ts +12 -0
- package/dist/engine/spec-migrator/flatten-specs.d.ts.map +1 -0
- package/dist/engine/spec-migrator/flatten-specs.js +111 -0
- package/dist/engine/spec-migrator/flatten-specs.js.map +1 -0
- package/dist/engine/spec-migrator/folder-operations.d.ts +9 -0
- package/dist/engine/spec-migrator/folder-operations.d.ts.map +1 -0
- package/dist/engine/spec-migrator/folder-operations.js +109 -0
- package/dist/engine/spec-migrator/folder-operations.js.map +1 -0
- package/dist/engine/spec-migrator/frontmatter-parser.d.ts +11 -0
- package/dist/engine/spec-migrator/frontmatter-parser.d.ts.map +1 -0
- package/dist/engine/spec-migrator/frontmatter-parser.js +92 -0
- package/dist/engine/spec-migrator/frontmatter-parser.js.map +1 -0
- package/dist/engine/spec-migrator/index.d.ts +9 -0
- package/dist/engine/spec-migrator/index.d.ts.map +1 -0
- package/dist/engine/spec-migrator/index.js +18 -0
- package/dist/engine/spec-migrator/index.js.map +1 -0
- package/dist/engine/spec-migrator/legacy-migration.d.ts +13 -0
- package/dist/engine/spec-migrator/legacy-migration.d.ts.map +1 -0
- package/dist/engine/spec-migrator/legacy-migration.js +75 -0
- package/dist/engine/spec-migrator/legacy-migration.js.map +1 -0
- package/dist/engine/spec-migrator/migration-validator.d.ts +20 -0
- package/dist/engine/spec-migrator/migration-validator.d.ts.map +1 -0
- package/dist/engine/spec-migrator/migration-validator.js +35 -0
- package/dist/engine/spec-migrator/migration-validator.js.map +1 -0
- package/dist/engine/spec-migrator/path-utils.d.ts +13 -0
- package/dist/engine/spec-migrator/path-utils.d.ts.map +1 -0
- package/dist/engine/spec-migrator/path-utils.js +40 -0
- package/dist/engine/spec-migrator/path-utils.js.map +1 -0
- package/dist/engine/spec-migrator/prefix-migration.d.ts +11 -0
- package/dist/engine/spec-migrator/prefix-migration.d.ts.map +1 -0
- package/dist/engine/spec-migrator/prefix-migration.js +73 -0
- package/dist/engine/spec-migrator/prefix-migration.js.map +1 -0
- package/dist/engine/spec-migrator/reconcile-paths.d.ts +12 -0
- package/dist/engine/spec-migrator/reconcile-paths.d.ts.map +1 -0
- package/dist/engine/spec-migrator/reconcile-paths.js +77 -0
- package/dist/engine/spec-migrator/reconcile-paths.js.map +1 -0
- package/dist/engine/spec-migrator/version-detection.d.ts +5 -0
- package/dist/engine/spec-migrator/version-detection.d.ts.map +1 -0
- package/dist/engine/spec-migrator/version-detection.js +19 -0
- package/dist/engine/spec-migrator/version-detection.js.map +1 -0
- package/dist/engine/spec-migrator.d.ts +1 -58
- package/dist/engine/spec-migrator.d.ts.map +1 -1
- package/dist/engine/spec-migrator.js +2 -658
- package/dist/engine/spec-migrator.js.map +1 -1
- package/dist/engine/spec-summary-html/dashboard-renderer.d.ts +6 -0
- package/dist/engine/spec-summary-html/dashboard-renderer.d.ts.map +1 -0
- package/dist/engine/spec-summary-html/dashboard-renderer.js +333 -0
- package/dist/engine/spec-summary-html/dashboard-renderer.js.map +1 -0
- package/dist/engine/spec-summary-html/hash-utils.d.ts +11 -0
- package/dist/engine/spec-summary-html/hash-utils.d.ts.map +1 -0
- package/dist/engine/spec-summary-html/hash-utils.js +39 -0
- package/dist/engine/spec-summary-html/hash-utils.js.map +1 -0
- package/dist/engine/spec-summary-html/index.d.ts +4 -0
- package/dist/engine/spec-summary-html/index.d.ts.map +1 -0
- package/dist/engine/spec-summary-html/index.js +6 -0
- package/dist/engine/spec-summary-html/index.js.map +1 -0
- package/dist/engine/spec-summary-html/report-renderer.d.ts +9 -0
- package/dist/engine/spec-summary-html/report-renderer.d.ts.map +1 -0
- package/dist/engine/spec-summary-html/report-renderer.js +139 -0
- package/dist/engine/spec-summary-html/report-renderer.js.map +1 -0
- package/dist/engine/spec-summary-html.d.ts +1 -0
- package/dist/engine/spec-summary-html.d.ts.map +1 -1
- package/dist/engine/spec-summary-html.js +19 -473
- package/dist/engine/spec-summary-html.js.map +1 -1
- package/dist/engine/update-notifier.d.ts +8 -0
- package/dist/engine/update-notifier.d.ts.map +1 -0
- package/dist/engine/update-notifier.js +130 -0
- package/dist/engine/update-notifier.js.map +1 -0
- package/dist/engine/validator/dor-dod.d.ts.map +1 -1
- package/dist/engine/validator/dor-dod.js +8 -5
- package/dist/engine/validator/dor-dod.js.map +1 -1
- package/dist/engine/validator.d.ts.map +1 -1
- package/dist/engine/validator.js +4 -3
- package/dist/engine/validator.js.map +1 -1
- package/dist/engine/validator.test.d.ts +2 -0
- package/dist/engine/validator.test.d.ts.map +1 -0
- package/dist/engine/validator.test.js +2371 -0
- package/dist/engine/validator.test.js.map +1 -0
- package/dist/engine/web-fetcher.test.d.ts +2 -0
- package/dist/engine/web-fetcher.test.d.ts.map +1 -0
- package/dist/engine/web-fetcher.test.js +360 -0
- package/dist/engine/web-fetcher.test.js.map +1 -0
- package/dist/i18n/index.test.d.ts +2 -0
- package/dist/i18n/index.test.d.ts.map +1 -0
- package/dist/i18n/index.test.js +375 -0
- package/dist/i18n/index.test.js.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +124 -0
- package/dist/index.test.js.map +1 -0
- package/dist/resources/patterns.test.d.ts +2 -0
- package/dist/resources/patterns.test.d.ts.map +1 -0
- package/dist/resources/patterns.test.js +142 -0
- package/dist/resources/patterns.test.js.map +1 -0
- package/dist/resources/process.test.d.ts +2 -0
- package/dist/resources/process.test.d.ts.map +1 -0
- package/dist/resources/process.test.js +48 -0
- package/dist/resources/process.test.js.map +1 -0
- package/dist/resources/registry.test.d.ts +2 -0
- package/dist/resources/registry.test.d.ts.map +1 -0
- package/dist/resources/registry.test.js +138 -0
- package/dist/resources/registry.test.js.map +1 -0
- package/dist/resources/specs.test.d.ts +2 -0
- package/dist/resources/specs.test.d.ts.map +1 -0
- package/dist/resources/specs.test.js +130 -0
- package/dist/resources/specs.test.js.map +1 -0
- package/dist/resources/templates.test.d.ts +2 -0
- package/dist/resources/templates.test.d.ts.map +1 -0
- package/dist/resources/templates.test.js +119 -0
- package/dist/resources/templates.test.js.map +1 -0
- package/dist/smoke.test.d.ts +2 -0
- package/dist/smoke.test.d.ts.map +1 -0
- package/dist/smoke.test.js +229 -0
- package/dist/smoke.test.js.map +1 -0
- package/dist/storage/base-store.test.d.ts +2 -0
- package/dist/storage/base-store.test.d.ts.map +1 -0
- package/dist/storage/base-store.test.js +180 -0
- package/dist/storage/base-store.test.js.map +1 -0
- package/dist/storage/global-store.test.d.ts +2 -0
- package/dist/storage/global-store.test.d.ts.map +1 -0
- package/dist/storage/global-store.test.js +327 -0
- package/dist/storage/global-store.test.js.map +1 -0
- package/dist/storage/index.test.d.ts +2 -0
- package/dist/storage/index.test.d.ts.map +1 -0
- package/dist/storage/index.test.js +56 -0
- package/dist/storage/index.test.js.map +1 -0
- package/dist/storage/knowledge-store.test.d.ts +2 -0
- package/dist/storage/knowledge-store.test.d.ts.map +1 -0
- package/dist/storage/knowledge-store.test.js +368 -0
- package/dist/storage/knowledge-store.test.js.map +1 -0
- package/dist/storage/metrics-store.test.d.ts +2 -0
- package/dist/storage/metrics-store.test.d.ts.map +1 -0
- package/dist/storage/metrics-store.test.js +212 -0
- package/dist/storage/metrics-store.test.js.map +1 -0
- package/dist/storage/pattern-store.test.d.ts +2 -0
- package/dist/storage/pattern-store.test.d.ts.map +1 -0
- package/dist/storage/pattern-store.test.js +224 -0
- package/dist/storage/pattern-store.test.js.map +1 -0
- package/dist/storage/spec-store.test.d.ts +2 -0
- package/dist/storage/spec-store.test.d.ts.map +1 -0
- package/dist/storage/spec-store.test.js +227 -0
- package/dist/storage/spec-store.test.js.map +1 -0
- package/dist/tools/audit.test.d.ts +2 -0
- package/dist/tools/audit.test.d.ts.map +1 -0
- package/dist/tools/audit.test.js +169 -0
- package/dist/tools/audit.test.js.map +1 -0
- package/dist/tools/challenge-spec.test.d.ts +2 -0
- package/dist/tools/challenge-spec.test.d.ts.map +1 -0
- package/dist/tools/challenge-spec.test.js +782 -0
- package/dist/tools/challenge-spec.test.js.map +1 -0
- package/dist/tools/check-versions.test.d.ts +2 -0
- package/dist/tools/check-versions.test.d.ts.map +1 -0
- package/dist/tools/check-versions.test.js +214 -0
- package/dist/tools/check-versions.test.js.map +1 -0
- package/dist/tools/clarify-requirements.test.d.ts +2 -0
- package/dist/tools/clarify-requirements.test.d.ts.map +1 -0
- package/dist/tools/clarify-requirements.test.js +161 -0
- package/dist/tools/clarify-requirements.test.js.map +1 -0
- package/dist/tools/consult-docs.test.d.ts +2 -0
- package/dist/tools/consult-docs.test.d.ts.map +1 -0
- package/dist/tools/consult-docs.test.js +140 -0
- package/dist/tools/consult-docs.test.js.map +1 -0
- package/dist/tools/create-spec.test.d.ts +2 -0
- package/dist/tools/create-spec.test.d.ts.map +1 -0
- package/dist/tools/create-spec.test.js +233 -0
- package/dist/tools/create-spec.test.js.map +1 -0
- package/dist/tools/define-ui-contract.test.d.ts +2 -0
- package/dist/tools/define-ui-contract.test.d.ts.map +1 -0
- package/dist/tools/define-ui-contract.test.js +479 -0
- package/dist/tools/define-ui-contract.test.js.map +1 -0
- package/dist/tools/design-schema.test.d.ts +2 -0
- package/dist/tools/design-schema.test.d.ts.map +1 -0
- package/dist/tools/design-schema.test.js +301 -0
- package/dist/tools/design-schema.test.js.map +1 -0
- package/dist/tools/detect-agent.test.d.ts +2 -0
- package/dist/tools/detect-agent.test.d.ts.map +1 -0
- package/dist/tools/detect-agent.test.js +133 -0
- package/dist/tools/detect-agent.test.js.map +1 -0
- package/dist/tools/detect-drift.test.d.ts +2 -0
- package/dist/tools/detect-drift.test.d.ts.map +1 -0
- package/dist/tools/detect-drift.test.js +312 -0
- package/dist/tools/detect-drift.test.js.map +1 -0
- package/dist/tools/discover-mcps.test.d.ts +2 -0
- package/dist/tools/discover-mcps.test.d.ts.map +1 -0
- package/dist/tools/discover-mcps.test.js +345 -0
- package/dist/tools/discover-mcps.test.js.map +1 -0
- package/dist/tools/estimate.test.d.ts +2 -0
- package/dist/tools/estimate.test.d.ts.map +1 -0
- package/dist/tools/estimate.test.js +137 -0
- package/dist/tools/estimate.test.js.map +1 -0
- package/dist/tools/generate-adr.test.d.ts +2 -0
- package/dist/tools/generate-adr.test.d.ts.map +1 -0
- package/dist/tools/generate-adr.test.js +206 -0
- package/dist/tools/generate-adr.test.js.map +1 -0
- package/dist/tools/generate-checklist.test.d.ts +2 -0
- package/dist/tools/generate-checklist.test.d.ts.map +1 -0
- package/dist/tools/generate-checklist.test.js +201 -0
- package/dist/tools/generate-checklist.test.js.map +1 -0
- package/dist/tools/generate-docs.test.d.ts +2 -0
- package/dist/tools/generate-docs.test.d.ts.map +1 -0
- package/dist/tools/generate-docs.test.js +183 -0
- package/dist/tools/generate-docs.test.js.map +1 -0
- package/dist/tools/generate-execution-plan.test.d.ts +2 -0
- package/dist/tools/generate-execution-plan.test.d.ts.map +1 -0
- package/dist/tools/generate-execution-plan.test.js +643 -0
- package/dist/tools/generate-execution-plan.test.js.map +1 -0
- package/dist/tools/generate-rules.test.d.ts +2 -0
- package/dist/tools/generate-rules.test.d.ts.map +1 -0
- package/dist/tools/generate-rules.test.js +148 -0
- package/dist/tools/generate-rules.test.js.map +1 -0
- package/dist/tools/generate-skill.test.d.ts +2 -0
- package/dist/tools/generate-skill.test.d.ts.map +1 -0
- package/dist/tools/generate-skill.test.js +138 -0
- package/dist/tools/generate-skill.test.js.map +1 -0
- package/dist/tools/generate-sub-agent.test.d.ts +2 -0
- package/dist/tools/generate-sub-agent.test.d.ts.map +1 -0
- package/dist/tools/generate-sub-agent.test.js +162 -0
- package/dist/tools/generate-sub-agent.test.js.map +1 -0
- package/dist/tools/generate-tests.test.d.ts +2 -0
- package/dist/tools/generate-tests.test.d.ts.map +1 -0
- package/dist/tools/generate-tests.test.js +222 -0
- package/dist/tools/generate-tests.test.js.map +1 -0
- package/dist/tools/init-constitution.test.d.ts +2 -0
- package/dist/tools/init-constitution.test.d.ts.map +1 -0
- package/dist/tools/init-constitution.test.js +398 -0
- package/dist/tools/init-constitution.test.js.map +1 -0
- package/dist/tools/init-project/config-builder.d.ts +12 -0
- package/dist/tools/init-project/config-builder.d.ts.map +1 -0
- package/dist/tools/init-project/config-builder.js +31 -0
- package/dist/tools/init-project/config-builder.js.map +1 -0
- package/dist/tools/init-project/git-setup.d.ts +8 -0
- package/dist/tools/init-project/git-setup.d.ts.map +1 -0
- package/dist/tools/init-project/git-setup.js +70 -0
- package/dist/tools/init-project/git-setup.js.map +1 -0
- package/dist/tools/init-project/handler.d.ts.map +1 -1
- package/dist/tools/init-project/handler.js +25 -371
- package/dist/tools/init-project/handler.js.map +1 -1
- package/dist/tools/init-project/lifecycle-helpers.d.ts +32 -0
- package/dist/tools/init-project/lifecycle-helpers.d.ts.map +1 -0
- package/dist/tools/init-project/lifecycle-helpers.js +153 -0
- package/dist/tools/init-project/lifecycle-helpers.js.map +1 -0
- package/dist/tools/init-project/migration-runner.d.ts +28 -0
- package/dist/tools/init-project/migration-runner.d.ts.map +1 -0
- package/dist/tools/init-project/migration-runner.js +57 -0
- package/dist/tools/init-project/migration-runner.js.map +1 -0
- package/dist/tools/init-project/rules-writer.d.ts +14 -0
- package/dist/tools/init-project/rules-writer.d.ts.map +1 -0
- package/dist/tools/init-project/rules-writer.js +43 -0
- package/dist/tools/init-project/rules-writer.js.map +1 -0
- package/dist/tools/init-project/scaffold-writer.d.ts +29 -0
- package/dist/tools/init-project/scaffold-writer.d.ts.map +1 -0
- package/dist/tools/init-project/scaffold-writer.js +76 -0
- package/dist/tools/init-project/scaffold-writer.js.map +1 -0
- package/dist/tools/init-project/stack-detector.d.ts +16 -0
- package/dist/tools/init-project/stack-detector.d.ts.map +1 -0
- package/dist/tools/init-project/stack-detector.js +19 -0
- package/dist/tools/init-project/stack-detector.js.map +1 -0
- package/dist/tools/init-project.test.d.ts +2 -0
- package/dist/tools/init-project.test.d.ts.map +1 -0
- package/dist/tools/init-project.test.js +158 -0
- package/dist/tools/init-project.test.js.map +1 -0
- package/dist/tools/integrate-pm.test.d.ts +2 -0
- package/dist/tools/integrate-pm.test.d.ts.map +1 -0
- package/dist/tools/integrate-pm.test.js +558 -0
- package/dist/tools/integrate-pm.test.js.map +1 -0
- package/dist/tools/learn.test.d.ts +2 -0
- package/dist/tools/learn.test.d.ts.map +1 -0
- package/dist/tools/learn.test.js +123 -0
- package/dist/tools/learn.test.js.map +1 -0
- package/dist/tools/list-specs.js +1 -1
- package/dist/tools/list-specs.js.map +1 -1
- package/dist/tools/list-specs.test.d.ts +2 -0
- package/dist/tools/list-specs.test.d.ts.map +1 -0
- package/dist/tools/list-specs.test.js +110 -0
- package/dist/tools/list-specs.test.js.map +1 -0
- package/dist/tools/manage-context.test.d.ts +2 -0
- package/dist/tools/manage-context.test.d.ts.map +1 -0
- package/dist/tools/manage-context.test.js +359 -0
- package/dist/tools/manage-context.test.js.map +1 -0
- package/dist/tools/manage-git.test.d.ts +2 -0
- package/dist/tools/manage-git.test.d.ts.map +1 -0
- package/dist/tools/manage-git.test.js +882 -0
- package/dist/tools/manage-git.test.js.map +1 -0
- package/dist/tools/orchestrate.test.d.ts +2 -0
- package/dist/tools/orchestrate.test.d.ts.map +1 -0
- package/dist/tools/orchestrate.test.js +1117 -0
- package/dist/tools/orchestrate.test.js.map +1 -0
- package/dist/tools/reconcile-spec.test.d.ts +2 -0
- package/dist/tools/reconcile-spec.test.d.ts.map +1 -0
- package/dist/tools/reconcile-spec.test.js +259 -0
- package/dist/tools/reconcile-spec.test.js.map +1 -0
- package/dist/tools/red-team.d.ts +3 -0
- package/dist/tools/red-team.d.ts.map +1 -0
- package/dist/tools/red-team.js +302 -0
- package/dist/tools/red-team.js.map +1 -0
- package/dist/tools/register-platform-tools/design-stack-tools.d.ts.map +1 -1
- package/dist/tools/register-platform-tools/design-stack-tools.js +14 -0
- package/dist/tools/register-platform-tools/design-stack-tools.js.map +1 -1
- package/dist/tools/register-platform-tools.test.d.ts +2 -0
- package/dist/tools/register-platform-tools.test.d.ts.map +1 -0
- package/dist/tools/register-platform-tools.test.js +404 -0
- package/dist/tools/register-platform-tools.test.js.map +1 -0
- package/dist/tools/register-spec-tools.test.d.ts +2 -0
- package/dist/tools/register-spec-tools.test.d.ts.map +1 -0
- package/dist/tools/register-spec-tools.test.js +407 -0
- package/dist/tools/register-spec-tools.test.js.map +1 -0
- package/dist/tools/reverse-engineer.test.d.ts +2 -0
- package/dist/tools/reverse-engineer.test.d.ts.map +1 -0
- package/dist/tools/reverse-engineer.test.js +206 -0
- package/dist/tools/reverse-engineer.test.js.map +1 -0
- package/dist/tools/schemas.d.ts +20 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +133 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/tools/schemas.test.d.ts +2 -0
- package/dist/tools/schemas.test.d.ts.map +1 -0
- package/dist/tools/schemas.test.js +245 -0
- package/dist/tools/schemas.test.js.map +1 -0
- package/dist/tools/set-locale.test.d.ts +2 -0
- package/dist/tools/set-locale.test.d.ts.map +1 -0
- package/dist/tools/set-locale.test.js +74 -0
- package/dist/tools/set-locale.test.js.map +1 -0
- package/dist/tools/suggest-mcps.test.d.ts +2 -0
- package/dist/tools/suggest-mcps.test.d.ts.map +1 -0
- package/dist/tools/suggest-mcps.test.js +198 -0
- package/dist/tools/suggest-mcps.test.js.map +1 -0
- package/dist/tools/suggest-stack.test.d.ts +2 -0
- package/dist/tools/suggest-stack.test.d.ts.map +1 -0
- package/dist/tools/suggest-stack.test.js +181 -0
- package/dist/tools/suggest-stack.test.js.map +1 -0
- package/dist/tools/suggest-tooling.test.d.ts +2 -0
- package/dist/tools/suggest-tooling.test.d.ts.map +1 -0
- package/dist/tools/suggest-tooling.test.js +213 -0
- package/dist/tools/suggest-tooling.test.js.map +1 -0
- package/dist/tools/summarize-spec.test.d.ts +2 -0
- package/dist/tools/summarize-spec.test.d.ts.map +1 -0
- package/dist/tools/summarize-spec.test.js +180 -0
- package/dist/tools/summarize-spec.test.js.map +1 -0
- package/dist/tools/update-status/dod-gates.d.ts +16 -0
- package/dist/tools/update-status/dod-gates.d.ts.map +1 -0
- package/dist/tools/update-status/dod-gates.js +117 -0
- package/dist/tools/update-status/dod-gates.js.map +1 -0
- package/dist/tools/update-status/file-sync.d.ts +6 -0
- package/dist/tools/update-status/file-sync.d.ts.map +1 -0
- package/dist/tools/update-status/file-sync.js +112 -0
- package/dist/tools/update-status/file-sync.js.map +1 -0
- package/dist/tools/update-status/index.d.ts +3 -0
- package/dist/tools/update-status/index.d.ts.map +1 -0
- package/dist/tools/update-status/index.js +181 -0
- package/dist/tools/update-status/index.js.map +1 -0
- package/dist/tools/update-status/response-builder.d.ts +4 -0
- package/dist/tools/update-status/response-builder.d.ts.map +1 -0
- package/dist/tools/update-status/response-builder.js +69 -0
- package/dist/tools/update-status/response-builder.js.map +1 -0
- package/dist/tools/update-status/side-effects.d.ts +15 -0
- package/dist/tools/update-status/side-effects.d.ts.map +1 -0
- package/dist/tools/update-status/side-effects.js +64 -0
- package/dist/tools/update-status/side-effects.js.map +1 -0
- package/dist/tools/update-status/transition-guard.d.ts +20 -0
- package/dist/tools/update-status/transition-guard.d.ts.map +1 -0
- package/dist/tools/update-status/transition-guard.js +75 -0
- package/dist/tools/update-status/transition-guard.js.map +1 -0
- package/dist/tools/update-status.d.ts +1 -2
- package/dist/tools/update-status.d.ts.map +1 -1
- package/dist/tools/update-status.js +2 -481
- package/dist/tools/update-status.js.map +1 -1
- package/dist/tools/update-status.test.d.ts +2 -0
- package/dist/tools/update-status.test.d.ts.map +1 -0
- package/dist/tools/update-status.test.js +142 -0
- package/dist/tools/update-status.test.js.map +1 -0
- package/dist/tools/validate.d.ts.map +1 -1
- package/dist/tools/validate.js +6 -4
- package/dist/tools/validate.js.map +1 -1
- package/dist/tools/validate.test.d.ts +2 -0
- package/dist/tools/validate.test.d.ts.map +1 -0
- package/dist/tools/validate.test.js +137 -0
- package/dist/tools/validate.test.js.map +1 -0
- package/dist/types/analysis.d.ts +2 -1
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/red-team.d.ts +29 -0
- package/dist/types/red-team.d.ts.map +1 -0
- package/dist/types/red-team.js +3 -0
- package/dist/types/red-team.js.map +1 -0
- package/dist/types/update-notifier.d.ts +5 -0
- package/dist/types/update-notifier.d.ts.map +1 -0
- package/dist/types/update-notifier.js +3 -0
- package/dist/types/update-notifier.js.map +1 -0
- package/package.json +9 -2
- package/src/config/license-plans.json +2 -1
- package/src/i18n/messages/en.json +5 -0
- package/src/i18n/messages/es.json +5 -0
- package/src/i18n/messages/pt.json +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-execution-plan.test.d.ts","sourceRoot":"","sources":["../../src/tools/generate-execution-plan.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
// Tests for handleGenerateExecutionPlan
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
3
|
+
vi.mock('../i18n/index.js', () => ({
|
|
4
|
+
t: (key) => key,
|
|
5
|
+
ti: (key, vars) => `${key}:${JSON.stringify(vars)}`,
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('../storage/index.js', () => ({
|
|
8
|
+
specStore: { getSpec: vi.fn() },
|
|
9
|
+
knowledgeStore: { getKnowledge: vi.fn() },
|
|
10
|
+
patternStore: { listPatterns: vi.fn() },
|
|
11
|
+
}));
|
|
12
|
+
vi.mock('node:fs/promises', () => ({
|
|
13
|
+
readFile: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
import { handleGenerateExecutionPlan } from './generate-execution-plan.js';
|
|
16
|
+
import { specStore, knowledgeStore, patternStore } from '../storage/index.js';
|
|
17
|
+
import { readFile } from 'node:fs/promises';
|
|
18
|
+
const mockGetSpec = vi.mocked(specStore.getSpec);
|
|
19
|
+
const mockGetKnowledge = vi.mocked(knowledgeStore.getKnowledge);
|
|
20
|
+
const mockListPatterns = vi.mocked(patternStore.listPatterns);
|
|
21
|
+
const mockReadFile = vi.mocked(readFile);
|
|
22
|
+
const baseSpec = {
|
|
23
|
+
id: 'SPEC-001',
|
|
24
|
+
slug: 'user-auth',
|
|
25
|
+
title: 'User Authentication',
|
|
26
|
+
type: 'feature',
|
|
27
|
+
scope: 'feature',
|
|
28
|
+
target: 'fullstack',
|
|
29
|
+
tags: ['auth', 'api'],
|
|
30
|
+
status: 'approved',
|
|
31
|
+
risk: 'medium',
|
|
32
|
+
difficulty: 3,
|
|
33
|
+
estimation: { devHours: 16, reviewHours: 4, totalCostUsd: 200 },
|
|
34
|
+
dependencies: [],
|
|
35
|
+
huPath: null,
|
|
36
|
+
fichaTecnicaPath: null,
|
|
37
|
+
gitBranch: null,
|
|
38
|
+
};
|
|
39
|
+
const baseKnowledge = {
|
|
40
|
+
language: 'typescript',
|
|
41
|
+
framework: 'next',
|
|
42
|
+
projectPath: '/test',
|
|
43
|
+
stack: [],
|
|
44
|
+
conventions: {},
|
|
45
|
+
architecture: {
|
|
46
|
+
primary: 'monolith',
|
|
47
|
+
secondary: [],
|
|
48
|
+
layers: [
|
|
49
|
+
{ name: 'infrastructure', directories: ['src/infra'] },
|
|
50
|
+
{ name: 'application', directories: ['src/services'] },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
database: 'postgresql',
|
|
54
|
+
testCommand: 'npm test',
|
|
55
|
+
buildCommand: 'npm run build',
|
|
56
|
+
linting: { detectedLinters: [{ tool: 'eslint' }] },
|
|
57
|
+
apiContracts: [{ type: 'rest' }],
|
|
58
|
+
layers: [],
|
|
59
|
+
};
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
vi.clearAllMocks();
|
|
62
|
+
mockReadFile.mockRejectedValue(new Error('not found'));
|
|
63
|
+
mockListPatterns.mockResolvedValue([]);
|
|
64
|
+
});
|
|
65
|
+
describe('handleGenerateExecutionPlan', () => {
|
|
66
|
+
it('should return error when spec not found', async () => {
|
|
67
|
+
mockGetSpec.mockResolvedValue(null);
|
|
68
|
+
const result = await handleGenerateExecutionPlan({
|
|
69
|
+
specId: 'SPEC-999',
|
|
70
|
+
projectId: 'proj-1',
|
|
71
|
+
});
|
|
72
|
+
expect(result.isError).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it('should return error when knowledge not found', async () => {
|
|
75
|
+
mockGetSpec.mockResolvedValue(baseSpec);
|
|
76
|
+
mockGetKnowledge.mockResolvedValue(null);
|
|
77
|
+
const result = await handleGenerateExecutionPlan({
|
|
78
|
+
specId: 'SPEC-001',
|
|
79
|
+
projectId: 'proj-1',
|
|
80
|
+
});
|
|
81
|
+
expect(result.isError).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
it('should generate plan for fullstack spec', async () => {
|
|
84
|
+
mockGetSpec.mockResolvedValue(baseSpec);
|
|
85
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
86
|
+
const result = await handleGenerateExecutionPlan({
|
|
87
|
+
specId: 'SPEC-001',
|
|
88
|
+
projectId: 'proj-1',
|
|
89
|
+
});
|
|
90
|
+
expect(result.isError).toBeUndefined();
|
|
91
|
+
expect(result.content).toHaveLength(2);
|
|
92
|
+
const data = JSON.parse(result.content[1].text);
|
|
93
|
+
expect(data.phases.length).toBeGreaterThanOrEqual(4);
|
|
94
|
+
expect(data.totalSteps).toBeGreaterThan(0);
|
|
95
|
+
expect(data.criticalPath.length).toBeGreaterThan(0);
|
|
96
|
+
expect(data.summary).toBeDefined();
|
|
97
|
+
expect(data.summary.estimatedMinutes).toBeGreaterThan(0);
|
|
98
|
+
// Should include: Setup, Data Layer, Business Logic, UI, Testing, Integration
|
|
99
|
+
const phaseNames = data.phases.map((p) => p.name);
|
|
100
|
+
expect(phaseNames).toContain('Setup & Scaffolding');
|
|
101
|
+
expect(phaseNames).toContain('Data Layer');
|
|
102
|
+
expect(phaseNames).toContain('Business Logic & API');
|
|
103
|
+
expect(phaseNames).toContain('UI Implementation');
|
|
104
|
+
expect(phaseNames).toContain('Testing & Verification');
|
|
105
|
+
expect(phaseNames).toContain('Integration & Cleanup');
|
|
106
|
+
});
|
|
107
|
+
it('should skip UI phase for backend-only spec', async () => {
|
|
108
|
+
mockGetSpec.mockResolvedValue({
|
|
109
|
+
...baseSpec, target: 'backend',
|
|
110
|
+
});
|
|
111
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
112
|
+
const result = await handleGenerateExecutionPlan({
|
|
113
|
+
specId: 'SPEC-001',
|
|
114
|
+
projectId: 'proj-1',
|
|
115
|
+
});
|
|
116
|
+
const data = JSON.parse(result.content[1].text);
|
|
117
|
+
const phaseNames = data.phases.map((p) => p.name);
|
|
118
|
+
expect(phaseNames).not.toContain('UI Implementation');
|
|
119
|
+
});
|
|
120
|
+
it('should skip data layer for frontend-only spec', async () => {
|
|
121
|
+
mockGetSpec.mockResolvedValue({
|
|
122
|
+
...baseSpec, target: 'frontend',
|
|
123
|
+
});
|
|
124
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
125
|
+
const result = await handleGenerateExecutionPlan({
|
|
126
|
+
specId: 'SPEC-001',
|
|
127
|
+
projectId: 'proj-1',
|
|
128
|
+
});
|
|
129
|
+
const data = JSON.parse(result.content[1].text);
|
|
130
|
+
const phaseNames = data.phases.map((p) => p.name);
|
|
131
|
+
expect(phaseNames).not.toContain('Data Layer');
|
|
132
|
+
expect(phaseNames).not.toContain('Business Logic & API');
|
|
133
|
+
expect(phaseNames).toContain('UI Implementation');
|
|
134
|
+
});
|
|
135
|
+
it('should include config update step for architectural scope', async () => {
|
|
136
|
+
mockGetSpec.mockResolvedValue({
|
|
137
|
+
...baseSpec, scope: 'architectural',
|
|
138
|
+
});
|
|
139
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
140
|
+
const result = await handleGenerateExecutionPlan({
|
|
141
|
+
specId: 'SPEC-001',
|
|
142
|
+
projectId: 'proj-1',
|
|
143
|
+
});
|
|
144
|
+
const data = JSON.parse(result.content[1].text);
|
|
145
|
+
const setupPhase = data.phases.find((p) => p.name === 'Setup & Scaffolding');
|
|
146
|
+
const hasConfigStep = setupPhase.steps.some((s) => s.title.includes('configuration'));
|
|
147
|
+
expect(hasConfigStep).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
it('should include type definitions step for typescript', async () => {
|
|
150
|
+
mockGetSpec.mockResolvedValue(baseSpec);
|
|
151
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
152
|
+
const result = await handleGenerateExecutionPlan({
|
|
153
|
+
specId: 'SPEC-001',
|
|
154
|
+
projectId: 'proj-1',
|
|
155
|
+
});
|
|
156
|
+
const data = JSON.parse(result.content[1].text);
|
|
157
|
+
const setupPhase = data.phases.find((p) => p.name === 'Setup & Scaffolding');
|
|
158
|
+
const hasTypeStep = setupPhase.steps.some((s) => s.title.includes('types'));
|
|
159
|
+
expect(hasTypeStep).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
it('should skip integration tests for trivial scope', async () => {
|
|
162
|
+
mockGetSpec.mockResolvedValue({
|
|
163
|
+
...baseSpec, scope: 'trivial', target: 'backend',
|
|
164
|
+
});
|
|
165
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
166
|
+
const result = await handleGenerateExecutionPlan({
|
|
167
|
+
specId: 'SPEC-001',
|
|
168
|
+
projectId: 'proj-1',
|
|
169
|
+
});
|
|
170
|
+
const data = JSON.parse(result.content[1].text);
|
|
171
|
+
const testPhase = data.phases.find((p) => p.name === 'Testing & Verification');
|
|
172
|
+
const hasIntegration = testPhase.steps.some((s) => s.title.includes('integration'));
|
|
173
|
+
expect(hasIntegration).toBe(false);
|
|
174
|
+
});
|
|
175
|
+
it('should use next.js page file paths for next framework', async () => {
|
|
176
|
+
mockGetSpec.mockResolvedValue(baseSpec);
|
|
177
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
178
|
+
const result = await handleGenerateExecutionPlan({
|
|
179
|
+
specId: 'SPEC-001',
|
|
180
|
+
projectId: 'proj-1',
|
|
181
|
+
});
|
|
182
|
+
const data = JSON.parse(result.content[1].text);
|
|
183
|
+
const uiPhase = data.phases.find((p) => p.name === 'UI Implementation');
|
|
184
|
+
if (uiPhase) {
|
|
185
|
+
const pageStep = uiPhase.steps.find((s) => s.title.includes('page layout'));
|
|
186
|
+
if (pageStep) {
|
|
187
|
+
expect(pageStep.files[0]).toContain('app/');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
// --- Coverage for readSpecContent catch blocks (lines 632-639) ---
|
|
192
|
+
it('should read huPath content when available', async () => {
|
|
193
|
+
mockGetSpec.mockResolvedValue({
|
|
194
|
+
...baseSpec,
|
|
195
|
+
huPath: '/test/hu.md',
|
|
196
|
+
fichaTecnicaPath: null,
|
|
197
|
+
});
|
|
198
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
199
|
+
mockReadFile.mockImplementation(((path) => {
|
|
200
|
+
if (path === '/test/hu.md') {
|
|
201
|
+
return Promise.resolve('validation input form api endpoint route');
|
|
202
|
+
}
|
|
203
|
+
return Promise.reject(new Error('not found'));
|
|
204
|
+
}));
|
|
205
|
+
const result = await handleGenerateExecutionPlan({
|
|
206
|
+
specId: 'SPEC-001',
|
|
207
|
+
projectId: 'proj-1',
|
|
208
|
+
});
|
|
209
|
+
expect(result.isError).toBeUndefined();
|
|
210
|
+
const data = JSON.parse(result.content[1].text);
|
|
211
|
+
expect(data.phases.length).toBeGreaterThan(0);
|
|
212
|
+
});
|
|
213
|
+
it('should read fichaTecnicaPath content when available', async () => {
|
|
214
|
+
mockGetSpec.mockResolvedValue({
|
|
215
|
+
...baseSpec,
|
|
216
|
+
huPath: null,
|
|
217
|
+
fichaTecnicaPath: '/test/ficha.md',
|
|
218
|
+
});
|
|
219
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
220
|
+
mockReadFile.mockImplementation(((path) => {
|
|
221
|
+
if (path === '/test/ficha.md') {
|
|
222
|
+
return Promise.resolve('table schema model entity migration seed fixture sample data');
|
|
223
|
+
}
|
|
224
|
+
return Promise.reject(new Error('not found'));
|
|
225
|
+
}));
|
|
226
|
+
const result = await handleGenerateExecutionPlan({
|
|
227
|
+
specId: 'SPEC-001',
|
|
228
|
+
projectId: 'proj-1',
|
|
229
|
+
});
|
|
230
|
+
expect(result.isError).toBeUndefined();
|
|
231
|
+
const data = JSON.parse(result.content[1].text);
|
|
232
|
+
const dataPhase = data.phases.find((p) => p.name === 'Data Layer');
|
|
233
|
+
expect(dataPhase).toBeDefined();
|
|
234
|
+
});
|
|
235
|
+
it('should handle readFile errors gracefully for both paths', async () => {
|
|
236
|
+
mockGetSpec.mockResolvedValue({
|
|
237
|
+
...baseSpec,
|
|
238
|
+
huPath: '/test/missing-hu.md',
|
|
239
|
+
fichaTecnicaPath: '/test/missing-ficha.md',
|
|
240
|
+
});
|
|
241
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
242
|
+
mockReadFile.mockRejectedValue(new Error('ENOENT'));
|
|
243
|
+
const result = await handleGenerateExecutionPlan({
|
|
244
|
+
specId: 'SPEC-001',
|
|
245
|
+
projectId: 'proj-1',
|
|
246
|
+
});
|
|
247
|
+
expect(result.isError).toBeUndefined();
|
|
248
|
+
});
|
|
249
|
+
// --- Coverage for generateDataLayerPhase with seed data (lines 315-618) ---
|
|
250
|
+
it('should include seed data step when content mentions seed/fixture', async () => {
|
|
251
|
+
mockGetSpec.mockResolvedValue({
|
|
252
|
+
...baseSpec,
|
|
253
|
+
target: 'backend',
|
|
254
|
+
title: 'User management with seed data and sample data',
|
|
255
|
+
tags: ['seed'],
|
|
256
|
+
});
|
|
257
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
258
|
+
const result = await handleGenerateExecutionPlan({
|
|
259
|
+
specId: 'SPEC-001',
|
|
260
|
+
projectId: 'proj-1',
|
|
261
|
+
});
|
|
262
|
+
const data = JSON.parse(result.content[1].text);
|
|
263
|
+
const dataPhase = data.phases.find((p) => p.name === 'Data Layer');
|
|
264
|
+
expect(dataPhase).toBeDefined();
|
|
265
|
+
const hasSeed = dataPhase.steps.some((s) => s.title.includes('seed data'));
|
|
266
|
+
expect(hasSeed).toBe(true);
|
|
267
|
+
});
|
|
268
|
+
// --- Coverage for generateBusinessLogicPhase: validation step ---
|
|
269
|
+
it('should include validation step when content mentions validation', async () => {
|
|
270
|
+
mockGetSpec.mockResolvedValue({
|
|
271
|
+
...baseSpec,
|
|
272
|
+
target: 'backend',
|
|
273
|
+
title: 'User registration validation input form',
|
|
274
|
+
tags: ['validation'],
|
|
275
|
+
});
|
|
276
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
277
|
+
const result = await handleGenerateExecutionPlan({
|
|
278
|
+
specId: 'SPEC-001',
|
|
279
|
+
projectId: 'proj-1',
|
|
280
|
+
});
|
|
281
|
+
const data = JSON.parse(result.content[1].text);
|
|
282
|
+
const logicPhase = data.phases.find((p) => p.name === 'Business Logic & API');
|
|
283
|
+
expect(logicPhase).toBeDefined();
|
|
284
|
+
const hasValidation = logicPhase.steps.some((s) => s.title.includes('validation'));
|
|
285
|
+
expect(hasValidation).toBe(true);
|
|
286
|
+
});
|
|
287
|
+
// --- Coverage for generateBusinessLogicPhase: API endpoints step ---
|
|
288
|
+
it('should include API endpoints step when content mentions api/endpoint/route', async () => {
|
|
289
|
+
mockGetSpec.mockResolvedValue({
|
|
290
|
+
...baseSpec,
|
|
291
|
+
target: 'backend',
|
|
292
|
+
title: 'REST api endpoint route handler',
|
|
293
|
+
tags: ['api'],
|
|
294
|
+
});
|
|
295
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
296
|
+
const result = await handleGenerateExecutionPlan({
|
|
297
|
+
specId: 'SPEC-001',
|
|
298
|
+
projectId: 'proj-1',
|
|
299
|
+
});
|
|
300
|
+
const data = JSON.parse(result.content[1].text);
|
|
301
|
+
const logicPhase = data.phases.find((p) => p.name === 'Business Logic & API');
|
|
302
|
+
const hasApiEndpoints = logicPhase.steps.some((s) => s.title.includes('API endpoints'));
|
|
303
|
+
expect(hasApiEndpoints).toBe(true);
|
|
304
|
+
});
|
|
305
|
+
// --- Coverage for generateUIPhase: form handling step ---
|
|
306
|
+
it('should include form handling step when UI content mentions form/create/edit', async () => {
|
|
307
|
+
mockGetSpec.mockResolvedValue({
|
|
308
|
+
...baseSpec,
|
|
309
|
+
target: 'frontend',
|
|
310
|
+
title: 'User form create edit input submission',
|
|
311
|
+
tags: ['form'],
|
|
312
|
+
});
|
|
313
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
314
|
+
const result = await handleGenerateExecutionPlan({
|
|
315
|
+
specId: 'SPEC-001',
|
|
316
|
+
projectId: 'proj-1',
|
|
317
|
+
});
|
|
318
|
+
const data = JSON.parse(result.content[1].text);
|
|
319
|
+
const uiPhase = data.phases.find((p) => p.name === 'UI Implementation');
|
|
320
|
+
expect(uiPhase).toBeDefined();
|
|
321
|
+
const hasFormHandling = uiPhase.steps.some((s) => s.title.includes('form handling'));
|
|
322
|
+
expect(hasFormHandling).toBe(true);
|
|
323
|
+
});
|
|
324
|
+
// --- Coverage for generateTestingPhase: E2E tests for frontend/fullstack ---
|
|
325
|
+
it('should include E2E tests for frontend spec', async () => {
|
|
326
|
+
mockGetSpec.mockResolvedValue({
|
|
327
|
+
...baseSpec,
|
|
328
|
+
target: 'frontend',
|
|
329
|
+
});
|
|
330
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
331
|
+
const result = await handleGenerateExecutionPlan({
|
|
332
|
+
specId: 'SPEC-001',
|
|
333
|
+
projectId: 'proj-1',
|
|
334
|
+
});
|
|
335
|
+
const data = JSON.parse(result.content[1].text);
|
|
336
|
+
const testPhase = data.phases.find((p) => p.name === 'Testing & Verification');
|
|
337
|
+
const hasE2E = testPhase.steps.some((s) => s.title.includes('E2E'));
|
|
338
|
+
expect(hasE2E).toBe(true);
|
|
339
|
+
});
|
|
340
|
+
// --- Coverage for inferPageFiles: nuxt framework ---
|
|
341
|
+
it('should use nuxt page paths for nuxt framework', async () => {
|
|
342
|
+
mockGetSpec.mockResolvedValue({
|
|
343
|
+
...baseSpec,
|
|
344
|
+
target: 'frontend',
|
|
345
|
+
});
|
|
346
|
+
mockGetKnowledge.mockResolvedValue({
|
|
347
|
+
...baseKnowledge,
|
|
348
|
+
framework: 'nuxt',
|
|
349
|
+
});
|
|
350
|
+
const result = await handleGenerateExecutionPlan({
|
|
351
|
+
specId: 'SPEC-001',
|
|
352
|
+
projectId: 'proj-1',
|
|
353
|
+
});
|
|
354
|
+
const data = JSON.parse(result.content[1].text);
|
|
355
|
+
const uiPhase = data.phases.find((p) => p.name === 'UI Implementation');
|
|
356
|
+
const pageStep = uiPhase?.steps.find((s) => s.title.includes('page layout'));
|
|
357
|
+
if (pageStep) {
|
|
358
|
+
expect(pageStep.files[0]).toContain('pages/');
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
// --- Coverage for inferPageFiles: generic framework (not next/nuxt) ---
|
|
362
|
+
it('should use generic page paths for unknown framework', async () => {
|
|
363
|
+
mockGetSpec.mockResolvedValue({
|
|
364
|
+
...baseSpec,
|
|
365
|
+
target: 'frontend',
|
|
366
|
+
});
|
|
367
|
+
mockGetKnowledge.mockResolvedValue({
|
|
368
|
+
...baseKnowledge,
|
|
369
|
+
framework: 'react',
|
|
370
|
+
});
|
|
371
|
+
const result = await handleGenerateExecutionPlan({
|
|
372
|
+
specId: 'SPEC-001',
|
|
373
|
+
projectId: 'proj-1',
|
|
374
|
+
});
|
|
375
|
+
const data = JSON.parse(result.content[1].text);
|
|
376
|
+
const uiPhase = data.phases.find((p) => p.name === 'UI Implementation');
|
|
377
|
+
const pageStep = uiPhase?.steps.find((s) => s.title.includes('page layout'));
|
|
378
|
+
if (pageStep) {
|
|
379
|
+
expect(pageStep.files[0]).toContain('src/pages/');
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
// --- Coverage for inferComponentFiles: vue extension ---
|
|
383
|
+
it('should use .vue extension for vue components', async () => {
|
|
384
|
+
mockGetSpec.mockResolvedValue({
|
|
385
|
+
...baseSpec,
|
|
386
|
+
target: 'frontend',
|
|
387
|
+
});
|
|
388
|
+
mockGetKnowledge.mockResolvedValue({
|
|
389
|
+
...baseKnowledge,
|
|
390
|
+
framework: 'vue',
|
|
391
|
+
});
|
|
392
|
+
const result = await handleGenerateExecutionPlan({
|
|
393
|
+
specId: 'SPEC-001',
|
|
394
|
+
projectId: 'proj-1',
|
|
395
|
+
});
|
|
396
|
+
const data = JSON.parse(result.content[1].text);
|
|
397
|
+
const uiPhase = data.phases.find((p) => p.name === 'UI Implementation');
|
|
398
|
+
const componentStep = uiPhase?.steps.find((s) => s.title.includes('UI components'));
|
|
399
|
+
if (componentStep) {
|
|
400
|
+
expect(componentStep.files[0]).toContain('.vue');
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
// --- Coverage for inferApiFiles: trpc type ---
|
|
404
|
+
it('should use trpc router paths for trpc API type', async () => {
|
|
405
|
+
mockGetSpec.mockResolvedValue({
|
|
406
|
+
...baseSpec,
|
|
407
|
+
target: 'backend',
|
|
408
|
+
title: 'API endpoint route',
|
|
409
|
+
tags: ['api'],
|
|
410
|
+
});
|
|
411
|
+
mockGetKnowledge.mockResolvedValue({
|
|
412
|
+
...baseKnowledge,
|
|
413
|
+
apiContracts: [{ type: 'trpc' }],
|
|
414
|
+
});
|
|
415
|
+
const result = await handleGenerateExecutionPlan({
|
|
416
|
+
specId: 'SPEC-001',
|
|
417
|
+
projectId: 'proj-1',
|
|
418
|
+
});
|
|
419
|
+
const data = JSON.parse(result.content[1].text);
|
|
420
|
+
const logicPhase = data.phases.find((p) => p.name === 'Business Logic & API');
|
|
421
|
+
const apiStep = logicPhase?.steps.find((s) => s.title.includes('API endpoints'));
|
|
422
|
+
if (apiStep) {
|
|
423
|
+
expect(apiStep.files[0]).toContain('src/server/routers');
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
// --- Coverage for inferDataLayerFiles: no infrastructure layer ---
|
|
427
|
+
it('should use default src path when no infrastructure layer exists', async () => {
|
|
428
|
+
mockGetSpec.mockResolvedValue({
|
|
429
|
+
...baseSpec,
|
|
430
|
+
target: 'backend',
|
|
431
|
+
title: 'table schema model entity',
|
|
432
|
+
tags: [],
|
|
433
|
+
});
|
|
434
|
+
mockGetKnowledge.mockResolvedValue({
|
|
435
|
+
...baseKnowledge,
|
|
436
|
+
architecture: {
|
|
437
|
+
primary: 'monolith',
|
|
438
|
+
secondary: [],
|
|
439
|
+
layers: [], // no layers defined
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
const result = await handleGenerateExecutionPlan({
|
|
443
|
+
specId: 'SPEC-001',
|
|
444
|
+
projectId: 'proj-1',
|
|
445
|
+
});
|
|
446
|
+
const data = JSON.parse(result.content[1].text);
|
|
447
|
+
const dataPhase = data.phases.find((p) => p.name === 'Data Layer');
|
|
448
|
+
expect(dataPhase).toBeDefined();
|
|
449
|
+
});
|
|
450
|
+
// --- Coverage for database-only spec ---
|
|
451
|
+
it('should generate data layer for database-only spec', async () => {
|
|
452
|
+
mockGetSpec.mockResolvedValue({
|
|
453
|
+
...baseSpec,
|
|
454
|
+
target: 'database',
|
|
455
|
+
title: 'Schema migration',
|
|
456
|
+
tags: [],
|
|
457
|
+
});
|
|
458
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
459
|
+
const result = await handleGenerateExecutionPlan({
|
|
460
|
+
specId: 'SPEC-001',
|
|
461
|
+
projectId: 'proj-1',
|
|
462
|
+
});
|
|
463
|
+
const data = JSON.parse(result.content[1].text);
|
|
464
|
+
const phaseNames = data.phases.map((p) => p.name);
|
|
465
|
+
expect(phaseNames).toContain('Data Layer');
|
|
466
|
+
// No UI for database spec
|
|
467
|
+
expect(phaseNames).not.toContain('UI Implementation');
|
|
468
|
+
});
|
|
469
|
+
// --- Coverage for data layer without migration keywords (no schema/table/model) ---
|
|
470
|
+
it('should still generate data layer with repository when database is known even without keywords', async () => {
|
|
471
|
+
mockGetSpec.mockResolvedValue({
|
|
472
|
+
...baseSpec,
|
|
473
|
+
target: 'backend',
|
|
474
|
+
title: 'Simple backend service',
|
|
475
|
+
tags: [],
|
|
476
|
+
});
|
|
477
|
+
mockGetKnowledge.mockResolvedValue({
|
|
478
|
+
...baseKnowledge,
|
|
479
|
+
database: 'postgresql',
|
|
480
|
+
});
|
|
481
|
+
const result = await handleGenerateExecutionPlan({
|
|
482
|
+
specId: 'SPEC-001',
|
|
483
|
+
projectId: 'proj-1',
|
|
484
|
+
});
|
|
485
|
+
const data = JSON.parse(result.content[1].text);
|
|
486
|
+
const dataPhase = data.phases.find((p) => p.name === 'Data Layer');
|
|
487
|
+
expect(dataPhase).toBeDefined();
|
|
488
|
+
const hasRepo = dataPhase.steps.some((s) => s.title.includes('data access'));
|
|
489
|
+
expect(hasRepo).toBe(true);
|
|
490
|
+
});
|
|
491
|
+
// --- Coverage for non-typescript language (no types step) ---
|
|
492
|
+
it('should skip types step for non-typescript language', async () => {
|
|
493
|
+
mockGetSpec.mockResolvedValue({
|
|
494
|
+
...baseSpec,
|
|
495
|
+
target: 'backend',
|
|
496
|
+
});
|
|
497
|
+
mockGetKnowledge.mockResolvedValue({
|
|
498
|
+
...baseKnowledge,
|
|
499
|
+
language: 'python',
|
|
500
|
+
});
|
|
501
|
+
const result = await handleGenerateExecutionPlan({
|
|
502
|
+
specId: 'SPEC-001',
|
|
503
|
+
projectId: 'proj-1',
|
|
504
|
+
});
|
|
505
|
+
const data = JSON.parse(result.content[1].text);
|
|
506
|
+
const setupPhase = data.phases.find((p) => p.name === 'Setup & Scaffolding');
|
|
507
|
+
const hasTypeStep = setupPhase.steps.some((s) => s.title.includes('types'));
|
|
508
|
+
expect(hasTypeStep).toBe(false);
|
|
509
|
+
});
|
|
510
|
+
// --- Coverage for findParallelizable: groups with shared dependencies ---
|
|
511
|
+
it('should find parallelizable step groups', async () => {
|
|
512
|
+
mockGetSpec.mockResolvedValue({
|
|
513
|
+
...baseSpec,
|
|
514
|
+
target: 'fullstack',
|
|
515
|
+
scope: 'architectural',
|
|
516
|
+
});
|
|
517
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
518
|
+
const result = await handleGenerateExecutionPlan({
|
|
519
|
+
specId: 'SPEC-001',
|
|
520
|
+
projectId: 'proj-1',
|
|
521
|
+
});
|
|
522
|
+
const data = JSON.parse(result.content[1].text);
|
|
523
|
+
// parallelizable groups are arrays of step titles that can run in parallel
|
|
524
|
+
expect(data.parallelizable).toBeDefined();
|
|
525
|
+
expect(data.summary.parallelizableGroups).toBeDefined();
|
|
526
|
+
});
|
|
527
|
+
// --- Coverage for cross-module scope config step ---
|
|
528
|
+
it('should include config step for cross-module scope', async () => {
|
|
529
|
+
mockGetSpec.mockResolvedValue({
|
|
530
|
+
...baseSpec,
|
|
531
|
+
scope: 'cross-module',
|
|
532
|
+
});
|
|
533
|
+
mockGetKnowledge.mockResolvedValue(baseKnowledge);
|
|
534
|
+
const result = await handleGenerateExecutionPlan({
|
|
535
|
+
specId: 'SPEC-001',
|
|
536
|
+
projectId: 'proj-1',
|
|
537
|
+
});
|
|
538
|
+
const data = JSON.parse(result.content[1].text);
|
|
539
|
+
const setupPhase = data.phases.find((p) => p.name === 'Setup & Scaffolding');
|
|
540
|
+
const hasConfigStep = setupPhase.steps.some((s) => s.title.includes('configuration'));
|
|
541
|
+
expect(hasConfigStep).toBe(true);
|
|
542
|
+
});
|
|
543
|
+
// --- Coverage for inferApiFiles without apiContracts ---
|
|
544
|
+
it('should default to rest routes when no apiContracts defined', async () => {
|
|
545
|
+
mockGetSpec.mockResolvedValue({
|
|
546
|
+
...baseSpec,
|
|
547
|
+
target: 'backend',
|
|
548
|
+
title: 'api endpoint route',
|
|
549
|
+
tags: ['api'],
|
|
550
|
+
});
|
|
551
|
+
mockGetKnowledge.mockResolvedValue({
|
|
552
|
+
...baseKnowledge,
|
|
553
|
+
apiContracts: [],
|
|
554
|
+
});
|
|
555
|
+
const result = await handleGenerateExecutionPlan({
|
|
556
|
+
specId: 'SPEC-001',
|
|
557
|
+
projectId: 'proj-1',
|
|
558
|
+
});
|
|
559
|
+
const data = JSON.parse(result.content[1].text);
|
|
560
|
+
const logicPhase = data.phases.find((p) => p.name === 'Business Logic & API');
|
|
561
|
+
const apiStep = logicPhase?.steps.find((s) => s.title.includes('API endpoints'));
|
|
562
|
+
if (apiStep) {
|
|
563
|
+
expect(apiStep.files[0]).toContain('src/routes');
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
// --- Coverage for linting step with no detected linters ---
|
|
567
|
+
it('should default to eslint in linting step when no linters detected', async () => {
|
|
568
|
+
mockGetSpec.mockResolvedValue({
|
|
569
|
+
...baseSpec,
|
|
570
|
+
target: 'backend',
|
|
571
|
+
});
|
|
572
|
+
mockGetKnowledge.mockResolvedValue({
|
|
573
|
+
...baseKnowledge,
|
|
574
|
+
linting: { detectedLinters: [] },
|
|
575
|
+
});
|
|
576
|
+
const result = await handleGenerateExecutionPlan({
|
|
577
|
+
specId: 'SPEC-001',
|
|
578
|
+
projectId: 'proj-1',
|
|
579
|
+
});
|
|
580
|
+
const data = JSON.parse(result.content[1].text);
|
|
581
|
+
const integrationPhase = data.phases.find((p) => p.name === 'Integration & Cleanup');
|
|
582
|
+
const lintStep = integrationPhase?.steps.find((s) => s.title.includes('linting'));
|
|
583
|
+
expect(lintStep).toBeDefined();
|
|
584
|
+
expect(lintStep.verification).toContain('eslint');
|
|
585
|
+
});
|
|
586
|
+
// --- Coverage for no framework (null) ---
|
|
587
|
+
it('should handle null framework', async () => {
|
|
588
|
+
mockGetSpec.mockResolvedValue({
|
|
589
|
+
...baseSpec,
|
|
590
|
+
target: 'frontend',
|
|
591
|
+
});
|
|
592
|
+
mockGetKnowledge.mockResolvedValue({
|
|
593
|
+
...baseKnowledge,
|
|
594
|
+
framework: null,
|
|
595
|
+
});
|
|
596
|
+
const result = await handleGenerateExecutionPlan({
|
|
597
|
+
specId: 'SPEC-001',
|
|
598
|
+
projectId: 'proj-1',
|
|
599
|
+
});
|
|
600
|
+
expect(result.isError).toBeUndefined();
|
|
601
|
+
const data = JSON.parse(result.content[1].text);
|
|
602
|
+
const uiPhase = data.phases.find((p) => p.name === 'UI Implementation');
|
|
603
|
+
expect(uiPhase).toBeDefined();
|
|
604
|
+
});
|
|
605
|
+
// --- Coverage for javascript language (should also get types step) ---
|
|
606
|
+
it('should include types step for javascript language', async () => {
|
|
607
|
+
mockGetSpec.mockResolvedValue(baseSpec);
|
|
608
|
+
mockGetKnowledge.mockResolvedValue({
|
|
609
|
+
...baseKnowledge,
|
|
610
|
+
language: 'javascript',
|
|
611
|
+
});
|
|
612
|
+
const result = await handleGenerateExecutionPlan({
|
|
613
|
+
specId: 'SPEC-001',
|
|
614
|
+
projectId: 'proj-1',
|
|
615
|
+
});
|
|
616
|
+
const data = JSON.parse(result.content[1].text);
|
|
617
|
+
const setupPhase = data.phases.find((p) => p.name === 'Setup & Scaffolding');
|
|
618
|
+
const hasTypeStep = setupPhase.steps.some((s) => s.title.includes('types'));
|
|
619
|
+
expect(hasTypeStep).toBe(true);
|
|
620
|
+
});
|
|
621
|
+
// --- Coverage for null buildCommand and testCommand ---
|
|
622
|
+
it('should use defaults when buildCommand and testCommand are null', async () => {
|
|
623
|
+
mockGetSpec.mockResolvedValue({
|
|
624
|
+
...baseSpec,
|
|
625
|
+
target: 'backend',
|
|
626
|
+
});
|
|
627
|
+
mockGetKnowledge.mockResolvedValue({
|
|
628
|
+
...baseKnowledge,
|
|
629
|
+
buildCommand: null,
|
|
630
|
+
testCommand: null,
|
|
631
|
+
});
|
|
632
|
+
const result = await handleGenerateExecutionPlan({
|
|
633
|
+
specId: 'SPEC-001',
|
|
634
|
+
projectId: 'proj-1',
|
|
635
|
+
});
|
|
636
|
+
const data = JSON.parse(result.content[1].text);
|
|
637
|
+
const integrationPhase = data.phases.find((p) => p.name === 'Integration & Cleanup');
|
|
638
|
+
const buildStep = integrationPhase?.steps.find((s) => s.title.includes('Full build'));
|
|
639
|
+
expect(buildStep.verification).toContain('npm run build');
|
|
640
|
+
expect(buildStep.verification).toContain('npm test');
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
//# sourceMappingURL=generate-execution-plan.test.js.map
|