@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.
Files changed (433) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +420 -49
  3. package/dist/scripts/__tests__/create-project.test.js +24 -28
  4. package/dist/scripts/__tests__/create-project.test.js.map +1 -1
  5. package/dist/scripts/__tests__/jira-transitions.test.d.ts +5 -0
  6. package/dist/scripts/__tests__/jira-transitions.test.d.ts.map +1 -0
  7. package/dist/scripts/__tests__/jira-transitions.test.js +172 -0
  8. package/dist/scripts/__tests__/jira-transitions.test.js.map +1 -0
  9. package/dist/scripts/__tests__/multi-project-estimate.test.js +14 -15
  10. package/dist/scripts/__tests__/multi-project-estimate.test.js.map +1 -1
  11. package/dist/scripts/__tests__/setup-existing-project.test.js +146 -5
  12. package/dist/scripts/__tests__/setup-existing-project.test.js.map +1 -1
  13. package/dist/scripts/__tests__/setup-interactive.test.js +23 -17
  14. package/dist/scripts/__tests__/setup-interactive.test.js.map +1 -1
  15. package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts +5 -0
  16. package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts.map +1 -0
  17. package/dist/scripts/__tests__/spec-impl-workflow.test.js +321 -0
  18. package/dist/scripts/__tests__/spec-impl-workflow.test.js.map +1 -0
  19. package/dist/scripts/__tests__/spec-loader.test.d.ts +5 -0
  20. package/dist/scripts/__tests__/spec-loader.test.d.ts.map +1 -0
  21. package/dist/scripts/__tests__/spec-loader.test.js +153 -0
  22. package/dist/scripts/__tests__/spec-loader.test.js.map +1 -0
  23. package/dist/scripts/__tests__/validate-phase.test.js +26 -22
  24. package/dist/scripts/__tests__/validate-phase.test.js.map +1 -1
  25. package/dist/scripts/config/config-schema.d.ts +17 -0
  26. package/dist/scripts/config/config-schema.d.ts.map +1 -1
  27. package/dist/scripts/config/config-schema.js +55 -26
  28. package/dist/scripts/config/config-schema.js.map +1 -1
  29. package/dist/scripts/config-interactive.d.ts.map +1 -1
  30. package/dist/scripts/config-interactive.js +53 -38
  31. package/dist/scripts/config-interactive.js.map +1 -1
  32. package/dist/scripts/confluence-sync.d.ts.map +1 -1
  33. package/dist/scripts/confluence-sync.js +0 -11
  34. package/dist/scripts/confluence-sync.js.map +1 -1
  35. package/dist/scripts/constants/__tests__/environments.test.d.ts +2 -0
  36. package/dist/scripts/constants/__tests__/environments.test.d.ts.map +1 -0
  37. package/dist/scripts/constants/__tests__/environments.test.js +125 -0
  38. package/dist/scripts/constants/__tests__/environments.test.js.map +1 -0
  39. package/dist/scripts/constants/__tests__/languages.test.d.ts +2 -0
  40. package/dist/scripts/constants/__tests__/languages.test.d.ts.map +1 -0
  41. package/dist/scripts/constants/__tests__/languages.test.js +82 -0
  42. package/dist/scripts/constants/__tests__/languages.test.js.map +1 -0
  43. package/dist/scripts/constants/environments.d.ts +33 -0
  44. package/dist/scripts/constants/environments.d.ts.map +1 -0
  45. package/dist/scripts/constants/environments.js +64 -0
  46. package/dist/scripts/constants/environments.js.map +1 -0
  47. package/dist/scripts/constants/languages.d.ts +23 -0
  48. package/dist/scripts/constants/languages.d.ts.map +1 -0
  49. package/dist/scripts/constants/languages.js +53 -0
  50. package/dist/scripts/constants/languages.js.map +1 -0
  51. package/dist/scripts/constants/test-commands.d.ts +36 -0
  52. package/dist/scripts/constants/test-commands.d.ts.map +1 -0
  53. package/dist/scripts/constants/test-commands.js +70 -0
  54. package/dist/scripts/constants/test-commands.js.map +1 -0
  55. package/dist/scripts/create-project.d.ts +4 -0
  56. package/dist/scripts/create-project.d.ts.map +1 -1
  57. package/dist/scripts/create-project.js +51 -22
  58. package/dist/scripts/create-project.js.map +1 -1
  59. package/dist/scripts/jira-sync.d.ts +89 -3
  60. package/dist/scripts/jira-sync.d.ts.map +1 -1
  61. package/dist/scripts/jira-sync.js +366 -96
  62. package/dist/scripts/jira-sync.js.map +1 -1
  63. package/dist/scripts/markdown-to-confluence.js +1 -1
  64. package/dist/scripts/markdown-to-confluence.js.map +1 -1
  65. package/dist/scripts/phase-runner.d.ts +1 -1
  66. package/dist/scripts/phase-runner.d.ts.map +1 -1
  67. package/dist/scripts/phase-runner.js +809 -13
  68. package/dist/scripts/phase-runner.js.map +1 -1
  69. package/dist/scripts/pr-automation.d.ts.map +1 -1
  70. package/dist/scripts/pr-automation.js.map +1 -1
  71. package/dist/scripts/pre-flight-check.js +1 -1
  72. package/dist/scripts/pre-flight-check.js.map +1 -1
  73. package/dist/scripts/setup-existing-project.d.ts +3 -1
  74. package/dist/scripts/setup-existing-project.d.ts.map +1 -1
  75. package/dist/scripts/setup-existing-project.js +165 -78
  76. package/dist/scripts/setup-existing-project.js.map +1 -1
  77. package/dist/scripts/setup-interactive.js +3 -3
  78. package/dist/scripts/setup-interactive.js.map +1 -1
  79. package/dist/scripts/spec-impl-workflow.d.ts +94 -0
  80. package/dist/scripts/spec-impl-workflow.d.ts.map +1 -0
  81. package/dist/scripts/spec-impl-workflow.js +354 -0
  82. package/dist/scripts/spec-impl-workflow.js.map +1 -0
  83. package/dist/scripts/template/__tests__/renderer.test.d.ts +2 -0
  84. package/dist/scripts/template/__tests__/renderer.test.d.ts.map +1 -0
  85. package/dist/scripts/template/__tests__/renderer.test.js +165 -0
  86. package/dist/scripts/template/__tests__/renderer.test.js.map +1 -0
  87. package/dist/scripts/template/renderer.d.ts +70 -0
  88. package/dist/scripts/template/renderer.d.ts.map +1 -0
  89. package/dist/scripts/template/renderer.js +99 -0
  90. package/dist/scripts/template/renderer.js.map +1 -0
  91. package/dist/scripts/test-execution-generator.d.ts +52 -0
  92. package/dist/scripts/test-execution-generator.d.ts.map +1 -0
  93. package/dist/scripts/test-execution-generator.js +576 -0
  94. package/dist/scripts/test-execution-generator.js.map +1 -0
  95. package/dist/scripts/test-interactive.d.ts +10 -0
  96. package/dist/scripts/test-interactive.d.ts.map +1 -0
  97. package/dist/scripts/test-interactive.js +627 -0
  98. package/dist/scripts/test-interactive.js.map +1 -0
  99. package/dist/scripts/test-new-features.d.ts +5 -0
  100. package/dist/scripts/test-new-features.d.ts.map +1 -0
  101. package/dist/scripts/test-new-features.js +145 -0
  102. package/dist/scripts/test-new-features.js.map +1 -0
  103. package/dist/scripts/test-spec-generator.d.ts +29 -0
  104. package/dist/scripts/test-spec-generator.d.ts.map +1 -0
  105. package/dist/scripts/test-spec-generator.js +494 -0
  106. package/dist/scripts/test-spec-generator.js.map +1 -0
  107. package/dist/scripts/test-workflow-stages.d.ts +6 -0
  108. package/dist/scripts/test-workflow-stages.d.ts.map +1 -0
  109. package/dist/scripts/test-workflow-stages.js +43 -0
  110. package/dist/scripts/test-workflow-stages.js.map +1 -0
  111. package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts +5 -0
  112. package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts.map +1 -0
  113. package/dist/scripts/utils/__tests__/aidlc-parser.test.js +315 -0
  114. package/dist/scripts/utils/__tests__/aidlc-parser.test.js.map +1 -0
  115. package/dist/scripts/utils/__tests__/business-days.test.d.ts +5 -0
  116. package/dist/scripts/utils/__tests__/business-days.test.d.ts.map +1 -0
  117. package/dist/scripts/utils/__tests__/business-days.test.js +171 -0
  118. package/dist/scripts/utils/__tests__/business-days.test.js.map +1 -0
  119. package/dist/scripts/utils/__tests__/config-loader.test.js +1 -1
  120. package/dist/scripts/utils/__tests__/config-loader.test.js.map +1 -1
  121. package/dist/scripts/utils/__tests__/config-validator.test.js +164 -35
  122. package/dist/scripts/utils/__tests__/config-validator.test.js.map +1 -1
  123. package/dist/scripts/utils/__tests__/env-config.test.d.ts +5 -0
  124. package/dist/scripts/utils/__tests__/env-config.test.d.ts.map +1 -0
  125. package/dist/scripts/utils/__tests__/env-config.test.js +218 -0
  126. package/dist/scripts/utils/__tests__/env-config.test.js.map +1 -0
  127. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts +5 -0
  128. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts.map +1 -0
  129. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js +202 -0
  130. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js.map +1 -0
  131. package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts +5 -0
  132. package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts.map +1 -0
  133. package/dist/scripts/utils/__tests__/tasks-converter.test.js +500 -0
  134. package/dist/scripts/utils/__tests__/tasks-converter.test.js.map +1 -0
  135. package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts +5 -0
  136. package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts.map +1 -0
  137. package/dist/scripts/utils/__tests__/tasks-format-validator.test.js +314 -0
  138. package/dist/scripts/utils/__tests__/tasks-format-validator.test.js.map +1 -0
  139. package/dist/scripts/utils/__tests__/test-runner.test.d.ts +5 -0
  140. package/dist/scripts/utils/__tests__/test-runner.test.d.ts.map +1 -0
  141. package/dist/scripts/utils/__tests__/test-runner.test.js +64 -0
  142. package/dist/scripts/utils/__tests__/test-runner.test.js.map +1 -0
  143. package/dist/scripts/utils/aidlc-parser.d.ts +86 -0
  144. package/dist/scripts/utils/aidlc-parser.d.ts.map +1 -0
  145. package/dist/scripts/utils/aidlc-parser.js +208 -0
  146. package/dist/scripts/utils/aidlc-parser.js.map +1 -0
  147. package/dist/scripts/utils/business-days.d.ts +52 -0
  148. package/dist/scripts/utils/business-days.d.ts.map +1 -0
  149. package/dist/scripts/utils/business-days.js +98 -0
  150. package/dist/scripts/utils/business-days.js.map +1 -0
  151. package/dist/scripts/utils/ci-generator.d.ts +14 -0
  152. package/dist/scripts/utils/ci-generator.d.ts.map +1 -0
  153. package/dist/scripts/utils/ci-generator.js +61 -0
  154. package/dist/scripts/utils/ci-generator.js.map +1 -0
  155. package/dist/scripts/utils/config-loader.js +2 -2
  156. package/dist/scripts/utils/config-loader.js.map +1 -1
  157. package/dist/scripts/utils/config-validator.d.ts +7 -1
  158. package/dist/scripts/utils/config-validator.d.ts.map +1 -1
  159. package/dist/scripts/utils/config-validator.js +136 -23
  160. package/dist/scripts/utils/config-validator.js.map +1 -1
  161. package/dist/scripts/utils/confluence-approval.d.ts +46 -0
  162. package/dist/scripts/utils/confluence-approval.d.ts.map +1 -0
  163. package/dist/scripts/utils/confluence-approval.js +118 -0
  164. package/dist/scripts/utils/confluence-approval.js.map +1 -0
  165. package/dist/scripts/utils/confluence-hierarchy.d.ts.map +1 -1
  166. package/dist/scripts/utils/confluence-hierarchy.js +1 -1
  167. package/dist/scripts/utils/confluence-hierarchy.js.map +1 -1
  168. package/dist/scripts/utils/docker-generator.d.ts +9 -0
  169. package/dist/scripts/utils/docker-generator.d.ts.map +1 -0
  170. package/dist/scripts/utils/docker-generator.js +132 -0
  171. package/dist/scripts/utils/docker-generator.js.map +1 -0
  172. package/dist/scripts/utils/docker-requirement-detector.d.ts +15 -0
  173. package/dist/scripts/utils/docker-requirement-detector.d.ts.map +1 -0
  174. package/dist/scripts/utils/docker-requirement-detector.js +124 -0
  175. package/dist/scripts/utils/docker-requirement-detector.js.map +1 -0
  176. package/dist/scripts/utils/env-config.d.ts +54 -0
  177. package/dist/scripts/utils/env-config.d.ts.map +1 -0
  178. package/dist/scripts/utils/env-config.js +414 -0
  179. package/dist/scripts/utils/env-config.js.map +1 -0
  180. package/dist/scripts/utils/jira-issue-type-fetcher.d.ts +70 -0
  181. package/dist/scripts/utils/jira-issue-type-fetcher.d.ts.map +1 -0
  182. package/dist/scripts/utils/jira-issue-type-fetcher.js +147 -0
  183. package/dist/scripts/utils/jira-issue-type-fetcher.js.map +1 -0
  184. package/dist/scripts/utils/language-detector.d.ts +14 -0
  185. package/dist/scripts/utils/language-detector.d.ts.map +1 -0
  186. package/dist/scripts/utils/language-detector.js +119 -0
  187. package/dist/scripts/utils/language-detector.js.map +1 -0
  188. package/dist/scripts/utils/markdown-parser.d.ts +55 -0
  189. package/dist/scripts/utils/markdown-parser.d.ts.map +1 -0
  190. package/dist/scripts/utils/markdown-parser.js +289 -0
  191. package/dist/scripts/utils/markdown-parser.js.map +1 -0
  192. package/dist/scripts/utils/project-detector.d.ts +17 -0
  193. package/dist/scripts/utils/project-detector.d.ts.map +1 -0
  194. package/dist/scripts/utils/project-detector.js +166 -0
  195. package/dist/scripts/utils/project-detector.js.map +1 -0
  196. package/dist/scripts/utils/project-finder.js +2 -2
  197. package/dist/scripts/utils/project-finder.js.map +1 -1
  198. package/dist/scripts/utils/release-notes-generator.d.ts +56 -0
  199. package/dist/scripts/utils/release-notes-generator.d.ts.map +1 -0
  200. package/dist/scripts/utils/release-notes-generator.js +162 -0
  201. package/dist/scripts/utils/release-notes-generator.js.map +1 -0
  202. package/dist/scripts/utils/spec-loader.d.ts +79 -0
  203. package/dist/scripts/utils/spec-loader.d.ts.map +1 -0
  204. package/dist/scripts/utils/spec-loader.js +80 -0
  205. package/dist/scripts/utils/spec-loader.js.map +1 -0
  206. package/dist/scripts/utils/spec-updater.d.ts +7 -0
  207. package/dist/scripts/utils/spec-updater.d.ts.map +1 -1
  208. package/dist/scripts/utils/spec-updater.js.map +1 -1
  209. package/dist/scripts/utils/tasks-converter.d.ts +57 -0
  210. package/dist/scripts/utils/tasks-converter.d.ts.map +1 -0
  211. package/dist/scripts/utils/tasks-converter.js +322 -0
  212. package/dist/scripts/utils/tasks-converter.js.map +1 -0
  213. package/dist/scripts/utils/tasks-format-validator.d.ts +36 -0
  214. package/dist/scripts/utils/tasks-format-validator.d.ts.map +1 -0
  215. package/dist/scripts/utils/tasks-format-validator.js +158 -0
  216. package/dist/scripts/utils/tasks-format-validator.js.map +1 -0
  217. package/dist/scripts/utils/template-applier.d.ts +37 -0
  218. package/dist/scripts/utils/template-applier.d.ts.map +1 -0
  219. package/dist/scripts/utils/template-applier.js +129 -0
  220. package/dist/scripts/utils/template-applier.js.map +1 -0
  221. package/dist/scripts/utils/template-finder.d.ts +37 -0
  222. package/dist/scripts/utils/template-finder.d.ts.map +1 -0
  223. package/dist/scripts/utils/template-finder.js +63 -0
  224. package/dist/scripts/utils/template-finder.js.map +1 -0
  225. package/dist/scripts/utils/test-config-generator.d.ts +12 -0
  226. package/dist/scripts/utils/test-config-generator.d.ts.map +1 -0
  227. package/dist/scripts/utils/test-config-generator.js +185 -0
  228. package/dist/scripts/utils/test-config-generator.js.map +1 -0
  229. package/dist/scripts/utils/test-runner.d.ts +31 -0
  230. package/dist/scripts/utils/test-runner.d.ts.map +1 -0
  231. package/dist/scripts/utils/test-runner.js +103 -0
  232. package/dist/scripts/utils/test-runner.js.map +1 -0
  233. package/dist/scripts/validate-phase.d.ts +1 -1
  234. package/dist/scripts/validate-phase.d.ts.map +1 -1
  235. package/dist/scripts/validate-phase.js +153 -5
  236. package/dist/scripts/validate-phase.js.map +1 -1
  237. package/dist/scripts/workflow-orchestrator.d.ts +8 -0
  238. package/dist/scripts/workflow-orchestrator.d.ts.map +1 -1
  239. package/dist/scripts/workflow-orchestrator.js +108 -7
  240. package/dist/scripts/workflow-orchestrator.js.map +1 -1
  241. package/dist/src/__tests__/integration/internationalization.test.d.ts +8 -0
  242. package/dist/src/__tests__/integration/internationalization.test.d.ts.map +1 -0
  243. package/dist/src/__tests__/integration/internationalization.test.js +333 -0
  244. package/dist/src/__tests__/integration/internationalization.test.js.map +1 -0
  245. package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +5 -0
  246. package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +1 -0
  247. package/dist/src/__tests__/integration/setup/claude-agent.test.js +122 -0
  248. package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +1 -0
  249. package/dist/src/__tests__/integration/setup/claude.test.d.ts +5 -0
  250. package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +1 -0
  251. package/dist/src/__tests__/integration/setup/claude.test.js +111 -0
  252. package/dist/src/__tests__/integration/setup/claude.test.js.map +1 -0
  253. package/dist/src/__tests__/integration/setup/cursor.test.d.ts +5 -0
  254. package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +1 -0
  255. package/dist/src/__tests__/integration/setup/cursor.test.js +166 -0
  256. package/dist/src/__tests__/integration/setup/cursor.test.js.map +1 -0
  257. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +32 -0
  258. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +1 -0
  259. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +72 -0
  260. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +1 -0
  261. package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +38 -0
  262. package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +1 -0
  263. package/dist/src/__tests__/integration/setup/helpers/test-project.js +83 -0
  264. package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +1 -0
  265. package/dist/src/__tests__/integration/setup/validation.test.d.ts +5 -0
  266. package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +1 -0
  267. package/dist/src/__tests__/integration/setup/validation.test.js +301 -0
  268. package/dist/src/__tests__/integration/setup/validation.test.js.map +1 -0
  269. package/dist/src/cli.d.ts.map +1 -1
  270. package/dist/src/cli.js +228 -18
  271. package/dist/src/cli.js.map +1 -1
  272. package/dist/src/commands/setup-existing.d.ts +25 -0
  273. package/dist/src/commands/setup-existing.d.ts.map +1 -0
  274. package/dist/src/commands/setup-existing.js +695 -0
  275. package/dist/src/commands/setup-existing.js.map +1 -0
  276. package/dist/vitest.config.d.ts.map +1 -1
  277. package/dist/vitest.config.js +4 -3
  278. package/dist/vitest.config.js.map +1 -1
  279. package/docs/README.md +3 -1
  280. package/docs/context.md +59 -0
  281. package/docs/design-issue-55.md +240 -0
  282. package/docs/design-issue-56.md +181 -0
  283. package/docs/michi-development/testing/manual-verification-flow.md +2242 -0
  284. package/docs/michi-development/testing/pre-publish-checklist.md +560 -0
  285. package/docs/plan.md +275 -0
  286. package/docs/user-guide/getting-started/github-token-setup.md +509 -0
  287. package/docs/{getting-started → user-guide/getting-started}/new-repository-setup.md +108 -28
  288. package/docs/{getting-started → user-guide/getting-started}/quick-start.md +73 -6
  289. package/docs/{getting-started → user-guide/getting-started}/setup.md +278 -3
  290. package/docs/{guides → user-guide/guides}/customization.md +3 -3
  291. package/docs/user-guide/guides/internationalization.md +540 -0
  292. package/docs/{guides → user-guide/guides}/multi-project.md +2 -2
  293. package/docs/{guides → user-guide/guides}/phase-automation.md +67 -9
  294. package/docs/user-guide/guides/workflow.md +582 -0
  295. package/docs/user-guide/hands-on/README.md +142 -0
  296. package/docs/user-guide/hands-on/claude-agent-setup.md +455 -0
  297. package/docs/user-guide/hands-on/claude-setup.md +398 -0
  298. package/docs/user-guide/hands-on/cursor-setup.md +352 -0
  299. package/docs/user-guide/hands-on/troubleshooting.md +964 -0
  300. package/docs/user-guide/hands-on/verification-checklist.md +438 -0
  301. package/docs/user-guide/hands-on/workflow-walkthrough.md +906 -0
  302. package/docs/user-guide/reference/config.md +564 -0
  303. package/docs/{reference → user-guide/reference}/quick-reference.md +75 -53
  304. package/docs/user-guide/release/ci-setup.md +541 -0
  305. package/docs/user-guide/release/release-flow.md +476 -0
  306. package/docs/user-guide/templates/test-specs/README.md +173 -0
  307. package/docs/user-guide/templates/test-specs/e2e-test-spec-template.md +547 -0
  308. package/docs/user-guide/templates/test-specs/integration-test-spec-template.md +435 -0
  309. package/docs/user-guide/templates/test-specs/performance-test-spec-template.md +454 -0
  310. package/docs/user-guide/templates/test-specs/security-test-spec-template.md +664 -0
  311. package/docs/user-guide/templates/test-specs/unit-test-spec-template.md +328 -0
  312. package/docs/user-guide/testing/integration-tests.md +312 -0
  313. package/docs/user-guide/testing/tdd-cycle.md +349 -0
  314. package/docs/user-guide/testing/test-execution-flow.md +396 -0
  315. package/docs/user-guide/testing/test-failure-handling.md +521 -0
  316. package/docs/user-guide/testing/test-planning-flow.md +181 -0
  317. package/docs/user-guide/testing-strategy.md +185 -0
  318. package/docs/verification-guide.md +518 -0
  319. package/package.json +13 -3
  320. package/scripts/__tests__/create-project.test.ts +67 -49
  321. package/scripts/__tests__/jira-transitions.test.ts +225 -0
  322. package/scripts/__tests__/multi-project-estimate.test.ts +36 -30
  323. package/scripts/__tests__/setup-existing-project.test.ts +171 -6
  324. package/scripts/__tests__/setup-interactive.test.ts +52 -46
  325. package/scripts/__tests__/spec-impl-workflow.test.ts +429 -0
  326. package/scripts/__tests__/spec-loader.test.ts +199 -0
  327. package/scripts/__tests__/validate-phase.test.ts +78 -54
  328. package/scripts/config/config-schema.ts +89 -50
  329. package/scripts/config-interactive.ts +191 -136
  330. package/scripts/confluence-sync.ts +0 -12
  331. package/scripts/constants/__tests__/environments.test.ts +146 -0
  332. package/scripts/constants/__tests__/languages.test.ts +100 -0
  333. package/scripts/constants/environments.ts +81 -0
  334. package/scripts/constants/languages.ts +70 -0
  335. package/scripts/constants/test-commands.ts +96 -0
  336. package/scripts/create-project.ts +52 -22
  337. package/scripts/jira-sync.ts +767 -232
  338. package/scripts/markdown-to-confluence.ts +1 -1
  339. package/scripts/phase-runner.ts +1056 -63
  340. package/scripts/pr-automation.ts +0 -1
  341. package/scripts/pre-flight-check.ts +1 -1
  342. package/scripts/pre-publish-check.sh +311 -0
  343. package/scripts/quick-verify.sh +115 -0
  344. package/scripts/setup-existing-project.ts +306 -143
  345. package/scripts/setup-interactive.ts +4 -4
  346. package/scripts/spec-impl-workflow.ts +505 -0
  347. package/scripts/template/__tests__/renderer.test.ts +206 -0
  348. package/scripts/template/renderer.ts +133 -0
  349. package/scripts/test-execution-generator.ts +695 -0
  350. package/scripts/test-interactive.ts +779 -0
  351. package/scripts/test-new-features.ts +168 -0
  352. package/scripts/test-npm-package.sh +345 -0
  353. package/scripts/test-spec-generator.ts +574 -0
  354. package/scripts/test-workflow-stages.ts +53 -0
  355. package/scripts/utils/__tests__/aidlc-parser.test.ts +349 -0
  356. package/scripts/utils/__tests__/business-days.test.ts +214 -0
  357. package/scripts/utils/__tests__/config-loader.test.ts +1 -1
  358. package/scripts/utils/__tests__/config-validator.test.ts +309 -88
  359. package/scripts/utils/__tests__/env-config.test.ts +259 -0
  360. package/scripts/utils/__tests__/jira-issue-type-fetcher.test.ts +272 -0
  361. package/scripts/utils/__tests__/tasks-converter.test.ts +582 -0
  362. package/scripts/utils/__tests__/tasks-format-validator.test.ts +338 -0
  363. package/scripts/utils/__tests__/test-runner.test.ts +77 -0
  364. package/scripts/utils/aidlc-parser.ts +289 -0
  365. package/scripts/utils/business-days.ts +115 -0
  366. package/scripts/utils/ci-generator.ts +84 -0
  367. package/scripts/utils/config-loader.ts +2 -2
  368. package/scripts/utils/config-validator.ts +304 -117
  369. package/scripts/utils/confluence-approval.ts +167 -0
  370. package/scripts/utils/confluence-hierarchy.ts +2 -4
  371. package/scripts/utils/docker-generator.ts +151 -0
  372. package/scripts/utils/docker-requirement-detector.ts +153 -0
  373. package/scripts/utils/env-config.ts +526 -0
  374. package/scripts/utils/jira-issue-type-fetcher.ts +199 -0
  375. package/scripts/utils/language-detector.ts +139 -0
  376. package/scripts/utils/markdown-parser.ts +376 -0
  377. package/scripts/utils/project-detector.ts +192 -0
  378. package/scripts/utils/project-finder.ts +2 -2
  379. package/scripts/utils/release-notes-generator.ts +210 -0
  380. package/scripts/utils/spec-loader.ts +125 -0
  381. package/scripts/utils/spec-updater.ts +8 -1
  382. package/scripts/utils/tasks-converter.ts +601 -0
  383. package/scripts/utils/tasks-format-validator.ts +193 -0
  384. package/scripts/utils/template-applier.ts +202 -0
  385. package/scripts/utils/template-finder.ts +75 -0
  386. package/scripts/utils/test-config-generator.ts +210 -0
  387. package/scripts/utils/test-runner.ts +133 -0
  388. package/scripts/validate-phase.ts +186 -9
  389. package/scripts/workflow-orchestrator.ts +130 -12
  390. package/templates/ci/github-actions/java.yml +54 -0
  391. package/templates/ci/github-actions/nodejs.yml +46 -0
  392. package/templates/ci/github-actions/php.yml +52 -0
  393. package/templates/ci/screwdriver/java.yaml +17 -0
  394. package/templates/ci/screwdriver/nodejs.yaml +17 -0
  395. package/templates/ci/screwdriver/php.yaml +20 -0
  396. package/templates/claude/commands/kiro/kiro-spec-impl.md +244 -0
  397. package/templates/claude/commands/kiro/kiro-spec-tasks.md +354 -0
  398. package/templates/claude/commands/michi/confluence-sync.md +38 -0
  399. package/templates/claude/commands/michi/project-switch.md +36 -0
  400. package/templates/claude/rules/atlassian-integration.md +35 -0
  401. package/templates/claude/rules/michi-core.md +54 -0
  402. package/templates/claude-agent/README.md +31 -0
  403. package/templates/claude-agent/agents/.gitkeep +0 -0
  404. package/templates/claude-agent/agents/designer.md +79 -0
  405. package/templates/claude-agent/agents/developer.md +68 -0
  406. package/templates/claude-agent/agents/manager-agent.md +59 -0
  407. package/templates/claude-agent/agents/tester.md +101 -0
  408. package/templates/claude-agent/commands/kiro/.gitkeep +0 -0
  409. package/templates/claude-agent/commands/kiro/kiro-spec-impl.md +244 -0
  410. package/templates/claude-agent/commands/kiro/kiro-spec-tasks.md +354 -0
  411. package/templates/cline/rules/atlassian-integration.md +36 -0
  412. package/templates/cline/rules/michi-core.md +56 -0
  413. package/templates/codex/AGENTS.override.md +277 -0
  414. package/templates/codex/prompts/confluence-sync.md +177 -0
  415. package/templates/codex/rules/README.md +210 -0
  416. package/templates/common/.kiro/project.json.template +21 -0
  417. package/templates/cursor/commands/kiro/kiro-spec-impl.md +244 -0
  418. package/templates/cursor/commands/kiro/kiro-spec-tasks.md +354 -0
  419. package/templates/cursor/commands/michi/confluence-sync.md +76 -0
  420. package/templates/cursor/commands/michi/project-switch.md +69 -0
  421. package/templates/cursor/rules/atlassian-mcp.mdc +188 -0
  422. package/templates/cursor/rules/github-ssot.mdc +151 -0
  423. package/templates/cursor/rules/multi-project.mdc +81 -0
  424. package/templates/gemini/commands/README.md +41 -0
  425. package/templates/gemini/rules/GEMINI.md +80 -0
  426. package/docs/guides/workflow.md +0 -342
  427. package/docs/reference/config.md +0 -545
  428. package/scripts/setup-env.sh +0 -52
  429. package/scripts/setup-existing.sh +0 -152
  430. /package/docs/{contributing → michi-development/contributing}/development.md +0 -0
  431. /package/docs/{contributing → michi-development/contributing}/release.md +0 -0
  432. /package/docs/{testing-strategy.md → michi-development/testing-strategy.md} +0 -0
  433. /package/docs/{reference → user-guide/reference}/tasks-template.md +0 -0
