@sk8metal/michi-cli 0.4.0 → 0.7.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 (321) hide show
  1. package/CHANGELOG.md +162 -1
  2. package/README.md +2 -1
  3. package/dist/scripts/config/config-schema.d.ts +87 -0
  4. package/dist/scripts/config/config-schema.d.ts.map +1 -1
  5. package/dist/scripts/config/config-schema.js +81 -0
  6. package/dist/scripts/config/config-schema.js.map +1 -1
  7. package/dist/scripts/confluence-sync.d.ts.map +1 -1
  8. package/dist/scripts/confluence-sync.js +15 -2
  9. package/dist/scripts/confluence-sync.js.map +1 -1
  10. package/dist/scripts/github-actions-client.d.ts +79 -0
  11. package/dist/scripts/github-actions-client.d.ts.map +1 -0
  12. package/dist/scripts/github-actions-client.js +182 -0
  13. package/dist/scripts/github-actions-client.js.map +1 -0
  14. package/dist/scripts/health-check-service.d.ts +46 -0
  15. package/dist/scripts/health-check-service.d.ts.map +1 -0
  16. package/dist/scripts/health-check-service.js +114 -0
  17. package/dist/scripts/health-check-service.js.map +1 -0
  18. package/dist/scripts/markdown-to-confluence.d.ts.map +1 -1
  19. package/dist/scripts/markdown-to-confluence.js +25 -3
  20. package/dist/scripts/markdown-to-confluence.js.map +1 -1
  21. package/dist/scripts/mermaid-converter.d.ts +24 -0
  22. package/dist/scripts/mermaid-converter.d.ts.map +1 -0
  23. package/dist/scripts/mermaid-converter.js +49 -0
  24. package/dist/scripts/mermaid-converter.js.map +1 -0
  25. package/dist/scripts/pr-automation.d.ts.map +1 -1
  26. package/dist/scripts/pr-automation.js +11 -3
  27. package/dist/scripts/pr-automation.js.map +1 -1
  28. package/dist/scripts/spec-impl-workflow.d.ts.map +1 -1
  29. package/dist/scripts/spec-impl-workflow.js +22 -6
  30. package/dist/scripts/spec-impl-workflow.js.map +1 -1
  31. package/dist/scripts/template/multi-repo-renderer.d.ts +67 -0
  32. package/dist/scripts/template/multi-repo-renderer.d.ts.map +1 -0
  33. package/dist/scripts/template/multi-repo-renderer.js +123 -0
  34. package/dist/scripts/template/multi-repo-renderer.js.map +1 -0
  35. package/dist/scripts/template/renderer.d.ts +4 -0
  36. package/dist/scripts/template/renderer.d.ts.map +1 -1
  37. package/dist/scripts/template/renderer.js.map +1 -1
  38. package/dist/scripts/test-execution-generator.d.ts.map +1 -1
  39. package/dist/scripts/test-execution-generator.js +94 -11
  40. package/dist/scripts/test-execution-generator.js.map +1 -1
  41. package/dist/scripts/test-script-runner.d.ts +33 -0
  42. package/dist/scripts/test-script-runner.d.ts.map +1 -0
  43. package/dist/scripts/test-script-runner.js +77 -0
  44. package/dist/scripts/test-script-runner.js.map +1 -0
  45. package/dist/scripts/utils/config-loader.d.ts +31 -5
  46. package/dist/scripts/utils/config-loader.d.ts.map +1 -1
  47. package/dist/scripts/utils/config-loader.js +363 -50
  48. package/dist/scripts/utils/config-loader.js.map +1 -1
  49. package/dist/scripts/utils/env-config.d.ts +1 -1
  50. package/dist/scripts/utils/env-config.d.ts.map +1 -1
  51. package/dist/scripts/utils/env-config.js +2 -14
  52. package/dist/scripts/utils/env-config.js.map +1 -1
  53. package/dist/scripts/utils/multi-repo-validator.d.ts +30 -0
  54. package/dist/scripts/utils/multi-repo-validator.d.ts.map +1 -0
  55. package/dist/scripts/utils/multi-repo-validator.js +105 -0
  56. package/dist/scripts/utils/multi-repo-validator.js.map +1 -0
  57. package/dist/scripts/utils/project-meta.d.ts +9 -0
  58. package/dist/scripts/utils/project-meta.d.ts.map +1 -1
  59. package/dist/scripts/utils/project-meta.js +22 -0
  60. package/dist/scripts/utils/project-meta.js.map +1 -1
  61. package/dist/scripts/utils/security-validator.d.ts +55 -0
  62. package/dist/scripts/utils/security-validator.d.ts.map +1 -0
  63. package/dist/scripts/utils/security-validator.js +232 -0
  64. package/dist/scripts/utils/security-validator.js.map +1 -0
  65. package/dist/scripts/utils/spec-archiver.d.ts +38 -0
  66. package/dist/scripts/utils/spec-archiver.d.ts.map +1 -0
  67. package/dist/scripts/utils/spec-archiver.js +210 -0
  68. package/dist/scripts/utils/spec-archiver.js.map +1 -0
  69. package/dist/scripts/utils/spec-updater.d.ts +4 -0
  70. package/dist/scripts/utils/spec-updater.d.ts.map +1 -1
  71. package/dist/scripts/utils/spec-updater.js.map +1 -1
  72. package/dist/src/cli.d.ts.map +1 -1
  73. package/dist/src/cli.js +303 -17
  74. package/dist/src/cli.js.map +1 -1
  75. package/dist/src/commands/config-validate.d.ts +9 -0
  76. package/dist/src/commands/config-validate.d.ts.map +1 -0
  77. package/dist/src/commands/config-validate.js +90 -0
  78. package/dist/src/commands/config-validate.js.map +1 -0
  79. package/dist/src/commands/init.d.ts +1 -0
  80. package/dist/src/commands/init.d.ts.map +1 -1
  81. package/dist/src/commands/init.js +29 -6
  82. package/dist/src/commands/init.js.map +1 -1
  83. package/dist/src/commands/migrate.d.ts +25 -0
  84. package/dist/src/commands/migrate.d.ts.map +1 -0
  85. package/dist/src/commands/migrate.js +341 -0
  86. package/dist/src/commands/migrate.js.map +1 -0
  87. package/dist/src/commands/multi-repo-add-repo.d.ts +26 -0
  88. package/dist/src/commands/multi-repo-add-repo.d.ts.map +1 -0
  89. package/dist/src/commands/multi-repo-add-repo.js +56 -0
  90. package/dist/src/commands/multi-repo-add-repo.js.map +1 -0
  91. package/dist/src/commands/multi-repo-ci-status.d.ts +46 -0
  92. package/dist/src/commands/multi-repo-ci-status.d.ts.map +1 -0
  93. package/dist/src/commands/multi-repo-ci-status.js +285 -0
  94. package/dist/src/commands/multi-repo-ci-status.js.map +1 -0
  95. package/dist/src/commands/multi-repo-confluence-sync.d.ts +45 -0
  96. package/dist/src/commands/multi-repo-confluence-sync.d.ts.map +1 -0
  97. package/dist/src/commands/multi-repo-confluence-sync.js +135 -0
  98. package/dist/src/commands/multi-repo-confluence-sync.js.map +1 -0
  99. package/dist/src/commands/multi-repo-init.d.ts +26 -0
  100. package/dist/src/commands/multi-repo-init.d.ts.map +1 -0
  101. package/dist/src/commands/multi-repo-init.js +101 -0
  102. package/dist/src/commands/multi-repo-init.js.map +1 -0
  103. package/dist/src/commands/multi-repo-list.d.ts +28 -0
  104. package/dist/src/commands/multi-repo-list.d.ts.map +1 -0
  105. package/dist/src/commands/multi-repo-list.js +38 -0
  106. package/dist/src/commands/multi-repo-list.js.map +1 -0
  107. package/dist/src/commands/multi-repo-test.d.ts +56 -0
  108. package/dist/src/commands/multi-repo-test.d.ts.map +1 -0
  109. package/dist/src/commands/multi-repo-test.js +70 -0
  110. package/dist/src/commands/multi-repo-test.js.map +1 -0
  111. package/dist/src/commands/setup-existing.d.ts.map +1 -1
  112. package/dist/src/commands/setup-existing.js +0 -1
  113. package/dist/src/commands/setup-existing.js.map +1 -1
  114. package/dist/src/commands/spec-archive.d.ts +17 -0
  115. package/dist/src/commands/spec-archive.d.ts.map +1 -0
  116. package/dist/src/commands/spec-archive.js +40 -0
  117. package/dist/src/commands/spec-archive.js.map +1 -0
  118. package/dist/src/commands/spec-list.d.ts +15 -0
  119. package/dist/src/commands/spec-list.d.ts.map +1 -0
  120. package/dist/src/commands/spec-list.js +55 -0
  121. package/dist/src/commands/spec-list.js.map +1 -0
  122. package/dist/vitest.config.d.ts.map +1 -1
  123. package/dist/vitest.config.js +32 -8
  124. package/dist/vitest.config.js.map +1 -1
  125. package/docs/michi-development/design/config-unification.md +4789 -0
  126. package/docs/user-guide/getting-started/github-token-setup.md +2 -1
  127. package/docs/user-guide/getting-started/new-repository-setup.md +1 -1
  128. package/docs/user-guide/getting-started/quick-start.md +1 -1
  129. package/docs/user-guide/getting-started/setup.md +4 -11
  130. package/docs/user-guide/guides/multi-repo-guide.md +591 -0
  131. package/docs/user-guide/guides/multi-repo-migration-guide.md +516 -0
  132. package/docs/user-guide/hands-on/claude-agent-setup.md +2 -2
  133. package/docs/user-guide/hands-on/claude-setup.md +2 -2
  134. package/docs/user-guide/hands-on/cursor-setup.md +2 -2
  135. package/docs/user-guide/hands-on/workflow-walkthrough.md +4 -1
  136. package/docs/user-guide/reference/multi-repo-api.md +771 -0
  137. package/docs/user-guide/reference/quick-reference.md +22 -37
  138. package/env.example +1 -1
  139. package/package.json +2 -5
  140. package/scripts/__tests__/config-loader-multi-repo.test.ts +342 -0
  141. package/scripts/__tests__/github-actions-client.test.ts +543 -0
  142. package/scripts/__tests__/health-check-service.test.ts +142 -0
  143. package/scripts/__tests__/markdown-to-confluence.test.ts +262 -0
  144. package/scripts/__tests__/mermaid-converter.test.ts +236 -0
  145. package/scripts/__tests__/multi-repo-config-schema.test.ts +335 -0
  146. package/scripts/__tests__/multi-repo-validator.test.ts +524 -0
  147. package/scripts/__tests__/spec-archiver.test.ts +512 -0
  148. package/scripts/__tests__/spec-impl-workflow.test.ts +5 -2
  149. package/scripts/__tests__/test-script-runner.test.ts +217 -0
  150. package/scripts/config/config-schema.ts +104 -0
  151. package/scripts/confluence-sync.ts +16 -2
  152. package/scripts/github-actions-client.ts +258 -0
  153. package/scripts/health-check-service.ts +171 -0
  154. package/scripts/markdown-to-confluence.ts +37 -6
  155. package/scripts/mermaid-converter.ts +56 -0
  156. package/scripts/pr-automation.ts +15 -5
  157. package/scripts/spec-impl-workflow.ts +22 -6
  158. package/scripts/template/__tests__/multi-repo-renderer.test.ts +261 -0
  159. package/scripts/template/multi-repo-renderer.ts +172 -0
  160. package/scripts/template/renderer.ts +5 -0
  161. package/scripts/test-execution-generator.ts +104 -11
  162. package/scripts/test-script-runner.ts +130 -0
  163. package/scripts/utils/__tests__/config-loader.test.ts +149 -0
  164. package/scripts/utils/__tests__/config-validator.test.ts +106 -6
  165. package/scripts/utils/__tests__/env-config.test.ts +0 -2
  166. package/scripts/utils/__tests__/multi-repo-validator.test.ts +335 -0
  167. package/scripts/utils/__tests__/project-meta.test.ts +192 -0
  168. package/scripts/utils/__tests__/security-validator.test.ts +272 -0
  169. package/scripts/utils/config-loader.ts +429 -56
  170. package/scripts/utils/env-config.ts +2 -14
  171. package/scripts/utils/multi-repo-validator.ts +141 -0
  172. package/scripts/utils/project-meta.ts +27 -0
  173. package/scripts/utils/security-validator.ts +286 -0
  174. package/scripts/utils/spec-archiver.ts +260 -0
  175. package/scripts/utils/spec-updater.ts +4 -0
  176. package/templates/claude/agents/pr-size-monitor/AGENT.md +330 -0
  177. package/templates/claude/commands/kiro/kiro-spec-impl.md +1 -1
  178. package/templates/claude/commands/michi/spec-impl.md +208 -35
  179. package/templates/claude-agent/commands/kiro/kiro-spec-impl.md +1 -1
  180. package/templates/cursor/commands/kiro/kiro-spec-impl.md +1 -1
  181. package/templates/multi-repo/docs/ci-status.md +51 -0
  182. package/templates/multi-repo/docs/release-notes.md +99 -0
  183. package/templates/multi-repo/overview/architecture.md +102 -0
  184. package/templates/multi-repo/overview/requirements.md +68 -0
  185. package/templates/multi-repo/overview/sequence.md +79 -0
  186. package/templates/multi-repo/steering/multi-repo.md +74 -0
  187. package/templates/multi-repo/tests/strategy.md +89 -0
  188. package/dist/scripts/__tests__/create-project.test.d.ts +0 -2
  189. package/dist/scripts/__tests__/create-project.test.d.ts.map +0 -1
  190. package/dist/scripts/__tests__/create-project.test.js +0 -243
  191. package/dist/scripts/__tests__/create-project.test.js.map +0 -1
  192. package/dist/scripts/__tests__/jira-transitions.test.d.ts +0 -5
  193. package/dist/scripts/__tests__/jira-transitions.test.d.ts.map +0 -1
  194. package/dist/scripts/__tests__/jira-transitions.test.js +0 -172
  195. package/dist/scripts/__tests__/jira-transitions.test.js.map +0 -1
  196. package/dist/scripts/__tests__/multi-project-estimate.test.d.ts +0 -2
  197. package/dist/scripts/__tests__/multi-project-estimate.test.d.ts.map +0 -1
  198. package/dist/scripts/__tests__/multi-project-estimate.test.js +0 -118
  199. package/dist/scripts/__tests__/multi-project-estimate.test.js.map +0 -1
  200. package/dist/scripts/__tests__/setup-existing-project.test.d.ts +0 -2
  201. package/dist/scripts/__tests__/setup-existing-project.test.d.ts.map +0 -1
  202. package/dist/scripts/__tests__/setup-existing-project.test.js +0 -208
  203. package/dist/scripts/__tests__/setup-existing-project.test.js.map +0 -1
  204. package/dist/scripts/__tests__/setup-interactive.test.d.ts +0 -2
  205. package/dist/scripts/__tests__/setup-interactive.test.d.ts.map +0 -1
  206. package/dist/scripts/__tests__/setup-interactive.test.js +0 -166
  207. package/dist/scripts/__tests__/setup-interactive.test.js.map +0 -1
  208. package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts +0 -5
  209. package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts.map +0 -1
  210. package/dist/scripts/__tests__/spec-impl-workflow.test.js +0 -321
  211. package/dist/scripts/__tests__/spec-impl-workflow.test.js.map +0 -1
  212. package/dist/scripts/__tests__/spec-loader.test.d.ts +0 -5
  213. package/dist/scripts/__tests__/spec-loader.test.d.ts.map +0 -1
  214. package/dist/scripts/__tests__/spec-loader.test.js +0 -153
  215. package/dist/scripts/__tests__/spec-loader.test.js.map +0 -1
  216. package/dist/scripts/__tests__/validate-phase.test.d.ts +0 -5
  217. package/dist/scripts/__tests__/validate-phase.test.d.ts.map +0 -1
  218. package/dist/scripts/__tests__/validate-phase.test.js +0 -249
  219. package/dist/scripts/__tests__/validate-phase.test.js.map +0 -1
  220. package/dist/scripts/constants/__tests__/environments.test.d.ts +0 -2
  221. package/dist/scripts/constants/__tests__/environments.test.d.ts.map +0 -1
  222. package/dist/scripts/constants/__tests__/environments.test.js +0 -125
  223. package/dist/scripts/constants/__tests__/environments.test.js.map +0 -1
  224. package/dist/scripts/constants/__tests__/languages.test.d.ts +0 -2
  225. package/dist/scripts/constants/__tests__/languages.test.d.ts.map +0 -1
  226. package/dist/scripts/constants/__tests__/languages.test.js +0 -82
  227. package/dist/scripts/constants/__tests__/languages.test.js.map +0 -1
  228. package/dist/scripts/create-project.d.ts +0 -16
  229. package/dist/scripts/create-project.d.ts.map +0 -1
  230. package/dist/scripts/create-project.js +0 -334
  231. package/dist/scripts/create-project.js.map +0 -1
  232. package/dist/scripts/list-projects.d.ts +0 -7
  233. package/dist/scripts/list-projects.d.ts.map +0 -1
  234. package/dist/scripts/list-projects.js +0 -88
  235. package/dist/scripts/list-projects.js.map +0 -1
  236. package/dist/scripts/template/__tests__/renderer.test.d.ts +0 -2
  237. package/dist/scripts/template/__tests__/renderer.test.d.ts.map +0 -1
  238. package/dist/scripts/template/__tests__/renderer.test.js +0 -165
  239. package/dist/scripts/template/__tests__/renderer.test.js.map +0 -1
  240. package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts +0 -5
  241. package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts.map +0 -1
  242. package/dist/scripts/utils/__tests__/aidlc-parser.test.js +0 -315
  243. package/dist/scripts/utils/__tests__/aidlc-parser.test.js.map +0 -1
  244. package/dist/scripts/utils/__tests__/business-days.test.d.ts +0 -5
  245. package/dist/scripts/utils/__tests__/business-days.test.d.ts.map +0 -1
  246. package/dist/scripts/utils/__tests__/business-days.test.js +0 -171
  247. package/dist/scripts/utils/__tests__/business-days.test.js.map +0 -1
  248. package/dist/scripts/utils/__tests__/config-loader.test.d.ts +0 -5
  249. package/dist/scripts/utils/__tests__/config-loader.test.d.ts.map +0 -1
  250. package/dist/scripts/utils/__tests__/config-loader.test.js +0 -201
  251. package/dist/scripts/utils/__tests__/config-loader.test.js.map +0 -1
  252. package/dist/scripts/utils/__tests__/config-validator.test.d.ts +0 -5
  253. package/dist/scripts/utils/__tests__/config-validator.test.d.ts.map +0 -1
  254. package/dist/scripts/utils/__tests__/config-validator.test.js +0 -394
  255. package/dist/scripts/utils/__tests__/config-validator.test.js.map +0 -1
  256. package/dist/scripts/utils/__tests__/env-config.test.d.ts +0 -5
  257. package/dist/scripts/utils/__tests__/env-config.test.d.ts.map +0 -1
  258. package/dist/scripts/utils/__tests__/env-config.test.js +0 -218
  259. package/dist/scripts/utils/__tests__/env-config.test.js.map +0 -1
  260. package/dist/scripts/utils/__tests__/feature-name-validator.test.d.ts +0 -5
  261. package/dist/scripts/utils/__tests__/feature-name-validator.test.d.ts.map +0 -1
  262. package/dist/scripts/utils/__tests__/feature-name-validator.test.js +0 -106
  263. package/dist/scripts/utils/__tests__/feature-name-validator.test.js.map +0 -1
  264. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts +0 -5
  265. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts.map +0 -1
  266. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js +0 -202
  267. package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js.map +0 -1
  268. package/dist/scripts/utils/__tests__/spec-updater.test.d.ts +0 -5
  269. package/dist/scripts/utils/__tests__/spec-updater.test.d.ts.map +0 -1
  270. package/dist/scripts/utils/__tests__/spec-updater.test.js +0 -158
  271. package/dist/scripts/utils/__tests__/spec-updater.test.js.map +0 -1
  272. package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts +0 -5
  273. package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts.map +0 -1
  274. package/dist/scripts/utils/__tests__/tasks-converter.test.js +0 -500
  275. package/dist/scripts/utils/__tests__/tasks-converter.test.js.map +0 -1
  276. package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts +0 -5
  277. package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts.map +0 -1
  278. package/dist/scripts/utils/__tests__/tasks-format-validator.test.js +0 -314
  279. package/dist/scripts/utils/__tests__/tasks-format-validator.test.js.map +0 -1
  280. package/dist/scripts/utils/__tests__/test-runner.test.d.ts +0 -5
  281. package/dist/scripts/utils/__tests__/test-runner.test.d.ts.map +0 -1
  282. package/dist/scripts/utils/__tests__/test-runner.test.js +0 -64
  283. package/dist/scripts/utils/__tests__/test-runner.test.js.map +0 -1
  284. package/dist/src/__tests__/cli.test.d.ts +0 -5
  285. package/dist/src/__tests__/cli.test.d.ts.map +0 -1
  286. package/dist/src/__tests__/cli.test.js +0 -58
  287. package/dist/src/__tests__/cli.test.js.map +0 -1
  288. package/dist/src/__tests__/integration/internationalization.test.d.ts +0 -8
  289. package/dist/src/__tests__/integration/internationalization.test.d.ts.map +0 -1
  290. package/dist/src/__tests__/integration/internationalization.test.js +0 -333
  291. package/dist/src/__tests__/integration/internationalization.test.js.map +0 -1
  292. package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +0 -5
  293. package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +0 -1
  294. package/dist/src/__tests__/integration/setup/claude-agent.test.js +0 -122
  295. package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +0 -1
  296. package/dist/src/__tests__/integration/setup/claude.test.d.ts +0 -5
  297. package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +0 -1
  298. package/dist/src/__tests__/integration/setup/claude.test.js +0 -193
  299. package/dist/src/__tests__/integration/setup/claude.test.js.map +0 -1
  300. package/dist/src/__tests__/integration/setup/cursor.test.d.ts +0 -5
  301. package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +0 -1
  302. package/dist/src/__tests__/integration/setup/cursor.test.js +0 -166
  303. package/dist/src/__tests__/integration/setup/cursor.test.js.map +0 -1
  304. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +0 -32
  305. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +0 -1
  306. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +0 -72
  307. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +0 -1
  308. package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +0 -38
  309. package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +0 -1
  310. package/dist/src/__tests__/integration/setup/helpers/test-project.js +0 -83
  311. package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +0 -1
  312. package/dist/src/__tests__/integration/setup/init.test.d.ts +0 -5
  313. package/dist/src/__tests__/integration/setup/init.test.d.ts.map +0 -1
  314. package/dist/src/__tests__/integration/setup/init.test.js +0 -352
  315. package/dist/src/__tests__/integration/setup/init.test.js.map +0 -1
  316. package/dist/src/__tests__/integration/setup/validation.test.d.ts +0 -5
  317. package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +0 -1
  318. package/dist/src/__tests__/integration/setup/validation.test.js +0 -301
  319. package/dist/src/__tests__/integration/setup/validation.test.js.map +0 -1
  320. package/scripts/create-project.ts +0 -386
  321. package/scripts/list-projects.ts +0 -112
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Tests for TestScriptRunner
3
+ */
4
+
5
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
6
+ import { TestScriptRunner } from '../test-script-runner.js';
7
+ import * as child_process from 'child_process';
8
+
9
+ vi.mock('child_process');
10
+
11
+ // カスタムエラー型の定義
12
+ interface ExecError extends Error {
13
+ status?: number;
14
+ code?: string;
15
+ stderr?: Buffer;
16
+ }
17
+
18
+ describe('TestScriptRunner', () => {
19
+ let runner: TestScriptRunner;
20
+
21
+ beforeEach(() => {
22
+ vi.clearAllMocks();
23
+ runner = new TestScriptRunner();
24
+ vi.useFakeTimers();
25
+ });
26
+
27
+ afterEach(() => {
28
+ vi.restoreAllMocks();
29
+ vi.useRealTimers();
30
+ });
31
+
32
+ describe('正常ケース', () => {
33
+ it('テストスクリプト実行が成功(終了コード0)', async () => {
34
+ vi.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('Test passed'));
35
+
36
+ const startTime = Date.now();
37
+ vi.setSystemTime(startTime);
38
+
39
+ const result = await runner.runTestScript('my-project', 'e2e');
40
+
41
+ expect(result.success).toBe(true);
42
+ expect(result.exitCode).toBe(0);
43
+ expect(result.executionTime).toBeGreaterThanOrEqual(0);
44
+ expect(result.outputPath).toContain('docs/michi/my-project/tests/results/e2e-');
45
+ expect(result.error).toBeUndefined();
46
+ });
47
+
48
+ it('統合テスト実行が成功', async () => {
49
+ vi.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('Integration test passed'));
50
+
51
+ const result = await runner.runTestScript('my-project', 'integration');
52
+
53
+ expect(result.success).toBe(true);
54
+ expect(result.exitCode).toBe(0);
55
+ expect(result.outputPath).toContain('integration-');
56
+ });
57
+
58
+ it('パフォーマンステスト実行が成功', async () => {
59
+ vi.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('Performance test passed'));
60
+
61
+ const result = await runner.runTestScript('my-project', 'performance');
62
+
63
+ expect(result.success).toBe(true);
64
+ expect(result.exitCode).toBe(0);
65
+ expect(result.outputPath).toContain('performance-');
66
+ });
67
+
68
+ it('実行時間を正しく計測', async () => {
69
+ const startTime = Date.now();
70
+ vi.setSystemTime(startTime);
71
+
72
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
73
+ // 5秒後に完了をシミュレート
74
+ vi.setSystemTime(startTime + 5000);
75
+ return Buffer.from('Test passed');
76
+ });
77
+
78
+ const result = await runner.runTestScript('my-project', 'e2e');
79
+
80
+ expect(result.executionTime).toBeCloseTo(5, 1);
81
+ });
82
+ });
83
+
84
+ describe('テスト失敗ケース', () => {
85
+ it('テストスクリプト実行が失敗(終了コード非0)', async () => {
86
+ const error: ExecError = new Error('Command failed');
87
+ error.status = 1;
88
+ error.stderr = Buffer.from('Test failed: assertion error');
89
+
90
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
91
+ throw error;
92
+ });
93
+
94
+ const result = await runner.runTestScript('my-project', 'e2e');
95
+
96
+ expect(result.success).toBe(false);
97
+ expect(result.exitCode).toBe(1);
98
+ expect(result.error).toContain('Test failed');
99
+ });
100
+
101
+ it('終了コード2のテスト失敗', async () => {
102
+ const error: ExecError = new Error('Command failed');
103
+ error.status = 2;
104
+
105
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
106
+ throw error;
107
+ });
108
+
109
+ const result = await runner.runTestScript('my-project', 'integration');
110
+
111
+ expect(result.success).toBe(false);
112
+ expect(result.exitCode).toBe(2);
113
+ });
114
+ });
115
+
116
+ describe('エラーハンドリング', () => {
117
+ it('スクリプト実行タイムアウトの場合はエラー', async () => {
118
+ const error: ExecError = new Error('Timeout');
119
+ error.code = 'ETIMEDOUT';
120
+
121
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
122
+ throw error;
123
+ });
124
+
125
+ const result = await runner.runTestScript('my-project', 'e2e');
126
+
127
+ expect(result.success).toBe(false);
128
+ expect(result.error).toContain('Timeout');
129
+ });
130
+
131
+ it('パーミッションエラーの場合はエラー', async () => {
132
+ const error: ExecError = new Error('Permission denied');
133
+ error.code = 'EACCES';
134
+
135
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
136
+ throw error;
137
+ });
138
+
139
+ const result = await runner.runTestScript('my-project', 'e2e');
140
+
141
+ expect(result.success).toBe(false);
142
+ expect(result.error).toContain('Permission denied');
143
+ });
144
+
145
+ it('スクリプト未存在エラーの場合はエラー', async () => {
146
+ const error: ExecError = new Error('Script not found');
147
+ error.code = 'ENOENT';
148
+
149
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
150
+ throw error;
151
+ });
152
+
153
+ const result = await runner.runTestScript('my-project', 'e2e');
154
+
155
+ expect(result.success).toBe(false);
156
+ expect(result.error).toContain('Script not found');
157
+ });
158
+ });
159
+
160
+ describe('カスタムプロジェクトルート', () => {
161
+ it('カスタムプロジェクトルートを指定できる', async () => {
162
+ const customRoot = '/custom/path';
163
+ vi.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('Test passed'));
164
+
165
+ const result = await runner.runTestScript('my-project', 'e2e', customRoot);
166
+
167
+ expect(result.success).toBe(true);
168
+ expect(child_process.execSync).toHaveBeenCalledWith(
169
+ expect.stringContaining(`${customRoot}/docs/michi/my-project/tests/scripts/run-e2e.sh`),
170
+ expect.any(Object)
171
+ );
172
+ });
173
+ });
174
+
175
+ describe('ログ出力', () => {
176
+ it('実行前にログを出力', async () => {
177
+ const consoleSpy = vi.spyOn(console, 'log');
178
+ vi.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('Test passed'));
179
+
180
+ await runner.runTestScript('my-project', 'e2e');
181
+
182
+ expect(consoleSpy).toHaveBeenCalledWith(
183
+ expect.stringContaining('🚀 テストスクリプトを実行中')
184
+ );
185
+ expect(consoleSpy).toHaveBeenCalledWith(
186
+ expect.stringContaining('テストタイプ: e2e')
187
+ );
188
+ });
189
+
190
+ it('成功時に成功メッセージを表示', async () => {
191
+ const consoleSpy = vi.spyOn(console, 'log');
192
+ vi.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('Test passed'));
193
+
194
+ await runner.runTestScript('my-project', 'e2e');
195
+
196
+ expect(consoleSpy).toHaveBeenCalledWith(
197
+ expect.stringContaining('✅ テスト実行が成功しました')
198
+ );
199
+ });
200
+
201
+ it('失敗時に失敗メッセージを表示', async () => {
202
+ const consoleSpy = vi.spyOn(console, 'log');
203
+ const error: ExecError = new Error('Command failed');
204
+ error.status = 1;
205
+
206
+ vi.spyOn(child_process, 'execSync').mockImplementation(() => {
207
+ throw error;
208
+ });
209
+
210
+ await runner.runTestScript('my-project', 'e2e');
211
+
212
+ expect(consoleSpy).toHaveBeenCalledWith(
213
+ expect.stringContaining('❌ テスト実行が失敗しました')
214
+ );
215
+ });
216
+ });
217
+ });
@@ -146,6 +146,92 @@ export const ValidationConfigSchema = z.object({
146
146
  weekendExclusion: z.boolean().default(true),
147
147
  });
