@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
@@ -0,0 +1,779 @@
1
+ /**
2
+ * 対話式テスト設定ツール
3
+ * Phase Bテスト(手動回帰、負荷、セキュリティ)を対話的に作成
4
+ */
5
+
6
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
7
+ import { join, dirname } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import * as readline from 'readline';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+
14
+ // テンプレートディレクトリ
15
+ const TEMPLATES_DIR = join(__dirname, '..', 'templates', 'testing');
16
+
17
+ /**
18
+ * テストタイプの定義
19
+ */
20
+ type TestType = 'manual-regression' | 'load-test' | 'security-test';
21
+
22
+ interface TestTypeConfig {
23
+ value: TestType;
24
+ label: string;
25
+ description: string;
26
+ templateFile: string;
27
+ }
28
+
29
+ const TEST_TYPES: TestTypeConfig[] = [
30
+ {
31
+ value: 'manual-regression',
32
+ label: '手動回帰テスト',
33
+ description: 'APIエンドポイントのcurlベース手動テスト',
34
+ templateFile: 'manual-regression-template.md'
35
+ },
36
+ {
37
+ value: 'load-test',
38
+ label: '負荷テスト(Locust)',
39
+ description: 'Locustを使用した負荷テスト',
40
+ templateFile: 'load-test-template.md'
41
+ },
42
+ {
43
+ value: 'security-test',
44
+ label: 'セキュリティテスト(OWASP ZAP)',
45
+ description: 'OWASP ZAPを使用したセキュリティテスト',
46
+ templateFile: 'security-test-template.md'
47
+ }
48
+ ];
49
+
50
+ /**
51
+ * 共通パラメータ
52
+ */
53
+ interface CommonParams {
54
+ projectName: string;
55
+ projectRoot: string;
56
+ baseUrl: string;
57
+ endpoint: string;
58
+ method: string;
59
+ }
60
+
61
+ /**
62
+ * 手動回帰テスト用パラメータ
63
+ */
64
+ interface ManualRegressionParams extends CommonParams {
65
+ bodyFormat: string;
66
+ successStatus: string;
67
+ errorStatus: string;
68
+ responseFormat: string;
69
+ sampleRequest: string;
70
+ sampleResponse: string;
71
+ startCommand: string;
72
+ port: string;
73
+ logCommand: string;
74
+ targetResponseTime: string;
75
+ }
76
+
77
+ /**
78
+ * 負荷テスト用パラメータ
79
+ */
80
+ interface LoadTestParams extends CommonParams {
81
+ totalUsers: string;
82
+ spawnRate: string;
83
+ runTime: string;
84
+ targetRps: string;
85
+ targetResponseTime: string;
86
+ maxErrorRate: string;
87
+ maxP95: string;
88
+ maxP99: string;
89
+ }
90
+
91
+ /**
92
+ * セキュリティテスト用パラメータ
93
+ */
94
+ interface SecurityTestParams extends CommonParams {
95
+ authType: string;
96
+ authHeader: string;
97
+ excludePaths: string;
98
+ scanPolicy: string;
99
+ maxAlerts: string;
100
+ }
101
+
102
+ /**
103
+ * readlineインターフェースを作成
104
+ */
105
+ function createInterface(): readline.Interface {
106
+ return readline.createInterface({
107
+ input: process.stdin,
108
+ output: process.stdout
109
+ });
110
+ }
111
+
112
+ /**
113
+ * 質問を表示して回答を取得
114
+ */
115
+ function question(rl: readline.Interface, query: string): Promise<string> {
116
+ return new Promise(resolve => {
117
+ rl.question(query, answer => {
118
+ resolve(answer.trim());
119
+ });
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Yes/No質問
125
+ */
126
+ async function confirm(rl: readline.Interface, prompt: string, defaultValue: boolean = true): Promise<boolean> {
127
+ const defaultText = defaultValue ? '[Y/n]' : '[y/N]';
128
+ const answer = await question(rl, `${prompt} ${defaultText}: `);
129
+
130
+ if (!answer) {
131
+ return defaultValue;
132
+ }
133
+
134
+ return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
135
+ }
136
+
137
+ /**
138
+ * 選択肢を表示
139
+ */
140
+ async function select<T extends { value: string; label: string }>(
141
+ rl: readline.Interface,
142
+ prompt: string,
143
+ choices: T[],
144
+ defaultIndex: number = 0
145
+ ): Promise<T> {
146
+ console.log(`\n${prompt}`);
147
+ choices.forEach((choice, index) => {
148
+ const marker = index === defaultIndex ? '*' : ' ';
149
+ console.log(` ${marker} ${index + 1}. ${choice.label}`);
150
+ });
151
+
152
+ const answer = await question(rl, `選択 [${defaultIndex + 1}]: `);
153
+ const selectedIndex = answer ? parseInt(answer, 10) - 1 : defaultIndex;
154
+
155
+ if (selectedIndex >= 0 && selectedIndex < choices.length) {
156
+ return choices[selectedIndex];
157
+ }
158
+ return choices[defaultIndex];
159
+ }
160
+
161
+ /**
162
+ * 共通パラメータの収集
163
+ */
164
+ async function collectCommonParams(rl: readline.Interface): Promise<CommonParams> {
165
+ console.log('\n📋 基本設定');
166
+ console.log('='.repeat(50));
167
+
168
+ const projectName = await question(rl, 'プロジェクト名: ') || 'My Project';
169
+ const projectRoot = await question(rl, 'プロジェクトルート [.]: ') || '.';
170
+ const baseUrl = await question(rl, 'ベースURL [http://localhost:8080]: ') || 'http://localhost:8080';
171
+ const endpoint = await question(rl, 'テスト対象エンドポイント [/api/health]: ') || '/api/health';
172
+
173
+ const methodChoices = [
174
+ { value: 'GET', label: 'GET' },
175
+ { value: 'POST', label: 'POST' },
176
+ { value: 'PUT', label: 'PUT' },
177
+ { value: 'DELETE', label: 'DELETE' },
178
+ { value: 'PATCH', label: 'PATCH' }
179
+ ];
180
+ const methodChoice = await select(rl, 'HTTPメソッド:', methodChoices, 0);
181
+
182
+ return {
183
+ projectName,
184
+ projectRoot,
185
+ baseUrl,
186
+ endpoint,
187
+ method: methodChoice.value
188
+ };
189
+ }
190
+
191
+ /**
192
+ * 手動回帰テストパラメータの収集
193
+ */
194
+ async function collectManualRegressionParams(
195
+ rl: readline.Interface,
196
+ common: CommonParams
197
+ ): Promise<ManualRegressionParams> {
198
+ console.log('\n🧪 手動回帰テスト設定');
199
+ console.log('='.repeat(50));
200
+
201
+ const bodyFormat = await question(rl, 'リクエストボディ形式 [JSON]: ') || 'JSON';
202
+ const successStatus = await question(rl, '期待HTTPステータス(成功時) [200]: ') || '200';
203
+ const errorStatus = await question(rl, '期待HTTPステータス(エラー時) [400]: ') || '400';
204
+ const responseFormat = await question(rl, '期待レスポンス形式 [{"status": "ok"}]: ') || '{"status": "ok"}';
205
+ const sampleRequest = await question(rl, 'サンプルリクエスト [{}]: ') || '{}';
206
+ const sampleResponse = await question(rl, 'サンプルレスポンス [{"status": "ok"}]: ') || '{"status": "ok"}';
207
+ const startCommand = await question(rl, 'アプリ起動コマンド [./gradlew bootRun]: ') || './gradlew bootRun';
208
+ const port = await question(rl, 'ポート番号 [8080]: ') || '8080';
209
+ const logCommand = await question(rl, 'ログ確認コマンド [tail -f logs/app.log]: ') || 'tail -f logs/app.log';
210
+ const targetResponseTime = await question(rl, '目標応答時間(ms) [500]: ') || '500';
211
+
212
+ return {
213
+ ...common,
214
+ bodyFormat,
215
+ successStatus,
216
+ errorStatus,
217
+ responseFormat,
218
+ sampleRequest,
219
+ sampleResponse,
220
+ startCommand,
221
+ port,
222
+ logCommand,
223
+ targetResponseTime
224
+ };
225
+ }
226
+
227
+ /**
228
+ * 負荷テストパラメータの収集
229
+ */
230
+ async function collectLoadTestParams(
231
+ rl: readline.Interface,
232
+ common: CommonParams
233
+ ): Promise<LoadTestParams> {
234
+ console.log('\n⚡ 負荷テスト設定');
235
+ console.log('='.repeat(50));
236
+
237
+ const totalUsers = await question(rl, '同時接続ユーザー数 [100]: ') || '100';
238
+ const spawnRate = await question(rl, 'ユーザー増加率(/秒) [10]: ') || '10';
239
+ const runTime = await question(rl, 'テスト実行時間 [5m]: ') || '5m';
240
+ const targetRps = await question(rl, '目標RPS [100]: ') || '100';
241
+ const targetResponseTime = await question(rl, '目標応答時間(ms) [500]: ') || '500';
242
+ const maxErrorRate = await question(rl, '許容エラー率(%) [1]: ') || '1';
243
+ const maxP95 = await question(rl, 'P95応答時間上限(ms) [1000]: ') || '1000';
244
+ const maxP99 = await question(rl, 'P99応答時間上限(ms) [2000]: ') || '2000';
245
+
246
+ return {
247
+ ...common,
248
+ totalUsers,
249
+ spawnRate,
250
+ runTime,
251
+ targetRps,
252
+ targetResponseTime,
253
+ maxErrorRate,
254
+ maxP95,
255
+ maxP99
256
+ };
257
+ }
258
+
259
+ /**
260
+ * セキュリティテストパラメータの収集
261
+ */
262
+ async function collectSecurityTestParams(
263
+ rl: readline.Interface,
264
+ common: CommonParams
265
+ ): Promise<SecurityTestParams> {
266
+ console.log('\n🔐 セキュリティテスト設定');
267
+ console.log('='.repeat(50));
268
+
269
+ const authTypeChoices = [
270
+ { value: 'none', label: '認証なし' },
271
+ { value: 'bearer', label: 'Bearer Token' },
272
+ { value: 'basic', label: 'Basic Auth' },
273
+ { value: 'api-key', label: 'API Key' }
274
+ ];
275
+ const authTypeChoice = await select(rl, '認証タイプ:', authTypeChoices, 0);
276
+
277
+ let authHeader = '';
278
+ if (authTypeChoice.value !== 'none') {
279
+ authHeader = await question(rl, '認証ヘッダー値: ') || '';
280
+ }
281
+
282
+ const excludePaths = await question(rl, '除外パス(カンマ区切り) [/health,/metrics]: ') || '/health,/metrics';
283
+
284
+ const scanPolicyChoices = [
285
+ { value: 'Default Policy', label: 'Default Policy(推奨)' },
286
+ { value: 'API-Minimal', label: 'API-Minimal(軽量)' },
287
+ { value: 'Full-Scan', label: 'Full-Scan(詳細)' }
288
+ ];
289
+ const scanPolicyChoice = await select(rl, 'スキャンポリシー:', scanPolicyChoices, 0);
290
+
291
+ const maxAlerts = await question(rl, '許容アラート数 [0]: ') || '0';
292
+
293
+ return {
294
+ ...common,
295
+ authType: authTypeChoice.value,
296
+ authHeader,
297
+ excludePaths,
298
+ scanPolicy: scanPolicyChoice.value,
299
+ maxAlerts
300
+ };
301
+ }
302
+
303
+ /**
304
+ * テンプレートを読み込んでパラメータを置換
305
+ */
306
+ function processTemplate(templateFile: string, params: Record<string, string>): string {
307
+ const templatePath = join(TEMPLATES_DIR, templateFile);
308
+
309
+ let content: string;
310
+
311
+ if (!existsSync(templatePath)) {
312
+ console.warn(`⚠️ テンプレートが見つかりません: ${templatePath}`);
313
+ console.warn(' デフォルトのテンプレートを使用します');
314
+
315
+ // デフォルトテンプレート(基本的なMarkdown構造)
316
+ content = `# テスト計画書
317
+
318
+ ## プロジェクト情報
319
+ - プロジェクト名: {{PROJECT_NAME}}
320
+ - プロジェクトルート: {{PROJECT_ROOT}}
321
+
322
+ ## テスト対象
323
+ - ベースURL: {{BASE_URL}}
324
+ - エンドポイント: {{ENDPOINT}}
325
+
326
+ ## テスト手順
327
+ 1. テスト環境の準備
328
+ 2. テストケースの実行
329
+ 3. 結果の記録
330
+
331
+ ## 注意事項
332
+ - このファイルは自動生成されたデフォルトテンプレートです
333
+ - 必要に応じて内容を編集してください
334
+ `;
335
+ } else {
336
+ content = readFileSync(templatePath, 'utf-8');
337
+ }
338
+
339
+ // パラメータを置換
340
+ for (const [key, value] of Object.entries(params)) {
341
+ const placeholder = `{{${key.toUpperCase()}}}`;
342
+ content = content.split(placeholder).join(value);
343
+ }
344
+
345
+ return content;
346
+ }
347
+
348
+ /**
349
+ * 安全なPythonクラス名を生成
350
+ * - 非英数字を削除
351
+ * - 空の場合は "Project" をフォールバック
352
+ * - 数字で始まる場合は "P" を前置
353
+ * - 最後に "User" を追加
354
+ */
355
+ function generateSafePythonClassName(projectName: string): string {
356
+ // 非英数字を削除
357
+ let safeName = projectName.replace(/[^a-zA-Z0-9]/g, '');
358
+
359
+ // 空の場合はフォールバック
360
+ if (safeName === '') {
361
+ safeName = 'Project';
362
+ }
363
+
364
+ // 数字で始まる場合は "P" を前置
365
+ if (/^[0-9]/.test(safeName)) {
366
+ safeName = 'P' + safeName;
367
+ }
368
+
369
+ // "User" を追加してクラス名を完成
370
+ return safeName + 'User';
371
+ }
372
+
373
+ /**
374
+ * 手動回帰テストの出力ファイルを生成
375
+ */
376
+ function generateManualRegressionFiles(params: ManualRegressionParams, outputDir: string): string[] {
377
+ const files: string[] = [];
378
+
379
+ // テンプレートパラメータを構築
380
+ const templateParams: Record<string, string> = {
381
+ project_name: params.projectName,
382
+ project_root: params.projectRoot,
383
+ base_url: params.baseUrl,
384
+ endpoint: params.endpoint,
385
+ method: params.method,
386
+ body_format: params.bodyFormat,
387
+ success_status: params.successStatus,
388
+ error_status: params.errorStatus,
389
+ response_format: params.responseFormat,
390
+ sample_request: params.sampleRequest,
391
+ sample_response: params.sampleResponse,
392
+ start_command: params.startCommand,
393
+ port: params.port,
394
+ log_command: params.logCommand,
395
+ target_response_time: params.targetResponseTime,
396
+ // テストケース用のプレースホルダー(デフォルト値)
397
+ normal_test_1_name: '基本リクエスト成功',
398
+ normal_test_1_request: params.sampleRequest,
399
+ normal_test_1_status: params.successStatus,
400
+ normal_test_1_response: params.sampleResponse,
401
+ normal_test_2_name: '別のリクエストパターン',
402
+ normal_test_2_request: params.sampleRequest,
403
+ normal_test_2_status: params.successStatus,
404
+ normal_test_2_response: params.sampleResponse,
405
+ error_test_1_name: '不正なリクエスト',
406
+ error_test_1_request: '{"invalid": true}',
407
+ error_test_1_status: params.errorStatus,
408
+ error_test_1_response: '{"error": "Bad Request"}',
409
+ error_test_2_name: '空のリクエスト',
410
+ error_test_2_request: '{}',
411
+ error_test_2_status: params.errorStatus,
412
+ sql_injection_request: '{"input": "\' OR 1=1 --"}',
413
+ xss_request: '{"input": "<script>alert(1)</script>"}',
414
+ repeat_char: 'A',
415
+ repeat_count: '10000',
416
+ input_field: 'input'
417
+ };
418
+
419
+ const content = processTemplate('manual-regression-template.md', templateParams);
420
+ const outputFile = join(outputDir, 'manual-regression-test.md');
421
+ writeFileSync(outputFile, content, 'utf-8');
422
+ files.push(outputFile);
423
+
424
+ return files;
425
+ }
426
+
427
+ /**
428
+ * 負荷テストの出力ファイルを生成
429
+ */
430
+ function generateLoadTestFiles(params: LoadTestParams, outputDir: string): string[] {
431
+ const files: string[] = [];
432
+
433
+ // テンプレートパラメータを構築
434
+ const templateParams: Record<string, string> = {
435
+ project_name: params.projectName,
436
+ base_url: params.baseUrl,
437
+ endpoint: params.endpoint,
438
+ method: params.method,
439
+ total_users: params.totalUsers,
440
+ spawn_rate: params.spawnRate,
441
+ run_time: params.runTime,
442
+ target_rps: params.targetRps,
443
+ target_response_time: params.targetResponseTime,
444
+ max_error_rate: params.maxErrorRate,
445
+ max_p95: params.maxP95,
446
+ max_p99: params.maxP99,
447
+ request_body: '{}'
448
+ };
449
+
450
+ const content = processTemplate('load-test-template.md', templateParams);
451
+ const outputFile = join(outputDir, 'load-test-plan.md');
452
+ writeFileSync(outputFile, content, 'utf-8');
453
+ files.push(outputFile);
454
+
455
+ // locustfile.pyも生成
456
+ const locustContent = generateLocustFile(params);
457
+ const locustFile = join(outputDir, 'locustfile.py');
458
+ writeFileSync(locustFile, locustContent, 'utf-8');
459
+ files.push(locustFile);
460
+
461
+ return files;
462
+ }
463
+
464
+ /**
465
+ * Locustファイルを生成
466
+ */
467
+ function generateLocustFile(params: LoadTestParams): string {
468
+ const methodLower = params.method.toLowerCase();
469
+ const hasBody = ['post', 'put', 'patch'].includes(methodLower);
470
+
471
+ // 安全なPythonクラス名を生成
472
+ const className = generateSafePythonClassName(params.projectName);
473
+
474
+ let taskCode = '';
475
+ if (hasBody) {
476
+ taskCode = ` self.client.${methodLower}(
477
+ "${params.endpoint}",
478
+ json={},
479
+ headers={"Content-Type": "application/json"}
480
+ )`;
481
+ } else {
482
+ taskCode = ` self.client.${methodLower}("${params.endpoint}")`;
483
+ }
484
+
485
+ return `"""
486
+ ${params.projectName} 負荷テスト
487
+ 自動生成: michi test-interactive
488
+ """
489
+
490
+ from locust import HttpUser, task, between
491
+
492
+
493
+ class ${className}(HttpUser):
494
+ """テスト対象ユーザーシミュレーション"""
495
+
496
+ wait_time = between(1, 3)
497
+ host = "${params.baseUrl}"
498
+
499
+ @task
500
+ def test_endpoint(self):
501
+ """${params.endpoint}への${params.method}リクエスト"""
502
+ ${taskCode}
503
+
504
+
505
+ # 実行方法:
506
+ # locust -f locustfile.py --users ${params.totalUsers} --spawn-rate ${params.spawnRate} --run-time ${params.runTime}
507
+ `;
508
+ }
509
+
510
+ /**
511
+ * セキュリティテストの出力ファイルを生成
512
+ */
513
+ function generateSecurityTestFiles(params: SecurityTestParams, outputDir: string): string[] {
514
+ const files: string[] = [];
515
+
516
+ // テンプレートパラメータを構築
517
+ const templateParams: Record<string, string> = {
518
+ project_name: params.projectName,
519
+ base_url: params.baseUrl,
520
+ endpoint: params.endpoint,
521
+ method: params.method,
522
+ auth_type: params.authType,
523
+ auth_header: params.authHeader,
524
+ exclude_paths: params.excludePaths,
525
+ scan_policy: params.scanPolicy,
526
+ max_alerts: params.maxAlerts
527
+ };
528
+
529
+ const content = processTemplate('security-test-template.md', templateParams);
530
+ const outputFile = join(outputDir, 'security-test-plan.md');
531
+ writeFileSync(outputFile, content, 'utf-8');
532
+ files.push(outputFile);
533
+
534
+ // ZAP設定ファイルも生成
535
+ const zapConfig = generateZapConfig(params);
536
+ const zapConfigFile = join(outputDir, 'zap-config.yaml');
537
+ writeFileSync(zapConfigFile, zapConfig, 'utf-8');
538
+ files.push(zapConfigFile);
539
+
540
+ // 実行スクリプトも生成
541
+ const zapScript = generateZapScript(params);
542
+ const zapScriptFile = join(outputDir, 'run-zap-scan.sh');
543
+ writeFileSync(zapScriptFile, zapScript, 'utf-8');
544
+ files.push(zapScriptFile);
545
+
546
+ return files;
547
+ }
548
+
549
+ /**
550
+ * ZAP設定ファイルを生成
551
+ */
552
+ function generateZapConfig(params: SecurityTestParams): string {
553
+ // excludePathsのリスト項目は8スペースでインデント(excludePathsの子要素)
554
+ const excludeList = params.excludePaths.split(',').map(p => ` - "${p.trim()}.*"`).join('\n');
555
+
556
+ let authConfig = '';
557
+ if (params.authType !== 'none' && params.authHeader) {
558
+ // authenticationブロックは6スペースでインデント(contextの子要素)
559
+ authConfig = `
560
+ authentication:
561
+ method: "script"
562
+ parameters:
563
+ authHeader: "${params.authHeader}"`;
564
+ }
565
+
566
+ return `# OWASP ZAP設定
567
+ # 自動生成: michi test-interactive
568
+
569
+ env:
570
+ contexts:
571
+ - name: "${params.projectName}"
572
+ urls:
573
+ - "${params.baseUrl}"
574
+ excludePaths:
575
+ ${excludeList}${authConfig}
576
+
577
+ jobs:
578
+ - type: spider
579
+ parameters:
580
+ context: "${params.projectName}"
581
+ maxDuration: 5
582
+ maxDepth: 5
583
+
584
+ - type: activeScan
585
+ parameters:
586
+ context: "${params.projectName}"
587
+ policy: "${params.scanPolicy}"
588
+ maxRuleDurationInMins: 5
589
+ maxScanDurationInMins: 30
590
+
591
+ - type: report
592
+ parameters:
593
+ template: "traditional-json"
594
+ reportDir: "./reports"
595
+ reportFile: "zap-report"
596
+ - type: report
597
+ parameters:
598
+ template: "traditional-html"
599
+ reportDir: "./reports"
600
+ reportFile: "zap-report-html"
601
+ `;
602
+ }
603
+
604
+ /**
605
+ * ZAP実行スクリプトを生成
606
+ */
607
+ function generateZapScript(params: SecurityTestParams): string {
608
+ return `#!/bin/bash
609
+ # OWASP ZAPセキュリティスキャン実行スクリプト
610
+ # 自動生成: michi test-interactive
611
+
612
+ set -e
613
+
614
+ # 変数定義
615
+ TARGET_URL="${params.baseUrl}"
616
+ CONFIG_FILE="zap-config.yaml"
617
+ REPORT_DIR="./reports"
618
+
619
+ # レポートディレクトリ作成
620
+ mkdir -p "\${REPORT_DIR}"
621
+
622
+ echo "🔐 OWASP ZAPセキュリティスキャン開始"
623
+ echo "対象: \${TARGET_URL}"
624
+ echo "設定: \${CONFIG_FILE}"
625
+
626
+ # Docker経由でZAPを実行
627
+ docker run --rm -v "$(pwd):/zap/wrk:rw" \\
628
+ -t ghcr.io/zaproxy/zaproxy:stable \\
629
+ zap.sh -cmd \\
630
+ -autorun /zap/wrk/\${CONFIG_FILE}
631
+
632
+ echo "✅ スキャン完了"
633
+ echo "レポート: \${REPORT_DIR}/zap-report.json"
634
+ echo "HTML版: \${REPORT_DIR}/zap-report-html.html"
635
+
636
+ # アラート数チェック(JSON + jq使用)
637
+ JSON_REPORT="\${REPORT_DIR}/zap-report.json"
638
+ MAX_ALERTS=${params.maxAlerts}
639
+
640
+ if [ ! -f "\${JSON_REPORT}" ]; then
641
+ echo "⚠️ JSONレポートが見つかりません: \${JSON_REPORT}"
642
+ ALERT_COUNT=0
643
+ elif ! command -v jq &> /dev/null; then
644
+ echo "⚠️ jqコマンドが見つかりません。アラート数を0として処理します"
645
+ echo " jqをインストールしてください: brew install jq"
646
+ ALERT_COUNT=0
647
+ else
648
+ # ZAP JSONレポートから全アラートをカウント
649
+ ALERT_COUNT=$(jq '[.. | .alerts? | select(. != null) | .[]] | length' "\${JSON_REPORT}" 2>/dev/null || echo "0")
650
+
651
+ # 数値でない場合は0にフォールバック
652
+ if ! [[ "\${ALERT_COUNT}" =~ ^[0-9]+$ ]]; then
653
+ echo "⚠️ アラート数の解析に失敗しました。0として処理します"
654
+ ALERT_COUNT=0
655
+ fi
656
+ fi
657
+
658
+ if [ "\${ALERT_COUNT}" -gt "\${MAX_ALERTS}" ]; then
659
+ echo "❌ アラート数が閾値を超えています: \${ALERT_COUNT} > \${MAX_ALERTS}"
660
+ exit 1
661
+ else
662
+ echo "✅ アラート数: \${ALERT_COUNT} (許容: \${MAX_ALERTS})"
663
+ fi
664
+ `;
665
+ }
666
+
667
+ /**
668
+ * メイン処理
669
+ */
670
+ async function main(): Promise<number> {
671
+ const rl = createInterface();
672
+
673
+ try {
674
+ console.log('🧪 Michi テスト設定ツール');
675
+ console.log('='.repeat(60));
676
+ console.log('Phase Bテスト(手動回帰、負荷、セキュリティ)を対話的に作成します。\n');
677
+
678
+ // テストタイプを選択
679
+ const testTypeChoices = TEST_TYPES.map(t => ({
680
+ value: t.value,
681
+ label: `${t.label} - ${t.description}`
682
+ }));
683
+
684
+ console.log('テストタイプを選択してください:');
685
+ TEST_TYPES.forEach((t, index) => {
686
+ console.log(` ${index + 1}. ${t.label}`);
687
+ console.log(` ${t.description}`);
688
+ });
689
+
690
+ const typeAnswer = await question(rl, '\n選択 [1]: ');
691
+ const typeIndex = typeAnswer ? parseInt(typeAnswer, 10) - 1 : 0;
692
+ const selectedType = TEST_TYPES[typeIndex >= 0 && typeIndex < TEST_TYPES.length ? typeIndex : 0];
693
+
694
+ console.log(`\n選択: ${selectedType.label}`);
695
+
696
+ // 共通パラメータを収集
697
+ const commonParams = await collectCommonParams(rl);
698
+
699
+ // 出力ディレクトリを決定
700
+ const defaultOutputDir = join(process.cwd(), 'tests', selectedType.value);
701
+ const outputDir = await question(rl, `\n出力ディレクトリ [${defaultOutputDir}]: `) || defaultOutputDir;
702
+
703
+ // ディレクトリ作成
704
+ if (!existsSync(outputDir)) {
705
+ mkdirSync(outputDir, { recursive: true });
706
+ }
707
+
708
+ let generatedFiles: string[] = [];
709
+
710
+ // テストタイプ別のパラメータ収集と生成
711
+ switch (selectedType.value) {
712
+ case 'manual-regression': {
713
+ const params = await collectManualRegressionParams(rl, commonParams);
714
+ generatedFiles = generateManualRegressionFiles(params, outputDir);
715
+ break;
716
+ }
717
+ case 'load-test': {
718
+ const params = await collectLoadTestParams(rl, commonParams);
719
+ generatedFiles = generateLoadTestFiles(params, outputDir);
720
+ break;
721
+ }
722
+ case 'security-test': {
723
+ const params = await collectSecurityTestParams(rl, commonParams);
724
+ generatedFiles = generateSecurityTestFiles(params, outputDir);
725
+ break;
726
+ }
727
+ }
728
+
729
+ // 結果表示
730
+ console.log('\n✅ テストファイルを生成しました:');
731
+ console.log('='.repeat(50));
732
+ generatedFiles.forEach(file => {
733
+ console.log(` 📄 ${file}`);
734
+ });
735
+
736
+ // 次のステップを案内
737
+ console.log('\n📋 次のステップ:');
738
+ switch (selectedType.value) {
739
+ case 'manual-regression':
740
+ console.log(' 1. 生成されたMarkdownファイルを確認・編集');
741
+ console.log(' 2. アプリケーションを起動');
742
+ console.log(' 3. curlコマンドを実行してテスト');
743
+ break;
744
+ case 'load-test':
745
+ console.log(' 1. pip install locust');
746
+ console.log(` 2. cd ${outputDir}`);
747
+ console.log(' 3. locust -f locustfile.py --web-host localhost');
748
+ console.log(' 4. http://localhost:8089 でテスト開始');
749
+ break;
750
+ case 'security-test':
751
+ console.log(' 1. Docker Desktop を起動');
752
+ console.log(` 2. cd ${outputDir}`);
753
+ console.log(' 3. chmod +x run-zap-scan.sh');
754
+ console.log(' 4. ./run-zap-scan.sh');
755
+ break;
756
+ }
757
+
758
+ console.log('\n🎉 設定が完了しました!');
759
+ return 0;
760
+
761
+ } catch (error) {
762
+ console.error('❌ エラーが発生しました:', error instanceof Error ? error.message : error);
763
+ return 1;
764
+ } finally {
765
+ rl.close();
766
+ }
767
+ }
768
+
769
+ // CLI実行
770
+ main()
771
+ .then(exitCode => {
772
+ process.exit(exitCode);
773
+ })
774
+ .catch(error => {
775
+ console.error('❌ 予期しないエラー:', error);
776
+ process.exit(1);
777
+ });
778
+
779
+ export { main as testInteractive };