@sk8metal/michi-cli 0.3.0 → 0.5.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.
Files changed (237) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/scripts/__tests__/spec-impl-workflow.test.js +4 -2
  3. package/dist/scripts/__tests__/spec-impl-workflow.test.js.map +1 -1
  4. package/dist/scripts/config/config-schema.d.ts +52 -0
  5. package/dist/scripts/config/config-schema.d.ts.map +1 -1
  6. package/dist/scripts/config/config-schema.js +25 -0
  7. package/dist/scripts/config/config-schema.js.map +1 -1
  8. package/dist/scripts/config-global.d.ts +10 -0
  9. package/dist/scripts/config-global.d.ts.map +1 -0
  10. package/dist/scripts/config-global.js +111 -0
  11. package/dist/scripts/config-global.js.map +1 -0
  12. package/dist/scripts/confluence-sync.d.ts +22 -4
  13. package/dist/scripts/confluence-sync.d.ts.map +1 -1
  14. package/dist/scripts/confluence-sync.js +22 -12
  15. package/dist/scripts/confluence-sync.js.map +1 -1
  16. package/dist/scripts/jira-sync.d.ts.map +1 -1
  17. package/dist/scripts/jira-sync.js +201 -167
  18. package/dist/scripts/jira-sync.js.map +1 -1
  19. package/dist/scripts/list-projects.js.map +1 -1
  20. package/dist/scripts/multi-project-estimate.js.map +1 -1
  21. package/dist/scripts/phase-runner.d.ts +1 -1
  22. package/dist/scripts/phase-runner.d.ts.map +1 -1
  23. package/dist/scripts/phase-runner.js +295 -522
  24. package/dist/scripts/phase-runner.js.map +1 -1
  25. package/dist/scripts/pr-automation.d.ts.map +1 -1
  26. package/dist/scripts/pr-automation.js +11 -3
  27. package/dist/scripts/pr-automation.js.map +1 -1
  28. package/dist/scripts/pre-flight-check.d.ts.map +1 -1
  29. package/dist/scripts/pre-flight-check.js +10 -6
  30. package/dist/scripts/pre-flight-check.js.map +1 -1
  31. package/dist/scripts/resource-dashboard.js.map +1 -1
  32. package/dist/scripts/spec-impl-workflow.d.ts.map +1 -1
  33. package/dist/scripts/spec-impl-workflow.js +23 -7
  34. package/dist/scripts/spec-impl-workflow.js.map +1 -1
  35. package/dist/scripts/template/renderer.d.ts +1 -1
  36. package/dist/scripts/template/renderer.d.ts.map +1 -1
  37. package/dist/scripts/test-interactive.d.ts.map +1 -1
  38. package/dist/scripts/test-interactive.js +0 -15
  39. package/dist/scripts/test-interactive.js.map +1 -1
  40. package/dist/scripts/test-new-features.js +6 -3
  41. package/dist/scripts/test-new-features.js.map +1 -1
  42. package/dist/scripts/test-spec-generator.d.ts.map +1 -1
  43. package/dist/scripts/test-spec-generator.js +1 -2
  44. package/dist/scripts/test-spec-generator.js.map +1 -1
  45. package/dist/scripts/utils/__tests__/config-loader.test.js +114 -1
  46. package/dist/scripts/utils/__tests__/config-loader.test.js.map +1 -1
  47. package/dist/scripts/utils/__tests__/config-validator.test.js +2 -0
  48. package/dist/scripts/utils/__tests__/config-validator.test.js.map +1 -1
  49. package/dist/scripts/utils/__tests__/env-config.test.js +0 -2
  50. package/dist/scripts/utils/__tests__/env-config.test.js.map +1 -1
  51. package/dist/scripts/utils/__tests__/project-meta.test.d.ts +6 -0
  52. package/dist/scripts/utils/__tests__/project-meta.test.d.ts.map +1 -0
  53. package/dist/scripts/utils/__tests__/project-meta.test.js +154 -0
  54. package/dist/scripts/utils/__tests__/project-meta.test.js.map +1 -0
  55. package/dist/scripts/utils/__tests__/security-validator.test.d.ts +6 -0
  56. package/dist/scripts/utils/__tests__/security-validator.test.d.ts.map +1 -0
  57. package/dist/scripts/utils/__tests__/security-validator.test.js +219 -0
  58. package/dist/scripts/utils/__tests__/security-validator.test.js.map +1 -0
  59. package/dist/scripts/utils/config-loader.d.ts +14 -3
  60. package/dist/scripts/utils/config-loader.d.ts.map +1 -1
  61. package/dist/scripts/utils/config-loader.js +284 -46
  62. package/dist/scripts/utils/config-loader.js.map +1 -1
  63. package/dist/scripts/utils/config-sections.d.ts +54 -0
  64. package/dist/scripts/utils/config-sections.d.ts.map +1 -0
  65. package/dist/scripts/utils/config-sections.js +178 -0
  66. package/dist/scripts/utils/config-sections.js.map +1 -0
  67. package/dist/scripts/utils/config-validator.d.ts +4 -0
  68. package/dist/scripts/utils/config-validator.d.ts.map +1 -1
  69. package/dist/scripts/utils/config-validator.js +57 -1
  70. package/dist/scripts/utils/config-validator.js.map +1 -1
  71. package/dist/scripts/utils/confluence-approval.d.ts.map +1 -1
  72. package/dist/scripts/utils/confluence-approval.js +5 -3
  73. package/dist/scripts/utils/confluence-approval.js.map +1 -1
  74. package/dist/scripts/utils/confluence-hierarchy.d.ts.map +1 -1
  75. package/dist/scripts/utils/confluence-hierarchy.js.map +1 -1
  76. package/dist/scripts/utils/env-config.d.ts +1 -1
  77. package/dist/scripts/utils/env-config.d.ts.map +1 -1
  78. package/dist/scripts/utils/env-config.js +2 -14
  79. package/dist/scripts/utils/env-config.js.map +1 -1
  80. package/dist/scripts/utils/interactive-helpers.d.ts +32 -0
  81. package/dist/scripts/utils/interactive-helpers.d.ts.map +1 -0
  82. package/dist/scripts/utils/interactive-helpers.js +92 -0
  83. package/dist/scripts/utils/interactive-helpers.js.map +1 -0
  84. package/dist/scripts/utils/jira-issue-type-fetcher.d.ts.map +1 -1
  85. package/dist/scripts/utils/jira-issue-type-fetcher.js +27 -18
  86. package/dist/scripts/utils/jira-issue-type-fetcher.js.map +1 -1
  87. package/dist/scripts/utils/project-meta.d.ts +9 -0
  88. package/dist/scripts/utils/project-meta.d.ts.map +1 -1
  89. package/dist/scripts/utils/project-meta.js +22 -0
  90. package/dist/scripts/utils/project-meta.js.map +1 -1
  91. package/dist/scripts/utils/release-notes-generator.d.ts.map +1 -1
  92. package/dist/scripts/utils/release-notes-generator.js +2 -1
  93. package/dist/scripts/utils/release-notes-generator.js.map +1 -1
  94. package/dist/scripts/utils/security-validator.d.ts +55 -0
  95. package/dist/scripts/utils/security-validator.d.ts.map +1 -0
  96. package/dist/scripts/utils/security-validator.js +232 -0
  97. package/dist/scripts/utils/security-validator.js.map +1 -0
  98. package/dist/scripts/utils/spec-updater.d.ts +19 -0
  99. package/dist/scripts/utils/spec-updater.d.ts.map +1 -1
  100. package/dist/scripts/utils/spec-updater.js.map +1 -1
  101. package/dist/scripts/utils/tasks-converter.d.ts.map +1 -1
  102. package/dist/scripts/utils/tasks-converter.js +2 -2
  103. package/dist/scripts/utils/tasks-converter.js.map +1 -1
  104. package/dist/scripts/utils/tasks-format-validator.d.ts.map +1 -1
  105. package/dist/scripts/utils/tasks-format-validator.js +0 -12
  106. package/dist/scripts/utils/tasks-format-validator.js.map +1 -1
  107. package/dist/scripts/utils/test-runner.d.ts.map +1 -1
  108. package/dist/scripts/utils/test-runner.js +3 -2
  109. package/dist/scripts/utils/test-runner.js.map +1 -1
  110. package/dist/scripts/validate-phase.d.ts +1 -1
  111. package/dist/scripts/validate-phase.d.ts.map +1 -1
  112. package/dist/scripts/validate-phase.js +12 -62
  113. package/dist/scripts/validate-phase.js.map +1 -1
  114. package/dist/scripts/workflow-orchestrator.d.ts.map +1 -1
  115. package/dist/scripts/workflow-orchestrator.js +11 -16
  116. package/dist/scripts/workflow-orchestrator.js.map +1 -1
  117. package/dist/src/__tests__/integration/setup/init.test.d.ts +5 -0
  118. package/dist/src/__tests__/integration/setup/init.test.d.ts.map +1 -0
  119. package/dist/src/__tests__/integration/setup/init.test.js +352 -0
  120. package/dist/src/__tests__/integration/setup/init.test.js.map +1 -0
  121. package/dist/src/cli.d.ts.map +1 -1
  122. package/dist/src/cli.js +67 -21
  123. package/dist/src/cli.js.map +1 -1
  124. package/dist/src/commands/__tests__/init.test.d.ts +5 -0
  125. package/dist/src/commands/__tests__/init.test.d.ts.map +1 -0
  126. package/dist/src/commands/__tests__/init.test.js +255 -0
  127. package/dist/src/commands/__tests__/init.test.js.map +1 -0
  128. package/dist/src/commands/__tests__/migrate.test.d.ts +5 -0
  129. package/dist/src/commands/__tests__/migrate.test.d.ts.map +1 -0
  130. package/dist/src/commands/__tests__/migrate.test.js +216 -0
  131. package/dist/src/commands/__tests__/migrate.test.js.map +1 -0
  132. package/dist/src/commands/config-validate.d.ts +9 -0
  133. package/dist/src/commands/config-validate.d.ts.map +1 -0
  134. package/dist/src/commands/config-validate.js +90 -0
  135. package/dist/src/commands/config-validate.js.map +1 -0
  136. package/dist/src/commands/init.d.ts +29 -0
  137. package/dist/src/commands/init.d.ts.map +1 -0
  138. package/dist/src/commands/init.js +513 -0
  139. package/dist/src/commands/init.js.map +1 -0
  140. package/dist/src/commands/migrate.d.ts +25 -0
  141. package/dist/src/commands/migrate.d.ts.map +1 -0
  142. package/dist/src/commands/migrate.js +341 -0
  143. package/dist/src/commands/migrate.js.map +1 -0
  144. package/dist/src/commands/setup-existing.d.ts.map +1 -1
  145. package/dist/src/commands/setup-existing.js +0 -1
  146. package/dist/src/commands/setup-existing.js.map +1 -1
  147. package/dist/vitest.config.d.ts.map +1 -1
  148. package/dist/vitest.config.js +32 -8
  149. package/dist/vitest.config.js.map +1 -1
  150. package/docs/michi-development/design/config-unification.md +4789 -0
  151. package/docs/user-guide/getting-started/github-token-setup.md +2 -1
  152. package/docs/user-guide/getting-started/new-repository-setup.md +1 -1
  153. package/docs/user-guide/getting-started/quick-start.md +1 -1
  154. package/docs/user-guide/getting-started/setup.md +35 -14
  155. package/docs/user-guide/guides/customization.md +64 -11
  156. package/docs/user-guide/guides/workflow.md +35 -21
  157. package/docs/user-guide/hands-on/claude-agent-setup.md +2 -2
  158. package/docs/user-guide/hands-on/claude-setup.md +2 -2
  159. package/docs/user-guide/hands-on/cursor-setup.md +2 -2
  160. package/docs/user-guide/hands-on/workflow-walkthrough.md +4 -1
  161. package/docs/user-guide/reference/config.md +30 -5
  162. package/docs/user-guide/reference/quick-reference.md +68 -74
  163. package/docs/user-guide/testing/test-planning-flow.md +4 -0
  164. package/env.example +1 -1
  165. package/package.json +3 -5
  166. package/scripts/__tests__/spec-impl-workflow.test.ts +5 -2
  167. package/scripts/config/config-schema.ts +40 -0
  168. package/scripts/config-global.ts +160 -0
  169. package/scripts/confluence-sync.ts +91 -27
  170. package/scripts/jira-sync.ts +284 -218
  171. package/scripts/list-projects.ts +2 -2
  172. package/scripts/multi-project-estimate.ts +3 -3
  173. package/scripts/phase-runner.ts +391 -594
  174. package/scripts/pr-automation.ts +15 -5
  175. package/scripts/pre-flight-check.ts +20 -9
  176. package/scripts/pre-publish-check.sh +3 -34
  177. package/scripts/resource-dashboard.ts +4 -4
  178. package/scripts/spec-impl-workflow.ts +23 -7
  179. package/scripts/template/renderer.ts +1 -1
  180. package/scripts/test-interactive.ts +0 -19
  181. package/scripts/test-new-features.ts +10 -7
  182. package/scripts/test-npm-package.sh +3 -34
  183. package/scripts/test-spec-generator.ts +3 -7
  184. package/scripts/utils/__tests__/config-loader.test.ts +149 -0
  185. package/scripts/utils/__tests__/config-validator.test.ts +2 -0
  186. package/scripts/utils/__tests__/env-config.test.ts +0 -2
  187. package/scripts/utils/__tests__/project-meta.test.ts +192 -0
  188. package/scripts/utils/__tests__/security-validator.test.ts +272 -0
  189. package/scripts/utils/config-loader.ts +328 -68
  190. package/scripts/utils/config-sections.ts +316 -0
  191. package/scripts/utils/config-validator.ts +66 -1
  192. package/scripts/utils/confluence-approval.ts +8 -6
  193. package/scripts/utils/confluence-hierarchy.ts +27 -27
  194. package/scripts/utils/env-config.ts +2 -14
  195. package/scripts/utils/interactive-helpers.ts +135 -0
  196. package/scripts/utils/jira-issue-type-fetcher.ts +29 -21
  197. package/scripts/utils/project-meta.ts +27 -0
  198. package/scripts/utils/release-notes-generator.ts +3 -2
  199. package/scripts/utils/security-validator.ts +286 -0
  200. package/scripts/utils/spec-updater.ts +37 -15
  201. package/scripts/utils/tasks-converter.ts +4 -6
  202. package/scripts/utils/tasks-format-validator.ts +0 -13
  203. package/scripts/utils/test-runner.ts +4 -3
  204. package/scripts/validate-phase.ts +21 -80
  205. package/scripts/workflow-orchestrator.ts +16 -25
  206. package/templates/claude/commands/kiro/kiro-spec-impl.md +5 -1
  207. package/templates/claude/commands/kiro/kiro-spec-tasks.md +3 -1
  208. package/templates/claude/commands/michi/confluence-sync.md +8 -2
  209. package/templates/claude/commands/michi/design-review.md +4 -0
  210. package/templates/claude/commands/michi/e2e-plan.md +4 -0
  211. package/templates/claude/commands/michi/license-check.md +4 -0
  212. package/templates/claude/commands/michi/pr-resolve.md +4 -0
  213. package/templates/claude/commands/michi/project-switch.md +8 -2
  214. package/templates/claude/commands/michi/spec-design.md +78 -0
  215. package/templates/claude/commands/michi/spec-impl.md +716 -0
  216. package/templates/claude/commands/michi/test-planning.md +174 -0
  217. package/templates/claude/commands/michi/validate-design.md +58 -0
  218. package/templates/claude/commands/michi/version-audit.md +4 -0
  219. package/templates/claude-agent/commands/kiro/kiro-spec-impl.md +1 -1
  220. package/templates/cursor/commands/kiro/kiro-spec-impl.md +1 -1
  221. package/templates/michi/cc-sdd-overrides/README.md +8 -0
  222. package/templates/michi/cc-sdd-overrides/settings/rules/design-review-michi.md +53 -0
  223. package/dist/scripts/config-interactive.d.ts +0 -10
  224. package/dist/scripts/config-interactive.d.ts.map +0 -1
  225. package/dist/scripts/config-interactive.js +0 -372
  226. package/dist/scripts/config-interactive.js.map +0 -1
  227. package/dist/scripts/setup-existing-project.d.ts +0 -15
  228. package/dist/scripts/setup-existing-project.d.ts.map +0 -1
  229. package/dist/scripts/setup-existing-project.js +0 -455
  230. package/dist/scripts/setup-existing-project.js.map +0 -1
  231. package/dist/scripts/setup-interactive.d.ts +0 -10
  232. package/dist/scripts/setup-interactive.d.ts.map +0 -1
  233. package/dist/scripts/setup-interactive.js +0 -413
  234. package/dist/scripts/setup-interactive.js.map +0 -1
  235. package/scripts/config-interactive.ts +0 -550
  236. package/scripts/setup-existing-project.ts +0 -585
  237. package/scripts/setup-interactive.ts +0 -565
