@sk8metal/michi-cli 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/README.md +420 -49
- package/dist/scripts/__tests__/create-project.test.js +24 -28
- package/dist/scripts/__tests__/create-project.test.js.map +1 -1
- package/dist/scripts/__tests__/jira-transitions.test.d.ts +5 -0
- package/dist/scripts/__tests__/jira-transitions.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/jira-transitions.test.js +172 -0
- package/dist/scripts/__tests__/jira-transitions.test.js.map +1 -0
- package/dist/scripts/__tests__/multi-project-estimate.test.js +14 -15
- package/dist/scripts/__tests__/multi-project-estimate.test.js.map +1 -1
- package/dist/scripts/__tests__/setup-existing-project.test.js +146 -5
- package/dist/scripts/__tests__/setup-existing-project.test.js.map +1 -1
- package/dist/scripts/__tests__/setup-interactive.test.js +23 -17
- package/dist/scripts/__tests__/setup-interactive.test.js.map +1 -1
- package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts +5 -0
- package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/spec-impl-workflow.test.js +321 -0
- package/dist/scripts/__tests__/spec-impl-workflow.test.js.map +1 -0
- package/dist/scripts/__tests__/spec-loader.test.d.ts +5 -0
- package/dist/scripts/__tests__/spec-loader.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/spec-loader.test.js +153 -0
- package/dist/scripts/__tests__/spec-loader.test.js.map +1 -0
- package/dist/scripts/__tests__/validate-phase.test.js +26 -22
- package/dist/scripts/__tests__/validate-phase.test.js.map +1 -1
- package/dist/scripts/config/config-schema.d.ts +17 -0
- package/dist/scripts/config/config-schema.d.ts.map +1 -1
- package/dist/scripts/config/config-schema.js +55 -26
- package/dist/scripts/config/config-schema.js.map +1 -1
- package/dist/scripts/config-interactive.d.ts.map +1 -1
- package/dist/scripts/config-interactive.js +53 -38
- package/dist/scripts/config-interactive.js.map +1 -1
- package/dist/scripts/confluence-sync.d.ts.map +1 -1
- package/dist/scripts/confluence-sync.js +0 -11
- package/dist/scripts/confluence-sync.js.map +1 -1
- package/dist/scripts/constants/__tests__/environments.test.d.ts +2 -0
- package/dist/scripts/constants/__tests__/environments.test.d.ts.map +1 -0
- package/dist/scripts/constants/__tests__/environments.test.js +125 -0
- package/dist/scripts/constants/__tests__/environments.test.js.map +1 -0
- package/dist/scripts/constants/__tests__/languages.test.d.ts +2 -0
- package/dist/scripts/constants/__tests__/languages.test.d.ts.map +1 -0
- package/dist/scripts/constants/__tests__/languages.test.js +82 -0
- package/dist/scripts/constants/__tests__/languages.test.js.map +1 -0
- package/dist/scripts/constants/environments.d.ts +33 -0
- package/dist/scripts/constants/environments.d.ts.map +1 -0
- package/dist/scripts/constants/environments.js +64 -0
- package/dist/scripts/constants/environments.js.map +1 -0
- package/dist/scripts/constants/languages.d.ts +23 -0
- package/dist/scripts/constants/languages.d.ts.map +1 -0
- package/dist/scripts/constants/languages.js +53 -0
- package/dist/scripts/constants/languages.js.map +1 -0
- package/dist/scripts/constants/test-commands.d.ts +36 -0
- package/dist/scripts/constants/test-commands.d.ts.map +1 -0
- package/dist/scripts/constants/test-commands.js +70 -0
- package/dist/scripts/constants/test-commands.js.map +1 -0
- package/dist/scripts/create-project.d.ts +4 -0
- package/dist/scripts/create-project.d.ts.map +1 -1
- package/dist/scripts/create-project.js +51 -22
- package/dist/scripts/create-project.js.map +1 -1
- package/dist/scripts/jira-sync.d.ts +89 -3
- package/dist/scripts/jira-sync.d.ts.map +1 -1
- package/dist/scripts/jira-sync.js +366 -96
- package/dist/scripts/jira-sync.js.map +1 -1
- package/dist/scripts/markdown-to-confluence.js +1 -1
- package/dist/scripts/markdown-to-confluence.js.map +1 -1
- package/dist/scripts/phase-runner.d.ts +1 -1
- package/dist/scripts/phase-runner.d.ts.map +1 -1
- package/dist/scripts/phase-runner.js +809 -13
- package/dist/scripts/phase-runner.js.map +1 -1
- package/dist/scripts/pr-automation.d.ts.map +1 -1
- package/dist/scripts/pr-automation.js.map +1 -1
- package/dist/scripts/pre-flight-check.js +1 -1
- package/dist/scripts/pre-flight-check.js.map +1 -1
- package/dist/scripts/setup-existing-project.d.ts +3 -1
- package/dist/scripts/setup-existing-project.d.ts.map +1 -1
- package/dist/scripts/setup-existing-project.js +165 -78
- package/dist/scripts/setup-existing-project.js.map +1 -1
- package/dist/scripts/setup-interactive.js +3 -3
- package/dist/scripts/setup-interactive.js.map +1 -1
- package/dist/scripts/spec-impl-workflow.d.ts +94 -0
- package/dist/scripts/spec-impl-workflow.d.ts.map +1 -0
- package/dist/scripts/spec-impl-workflow.js +354 -0
- package/dist/scripts/spec-impl-workflow.js.map +1 -0
- package/dist/scripts/template/__tests__/renderer.test.d.ts +2 -0
- package/dist/scripts/template/__tests__/renderer.test.d.ts.map +1 -0
- package/dist/scripts/template/__tests__/renderer.test.js +165 -0
- package/dist/scripts/template/__tests__/renderer.test.js.map +1 -0
- package/dist/scripts/template/renderer.d.ts +70 -0
- package/dist/scripts/template/renderer.d.ts.map +1 -0
- package/dist/scripts/template/renderer.js +99 -0
- package/dist/scripts/template/renderer.js.map +1 -0
- package/dist/scripts/test-execution-generator.d.ts +52 -0
- package/dist/scripts/test-execution-generator.d.ts.map +1 -0
- package/dist/scripts/test-execution-generator.js +576 -0
- package/dist/scripts/test-execution-generator.js.map +1 -0
- package/dist/scripts/test-interactive.d.ts +10 -0
- package/dist/scripts/test-interactive.d.ts.map +1 -0
- package/dist/scripts/test-interactive.js +627 -0
- package/dist/scripts/test-interactive.js.map +1 -0
- package/dist/scripts/test-new-features.d.ts +5 -0
- package/dist/scripts/test-new-features.d.ts.map +1 -0
- package/dist/scripts/test-new-features.js +145 -0
- package/dist/scripts/test-new-features.js.map +1 -0
- package/dist/scripts/test-spec-generator.d.ts +29 -0
- package/dist/scripts/test-spec-generator.d.ts.map +1 -0
- package/dist/scripts/test-spec-generator.js +494 -0
- package/dist/scripts/test-spec-generator.js.map +1 -0
- package/dist/scripts/test-workflow-stages.d.ts +6 -0
- package/dist/scripts/test-workflow-stages.d.ts.map +1 -0
- package/dist/scripts/test-workflow-stages.js +43 -0
- package/dist/scripts/test-workflow-stages.js.map +1 -0
- package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/aidlc-parser.test.js +315 -0
- package/dist/scripts/utils/__tests__/aidlc-parser.test.js.map +1 -0
- package/dist/scripts/utils/__tests__/business-days.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/business-days.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/business-days.test.js +171 -0
- package/dist/scripts/utils/__tests__/business-days.test.js.map +1 -0
- package/dist/scripts/utils/__tests__/config-loader.test.js +1 -1
- package/dist/scripts/utils/__tests__/config-loader.test.js.map +1 -1
- package/dist/scripts/utils/__tests__/config-validator.test.js +164 -35
- package/dist/scripts/utils/__tests__/config-validator.test.js.map +1 -1
- package/dist/scripts/utils/__tests__/env-config.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/env-config.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/env-config.test.js +218 -0
- package/dist/scripts/utils/__tests__/env-config.test.js.map +1 -0
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js +202 -0
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js.map +1 -0
- package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/tasks-converter.test.js +500 -0
- package/dist/scripts/utils/__tests__/tasks-converter.test.js.map +1 -0
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.js +314 -0
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.js.map +1 -0
- package/dist/scripts/utils/__tests__/test-runner.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/test-runner.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/test-runner.test.js +64 -0
- package/dist/scripts/utils/__tests__/test-runner.test.js.map +1 -0
- package/dist/scripts/utils/aidlc-parser.d.ts +86 -0
- package/dist/scripts/utils/aidlc-parser.d.ts.map +1 -0
- package/dist/scripts/utils/aidlc-parser.js +208 -0
- package/dist/scripts/utils/aidlc-parser.js.map +1 -0
- package/dist/scripts/utils/business-days.d.ts +52 -0
- package/dist/scripts/utils/business-days.d.ts.map +1 -0
- package/dist/scripts/utils/business-days.js +98 -0
- package/dist/scripts/utils/business-days.js.map +1 -0
- package/dist/scripts/utils/ci-generator.d.ts +14 -0
- package/dist/scripts/utils/ci-generator.d.ts.map +1 -0
- package/dist/scripts/utils/ci-generator.js +61 -0
- package/dist/scripts/utils/ci-generator.js.map +1 -0
- package/dist/scripts/utils/config-loader.js +2 -2
- package/dist/scripts/utils/config-loader.js.map +1 -1
- package/dist/scripts/utils/config-validator.d.ts +7 -1
- package/dist/scripts/utils/config-validator.d.ts.map +1 -1
- package/dist/scripts/utils/config-validator.js +136 -23
- package/dist/scripts/utils/config-validator.js.map +1 -1
- package/dist/scripts/utils/confluence-approval.d.ts +46 -0
- package/dist/scripts/utils/confluence-approval.d.ts.map +1 -0
- package/dist/scripts/utils/confluence-approval.js +118 -0
- package/dist/scripts/utils/confluence-approval.js.map +1 -0
- package/dist/scripts/utils/confluence-hierarchy.d.ts.map +1 -1
- package/dist/scripts/utils/confluence-hierarchy.js +1 -1
- package/dist/scripts/utils/confluence-hierarchy.js.map +1 -1
- package/dist/scripts/utils/docker-generator.d.ts +9 -0
- package/dist/scripts/utils/docker-generator.d.ts.map +1 -0
- package/dist/scripts/utils/docker-generator.js +132 -0
- package/dist/scripts/utils/docker-generator.js.map +1 -0
- package/dist/scripts/utils/docker-requirement-detector.d.ts +15 -0
- package/dist/scripts/utils/docker-requirement-detector.d.ts.map +1 -0
- package/dist/scripts/utils/docker-requirement-detector.js +124 -0
- package/dist/scripts/utils/docker-requirement-detector.js.map +1 -0
- package/dist/scripts/utils/env-config.d.ts +54 -0
- package/dist/scripts/utils/env-config.d.ts.map +1 -0
- package/dist/scripts/utils/env-config.js +414 -0
- package/dist/scripts/utils/env-config.js.map +1 -0
- package/dist/scripts/utils/jira-issue-type-fetcher.d.ts +70 -0
- package/dist/scripts/utils/jira-issue-type-fetcher.d.ts.map +1 -0
- package/dist/scripts/utils/jira-issue-type-fetcher.js +147 -0
- package/dist/scripts/utils/jira-issue-type-fetcher.js.map +1 -0
- package/dist/scripts/utils/language-detector.d.ts +14 -0
- package/dist/scripts/utils/language-detector.d.ts.map +1 -0
- package/dist/scripts/utils/language-detector.js +119 -0
- package/dist/scripts/utils/language-detector.js.map +1 -0
- package/dist/scripts/utils/markdown-parser.d.ts +55 -0
- package/dist/scripts/utils/markdown-parser.d.ts.map +1 -0
- package/dist/scripts/utils/markdown-parser.js +289 -0
- package/dist/scripts/utils/markdown-parser.js.map +1 -0
- package/dist/scripts/utils/project-detector.d.ts +17 -0
- package/dist/scripts/utils/project-detector.d.ts.map +1 -0
- package/dist/scripts/utils/project-detector.js +166 -0
- package/dist/scripts/utils/project-detector.js.map +1 -0
- package/dist/scripts/utils/project-finder.js +2 -2
- package/dist/scripts/utils/project-finder.js.map +1 -1
- package/dist/scripts/utils/release-notes-generator.d.ts +56 -0
- package/dist/scripts/utils/release-notes-generator.d.ts.map +1 -0
- package/dist/scripts/utils/release-notes-generator.js +162 -0
- package/dist/scripts/utils/release-notes-generator.js.map +1 -0
- package/dist/scripts/utils/spec-loader.d.ts +79 -0
- package/dist/scripts/utils/spec-loader.d.ts.map +1 -0
- package/dist/scripts/utils/spec-loader.js +80 -0
- package/dist/scripts/utils/spec-loader.js.map +1 -0
- package/dist/scripts/utils/spec-updater.d.ts +7 -0
- package/dist/scripts/utils/spec-updater.d.ts.map +1 -1
- package/dist/scripts/utils/spec-updater.js.map +1 -1
- package/dist/scripts/utils/tasks-converter.d.ts +57 -0
- package/dist/scripts/utils/tasks-converter.d.ts.map +1 -0
- package/dist/scripts/utils/tasks-converter.js +322 -0
- package/dist/scripts/utils/tasks-converter.js.map +1 -0
- package/dist/scripts/utils/tasks-format-validator.d.ts +36 -0
- package/dist/scripts/utils/tasks-format-validator.d.ts.map +1 -0
- package/dist/scripts/utils/tasks-format-validator.js +158 -0
- package/dist/scripts/utils/tasks-format-validator.js.map +1 -0
- package/dist/scripts/utils/template-applier.d.ts +37 -0
- package/dist/scripts/utils/template-applier.d.ts.map +1 -0
- package/dist/scripts/utils/template-applier.js +129 -0
- package/dist/scripts/utils/template-applier.js.map +1 -0
- package/dist/scripts/utils/template-finder.d.ts +37 -0
- package/dist/scripts/utils/template-finder.d.ts.map +1 -0
- package/dist/scripts/utils/template-finder.js +63 -0
- package/dist/scripts/utils/template-finder.js.map +1 -0
- package/dist/scripts/utils/test-config-generator.d.ts +12 -0
- package/dist/scripts/utils/test-config-generator.d.ts.map +1 -0
- package/dist/scripts/utils/test-config-generator.js +185 -0
- package/dist/scripts/utils/test-config-generator.js.map +1 -0
- package/dist/scripts/utils/test-runner.d.ts +31 -0
- package/dist/scripts/utils/test-runner.d.ts.map +1 -0
- package/dist/scripts/utils/test-runner.js +103 -0
- package/dist/scripts/utils/test-runner.js.map +1 -0
- package/dist/scripts/validate-phase.d.ts +1 -1
- package/dist/scripts/validate-phase.d.ts.map +1 -1
- package/dist/scripts/validate-phase.js +153 -5
- package/dist/scripts/validate-phase.js.map +1 -1
- package/dist/scripts/workflow-orchestrator.d.ts +8 -0
- package/dist/scripts/workflow-orchestrator.d.ts.map +1 -1
- package/dist/scripts/workflow-orchestrator.js +108 -7
- package/dist/scripts/workflow-orchestrator.js.map +1 -1
- package/dist/src/__tests__/integration/internationalization.test.d.ts +8 -0
- package/dist/src/__tests__/integration/internationalization.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/internationalization.test.js +333 -0
- package/dist/src/__tests__/integration/internationalization.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.js +122 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/claude.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/claude.test.js +111 -0
- package/dist/src/__tests__/integration/setup/claude.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/cursor.test.js +166 -0
- package/dist/src/__tests__/integration/setup/cursor.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +32 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +72 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +38 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.js +83 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +1 -0
- package/dist/src/__tests__/integration/setup/validation.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/validation.test.js +301 -0
- package/dist/src/__tests__/integration/setup/validation.test.js.map +1 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +228 -18
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/setup-existing.d.ts +25 -0
- package/dist/src/commands/setup-existing.d.ts.map +1 -0
- package/dist/src/commands/setup-existing.js +695 -0
- package/dist/src/commands/setup-existing.js.map +1 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +4 -3
- package/dist/vitest.config.js.map +1 -1
- package/docs/README.md +3 -1
- package/docs/context.md +59 -0
- package/docs/design-issue-55.md +240 -0
- package/docs/design-issue-56.md +181 -0
- package/docs/michi-development/testing/manual-verification-flow.md +2242 -0
- package/docs/michi-development/testing/pre-publish-checklist.md +560 -0
- package/docs/plan.md +275 -0
- package/docs/user-guide/getting-started/github-token-setup.md +509 -0
- package/docs/{getting-started → user-guide/getting-started}/new-repository-setup.md +108 -28
- package/docs/{getting-started → user-guide/getting-started}/quick-start.md +73 -6
- package/docs/{getting-started → user-guide/getting-started}/setup.md +278 -3
- package/docs/{guides → user-guide/guides}/customization.md +3 -3
- package/docs/user-guide/guides/internationalization.md +540 -0
- package/docs/{guides → user-guide/guides}/multi-project.md +2 -2
- package/docs/{guides → user-guide/guides}/phase-automation.md +67 -9
- package/docs/user-guide/guides/workflow.md +582 -0
- package/docs/user-guide/hands-on/README.md +142 -0
- package/docs/user-guide/hands-on/claude-agent-setup.md +455 -0
- package/docs/user-guide/hands-on/claude-setup.md +398 -0
- package/docs/user-guide/hands-on/cursor-setup.md +352 -0
- package/docs/user-guide/hands-on/troubleshooting.md +964 -0
- package/docs/user-guide/hands-on/verification-checklist.md +438 -0
- package/docs/user-guide/hands-on/workflow-walkthrough.md +906 -0
- package/docs/user-guide/reference/config.md +564 -0
- package/docs/{reference → user-guide/reference}/quick-reference.md +75 -53
- package/docs/user-guide/release/ci-setup.md +541 -0
- package/docs/user-guide/release/release-flow.md +476 -0
- package/docs/user-guide/templates/test-specs/README.md +173 -0
- package/docs/user-guide/templates/test-specs/e2e-test-spec-template.md +547 -0
- package/docs/user-guide/templates/test-specs/integration-test-spec-template.md +435 -0
- package/docs/user-guide/templates/test-specs/performance-test-spec-template.md +454 -0
- package/docs/user-guide/templates/test-specs/security-test-spec-template.md +664 -0
- package/docs/user-guide/templates/test-specs/unit-test-spec-template.md +328 -0
- package/docs/user-guide/testing/integration-tests.md +312 -0
- package/docs/user-guide/testing/tdd-cycle.md +349 -0
- package/docs/user-guide/testing/test-execution-flow.md +396 -0
- package/docs/user-guide/testing/test-failure-handling.md +521 -0
- package/docs/user-guide/testing/test-planning-flow.md +181 -0
- package/docs/user-guide/testing-strategy.md +185 -0
- package/docs/verification-guide.md +518 -0
- package/package.json +13 -3
- package/scripts/__tests__/create-project.test.ts +67 -49
- package/scripts/__tests__/jira-transitions.test.ts +225 -0
- package/scripts/__tests__/multi-project-estimate.test.ts +36 -30
- package/scripts/__tests__/setup-existing-project.test.ts +171 -6
- package/scripts/__tests__/setup-interactive.test.ts +52 -46
- package/scripts/__tests__/spec-impl-workflow.test.ts +429 -0
- package/scripts/__tests__/spec-loader.test.ts +199 -0
- package/scripts/__tests__/validate-phase.test.ts +78 -54
- package/scripts/config/config-schema.ts +89 -50
- package/scripts/config-interactive.ts +191 -136
- package/scripts/confluence-sync.ts +0 -12
- package/scripts/constants/__tests__/environments.test.ts +146 -0
- package/scripts/constants/__tests__/languages.test.ts +100 -0
- package/scripts/constants/environments.ts +81 -0
- package/scripts/constants/languages.ts +70 -0
- package/scripts/constants/test-commands.ts +96 -0
- package/scripts/create-project.ts +52 -22
- package/scripts/jira-sync.ts +767 -232
- package/scripts/markdown-to-confluence.ts +1 -1
- package/scripts/phase-runner.ts +1056 -63
- package/scripts/pr-automation.ts +0 -1
- package/scripts/pre-flight-check.ts +1 -1
- package/scripts/pre-publish-check.sh +311 -0
- package/scripts/quick-verify.sh +115 -0
- package/scripts/setup-existing-project.ts +306 -143
- package/scripts/setup-interactive.ts +4 -4
- package/scripts/spec-impl-workflow.ts +505 -0
- package/scripts/template/__tests__/renderer.test.ts +206 -0
- package/scripts/template/renderer.ts +133 -0
- package/scripts/test-execution-generator.ts +695 -0
- package/scripts/test-interactive.ts +779 -0
- package/scripts/test-new-features.ts +168 -0
- package/scripts/test-npm-package.sh +345 -0
- package/scripts/test-spec-generator.ts +574 -0
- package/scripts/test-workflow-stages.ts +53 -0
- package/scripts/utils/__tests__/aidlc-parser.test.ts +349 -0
- package/scripts/utils/__tests__/business-days.test.ts +214 -0
- package/scripts/utils/__tests__/config-loader.test.ts +1 -1
- package/scripts/utils/__tests__/config-validator.test.ts +309 -88
- package/scripts/utils/__tests__/env-config.test.ts +259 -0
- package/scripts/utils/__tests__/jira-issue-type-fetcher.test.ts +272 -0
- package/scripts/utils/__tests__/tasks-converter.test.ts +582 -0
- package/scripts/utils/__tests__/tasks-format-validator.test.ts +338 -0
- package/scripts/utils/__tests__/test-runner.test.ts +77 -0
- package/scripts/utils/aidlc-parser.ts +289 -0
- package/scripts/utils/business-days.ts +115 -0
- package/scripts/utils/ci-generator.ts +84 -0
- package/scripts/utils/config-loader.ts +2 -2
- package/scripts/utils/config-validator.ts +304 -117
- package/scripts/utils/confluence-approval.ts +167 -0
- package/scripts/utils/confluence-hierarchy.ts +2 -4
- package/scripts/utils/docker-generator.ts +151 -0
- package/scripts/utils/docker-requirement-detector.ts +153 -0
- package/scripts/utils/env-config.ts +526 -0
- package/scripts/utils/jira-issue-type-fetcher.ts +199 -0
- package/scripts/utils/language-detector.ts +139 -0
- package/scripts/utils/markdown-parser.ts +376 -0
- package/scripts/utils/project-detector.ts +192 -0
- package/scripts/utils/project-finder.ts +2 -2
- package/scripts/utils/release-notes-generator.ts +210 -0
- package/scripts/utils/spec-loader.ts +125 -0
- package/scripts/utils/spec-updater.ts +8 -1
- package/scripts/utils/tasks-converter.ts +601 -0
- package/scripts/utils/tasks-format-validator.ts +193 -0
- package/scripts/utils/template-applier.ts +202 -0
- package/scripts/utils/template-finder.ts +75 -0
- package/scripts/utils/test-config-generator.ts +210 -0
- package/scripts/utils/test-runner.ts +133 -0
- package/scripts/validate-phase.ts +186 -9
- package/scripts/workflow-orchestrator.ts +130 -12
- package/templates/ci/github-actions/java.yml +54 -0
- package/templates/ci/github-actions/nodejs.yml +46 -0
- package/templates/ci/github-actions/php.yml +52 -0
- package/templates/ci/screwdriver/java.yaml +17 -0
- package/templates/ci/screwdriver/nodejs.yaml +17 -0
- package/templates/ci/screwdriver/php.yaml +20 -0
- package/templates/claude/commands/kiro/kiro-spec-impl.md +244 -0
- package/templates/claude/commands/kiro/kiro-spec-tasks.md +354 -0
- package/templates/claude/commands/michi/confluence-sync.md +38 -0
- package/templates/claude/commands/michi/project-switch.md +36 -0
- package/templates/claude/rules/atlassian-integration.md +35 -0
- package/templates/claude/rules/michi-core.md +54 -0
- package/templates/claude-agent/README.md +31 -0
- package/templates/claude-agent/agents/.gitkeep +0 -0
- package/templates/claude-agent/agents/designer.md +79 -0
- package/templates/claude-agent/agents/developer.md +68 -0
- package/templates/claude-agent/agents/manager-agent.md +59 -0
- package/templates/claude-agent/agents/tester.md +101 -0
- package/templates/claude-agent/commands/kiro/.gitkeep +0 -0
- package/templates/claude-agent/commands/kiro/kiro-spec-impl.md +244 -0
- package/templates/claude-agent/commands/kiro/kiro-spec-tasks.md +354 -0
- package/templates/cline/rules/atlassian-integration.md +36 -0
- package/templates/cline/rules/michi-core.md +56 -0
- package/templates/codex/AGENTS.override.md +277 -0
- package/templates/codex/prompts/confluence-sync.md +177 -0
- package/templates/codex/rules/README.md +210 -0
- package/templates/common/.kiro/project.json.template +21 -0
- package/templates/cursor/commands/kiro/kiro-spec-impl.md +244 -0
- package/templates/cursor/commands/kiro/kiro-spec-tasks.md +354 -0
- package/templates/cursor/commands/michi/confluence-sync.md +76 -0
- package/templates/cursor/commands/michi/project-switch.md +69 -0
- package/templates/cursor/rules/atlassian-mcp.mdc +188 -0
- package/templates/cursor/rules/github-ssot.mdc +151 -0
- package/templates/cursor/rules/multi-project.mdc +81 -0
- package/templates/gemini/commands/README.md +41 -0
- package/templates/gemini/rules/GEMINI.md +80 -0
- package/docs/guides/workflow.md +0 -342
- package/docs/reference/config.md +0 -545
- package/scripts/setup-env.sh +0 -52
- package/scripts/setup-existing.sh +0 -152
- /package/docs/{contributing → michi-development/contributing}/development.md +0 -0
- /package/docs/{contributing → michi-development/contributing}/release.md +0 -0
- /package/docs/{testing-strategy.md → michi-development/testing-strategy.md} +0 -0
- /package/docs/{reference → user-guide/reference}/tasks-template.md +0 -0
package/scripts/phase-runner.ts
CHANGED
|
@@ -3,15 +3,26 @@
|
|
|
3
3
|
* 各フェーズを実行し、Confluence/JIRA作成を確実に実行
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { existsSync } from 'fs';
|
|
7
|
-
import { join } from 'path';
|
|
6
|
+
import { existsSync, writeFileSync, readFileSync, mkdirSync } from 'fs';
|
|
7
|
+
import { join, relative } from 'path';
|
|
8
8
|
import { syncToConfluence } from './confluence-sync.js';
|
|
9
9
|
import { syncTasksToJIRA } from './jira-sync.js';
|
|
10
10
|
import { validatePhase } from './validate-phase.js';
|
|
11
11
|
import { runPreFlightCheck } from './pre-flight-check.js';
|
|
12
12
|
import { validateFeatureNameOrThrow } from './utils/feature-name-validator.js';
|
|
13
|
+
import { getTestCommands } from './constants/test-commands.js';
|
|
14
|
+
import { loadSpecJson } from './utils/spec-updater.js';
|
|
15
|
+
import inquirer from 'inquirer';
|
|
13
16
|
|
|
14
|
-
type Phase =
|
|
17
|
+
type Phase =
|
|
18
|
+
| 'requirements'
|
|
19
|
+
| 'design'
|
|
20
|
+
| 'test-type-selection'
|
|
21
|
+
| 'test-spec'
|
|
22
|
+
| 'tasks'
|
|
23
|
+
| 'environment-setup'
|
|
24
|
+
| 'phase-a'
|
|
25
|
+
| 'phase-b';
|
|
15
26
|
|
|
16
27
|
interface PhaseRunResult {
|
|
17
28
|
phase: Phase;
|
|
@@ -28,27 +39,35 @@ interface PhaseRunResult {
|
|
|
28
39
|
async function runRequirementsPhase(feature: string): Promise<PhaseRunResult> {
|
|
29
40
|
console.log('\n📋 Phase: Requirements(要件定義)');
|
|
30
41
|
console.log('='.repeat(60));
|
|
31
|
-
|
|
42
|
+
|
|
32
43
|
const errors: string[] = [];
|
|
33
44
|
let confluenceCreated = false;
|
|
34
45
|
let confluenceUrl: string | null = null;
|
|
35
|
-
|
|
46
|
+
|
|
36
47
|
// Step 1: requirements.md存在確認
|
|
37
|
-
const requirementsPath = join(
|
|
48
|
+
const requirementsPath = join(
|
|
49
|
+
process.cwd(),
|
|
50
|
+
'.kiro',
|
|
51
|
+
'specs',
|
|
52
|
+
feature,
|
|
53
|
+
'requirements.md',
|
|
54
|
+
);
|
|
38
55
|
if (!existsSync(requirementsPath)) {
|
|
39
|
-
errors.push(
|
|
56
|
+
errors.push(
|
|
57
|
+
'requirements.mdが存在しません。先に/kiro:spec-requirements を実行してください',
|
|
58
|
+
);
|
|
40
59
|
return {
|
|
41
60
|
phase: 'requirements',
|
|
42
61
|
success: false,
|
|
43
62
|
confluenceCreated: false,
|
|
44
63
|
jiraCreated: false,
|
|
45
64
|
validationPassed: false,
|
|
46
|
-
errors
|
|
65
|
+
errors,
|
|
47
66
|
};
|
|
48
67
|
}
|
|
49
|
-
|
|
68
|
+
|
|
50
69
|
console.log('✅ requirements.md 存在確認');
|
|
51
|
-
|
|
70
|
+
|
|
52
71
|
// Step 2: Confluenceページ作成
|
|
53
72
|
console.log('\n📤 Confluenceページ作成中...');
|
|
54
73
|
try {
|
|
@@ -59,37 +78,44 @@ async function runRequirementsPhase(feature: string): Promise<PhaseRunResult> {
|
|
|
59
78
|
errors.push(`Confluenceページ作成失敗: ${error.message}`);
|
|
60
79
|
console.error('❌ Confluenceページ作成失敗:', error.message);
|
|
61
80
|
}
|
|
62
|
-
|
|
81
|
+
|
|
63
82
|
// Step 3: バリデーション
|
|
64
83
|
console.log('\n🔍 バリデーション実行中...');
|
|
65
84
|
const validation = validatePhase(feature, 'requirements');
|
|
66
85
|
errors.push(...validation.errors);
|
|
67
|
-
|
|
86
|
+
|
|
68
87
|
// Step 4: 結果サマリー
|
|
69
88
|
console.log('\n' + '='.repeat(60));
|
|
70
89
|
console.log('📊 要件定義フェーズ完了チェック:');
|
|
71
90
|
console.log(' ✅ requirements.md: 作成済み');
|
|
72
|
-
console.log(
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
console.log(
|
|
92
|
+
` ${confluenceCreated ? '✅' : '❌'} Confluenceページ: ${confluenceCreated ? '作成済み' : '未作成'}`,
|
|
93
|
+
);
|
|
94
|
+
console.log(
|
|
95
|
+
` ${validation.valid ? '✅' : '❌'} バリデーション: ${validation.valid ? '成功' : '失敗'}`,
|
|
96
|
+
);
|
|
97
|
+
|
|
75
98
|
if (validation.valid && confluenceCreated) {
|
|
76
99
|
console.log('\n🎉 要件定義フェーズが完了しました!');
|
|
77
100
|
console.log('📢 PMや部長にConfluenceでレビューを依頼してください');
|
|
78
101
|
if (confluenceUrl) {
|
|
79
102
|
console.log(`📄 Confluence: ${confluenceUrl}`);
|
|
80
103
|
} else {
|
|
81
|
-
const baseUrl =
|
|
82
|
-
|
|
104
|
+
const baseUrl =
|
|
105
|
+
process.env.ATLASSIAN_URL || 'https://your-site.atlassian.net';
|
|
106
|
+
console.log(
|
|
107
|
+
`📄 Confluence: ${baseUrl}/wiki/spaces/(URLは上記のログを参照)`,
|
|
108
|
+
);
|
|
83
109
|
}
|
|
84
110
|
}
|
|
85
|
-
|
|
111
|
+
|
|
86
112
|
return {
|
|
87
113
|
phase: 'requirements',
|
|
88
114
|
success: validation.valid && confluenceCreated,
|
|
89
115
|
confluenceCreated,
|
|
90
116
|
jiraCreated: false,
|
|
91
117
|
validationPassed: validation.valid,
|
|
92
|
-
errors
|
|
118
|
+
errors,
|
|
93
119
|
};
|
|
94
120
|
}
|
|
95
121
|
|
|
@@ -99,27 +125,35 @@ async function runRequirementsPhase(feature: string): Promise<PhaseRunResult> {
|
|
|
99
125
|
async function runDesignPhase(feature: string): Promise<PhaseRunResult> {
|
|
100
126
|
console.log('\n🏗️ Phase: Design(設計)');
|
|
101
127
|
console.log('='.repeat(60));
|
|
102
|
-
|
|
128
|
+
|
|
103
129
|
const errors: string[] = [];
|
|
104
130
|
let confluenceCreated = false;
|
|
105
131
|
let confluenceUrl: string | null = null;
|
|
106
|
-
|
|
132
|
+
|
|
107
133
|
// Step 1: design.md存在確認
|
|
108
|
-
const designPath = join(
|
|
134
|
+
const designPath = join(
|
|
135
|
+
process.cwd(),
|
|
136
|
+
'.kiro',
|
|
137
|
+
'specs',
|
|
138
|
+
feature,
|
|
139
|
+
'design.md',
|
|
140
|
+
);
|
|
109
141
|
if (!existsSync(designPath)) {
|
|
110
|
-
errors.push(
|
|
142
|
+
errors.push(
|
|
143
|
+
'design.mdが存在しません。先に/kiro:spec-design を実行してください',
|
|
144
|
+
);
|
|
111
145
|
return {
|
|
112
146
|
phase: 'design',
|
|
113
147
|
success: false,
|
|
114
148
|
confluenceCreated: false,
|
|
115
149
|
jiraCreated: false,
|
|
116
150
|
validationPassed: false,
|
|
117
|
-
errors
|
|
151
|
+
errors,
|
|
118
152
|
};
|
|
119
153
|
}
|
|
120
|
-
|
|
154
|
+
|
|
121
155
|
console.log('✅ design.md 存在確認');
|
|
122
|
-
|
|
156
|
+
|
|
123
157
|
// Step 2: Confluenceページ作成
|
|
124
158
|
console.log('\n📤 Confluenceページ作成中...');
|
|
125
159
|
try {
|
|
@@ -130,37 +164,44 @@ async function runDesignPhase(feature: string): Promise<PhaseRunResult> {
|
|
|
130
164
|
errors.push(`Confluenceページ作成失敗: ${error.message}`);
|
|
131
165
|
console.error('❌ Confluenceページ作成失敗:', error.message);
|
|
132
166
|
}
|
|
133
|
-
|
|
167
|
+
|
|
134
168
|
// Step 3: バリデーション
|
|
135
169
|
console.log('\n🔍 バリデーション実行中...');
|
|
136
170
|
const validation = validatePhase(feature, 'design');
|
|
137
171
|
errors.push(...validation.errors);
|
|
138
|
-
|
|
172
|
+
|
|
139
173
|
// Step 4: 結果サマリー
|
|
140
174
|
console.log('\n' + '='.repeat(60));
|
|
141
175
|
console.log('📊 設計フェーズ完了チェック:');
|
|
142
176
|
console.log(' ✅ design.md: 作成済み');
|
|
143
|
-
console.log(
|
|
144
|
-
|
|
145
|
-
|
|
177
|
+
console.log(
|
|
178
|
+
` ${confluenceCreated ? '✅' : '❌'} Confluenceページ: ${confluenceCreated ? '作成済み' : '未作成'}`,
|
|
179
|
+
);
|
|
180
|
+
console.log(
|
|
181
|
+
` ${validation.valid ? '✅' : '❌'} バリデーション: ${validation.valid ? '成功' : '失敗'}`,
|
|
182
|
+
);
|
|
183
|
+
|
|
146
184
|
if (validation.valid && confluenceCreated) {
|
|
147
185
|
console.log('\n🎉 設計フェーズが完了しました!');
|
|
148
186
|
console.log('📢 PMや部長にConfluenceでレビューを依頼してください');
|
|
149
187
|
if (confluenceUrl) {
|
|
150
188
|
console.log(`📄 Confluence: ${confluenceUrl}`);
|
|
151
189
|
} else {
|
|
152
|
-
const baseUrl =
|
|
153
|
-
|
|
190
|
+
const baseUrl =
|
|
191
|
+
process.env.ATLASSIAN_URL || 'https://your-site.atlassian.net';
|
|
192
|
+
console.log(
|
|
193
|
+
`📄 Confluence: ${baseUrl}/wiki/spaces/(URLは上記のログを参照)`,
|
|
194
|
+
);
|
|
154
195
|
}
|
|
155
196
|
}
|
|
156
|
-
|
|
197
|
+
|
|
157
198
|
return {
|
|
158
199
|
phase: 'design',
|
|
159
200
|
success: validation.valid && confluenceCreated,
|
|
160
201
|
confluenceCreated,
|
|
161
202
|
jiraCreated: false,
|
|
162
203
|
validationPassed: validation.valid,
|
|
163
|
-
errors
|
|
204
|
+
errors,
|
|
164
205
|
};
|
|
165
206
|
}
|
|
166
207
|
|
|
@@ -170,45 +211,142 @@ async function runDesignPhase(feature: string): Promise<PhaseRunResult> {
|
|
|
170
211
|
async function runTasksPhase(feature: string): Promise<PhaseRunResult> {
|
|
171
212
|
console.log('\n📝 Phase: Tasks(タスク分割)');
|
|
172
213
|
console.log('='.repeat(60));
|
|
173
|
-
|
|
214
|
+
|
|
174
215
|
const errors: string[] = [];
|
|
175
216
|
let jiraCreated = false;
|
|
176
|
-
|
|
217
|
+
|
|
177
218
|
// Step 0: プリフライトチェック
|
|
178
219
|
console.log('\n🔍 プリフライトチェック...');
|
|
179
220
|
const preFlightResult = await runPreFlightCheck('jira');
|
|
180
|
-
|
|
221
|
+
|
|
181
222
|
if (!preFlightResult.valid) {
|
|
182
223
|
console.log('\n❌ プリフライトチェック失敗:');
|
|
183
|
-
preFlightResult.errors.forEach(e => console.log(` ${e}`));
|
|
224
|
+
preFlightResult.errors.forEach((e) => console.log(` ${e}`));
|
|
184
225
|
return {
|
|
185
226
|
phase: 'tasks',
|
|
186
227
|
success: false,
|
|
187
228
|
confluenceCreated: false,
|
|
188
229
|
jiraCreated: false,
|
|
189
230
|
validationPassed: false,
|
|
190
|
-
errors: preFlightResult.errors
|
|
231
|
+
errors: preFlightResult.errors,
|
|
191
232
|
};
|
|
192
233
|
}
|
|
193
|
-
|
|
234
|
+
|
|
194
235
|
console.log('✅ プリフライトチェック成功');
|
|
195
|
-
|
|
236
|
+
|
|
196
237
|
// Step 1: tasks.md存在確認
|
|
197
238
|
const tasksPath = join(process.cwd(), '.kiro', 'specs', feature, 'tasks.md');
|
|
198
239
|
if (!existsSync(tasksPath)) {
|
|
199
|
-
errors.push(
|
|
240
|
+
errors.push(
|
|
241
|
+
'tasks.mdが存在しません。先に/kiro:spec-tasks を実行してください',
|
|
242
|
+
);
|
|
200
243
|
return {
|
|
201
244
|
phase: 'tasks',
|
|
202
245
|
success: false,
|
|
203
246
|
confluenceCreated: false,
|
|
204
247
|
jiraCreated: false,
|
|
205
248
|
validationPassed: false,
|
|
206
|
-
errors
|
|
249
|
+
errors,
|
|
207
250
|
};
|
|
208
251
|
}
|
|
209
|
-
|
|
252
|
+
|
|
210
253
|
console.log('✅ tasks.md 存在確認');
|
|
211
|
-
|
|
254
|
+
|
|
255
|
+
// Step 1.5: AI-DLC形式検出と変換提案
|
|
256
|
+
console.log('\n🔍 tasks.mdフォーマット検証中...');
|
|
257
|
+
const { isAIDLCFormat } = await import('./utils/aidlc-parser.js');
|
|
258
|
+
const tasksContent = readFileSync(tasksPath, 'utf-8');
|
|
259
|
+
|
|
260
|
+
if (isAIDLCFormat(tasksContent)) {
|
|
261
|
+
console.log('\n⚠️ AI-DLC形式が検出されました');
|
|
262
|
+
console.log(' tasks.mdはMichiワークフロー形式ではなくAI-DLC形式です。');
|
|
263
|
+
console.log('');
|
|
264
|
+
console.log('🔄 変換オプション:');
|
|
265
|
+
console.log(` michi tasks:convert ${feature} --dry-run # プレビュー`);
|
|
266
|
+
console.log(
|
|
267
|
+
` michi tasks:convert ${feature} --backup # バックアップ付きで変換`,
|
|
268
|
+
);
|
|
269
|
+
console.log(` michi tasks:convert ${feature} # 直接変換`);
|
|
270
|
+
console.log('');
|
|
271
|
+
|
|
272
|
+
// 対話的に変換を提案
|
|
273
|
+
const shouldConvert = await inquirer.prompt([
|
|
274
|
+
{
|
|
275
|
+
type: 'confirm',
|
|
276
|
+
name: 'convert',
|
|
277
|
+
message: 'AI-DLC形式をMichiワークフロー形式に変換しますか?',
|
|
278
|
+
default: true,
|
|
279
|
+
},
|
|
280
|
+
]);
|
|
281
|
+
|
|
282
|
+
if (shouldConvert.convert) {
|
|
283
|
+
console.log('\n🔄 AI-DLC形式をMichiワークフロー形式に変換中...');
|
|
284
|
+
const { convertTasksFile } = await import('./utils/tasks-converter.js');
|
|
285
|
+
const result = convertTasksFile(tasksPath, undefined, {
|
|
286
|
+
backup: true,
|
|
287
|
+
language: 'ja',
|
|
288
|
+
projectName: feature,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
if (result.success) {
|
|
292
|
+
console.log('✅ 変換成功!');
|
|
293
|
+
console.log(` 元ファイル: ${result.backupPath}`);
|
|
294
|
+
console.log(` 変換後: ${tasksPath}`);
|
|
295
|
+
console.log(
|
|
296
|
+
` 統計: ${result.stats.originalTasks}タスク → ${result.stats.convertedStories}ストーリー`,
|
|
297
|
+
);
|
|
298
|
+
} else {
|
|
299
|
+
errors.push('AI-DLC形式の変換に失敗しました');
|
|
300
|
+
result.warnings.forEach((w) => errors.push(w));
|
|
301
|
+
console.error('❌ 変換失敗');
|
|
302
|
+
return {
|
|
303
|
+
phase: 'tasks',
|
|
304
|
+
success: false,
|
|
305
|
+
confluenceCreated: false,
|
|
306
|
+
jiraCreated: false,
|
|
307
|
+
validationPassed: false,
|
|
308
|
+
errors,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
console.log('\n⏭️ 変換をスキップしました');
|
|
313
|
+
console.log(
|
|
314
|
+
' AI-DLC形式のままではJIRA連携が正常に動作しない可能性があります。',
|
|
315
|
+
);
|
|
316
|
+
errors.push(
|
|
317
|
+
'tasks.mdがAI-DLC形式のため、フォーマット検証をスキップしました',
|
|
318
|
+
);
|
|
319
|
+
return {
|
|
320
|
+
phase: 'tasks',
|
|
321
|
+
success: false,
|
|
322
|
+
confluenceCreated: false,
|
|
323
|
+
jiraCreated: false,
|
|
324
|
+
validationPassed: false,
|
|
325
|
+
errors,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Step 1.6: tasks.mdフォーマット検証
|
|
331
|
+
const { validateTasksFormat } = await import(
|
|
332
|
+
'./utils/tasks-format-validator.js'
|
|
333
|
+
);
|
|
334
|
+
try {
|
|
335
|
+
validateTasksFormat(tasksPath);
|
|
336
|
+
console.log('✅ tasks.mdフォーマット検証成功');
|
|
337
|
+
} catch (error: any) {
|
|
338
|
+
errors.push(`フォーマット検証失敗: ${error.message}`);
|
|
339
|
+
console.error('❌ フォーマット検証失敗:', error.message);
|
|
340
|
+
return {
|
|
341
|
+
phase: 'tasks',
|
|
342
|
+
success: false,
|
|
343
|
+
confluenceCreated: false,
|
|
344
|
+
jiraCreated: false,
|
|
345
|
+
validationPassed: false,
|
|
346
|
+
errors,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
212
350
|
// Step 2: JIRA Epic/Story作成
|
|
213
351
|
console.log('\n📤 JIRA Epic/Story作成中...');
|
|
214
352
|
try {
|
|
@@ -219,49 +357,883 @@ async function runTasksPhase(feature: string): Promise<PhaseRunResult> {
|
|
|
219
357
|
errors.push(`JIRA作成失敗: ${error.message}`);
|
|
220
358
|
console.error('❌ JIRA作成失敗:', error.message);
|
|
221
359
|
}
|
|
222
|
-
|
|
360
|
+
|
|
223
361
|
// Step 3: バリデーション
|
|
224
362
|
console.log('\n🔍 バリデーション実行中...');
|
|
225
363
|
const validation = validatePhase(feature, 'tasks');
|
|
226
364
|
errors.push(...validation.errors);
|
|
227
|
-
|
|
365
|
+
|
|
228
366
|
// Step 4: 結果サマリー
|
|
229
367
|
console.log('\n' + '='.repeat(60));
|
|
230
368
|
console.log('📊 タスク分割フェーズ完了チェック:');
|
|
231
369
|
console.log(' ✅ tasks.md: 作成済み');
|
|
232
|
-
console.log(
|
|
233
|
-
|
|
234
|
-
|
|
370
|
+
console.log(
|
|
371
|
+
` ${jiraCreated ? '✅' : '❌'} JIRA Epic/Story: ${jiraCreated ? '作成済み' : '未作成'}`,
|
|
372
|
+
);
|
|
373
|
+
console.log(
|
|
374
|
+
` ${validation.valid ? '✅' : '❌'} バリデーション: ${validation.valid ? '成功' : '失敗'}`,
|
|
375
|
+
);
|
|
376
|
+
|
|
235
377
|
if (validation.valid && jiraCreated) {
|
|
236
378
|
console.log('\n🎉 タスク分割フェーズが完了しました!');
|
|
237
379
|
console.log('📢 開発チームに実装開始を通知してください');
|
|
238
380
|
console.log('🚀 次のステップ: /kiro:spec-impl <feature>');
|
|
239
381
|
}
|
|
240
|
-
|
|
382
|
+
|
|
241
383
|
return {
|
|
242
384
|
phase: 'tasks',
|
|
243
385
|
success: validation.valid && jiraCreated,
|
|
244
386
|
confluenceCreated: false,
|
|
245
387
|
jiraCreated,
|
|
246
388
|
validationPassed: validation.valid,
|
|
247
|
-
errors
|
|
389
|
+
errors,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* テストタイプ選択フェーズを実行(Phase 0.3)
|
|
395
|
+
* 対話的にテストタイプを選択
|
|
396
|
+
*/
|
|
397
|
+
async function runTestTypeSelectionPhase(
|
|
398
|
+
feature: string,
|
|
399
|
+
): Promise<PhaseRunResult> {
|
|
400
|
+
console.log('\n🧪 Phase 0.3: Test Type Selection(テストタイプ選択)');
|
|
401
|
+
console.log('='.repeat(60));
|
|
402
|
+
|
|
403
|
+
const errors: string[] = [];
|
|
404
|
+
const specDir = join(process.cwd(), '.kiro', 'specs', feature);
|
|
405
|
+
const selectionPath = join(specDir, 'test-type-selection.json');
|
|
406
|
+
|
|
407
|
+
// 既存の選択を読み込む(存在する場合)
|
|
408
|
+
let existingSelection: any = null;
|
|
409
|
+
if (existsSync(selectionPath)) {
|
|
410
|
+
try {
|
|
411
|
+
existingSelection = JSON.parse(readFileSync(selectionPath, 'utf-8'));
|
|
412
|
+
console.log('\n📋 既存の選択が見つかりました:');
|
|
413
|
+
console.log(
|
|
414
|
+
` 選択済みテストタイプ: ${existingSelection.selectedTypes?.join(', ') || 'なし'}`,
|
|
415
|
+
);
|
|
416
|
+
} catch {
|
|
417
|
+
console.warn('⚠️ 既存の選択ファイルの読み込みに失敗しました');
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
console.log('\n📚 プロジェクト要件に応じてテストタイプを選択してください\n');
|
|
422
|
+
|
|
423
|
+
// 対話的な質問
|
|
424
|
+
const answers = await inquirer.prompt([
|
|
425
|
+
{
|
|
426
|
+
type: 'checkbox',
|
|
427
|
+
name: 'testTypes',
|
|
428
|
+
message:
|
|
429
|
+
'実施するテストタイプを選択してください(スペースキーで選択/解除、Enterで確定):',
|
|
430
|
+
choices: [
|
|
431
|
+
{
|
|
432
|
+
name: '単体テスト (Unit Tests) - 必須 [Phase A]',
|
|
433
|
+
value: 'unit',
|
|
434
|
+
checked: true, // 必須のためデフォルトで選択
|
|
435
|
+
disabled: true, // 必須のため変更不可
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
name: 'Lint実行 - 必須 [Phase A]',
|
|
439
|
+
value: 'lint',
|
|
440
|
+
checked: true,
|
|
441
|
+
disabled: true,
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
name: 'ビルド実行 - 必須 [Phase A]',
|
|
445
|
+
value: 'build',
|
|
446
|
+
checked: true,
|
|
447
|
+
disabled: true,
|
|
448
|
+
},
|
|
449
|
+
new inquirer.Separator('--- 推奨テスト ---'),
|
|
450
|
+
{
|
|
451
|
+
name: '統合テスト (Integration Tests) - 推奨 [Phase 3/B]',
|
|
452
|
+
value: 'integration',
|
|
453
|
+
checked:
|
|
454
|
+
existingSelection?.selectedTypes?.includes('integration') || false,
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
name: 'E2Eテスト (End-to-End Tests) - 推奨 [Phase 3/B]',
|
|
458
|
+
value: 'e2e',
|
|
459
|
+
checked: existingSelection?.selectedTypes?.includes('e2e') || false,
|
|
460
|
+
},
|
|
461
|
+
new inquirer.Separator('--- 任意テスト ---'),
|
|
462
|
+
{
|
|
463
|
+
name: '性能テスト (Performance Tests) - 任意 [Phase B]',
|
|
464
|
+
value: 'performance',
|
|
465
|
+
checked:
|
|
466
|
+
existingSelection?.selectedTypes?.includes('performance') || false,
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
name: 'セキュリティテスト (Security Tests) - 任意 [Phase B]',
|
|
470
|
+
value: 'security',
|
|
471
|
+
checked:
|
|
472
|
+
existingSelection?.selectedTypes?.includes('security') || false,
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
validate: () => {
|
|
476
|
+
// disabled項目は自動的に含まれるため、バリデーションは常に成功
|
|
477
|
+
return true;
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
type: 'confirm',
|
|
482
|
+
name: 'confirm',
|
|
483
|
+
message: (answers: any) => {
|
|
484
|
+
// 必須テストを自動的に追加
|
|
485
|
+
const required = ['unit', 'lint', 'build'];
|
|
486
|
+
const selected = [...new Set([...required, ...answers.testTypes])];
|
|
487
|
+
const optional = selected.filter((t: string) => !required.includes(t));
|
|
488
|
+
if (optional.length === 0) {
|
|
489
|
+
return '必須テストのみが選択されています。この選択で進めますか?';
|
|
490
|
+
}
|
|
491
|
+
return `選択したテストタイプ: ${selected.join(', ')}\nこの選択で進めますか?`;
|
|
492
|
+
},
|
|
493
|
+
default: true,
|
|
494
|
+
},
|
|
495
|
+
]);
|
|
496
|
+
|
|
497
|
+
// 必須テストを自動的に追加(disabled項目はanswers.testTypesに含まれないため)
|
|
498
|
+
const requiredTests = ['unit', 'lint', 'build'];
|
|
499
|
+
answers.testTypes = [...new Set([...requiredTests, ...answers.testTypes])];
|
|
500
|
+
|
|
501
|
+
if (!answers.confirm) {
|
|
502
|
+
console.log('\n❌ 選択がキャンセルされました');
|
|
503
|
+
return {
|
|
504
|
+
phase: 'test-type-selection' as Phase,
|
|
505
|
+
success: false,
|
|
506
|
+
confluenceCreated: false,
|
|
507
|
+
jiraCreated: false,
|
|
508
|
+
validationPassed: false,
|
|
509
|
+
errors: ['ユーザーが選択をキャンセルしました'],
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// 選択結果を保存
|
|
514
|
+
const selection = {
|
|
515
|
+
feature,
|
|
516
|
+
selectedTypes: answers.testTypes,
|
|
517
|
+
selectedAt: new Date().toISOString(),
|
|
518
|
+
testTypes: {
|
|
519
|
+
unit: {
|
|
520
|
+
enabled: true,
|
|
521
|
+
required: true,
|
|
522
|
+
phase: 'A',
|
|
523
|
+
description: '単体テスト',
|
|
524
|
+
},
|
|
525
|
+
lint: {
|
|
526
|
+
enabled: true,
|
|
527
|
+
required: true,
|
|
528
|
+
phase: 'A',
|
|
529
|
+
description: 'Lint実行',
|
|
530
|
+
},
|
|
531
|
+
build: {
|
|
532
|
+
enabled: true,
|
|
533
|
+
required: true,
|
|
534
|
+
phase: 'A',
|
|
535
|
+
description: 'ビルド実行',
|
|
536
|
+
},
|
|
537
|
+
integration: {
|
|
538
|
+
enabled: answers.testTypes.includes('integration'),
|
|
539
|
+
required: false,
|
|
540
|
+
phase: 'B',
|
|
541
|
+
description: '統合テスト',
|
|
542
|
+
},
|
|
543
|
+
e2e: {
|
|
544
|
+
enabled: answers.testTypes.includes('e2e'),
|
|
545
|
+
required: false,
|
|
546
|
+
phase: 'B',
|
|
547
|
+
description: 'E2Eテスト',
|
|
548
|
+
},
|
|
549
|
+
performance: {
|
|
550
|
+
enabled: answers.testTypes.includes('performance'),
|
|
551
|
+
required: false,
|
|
552
|
+
phase: 'B',
|
|
553
|
+
description: '性能テスト',
|
|
554
|
+
},
|
|
555
|
+
security: {
|
|
556
|
+
enabled: answers.testTypes.includes('security'),
|
|
557
|
+
required: false,
|
|
558
|
+
phase: 'B',
|
|
559
|
+
description: 'セキュリティテスト',
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// ディレクトリが存在しない場合は作成
|
|
565
|
+
if (!existsSync(specDir)) {
|
|
566
|
+
mkdirSync(specDir, { recursive: true });
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// 選択結果を保存
|
|
570
|
+
writeFileSync(selectionPath, JSON.stringify(selection, null, 2), 'utf-8');
|
|
571
|
+
console.log(`\n✅ テストタイプ選択を保存しました: ${selectionPath}`);
|
|
572
|
+
|
|
573
|
+
// spec.jsonを更新
|
|
574
|
+
try {
|
|
575
|
+
const specPath = join(specDir, 'spec.json');
|
|
576
|
+
if (existsSync(specPath)) {
|
|
577
|
+
const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
|
|
578
|
+
spec.testTypeSelection = {
|
|
579
|
+
completed: true,
|
|
580
|
+
selectedTypes: answers.testTypes,
|
|
581
|
+
selectedAt: selection.selectedAt,
|
|
582
|
+
};
|
|
583
|
+
spec.lastUpdated = new Date().toISOString();
|
|
584
|
+
writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
|
|
585
|
+
console.log('✅ spec.jsonを更新しました');
|
|
586
|
+
}
|
|
587
|
+
} catch (error: any) {
|
|
588
|
+
errors.push(`spec.json更新失敗: ${error.message}`);
|
|
589
|
+
console.warn(`⚠️ spec.json更新失敗: ${error.message}`);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// 選択結果のサマリーを表示
|
|
593
|
+
console.log('\n' + '='.repeat(60));
|
|
594
|
+
console.log('📊 選択結果サマリー:');
|
|
595
|
+
console.log(` 必須テスト: ${['unit', 'lint', 'build'].join(', ')}`);
|
|
596
|
+
const optional = answers.testTypes.filter(
|
|
597
|
+
(t: string) => !['unit', 'lint', 'build'].includes(t),
|
|
598
|
+
);
|
|
599
|
+
if (optional.length > 0) {
|
|
600
|
+
console.log(` 追加テスト: ${optional.join(', ')}`);
|
|
601
|
+
} else {
|
|
602
|
+
console.log(' 追加テスト: なし');
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
console.log('\n📖 次のステップ:');
|
|
606
|
+
console.log(' 1. Phase 0.4: テスト仕様書作成へ進む');
|
|
607
|
+
console.log(' michi phase:run ' + feature + ' test-spec');
|
|
608
|
+
console.log(
|
|
609
|
+
' 2. 詳細ガイド: docs/user-guide/testing/test-planning-flow.md',
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
console.log('\n' + '='.repeat(60));
|
|
613
|
+
console.log('✅ Phase 0.3: テストタイプ選択が完了しました');
|
|
614
|
+
|
|
615
|
+
return {
|
|
616
|
+
phase: 'test-type-selection' as Phase,
|
|
617
|
+
success: true,
|
|
618
|
+
confluenceCreated: false,
|
|
619
|
+
jiraCreated: false,
|
|
620
|
+
validationPassed: true,
|
|
621
|
+
errors,
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* テスト仕様書作成フェーズを実行(Phase 0.4)
|
|
627
|
+
* 自動生成: test-type-selectionから選択されたテストタイプの仕様書を生成
|
|
628
|
+
*/
|
|
629
|
+
async function runTestSpecPhase(feature: string): Promise<PhaseRunResult> {
|
|
630
|
+
console.log('\n📝 Phase 0.4: Test Specification(テスト仕様書作成)');
|
|
631
|
+
console.log('='.repeat(60));
|
|
632
|
+
|
|
633
|
+
const errors: string[] = [];
|
|
634
|
+
|
|
635
|
+
// Step 1: テストタイプ選択の読み込み
|
|
636
|
+
const selectionPath = join(
|
|
637
|
+
process.cwd(),
|
|
638
|
+
'.kiro',
|
|
639
|
+
'specs',
|
|
640
|
+
feature,
|
|
641
|
+
'test-type-selection.json',
|
|
642
|
+
);
|
|
643
|
+
if (!existsSync(selectionPath)) {
|
|
644
|
+
errors.push(
|
|
645
|
+
'test-type-selection.jsonが存在しません。先にtest-type-selectionフェーズを実行してください',
|
|
646
|
+
);
|
|
647
|
+
return {
|
|
648
|
+
phase: 'test-spec' as Phase,
|
|
649
|
+
success: false,
|
|
650
|
+
confluenceCreated: false,
|
|
651
|
+
jiraCreated: false,
|
|
652
|
+
validationPassed: false,
|
|
653
|
+
errors,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
let selection: { selectedTypes?: string[] };
|
|
658
|
+
let testTypes: string[] = [];
|
|
659
|
+
|
|
660
|
+
try {
|
|
661
|
+
selection = JSON.parse(readFileSync(selectionPath, 'utf-8'));
|
|
662
|
+
testTypes = selection.selectedTypes || [];
|
|
663
|
+
} catch (error) {
|
|
664
|
+
errors.push(
|
|
665
|
+
`test-type-selection.jsonの読み込みまたはパースに失敗しました: ${error instanceof Error ? error.message : String(error)}`,
|
|
666
|
+
);
|
|
667
|
+
return {
|
|
668
|
+
phase: 'test-spec' as Phase,
|
|
669
|
+
success: false,
|
|
670
|
+
confluenceCreated: false,
|
|
671
|
+
jiraCreated: false,
|
|
672
|
+
validationPassed: false,
|
|
673
|
+
errors,
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
console.log(`\n✅ 選択されたテストタイプ: ${testTypes.join(', ')}`);
|
|
678
|
+
|
|
679
|
+
// Step 2: 各テストタイプのテスト仕様書を生成
|
|
680
|
+
console.log('\n🤖 テスト仕様書を自動生成中...');
|
|
681
|
+
|
|
682
|
+
const specDir = join(process.cwd(), '.kiro', 'specs', feature, 'test-specs');
|
|
683
|
+
mkdirSync(specDir, { recursive: true });
|
|
684
|
+
|
|
685
|
+
const { generateTestSpec } = await import('./test-spec-generator.js');
|
|
686
|
+
const generatedSpecs: string[] = [];
|
|
687
|
+
|
|
688
|
+
for (const testType of testTypes) {
|
|
689
|
+
// lint/buildはテスト仕様書不要(CI設定で対応)
|
|
690
|
+
if (testType === 'lint' || testType === 'build') {
|
|
691
|
+
console.log(` ⏭️ ${testType}: スキップ(CI設定で対応)`);
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
try {
|
|
696
|
+
await generateTestSpec(feature, testType);
|
|
697
|
+
console.log(` ✅ ${testType}テスト仕様書: ${testType}-test-spec.md`);
|
|
698
|
+
generatedSpecs.push(testType);
|
|
699
|
+
} catch (error: any) {
|
|
700
|
+
errors.push(`${testType}テスト仕様書生成失敗: ${error.message}`);
|
|
701
|
+
console.error(` ❌ ${testType}テスト仕様書生成失敗: ${error.message}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Step 3: spec.json更新
|
|
706
|
+
const specPath = join(process.cwd(), '.kiro', 'specs', feature, 'spec.json');
|
|
707
|
+
if (existsSync(specPath)) {
|
|
708
|
+
try {
|
|
709
|
+
const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
|
|
710
|
+
spec.testSpecification = {
|
|
711
|
+
completed: true,
|
|
712
|
+
generatedAt: new Date().toISOString(),
|
|
713
|
+
testTypes: testTypes,
|
|
714
|
+
generatedSpecs: generatedSpecs,
|
|
715
|
+
};
|
|
716
|
+
spec.lastUpdated = new Date().toISOString();
|
|
717
|
+
writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
|
|
718
|
+
console.log('\n✅ spec.jsonを更新しました');
|
|
719
|
+
} catch (error: any) {
|
|
720
|
+
errors.push(`spec.json更新失敗: ${error.message}`);
|
|
721
|
+
console.warn(`⚠️ spec.json更新失敗: ${error.message}`);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Step 4: サマリー表示
|
|
726
|
+
console.log('\n' + '='.repeat(60));
|
|
727
|
+
console.log('📊 テスト仕様書作成完了:');
|
|
728
|
+
console.log(` 生成されたファイル: ${generatedSpecs.length}件`);
|
|
729
|
+
console.log(` 保存先: .kiro/specs/${feature}/test-specs/`);
|
|
730
|
+
|
|
731
|
+
if (generatedSpecs.length > 0) {
|
|
732
|
+
console.log('\n📄 生成されたファイル:');
|
|
733
|
+
generatedSpecs.forEach((type) => {
|
|
734
|
+
console.log(` - ${type}-test-spec.md`);
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
console.log('\n📖 次のステップ:');
|
|
739
|
+
console.log(' 1. Phase 0.5: タスク分割へ進む');
|
|
740
|
+
console.log(` michi phase:run ${feature} tasks`);
|
|
741
|
+
|
|
742
|
+
console.log('\n' + '='.repeat(60));
|
|
743
|
+
console.log('✅ Phase 0.4: テスト仕様書作成が完了しました');
|
|
744
|
+
|
|
745
|
+
return {
|
|
746
|
+
phase: 'test-spec' as Phase,
|
|
747
|
+
success: errors.length === 0 && generatedSpecs.length > 0,
|
|
748
|
+
confluenceCreated: false,
|
|
749
|
+
jiraCreated: false,
|
|
750
|
+
validationPassed: true,
|
|
751
|
+
errors,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* 環境構築フェーズを実行(Phase 1)
|
|
757
|
+
* 対話的に環境を構築し、必要な設定ファイルを生成
|
|
758
|
+
*/
|
|
759
|
+
async function runEnvironmentSetupPhase(
|
|
760
|
+
feature: string,
|
|
761
|
+
): Promise<PhaseRunResult> {
|
|
762
|
+
console.log('\n⚙️ Phase 1: Environment Setup(環境構築)');
|
|
763
|
+
console.log('='.repeat(60));
|
|
764
|
+
|
|
765
|
+
const errors: string[] = [];
|
|
766
|
+
|
|
767
|
+
// Step 1: プロジェクト検出
|
|
768
|
+
const { detectProject } = await import('./utils/project-detector.js');
|
|
769
|
+
const detected = detectProject();
|
|
770
|
+
|
|
771
|
+
console.log(`\n🔍 検出されたプロジェクト: ${detected.language}`);
|
|
772
|
+
console.log(` ビルドツール: ${detected.buildTool}`);
|
|
773
|
+
if (detected.testFramework) {
|
|
774
|
+
console.log(` テストフレームワーク: ${detected.testFramework}`);
|
|
775
|
+
}
|
|
776
|
+
if (detected.hasCI) {
|
|
777
|
+
console.log(' CI/CD: 既存の設定あり');
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Step 2: 実装言語を分析
|
|
781
|
+
const { analyzeLanguage } = await import('./utils/language-detector.js');
|
|
782
|
+
const languageAnalysis = analyzeLanguage(feature);
|
|
783
|
+
|
|
784
|
+
if (languageAnalysis.confidence !== 'low') {
|
|
785
|
+
console.log(
|
|
786
|
+
`\n💡 実装言語を推奨します: ${languageAnalysis.language}(信頼度: ${languageAnalysis.confidence})`,
|
|
787
|
+
);
|
|
788
|
+
console.log(' 理由:');
|
|
789
|
+
languageAnalysis.reasons.forEach((reason) => console.log(` - ${reason}`));
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Step 3: Docker Compose要件を分析
|
|
793
|
+
const { analyzeDockerRequirement } = await import(
|
|
794
|
+
'./utils/docker-requirement-detector.js'
|
|
795
|
+
);
|
|
796
|
+
const dockerAnalysis = analyzeDockerRequirement(feature);
|
|
797
|
+
|
|
798
|
+
if (dockerAnalysis.recommended) {
|
|
799
|
+
console.log(
|
|
800
|
+
`\n💡 Docker Composeを推奨します(信頼度: ${dockerAnalysis.confidence})`,
|
|
801
|
+
);
|
|
802
|
+
console.log(' 理由:');
|
|
803
|
+
dockerAnalysis.reasons.forEach((reason) => console.log(` - ${reason}`));
|
|
804
|
+
if (dockerAnalysis.suggestedServices.length > 0) {
|
|
805
|
+
console.log(
|
|
806
|
+
` 推奨サービス: ${dockerAnalysis.suggestedServices.join(', ')}`,
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// Step 4: 対話的質問
|
|
812
|
+
console.log('\n📚 環境構築を対話的に設定します\n');
|
|
813
|
+
|
|
814
|
+
const languageMap: Record<string, string> = {
|
|
815
|
+
nodejs: 'Node.js/TypeScript',
|
|
816
|
+
java: 'Java',
|
|
817
|
+
php: 'PHP',
|
|
818
|
+
python: 'Python',
|
|
819
|
+
go: 'Go',
|
|
820
|
+
rust: 'Rust',
|
|
821
|
+
other: 'その他',
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
// 言語のデフォルト値を決定(分析結果 > プロジェクト検出)
|
|
825
|
+
const defaultLanguage =
|
|
826
|
+
languageAnalysis.confidence !== 'low'
|
|
827
|
+
? languageAnalysis.language
|
|
828
|
+
: languageMap[detected.language] || 'その他';
|
|
829
|
+
|
|
830
|
+
const answers = await inquirer.prompt([
|
|
831
|
+
{
|
|
832
|
+
type: 'list',
|
|
833
|
+
name: 'language',
|
|
834
|
+
message:
|
|
835
|
+
languageAnalysis.confidence !== 'low'
|
|
836
|
+
? `プロジェクトの言語を選択してください(推奨: ${languageAnalysis.language}):`
|
|
837
|
+
: 'プロジェクトの言語を選択してください:',
|
|
838
|
+
choices: [
|
|
839
|
+
'Node.js/TypeScript',
|
|
840
|
+
'Java',
|
|
841
|
+
'PHP',
|
|
842
|
+
'Python',
|
|
843
|
+
'Go',
|
|
844
|
+
'Rust',
|
|
845
|
+
'その他',
|
|
846
|
+
],
|
|
847
|
+
default: defaultLanguage,
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
type: 'list',
|
|
851
|
+
name: 'ciTool',
|
|
852
|
+
message: 'CI/CDツールを選択してください:',
|
|
853
|
+
choices: ['GitHub Actions', 'Screwdriver', 'GitLab CI', 'なし'],
|
|
854
|
+
default: detected.hasCI ? 'GitHub Actions' : 'GitHub Actions',
|
|
855
|
+
},
|
|
856
|
+
{
|
|
857
|
+
type: 'confirm',
|
|
858
|
+
name: 'needsDocker',
|
|
859
|
+
message: dockerAnalysis.recommended
|
|
860
|
+
? `Docker Composeを使用しますか?(推奨: ${dockerAnalysis.confidence})`
|
|
861
|
+
: 'Docker Composeが必要ですか?(データベース・モックサーバー用)',
|
|
862
|
+
default: dockerAnalysis.recommended,
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
type: 'confirm',
|
|
866
|
+
name: 'installDeps',
|
|
867
|
+
message: '依存関係を自動インストールしますか?',
|
|
868
|
+
default: true,
|
|
869
|
+
when: () => detected.hasDependencies,
|
|
870
|
+
},
|
|
871
|
+
]);
|
|
872
|
+
|
|
873
|
+
// Docker Composeの推奨サービスを保存
|
|
874
|
+
answers.suggestedServices = dockerAnalysis.suggestedServices;
|
|
875
|
+
|
|
876
|
+
// Step 3: 設定ファイル生成
|
|
877
|
+
console.log('\n🤖 設定ファイルを生成中...');
|
|
878
|
+
|
|
879
|
+
try {
|
|
880
|
+
const { generateCIConfig } = await import('./utils/ci-generator.js');
|
|
881
|
+
await generateCIConfig(feature, answers);
|
|
882
|
+
} catch (error: any) {
|
|
883
|
+
errors.push(`CI/CD設定生成失敗: ${error.message}`);
|
|
884
|
+
console.error(` ❌ CI/CD設定生成失敗: ${error.message}`);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
try {
|
|
888
|
+
const { generateTestConfig } = await import(
|
|
889
|
+
'./utils/test-config-generator.js'
|
|
890
|
+
);
|
|
891
|
+
await generateTestConfig(feature, answers);
|
|
892
|
+
} catch (error: any) {
|
|
893
|
+
errors.push(`テスト設定生成失敗: ${error.message}`);
|
|
894
|
+
console.error(` ❌ テスト設定生成失敗: ${error.message}`);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (answers.needsDocker) {
|
|
898
|
+
try {
|
|
899
|
+
const { generateDockerCompose } = await import(
|
|
900
|
+
'./utils/docker-generator.js'
|
|
901
|
+
);
|
|
902
|
+
await generateDockerCompose(feature, answers.suggestedServices || []);
|
|
903
|
+
} catch (error: any) {
|
|
904
|
+
errors.push(`Docker Compose生成失敗: ${error.message}`);
|
|
905
|
+
console.error(` ❌ Docker Compose生成失敗: ${error.message}`);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// Step 4: 依存関係インストール(オプション)
|
|
910
|
+
if (answers.installDeps) {
|
|
911
|
+
console.log('\n📦 依存関係をインストール中...');
|
|
912
|
+
|
|
913
|
+
const { execSync } = await import('child_process');
|
|
914
|
+
|
|
915
|
+
// 言語別のビルドファイル存在確認
|
|
916
|
+
const buildFileChecks: Record<string, string> = {
|
|
917
|
+
'Node.js/TypeScript': 'package.json',
|
|
918
|
+
Java: 'build.gradle',
|
|
919
|
+
PHP: 'composer.json',
|
|
920
|
+
Python: 'requirements.txt',
|
|
921
|
+
Go: 'go.mod',
|
|
922
|
+
Rust: 'Cargo.toml',
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
const buildFile = buildFileChecks[answers.language];
|
|
926
|
+
if (!buildFile || !existsSync(buildFile)) {
|
|
927
|
+
console.log(
|
|
928
|
+
` ℹ️ ${buildFile || 'ビルドファイル'}が見つかりません(スキップ)`,
|
|
929
|
+
);
|
|
930
|
+
console.log(
|
|
931
|
+
' 💡 実際のプロジェクトでは、先にプロジェクトを初期化してください',
|
|
932
|
+
);
|
|
933
|
+
} else {
|
|
934
|
+
const commands: Record<string, string> = {
|
|
935
|
+
'Node.js/TypeScript':
|
|
936
|
+
detected.packageManager === 'pnpm'
|
|
937
|
+
? 'pnpm install'
|
|
938
|
+
: detected.packageManager === 'yarn'
|
|
939
|
+
? 'yarn install'
|
|
940
|
+
: 'npm install',
|
|
941
|
+
Java: existsSync('./gradlew')
|
|
942
|
+
? './gradlew build --no-daemon'
|
|
943
|
+
: 'gradle build',
|
|
944
|
+
PHP: 'composer install',
|
|
945
|
+
Python: 'pip install -r requirements.txt',
|
|
946
|
+
Go: 'go mod download',
|
|
947
|
+
Rust: 'cargo fetch',
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
const command = commands[answers.language];
|
|
951
|
+
if (command) {
|
|
952
|
+
try {
|
|
953
|
+
execSync(command, { stdio: 'inherit', cwd: process.cwd() });
|
|
954
|
+
console.log(' ✅ 依存関係のインストール完了');
|
|
955
|
+
} catch (error: any) {
|
|
956
|
+
console.warn(` ⚠️ 依存関係インストール失敗: ${error.message}`);
|
|
957
|
+
console.warn(
|
|
958
|
+
' 💡 プロジェクト初期化後に手動でインストールしてください',
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// Step 5: spec.json更新
|
|
966
|
+
const specPath = join(process.cwd(), '.kiro', 'specs', feature, 'spec.json');
|
|
967
|
+
if (existsSync(specPath)) {
|
|
968
|
+
try {
|
|
969
|
+
const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
|
|
970
|
+
spec.environmentSetup = {
|
|
971
|
+
completed: true,
|
|
972
|
+
language: answers.language,
|
|
973
|
+
ciTool: answers.ciTool,
|
|
974
|
+
dockerCompose: answers.needsDocker,
|
|
975
|
+
completedAt: new Date().toISOString(),
|
|
976
|
+
};
|
|
977
|
+
spec.lastUpdated = new Date().toISOString();
|
|
978
|
+
writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
|
|
979
|
+
console.log('\n✅ spec.jsonを更新しました');
|
|
980
|
+
} catch (error: any) {
|
|
981
|
+
errors.push(`spec.json更新失敗: ${error.message}`);
|
|
982
|
+
console.warn(`⚠️ spec.json更新失敗: ${error.message}`);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// Step 6: サマリー表示
|
|
987
|
+
console.log('\n' + '='.repeat(60));
|
|
988
|
+
console.log('📊 環境構築完了:');
|
|
989
|
+
console.log(` 言語: ${answers.language}`);
|
|
990
|
+
console.log(` CI/CD: ${answers.ciTool}`);
|
|
991
|
+
console.log(` Docker Compose: ${answers.needsDocker ? 'あり' : 'なし'}`);
|
|
992
|
+
|
|
993
|
+
console.log('\n📖 次のステップ:');
|
|
994
|
+
console.log(' 1. Phase 2: TDD実装へ進む');
|
|
995
|
+
console.log(` /kiro:spec-impl ${feature}`);
|
|
996
|
+
|
|
997
|
+
console.log('\n' + '='.repeat(60));
|
|
998
|
+
console.log('✅ Phase 1: 環境構築が完了しました');
|
|
999
|
+
|
|
1000
|
+
return {
|
|
1001
|
+
phase: 'environment-setup' as Phase,
|
|
1002
|
+
success: errors.length === 0,
|
|
1003
|
+
confluenceCreated: false,
|
|
1004
|
+
jiraCreated: false,
|
|
1005
|
+
validationPassed: true,
|
|
1006
|
+
errors,
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/**
|
|
1011
|
+
* PR前自動テストフェーズを実行(Phase A)
|
|
1012
|
+
* マニュアル対応:CI/CD案内を表示
|
|
1013
|
+
*/
|
|
1014
|
+
async function runPhaseAPhase(feature: string): Promise<PhaseRunResult> {
|
|
1015
|
+
console.log('\n🤖 Phase A: PR前自動テスト(PR Tests)');
|
|
1016
|
+
console.log('='.repeat(60));
|
|
1017
|
+
|
|
1018
|
+
const errors: string[] = [];
|
|
1019
|
+
|
|
1020
|
+
// spec.jsonから言語を読み取る
|
|
1021
|
+
const spec = loadSpecJson(feature);
|
|
1022
|
+
const language = spec.environmentSetup?.language || 'Node.js/TypeScript';
|
|
1023
|
+
const commands = getTestCommands(language);
|
|
1024
|
+
|
|
1025
|
+
console.log('\n📚 このフェーズはCI/CD自動実行です');
|
|
1026
|
+
console.log('PR作成時に以下のテストが自動実行されます:\n');
|
|
1027
|
+
|
|
1028
|
+
console.log('自動実行テスト:');
|
|
1029
|
+
console.log(` - 単体テスト (${commands.test})`);
|
|
1030
|
+
console.log(` - Lint実行 (${commands.lint})`);
|
|
1031
|
+
console.log(` - ビルド実行 (${commands.build})\n`);
|
|
1032
|
+
|
|
1033
|
+
console.log('CI/CD設定ファイル:');
|
|
1034
|
+
console.log(' - .github/workflows/ci.yml');
|
|
1035
|
+
console.log(' - .github/workflows/test.yml\n');
|
|
1036
|
+
|
|
1037
|
+
console.log('📖 詳細ガイド:');
|
|
1038
|
+
console.log(' docs/user-guide/testing/test-execution-flow.md\n');
|
|
1039
|
+
|
|
1040
|
+
console.log('確認事項:');
|
|
1041
|
+
console.log(' [ ] CI/CDパイプラインが正常に動作している');
|
|
1042
|
+
console.log(' [ ] すべての自動テストが成功している');
|
|
1043
|
+
console.log(' [ ] テストカバレッジが95%以上');
|
|
1044
|
+
|
|
1045
|
+
console.log('\n' + '='.repeat(60));
|
|
1046
|
+
console.log('✅ Phase A: PR前自動テスト案内を表示しました');
|
|
1047
|
+
console.log('📢 CI/CDが自動実行します。Phase 3に進んでください');
|
|
1048
|
+
|
|
1049
|
+
return {
|
|
1050
|
+
phase: 'phase-a' as Phase,
|
|
1051
|
+
success: true,
|
|
1052
|
+
confluenceCreated: false,
|
|
1053
|
+
jiraCreated: false,
|
|
1054
|
+
validationPassed: true,
|
|
1055
|
+
errors,
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* リリース準備テストフェーズを実行(Phase B)
|
|
1061
|
+
* テスト実行ファイルを自動生成し、手動テストチェックリストを表示
|
|
1062
|
+
*/
|
|
1063
|
+
async function runPhaseBPhase(feature: string): Promise<PhaseRunResult> {
|
|
1064
|
+
console.log('\n🔍 Phase B: リリース準備テスト(Release Tests)');
|
|
1065
|
+
console.log('='.repeat(60));
|
|
1066
|
+
|
|
1067
|
+
const errors: string[] = [];
|
|
1068
|
+
const generatedFiles: string[] = [];
|
|
1069
|
+
|
|
1070
|
+
// Step 1: テストタイプ選択の読み込み
|
|
1071
|
+
const selectionPath = join(
|
|
1072
|
+
process.cwd(),
|
|
1073
|
+
'.kiro',
|
|
1074
|
+
'specs',
|
|
1075
|
+
feature,
|
|
1076
|
+
'test-type-selection.json',
|
|
1077
|
+
);
|
|
1078
|
+
|
|
1079
|
+
let selectedTypes: string[] = [];
|
|
1080
|
+
if (existsSync(selectionPath)) {
|
|
1081
|
+
try {
|
|
1082
|
+
const selection = JSON.parse(readFileSync(selectionPath, 'utf-8'));
|
|
1083
|
+
selectedTypes = selection.selectedTypes || [];
|
|
1084
|
+
console.log(`\n✅ 選択されたテストタイプ: ${selectedTypes.join(', ')}`);
|
|
1085
|
+
} catch {
|
|
1086
|
+
console.warn('⚠️ test-type-selection.jsonの読み込みに失敗しました');
|
|
1087
|
+
}
|
|
1088
|
+
} else {
|
|
1089
|
+
console.log('\n⚠️ test-type-selection.jsonが存在しません');
|
|
1090
|
+
console.log(' デフォルトのテストタイプを使用します');
|
|
1091
|
+
selectedTypes = [
|
|
1092
|
+
'unit',
|
|
1093
|
+
'lint',
|
|
1094
|
+
'build',
|
|
1095
|
+
'integration',
|
|
1096
|
+
'performance',
|
|
1097
|
+
'security',
|
|
1098
|
+
];
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// Step 2: Phase B対象のテストタイプを抽出
|
|
1102
|
+
const phaseBTypes = selectedTypes.filter(
|
|
1103
|
+
(t) => !['unit', 'lint', 'build'].includes(t),
|
|
1104
|
+
);
|
|
1105
|
+
|
|
1106
|
+
if (phaseBTypes.length > 0) {
|
|
1107
|
+
console.log(`\n📝 Phase B対象テスト: ${phaseBTypes.join(', ')}`);
|
|
1108
|
+
|
|
1109
|
+
// Step 3: テスト実行ファイルを生成
|
|
1110
|
+
console.log('\n🤖 テスト実行ファイルを自動生成中...');
|
|
1111
|
+
|
|
1112
|
+
const { generateTestExecution } = await import(
|
|
1113
|
+
'./test-execution-generator.js'
|
|
1114
|
+
);
|
|
1115
|
+
|
|
1116
|
+
for (const testType of phaseBTypes) {
|
|
1117
|
+
try {
|
|
1118
|
+
const result = await generateTestExecution(feature, testType);
|
|
1119
|
+
|
|
1120
|
+
if (result.success) {
|
|
1121
|
+
console.log(
|
|
1122
|
+
` ✅ ${result.testType}: ${result.files.length}ファイル生成`,
|
|
1123
|
+
);
|
|
1124
|
+
generatedFiles.push(...result.files);
|
|
1125
|
+
} else {
|
|
1126
|
+
console.error(` ❌ ${result.testType}: ${result.error}`);
|
|
1127
|
+
errors.push(`${result.testType}テスト生成失敗: ${result.error}`);
|
|
1128
|
+
}
|
|
1129
|
+
} catch (error: any) {
|
|
1130
|
+
errors.push(`${testType}テスト生成失敗: ${error.message}`);
|
|
1131
|
+
console.error(`❌ ${testType}テスト生成失敗:`, error.message);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
// Step 4: 生成されたファイルのサマリー
|
|
1137
|
+
const testExecutionDir = join(
|
|
1138
|
+
process.cwd(),
|
|
1139
|
+
'.kiro',
|
|
1140
|
+
'specs',
|
|
1141
|
+
feature,
|
|
1142
|
+
'test-execution',
|
|
1143
|
+
);
|
|
1144
|
+
if (generatedFiles.length > 0) {
|
|
1145
|
+
console.log('\n📄 生成されたファイル:');
|
|
1146
|
+
generatedFiles.forEach((file) => {
|
|
1147
|
+
const relativePath = relative(testExecutionDir, file);
|
|
1148
|
+
console.log(` - ${relativePath}`);
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// Step 5: チェックリスト表示
|
|
1153
|
+
console.log('\n' + '='.repeat(60));
|
|
1154
|
+
console.log('📋 リリース準備テストチェックリスト:\n');
|
|
1155
|
+
|
|
1156
|
+
if (phaseBTypes.includes('performance')) {
|
|
1157
|
+
console.log(' [ ] 性能テスト実行');
|
|
1158
|
+
console.log(` 📁 .kiro/specs/${feature}/test-execution/performance/`);
|
|
1159
|
+
console.log(' 📖 詳細はディレクトリ内のREADME/計画書を参照');
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
if (phaseBTypes.includes('security')) {
|
|
1163
|
+
console.log(' [ ] セキュリティテスト実行');
|
|
1164
|
+
console.log(` 📁 .kiro/specs/${feature}/test-execution/security/`);
|
|
1165
|
+
console.log(' 📖 詳細はディレクトリ内のREADME/計画書を参照');
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
if (phaseBTypes.includes('integration')) {
|
|
1169
|
+
console.log(' [ ] 統合テスト実行');
|
|
1170
|
+
console.log(` 📁 .kiro/specs/${feature}/test-execution/integration/`);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
if (phaseBTypes.includes('e2e')) {
|
|
1174
|
+
console.log(' [ ] E2Eテスト実行');
|
|
1175
|
+
console.log(` 📁 .kiro/specs/${feature}/test-execution/e2e/`);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
console.log('\n参考ドキュメント:');
|
|
1179
|
+
console.log(` - .kiro/specs/${feature}/test-specs/ (テスト仕様書)`);
|
|
1180
|
+
console.log(' - docs/user-guide/testing/test-execution-flow.md');
|
|
1181
|
+
|
|
1182
|
+
console.log('\n次のステップ:');
|
|
1183
|
+
console.log(' 1. 生成されたテストファイルを確認・編集');
|
|
1184
|
+
console.log(' 2. 各テストを実行');
|
|
1185
|
+
console.log(' 3. テスト結果をドキュメント化');
|
|
1186
|
+
console.log(' 4. Phase 4: リリース準備へ進む');
|
|
1187
|
+
|
|
1188
|
+
console.log('\n' + '='.repeat(60));
|
|
1189
|
+
const success = errors.length === 0;
|
|
1190
|
+
if (success) {
|
|
1191
|
+
console.log('✅ Phase B: テスト実行ファイル生成が完了しました');
|
|
1192
|
+
console.log('📢 テストを実行してPhase 4に進んでください');
|
|
1193
|
+
} else {
|
|
1194
|
+
console.log('⚠️ Phase B: テスト実行ファイル生成が部分的に完了しました');
|
|
1195
|
+
console.log(`❌ ${errors.length}件のエラーが発生しています`);
|
|
1196
|
+
errors.forEach((err) => console.log(` - ${err}`));
|
|
1197
|
+
console.log('📢 エラーを修正してから再実行してください');
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
return {
|
|
1201
|
+
phase: 'phase-b' as Phase,
|
|
1202
|
+
success,
|
|
1203
|
+
confluenceCreated: false,
|
|
1204
|
+
jiraCreated: false,
|
|
1205
|
+
validationPassed: true,
|
|
1206
|
+
errors,
|
|
248
1207
|
};
|
|
249
1208
|
}
|
|
250
1209
|
|
|
251
1210
|
/**
|
|
252
1211
|
* フェーズを実行
|
|
253
1212
|
*/
|
|
254
|
-
export async function runPhase(
|
|
1213
|
+
export async function runPhase(
|
|
1214
|
+
feature: string,
|
|
1215
|
+
phase: Phase,
|
|
1216
|
+
): Promise<PhaseRunResult> {
|
|
255
1217
|
// feature名のバリデーション(必須)
|
|
256
1218
|
validateFeatureNameOrThrow(feature);
|
|
257
|
-
|
|
1219
|
+
|
|
258
1220
|
switch (phase) {
|
|
259
1221
|
case 'requirements':
|
|
260
1222
|
return await runRequirementsPhase(feature);
|
|
261
1223
|
case 'design':
|
|
262
1224
|
return await runDesignPhase(feature);
|
|
1225
|
+
case 'test-type-selection':
|
|
1226
|
+
return await runTestTypeSelectionPhase(feature);
|
|
1227
|
+
case 'test-spec':
|
|
1228
|
+
return await runTestSpecPhase(feature);
|
|
263
1229
|
case 'tasks':
|
|
264
1230
|
return await runTasksPhase(feature);
|
|
1231
|
+
case 'environment-setup':
|
|
1232
|
+
return await runEnvironmentSetupPhase(feature);
|
|
1233
|
+
case 'phase-a':
|
|
1234
|
+
return await runPhaseAPhase(feature);
|
|
1235
|
+
case 'phase-b':
|
|
1236
|
+
return await runPhaseBPhase(feature);
|
|
265
1237
|
default:
|
|
266
1238
|
throw new Error(`Unknown phase: ${phase}`);
|
|
267
1239
|
}
|
|
@@ -270,21 +1242,43 @@ export async function runPhase(feature: string, phase: Phase): Promise<PhaseRunR
|
|
|
270
1242
|
// CLI実行
|
|
271
1243
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
272
1244
|
const args = process.argv.slice(2);
|
|
273
|
-
|
|
1245
|
+
|
|
274
1246
|
if (args.length < 2) {
|
|
275
1247
|
console.error('Usage: npm run phase:run <feature> <phase>');
|
|
276
1248
|
console.error('Example: npm run phase:run calculator-app requirements');
|
|
277
|
-
console.error('Phases:
|
|
1249
|
+
console.error('\nAvailable Phases:');
|
|
1250
|
+
console.error(' requirements - Phase 0.1: 要件定義');
|
|
1251
|
+
console.error(' design - Phase 0.2: 設計');
|
|
1252
|
+
console.error(' test-type-selection- Phase 0.3: テストタイプ選択(任意)');
|
|
1253
|
+
console.error(' test-spec - Phase 0.4: テスト仕様書作成(任意)');
|
|
1254
|
+
console.error(' tasks - Phase 0.5-0.6: タスク分割・JIRA同期');
|
|
1255
|
+
console.error(' environment-setup - Phase 1: 環境構築(任意)');
|
|
1256
|
+
console.error(' phase-a - Phase A: PR前自動テスト(任意)');
|
|
1257
|
+
console.error(' phase-b - Phase B: リリース準備テスト(任意)');
|
|
278
1258
|
process.exit(1);
|
|
279
1259
|
}
|
|
280
|
-
|
|
1260
|
+
|
|
281
1261
|
const [feature, phase] = args;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
1262
|
+
|
|
1263
|
+
const validPhases = [
|
|
1264
|
+
'requirements',
|
|
1265
|
+
'design',
|
|
1266
|
+
'test-type-selection',
|
|
1267
|
+
'test-spec',
|
|
1268
|
+
'tasks',
|
|
1269
|
+
'environment-setup',
|
|
1270
|
+
'phase-a',
|
|
1271
|
+
'phase-b',
|
|
1272
|
+
];
|
|
1273
|
+
|
|
1274
|
+
if (!validPhases.includes(phase)) {
|
|
1275
|
+
console.error(`Invalid phase: ${phase}`);
|
|
1276
|
+
console.error(
|
|
1277
|
+
'Must be one of: requirements, design, test-type-selection, test-spec, tasks, environment-setup, phase-a, phase-b',
|
|
1278
|
+
);
|
|
285
1279
|
process.exit(1);
|
|
286
1280
|
}
|
|
287
|
-
|
|
1281
|
+
|
|
288
1282
|
runPhase(feature, phase as Phase)
|
|
289
1283
|
.then((result) => {
|
|
290
1284
|
if (result.success) {
|
|
@@ -300,4 +1294,3 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
300
1294
|
process.exit(1);
|
|
301
1295
|
});
|
|
302
1296
|
}
|
|
303
|
-
|