148
148
 
149
+ /**
150
+ * Atlassian設定スキーマ
151
+ */
152
+ export const AtlassianConfigSchema = z.object({
153
+ url: z.string().optional(),
154
+ email: z.string().optional(),
155
+ apiToken: z.string().optional(),
156
+ });
157
+
158
+ /**
159
+ * プロジェクトメタデータスキーマ
160
+ */
161
+ export const ProjectMetaSchema = z.object({
162
+ projectId: z.string().min(1),
163
+ projectName: z.string().min(1),
164
+ language: z.enum(['ja', 'en']).optional(),
165
+ jiraProjectKey: z.string().optional(),
166
+ confluenceLabels: z.array(z.string()).optional(),
167
+ status: z.string().optional(),
168
+ team: z.array(z.string()).optional(),
169
+ stakeholders: z.array(z.string()).optional(),
170
+ repository: z.string().optional(),
171
+ description: z.string().optional(),
172
+ });
173
+
174
+ /**
175
+ * Multi-Repo リポジトリスキーマ
176
+ */
177
+ export const RepositorySchema = z.object({
178
+ name: z.string().min(1),
179
+ url: z
180
+ .string()
181
+ .url()
182
+ .regex(/^https:\/\/github\.com\/[^/]+\/[^/]+$/, {
183
+ message: 'GitHub URL must be in format: https://github.com/{owner}/{repo}',
184
+ }),
185
+ branch: z.string().default('main'),
186
+ });
187
+
188
+ /**
189
+ * Multi-Repo プロジェクトスキーマ
190
+ */
191
+ export const MultiRepoProjectSchema = z.object({
192
+ name: z
193
+ .string()
194
+ .min(1, { message: 'Project name must be at least 1 character' })
195
+ .max(100, { message: 'Project name must be at most 100 characters' })
196
+ .refine(
197
+ (name) => {
198
+ // パストラバーサル対策: '/', '\' 禁止
199
+ if (name.includes('/') || name.includes('\\')) {
200
+ return false;
201
+ }
202
+ // 相対パス対策: '.', '..' 禁止
203
+ if (name === '.' || name === '..') {
204
+ return false;
205
+ }
206
+ // 制御文字対策: \x00-\x1F, \x7F 禁止
207
+ // eslint-disable-next-line no-control-regex
208
+ const controlCharRegex = /[\x00-\x1F\x7F]/;
209
+ if (controlCharRegex.test(name)) {
210
+ return false;
211
+ }
212
+ return true;
213
+ },
214
+ {
215
+ message:
216
+ 'Project name must not contain path traversal characters (/, \\), relative path components (., ..), or control characters',
217
+ },
218
+ ),
219
+ jiraKey: z
220
+ .string()
221
+ .min(1)
222
+ .regex(/^[A-Z]{2,10}$/, {
223
+ message: 'JIRA key must be 2-10 uppercase letters',
224
+ }),
225
+ confluenceSpace: z.string().min(1, {
226
+ message: 'Confluence space must be a non-empty string',
227
+ }),
228
+ createdAt: z.string().datetime({
229
+ offset: true,
230
+ message: 'createdAt must be in ISO 8601 format',
231
+ }),
232
+ repositories: z.array(RepositorySchema).default([]),
233
+ });
234
+
149
235
  /**
150
236
  * 全体設定スキーマ
151
237
  */