@@ -2,7 +2,7 @@
2
2
  * フェーズランナー
3
3
  * 各フェーズを実行し、Confluence/JIRA作成を確実に実行
4
4
  */
5
- import { existsSync, writeFileSync, readFileSync, mkdirSync } from 'fs';
5
+ import { existsSync, writeFileSync, readFileSync } from 'fs';
6
6
  import { join, relative } from 'path';
7
7
  import { syncToConfluence } from './confluence-sync.js';
8
8
  import { syncTasksToJIRA } from './jira-sync.js';
@@ -43,8 +43,9 @@ async function runRequirementsPhase(feature) {
43
43
  console.log('✅ Confluenceページ作成成功');
44
44
  }
45
45
  catch (error) {
46
- errors.push(`Confluenceページ作成失敗: ${error.message}`);
47
- console.error('❌ Confluenceページ作成失敗:', error.message);
46
+ const message = error instanceof Error ? error.message : String(error);
47
+ errors.push(`Confluenceページ作成失敗: ${message}`);
48
+ console.error('❌ Confluenceページ作成失敗:', message);
48
49
  }
49
50
  // Step 3: バリデーション
50
51
  console.log('\n🔍 バリデーション実行中...');
@@ -107,8 +108,9 @@ async function runDesignPhase(feature) {
107
108
  console.log('✅ Confluenceページ作成成功');
108
109
  }