@@ -23,14 +23,14 @@ import { config } from 'dotenv';
23
23
  import { loadProjectMeta } from './utils/project-meta.js';
24
24
  import { validateFeatureNameOrThrow } from './utils/feature-name-validator.js';
25
25
  import { getConfig, getConfigPath } from './utils/config-loader.js';
26
- import { validateForJiraSync } from './utils/config-validator.js';
27
- import { updateSpecJsonAfterJiraSync } from './utils/spec-updater.js';
26
+ import { validateForJiraSyncAsync } from './utils/config-validator.js';
27
+ import { updateSpecJsonAfterJiraSync, } from './utils/spec-updater.js';
28
28
  config();
29
29
  /**
30
30
  * リクエスト間のスリープ処理(レートリミット対策)
31
31
  */
32
32
  function sleep(ms) {
33
- return new Promise(resolve => setTimeout(resolve, ms));
33
+ return new Promise((resolve) => setTimeout(resolve, ms));
34
34
  }
35
35
  /**
36
36
  * リクエスト間の待機時間(ミリ秒)
@@ -73,18 +73,18 @@ function extractStoryDetails(tasksContent, storyTitle) {
73
73
  if (criteriaMatch) {
74
74
  details.acceptanceCriteria = criteriaMatch[1]
75
75
  .split('\n')
76
- .filter(line => line.trim().startsWith('- ['))
77
- .map(line => line.replace(/^- \[.\]\s*/, '').trim())
78
- .filter(line => line.length > 0);
76
+ .filter((line) => line.trim().startsWith('- ['))
77
+ .map((line) => line.replace(/^- \[.\]\s*/, '').trim())
78
+ .filter((line) => line.length > 0);
79
79
  }
