@planu/cli 0.88.1 → 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 +5 -2
- 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/convention-scanner/codebase-scanner.js +2 -2
- package/dist/engine/convention-scanner/codebase-scanner.js.map +1 -1
- package/dist/engine/conventions-cache.d.ts +6 -0
- package/dist/engine/conventions-cache.d.ts.map +1 -0
- package/dist/engine/conventions-cache.js +20 -0
- package/dist/engine/conventions-cache.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 +10 -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.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- 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/lessons-store.d.ts +10 -0
- package/dist/storage/lessons-store.d.ts.map +1 -0
- package/dist/storage/lessons-store.js +67 -0
- package/dist/storage/lessons-store.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/lessons-injector.d.ts +6 -0
- package/dist/tools/create-spec/lessons-injector.d.ts.map +1 -0
- package/dist/tools/create-spec/lessons-injector.js +53 -0
- package/dist/tools/create-spec/lessons-injector.js.map +1 -0
- package/dist/tools/create-spec.d.ts.map +1 -1
- package/dist/tools/create-spec.js +6 -1
- package/dist/tools/create-spec.js.map +1 -1
- 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 +27 -364
- 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/result-builder.d.ts.map +1 -1
- package/dist/tools/init-project/result-builder.js +1 -0
- package/dist/tools/init-project/result-builder.js.map +1 -1
- 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/lessons-handler.d.ts +6 -0
- package/dist/tools/lessons-handler.d.ts.map +1 -0
- package/dist/tools/lessons-handler.js +64 -0
- package/dist/tools/lessons-handler.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-lessons-tools.d.ts +3 -0
- package/dist/tools/register-lessons-tools.d.ts.map +1 -0
- package/dist/tools/register-lessons-tools.js +62 -0
- package/dist/tools/register-lessons-tools.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 -461
- 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 +18 -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/conventions.d.ts +5 -0
- package/dist/types/conventions.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/lessons.d.ts +50 -0
- package/dist/types/lessons.d.ts.map +1 -0
- package/dist/types/lessons.js +3 -0
- package/dist/types/lessons.js.map +1 -0
- package/dist/types/project/planu-config.d.ts +2 -0
- package/dist/types/project/planu-config.d.ts.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 +5 -2
- 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,961 @@
|
|
|
1
|
+
// SpecForge — Documentation Generator Engine Tests
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { generateDocs, generateDocument, generateDiagram } from './doc-generator.js';
|
|
4
|
+
// === Helper factories ===
|
|
5
|
+
function makeKnowledge(overrides = {}) {
|
|
6
|
+
return {
|
|
7
|
+
projectId: 'proj-1',
|
|
8
|
+
projectPath: '/home/user/my-project',
|
|
9
|
+
locale: 'en',
|
|
10
|
+
experienceLevel: 'intermediate',
|
|
11
|
+
language: 'typescript',
|
|
12
|
+
framework: 'express',
|
|
13
|
+
packageManager: 'npm',
|
|
14
|
+
buildCommand: 'npm run build',
|
|
15
|
+
testCommand: 'npm test',
|
|
16
|
+
stack: ['typescript', 'express', 'postgresql'],
|
|
17
|
+
database: 'postgresql',
|
|
18
|
+
architecture: {
|
|
19
|
+
primary: 'layered',
|
|
20
|
+
secondary: ['clean-architecture'],
|
|
21
|
+
layers: [
|
|
22
|
+
{
|
|
23
|
+
name: 'API',
|
|
24
|
+
directories: ['src/routes'],
|
|
25
|
+
responsibility: 'HTTP handling',
|
|
26
|
+
dependsOn: ['Service'],
|
|
27
|
+
neverDependsOn: ['Database'],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'Service',
|
|
31
|
+
directories: ['src/services'],
|
|
32
|
+
responsibility: 'Business logic',
|
|
33
|
+
dependsOn: ['Database'],
|
|
34
|
+
neverDependsOn: [],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'Database',
|
|
38
|
+
directories: ['src/db'],
|
|
39
|
+
responsibility: 'Data access',
|
|
40
|
+
dependsOn: [],
|
|
41
|
+
neverDependsOn: ['API'],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
boundaries: [
|
|
45
|
+
{
|
|
46
|
+
name: 'Auth Module',
|
|
47
|
+
directories: ['src/auth'],
|
|
48
|
+
publicApi: ['src/auth/index.ts'],
|
|
49
|
+
internalOnly: ['src/auth/internal.ts'],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
communicationPatterns: ['REST', 'Events'],
|
|
53
|
+
deploymentUnits: ['docker', 'vercel'],
|
|
54
|
+
},
|
|
55
|
+
apps: [
|
|
56
|
+
{ name: 'web', path: 'apps/web', type: 'frontend', language: 'typescript', framework: 'react' },
|
|
57
|
+
{ name: 'api', path: 'apps/api', type: 'backend', language: 'typescript', framework: 'express' },
|
|
58
|
+
],
|
|
59
|
+
conventions: { 'naming-files': 'kebab-case', 'naming-variables': 'camelCase' },
|
|
60
|
+
layers: ['routes', 'services', 'db'],
|
|
61
|
+
environments: ['development', 'staging', 'production'],
|
|
62
|
+
apiContracts: [
|
|
63
|
+
{ type: 'openapi', path: 'openapi.yaml', endpoints: ['GET /users', 'POST /users'] },
|
|
64
|
+
],
|
|
65
|
+
specLocation: 'docs/sdd/specs',
|
|
66
|
+
envSetup: {
|
|
67
|
+
projectId: 'proj-1',
|
|
68
|
+
variables: [
|
|
69
|
+
{ name: 'DATABASE_URL', service: 'PostgreSQL', required: true, sensitive: true, description: 'DB conn string', howToGet: 'Create DB', environments: ['development'] },
|
|
70
|
+
{ name: 'PORT', service: 'App', required: false, sensitive: false, description: 'Port', howToGet: 'Set port', environments: ['development'] },
|
|
71
|
+
],
|
|
72
|
+
missing: [],
|
|
73
|
+
security: {
|
|
74
|
+
gitignoreHasEnv: true,
|
|
75
|
+
noSecretsInCode: true,
|
|
76
|
+
noEnvInGit: true,
|
|
77
|
+
noSecretsInLogs: true,
|
|
78
|
+
usesSecretManager: false,
|
|
79
|
+
issues: [
|
|
80
|
+
{ severity: 'warning', issue: 'No secret manager', fix: 'Use Vault or AWS Secrets Manager' },
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
setupSteps: [],
|
|
84
|
+
},
|
|
85
|
+
linting: {
|
|
86
|
+
projectId: 'proj-1',
|
|
87
|
+
language: 'typescript',
|
|
88
|
+
detectedLinters: [],
|
|
89
|
+
missingRecommended: [],
|
|
90
|
+
rulesConflicts: [],
|
|
91
|
+
customRulesFromProject: [],
|
|
92
|
+
maturityScore: 0.5,
|
|
93
|
+
},
|
|
94
|
+
availableMcps: [],
|
|
95
|
+
docsRegistry: {},
|
|
96
|
+
qualityProfile: {
|
|
97
|
+
enabledCategories: ['solid', 'clean-code'],
|
|
98
|
+
customRules: [],
|
|
99
|
+
principles: ['SOLID', 'DRY'],
|
|
100
|
+
strictness: 'standard',
|
|
101
|
+
},
|
|
102
|
+
lastAnalyzed: '2025-01-01T00:00:00Z',
|
|
103
|
+
...overrides,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function makeSpec(overrides = {}) {
|
|
107
|
+
return {
|
|
108
|
+
id: 'SPEC-001',
|
|
109
|
+
title: 'User Authentication',
|
|
110
|
+
slug: 'user-auth',
|
|
111
|
+
type: 'feature',
|
|
112
|
+
scope: 'feature',
|
|
113
|
+
status: 'done',
|
|
114
|
+
difficulty: 3,
|
|
115
|
+
risk: 'medium',
|
|
116
|
+
projectId: 'proj-1',
|
|
117
|
+
createdAt: '2025-01-01T00:00:00Z',
|
|
118
|
+
updatedAt: '2025-01-15T00:00:00Z',
|
|
119
|
+
huPath: '/tmp/HU.md',
|
|
120
|
+
fichaTecnicaPath: '/tmp/FICHA-TECNICA.md',
|
|
121
|
+
estimation: {
|
|
122
|
+
devHours: 8,
|
|
123
|
+
reviewHours: 1.6,
|
|
124
|
+
recommendedModel: 'mixed',
|
|
125
|
+
tokensOpus: 10000,
|
|
126
|
+
tokensSonnet: 20000,
|
|
127
|
+
apiCostUsd: 0.21,
|
|
128
|
+
hourlyRate: 65,
|
|
129
|
+
humanCostUsd: 624,
|
|
130
|
+
totalCostUsd: 624.21,
|
|
131
|
+
tokenOptimization: { mode: 'local', reasoning: 'test', estimatedTokens: 15000, savings: '~50%' },
|
|
132
|
+
},
|
|
133
|
+
actuals: { devHours: 8, reviewHours: 2, tokensOpus: 10000, tokensSonnet: 20000, apiCostUsd: 0.21, humanCostUsd: 650, totalCostUsd: 650.21, completedAt: '2025-01-15T00:00:00Z', notes: 'done' },
|
|
134
|
+
target: 'backend',
|
|
135
|
+
tags: ['auth'],
|
|
136
|
+
dependencies: [],
|
|
137
|
+
blockedBy: [],
|
|
138
|
+
gitBranch: 'feat/auth',
|
|
139
|
+
impactAnalysis: null,
|
|
140
|
+
...overrides,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
// === Tests for generateDocs ===
|
|
144
|
+
describe('generateDocs', () => {
|
|
145
|
+
it('generates documents for multiple types', () => {
|
|
146
|
+
const knowledge = makeKnowledge();
|
|
147
|
+
const specs = [makeSpec()];
|
|
148
|
+
const result = generateDocs(['readme', 'setup-guide'], knowledge, specs);
|
|
149
|
+
expect(result.documents).toHaveLength(2);
|
|
150
|
+
expect(result.message).toContain('2 document(s)');
|
|
151
|
+
expect(result.message).toContain('readme, setup-guide');
|
|
152
|
+
});
|
|
153
|
+
it('generates a single document', () => {
|
|
154
|
+
const knowledge = makeKnowledge();
|
|
155
|
+
const result = generateDocs(['readme'], knowledge);
|
|
156
|
+
expect(result.documents).toHaveLength(1);
|
|
157
|
+
expect(result.message).toContain('1 document(s)');
|
|
158
|
+
});
|
|
159
|
+
it('defaults to empty specs and developer audience', () => {
|
|
160
|
+
const knowledge = makeKnowledge();
|
|
161
|
+
const result = generateDocs(['faq'], knowledge);
|
|
162
|
+
expect(result.documents).toHaveLength(1);
|
|
163
|
+
expect(result.documents[0].audience).toBe('developer');
|
|
164
|
+
});
|
|
165
|
+
it('handles empty types array', () => {
|
|
166
|
+
const knowledge = makeKnowledge();
|
|
167
|
+
const result = generateDocs([], knowledge, []);
|
|
168
|
+
expect(result.documents).toHaveLength(0);
|
|
169
|
+
expect(result.message).toContain('0 document(s)');
|
|
170
|
+
});
|
|
171
|
+
it('generates all 14 document types', () => {
|
|
172
|
+
const knowledge = makeKnowledge();
|
|
173
|
+
const specs = [makeSpec()];
|
|
174
|
+
const allTypes = [
|
|
175
|
+
'user-guide', 'api-reference', 'readme', 'setup-guide',
|
|
176
|
+
'changelog', 'onboarding', 'faq', 'architecture-doc',
|
|
177
|
+
'deployment-guide', 'database-doc', 'help-articles',
|
|
178
|
+
'release-notes', 'runbook', 'security-doc',
|
|
179
|
+
];
|
|
180
|
+
const result = generateDocs([...allTypes], knowledge, specs);
|
|
181
|
+
expect(result.documents).toHaveLength(14);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
// === Tests for generateDocument ===
|
|
185
|
+
describe('generateDocument', () => {
|
|
186
|
+
describe('unsupported type', () => {
|
|
187
|
+
it('returns fallback for unknown type', () => {
|
|
188
|
+
const knowledge = makeKnowledge();
|
|
189
|
+
const doc = generateDocument('unknown-type', knowledge, [], 'developer', 'en');
|
|
190
|
+
expect(doc.title).toContain('Unsupported');
|
|
191
|
+
expect(doc.content).toContain('not yet supported');
|
|
192
|
+
expect(doc.sections).toEqual([]);
|
|
193
|
+
expect(doc.diagrams).toEqual([]);
|
|
194
|
+
expect(doc.relatedSpecs).toEqual([]);
|
|
195
|
+
expect(doc.audience).toBe('developer');
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe('readme', () => {
|
|
199
|
+
it('generates readme with project name from path', () => {
|
|
200
|
+
const knowledge = makeKnowledge();
|
|
201
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
202
|
+
expect(doc.type).toBe('readme');
|
|
203
|
+
expect(doc.title).toContain('my-project');
|
|
204
|
+
expect(doc.path).toBe('README.md');
|
|
205
|
+
expect(doc.content).toContain('typescript');
|
|
206
|
+
expect(doc.content).toContain('express');
|
|
207
|
+
expect(doc.sections.length).toBeGreaterThanOrEqual(5);
|
|
208
|
+
});
|
|
209
|
+
it('handles project path with no trailing slash', () => {
|
|
210
|
+
const knowledge = makeKnowledge({ projectPath: '/single' });
|
|
211
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
212
|
+
expect(doc.title).toContain('single');
|
|
213
|
+
});
|
|
214
|
+
it('includes tech stack with framework, database, package manager', () => {
|
|
215
|
+
const knowledge = makeKnowledge();
|
|
216
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
217
|
+
expect(doc.content).toContain('Framework');
|
|
218
|
+
expect(doc.content).toContain('express');
|
|
219
|
+
expect(doc.content).toContain('Database');
|
|
220
|
+
expect(doc.content).toContain('postgresql');
|
|
221
|
+
expect(doc.content).toContain('Package Manager');
|
|
222
|
+
expect(doc.content).toContain('npm');
|
|
223
|
+
});
|
|
224
|
+
it('omits framework if null', () => {
|
|
225
|
+
const knowledge = makeKnowledge({ framework: null });
|
|
226
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
227
|
+
// Intro should not have "built with"
|
|
228
|
+
expect(doc.sections[0].content).not.toContain('built with');
|
|
229
|
+
});
|
|
230
|
+
it('omits database if unknown', () => {
|
|
231
|
+
const knowledge = makeKnowledge({ database: 'unknown' });
|
|
232
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
233
|
+
expect(doc.sections[0].content).not.toContain('Uses unknown');
|
|
234
|
+
});
|
|
235
|
+
it('omits packageManager if null', () => {
|
|
236
|
+
const knowledge = makeKnowledge({ packageManager: null });
|
|
237
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
238
|
+
// tech stack section should not contain Package Manager
|
|
239
|
+
const techSection = doc.sections.find((s) => s.title === 'Tech Stack');
|
|
240
|
+
expect(techSection.content).not.toContain('Package Manager');
|
|
241
|
+
});
|
|
242
|
+
it('includes getting started with install, build, test commands', () => {
|
|
243
|
+
const knowledge = makeKnowledge();
|
|
244
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
245
|
+
expect(doc.content).toContain('npm install');
|
|
246
|
+
expect(doc.content).toContain('npm run build');
|
|
247
|
+
expect(doc.content).toContain('npm test');
|
|
248
|
+
});
|
|
249
|
+
it('omits build and test commands if null', () => {
|
|
250
|
+
const knowledge = makeKnowledge({ buildCommand: null, testCommand: null });
|
|
251
|
+
const doc = generateDocument('readme', knowledge, [], 'developer', 'en');
|
|
252
|
+
const devSection = doc.sections.find((s) => s.title === 'Development');
|
|
253
|
+
expect(devSection.content).not.toContain('Build');
|
|
254
|
+
expect(devSection.content).not.toContain('Test');
|
|
255
|
+
});
|
|
256
|
+
it('sets audience from parameter', () => {
|
|
257
|
+
const knowledge = makeKnowledge();
|
|
258
|
+
const doc = generateDocument('readme', knowledge, [], 'ops', 'en');
|
|
259
|
+
expect(doc.audience).toBe('ops');
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
describe('setup-guide', () => {
|
|
263
|
+
it('generates setup guide with all sections', () => {
|
|
264
|
+
const knowledge = makeKnowledge();
|
|
265
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
266
|
+
expect(doc.type).toBe('setup-guide');
|
|
267
|
+
expect(doc.path).toBe('docs/setup-guide.md');
|
|
268
|
+
expect(doc.sections.length).toBeGreaterThanOrEqual(6);
|
|
269
|
+
expect(doc.content).toContain('Prerequisites');
|
|
270
|
+
expect(doc.content).toContain('Installation');
|
|
271
|
+
expect(doc.content).toContain('Environment Variables');
|
|
272
|
+
expect(doc.content).toContain('Database Setup');
|
|
273
|
+
expect(doc.content).toContain('Running the Project');
|
|
274
|
+
expect(doc.content).toContain('Verifying Setup');
|
|
275
|
+
});
|
|
276
|
+
it('shows database setup when known', () => {
|
|
277
|
+
const knowledge = makeKnowledge();
|
|
278
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
279
|
+
expect(doc.content).toContain('postgresql');
|
|
280
|
+
});
|
|
281
|
+
it('shows no database message when unknown', () => {
|
|
282
|
+
const knowledge = makeKnowledge({ database: 'unknown' });
|
|
283
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
284
|
+
expect(doc.content).toContain('No database configured');
|
|
285
|
+
});
|
|
286
|
+
it('shows env vars table when variables exist', () => {
|
|
287
|
+
const knowledge = makeKnowledge();
|
|
288
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
289
|
+
expect(doc.content).toContain('DATABASE_URL');
|
|
290
|
+
expect(doc.content).toContain('PostgreSQL');
|
|
291
|
+
expect(doc.content).toContain('Required variables');
|
|
292
|
+
});
|
|
293
|
+
it('shows simple env message when no variables', () => {
|
|
294
|
+
const knowledge = makeKnowledge({
|
|
295
|
+
envSetup: {
|
|
296
|
+
projectId: 'proj-1',
|
|
297
|
+
variables: [],
|
|
298
|
+
missing: [],
|
|
299
|
+
security: { gitignoreHasEnv: true, noSecretsInCode: true, noEnvInGit: true, noSecretsInLogs: true, usesSecretManager: false, issues: [] },
|
|
300
|
+
setupSteps: [],
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
304
|
+
expect(doc.content).toContain('cp .env.example .env');
|
|
305
|
+
});
|
|
306
|
+
it('includes prerequisites for known languages', () => {
|
|
307
|
+
const knowledge = makeKnowledge({ language: 'python' });
|
|
308
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
309
|
+
expect(doc.content).toContain('Python 3.10+');
|
|
310
|
+
});
|
|
311
|
+
it('uses fallback prerequisites for unknown language', () => {
|
|
312
|
+
const knowledge = makeKnowledge({ language: 'haskell' });
|
|
313
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
314
|
+
expect(doc.content).toContain('haskell');
|
|
315
|
+
expect(doc.content).toContain('latest stable');
|
|
316
|
+
});
|
|
317
|
+
it('includes install command for known package managers', () => {
|
|
318
|
+
const knowledge = makeKnowledge({ packageManager: 'pnpm' });
|
|
319
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
320
|
+
expect(doc.content).toContain('pnpm install');
|
|
321
|
+
});
|
|
322
|
+
it('falls back for unknown package manager', () => {
|
|
323
|
+
const knowledge = makeKnowledge({ packageManager: 'mega-pm' });
|
|
324
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
325
|
+
expect(doc.content).toContain('mega-pm install');
|
|
326
|
+
});
|
|
327
|
+
it('handles null packageManager in installation', () => {
|
|
328
|
+
const knowledge = makeKnowledge({ packageManager: null });
|
|
329
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
330
|
+
expect(doc.content).not.toContain('Install dependencies');
|
|
331
|
+
});
|
|
332
|
+
it('renders verify section with build and test commands', () => {
|
|
333
|
+
const knowledge = makeKnowledge();
|
|
334
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
335
|
+
expect(doc.content).toContain('Build succeeds');
|
|
336
|
+
expect(doc.content).toContain('Tests pass');
|
|
337
|
+
});
|
|
338
|
+
it('renders running section with build command replacement', () => {
|
|
339
|
+
const knowledge = makeKnowledge({ buildCommand: 'npm run build' });
|
|
340
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
341
|
+
expect(doc.content).toContain('npm run dev');
|
|
342
|
+
});
|
|
343
|
+
it('renders running section fallback when no build command', () => {
|
|
344
|
+
const knowledge = makeKnowledge({ buildCommand: null });
|
|
345
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
346
|
+
expect(doc.content).toContain('npm run dev');
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
describe('architecture-doc', () => {
|
|
350
|
+
it('generates architecture doc with layers and diagrams', () => {
|
|
351
|
+
const knowledge = makeKnowledge();
|
|
352
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
353
|
+
expect(doc.type).toBe('architecture-doc');
|
|
354
|
+
expect(doc.path).toBe('docs/architecture.md');
|
|
355
|
+
expect(doc.content).toContain('layered');
|
|
356
|
+
expect(doc.content).toContain('API');
|
|
357
|
+
expect(doc.content).toContain('Service');
|
|
358
|
+
expect(doc.content).toContain('Database');
|
|
359
|
+
expect(doc.diagrams).toHaveLength(2);
|
|
360
|
+
});
|
|
361
|
+
it('includes secondary patterns when present', () => {
|
|
362
|
+
const knowledge = makeKnowledge();
|
|
363
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
364
|
+
expect(doc.content).toContain('clean-architecture');
|
|
365
|
+
});
|
|
366
|
+
it('omits secondary patterns line when empty', () => {
|
|
367
|
+
const knowledge = makeKnowledge();
|
|
368
|
+
knowledge.architecture.secondary = [];
|
|
369
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
370
|
+
expect(doc.content).not.toContain('Secondary patterns:');
|
|
371
|
+
});
|
|
372
|
+
it('shows layer dependencies', () => {
|
|
373
|
+
const knowledge = makeKnowledge();
|
|
374
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
375
|
+
expect(doc.content).toContain('Depends on:** Service');
|
|
376
|
+
});
|
|
377
|
+
it('shows foundation layer when no dependencies', () => {
|
|
378
|
+
const knowledge = makeKnowledge();
|
|
379
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
380
|
+
expect(doc.content).toContain('foundation layer');
|
|
381
|
+
});
|
|
382
|
+
it('shows never depends on when present', () => {
|
|
383
|
+
const knowledge = makeKnowledge();
|
|
384
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
385
|
+
expect(doc.content).toContain('NEVER depends on');
|
|
386
|
+
});
|
|
387
|
+
it('includes boundaries section when present', () => {
|
|
388
|
+
const knowledge = makeKnowledge();
|
|
389
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
390
|
+
expect(doc.content).toContain('Module Boundaries');
|
|
391
|
+
expect(doc.content).toContain('Auth Module');
|
|
392
|
+
expect(doc.content).toContain('Public API');
|
|
393
|
+
});
|
|
394
|
+
it('omits boundaries when empty', () => {
|
|
395
|
+
const knowledge = makeKnowledge();
|
|
396
|
+
knowledge.architecture.boundaries = [];
|
|
397
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
398
|
+
expect(doc.content).not.toContain('Module Boundaries');
|
|
399
|
+
});
|
|
400
|
+
it('handles boundary with no public API', () => {
|
|
401
|
+
const knowledge = makeKnowledge();
|
|
402
|
+
knowledge.architecture.boundaries = [
|
|
403
|
+
{ name: 'Utils', directories: ['src/utils'], publicApi: [], internalOnly: [] },
|
|
404
|
+
];
|
|
405
|
+
const doc = generateDocument('architecture-doc', knowledge, [], 'developer', 'en');
|
|
406
|
+
expect(doc.content).toContain('Utils');
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
describe('api-reference', () => {
|
|
410
|
+
it('generates API reference with contracts', () => {
|
|
411
|
+
const knowledge = makeKnowledge();
|
|
412
|
+
const specs = [makeSpec()];
|
|
413
|
+
const doc = generateDocument('api-reference', knowledge, specs, 'developer', 'en');
|
|
414
|
+
expect(doc.type).toBe('api-reference');
|
|
415
|
+
expect(doc.path).toBe('docs/api-reference.md');
|
|
416
|
+
expect(doc.content).toContain('OPENAPI');
|
|
417
|
+
expect(doc.content).toContain('GET /users');
|
|
418
|
+
});
|
|
419
|
+
it('uses framework in overview when present', () => {
|
|
420
|
+
const knowledge = makeKnowledge();
|
|
421
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
422
|
+
expect(doc.content).toContain('express');
|
|
423
|
+
});
|
|
424
|
+
it('falls back to language when no framework', () => {
|
|
425
|
+
const knowledge = makeKnowledge({ framework: null });
|
|
426
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
427
|
+
expect(doc.content).toContain('typescript');
|
|
428
|
+
});
|
|
429
|
+
it('shows no contracts message when empty', () => {
|
|
430
|
+
const knowledge = makeKnowledge({ apiContracts: [] });
|
|
431
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
432
|
+
expect(doc.content).toContain('No formal API contracts detected');
|
|
433
|
+
});
|
|
434
|
+
it('shows endpoint list when contract has endpoints', () => {
|
|
435
|
+
const knowledge = makeKnowledge();
|
|
436
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
437
|
+
expect(doc.content).toContain('Endpoints:');
|
|
438
|
+
});
|
|
439
|
+
it('shows auto-detected message when no endpoints', () => {
|
|
440
|
+
const knowledge = makeKnowledge({
|
|
441
|
+
apiContracts: [{ type: 'rest-informal', endpoints: [] }],
|
|
442
|
+
});
|
|
443
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
444
|
+
expect(doc.content).toContain('auto-detected from code');
|
|
445
|
+
});
|
|
446
|
+
it('filters related specs for backend/fullstack targets', () => {
|
|
447
|
+
const backendSpec = makeSpec({ id: 'SPEC-001', target: 'backend' });
|
|
448
|
+
const frontendSpec = makeSpec({ id: 'SPEC-002', target: 'frontend' });
|
|
449
|
+
const fullstackSpec = makeSpec({ id: 'SPEC-003', target: 'fullstack' });
|
|
450
|
+
const knowledge = makeKnowledge();
|
|
451
|
+
const doc = generateDocument('api-reference', knowledge, [backendSpec, frontendSpec, fullstackSpec], 'developer', 'en');
|
|
452
|
+
expect(doc.relatedSpecs).toContain('SPEC-001');
|
|
453
|
+
expect(doc.relatedSpecs).toContain('SPEC-003');
|
|
454
|
+
expect(doc.relatedSpecs).not.toContain('SPEC-002');
|
|
455
|
+
});
|
|
456
|
+
it('includes contract path when present', () => {
|
|
457
|
+
const knowledge = makeKnowledge();
|
|
458
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
459
|
+
expect(doc.content).toContain('openapi.yaml');
|
|
460
|
+
});
|
|
461
|
+
it('omits contract path when not present', () => {
|
|
462
|
+
const knowledge = makeKnowledge({
|
|
463
|
+
apiContracts: [{ type: 'rest-informal', endpoints: ['GET /health'] }],
|
|
464
|
+
});
|
|
465
|
+
const doc = generateDocument('api-reference', knowledge, [], 'developer', 'en');
|
|
466
|
+
expect(doc.content).not.toContain('Schema:');
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
describe('user-guide', () => {
|
|
470
|
+
it('generates user guide', () => {
|
|
471
|
+
const knowledge = makeKnowledge();
|
|
472
|
+
const specs = [makeSpec()];
|
|
473
|
+
const doc = generateDocument('user-guide', knowledge, specs, 'end-user', 'en');
|
|
474
|
+
expect(doc.type).toBe('user-guide');
|
|
475
|
+
expect(doc.path).toBe('docs/user-guide.md');
|
|
476
|
+
expect(doc.content).toContain('my-project');
|
|
477
|
+
expect(doc.relatedSpecs).toContain('SPEC-001');
|
|
478
|
+
});
|
|
479
|
+
it('shows done specs as features', () => {
|
|
480
|
+
const specs = [makeSpec({ status: 'done' })];
|
|
481
|
+
const knowledge = makeKnowledge();
|
|
482
|
+
const doc = generateDocument('user-guide', knowledge, specs, 'end-user', 'en');
|
|
483
|
+
expect(doc.content).toContain('User Authentication');
|
|
484
|
+
});
|
|
485
|
+
it('shows fallback when no specs', () => {
|
|
486
|
+
const knowledge = makeKnowledge();
|
|
487
|
+
const doc = generateDocument('user-guide', knowledge, [], 'end-user', 'en');
|
|
488
|
+
expect(doc.content).toContain('Feature list will be populated');
|
|
489
|
+
});
|
|
490
|
+
it('filters only done specs for feature list', () => {
|
|
491
|
+
const doneSpec = makeSpec({ id: 'SPEC-001', status: 'done', title: 'Done Feature' });
|
|
492
|
+
const draftSpec = makeSpec({ id: 'SPEC-002', status: 'draft', title: 'Draft Feature' });
|
|
493
|
+
const knowledge = makeKnowledge();
|
|
494
|
+
const doc = generateDocument('user-guide', knowledge, [doneSpec, draftSpec], 'end-user', 'en');
|
|
495
|
+
expect(doc.content).toContain('Done Feature');
|
|
496
|
+
expect(doc.content).not.toContain('Draft Feature');
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
describe('changelog', () => {
|
|
500
|
+
it('generates changelog with categorized specs', () => {
|
|
501
|
+
const done = makeSpec({ status: 'done', type: 'feature' });
|
|
502
|
+
const implementing = makeSpec({ id: 'SPEC-002', status: 'implementing', type: 'bugfix', title: 'Fix Bug' });
|
|
503
|
+
const approved = makeSpec({ id: 'SPEC-003', status: 'approved', type: 'refactor', title: 'Refactor' });
|
|
504
|
+
const knowledge = makeKnowledge();
|
|
505
|
+
const doc = generateDocument('changelog', knowledge, [done, implementing, approved], 'developer', 'en');
|
|
506
|
+
expect(doc.type).toBe('changelog');
|
|
507
|
+
expect(doc.path).toBe('CHANGELOG.md');
|
|
508
|
+
expect(doc.content).toContain('Completed');
|
|
509
|
+
expect(doc.content).toContain('In Progress');
|
|
510
|
+
expect(doc.content).toContain('Planned');
|
|
511
|
+
});
|
|
512
|
+
it('omits sections for empty categories', () => {
|
|
513
|
+
const done = makeSpec({ status: 'done' });
|
|
514
|
+
const knowledge = makeKnowledge();
|
|
515
|
+
const doc = generateDocument('changelog', knowledge, [done], 'developer', 'en');
|
|
516
|
+
expect(doc.content).toContain('Completed');
|
|
517
|
+
expect(doc.content).not.toContain('In Progress');
|
|
518
|
+
expect(doc.content).not.toContain('Planned');
|
|
519
|
+
});
|
|
520
|
+
it('handles empty specs', () => {
|
|
521
|
+
const knowledge = makeKnowledge();
|
|
522
|
+
const doc = generateDocument('changelog', knowledge, [], 'developer', 'en');
|
|
523
|
+
expect(doc.type).toBe('changelog');
|
|
524
|
+
expect(doc.sections).toHaveLength(0);
|
|
525
|
+
});
|
|
526
|
+
it('uses completedAt date if present in actuals', () => {
|
|
527
|
+
const done = makeSpec({
|
|
528
|
+
status: 'done',
|
|
529
|
+
actuals: { completedAt: '2025-06-01', devHours: 5, reviewHours: 1, tokensOpus: 0, tokensSonnet: 0, apiCostUsd: 0, humanCostUsd: 0, totalCostUsd: 0, notes: '' },
|
|
530
|
+
});
|
|
531
|
+
const knowledge = makeKnowledge();
|
|
532
|
+
const doc = generateDocument('changelog', knowledge, [done], 'developer', 'en');
|
|
533
|
+
expect(doc.content).toContain('2025-06-01');
|
|
534
|
+
});
|
|
535
|
+
it('falls back to updatedAt when no actuals', () => {
|
|
536
|
+
const done = makeSpec({ status: 'done', actuals: null, updatedAt: '2025-03-01T00:00:00Z' });
|
|
537
|
+
const knowledge = makeKnowledge();
|
|
538
|
+
const doc = generateDocument('changelog', knowledge, [done], 'developer', 'en');
|
|
539
|
+
expect(doc.content).toContain('2025-03-01');
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
describe('onboarding', () => {
|
|
543
|
+
it('generates onboarding guide', () => {
|
|
544
|
+
const knowledge = makeKnowledge();
|
|
545
|
+
const doc = generateDocument('onboarding', knowledge, [], 'developer', 'en');
|
|
546
|
+
expect(doc.type).toBe('onboarding');
|
|
547
|
+
expect(doc.path).toBe('docs/onboarding.md');
|
|
548
|
+
expect(doc.content).toContain('Welcome');
|
|
549
|
+
expect(doc.content).toContain('typescript');
|
|
550
|
+
expect(doc.content).toContain('express');
|
|
551
|
+
expect(doc.content).toContain('layered');
|
|
552
|
+
});
|
|
553
|
+
it('omits framework when null', () => {
|
|
554
|
+
const knowledge = makeKnowledge({ framework: null });
|
|
555
|
+
const doc = generateDocument('onboarding', knowledge, [], 'developer', 'en');
|
|
556
|
+
expect(doc.content).not.toContain('using **null**');
|
|
557
|
+
});
|
|
558
|
+
it('includes build and test commands in first day setup', () => {
|
|
559
|
+
const knowledge = makeKnowledge();
|
|
560
|
+
const doc = generateDocument('onboarding', knowledge, [], 'developer', 'en');
|
|
561
|
+
expect(doc.content).toContain('npm run build');
|
|
562
|
+
expect(doc.content).toContain('npm test');
|
|
563
|
+
});
|
|
564
|
+
it('omits build/test steps when null', () => {
|
|
565
|
+
const knowledge = makeKnowledge({ buildCommand: null, testCommand: null });
|
|
566
|
+
const doc = generateDocument('onboarding', knowledge, [], 'developer', 'en');
|
|
567
|
+
expect(doc.content).not.toContain('verify the build');
|
|
568
|
+
expect(doc.content).not.toContain('verify tests pass');
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
describe('faq', () => {
|
|
572
|
+
it('generates FAQ', () => {
|
|
573
|
+
const knowledge = makeKnowledge();
|
|
574
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
575
|
+
expect(doc.type).toBe('faq');
|
|
576
|
+
expect(doc.path).toBe('docs/faq.md');
|
|
577
|
+
expect(doc.content).toContain('Frequently Asked Questions');
|
|
578
|
+
expect(doc.content).toContain('typescript');
|
|
579
|
+
});
|
|
580
|
+
it('includes framework in language question', () => {
|
|
581
|
+
const knowledge = makeKnowledge();
|
|
582
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
583
|
+
expect(doc.content).toContain('with express');
|
|
584
|
+
});
|
|
585
|
+
it('omits framework when null', () => {
|
|
586
|
+
const knowledge = makeKnowledge({ framework: null });
|
|
587
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
588
|
+
expect(doc.content).toContain('typescript.');
|
|
589
|
+
});
|
|
590
|
+
it('shows database info when known', () => {
|
|
591
|
+
const knowledge = makeKnowledge();
|
|
592
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
593
|
+
expect(doc.content).toContain('postgresql');
|
|
594
|
+
});
|
|
595
|
+
it('shows no database message when unknown', () => {
|
|
596
|
+
const knowledge = makeKnowledge({ database: 'unknown' });
|
|
597
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
598
|
+
expect(doc.content).toContain('No database is configured yet');
|
|
599
|
+
});
|
|
600
|
+
it('shows test command when present', () => {
|
|
601
|
+
const knowledge = makeKnowledge();
|
|
602
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
603
|
+
expect(doc.content).toContain('npm test');
|
|
604
|
+
});
|
|
605
|
+
it('shows no test command message when null', () => {
|
|
606
|
+
const knowledge = makeKnowledge({ testCommand: null });
|
|
607
|
+
const doc = generateDocument('faq', knowledge, [], 'developer', 'en');
|
|
608
|
+
expect(doc.content).toContain('No test command is configured yet');
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
describe('database-doc', () => {
|
|
612
|
+
it('generates database doc with known database', () => {
|
|
613
|
+
const knowledge = makeKnowledge();
|
|
614
|
+
const doc = generateDocument('database-doc', knowledge, [], 'developer', 'en');
|
|
615
|
+
expect(doc.type).toBe('database-doc');
|
|
616
|
+
expect(doc.path).toBe('docs/database.md');
|
|
617
|
+
expect(doc.content).toContain('postgresql');
|
|
618
|
+
expect(doc.content).toContain('Connection');
|
|
619
|
+
expect(doc.content).toContain('Migrations');
|
|
620
|
+
expect(doc.content).toContain('Schema');
|
|
621
|
+
expect(doc.diagrams).toHaveLength(1);
|
|
622
|
+
});
|
|
623
|
+
it('generates minimal doc when database unknown', () => {
|
|
624
|
+
const knowledge = makeKnowledge({ database: 'unknown' });
|
|
625
|
+
const doc = generateDocument('database-doc', knowledge, [], 'developer', 'en');
|
|
626
|
+
expect(doc.content).toContain('No database is configured');
|
|
627
|
+
expect(doc.content).not.toContain('Connection');
|
|
628
|
+
expect(doc.diagrams).toHaveLength(0);
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
describe('deployment-guide', () => {
|
|
632
|
+
it('generates deployment guide for deployment units', () => {
|
|
633
|
+
const knowledge = makeKnowledge();
|
|
634
|
+
const doc = generateDocument('deployment-guide', knowledge, [], 'ops', 'en');
|
|
635
|
+
expect(doc.type).toBe('deployment-guide');
|
|
636
|
+
expect(doc.path).toBe('docs/deployment.md');
|
|
637
|
+
expect(doc.content).toContain('docker');
|
|
638
|
+
expect(doc.content).toContain('vercel');
|
|
639
|
+
expect(doc.content).toContain('Rollback');
|
|
640
|
+
expect(doc.diagrams).toHaveLength(1);
|
|
641
|
+
});
|
|
642
|
+
it('includes specific deployment instructions for known units', () => {
|
|
643
|
+
const knowledge = makeKnowledge();
|
|
644
|
+
const doc = generateDocument('deployment-guide', knowledge, [], 'ops', 'en');
|
|
645
|
+
expect(doc.content).toContain('docker build');
|
|
646
|
+
expect(doc.content).toContain('vercel');
|
|
647
|
+
});
|
|
648
|
+
it('includes fallback for unknown deployment unit', () => {
|
|
649
|
+
const knowledge = makeKnowledge();
|
|
650
|
+
knowledge.architecture.deploymentUnits = ['custom-target'];
|
|
651
|
+
const doc = generateDocument('deployment-guide', knowledge, [], 'ops', 'en');
|
|
652
|
+
expect(doc.content).toContain('custom-target');
|
|
653
|
+
expect(doc.content).toContain('document your steps here');
|
|
654
|
+
});
|
|
655
|
+
it('covers all known deployment unit instructions', () => {
|
|
656
|
+
const units = ['docker', 'docker-compose', 'vercel', 'railway', 'netlify', 'fly.io', 'manual'];
|
|
657
|
+
for (const unit of units) {
|
|
658
|
+
const knowledge = makeKnowledge();
|
|
659
|
+
knowledge.architecture.deploymentUnits = [unit];
|
|
660
|
+
const doc = generateDocument('deployment-guide', knowledge, [], 'ops', 'en');
|
|
661
|
+
expect(doc.content).toContain(unit);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
describe('help-articles', () => {
|
|
666
|
+
it('generates help articles from done specs', () => {
|
|
667
|
+
const specs = [makeSpec({ status: 'done' })];
|
|
668
|
+
const knowledge = makeKnowledge();
|
|
669
|
+
const doc = generateDocument('help-articles', knowledge, specs, 'end-user', 'en');
|
|
670
|
+
expect(doc.type).toBe('help-articles');
|
|
671
|
+
expect(doc.path).toBe('docs/help.md');
|
|
672
|
+
expect(doc.content).toContain('User Authentication');
|
|
673
|
+
expect(doc.relatedSpecs).toContain('SPEC-001');
|
|
674
|
+
});
|
|
675
|
+
it('limits to 10 done specs', () => {
|
|
676
|
+
const specs = Array.from({ length: 15 }, (_, i) => makeSpec({ id: `SPEC-${String(i).padStart(3, '0')}`, status: 'done', title: `Feature ${i}` }));
|
|
677
|
+
const knowledge = makeKnowledge();
|
|
678
|
+
const doc = generateDocument('help-articles', knowledge, specs, 'end-user', 'en');
|
|
679
|
+
// Help center + up to 10 articles
|
|
680
|
+
expect(doc.sections.length).toBeLessThanOrEqual(11);
|
|
681
|
+
});
|
|
682
|
+
it('generates help center section even with no done specs', () => {
|
|
683
|
+
const specs = [makeSpec({ status: 'draft' })];
|
|
684
|
+
const knowledge = makeKnowledge();
|
|
685
|
+
const doc = generateDocument('help-articles', knowledge, specs, 'end-user', 'en');
|
|
686
|
+
expect(doc.sections).toHaveLength(1);
|
|
687
|
+
expect(doc.sections[0].title).toBe('Help Center');
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
describe('release-notes', () => {
|
|
691
|
+
it('generates release notes grouped by type', () => {
|
|
692
|
+
const feature = makeSpec({ id: 'SPEC-001', type: 'feature', status: 'done', title: 'New Feature' });
|
|
693
|
+
const bugfix = makeSpec({ id: 'SPEC-002', type: 'bugfix', status: 'done', title: 'Fix Bug' });
|
|
694
|
+
const refactor = makeSpec({ id: 'SPEC-003', type: 'refactor', status: 'done', title: 'Refactor Code' });
|
|
695
|
+
const knowledge = makeKnowledge();
|
|
696
|
+
const doc = generateDocument('release-notes', knowledge, [feature, bugfix, refactor], 'stakeholder', 'en');
|
|
697
|
+
expect(doc.type).toBe('release-notes');
|
|
698
|
+
expect(doc.path).toBe('docs/release-notes.md');
|
|
699
|
+
expect(doc.content).toContain('New Features');
|
|
700
|
+
expect(doc.content).toContain('Bug Fixes');
|
|
701
|
+
expect(doc.content).toContain('Improvements');
|
|
702
|
+
});
|
|
703
|
+
it('omits empty type sections', () => {
|
|
704
|
+
const feature = makeSpec({ type: 'feature', status: 'done' });
|
|
705
|
+
const knowledge = makeKnowledge();
|
|
706
|
+
const doc = generateDocument('release-notes', knowledge, [feature], 'stakeholder', 'en');
|
|
707
|
+
expect(doc.content).toContain('New Features');
|
|
708
|
+
expect(doc.content).not.toContain('Bug Fixes');
|
|
709
|
+
expect(doc.content).not.toContain('Improvements');
|
|
710
|
+
});
|
|
711
|
+
it('only includes done specs', () => {
|
|
712
|
+
const draft = makeSpec({ status: 'draft', type: 'feature', title: 'Draft' });
|
|
713
|
+
const knowledge = makeKnowledge();
|
|
714
|
+
const doc = generateDocument('release-notes', knowledge, [draft], 'stakeholder', 'en');
|
|
715
|
+
expect(doc.content).not.toContain('Draft');
|
|
716
|
+
expect(doc.relatedSpecs).toHaveLength(0);
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
describe('runbook', () => {
|
|
720
|
+
it('generates runbook', () => {
|
|
721
|
+
const knowledge = makeKnowledge();
|
|
722
|
+
const doc = generateDocument('runbook', knowledge, [], 'ops', 'en');
|
|
723
|
+
expect(doc.type).toBe('runbook');
|
|
724
|
+
expect(doc.path).toBe('docs/runbook.md');
|
|
725
|
+
expect(doc.content).toContain('Service Overview');
|
|
726
|
+
expect(doc.content).toContain('Health Checks');
|
|
727
|
+
expect(doc.content).toContain('Common Issues');
|
|
728
|
+
expect(doc.content).toContain('Escalation');
|
|
729
|
+
expect(doc.content).toContain('typescript');
|
|
730
|
+
expect(doc.content).toContain('express');
|
|
731
|
+
expect(doc.content).toContain('postgresql');
|
|
732
|
+
});
|
|
733
|
+
it('shows none for framework when null', () => {
|
|
734
|
+
const knowledge = makeKnowledge({ framework: null });
|
|
735
|
+
const doc = generateDocument('runbook', knowledge, [], 'ops', 'en');
|
|
736
|
+
expect(doc.content).toContain('Framework: none');
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
describe('security-doc', () => {
|
|
740
|
+
it('generates security doc', () => {
|
|
741
|
+
const knowledge = makeKnowledge();
|
|
742
|
+
const doc = generateDocument('security-doc', knowledge, [], 'developer', 'en');
|
|
743
|
+
expect(doc.type).toBe('security-doc');
|
|
744
|
+
expect(doc.path).toBe('docs/security.md');
|
|
745
|
+
expect(doc.content).toContain('Security Overview');
|
|
746
|
+
expect(doc.content).toContain('Authentication & Authorization');
|
|
747
|
+
expect(doc.content).toContain('Data Protection');
|
|
748
|
+
expect(doc.content).toContain('Reporting Vulnerabilities');
|
|
749
|
+
});
|
|
750
|
+
it('shows positive security checks', () => {
|
|
751
|
+
const knowledge = makeKnowledge();
|
|
752
|
+
const doc = generateDocument('security-doc', knowledge, [], 'developer', 'en');
|
|
753
|
+
expect(doc.content).toContain('.env in .gitignore: Yes');
|
|
754
|
+
expect(doc.content).toContain('No .env committed to git: Yes');
|
|
755
|
+
expect(doc.content).toContain('No secrets in code: Yes');
|
|
756
|
+
});
|
|
757
|
+
it('shows negative security checks', () => {
|
|
758
|
+
const knowledge = makeKnowledge({
|
|
759
|
+
envSetup: {
|
|
760
|
+
projectId: 'proj-1',
|
|
761
|
+
variables: [],
|
|
762
|
+
missing: [],
|
|
763
|
+
security: {
|
|
764
|
+
gitignoreHasEnv: false,
|
|
765
|
+
noSecretsInCode: false,
|
|
766
|
+
noEnvInGit: false,
|
|
767
|
+
noSecretsInLogs: true,
|
|
768
|
+
usesSecretManager: true,
|
|
769
|
+
issues: [],
|
|
770
|
+
},
|
|
771
|
+
setupSteps: [],
|
|
772
|
+
},
|
|
773
|
+
});
|
|
774
|
+
const doc = generateDocument('security-doc', knowledge, [], 'developer', 'en');
|
|
775
|
+
expect(doc.content).toContain('FIX IMMEDIATELY');
|
|
776
|
+
expect(doc.content).toContain('REMOVE FROM GIT');
|
|
777
|
+
expect(doc.content).toContain('Needs review');
|
|
778
|
+
expect(doc.content).toContain('Uses secret manager: Yes');
|
|
779
|
+
});
|
|
780
|
+
it('shows security issues when present', () => {
|
|
781
|
+
const knowledge = makeKnowledge();
|
|
782
|
+
const doc = generateDocument('security-doc', knowledge, [], 'developer', 'en');
|
|
783
|
+
expect(doc.content).toContain('Issues');
|
|
784
|
+
expect(doc.content).toContain('WARNING');
|
|
785
|
+
expect(doc.content).toContain('No secret manager');
|
|
786
|
+
});
|
|
787
|
+
it('omits issues section when no issues', () => {
|
|
788
|
+
const knowledge = makeKnowledge({
|
|
789
|
+
envSetup: {
|
|
790
|
+
projectId: 'proj-1',
|
|
791
|
+
variables: [],
|
|
792
|
+
missing: [],
|
|
793
|
+
security: {
|
|
794
|
+
gitignoreHasEnv: true,
|
|
795
|
+
noSecretsInCode: true,
|
|
796
|
+
noEnvInGit: true,
|
|
797
|
+
noSecretsInLogs: true,
|
|
798
|
+
usesSecretManager: true,
|
|
799
|
+
issues: [],
|
|
800
|
+
},
|
|
801
|
+
setupSteps: [],
|
|
802
|
+
},
|
|
803
|
+
});
|
|
804
|
+
const doc = generateDocument('security-doc', knowledge, [], 'developer', 'en');
|
|
805
|
+
expect(doc.content).not.toContain('### Issues');
|
|
806
|
+
});
|
|
807
|
+
});
|
|
808
|
+
});
|
|
809
|
+
// === Tests for generateDiagram ===
|
|
810
|
+
describe('generateDiagram', () => {
|
|
811
|
+
it('generates architecture diagram', () => {
|
|
812
|
+
const knowledge = makeKnowledge();
|
|
813
|
+
const diagram = generateDiagram('architecture', knowledge);
|
|
814
|
+
expect(diagram.type).toBe('architecture');
|
|
815
|
+
expect(diagram.format).toBe('mermaid');
|
|
816
|
+
expect(diagram.content).toContain('graph TB');
|
|
817
|
+
expect(diagram.content).toContain('API');
|
|
818
|
+
expect(diagram.content).toContain('Service');
|
|
819
|
+
expect(diagram.description).toContain('layered');
|
|
820
|
+
});
|
|
821
|
+
it('generates component diagram', () => {
|
|
822
|
+
const knowledge = makeKnowledge();
|
|
823
|
+
const diagram = generateDiagram('component', knowledge);
|
|
824
|
+
expect(diagram.type).toBe('component');
|
|
825
|
+
expect(diagram.content).toContain('graph LR');
|
|
826
|
+
expect(diagram.content).toContain('web');
|
|
827
|
+
expect(diagram.content).toContain('api');
|
|
828
|
+
// frontend -> backend connection
|
|
829
|
+
expect(diagram.content).toContain('-->');
|
|
830
|
+
expect(diagram.description).toContain('2 app(s)');
|
|
831
|
+
});
|
|
832
|
+
it('generates data-flow diagram with database', () => {
|
|
833
|
+
const knowledge = makeKnowledge();
|
|
834
|
+
const diagram = generateDiagram('data-flow', knowledge);
|
|
835
|
+
expect(diagram.type).toBe('data-flow');
|
|
836
|
+
expect(diagram.content).toContain('graph LR');
|
|
837
|
+
expect(diagram.content).toContain('DB[(postgresql)]');
|
|
838
|
+
});
|
|
839
|
+
it('generates data-flow diagram without database', () => {
|
|
840
|
+
const knowledge = makeKnowledge({ database: 'unknown' });
|
|
841
|
+
const diagram = generateDiagram('data-flow', knowledge);
|
|
842
|
+
expect(diagram.content).not.toContain('DB[(');
|
|
843
|
+
expect(diagram.content).not.toContain('Logic --> DB');
|
|
844
|
+
});
|
|
845
|
+
it('generates sequence diagram with spec', () => {
|
|
846
|
+
const knowledge = makeKnowledge();
|
|
847
|
+
const spec = makeSpec();
|
|
848
|
+
const diagram = generateDiagram('sequence', knowledge, spec);
|
|
849
|
+
expect(diagram.type).toBe('sequence');
|
|
850
|
+
expect(diagram.content).toContain('sequenceDiagram');
|
|
851
|
+
expect(diagram.content).toContain('User Authentication');
|
|
852
|
+
expect(diagram.title).toContain('User Authentication');
|
|
853
|
+
});
|
|
854
|
+
it('generates sequence diagram without spec', () => {
|
|
855
|
+
const knowledge = makeKnowledge();
|
|
856
|
+
const diagram = generateDiagram('sequence', knowledge);
|
|
857
|
+
expect(diagram.content).toContain('Request Flow');
|
|
858
|
+
expect(diagram.title).toContain('Request Flow');
|
|
859
|
+
});
|
|
860
|
+
it('generates ER diagram', () => {
|
|
861
|
+
const knowledge = makeKnowledge();
|
|
862
|
+
const diagram = generateDiagram('er', knowledge);
|
|
863
|
+
expect(diagram.type).toBe('er');
|
|
864
|
+
expect(diagram.content).toContain('erDiagram');
|
|
865
|
+
expect(diagram.content).toContain('USERS');
|
|
866
|
+
expect(diagram.description).toContain('postgresql');
|
|
867
|
+
});
|
|
868
|
+
it('generates state-machine diagram with spec', () => {
|
|
869
|
+
const knowledge = makeKnowledge();
|
|
870
|
+
const spec = makeSpec();
|
|
871
|
+
const diagram = generateDiagram('state-machine', knowledge, spec);
|
|
872
|
+
expect(diagram.type).toBe('state-machine');
|
|
873
|
+
expect(diagram.content).toContain('stateDiagram-v2');
|
|
874
|
+
expect(diagram.content).toContain('draft');
|
|
875
|
+
expect(diagram.content).toContain('approved');
|
|
876
|
+
});
|
|
877
|
+
it('generates state-machine diagram without spec', () => {
|
|
878
|
+
const knowledge = makeKnowledge();
|
|
879
|
+
const diagram = generateDiagram('state-machine', knowledge);
|
|
880
|
+
expect(diagram.content).toContain('Created');
|
|
881
|
+
expect(diagram.content).toContain('Active');
|
|
882
|
+
expect(diagram.content).not.toContain('draft');
|
|
883
|
+
});
|
|
884
|
+
it('generates dependency diagram with allowed and forbidden deps', () => {
|
|
885
|
+
const knowledge = makeKnowledge();
|
|
886
|
+
const diagram = generateDiagram('dependency', knowledge);
|
|
887
|
+
expect(diagram.type).toBe('dependency');
|
|
888
|
+
expect(diagram.content).toContain('graph TD');
|
|
889
|
+
expect(diagram.content).toContain('-.->'); // allowed dep
|
|
890
|
+
expect(diagram.content).toContain('-.-x'); // forbidden dep
|
|
891
|
+
});
|
|
892
|
+
it('generates deployment diagram', () => {
|
|
893
|
+
const knowledge = makeKnowledge();
|
|
894
|
+
const diagram = generateDiagram('deployment', knowledge);
|
|
895
|
+
expect(diagram.type).toBe('deployment');
|
|
896
|
+
expect(diagram.content).toContain('graph LR');
|
|
897
|
+
expect(diagram.content).toContain('Dev');
|
|
898
|
+
expect(diagram.content).toContain('Git');
|
|
899
|
+
expect(diagram.content).toContain('docker');
|
|
900
|
+
expect(diagram.content).toContain('vercel');
|
|
901
|
+
expect(diagram.description).toContain('2 target(s)');
|
|
902
|
+
});
|
|
903
|
+
it('returns placeholder for unsupported diagram type', () => {
|
|
904
|
+
const knowledge = makeKnowledge();
|
|
905
|
+
const diagram = generateDiagram('unknown-type', knowledge);
|
|
906
|
+
expect(diagram.content).toContain('Not yet implemented');
|
|
907
|
+
expect(diagram.description).toContain('placeholder');
|
|
908
|
+
});
|
|
909
|
+
});
|
|
910
|
+
// === Tests for getInstallCommand coverage (various package managers) ===
|
|
911
|
+
describe('getInstallCommand coverage via setup-guide', () => {
|
|
912
|
+
const managers = [
|
|
913
|
+
{ pm: 'npm', expected: 'npm install' },
|
|
914
|
+
{ pm: 'pnpm', expected: 'pnpm install' },
|
|
915
|
+
{ pm: 'yarn', expected: 'yarn' },
|
|
916
|
+
{ pm: 'bun', expected: 'bun install' },
|
|
917
|
+
{ pm: 'pip', expected: 'pip install -r requirements.txt' },
|
|
918
|
+
{ pm: 'poetry', expected: 'poetry install' },
|
|
919
|
+
{ pm: 'uv', expected: 'uv sync' },
|
|
920
|
+
{ pm: 'pipenv', expected: 'pipenv install' },
|
|
921
|
+
{ pm: 'cargo', expected: 'cargo build' },
|
|
922
|
+
{ pm: 'go-mod', expected: 'go mod download' },
|
|
923
|
+
{ pm: 'composer', expected: 'composer install' },
|
|
924
|
+
{ pm: 'bundler', expected: 'bundle install' },
|
|
925
|
+
{ pm: 'pub', expected: 'flutter pub get' },
|
|
926
|
+
{ pm: 'mix', expected: 'mix deps.get' },
|
|
927
|
+
{ pm: 'spm', expected: 'swift package resolve' },
|
|
928
|
+
];
|
|
929
|
+
for (const { pm, expected } of managers) {
|
|
930
|
+
it(`returns correct command for ${pm}`, () => {
|
|
931
|
+
const knowledge = makeKnowledge({ packageManager: pm });
|
|
932
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
933
|
+
expect(doc.content).toContain(expected);
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
// === Tests for various prerequisite languages ===
|
|
938
|
+
describe('buildPrerequisitesSection coverage via setup-guide', () => {
|
|
939
|
+
const langs = [
|
|
940
|
+
{ lang: 'typescript', expected: 'Node.js 18+' },
|
|
941
|
+
{ lang: 'javascript', expected: 'Node.js 18+' },
|
|
942
|
+
{ lang: 'python', expected: 'Python 3.10+' },
|
|
943
|
+
{ lang: 'go', expected: 'Go 1.21+' },
|
|
944
|
+
{ lang: 'rust', expected: 'Rust 1.70+' },
|
|
945
|
+
{ lang: 'java', expected: 'Java 17+' },
|
|
946
|
+
{ lang: 'kotlin', expected: 'Kotlin 1.9+' },
|
|
947
|
+
{ lang: 'php', expected: 'PHP 8.2+' },
|
|
948
|
+
{ lang: 'ruby', expected: 'Ruby 3.2+' },
|
|
949
|
+
{ lang: 'swift', expected: 'Xcode 15+' },
|
|
950
|
+
{ lang: 'dart', expected: 'Dart 3.0+' },
|
|
951
|
+
{ lang: 'csharp', expected: '.NET 8+' },
|
|
952
|
+
];
|
|
953
|
+
for (const { lang, expected } of langs) {
|
|
954
|
+
it(`shows correct prerequisite for ${lang}`, () => {
|
|
955
|
+
const knowledge = makeKnowledge({ language: lang });
|
|
956
|
+
const doc = generateDocument('setup-guide', knowledge, [], 'developer', 'en');
|
|
957
|
+
expect(doc.content).toContain(expected);
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
//# sourceMappingURL=doc-generator.test.js.map
|