109
110
  catch (error) {
110
- errors.push(`Confluenceページ作成失敗: ${error.message}`);
111
- console.error('❌ Confluenceページ作成失敗:', error.message);
111
+ const message = error instanceof Error ? error.message : String(error);
112
+ errors.push(`Confluenceページ作成失敗: ${message}`);
113
+ console.error('❌ Confluenceページ作成失敗:', message);
112
114
  }
113
115
  // Step 3: バリデーション
114
116
  console.log('\n🔍 バリデーション実行中...');
@@ -141,126 +143,100 @@ async function runDesignPhase(feature) {
141
143
  };
142
144
  }
143
145
  /**
144
- * タスク分割フェーズを実行
146
+ * タスク分割フェーズの前提条件をチェック
145
147
  */
146
- async function runTasksPhase(feature) {
147
- console.log('\n📝 Phase: Tasks(タスク分割)');
148
- console.log('='.repeat(60));
148
+ async function checkTasksPrerequisites(feature) {
149
149
  const errors = [];
150
- let jiraCreated = false;
151
- // Step 0: プリフライトチェック
150
+ // プリフライトチェック
152
151
  console.log('\n🔍 プリフライトチェック...');
153
152
  const preFlightResult = await runPreFlightCheck('jira');
154
153
  if (!preFlightResult.valid) {
155
154
  console.log('\n❌ プリフライトチェック失敗:');
156
155
  preFlightResult.errors.forEach((e) => console.log(` ${e}`));
157
- return {
158
- phase: 'tasks',
159
- success: false,
160
- confluenceCreated: false,
161
- jiraCreated: false,
162
- validationPassed: false,
163
- errors: preFlightResult.errors,
164
- };
156
+ return { valid: false, errors: preFlightResult.errors };
165
157
  }
166
158
  console.log('✅ プリフライトチェック成功');
167
- // Step 1: tasks.md存在確認
159
+ // tasks.md存在確認
168
160
  const tasksPath = join(process.cwd(), '.kiro', 'specs', feature, 'tasks.md');
169
161
  if (!existsSync(tasksPath)) {
170
162
  errors.push('tasks.mdが存在しません。先に/kiro:spec-tasks を実行してください');
171
- return {
172
- phase: 'tasks',
173
- success: false,
174
- confluenceCreated: false,
175
- jiraCreated: false,
176
- validationPassed: false,
177
- errors,
178
- };
163
+ return { valid: false, errors };
179
164
  }
180
165
  console.log('✅ tasks.md 存在確認');
181
- // Step 1.5: AI-DLC形式検出と変換提案
166
+ return { valid: true, errors: [] };
167
+ }
168
+ /**
169
+ * AI-DLC形式を検出して変換を提案
170
+ */
171
+ async function detectAndConvertAIDLCFormat(feature, tasksPath) {
172
+ const errors = [];
182
173
  console.log('\n🔍 tasks.mdフォーマット検証中...');
183
174
  const { isAIDLCFormat } = await import('./utils/aidlc-parser.js');
184
175
  const tasksContent = readFileSync(tasksPath, 'utf-8');
185
- if (isAIDLCFormat(tasksContent)) {
186
- console.log('\n⚠️ AI-DLC形式が検出されました');
187
- console.log(' tasks.mdはMichiワークフロー形式ではなくAI-DLC形式です。');
188
- console.log('');
189
- console.log('🔄 変換オプション:');
190
- console.log(` michi tasks:convert ${feature} --dry-run # プレビュー`);
191
- console.log(` michi tasks:convert ${feature} --backup # バックアップ付きで変換`);
192
- console.log(` michi tasks:convert ${feature} # 直接変換`);
193
- console.log('');
194
- // 対話的に変換を提案
195
- const shouldConvert = await inquirer.prompt([
196
- {
197
- type: 'confirm',
198
- name: 'convert',
199
- message: 'AI-DLC形式をMichiワークフロー形式に変換しますか?',
200
- default: true,
201
- },
202
- ]);
203
- if (shouldConvert.convert) {
204
- console.log('\n🔄 AI-DLC形式をMichiワークフロー形式に変換中...');
205
- const { convertTasksFile } = await import('./utils/tasks-converter.js');
206
- const result = convertTasksFile(tasksPath, undefined, {
207
- backup: true,
208
- language: 'ja',
209
- projectName: feature,
210
- });
211
- if (result.success) {
212
- console.log('✅ 変換成功!');
213
- console.log(` 元ファイル: ${result.backupPath}`);
214
- console.log(` 変換後: ${tasksPath}`);
215
- console.log(` 統計: ${result.stats.originalTasks}タスク → ${result.stats.convertedStories}ストーリー`);
216
- }
217
- else {
218
- errors.push('AI-DLC形式の変換に失敗しました');
219
- result.warnings.forEach((w) => errors.push(w));
220
- console.error('❌ 変換失敗');
221
- return {
222
- phase: 'tasks',
223
- success: false,
224
- confluenceCreated: false,
225
- jiraCreated: false,
226
- validationPassed: false,
227
- errors,
228
- };
229
- }
230
- }
231
- else {
232
- console.log('\n⏭️ 変換をスキップしました');
233
- console.log(' AI-DLC形式のままではJIRA連携が正常に動作しない可能性があります。');
234
- errors.push('tasks.mdがAI-DLC形式のため、フォーマット検証をスキップしました');
235
- return {
236
- phase: 'tasks',
237
- success: false,
238
- confluenceCreated: false,
239
- jiraCreated: false,
240
- validationPassed: false,
241
- errors,
242
- };
243
- }
244
- }
245
- // Step 1.6: tasks.mdフォーマット検証
176
+ if (!isAIDLCFormat(tasksContent)) {
177
+ return { success: true, errors: [] };
178
+ }
179
+ console.log('\n⚠️ AI-DLC形式が検出されました');
180
+ console.log(' tasks.mdはMichiワークフロー形式ではなくAI-DLC形式です。');
181
+ console.log('');
182
+ console.log('🔄 変換オプション:');
183
+ console.log(` michi tasks:convert ${feature} --dry-run # プレビュー`);
184
+ console.log(` michi tasks:convert ${feature} --backup # バックアップ付きで変換`);
185
+ console.log(` michi tasks:convert ${feature} # 直接変換`);
186
+ console.log('');
187
+ // 対話的に変換を提案
188
+ const shouldConvert = await inquirer.prompt([
189
+ {
190
+ type: 'confirm',
191
+ name: 'convert',
192
+ message: 'AI-DLC形式をMichiワークフロー形式に変換しますか?',
193
+ default: true,
194
+ },
195
+ ]);
196
+ if (!shouldConvert.convert) {
197
+ console.log('\n⏭️ 変換をスキップしました');
198
+ console.log(' AI-DLC形式のままではJIRA連携が正常に動作しない可能性があります。');
199
+ errors.push('tasks.mdがAI-DLC形式のため、フォーマット検証をスキップしました');
200
+ return { success: false, errors };
201
+ }
202
+ console.log('\n🔄 AI-DLC形式をMichiワークフロー形式に変換中...');
203
+ const { convertTasksFile } = await import('./utils/tasks-converter.js');
204
+ const result = convertTasksFile(tasksPath, undefined, {
205
+ backup: true,
206
+ language: 'ja',
207
+ projectName: feature,
208
+ });
209
+ if (result.success) {
210
+ console.log('✅ 変換成功!');
211
+ console.log(` 元ファイル: ${result.backupPath}`);
212
+ console.log(` 変換後: ${tasksPath}`);
213
+ console.log(` 統計: ${result.stats.originalTasks}タスク → ${result.stats.convertedStories}ストーリー`);
214
+ return { success: true, errors: [] };
215
+ }
216
+ errors.push('AI-DLC形式の変換に失敗しました');
217
+ result.warnings.forEach((w) => errors.push(w));
218
+ console.error('❌ 変換失敗');
219
+ return { success: false, errors };
220
+ }
221
+ /**
222
+ * tasks.mdのフォーマット検証とJIRA同期
223
+ */
224
+ async function validateTasksFormatAndSyncJIRA(feature, tasksPath) {
225
+ const errors = [];
226
+ let jiraCreated = false;
227
+ // フォーマット検証
246
228
  const { validateTasksFormat } = await import('./utils/tasks-format-validator.js');
247
229
  try {
248
230
  validateTasksFormat(tasksPath);
249
231
  console.log('✅ tasks.mdフォーマット検証成功');
250
232
  }
251
233
  catch (error) {
252
- errors.push(`フォーマット検証失敗: ${error.message}`);
253
- console.error('❌ フォーマット検証失敗:', error.message);
254
- return {
255
- phase: 'tasks',
256
- success: false,
257
- confluenceCreated: false,
258
- jiraCreated: false,
259
- validationPassed: false,
260
- errors,
261
- };
234
+ const message = error instanceof Error ? error.message : String(error);
235
+ errors.push(`フォーマット検証失敗: ${message}`);
236
+ console.error('❌ フォーマット検証失敗:', message);
237
+ return { jiraCreated: false, errors };
262
238
  }
263
- // Step 2: JIRA Epic/Story作成
239
+ // JIRA Epic/Story作成
264
240
  console.log('\n📤 JIRA Epic/Story作成中...');
265
241
  try {
266
242
  await syncTasksToJIRA(feature);
@@ -268,14 +244,16 @@ async function runTasksPhase(feature) {
268
244
  console.log('✅ JIRA Epic/Story作成成功');
269
245
  }
270
246
  catch (error) {
271
- errors.push(`JIRA作成失敗: ${error.message}`);
272
- console.error('❌ JIRA作成失敗:', error.message);
247
+ const message = error instanceof Error ? error.message : String(error);
248
+ errors.push(`JIRA作成失敗: ${message}`);
249
+ console.error('❌ JIRA作成失敗:', message);
273
250
  }
274
- // Step 3: バリデーション
275
- console.log('\n🔍 バリデーション実行中...');
276
- const validation = validatePhase(feature, 'tasks');
277
- errors.push(...validation.errors);
278
- // Step 4: 結果サマリー
251
+ return { jiraCreated, errors };
252
+ }
253
+ /**
254
+ * タスク分割フェーズのサマリーを表示
255
+ */
256
+ function displayTasksPhaseSummary(jiraCreated, validation) {
279
257
  console.log('\n' + '='.repeat(60));
280
258
  console.log('📊 タスク分割フェーズ完了チェック:');
281
259
  console.log(' ✅ tasks.md: 作成済み');
@@ -286,254 +264,34 @@ async function runTasksPhase(feature) {
286
264
  console.log('📢 開発チームに実装開始を通知してください');
287
265
  console.log('🚀 次のステップ: /kiro:spec-impl <feature>');
288
266
  }
289
- return {
290
- phase: 'tasks',
291
- success: validation.valid && jiraCreated,
292
- confluenceCreated: false,
293
- jiraCreated,
294
- validationPassed: validation.valid,
295
- errors,
296
- };
297
- }
298
- /**
299
- * テストタイプ選択フェーズを実行(Phase 0.3)
300
- * 対話的にテストタイプを選択
301
- */
302
- async function runTestTypeSelectionPhase(feature) {
303
- console.log('\n🧪 Phase 0.3: Test Type Selection(テストタイプ選択)');
304
- console.log('='.repeat(60));
305
- const errors = [];
306
- const specDir = join(process.cwd(), '.kiro', 'specs', feature);
307
- const selectionPath = join(specDir, 'test-type-selection.json');
308
- // 既存の選択を読み込む(存在する場合)
309
- let existingSelection = null;
310
- if (existsSync(selectionPath)) {
311
- try {
312
- existingSelection = JSON.parse(readFileSync(selectionPath, 'utf-8'));
313
- console.log('\n📋 既存の選択が見つかりました:');
314
- console.log(` 選択済みテストタイプ: ${existingSelection.selectedTypes?.join(', ') || 'なし'}`);
315
- }
316
- catch {
317
- console.warn('⚠️ 既存の選択ファイルの読み込みに失敗しました');
318
- }
319
- }
320
- console.log('\n📚 プロジェクト要件に応じてテストタイプを選択してください\n');
321
- // 対話的な質問
322
- const answers = await inquirer.prompt([
323
- {
324
- type: 'checkbox',
325
- name: 'testTypes',
326
- message: '実施するテストタイプを選択してください(スペースキーで選択/解除、Enterで確定):',
327
- choices: [
328
- {
329
- name: '単体テスト (Unit Tests) - 必須 [Phase A]',
330
- value: 'unit',
331
- checked: true, // 必須のためデフォルトで選択
332
- disabled: true, // 必須のため変更不可
333
- },
334
- {
335
- name: 'Lint実行 - 必須 [Phase A]',
336
- value: 'lint',
337
- checked: true,
338
- disabled: true,
339
- },
340
- {
341
- name: 'ビルド実行 - 必須 [Phase A]',
342
- value: 'build',
343
- checked: true,
344
- disabled: true,
345
- },
346
- new inquirer.Separator('--- 推奨テスト ---'),
347
- {
348
- name: '統合テスト (Integration Tests) - 推奨 [Phase 3/B]',
349
- value: 'integration',
350
- checked: existingSelection?.selectedTypes?.includes('integration') || false,
351
- },
352
- {
353
- name: 'E2Eテスト (End-to-End Tests) - 推奨 [Phase 3/B]',
354
- value: 'e2e',
355
- checked: existingSelection?.selectedTypes?.includes('e2e') || false,
356
- },
357
- new inquirer.Separator('--- 任意テスト ---'),
358
- {
359
- name: '性能テスト (Performance Tests) - 任意 [Phase B]',
360
- value: 'performance',
361
- checked: existingSelection?.selectedTypes?.includes('performance') || false,
362
- },
363
- {
364
- name: 'セキュリティテスト (Security Tests) - 任意 [Phase B]',
365
- value: 'security',
366
- checked: existingSelection?.selectedTypes?.includes('security') || false,
367
- },
368
- ],
369
- validate: () => {
370
- // disabled項目は自動的に含まれるため、バリデーションは常に成功
371
- return true;
372
- },
373
- },
374
- {
375
- type: 'confirm',
376
- name: 'confirm',
377
- message: (answers) => {
378
- // 必須テストを自動的に追加
379
- const required = ['unit', 'lint', 'build'];
380
- const selected = [...new Set([...required, ...answers.testTypes])];
381
- const optional = selected.filter((t) => !required.includes(t));
382
- if (optional.length === 0) {
383
- return '必須テストのみが選択されています。この選択で進めますか?';
384
- }
385
- return `選択したテストタイプ: ${selected.join(', ')}\nこの選択で進めますか?`;
386
- },
387
- default: true,
388
- },
389
- ]);
390
- // 必須テストを自動的に追加(disabled項目はanswers.testTypesに含まれないため)
391
- const requiredTests = ['unit', 'lint', 'build'];
392
- answers.testTypes = [...new Set([...requiredTests, ...answers.testTypes])];
393
- if (!answers.confirm) {
394
- console.log('\n❌ 選択がキャンセルされました');
395
- return {
396
- phase: 'test-type-selection',
397
- success: false,
398
- confluenceCreated: false,
399
- jiraCreated: false,
400
- validationPassed: false,
401
- errors: ['ユーザーが選択をキャンセルしました'],
402
- };
403
- }
404
- // 選択結果を保存
405
- const selection = {
406
- feature,
407
- selectedTypes: answers.testTypes,
408
- selectedAt: new Date().toISOString(),
409
- testTypes: {
410
- unit: {
411
- enabled: true,
412
- required: true,
413
- phase: 'A',
414
- description: '単体テスト',
415
- },
416
- lint: {
417
- enabled: true,
418
- required: true,
419
- phase: 'A',
420
- description: 'Lint実行',
421
- },
422
- build: {
423
- enabled: true,
424
- required: true,
425
- phase: 'A',
426
- description: 'ビルド実行',
427
- },
428
- integration: {
429
- enabled: answers.testTypes.includes('integration'),
430
- required: false,
431
- phase: 'B',
432
- description: '統合テスト',
433
- },
434
- e2e: {
435
- enabled: answers.testTypes.includes('e2e'),
436
- required: false,
437
- phase: 'B',
438
- description: 'E2Eテスト',
439
- },
440
- performance: {
441
- enabled: answers.testTypes.includes('performance'),
442
- required: false,
443
- phase: 'B',
444
- description: '性能テスト',
445
- },
446
- security: {
447
- enabled: answers.testTypes.includes('security'),
448
- required: false,
449
- phase: 'B',
450
- description: 'セキュリティテスト',
451
- },
452
- },
453
- };
454
- // ディレクトリが存在しない場合は作成
455
- if (!existsSync(specDir)) {
456
- mkdirSync(specDir, { recursive: true });
457
- }
458
- // 選択結果を保存
459
- writeFileSync(selectionPath, JSON.stringify(selection, null, 2), 'utf-8');
460
- console.log(`\n✅ テストタイプ選択を保存しました: ${selectionPath}`);
461
- // spec.jsonを更新
462
- try {
463
- const specPath = join(specDir, 'spec.json');
464
- if (existsSync(specPath)) {
465
- const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
466
- spec.testTypeSelection = {
467
- completed: true,
468
- selectedTypes: answers.testTypes,
469
- selectedAt: selection.selectedAt,
470
- };
471
- spec.lastUpdated = new Date().toISOString();
472
- writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
473
- console.log('✅ spec.jsonを更新しました');
474
- }
475
- }
476
- catch (error) {
477
- errors.push(`spec.json更新失敗: ${error.message}`);
478
- console.warn(`⚠️ spec.json更新失敗: ${error.message}`);
479
- }
480
- // 選択結果のサマリーを表示
481
- console.log('\n' + '='.repeat(60));
482
- console.log('📊 選択結果サマリー:');
483
- console.log(` 必須テスト: ${['unit', 'lint', 'build'].join(', ')}`);
484
- const optional = answers.testTypes.filter((t) => !['unit', 'lint', 'build'].includes(t));
485
- if (optional.length > 0) {
486
- console.log(` 追加テスト: ${optional.join(', ')}`);
487
- }
488
- else {
489
- console.log(' 追加テスト: なし');
490
- }
491
- console.log('\n📖 次のステップ:');
492
- console.log(' 1. Phase 0.4: テスト仕様書作成へ進む');
493
- console.log(' michi phase:run ' + feature + ' test-spec');
494
- console.log(' 2. 詳細ガイド: docs/user-guide/testing/test-planning-flow.md');
495
- console.log('\n' + '='.repeat(60));
496
- console.log('✅ Phase 0.3: テストタイプ選択が完了しました');
497
- return {
498
- phase: 'test-type-selection',
499
- success: true,
500
- confluenceCreated: false,
501
- jiraCreated: false,
502
- validationPassed: true,
503
- errors,
504
- };
505
267
  }
506
268
  /**
507
- * テスト仕様書作成フェーズを実行(Phase 0.4)
508
- * 自動生成: test-type-selectionから選択されたテストタイプの仕様書を生成
269
+ * タスク分割フェーズを実行
509
270
  */
510
- async function runTestSpecPhase(feature) {
511
- console.log('\n📝 Phase 0.4: Test Specification(テスト仕様書作成)');
271
+ async function runTasksPhase(feature) {
272
+ console.log('\n📝 Phase: Tasks(タスク分割)');
512
273
  console.log('='.repeat(60));
513
274
  const errors = [];
514
- // Step 1: テストタイプ選択の読み込み
515
- const selectionPath = join(process.cwd(), '.kiro', 'specs', feature, 'test-type-selection.json');
516
- if (!existsSync(selectionPath)) {
517
- errors.push('test-type-selection.jsonが存在しません。先にtest-type-selectionフェーズを実行してください');
275
+ let jiraCreated = false;
276
+ const tasksPath = join(process.cwd(), '.kiro', 'specs', feature, 'tasks.md');
277
+ // 前提条件チェック
278
+ const prereqCheck = await checkTasksPrerequisites(feature);
279
+ if (!prereqCheck.valid) {
518
280
  return {
519
- phase: 'test-spec',
281
+ phase: 'tasks',
520
282
  success: false,
521
283
  confluenceCreated: false,
522
284
  jiraCreated: false,
523
285
  validationPassed: false,
524
- errors,
286
+ errors: prereqCheck.errors,
525
287
  };
526
288
  }
527
- let selection;
528
- let testTypes = [];
529
- try {
530
- selection = JSON.parse(readFileSync(selectionPath, 'utf-8'));
531
- testTypes = selection.selectedTypes || [];
532
- }
533
- catch (error) {
534
- errors.push(`test-type-selection.jsonの読み込みまたはパースに失敗しました: ${error instanceof Error ? error.message : String(error)}`);
289
+ // AI-DLC形式検出と変換
290
+ const convertResult = await detectAndConvertAIDLCFormat(feature, tasksPath);
291
+ if (!convertResult.success) {
292
+ errors.push(...convertResult.errors);
535
293
  return {
536
- phase: 'test-spec',
294
+ phase: 'tasks',
537
295
  success: false,
538
296
  confluenceCreated: false,
539
297
  jiraCreated: false,
@@ -541,82 +299,29 @@ async function runTestSpecPhase(feature) {
541
299
  errors,
542
300
  };
543
301
  }
544
- console.log(`\n✅ 選択されたテストタイプ: ${testTypes.join(', ')}`);
545
- // Step 2: 各テストタイプのテスト仕様書を生成
546
- console.log('\n🤖 テスト仕様書を自動生成中...');
547
- const specDir = join(process.cwd(), '.kiro', 'specs', feature, 'test-specs');
548
- mkdirSync(specDir, { recursive: true });
549
- const { generateTestSpec } = await import('./test-spec-generator.js');
550
- const generatedSpecs = [];
551
- for (const testType of testTypes) {
552
- // lint/buildはテスト仕様書不要(CI設定で対応)
553
- if (testType === 'lint' || testType === 'build') {
554
- console.log(` ⏭️ ${testType}: スキップ(CI設定で対応)`);
555
- continue;
556
- }
557
- try {
558
- await generateTestSpec(feature, testType);
559
- console.log(` ✅ ${testType}テスト仕様書: ${testType}-test-spec.md`);
560
- generatedSpecs.push(testType);
561
- }
562
- catch (error) {
563
- errors.push(`${testType}テスト仕様書生成失敗: ${error.message}`);
564
- console.error(` ❌ ${testType}テスト仕様書生成失敗: ${error.message}`);
565
- }
566
- }
567
- // Step 3: spec.json更新
568
- const specPath = join(process.cwd(), '.kiro', 'specs', feature, 'spec.json');
569
- if (existsSync(specPath)) {
570
- try {
571
- const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
572
- spec.testSpecification = {
573
- completed: true,
574
- generatedAt: new Date().toISOString(),
575
- testTypes: testTypes,
576
- generatedSpecs: generatedSpecs,
577
- };
578
- spec.lastUpdated = new Date().toISOString();
579
- writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
580
- console.log('\n✅ spec.jsonを更新しました');
581
- }
582
- catch (error) {
583
- errors.push(`spec.json更新失敗: ${error.message}`);
584
- console.warn(`⚠️ spec.json更新失敗: ${error.message}`);
585
- }
586
- }
587
- // Step 4: サマリー表示
588
- console.log('\n' + '='.repeat(60));
589
- console.log('📊 テスト仕様書作成完了:');
590
- console.log(` 生成されたファイル: ${generatedSpecs.length}件`);
591
- console.log(` 保存先: .kiro/specs/${feature}/test-specs/`);
592
- if (generatedSpecs.length > 0) {
593
- console.log('\n📄 生成されたファイル:');
594
- generatedSpecs.forEach((type) => {
595
- console.log(` - ${type}-test-spec.md`);
596
- });
597
- }
598
- console.log('\n📖 次のステップ:');
599
- console.log(' 1. Phase 0.5: タスク分割へ進む');
600
- console.log(` michi phase:run ${feature} tasks`);
601
- console.log('\n' + '='.repeat(60));
602
- console.log('✅ Phase 0.4: テスト仕様書作成が完了しました');
302
+ // フォーマット検証とJIRA同期
303
+ const syncResult = await validateTasksFormatAndSyncJIRA(feature, tasksPath);
304
+ jiraCreated = syncResult.jiraCreated;
305
+ errors.push(...syncResult.errors);
306
+ // バリデーション
307
+ console.log('\n🔍 バリデーション実行中...');
308
+ const validation = validatePhase(feature, 'tasks');
309
+ errors.push(...validation.errors);
310
+ // サマリー表示
311
+ displayTasksPhaseSummary(jiraCreated, validation);
603
312
  return {
604
- phase: 'test-spec',
605
- success: errors.length === 0 && generatedSpecs.length > 0,
313
+ phase: 'tasks',
314
+ success: validation.valid && jiraCreated,
606
315
  confluenceCreated: false,
607
- jiraCreated: false,
608
- validationPassed: true,
316
+ jiraCreated,
317
+ validationPassed: validation.valid,
609
318
  errors,
610
319
  };
611
320
  }
612
321
  /**
613
- * 環境構築フェーズを実行(Phase 1)
614
- * 対話的に環境を構築し、必要な設定ファイルを生成
322
+ * プロジェクト検出と言語/Docker要件を分析
615
323
  */
616
- async function runEnvironmentSetupPhase(feature) {
617
- console.log('\n⚙️ Phase 1: Environment Setup(環境構築)');
618
- console.log('='.repeat(60));
619
- const errors = [];
324
+ async function detectAndAnalyzeProject(feature) {
620
325
  // Step 1: プロジェクト検出
621
326
  const { detectProject } = await import('./utils/project-detector.js');
622
327
  const detected = detectProject();
@@ -647,7 +352,12 @@ async function runEnvironmentSetupPhase(feature) {
647
352
  console.log(` 推奨サービス: ${dockerAnalysis.suggestedServices.join(', ')}`);
648
353
  }
649
354
  }
650
- // Step 4: 対話的質問
355
+ return { detected, languageAnalysis, dockerAnalysis };
356
+ }
357
+ /**
358
+ * 環境構築の対話的質問を収集
359
+ */
360
+ async function collectEnvironmentAnswers(detected, languageAnalysis, dockerAnalysis) {
651
361
  console.log('\n📚 環境構築を対話的に設定します\n');
652
362
  const languageMap = {
653
363
  nodejs: 'Node.js/TypeScript',
@@ -705,23 +415,30 @@ async function runEnvironmentSetupPhase(feature) {
705
415
  ]);
706
416
  // Docker Composeの推奨サービスを保存
707
417
  answers.suggestedServices = dockerAnalysis.suggestedServices;
708
- // Step 3: 設定ファイル生成
418
+ return answers;
419
+ }
420
+ /**
421
+ * 環境構築の設定ファイルを生成
422
+ */
423
+ async function generateEnvironmentConfigs(feature, answers, errors) {
709
424
  console.log('\n🤖 設定ファイルを生成中...');
710
425
  try {
711
426
  const { generateCIConfig } = await import('./utils/ci-generator.js');
712
427
  await generateCIConfig(feature, answers);
713
428
  }
714
429
  catch (error) {
715
- errors.push(`CI/CD設定生成失敗: ${error.message}`);
716
- console.error(`CI/CD設定生成失敗: ${error.message}`);
430
+ const message = error instanceof Error ? error.message : String(error);
431
+ errors.push(`CI/CD設定生成失敗: ${message}`);
432
+ console.error(` ❌ CI/CD設定生成失敗: ${message}`);
717
433
  }
718
434
  try {
719
435
  const { generateTestConfig } = await import('./utils/test-config-generator.js');
720
436
  await generateTestConfig(feature, answers);
721
437
  }
722
438
  catch (error) {
723
- errors.push(`テスト設定生成失敗: ${error.message}`);
724
- console.error(` ❌ テスト設定生成失敗: ${error.message}`);
439
+ const message = error instanceof Error ? error.message : String(error);
440
+ errors.push(`テスト設定生成失敗: ${message}`);
441
+ console.error(` ❌ テスト設定生成失敗: ${message}`);
725
442
  }
726
443
  if (answers.needsDocker) {
727
444
  try {
@@ -729,78 +446,94 @@ async function runEnvironmentSetupPhase(feature) {
729
446
  await generateDockerCompose(feature, answers.suggestedServices || []);
730
447
  }
731
448
  catch (error) {
732
- errors.push(`Docker Compose生成失敗: ${error.message}`);
733
- console.error(`Docker Compose生成失敗: ${error.message}`);
449
+ const message = error instanceof Error ? error.message : String(error);
450
+ errors.push(`Docker Compose生成失敗: ${message}`);
451
+ console.error(` ❌ Docker Compose生成失敗: ${message}`);
734
452
  }
735
453
  }
736
- // Step 4: 依存関係インストール(オプション)
737
- if (answers.installDeps) {
738
- console.log('\n📦 依存関係をインストール中...');
739
- const { execSync } = await import('child_process');
740
- // 言語別のビルドファイル存在確認
741
- const buildFileChecks = {
742
- 'Node.js/TypeScript': 'package.json',
743
- Java: 'build.gradle',
744
- PHP: 'composer.json',
745
- Python: 'requirements.txt',
746
- Go: 'go.mod',
747
- Rust: 'Cargo.toml',
748
- };
749
- const buildFile = buildFileChecks[answers.language];
750
- if (!buildFile || !existsSync(buildFile)) {
751
- console.log(` ℹ️ ${buildFile || 'ビルドファイル'}が見つかりません(スキップ)`);
752
- console.log(' 💡 実際のプロジェクトでは、先にプロジェクトを初期化してください');
753
- }
754
- else {
755
- const commands = {
756
- 'Node.js/TypeScript': detected.packageManager === 'pnpm'
757
- ? 'pnpm install'
758
- : detected.packageManager === 'yarn'
759
- ? 'yarn install'
760
- : 'npm install',
761
- Java: existsSync('./gradlew')
762
- ? './gradlew build --no-daemon'
763
- : 'gradle build',
764
- PHP: 'composer install',
765
- Python: 'pip install -r requirements.txt',
766
- Go: 'go mod download',
767
- Rust: 'cargo fetch',
768
- };
769
- const command = commands[answers.language];
770
- if (command) {
771
- try {
772
- execSync(command, { stdio: 'inherit', cwd: process.cwd() });
773
- console.log(' 依存関係のインストール完了');
774
- }
775
- catch (error) {
776
- console.warn(` ⚠️ 依存関係インストール失敗: ${error.message}`);
777
- console.warn(' 💡 プロジェクト初期化後に手動でインストールしてください');
778
- }
779
- }
780
- }
781
- }
782
- // Step 5: spec.json更新
783
- const specPath = join(process.cwd(), '.kiro', 'specs', feature, 'spec.json');
784
- if (existsSync(specPath)) {
454
+ }
455
+ /**
456
+ * 依存関係を自動インストール
457
+ */
458
+ async function installDependencies(answers, detected) {
459
+ if (!answers.installDeps) {
460
+ return;
461
+ }
462
+ console.log('\n📦 依存関係をインストール中...');
463
+ const { execSync } = await import('child_process');
464
+ // 言語別のビルドファイル存在確認
465
+ const buildFileChecks = {
466
+ 'Node.js/TypeScript': 'package.json',
467
+ Java: 'build.gradle',
468
+ PHP: 'composer.json',
469
+ Python: 'requirements.txt',
470
+ Go: 'go.mod',
471
+ Rust: 'Cargo.toml',
472
+ };
473
+ const buildFile = buildFileChecks[answers.language];
474
+ if (!buildFile || !existsSync(buildFile)) {
475
+ console.log(` ℹ️ ${buildFile || 'ビルドファイル'}が見つかりません(スキップ)`);
476
+ console.log(' 💡 実際のプロジェクトでは、先にプロジェクトを初期化してください');
477
+ return;
478
+ }
479
+ const commands = {
480
+ 'Node.js/TypeScript': detected.packageManager === 'pnpm'
481
+ ? 'pnpm install'
482
+ : detected.packageManager === 'yarn'
483
+ ? 'yarn install'
484
+ : 'npm install',
485
+ Java: existsSync('./gradlew')
486
+ ? './gradlew build --no-daemon'
487
+ : 'gradle build',
488
+ PHP: 'composer install',
489
+ Python: 'pip install -r requirements.txt',
490
+ Go: 'go mod download',
491
+ Rust: 'cargo fetch',
492
+ };
493
+ const command = commands[answers.language];
494
+ if (command) {
785
495
  try {
786
- const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
787
- spec.environmentSetup = {
788
- completed: true,
789
- language: answers.language,
790
- ciTool: answers.ciTool,
791
- dockerCompose: answers.needsDocker,
792
- completedAt: new Date().toISOString(),
793
- };
794
- spec.lastUpdated = new Date().toISOString();
795
- writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
796
- console.log('\n✅ spec.jsonを更新しました');
496
+ execSync(command, { stdio: 'inherit', cwd: process.cwd() });
497
+ console.log(' ✅ 依存関係のインストール完了');
797
498
  }
798
499
  catch (error) {
799
- errors.push(`spec.json更新失敗: ${error.message}`);
800
- console.warn(`⚠️ spec.json更新失敗: ${error.message}`);
500
+ const message = error instanceof Error ? error.message : String(error);
501
+ console.warn(` ⚠️ 依存関係インストール失敗: ${message}`);
502
+ console.warn(' 💡 プロジェクト初期化後に手動でインストールしてください');
801
503
  }
802
504
  }
803
- // Step 6: サマリー表示
505
+ }
506
+ /**
507
+ * spec.jsonを更新
508
+ */
509
+ async function updateEnvironmentSpecJson(feature, answers, errors) {
510
+ const specPath = join(process.cwd(), '.kiro', 'specs', feature, 'spec.json');
511
+ if (!existsSync(specPath)) {
512
+ return;
513
+ }
514
+ try {
515
+ const spec = JSON.parse(readFileSync(specPath, 'utf-8'));
516
+ spec.environmentSetup = {
517
+ completed: true,
518
+ language: answers.language,
519
+ ciTool: answers.ciTool,
520
+ dockerCompose: answers.needsDocker,
521
+ completedAt: new Date().toISOString(),
522
+ };
523
+ spec.lastUpdated = new Date().toISOString();
524
+ writeFileSync(specPath, JSON.stringify(spec, null, 2), 'utf-8');
525
+ console.log('\n✅ spec.jsonを更新しました');
526
+ }
527
+ catch (error) {
528
+ const message = error instanceof Error ? error.message : String(error);
529
+ errors.push(`spec.json更新失敗: ${message}`);
530
+ console.warn(`⚠️ spec.json更新失敗: ${message}`);
531
+ }
532
+ }
533
+ /**
534
+ * 環境構築のサマリーを表示
535
+ */
536
+ function displayEnvironmentSummary(feature, answers) {
804
537
  console.log('\n' + '='.repeat(60));
805
538
  console.log('📊 環境構築完了:');
806
539
  console.log(` 言語: ${answers.language}`);
@@ -811,6 +544,27 @@ async function runEnvironmentSetupPhase(feature) {
811
544
  console.log(` /kiro:spec-impl ${feature}`);
812
545
  console.log('\n' + '='.repeat(60));
813
546
  console.log('✅ Phase 1: 環境構築が完了しました');
547
+ }
548
+ /**
549
+ * 環境構築フェーズを実行(Phase 1)
550
+ * 対話的に環境を構築し、必要な設定ファイルを生成
551
+ */
552
+ async function runEnvironmentSetupPhase(feature) {
553
+ console.log('\n⚙️ Phase 1: Environment Setup(環境構築)');
554
+ console.log('='.repeat(60));
555
+ const errors = [];
556
+ // プロジェクト検出と分析
557
+ const { detected, languageAnalysis, dockerAnalysis } = await detectAndAnalyzeProject(feature);
558
+ // 対話的質問の収集
559
+ const answers = await collectEnvironmentAnswers(detected, languageAnalysis, dockerAnalysis);
560
+ // 設定ファイル生成
561
+ await generateEnvironmentConfigs(feature, answers, errors);
562
+ // 依存関係インストール
563
+ await installDependencies(answers, detected);
564
+ // spec.json更新
565
+ await updateEnvironmentSpecJson(feature, answers, errors);
566
+ // サマリー表示
567
+ displayEnvironmentSummary(feature, answers);
814
568
  return {
815
569
  phase: 'environment-setup',
816
570
  success: errors.length === 0,
@@ -860,15 +614,9 @@ async function runPhaseAPhase(feature) {
860
614
  };
861
615
  }
862
616
  /**
863
- * リリース準備テストフェーズを実行(Phase B
864
- * テスト実行ファイルを自動生成し、手動テストチェックリストを表示
617
+ * Phase B対象のテストタイプを読み込み
865
618
  */
866
- async function runPhaseBPhase(feature) {
867
- console.log('\n🔍 Phase B: リリース準備テスト(Release Tests)');
868
- console.log('='.repeat(60));
869
- const errors = [];
870
- const generatedFiles = [];
871
- // Step 1: テストタイプ選択の読み込み
619
+ function loadPhaseBTestTypes(feature) {
872
620
  const selectionPath = join(process.cwd(), '.kiro', 'specs', feature, 'test-type-selection.json');
873
621
  let selectedTypes = [];
874
622
  if (existsSync(selectionPath)) {
@@ -893,32 +641,49 @@ async function runPhaseBPhase(feature) {
893
641
  'security',
894
642
  ];
895
643
  }
896
- // Step 2: Phase B対象のテストタイプを抽出
644
+ // Phase B対象のテストタイプを抽出(Phase Aのテストを除外)
897
645
  const phaseBTypes = selectedTypes.filter((t) => !['unit', 'lint', 'build'].includes(t));
898
646
  if (phaseBTypes.length > 0) {
899
647
  console.log(`\n📝 Phase B対象テスト: ${phaseBTypes.join(', ')}`);
900
- // Step 3: テスト実行ファイルを生成
901
- console.log('\n🤖 テスト実行ファイルを自動生成中...');
902
- const { generateTestExecution } = await import('./test-execution-generator.js');
903
- for (const testType of phaseBTypes) {
904
- try {
905
- const result = await generateTestExecution(feature, testType);
906
- if (result.success) {
907
- console.log(` ✅ ${result.testType}: ${result.files.length}ファイル生成`);
908
- generatedFiles.push(...result.files);
909
- }
910
- else {
911
- console.error(` ❌ ${result.testType}: ${result.error}`);
912
- errors.push(`${result.testType}テスト生成失敗: ${result.error}`);
913
- }
648
+ }
649
+ return phaseBTypes;
650
+ }
651
+ /**
652
+ * Phase Bのテスト実行ファイルを生成
653
+ */
654
+ async function generatePhaseBTestFiles(feature, phaseBTypes) {
655
+ const generatedFiles = [];
656
+ const errors = [];
657
+ if (phaseBTypes.length === 0) {
658
+ return { generatedFiles, errors };
659
+ }
660
+ console.log('\n🤖 テスト実行ファイルを自動生成中...');
661
+ const { generateTestExecution } = await import('./test-execution-generator.js');
662
+ for (const testType of phaseBTypes) {
663
+ try {
664
+ const result = await generateTestExecution(feature, testType);
665
+ if (result.success) {
666
+ console.log(` ✅ ${result.testType}: ${result.files.length}ファイル生成`);
667
+ generatedFiles.push(...result.files);
914
668
  }
915
- catch (error) {
916
- errors.push(`${testType}テスト生成失敗: ${error.message}`);
917
- console.error(`❌ ${testType}テスト生成失敗:`, error.message);
669
+ else {
670
+ console.error(` ❌ ${result.testType}: ${result.error}`);
671
+ errors.push(`${result.testType}テスト生成失敗: ${result.error}`);
918
672
  }
919
673
  }
674
+ catch (error) {
675
+ const message = error instanceof Error ? error.message : String(error);
676
+ errors.push(`${testType}テスト生成失敗: ${message}`);
677
+ console.error(`❌ ${testType}テスト生成失敗:`, message);
678
+ }
920
679
  }
921
- // Step 4: 生成されたファイルのサマリー
680
+ return { generatedFiles, errors };
681
+ }
682
+ /**
683
+ * Phase Bのチェックリストとサマリーを表示
684
+ */
685
+ function displayPhaseBChecklist(feature, phaseBTypes, generatedFiles, errors) {
686
+ // 生成されたファイルのサマリー
922
687
  const testExecutionDir = join(process.cwd(), '.kiro', 'specs', feature, 'test-execution');
923
688
  if (generatedFiles.length > 0) {
924
689
  console.log('\n📄 生成されたファイル:');
@@ -927,7 +692,7 @@ async function runPhaseBPhase(feature) {
927
692
  console.log(` - ${relativePath}`);
928
693
  });
929
694
  }
930
- // Step 5: チェックリスト表示
695
+ // チェックリスト表示
931
696
  console.log('\n' + '='.repeat(60));
932
697
  console.log('📋 リリース準備テストチェックリスト:\n');
933
698
  if (phaseBTypes.includes('performance')) {
@@ -968,9 +733,23 @@ async function runPhaseBPhase(feature) {
968
733
  errors.forEach((err) => console.log(` - ${err}`));
969
734
  console.log('📢 エラーを修正してから再実行してください');
970
735
  }
736
+ }
737
+ /**
738
+ * リリース準備テストフェーズを実行(Phase B)
739
+ * テスト実行ファイルを自動生成し、手動テストチェックリストを表示
740
+ */
741
+ async function runPhaseBPhase(feature) {
742
+ console.log('\n🔍 Phase B: リリース準備テスト(Release Tests)');
743
+ console.log('='.repeat(60));
744
+ // Phase B対象のテストタイプを読み込み
745
+ const phaseBTypes = loadPhaseBTestTypes(feature);
746
+ // テスト実行ファイルを生成
747
+ const { generatedFiles, errors } = await generatePhaseBTestFiles(feature, phaseBTypes);
748
+ // チェックリストとサマリーを表示
749
+ displayPhaseBChecklist(feature, phaseBTypes, generatedFiles, errors);
971
750
  return {
972
751
  phase: 'phase-b',
973
- success,
752
+ success: errors.length === 0,
974
753
  confluenceCreated: false,
975
754
  jiraCreated: false,
976
755
  validationPassed: true,
@@ -988,10 +767,6 @@ export async function runPhase(feature, phase) {
988
767
  return await runRequirementsPhase(feature);
989
768
  case 'design':
990
769
  return await runDesignPhase(feature);
991
- case 'test-type-selection':
992
- return await runTestTypeSelectionPhase(feature);
993
- case 'test-spec':
994
- return await runTestSpecPhase(feature);
995
770
  case 'tasks':
996
771
  return await runTasksPhase(feature);
997
772
  case 'environment-setup':
@@ -1013,20 +788,17 @@ if (import.meta.url === `file://${process.argv[1]}`) {
1013
788
  console.error('\nAvailable Phases:');
1014
789
  console.error(' requirements - Phase 0.1: 要件定義');
1015
790
  console.error(' design - Phase 0.2: 設計');
1016
- console.error(' test-type-selection- Phase 0.3: テストタイプ選択(任意)');
1017
- console.error(' test-spec - Phase 0.4: テスト仕様書作成(任意)');
1018
791
  console.error(' tasks - Phase 0.5-0.6: タスク分割・JIRA同期');
1019
792
  console.error(' environment-setup - Phase 1: 環境構築(任意)');
1020
793
  console.error(' phase-a - Phase A: PR前自動テスト(任意)');
1021
794
  console.error(' phase-b - Phase B: リリース準備テスト(任意)');
795
+ console.error('\nNote: For test planning (Phase 0.3-0.4), use /michi:test-planning AI command');
1022
796
  process.exit(1);
1023
797
  }
1024
798
  const [feature, phase] = args;
1025
799
  const validPhases = [
1026
800
  'requirements',
1027
801
  'design',
1028
- 'test-type-selection',
1029
- 'test-spec',
1030
802
  'tasks',
1031
803
  'environment-setup',
1032
804
  'phase-a',
@@ -1034,7 +806,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
1034
806
  ];
1035
807
  if (!validPhases.includes(phase)) {
1036
808
  console.error(`Invalid phase: ${phase}`);
1037
- console.error('Must be one of: requirements, design, test-type-selection, test-spec, tasks, environment-setup, phase-a, phase-b');
809
+ console.error('Must be one of: requirements, design, tasks, environment-setup, phase-a, phase-b');
1038
810
  process.exit(1);
1039
811
  }
1040
812
  runPhase(feature, phase)
@@ -1049,7 +821,8 @@ if (import.meta.url === `file://${process.argv[1]}`) {
1049
821
  }
1050
822
  })
1051
823
  .catch((error) => {
1052
- console.error(`\n❌ フェーズ実行エラー: ${error.message}`);
824
+ const message = error instanceof Error ? error.message : String(error);
825
+ console.error(`\n❌ フェーズ実行エラー: ${message}`);
1053
826
  process.exit(1);
1054
827
  });
1055
828
  }