80
80
  // サブタスク抽出
81
81
  const subtasksMatch = storySection.match(/\*\*サブタスク\*\*:\s*\n((?:- \[.\].*\n?)+)/);
82
82
  if (subtasksMatch) {
83
83
  details.subtasks = subtasksMatch[1]
84
84
  .split('\n')
85
- .filter(line => line.trim().startsWith('- ['))
86
- .map(line => line.replace(/^- \[.\]\s*/, '').trim())
87
- .filter(line => line.length > 0);
85
+ .filter((line) => line.trim().startsWith('- ['))
86
+ .map((line) => line.replace(/^- \[.\]\s*/, '').trim())
87
+ .filter((line) => line.length > 0);
88
88
  }
89
89
  // 依存関係抽出
90
90
  const dependenciesMatch = storySection.match(/\*\*依存関係\*\*:\s*(.+)/);
@@ -102,11 +102,11 @@ function createRichADF(details, phaseLabel, githubUrl) {
102
102
  content.push({
103
103
  type: 'heading',
104
104
  attrs: { level: 2 },
105
- content: [{ type: 'text', text: '説明' }]
105
+ content: [{ type: 'text', text: '説明' }],
106
106
  });
107
107
  content.push({
108
108
  type: 'paragraph',
109
- content: [{ type: 'text', text: details.description }]
109
+ content: [{ type: 'text', text: details.description }],
110
110
  });
111
111
  }