@@ -154,6 +240,9 @@ export const AppConfigSchema = z.object({
154
240
  jira: JiraConfigSchema.optional(),
155
241
  workflow: WorkflowConfigSchema.optional(),
156
242
  validation: ValidationConfigSchema.optional(),
243
+ atlassian: AtlassianConfigSchema.optional(),
244
+ project: ProjectMetaSchema.optional(),
245
+ multiRepoProjects: z.array(MultiRepoProjectSchema).default([]),
157
246
  });
158
247
 
159
248
  /**
@@ -177,4 +266,19 @@ export type JiraStatusMapping = z.infer<typeof JiraStatusMappingSchema>;
177
266
  export type JiraConfig = z.infer<typeof JiraConfigSchema>;
178
267
  export type WorkflowConfig = z.infer<typeof WorkflowConfigSchema>;
179
268
  export type ValidationConfig = z.infer<typeof ValidationConfigSchema>;
269
+ export type AtlassianConfig = z.infer<typeof AtlassianConfigSchema>;
270
+ export type ProjectMeta = z.infer<typeof ProjectMetaSchema>;
271
+ export type Repository = z.infer<typeof RepositorySchema>;
272
+ export type MultiRepoProject = z.infer<typeof MultiRepoProjectSchema>;
180
273
  export type AppConfig = z.infer<typeof AppConfigSchema>;
274
+
275
+ /**
276
+ * 設定の読み込み元
277
+ */
278
+ export type ConfigSource =
279
+ | 'default' // default-config.json
280
+ | 'global-env' // ~/.michi/.env
281
+ | 'global-config' // ~/.michi/config.json
282
+ | 'project-meta' // .kiro/project.json
283
+ | 'project-config' // .michi/config.json
284
+ | 'project-env'; // .env
@@ -17,6 +17,20 @@ import { updateSpecJsonAfterConfluenceSync, loadSpecJson } from './utils/spec-up
17
17
  // 環境変数読み込み