112
112
  // メタデータセクション
@@ -123,12 +123,12 @@ function createRichADF(details, phaseLabel, githubUrl) {
123
123
  content.push({
124
124
  type: 'heading',
125
125
  attrs: { level: 2 },
126
- content: [{ type: 'text', text: 'メタデータ' }]
126
+ content: [{ type: 'text', text: 'メタデータ' }],
127
127
  });
128
- metadata.forEach(item => {
128
+ metadata.forEach((item) => {
129
129
  content.push({
130
130
  type: 'paragraph',
131
- content: [{ type: 'text', text: item }]
131
+ content: [{ type: 'text', text: item }],
132
132
  });
133
133
  });
134
134
  }
@@ -137,18 +137,20 @@ function createRichADF(details, phaseLabel, githubUrl) {
137
137
  content.push({
138
138
  type: 'heading',
139
139
  attrs: { level: 2 },
140
- content: [{ type: 'text', text: '完了条件' }]
140
+ content: [{ type: 'text', text: '完了条件' }],
141
141
  });
142
- const listItems = details.acceptanceCriteria.map(criterion => ({
142
+ const listItems = details.acceptanceCriteria.map((criterion) => ({
143
143
  type: 'listItem',
144
- content: [{
144
+ content: [
145
+ {
145
146
  type: 'paragraph',
146
- content: [{ type: 'text', text: criterion }]
147
- }]
147
+ content: [{ type: 'text', text: criterion }],
148
+ },
149
+ ],
148
150
  }));
149
151
  content.push({
150
152
  type: 'bulletList',
151
- content: listItems
153
+ content: listItems,
152
154
  });
153
155
  }
154
156
  // サブタスクセクション
@@ -156,30 +158,32 @@ function createRichADF(details, phaseLabel, githubUrl) {
156
158
  content.push({
157
159
  type: 'heading',
158
160
  attrs: { level: 2 },
159
- content: [{ type: 'text', text: 'サブタスク' }]
161
+ content: [{ type: 'text', text: 'サブタスク' }],
160
162
  });
161
- const listItems = details.subtasks.map(subtask => ({
163
+ const listItems = details.subtasks.map((subtask) => ({
162
164
  type: 'listItem',
163
- content: [{
165
+ content: [
166
+ {
164
167
  type: 'paragraph',
165
- content: [{ type: 'text', text: subtask }]
166
- }]
168
+ content: [{ type: 'text', text: subtask }],
169
+ },
170
+ ],
167
171
  }));
168
172
  content.push({
169
173
  type: 'bulletList',
170
- content: listItems
174
+ content: listItems,
171
175
  });
172
176
  }
173
177
  // フッター(Phase、GitHubリンク)
174
178
  content.push({
175
- type: 'rule'
179
+ type: 'rule',
176
180
  });
177
181
  content.push({
178
182
  type: 'paragraph',
179
183
  content: [
180
184
  { type: 'text', text: 'Phase: ', marks: [{ type: 'strong' }] },
181
- { type: 'text', text: phaseLabel }
182
- ]
185
+ { type: 'text', text: phaseLabel },
186
+ ],
183
187
  });
184
188
  content.push({
185
189
  type: 'paragraph',
@@ -188,17 +192,19 @@ function createRichADF(details, phaseLabel, githubUrl) {
188
192
  {
189
193
  type: 'text',
190
194
  text: githubUrl,
191
- marks: [{
195
+ marks: [
196
+ {
192
197
  type: 'link',
193
- attrs: { href: githubUrl }
194
- }]
195
- }
196
- ]
198
+ attrs: { href: githubUrl },
199
+ },
200
+ ],
201
+ },
202
+ ],
197
203
  });
198
204
  return {
199
205
  type: 'doc',
200
206
  version: 1,
201
- content: content
207
+ content: content,
202
208
  };
203
209
  }
204
210
  /**
@@ -206,19 +212,19 @@ function createRichADF(details, phaseLabel, githubUrl) {
206
212
  */
207
213
  function textToADF(text) {
208
214
  // 改行で分割して段落を作成
209
- const paragraphs = text.split('\n').filter(line => line.trim().length > 0);
215
+ const paragraphs = text.split('\n').filter((line) => line.trim().length > 0);
210
216
  return {
211
217
  type: 'doc',
212
218
  version: 1,
213
- content: paragraphs.map(para => ({
219
+ content: paragraphs.map((para) => ({
214
220
  type: 'paragraph',
215
221
  content: [
216
222
  {
217
223
  type: 'text',
218
- text: para.trim()
219
- }
220
- ]
221
- }))
224
+ text: para.trim(),
225
+ },
226
+ ],
227
+ })),
222
228
  };
223
229
  }
224
230
  function getJIRAConfig() {
@@ -247,17 +253,43 @@ class JIRAClient {
247
253
  // レートリミット対策: リクエスト前に待機
248
254
  await sleep(this.requestDelay);
249
255
  try {
256
+ // JIRA API v3の検索エンドポイントを使用
257
+ // GET /rest/api/3/search でJQL検索を実行(GETメソッドが推奨)
250
258
  const response = await axios.get(`${this.baseUrl}/search`, {
251
- params: { jql, maxResults: 100 },
259
+ params: {
260
+ jql,
261
+ maxResults: 100,
262
+ fields: 'summary,issuetype,status,key',
263
+ },
252
264
  headers: {
253
- 'Authorization': `Basic ${this.auth}`,
254
- 'Content-Type': 'application/json'
255
- }
265
+ Authorization: `Basic ${this.auth}`,
266
+ 'Content-Type': 'application/json',
267
+ },
256
268
  });
257
269
  return response.data.issues || [];
258
270
  }
259
271
  catch (error) {
260
- console.error('Error searching issues:', error instanceof Error ? error.message : error);
272
+ // エラーハンドリング改善
273
+ if (axios.isAxiosError(error)) {
274
+ const status = error.response?.status;
275
+ const errorMessages = error.response?.data?.errorMessages || [];
276
+ const message = errorMessages.join(', ') || error.message;
277
+ console.error(`Error searching issues (HTTP ${status}): ${message}`);
278
+ if (status === 410) {
279
+ console.error('💡 Hint: The search API endpoint returned 410 (Gone).');
280
+ console.error(' This may indicate the endpoint has been deprecated or disabled.');
281
+ console.error(' Check JIRA instance configuration or try alternative search methods.');
282
+ }
283
+ else if (status === 401) {
284
+ console.error('💡 Hint: Authentication failed. Check ATLASSIAN_API_TOKEN in .env');
285
+ }
286
+ else if (status === 403) {
287
+ console.error('💡 Hint: Permission denied. Check API token permissions in JIRA.');
288
+ }
289
+ }
290
+ else {
291
+ console.error('Error searching issues:', error instanceof Error ? error.message : error);
292
+ }
261
293
  throw error; // エラーを再スローして呼び出し元で処理
262
294
  }
263
295
  }
@@ -266,9 +298,9 @@ class JIRAClient {
266
298
  await sleep(this.requestDelay);
267
299
  const response = await axios.post(`${this.baseUrl}/issue`, payload, {
268
300
  headers: {
269
- 'Authorization': `Basic ${this.auth}`,
270
- 'Content-Type': 'application/json'
271
- }
301
+ Authorization: `Basic ${this.auth}`,
302
+ 'Content-Type': 'application/json',
303
+ },
272
304
  });
273
305
  return response.data;
274
306
  }
@@ -277,28 +309,159 @@ class JIRAClient {
277
309
  await sleep(this.requestDelay);
278
310
  await axios.put(`${this.baseUrl}/issue/${issueKey}`, payload, {
279
311
  headers: {
280
- 'Authorization': `Basic ${this.auth}`,
281
- 'Content-Type': 'application/json'
282
- }
312
+ Authorization: `Basic ${this.auth}`,
313
+ 'Content-Type': 'application/json',
314
+ },
283
315
  });
284
316
  }
317
+ /**
318
+ * JIRAチケットのステータスを変更(トランジション実行)
319
+ * @param issueKey JIRAチケットキー (例: "PROJ-123")
320
+ * @param transitionName 遷移先ステータス名 (例: "In Progress", "Ready for Review")
321
+ * @throws トランジションが見つからない場合はエラー
322
+ */
323
+ async transitionIssue(issueKey, transitionName) {
324
+ // レートリミット対策: リクエスト前に待機
325
+ await sleep(this.requestDelay);
326
+ try {
327
+ // 1. 利用可能なトランジションを取得
328
+ const transitionsResponse = await axios.get(`${this.baseUrl}/issue/${issueKey}/transitions`, {
329
+ headers: {
330
+ Authorization: `Basic ${this.auth}`,
331
+ 'Content-Type': 'application/json',
332
+ },
333
+ });
334
+ const transitions = transitionsResponse.data.transitions || [];
335
+ // 2. transitionNameに一致するトランジションIDを特定
336
+ // 名前の完全一致または部分一致で検索
337
+ const transition = transitions.find((t) => t.name.toLowerCase() === transitionName.toLowerCase() ||
338
+ t.name.toLowerCase().includes(transitionName.toLowerCase()));
339
+ if (!transition) {
340
+ const availableTransitions = transitions
341
+ .map((t) => t.name)
342
+ .join(', ');
343
+ throw new Error(`Transition "${transitionName}" not found for issue ${issueKey}. ` +
344
+ `Available transitions: ${availableTransitions || 'none'}`);
345
+ }
346
+ // レートリミット対策: リクエスト前に待機
347
+ await sleep(this.requestDelay);
348
+ // 3. トランジションを実行
349
+ await axios.post(`${this.baseUrl}/issue/${issueKey}/transitions`, {
350
+ transition: { id: transition.id },
351
+ }, {
352
+ headers: {
353
+ Authorization: `Basic ${this.auth}`,
354
+ 'Content-Type': 'application/json',
355
+ },
356
+ });
357
+ console.log(`✅ ${issueKey} のステータスを「${transition.name}」に変更しました`);
358
+ }
359
+ catch (error) {
360
+ if (axios.isAxiosError(error)) {
361
+ const status = error.response?.status;
362
+ const errorMessages = error.response?.data?.errorMessages || [];
363
+ const message = errorMessages.join(', ') || error.message;
364
+ console.error(`Error transitioning issue ${issueKey} (HTTP ${status}): ${message}`);
365
+ if (status === 404) {
366
+ console.error(`💡 Hint: Issue ${issueKey} was not found. Check the issue key.`);
367
+ }
368
+ else if (status === 400) {
369
+ console.error('💡 Hint: The transition may not be valid from the current status.');
370
+ }
371
+ }
372
+ throw error;
373
+ }
374
+ }
375
+ /**
376
+ * JIRAチケットにコメントを追加
377
+ * @param issueKey JIRAチケットキー
378
+ * @param commentText コメント内容
379
+ */
380
+ async addComment(issueKey, commentText) {
381
+ // レートリミット対策: リクエスト前に待機
382
+ await sleep(this.requestDelay);
383
+ try {
384
+ // Atlassian Document Format (ADF) でコメントを作成
385
+ const commentBody = {
386
+ type: 'doc',
387
+ version: 1,
388
+ content: [
389
+ {
390
+ type: 'paragraph',
391
+ content: [
392
+ {
393
+ type: 'text',
394
+ text: commentText,
395
+ },
396
+ ],
397
+ },
398
+ ],
399
+ };
400
+ await axios.post(`${this.baseUrl}/issue/${issueKey}/comment`, {
401
+ body: commentBody,
402
+ }, {
403
+ headers: {
404
+ Authorization: `Basic ${this.auth}`,
405
+ 'Content-Type': 'application/json',
406
+ },
407
+ });
408
+ console.log(`✅ ${issueKey} にコメントを追加しました`);
409
+ }
410
+ catch (error) {
411
+ if (axios.isAxiosError(error)) {
412
+ const status = error.response?.status;
413
+ const errorMessages = error.response?.data?.errorMessages || [];
414
+ const message = errorMessages.join(', ') || error.message;
415
+ console.error(`Error adding comment to ${issueKey} (HTTP ${status}): ${message}`);
416
+ if (status === 404) {
417
+ console.error(`💡 Hint: Issue ${issueKey} was not found. Check the issue key.`);
418
+ }
419
+ }
420
+ throw error;
421
+ }
422
+ }
423
+ /**
424
+ * プロジェクトのIssue Type IDを取得
425
+ * @param projectKey プロジェクトキー
426
+ * @param issueTypeName Issue Type名(例: "Epic", "Story")
427
+ * @returns Issue Type ID
428
+ */
429
+ async getIssueTypeId(projectKey, issueTypeName) {
430
+ await sleep(this.requestDelay);
431
+ try {
432
+ const response = await axios.get(`${this.baseUrl}/project/${projectKey}`, {
433
+ headers: {
434
+ Authorization: `Basic ${this.auth}`,
435
+ 'Content-Type': 'application/json',
436
+ },
437
+ });
438
+ const issueTypes = (response.data.issueTypes || []);
439
+ const issueType = issueTypes.find((it) => it.name.toLowerCase() === issueTypeName.toLowerCase() ||
440
+ it.name === issueTypeName);
441
+ return issueType ? issueType.id : null;
442
+ }
443
+ catch (error) {
444
+ console.error(`Error getting issue type ID for ${issueTypeName}:`, error instanceof Error ? error.message : error);
445
+ return null;
446
+ }
447
+ }
285
448
  }