18
18
  config();
19
19
 
20
+ /**
21
+ * セキュリティ: CQLクエリ文字列のエスケープ
22
+ * CQLインジェクション対策: バックスラッシュと引用符を適切にエスケープ
23
+ *
24
+ * @param str - エスケープする文字列
25
+ * @returns エスケープされた文字列
26
+ */
27
+ function escapeCQL(str: string): string {
28
+ return str
29
+ .replace(/\\/g, '\\\\') // バックスラッシュを先にエスケープ(重要: 最初に実行)
30
+ .replace(/"/g, '\\"') // ダブルクォート
31
+ .replace(/'/g, '\\\''); // シングルクォート
32
+ }
33
+
20
34
  /**
21
35
  * Confluence APIページレスポンス
22
36
  */
@@ -133,8 +147,8 @@ class ConfluenceClient {
133
147
  // 親ページIDが指定されている場合、CQLクエリを使用して親ページの子ページのみを検索
134
148
  if (parentId) {
135
149
  // CQLクエリ: スペース、タイトル、親ページIDで検索
136
- // タイトル内の特殊文字をエスケープ
137
- const escapedTitle = title.replace(/"/g, '\\"');
150
+ // セキュリティ: CQLインジェクション対策 - タイトルを適切にエスケープ
151
+ const escapedTitle = escapeCQL(title);
138
152
  // ancestorの代わりにparentを使用(Confluence CQLの正しい構文)
139
153
  const cql = `space = ${spaceKey} AND title = "${escapedTitle}" AND parent = ${parentId}`;
140
154
  console.log(` CQL Query: ${cql}`);
@@ -0,0 +1,258 @@
1
+ /**
2
+ * GitHub Actions Client
3
+ * GitHub Actions APIへのアクセスを抽象化し、Workflow Runsの取得とレート制限対策を提供
4
+ */
5
+
6
+ import { Octokit } from '@octokit/rest';
7
+
8
+ /**
9
+ * GitHub Workflow Run情報
10
+ */
11
+ export interface IGitHubWorkflowRun {
12
+ id: number;
13
+ name: string;
14
+ head_branch: string;
15
+ status: 'completed' | 'in_progress' | 'queued';
16
+ conclusion: 'success' | 'failure' | 'cancelled' | 'skipped' | null;
17
+ created_at: string;
18
+ updated_at: string;
19
+ html_url: string;
20
+ }
21
+
22
+ /**
23
+ * リポジトリのCI結果
24
+ */
25
+ export interface IRepositoryCIStatus {
26
+ name: string;
27
+ url: string;
28
+ branch: string;
29
+ status: 'success' | 'failure' | 'running' | 'unknown';
30
+ testStatus: 'passed' | 'failed' | 'skipped' | 'unknown';
31
+ coverage?: number;
32
+ lastExecutionTime: Date;
33
+ failureDetails?: string;
34
+ }
35
+
36
+ /**
37
+ * GitHub APIエラー
38
+ */
39
+ export type GitHubAPIError =
40
+ | { type: 'RATE_LIMIT_EXCEEDED'; retryAfter: number }
41
+ | { type: 'NOT_FOUND'; message: string }
42
+ | { type: 'UNAUTHORIZED'; message: string }
43
+ | { type: 'SERVER_ERROR'; message: string; statusCode: number };
44
+
45
+ /**
46
+ * Octokit APIから返されるエラーオブジェクトの型
47
+ */
48
+ interface OctokitError extends Error {
49
+ status?: number;
50
+ response?: {
51
+ url?: string;
52
+ status?: number;
53
+ headers?: Record<string, string>;
54
+ data?: unknown;
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Result型
60
+ */
61
+ export type Result<T, E> =
62
+ | { success: true; data: T }
63
+ | { success: false; error: E };
64
+
65
+ /**
66
+ * GitHub Workflow Runを解析してCI結果に変換
67
+ * @param run GitHub Workflow Run情報
68
+ * @returns CI結果
69
+ */
70
+ export function parseGitHubWorkflowRun(
71
+ run: IGitHubWorkflowRun
72
+ ): Omit<IRepositoryCIStatus, 'name' | 'url' | 'branch'> {
73
+ // statusマッピング
74
+ let status: 'success' | 'failure' | 'running' | 'unknown';
75
+ let testStatus: 'passed' | 'failed' | 'skipped' | 'unknown';
76
+
77
+ if (run.status === 'completed') {
78
+ if (run.conclusion === 'success') {
79
+ status = 'success';
80
+ testStatus = 'passed';
81
+ } else if (run.conclusion === 'failure') {
82
+ status = 'failure';
83
+ testStatus = 'failed';
84
+ } else if (run.conclusion === 'cancelled') {
85
+ status = 'unknown';
86
+ testStatus = 'skipped';
87
+ } else if (run.conclusion === 'skipped') {
88
+ status = 'unknown';
89
+ testStatus = 'skipped';
90
+ } else {
91
+ status = 'unknown';
92
+ testStatus = 'unknown';
93
+ }
94
+ } else if (run.status === 'in_progress' || run.status === 'queued') {
95
+ status = 'running';
96
+ testStatus = 'unknown';
97
+ } else {
98
+ status = 'unknown';
99
+ testStatus = 'unknown';
100
+ }
101
+
102
+ // 日時変換
103
+ const lastExecutionTime = new Date(run.updated_at);
104
+
105
+ // 失敗詳細
106
+ const failureDetails =
107
+ status === 'failure' ? run.html_url : undefined;
108
+
109
+ return {
110
+ status,
111
+ testStatus,
112
+ lastExecutionTime,
113
+ failureDetails,
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Exponential Backoffで再試行
119
+ * @param fn 実行する関数
120
+ * @param maxRetries 最大再試行回数
121
+ * @returns 関数の実行結果
122
+ */
123
+ async function exponentialBackoff<T>(
124
+ fn: () => Promise<T>,
125
+ maxRetries: number = 3
126
+ ): Promise<T> {
127
+ let lastError: OctokitError | undefined;
128
+
129
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
130
+ try {
131
+ return await fn();
132
+ } catch (error) {
133
+ const octokitError = error as OctokitError;
134
+ lastError = octokitError;
135
+
136
+ // レート制限エラーでない場合は即座にスロー
137
+ if (octokitError.status !== 403 || !octokitError.response?.headers) {
138
+ throw octokitError;
139
+ }
140
+
141
+ // 最後の試行の場合はスロー
142
+ if (attempt === maxRetries - 1) {
143
+ throw octokitError;
144
+ }
145
+
146
+ // Exponential Backoff: 1秒、2秒、4秒
147
+ const waitTime = Math.pow(2, attempt) * 1000;
148
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
149
+ }
150
+ }
151
+
152
+ throw lastError ?? new Error('Unexpected error in exponentialBackoff');
153
+ }
154
+
155
+ /**
156
+ * GitHub Actions Client
157
+ */
158
+ export class GitHubActionsClient {
159
+ private octokit: Octokit;
160
+
161
+ constructor() {
162
+ const token = process.env.GITHUB_TOKEN;
163
+ if (!token) {
164
+ throw new Error('GITHUB_TOKENが設定されていません');
165
+ }
166
+
167
+ this.octokit = new Octokit({
168
+ auth: token,
169
+ });
170
+ }
171
+
172
+ /**
173
+ * リポジトリの最新Workflow Runを取得
174
+ * @param owner リポジトリオーナー
175
+ * @param repo リポジトリ名
176
+ * @param branch ブランチ名
177
+ * @returns Workflow Run情報(成功/失敗)
178
+ */
179
+ async getLatestWorkflowRun(
180
+ owner: string,
181
+ repo: string,
182
+ branch: string
183
+ ): Promise<Result<IGitHubWorkflowRun, GitHubAPIError>> {
184
+ try {
185
+ const response = await exponentialBackoff(async () => {
186
+ return await this.octokit.actions.listWorkflowRunsForRepo({
187
+ owner,
188
+ repo,
189
+ branch,
190
+ status: 'completed',
191
+ per_page: 1,
192
+ });
193
+ });
194
+
195
+ if (
196
+ !response.data.workflow_runs ||
197
+ response.data.workflow_runs.length === 0
198
+ ) {
199
+ return {
200
+ success: false,
201
+ error: {
202
+ type: 'NOT_FOUND',
203
+ message: `リポジトリ ${owner}/${repo} のWorkflow Runが見つかりません`,
204
+ },
205
+ };
206
+ }
207
+
208
+ const run = response.data.workflow_runs[0] as IGitHubWorkflowRun;
209
+ return {
210
+ success: true,
211
+ data: run,
212
+ };
213
+ } catch (error) {
214
+ // エラーハンドリング
215
+ const octokitError = error as OctokitError;
216
+ if (octokitError.status === 404) {
217
+ return {
218
+ success: false,
219
+ error: {
220
+ type: 'NOT_FOUND',
221
+ message: octokitError.message || 'リポジトリが見つかりません',
222
+ },
223
+ };
224
+ } else if (octokitError.status === 403) {
225
+ // レート制限
226
+ const resetTime = octokitError.response?.headers?.['x-ratelimit-reset'];
227
+ const retryAfter = resetTime
228
+ ? parseInt(resetTime, 10) - Math.floor(Date.now() / 1000)
229
+ : 3600;
230
+
231
+ return {
232
+ success: false,
233
+ error: {
234
+ type: 'RATE_LIMIT_EXCEEDED',
235
+ retryAfter: Math.max(retryAfter, 0),
236
+ },
237
+ };
238
+ } else if (octokitError.status === 401) {
239
+ return {
240
+ success: false,
241
+ error: {
242
+ type: 'UNAUTHORIZED',
243
+ message: octokitError.message || '認証エラー',
244
+ },
245
+ };
246
+ } else {
247
+ return {
248
+ success: false,
249
+ error: {
250
+ type: 'SERVER_ERROR',
251
+ message: octokitError.message || 'サーバーエラー',
252
+ statusCode: octokitError.status || 500,
253
+ },
254
+ };
255
+ }
256
+ }
257
+ }
258
+ }