286
449
  async function syncTasksToJIRA(featureName) {
287
450
  console.log(`Syncing tasks for feature: ${featureName}`);
288
451
  // feature名のバリデーション(必須)
289
452
  validateFeatureNameOrThrow(featureName);
290
- // 実行前の必須設定値チェック
291
- const validation = validateForJiraSync();
453
+ // 実行前の必須設定値チェック(非同期版:Issue Type IDの存在チェック付き)
454
+ const validation = await validateForJiraSyncAsync();
292
455
  if (validation.info.length > 0) {
293
- validation.info.forEach(msg => console.log(`ℹ️ ${msg}`));
456
+ validation.info.forEach((msg) => console.log(`ℹ️ ${msg}`));
294
457
  }
295
458
  if (validation.warnings.length > 0) {
296
459
  console.warn('⚠️ Warnings:');
297
- validation.warnings.forEach(warning => console.warn(` ${warning}`));
460
+ validation.warnings.forEach((warning) => console.warn(` ${warning}`));
298
461
  }
299
462
  if (validation.errors.length > 0) {
300
463
  console.error('❌ Configuration errors:');
301
- validation.errors.forEach(error => console.error(` ${error}`));
464
+ validation.errors.forEach((error) => console.error(` ${error}`));
302
465
  const configPath = getConfigPath();
303
466
  console.error(`\n設定ファイル: ${configPath}`);
304
467
  throw new Error('JIRA同期に必要な設定値が不足しています。上記のエラーを確認して設定を修正してください。');
@@ -306,26 +469,35 @@ async function syncTasksToJIRA(featureName) {
306
469
  console.log(`⏳ Request delay: ${getRequestDelay()}ms (set ATLASSIAN_REQUEST_DELAY to adjust)`);
307
470
  // 設定からissue type IDを取得(検索と作成の両方で使用)
308
471
  const appConfig = getConfig();
309
- const storyIssueTypeId = appConfig.jira?.issueTypes?.story || process.env.JIRA_ISSUE_TYPE_STORY;
310
- const subtaskIssueTypeId = appConfig.jira?.issueTypes?.subtask || process.env.JIRA_ISSUE_TYPE_SUBTASK;
472
+ const projectMeta = loadProjectMeta();
473
+ const config = getJIRAConfig();
474
+ const client = new JIRAClient(config);
475
+ // StoryタイプのIDを動的に取得(日本語JIRAでは "ストーリー" という名前の場合がある)
476
+ let storyIssueTypeId = appConfig.jira?.issueTypes?.story || process.env.JIRA_ISSUE_TYPE_STORY;
477
+ console.log(`📋 Story Issue Type ID from config/env: ${storyIssueTypeId || 'not found'}`);
311
478
  if (!storyIssueTypeId) {
312
- throw new Error('JIRA Story issue type ID is not configured. ' +
479
+ console.log('🔍 Attempting to find Story issue type dynamically...');
480
+ const foundId = (await client.getIssueTypeId(projectMeta.jiraProjectKey, 'Story')) ||
481
+ (await client.getIssueTypeId(projectMeta.jiraProjectKey, 'ストーリー'));
482
+ storyIssueTypeId = foundId ?? undefined;
483
+ console.log(`📋 Story Issue Type ID from API: ${storyIssueTypeId || 'not found'}`);
484
+ }
485
+ if (!storyIssueTypeId) {
486
+ throw new Error('JIRA Story issue type ID is not configured and could not be found in project. ' +
313
487
  'Please set JIRA_ISSUE_TYPE_STORY environment variable or configure it in .michi/config.json. ' +
314
488
  'You can find the issue type ID in JIRA UI (Settings > Issues > Issue types) or via REST API: ' +
315
- 'GET https://your-domain.atlassian.net/rest/api/3/issuetype');
489
+ 'GET https://your-domain.atlassian.net/rest/api/3/project/{projectKey}');
316
490
  }
317
- const projectMeta = loadProjectMeta();
491
+ console.log(`✅ Using Story Issue Type ID: ${storyIssueTypeId}`);
318
492
  const tasksPath = resolve(`.kiro/specs/${featureName}/tasks.md`);
319
493
  const tasksContent = readFileSync(tasksPath, 'utf-8');
320
- const config = getJIRAConfig();
321
- const client = new JIRAClient(config);
322
494
  // spec.jsonを読み込んで既存のEpicキーを確認
323
495
  const specPath = resolve(`.kiro/specs/${featureName}/spec.json`);
324
496
  let spec = {};
325
497
  try {
326
498
  spec = JSON.parse(readFileSync(specPath, 'utf-8'));
327
499
  }
328
- catch (error) {
500
+ catch {
329
501
  console.error('spec.json not found or invalid');
330
502
  }
331
503
  let epic;
@@ -347,8 +519,10 @@ async function syncTasksToJIRA(featureName) {
347
519
  }
348
520
  catch (error) {
349
521
  console.error('❌ Failed to search existing Epics:', error instanceof Error ? error.message : error);
350
- console.error('⚠️ Cannot verify idempotency - Epic creation may result in duplicates');
351
- throw new Error(`JIRA Epic search failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
522
+ console.error('⚠️ Cannot verify idempotency - proceeding with Epic creation');
523
+ console.error(' If Epic already exists, manual cleanup may be required');
524
+ // 検索失敗時はフォールバック: 新規作成を試みる(重複リスクあり)
525
+ existingEpics = [];
352
526
  }
353
527
  if (existingEpics.length > 0) {
354
528
  console.log(`Found existing Epic with similar title: ${existingEpics[0].key}`);
@@ -356,27 +530,38 @@ async function syncTasksToJIRA(featureName) {
356
530
  epic = existingEpics[0];
357
531
  }
358
532
  else {
533
+ // EpicタイプのIDを取得(日本語JIRAでは "エピック" という名前の場合がある)
534
+ const epicTypeId = (await client.getIssueTypeId(projectMeta.jiraProjectKey, 'Epic')) ||
535
+ (await client.getIssueTypeId(projectMeta.jiraProjectKey, 'エピック'));
536
+ if (!epicTypeId) {
537
+ throw new Error('Epic issue type not found in project. ' +
538
+ 'Please ensure the project has Epic issue type enabled.');
539
+ }
359
540
  const epicDescription = `機能: ${featureName}\nGitHub: ${projectMeta.repository}/tree/main/.kiro/specs/${featureName}`;
360
541
  const epicPayload = {
361
542
  fields: {
362
543
  project: { key: projectMeta.jiraProjectKey },
363
544
  summary: epicSummary,
364
545
  description: textToADF(epicDescription), // ADF形式に変換
365
- issuetype: { name: 'Epic' },
366
- labels: projectMeta.confluenceLabels
367
- }
546
+ issuetype: { id: epicTypeId }, // IDを使用(nameではなく)
547
+ labels: projectMeta.confluenceLabels,
548
+ },
368
549
  };
369
550
  epic = await client.createIssue(epicPayload);
370
551
  console.log(`✅ Epic created: ${epic.key}`);
371
552
  }
372
553
  }
554
+ // Epicが確実に設定されていることを確認
555
+ if (!epic) {
556
+ throw new Error('Epic creation or retrieval failed');
557
+ }
373
558
  // 既存のStoryを検索(重複防止)
374
559
  // ラベルで検索(summary検索では "Story: タイトル" 形式に一致しないため)
375
560
  // issuetype検索にはIDを使用(名前は言語依存のため)
376
- const jql = `project = ${projectMeta.jiraProjectKey} AND issuetype = ${storyIssueTypeId} AND labels = "${featureName}"`;
561
+ const storyJql = `project = ${projectMeta.jiraProjectKey} AND issuetype = ${storyIssueTypeId} AND labels = "${featureName}"`;
377
562
  let existingStories = [];
378
563
  try {
379
- existingStories = await client.searchIssues(jql);
564
+ existingStories = await client.searchIssues(storyJql);
380
565
  }
381
566
  catch (error) {
382
567
  console.error('❌ Failed to search existing Stories:', error instanceof Error ? error.message : error);
@@ -385,12 +570,17 @@ async function syncTasksToJIRA(featureName) {
385
570
  // 検索失敗時も処理を継続(既存ストーリーなしとして扱う)
386
571
  existingStories = [];
387
572
  }
388
- const existingStorySummaries = new Set(existingStories.map((s) => s.fields.summary));
389
- const existingStoryKeys = new Set(existingStories.map((s) => s.key));
573
+ const existingStorySummaries = new Set(existingStories
574
+ .filter((s) => s?.fields?.summary)
575
+ .map((s) => s.fields.summary));
576
+ const existingStoryKeys = new Set(existingStories
577
+ .filter((s) => s?.key)
578
+ .map((s) => s.key));
390
579
  console.log(`Found ${existingStories.length} existing stories for this feature`);
391
580
  // フェーズラベル検出用の正規表現
392
581
  // Phase X: フェーズ名(ラベル)の形式を検出
393
- const phasePattern = /## Phase [\d.]+:\s*(.+?)((.+?))/;
582
+ // Phase番号: 数字(0, 1, 2...)、ドット付き数字(0.1, 0.2...)、英字(A, B)に対応
583
+ const phasePattern = /## Phase [\d.A-Z]+:\s*(.+?)(?:((.+?)))?/;
394
584
  // Story作成(フェーズ検出付きパーサー)
395
585
  const lines = tasksContent.split('\n');
396
586
  let currentPhaseLabel = 'implementation'; // デフォルトは実装フェーズ
@@ -400,27 +590,98 @@ async function syncTasksToJIRA(featureName) {
400
590
  // フェーズ検出
401
591
  const phaseMatch = line.match(phasePattern);
402
592
  if (phaseMatch) {
403
- const phaseName = phaseMatch[2]; // 括弧内のラベル(例: Requirements)
404
- // フェーズ名からラベルを決定
405
- if (phaseName.includes('要件定義') || phaseName.toLowerCase().includes('requirements')) {
593
+ const phaseTitle = phaseMatch[1]; // フェーズタイトル全体
594
+ const phaseName = phaseMatch[2] || phaseTitle; // 括弧内のラベル(例: Requirements)または全体
595
+ // Phase番号を抽出(例: "0.1", "2", "A")
596
+ const phaseNumberMatch = line.match(/## Phase ([\d.A-Z]+):/);
597
+ const phaseNumber = phaseNumberMatch ? phaseNumberMatch[1] : '';
598
+ // フェーズ番号またはフェーズ名からラベルを決定
599
+ // 新ワークフロー構造に対応
600
+ if (phaseNumber === '0.0' ||
601
+ phaseName.includes('初期化') ||
602
+ phaseName.toLowerCase().includes('init')) {
603
+ currentPhaseLabel = 'spec-init';
604
+ }
605
+ else if (phaseNumber === '0.1' ||
606
+ phaseName.includes('要件定義') ||
607
+ phaseName.toLowerCase().includes('requirements')) {
406
608
  currentPhaseLabel = 'requirements';
407
609
  }
408
- else if (phaseName.includes('設計') || phaseName.toLowerCase().includes('design')) {
610
+ else if (phaseNumber === '0.2' ||
611
+ phaseName.includes('設計') ||
612
+ phaseName.toLowerCase().includes('design')) {
409
613
  currentPhaseLabel = 'design';
410
614
  }
411
- else if (phaseName.includes('実装') || phaseName.toLowerCase().includes('implementation')) {
615
+ else if (phaseNumber === '0.3' ||
616
+ phaseName.includes('テストタイプ') ||
617
+ phaseName.toLowerCase().includes('test-type') ||
618
+ phaseName.toLowerCase().includes('test type')) {
619
+ currentPhaseLabel = 'test-type-selection';
620
+ }
621
+ else if (phaseNumber === '0.4' ||
622
+ phaseName.includes('テスト仕様') ||
623
+ phaseName.toLowerCase().includes('test-spec') ||
624
+ phaseName.toLowerCase().includes('test spec')) {
625
+ currentPhaseLabel = 'test-spec';
626
+ }
627
+ else if (phaseNumber === '0.5' ||
628
+ phaseName.includes('タスク分割') ||
629
+ phaseName.toLowerCase().includes('tasks') ||
630
+ phaseName.toLowerCase().includes('task breakdown')) {
631
+ currentPhaseLabel = 'spec-tasks';
632
+ }
633
+ else if (phaseNumber === '0.6' ||
634
+ phaseName.includes('JIRA') ||
635
+ phaseName.toLowerCase().includes('jira')) {
636
+ currentPhaseLabel = 'jira-sync';
637
+ }
638
+ else if (phaseNumber === '1' ||
639
+ phaseName.includes('環境構築') ||
640
+ phaseName.toLowerCase().includes('environment') ||
641
+ phaseName.toLowerCase().includes('setup')) {
642
+ currentPhaseLabel = 'environment-setup';
643
+ }
644
+ else if (phaseNumber === '2' ||
645
+ phaseName.includes('実装') ||
646
+ phaseName.includes('TDD') ||
647
+ phaseName.toLowerCase().includes('implementation')) {
412
648
  currentPhaseLabel = 'implementation';
413
649
  }
414
- else if (phaseName.includes('試験') || phaseName.toLowerCase().includes('testing')) {
415
- currentPhaseLabel = 'testing';
650
+ else if (phaseNumber === 'A' ||
651
+ phaseNumber.toLowerCase() === 'a' ||
652
+ phaseName.includes('PR前') ||
653
+ phaseName.toLowerCase().includes('pr-test') ||
654
+ phaseName.toLowerCase().includes('pr test')) {
655
+ currentPhaseLabel = 'phase-a';
416
656
  }
417
- else if (phaseName.includes('リリース準備') || phaseName.toLowerCase().includes('release-prep') || phaseName.toLowerCase().includes('release preparation')) {
657
+ else if (phaseNumber === '3' ||
658
+ phaseName.includes('追加QA') ||
659
+ phaseName.includes('QA') ||
660
+ phaseName.includes('試験') ||
661
+ phaseName.toLowerCase().includes('testing') ||
662
+ phaseName.toLowerCase().includes('additional qa')) {
663
+ currentPhaseLabel = 'additional-qa';
664
+ }
665
+ else if (phaseNumber === 'B' ||
666
+ phaseNumber.toLowerCase() === 'b' ||
667
+ phaseName.includes('リリース準備テスト') ||
668
+ phaseName.toLowerCase().includes('release-test') ||
669
+ phaseName.toLowerCase().includes('release test')) {
670
+ currentPhaseLabel = 'phase-b';
671
+ }
672
+ else if (phaseNumber === '4' ||
673
+ phaseName.includes('リリース準備') ||
674
+ phaseName.toLowerCase().includes('release-prep') ||
675
+ phaseName.toLowerCase().includes('release preparation')) {
418
676
  currentPhaseLabel = 'release-prep';
419
677
  }
420
- else if (phaseName.includes('リリース') || phaseName.toLowerCase().includes('release')) {
678
+ else if (phaseNumber === '5' ||
679
+ (phaseName.includes('リリース') && !phaseName.includes('準備')) ||
680
+ (phaseName.toLowerCase().includes('release') &&
681
+ !phaseName.toLowerCase().includes('prep'))) {
421
682
  currentPhaseLabel = 'release';
422
683
  }
423
- console.log(`📌 Phase detected: ${phaseName} (label: ${currentPhaseLabel})`);
684
+ console.log(`📌 Phase detected: ${phaseTitle} (number: ${phaseNumber}, label: ${currentPhaseLabel})`);
424
685
  continue;
425
686
  }
426
687
  // Story検出
@@ -432,9 +693,13 @@ async function syncTasksToJIRA(featureName) {
432
693
  // 既に同じタイトルのStoryが存在するかチェック
433
694
  if (existingStorySummaries.has(storySummary)) {
434
695
  console.log(`Skipping Story (already exists): ${storyTitle}`);
435
- const existing = existingStories.find((s) => s.fields.summary === storySummary);
696
+ const existing = existingStories.find((s) => s?.fields?.summary === storySummary);
436
697
  if (existing) {
437
698
  createdStories.push(existing.key);
699
+ existingStoryKeys.add(existing.key);
700
+ }
701
+ else {
702
+ console.warn(`⚠️ Warning: Story "${storyTitle}" is in summary set but not found in existingStories array`);
438
703
  }
439
704
  continue;
440
705
  }
@@ -448,9 +713,9 @@ async function syncTasksToJIRA(featureName) {
448
713
  const richDescription = createRichADF(storyDetails, currentPhaseLabel, githubUrl);
449
714
  // 優先度のマッピング(デフォルト: Medium)
450
715
  const priorityMap = {
451
- 'High': 'High',
452
- 'Medium': 'Medium',
453
- 'Low': 'Low'
716
+ High: 'High',
717
+ Medium: 'Medium',
718
+ Low: 'Low',
454
719
  };
455
720
  const priority = storyDetails.priority && priorityMap[storyDetails.priority]
456
721
  ? priorityMap[storyDetails.priority]
@@ -470,9 +735,13 @@ async function syncTasksToJIRA(featureName) {
470
735
  summary: storySummary,
471
736
  description: richDescription, // リッチなADF形式
472
737
  issuetype: { id: storyIssueTypeId },
473
- labels: [...projectMeta.confluenceLabels, featureName, currentPhaseLabel],
474
- priority: { name: priority }
475
- }
738
+ labels: [
739
+ ...projectMeta.confluenceLabels,
740
+ featureName,
741
+ currentPhaseLabel,
742
+ ],
743
+ priority: { name: priority },
744
+ },
476
745
  };
477
746
  // 期限(Due Date)を設定
478
747
  if (storyDetails.dueDate) {
@@ -516,7 +785,8 @@ async function syncTasksToJIRA(featureName) {
516
785
  if (error.response?.data) {
517
786
  console.error(' 📋 JIRA API Error Details:', JSON.stringify(error.response.data, null, 2));
518
787
  // Story Pointsフィールドのエラーの場合、警告を表示
519
- if (error.response.data.errors && Object.keys(error.response.data.errors).some(key => key.includes('customfield'))) {
788
+ if (error.response.data.errors &&
789
+ Object.keys(error.response.data.errors).some((key) => key.includes('customfield'))) {
520
790
  console.error(' ⚠️ Story Pointsフィールドの設定に失敗しました。');
521
791
  console.error(' 💡 環境変数 JIRA_STORY_POINTS_FIELD を正しいカスタムフィールドIDに設定してください。');
522
792
  console.error(' 💡 JIRA管理画面でStory PointsのカスタムフィールドIDを確認してください。');
@@ -526,8 +796,8 @@ async function syncTasksToJIRA(featureName) {
526
796
  }
527
797
  }
528
798
  // 新規作成数と再利用数を正確に計算
529
- const newStoryCount = createdStories.filter(key => !existingStoryKeys.has(key)).length;
530
- const reusedStoryCount = createdStories.filter(key => existingStoryKeys.has(key)).length;
799
+ const newStoryCount = createdStories.filter((key) => !existingStoryKeys.has(key)).length;
800
+ const reusedStoryCount = createdStories.filter((key) => existingStoryKeys.has(key)).length;
531
801
  console.log('\n✅ JIRA sync completed');
532
802
  console.log(` Epic: ${epic.key}`);
533
803
  console.log(` Stories: ${createdStories.length} processed (${newStoryCount} new, ${reusedStoryCount} reused)`);
@@ -538,7 +808,7 @@ async function syncTasksToJIRA(featureName) {
538
808
  projectKey: projectMeta.jiraProjectKey,
539
809
  epicKey: epic.key,
540
810
  epicUrl: `${jiraBaseUrl}/browse/${epic.key}`,
541
- storyKeys: createdStories
811
+ storyKeys: createdStories,
542
812
  });
543
813
  }
544
814
  catch (error) {