@sk8metal/michi-cli 0.0.7 → 0.0.9

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 (175) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +205 -11
  3. package/dist/scripts/__tests__/create-project.test.d.ts +2 -0
  4. package/dist/scripts/__tests__/create-project.test.d.ts.map +1 -0
  5. package/dist/scripts/__tests__/create-project.test.js +247 -0
  6. package/dist/scripts/__tests__/create-project.test.js.map +1 -0
  7. package/dist/scripts/__tests__/multi-project-estimate.test.d.ts +2 -0
  8. package/dist/scripts/__tests__/multi-project-estimate.test.d.ts.map +1 -0
  9. package/dist/scripts/__tests__/multi-project-estimate.test.js +119 -0
  10. package/dist/scripts/__tests__/multi-project-estimate.test.js.map +1 -0
  11. package/dist/scripts/__tests__/setup-existing-project.test.d.ts +2 -0
  12. package/dist/scripts/__tests__/setup-existing-project.test.d.ts.map +1 -0
  13. package/dist/scripts/__tests__/setup-existing-project.test.js +129 -0
  14. package/dist/scripts/__tests__/setup-existing-project.test.js.map +1 -0
  15. package/dist/scripts/__tests__/setup-interactive.test.d.ts +2 -0
  16. package/dist/scripts/__tests__/setup-interactive.test.d.ts.map +1 -0
  17. package/dist/scripts/__tests__/setup-interactive.test.js +160 -0
  18. package/dist/scripts/__tests__/setup-interactive.test.js.map +1 -0
  19. package/dist/scripts/config/default-config.json +57 -0
  20. package/dist/scripts/confluence-sync.d.ts +4 -0
  21. package/dist/scripts/confluence-sync.d.ts.map +1 -1
  22. package/dist/scripts/confluence-sync.js +12 -23
  23. package/dist/scripts/confluence-sync.js.map +1 -1
  24. package/dist/scripts/constants/__tests__/environments.test.d.ts +2 -0
  25. package/dist/scripts/constants/__tests__/environments.test.d.ts.map +1 -0
  26. package/dist/scripts/constants/__tests__/environments.test.js +91 -0
  27. package/dist/scripts/constants/__tests__/environments.test.js.map +1 -0
  28. package/dist/scripts/constants/__tests__/languages.test.d.ts +2 -0
  29. package/dist/scripts/constants/__tests__/languages.test.d.ts.map +1 -0
  30. package/dist/scripts/constants/__tests__/languages.test.js +82 -0
  31. package/dist/scripts/constants/__tests__/languages.test.js.map +1 -0
  32. package/dist/scripts/constants/environments.d.ts +33 -0
  33. package/dist/scripts/constants/environments.d.ts.map +1 -0
  34. package/dist/scripts/constants/environments.js +49 -0
  35. package/dist/scripts/constants/environments.js.map +1 -0
  36. package/dist/scripts/constants/languages.d.ts +23 -0
  37. package/dist/scripts/constants/languages.d.ts.map +1 -0
  38. package/dist/scripts/constants/languages.js +53 -0
  39. package/dist/scripts/constants/languages.js.map +1 -0
  40. package/dist/scripts/create-project.d.ts +4 -0
  41. package/dist/scripts/create-project.d.ts.map +1 -1
  42. package/dist/scripts/create-project.js +227 -137
  43. package/dist/scripts/create-project.js.map +1 -1
  44. package/dist/scripts/jira-sync.d.ts.map +1 -1
  45. package/dist/scripts/jira-sync.js +15 -0
  46. package/dist/scripts/jira-sync.js.map +1 -1
  47. package/dist/scripts/list-projects.d.ts.map +1 -1
  48. package/dist/scripts/list-projects.js +42 -15
  49. package/dist/scripts/list-projects.js.map +1 -1
  50. package/dist/scripts/multi-project-estimate.d.ts.map +1 -1
  51. package/dist/scripts/multi-project-estimate.js +56 -21
  52. package/dist/scripts/multi-project-estimate.js.map +1 -1
  53. package/dist/scripts/resource-dashboard.d.ts.map +1 -1
  54. package/dist/scripts/resource-dashboard.js +74 -17
  55. package/dist/scripts/resource-dashboard.js.map +1 -1
  56. package/dist/scripts/setup-existing-project.d.ts +3 -1
  57. package/dist/scripts/setup-existing-project.d.ts.map +1 -1
  58. package/dist/scripts/setup-existing-project.js +306 -217
  59. package/dist/scripts/setup-existing-project.js.map +1 -1
  60. package/dist/scripts/setup-interactive.d.ts +10 -0
  61. package/dist/scripts/setup-interactive.d.ts.map +1 -0
  62. package/dist/scripts/setup-interactive.js +413 -0
  63. package/dist/scripts/setup-interactive.js.map +1 -0
  64. package/dist/scripts/template/__tests__/renderer.test.d.ts +2 -0
  65. package/dist/scripts/template/__tests__/renderer.test.d.ts.map +1 -0
  66. package/dist/scripts/template/__tests__/renderer.test.js +165 -0
  67. package/dist/scripts/template/__tests__/renderer.test.js.map +1 -0
  68. package/dist/scripts/template/renderer.d.ts +70 -0
  69. package/dist/scripts/template/renderer.d.ts.map +1 -0
  70. package/dist/scripts/template/renderer.js +99 -0
  71. package/dist/scripts/template/renderer.js.map +1 -0
  72. package/dist/scripts/utils/__tests__/config-validator.test.js +5 -0
  73. package/dist/scripts/utils/__tests__/config-validator.test.js.map +1 -1
  74. package/dist/scripts/utils/__tests__/spec-updater.test.d.ts +5 -0
  75. package/dist/scripts/utils/__tests__/spec-updater.test.d.ts.map +1 -0
  76. package/dist/scripts/utils/__tests__/spec-updater.test.js +158 -0
  77. package/dist/scripts/utils/__tests__/spec-updater.test.js.map +1 -0
  78. package/dist/scripts/utils/confluence-hierarchy.d.ts +2 -1
  79. package/dist/scripts/utils/confluence-hierarchy.d.ts.map +1 -1
  80. package/dist/scripts/utils/confluence-hierarchy.js +5 -0
  81. package/dist/scripts/utils/confluence-hierarchy.js.map +1 -1
  82. package/dist/scripts/utils/project-finder.d.ts +30 -0
  83. package/dist/scripts/utils/project-finder.d.ts.map +1 -0
  84. package/dist/scripts/utils/project-finder.js +147 -0
  85. package/dist/scripts/utils/project-finder.js.map +1 -0
  86. package/dist/scripts/utils/spec-updater.d.ts +72 -0
  87. package/dist/scripts/utils/spec-updater.d.ts.map +1 -0
  88. package/dist/scripts/utils/spec-updater.js +141 -0
  89. package/dist/scripts/utils/spec-updater.js.map +1 -0
  90. package/dist/scripts/utils/template-finder.d.ts +37 -0
  91. package/dist/scripts/utils/template-finder.d.ts.map +1 -0
  92. package/dist/scripts/utils/template-finder.js +63 -0
  93. package/dist/scripts/utils/template-finder.js.map +1 -0
  94. package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +5 -0
  95. package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +1 -0
  96. package/dist/src/__tests__/integration/setup/claude-agent.test.js +125 -0
  97. package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +1 -0
  98. package/dist/src/__tests__/integration/setup/claude.test.d.ts +5 -0
  99. package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +1 -0
  100. package/dist/src/__tests__/integration/setup/claude.test.js +111 -0
  101. package/dist/src/__tests__/integration/setup/claude.test.js.map +1 -0
  102. package/dist/src/__tests__/integration/setup/cursor.test.d.ts +5 -0
  103. package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +1 -0
  104. package/dist/src/__tests__/integration/setup/cursor.test.js +162 -0
  105. package/dist/src/__tests__/integration/setup/cursor.test.js.map +1 -0
  106. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +32 -0
  107. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +1 -0
  108. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +72 -0
  109. package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +1 -0
  110. package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +38 -0
  111. package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +1 -0
  112. package/dist/src/__tests__/integration/setup/helpers/test-project.js +83 -0
  113. package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +1 -0
  114. package/dist/src/__tests__/integration/setup/validation.test.d.ts +5 -0
  115. package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +1 -0
  116. package/dist/src/__tests__/integration/setup/validation.test.js +318 -0
  117. package/dist/src/__tests__/integration/setup/validation.test.js.map +1 -0
  118. package/dist/src/cli.d.ts.map +1 -1
  119. package/dist/src/cli.js +20 -0
  120. package/dist/src/cli.js.map +1 -1
  121. package/dist/src/commands/setup-existing.d.ts +22 -0
  122. package/dist/src/commands/setup-existing.d.ts.map +1 -0
  123. package/dist/src/commands/setup-existing.js +408 -0
  124. package/dist/src/commands/setup-existing.js.map +1 -0
  125. package/dist/vitest.config.d.ts.map +1 -1
  126. package/dist/vitest.config.js +9 -6
  127. package/dist/vitest.config.js.map +1 -1
  128. package/docs/README.md +2 -2
  129. package/docs/contributing/development.md +37 -0
  130. package/docs/getting-started/{new-project-setup.md → new-repository-setup.md} +165 -38
  131. package/docs/getting-started/quick-start.md +57 -6
  132. package/docs/getting-started/setup.md +551 -180
  133. package/docs/guides/customization.md +4 -4
  134. package/docs/guides/multi-project.md +12 -9
  135. package/docs/reference/quick-reference.md +27 -18
  136. package/docs/testing/integration-tests.md +297 -0
  137. package/docs/testing-strategy.md +87 -0
  138. package/package.json +23 -6
  139. package/scripts/__tests__/create-project.test.ts +292 -0
  140. package/scripts/__tests__/multi-project-estimate.test.ts +145 -0
  141. package/scripts/__tests__/setup-existing-project.test.ts +147 -0
  142. package/scripts/__tests__/setup-interactive.test.ts +199 -0
  143. package/scripts/confluence-sync.ts +17 -29
  144. package/scripts/constants/__tests__/environments.test.ts +110 -0
  145. package/scripts/constants/__tests__/languages.test.ts +100 -0
  146. package/scripts/constants/environments.ts +61 -0
  147. package/scripts/constants/languages.ts +70 -0
  148. package/scripts/copy-static-assets.js +50 -0
  149. package/scripts/create-project.ts +251 -158
  150. package/scripts/jira-sync.ts +16 -1
  151. package/scripts/list-projects.ts +51 -24
  152. package/scripts/multi-project-estimate.ts +58 -22
  153. package/scripts/resource-dashboard.ts +91 -26
  154. package/scripts/setup-existing-project.ts +350 -230
  155. package/scripts/setup-existing.sh +159 -25
  156. package/scripts/setup-interactive.ts +565 -0
  157. package/scripts/template/__tests__/renderer.test.ts +207 -0
  158. package/scripts/template/renderer.ts +133 -0
  159. package/scripts/utils/__tests__/config-validator.test.ts +6 -0
  160. package/scripts/utils/__tests__/spec-updater.test.ts +220 -0
  161. package/scripts/utils/confluence-hierarchy.ts +7 -1
  162. package/scripts/utils/project-finder.ts +184 -0
  163. package/scripts/utils/spec-updater.ts +212 -0
  164. package/scripts/utils/template-finder.ts +75 -0
  165. package/templates/claude/commands/michi/confluence-sync.md +38 -0
  166. package/templates/claude/commands/michi/project-switch.md +36 -0
  167. package/templates/claude/rules/atlassian-integration.md +35 -0
  168. package/templates/claude/rules/michi-core.md +54 -0
  169. package/templates/claude-agent/README.md +25 -0
  170. package/templates/cursor/commands/michi/confluence-sync.md +76 -0
  171. package/templates/cursor/commands/michi/project-switch.md +69 -0
  172. package/templates/cursor/rules/atlassian-mcp.mdc +188 -0
  173. package/templates/cursor/rules/github-ssot.mdc +151 -0
  174. package/templates/cursor/rules/multi-project.mdc +81 -0
  175. package/scripts/setup-env.sh +0 -52
@@ -7,11 +7,21 @@
7
7
  * npx tsx /path/to/michi/scripts/setup-existing-project.ts \
8
8
  * --michi-path /path/to/michi \
9
9
  * --project-name "既存プロジェクト" \
10
- * --jira-key "EXIST"
10
+ * --jira-key "EXIST" \
11
+ * --environment cursor \
12
+ * --lang ja
11
13
  */
12
- import { cpSync, existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
13
- import { resolve, join, basename } from 'path';
14
+ import { cpSync, existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from 'fs';
15
+ import { resolve, join, basename, dirname } from 'path';
16
+ import { fileURLToPath } from 'url';
14
17
  import { execSync } from 'child_process';
18
+ import { findRepositoryRoot } from './utils/project-finder.js';
19
+ import { getEnvironmentConfig, isSupportedEnvironment } from './constants/environments.js';
20
+ import { isSupportedLanguage } from './constants/languages.js';
21
+ import { createTemplateContext, renderTemplate } from './template/renderer.js';
22
+ // ES module で __dirname を取得
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = dirname(__filename);
15
25
  function parseArgs() {
16
26
  const args = process.argv.slice(2);
17
27
  const config = {};
@@ -28,20 +38,69 @@ function parseArgs() {
28
38
  case 'jira-key':
29
39
  config.jiraKey = value;
30
40
  break;
41
+ case 'environment':
42
+ config.environment = value;
43
+ break;
44
+ case 'lang':
45
+ config.langCode = value;
46
+ break;
31
47
  }
32
48
  }
33
49
  // デフォルト値
34
50
  if (!config.michiPath) {
35
51
  config.michiPath = resolve(__dirname, '..');
36
52
  }
53
+ if (!config.environment) {
54
+ config.environment = 'claude';
55
+ }
56
+ if (!config.langCode) {
57
+ config.langCode = 'ja';
58
+ }
37
59
  // 必須フィールドチェック
38
60
  if (!config.projectName || !config.jiraKey) {
39
61
  console.error('Missing required parameters');
40
- console.error('Usage: tsx setup-existing-project.ts --project-name <name> --jira-key <key> [--michi-path <path>]');
62
+ console.error('Usage: tsx setup-existing-project.ts --project-name <name> --jira-key <key> [--michi-path <path>] [--environment <env>] [--lang <code>]');
63
+ process.exit(1);
64
+ }
65
+ // 環境バリデーション
66
+ if (!isSupportedEnvironment(config.environment)) {
67
+ console.error(`Unsupported environment: ${config.environment}`);
68
+ console.error('Supported environments: claude, claude-agent, cursor');
69
+ process.exit(1);
70
+ }
71
+ // 言語バリデーション
72
+ if (!isSupportedLanguage(config.langCode)) {
73
+ console.error(`Unsupported language: ${config.langCode}`);
74
+ console.error('Supported languages: ja, en, zh-TW, zh, es, pt, de, fr, ru, it, ko, ar');
41
75
  process.exit(1);
42
76
  }
43
77
  return config;
44
78
  }
79
+ /**
80
+ * Copy and render templates recursively
81
+ *
82
+ * @param sourceDir - Source directory containing templates
83
+ * @param destDir - Destination directory for rendered files
84
+ * @param context - Template context for rendering
85
+ */
86
+ function copyAndRenderTemplates(sourceDir, destDir, context) {
87
+ const entries = readdirSync(sourceDir, { withFileTypes: true });
88
+ for (const entry of entries) {
89
+ const sourcePath = join(sourceDir, entry.name);
90
+ const destPath = join(destDir, entry.name);
91
+ if (entry.isDirectory()) {
92
+ // ディレクトリは再帰的にコピー
93
+ mkdirSync(destPath, { recursive: true });
94
+ copyAndRenderTemplates(sourcePath, destPath, context);
95
+ }
96
+ else if (entry.isFile()) {
97
+ // ファイルはレンダリングしてコピー
98
+ const content = readFileSync(sourcePath, 'utf-8');
99
+ const rendered = renderTemplate(content, context);
100
+ writeFileSync(destPath, rendered, 'utf-8');
101
+ }
102
+ }
103
+ }
45
104
  async function setupExistingProject(config) {
46
105
  const currentDir = process.cwd();
47
106
  const projectId = basename(currentDir);
@@ -49,167 +108,190 @@ async function setupExistingProject(config) {
49
108
  console.log(` プロジェクト: ${config.projectName}`);
50
109
  console.log(` ディレクトリ: ${currentDir}`);
51
110
  console.log(` Michiパス: ${config.michiPath}`);
111
+ console.log(` 環境: ${config.environment}`);
112
+ console.log(` 言語: ${config.langCode}`);
52
113
  console.log('');
53
- // Step 1: cc-sdd導入確認
54
- console.log('📦 Step 1: Checking cc-sdd installation...');
55
- if (!existsSync('.cursor/commands/kiro')) {
56
- console.log(' Installing cc-sdd...');
57
- execSync('npx cc-sdd@latest --cursor --lang ja --yes', { stdio: 'inherit' });
58
- console.log(' ✅ cc-sdd installed');
114
+ // リポジトリルートを検出
115
+ const repoRoot = findRepositoryRoot(currentDir);
116
+ // projects/{project-id}/配下にプロジェクトを作成
117
+ const projectsDir = join(repoRoot, 'projects');
118
+ const projectDir = join(projectsDir, projectId);
119
+ console.log(`📁 リポジトリルート: ${repoRoot}`);
120
+ console.log(`📁 プロジェクトディレクトリ: ${projectDir}`);
121
+ console.log('');
122
+ // projects/ディレクトリとプロジェクトディレクトリを作成
123
+ if (!existsSync(projectsDir)) {
124
+ mkdirSync(projectsDir, { recursive: true });
125
+ console.log(` ✅ Created: ${projectsDir}`);
59
126
  }
60
- else {
61
- console.log(' ✅ cc-sdd already installed');
127
+ if (!existsSync(projectDir)) {
128
+ mkdirSync(projectDir, { recursive: true });
129
+ console.log(` ✅ Created: ${projectDir}`);
62
130
  }
63
- // Step 2: .kiro ディレクトリ作成
64
- console.log('\n📁 Step 2: Creating .kiro directory structure...');
65
- mkdirSync('.kiro/settings/templates', { recursive: true });
66
- mkdirSync('.kiro/steering', { recursive: true });
67
- mkdirSync('.kiro/specs', { recursive: true });
68
- console.log(' ✅ Directory structure created');
69
- // Step 3: プロジェクトメタデータ作成
70
- console.log('\n📝 Step 3: Creating project metadata...');
71
- // GitHub URLを取得(既存リポジトリから)
72
- let repoUrl = '';
131
+ // 元の作業ディレクトリを保存
132
+ const originalCwd = process.cwd();
73
133
  try {
74
- repoUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8' }).trim();
75
- // SSH形式をHTTPS形式に変換
76
- if (repoUrl.startsWith('git@github.com:')) {
77
- repoUrl = repoUrl.replace('git@github.com:', 'https://github.com/').replace('.git', '');
134
+ // プロジェクトディレクトリに移動
135
+ process.chdir(projectDir);
136
+ // Step 1: cc-sdd導入確認
137
+ console.log('\n📦 Step 1: Checking cc-sdd installation...');
138
+ if (!existsSync('.cursor/commands/kiro')) {
139
+ console.log(' Installing cc-sdd...');
140
+ execSync('npx cc-sdd@latest --cursor --lang ja --yes', { stdio: 'inherit' });
141
+ console.log(' ✅ cc-sdd installed');
78
142
  }
79
- }
80
- catch {
81
- repoUrl = `https://github.com/org/${projectId}`;
82
- }
83
- const labels = config.labels || (() => {
84
- // プロジェクトIDからプロジェクトラベル生成
85
- const projectLabel = projectId.toLowerCase().replace(/[^a-z0-9-]/g, '');
86
- const labelSet = new Set([`project:${projectLabel}`]);
87
- // ハイフンが存在する場合のみサービスラベルを生成
88
- if (projectId.includes('-')) {
89
- const parts = projectId.split('-');
90
- const servicePart = parts[parts.length - 1];
91
- const serviceLabel = servicePart.toLowerCase().replace(/[^a-z0-9-]/g, '');
92
- // サービスラベルがプロジェクトラベルと異なる場合のみ追加
93
- if (serviceLabel !== projectLabel) {
94
- labelSet.add(`service:${serviceLabel}`);
143
+ else {
144
+ console.log(' ✅ cc-sdd already installed');
145
+ }
146
+ // Step 2: .kiro ディレクトリ作成
147
+ console.log('\n📁 Step 2: Creating .kiro directory structure...');
148
+ mkdirSync('.kiro/settings/templates', { recursive: true });
149
+ mkdirSync('.kiro/steering', { recursive: true });
150
+ mkdirSync('.kiro/specs', { recursive: true });
151
+ console.log(' ✅ Directory structure created');
152
+ // Step 3: プロジェクトメタデータ作成
153
+ console.log('\n📝 Step 3: Creating project metadata...');
154
+ // GitHub URLを取得(既存リポジトリから)
155
+ let repoUrl = '';
156
+ try {
157
+ repoUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8', cwd: repoRoot }).trim();
158
+ // SSH形式をHTTPS形式に変換
159
+ if (repoUrl.startsWith('git@github.com:')) {
160
+ repoUrl = repoUrl.replace('git@github.com:', 'https://github.com/').replace('.git', '');
95
161
  }
96
162
  }
97
- return Array.from(labelSet);
98
- })();
99
- const projectJson = {
100
- projectId,
101
- projectName: config.projectName,
102
- jiraProjectKey: config.jiraKey,
103
- confluenceLabels: labels,
104
- status: 'active',
105
- team: [],
106
- stakeholders: ['@企画', '@部長'],
107
- repository: repoUrl,
108
- description: `${config.projectName}の開発`
109
- };
110
- writeFileSync('.kiro/project.json', JSON.stringify(projectJson, null, 2));
111
- console.log(' ✅ project.json created');
112
- // Step 4: Michiから共通ルールをコピー
113
- console.log('\n📋 Step 4: Copying common rules from Michi...');
114
- const rulesToCopy = [
115
- 'multi-project.mdc',
116
- 'github-ssot.mdc',
117
- 'atlassian-mcp.mdc'
118
- ];
119
- for (const rule of rulesToCopy) {
120
- const src = join(config.michiPath, '.cursor/rules', rule);
121
- const dest = join(currentDir, '.cursor/rules', rule);
122
- if (existsSync(src)) {
123
- cpSync(src, dest);
124
- console.log(` ✅ ${rule}`);
163
+ catch {
164
+ repoUrl = `https://github.com/org/${projectId}`;
165
+ }
166
+ const labels = config.labels || (() => {
167
+ // プロジェクトIDからプロジェクトラベル生成
168
+ const projectLabel = projectId.toLowerCase().replace(/[^a-z0-9-]/g, '');
169
+ const labelSet = new Set([`project:${projectLabel}`]);
170
+ // ハイフンが存在する場合のみサービスラベルを生成
171
+ if (projectId.includes('-')) {
172
+ const parts = projectId.split('-');
173
+ const servicePart = parts[parts.length - 1];
174
+ const serviceLabel = servicePart.toLowerCase().replace(/[^a-z0-9-]/g, '');
175
+ // サービスラベルがプロジェクトラベルと異なる場合のみ追加
176
+ if (serviceLabel !== projectLabel) {
177
+ labelSet.add(`service:${serviceLabel}`);
178
+ }
179
+ }
180
+ return Array.from(labelSet);
181
+ })();
182
+ const projectJson = {
183
+ projectId,
184
+ projectName: config.projectName,
185
+ language: config.langCode,
186
+ jiraProjectKey: config.jiraKey,
187
+ confluenceLabels: labels,
188
+ status: 'active',
189
+ team: [],
190
+ stakeholders: ['@企画', '@部長'],
191
+ repository: repoUrl,
192
+ description: `${config.projectName}の開発`
193
+ };
194
+ writeFileSync('.kiro/project.json', JSON.stringify(projectJson, null, 2));
195
+ console.log(' ✅ project.json created');
196
+ // Step 4: 環境別テンプレートのコピーとレンダリング
197
+ console.log('\n📋 Step 4: Copying and rendering templates from Michi...');
198
+ const envConfig = getEnvironmentConfig(config.environment);
199
+ const templateContext = createTemplateContext(config.langCode, '.kiro', envConfig.rulesDir.startsWith('.') ? envConfig.rulesDir.substring(1, envConfig.rulesDir.indexOf('/', 1)) : envConfig.rulesDir.split('/')[0]);
200
+ // テンプレートソースディレクトリ
201
+ const templateSourceDir = join(config.michiPath, 'templates', envConfig.templateSource);
202
+ if (!existsSync(templateSourceDir)) {
203
+ console.log(` ⚠️ Template source not found: ${templateSourceDir}`);
204
+ console.log(' Skipping template copy');
125
205
  }
126
206
  else {
127
- console.log(` ⚠️ ${rule} not found in Michi`);
207
+ // rulesディレクトリのコピーとレンダリング
208
+ const rulesTemplateDir = join(templateSourceDir, 'rules');
209
+ const rulesDestDir = join(projectDir, envConfig.rulesDir);
210
+ if (existsSync(rulesTemplateDir)) {
211
+ mkdirSync(rulesDestDir, { recursive: true });
212
+ copyAndRenderTemplates(rulesTemplateDir, rulesDestDir, templateContext);
213
+ console.log(` ✅ Rules copied and rendered to ${envConfig.rulesDir}`);
214
+ }
215
+ // commandsディレクトリのコピーとレンダリング
216
+ const commandsTemplateDir = join(templateSourceDir, 'commands');
217
+ const commandsDestDir = join(projectDir, envConfig.commandsDir);
218
+ if (existsSync(commandsTemplateDir)) {
219
+ mkdirSync(commandsDestDir, { recursive: true });
220
+ copyAndRenderTemplates(commandsTemplateDir, commandsDestDir, templateContext);
221
+ console.log(` ✅ Commands copied and rendered to ${envConfig.commandsDir}`);
222
+ }
128
223
  }
129
- }
130
- // Step 5: カスタムコマンドをコピー
131
- console.log('\n🔧 Step 5: Copying custom commands...');
132
- const commandsToCopy = [
133
- 'confluence-sync.md',
134
- 'project-switch.md'
135
- ];
136
- for (const cmd of commandsToCopy) {
137
- const src = join(config.michiPath, '.cursor/commands/kiro', cmd);
138
- const dest = join(currentDir, '.cursor/commands/kiro', cmd);
139
- if (existsSync(src)) {
140
- cpSync(src, dest);
141
- console.log(` ✅ ${cmd}`);
224
+ // Step 5: Steeringテンプレートをコピー
225
+ console.log('\n📚 Step 5: Copying steering templates...');
226
+ const steeringDir = join(config.michiPath, '.kiro/steering');
227
+ if (existsSync(steeringDir)) {
228
+ cpSync(steeringDir, join(projectDir, '.kiro/steering'), { recursive: true });
229
+ console.log(' ✅ product.md, tech.md, structure.md');
142
230
  }
143
- }
144
- // Step 6: Steeringテンプレートをコピー
145
- console.log('\n📚 Step 6: Copying steering templates...');
146
- const steeringDir = join(config.michiPath, '.kiro/steering');
147
- if (existsSync(steeringDir)) {
148
- cpSync(steeringDir, '.kiro/steering', { recursive: true });
149
- console.log(' ✅ product.md, tech.md, structure.md');
150
- }
151
- // Step 7: テンプレートをコピー
152
- console.log('\n📄 Step 7: Copying spec templates...');
153
- const templatesDir = join(config.michiPath, '.kiro/settings/templates');
154
- if (existsSync(templatesDir)) {
155
- cpSync(templatesDir, '.kiro/settings/templates', { recursive: true });
156
- console.log(' ✅ requirements.md, design.md, tasks.md');
157
- }
158
- // Step 8: CLIツールのセットアップ案内
159
- console.log('\n⚙️ Step 8: Setting up Michi CLI...');
160
- console.log(' ✅ Michi CLI setup complete!');
161
- console.log('');
162
- console.log(' 📋 使用方法:');
163
- console.log(' npx @michi/cli jira:sync <feature>');
164
- console.log(' npx @michi/cli confluence:sync <feature> requirements');
165
- console.log(' npx @michi/cli phase:run <feature> tasks');
166
- console.log('');
167
- console.log(' または、グローバルインストール:');
168
- console.log(' npm install -g @michi/cli');
169
- console.log(' michi jira:sync <feature>');
170
- // Step 9: package.json と tsconfig.json をコピー
171
- console.log('\n📦 Step 9: Setting up package.json and TypeScript...');
172
- // 既存の package.json があるかチェック
173
- const hasPackageJson = existsSync('package.json');
174
- if (!hasPackageJson) {
175
- // package.json がない場合はコピー
176
- const src = join(config.michiPath, 'package.json');
177
- if (existsSync(src)) {
178
- cpSync(src, 'package.json');
179
- console.log(' ✅ package.json created');
231
+ // Step 6: テンプレートをコピー
232
+ console.log('\n📄 Step 6: Copying spec templates...');
233
+ const templatesDir = join(config.michiPath, '.kiro/settings/templates');
234
+ if (existsSync(templatesDir)) {
235
+ cpSync(templatesDir, join(projectDir, '.kiro/settings/templates'), { recursive: true });
236
+ console.log(' ✅ requirements.md, design.md, tasks.md');
180
237
  }
181
- }
182
- else {
183
- // 既存の package.json にスクリプトを追加
184
- console.log(' ℹ️ Existing package.json found');
185
- console.log(' 📝 手動で以下のスクリプトを追加してください:');
238
+ // Step 7: CLIツールのセットアップ案内
239
+ console.log('\n⚙️ Step 7: Setting up Michi CLI...');
240
+ console.log(' ✅ Michi CLI setup complete!');
186
241
  console.log('');
187
- console.log(' "scripts": {');
188
- console.log(' "jira:sync": "npx @michi/cli jira:sync",');
189
- console.log(' "confluence:sync": "npx @michi/cli confluence:sync",');
190
- console.log(' "phase:run": "npx @michi/cli phase:run",');
191
- console.log(' "validate:phase": "npx @michi/cli validate:phase",');
192
- console.log(' "preflight": "npx @michi/cli preflight",');
193
- console.log(' "project:list": "npx @michi/cli project:list",');
194
- console.log(' "project:dashboard": "npx @michi/cli project:dashboard",');
195
- console.log(' "workflow:run": "npx @michi/cli workflow:run"');
196
- console.log(' }');
242
+ console.log(' 📋 使用方法:');
243
+ console.log(' npx @sk8metal/michi-cli jira:sync <feature>');
244
+ console.log(' npx @sk8metal/michi-cli confluence:sync <feature> requirements');
245
+ console.log(' npx @sk8metal/michi-cli phase:run <feature> tasks');
197
246
  console.log('');
198
- }
199
- // tsconfig.json をコピー
200
- if (!existsSync('tsconfig.json')) {
201
- const src = join(config.michiPath, 'tsconfig.json');
202
- if (existsSync(src)) {
203
- cpSync(src, 'tsconfig.json');
204
- console.log(' ✅ tsconfig.json created');
247
+ console.log(' または、グローバルインストール:');
248
+ console.log(' npm install -g @sk8metal/michi-cli');
249
+ console.log(' michi jira:sync <feature>');
250
+ // Step 8: package.json tsconfig.json をリポジトリルートにコピー
251
+ console.log('\n📦 Step 8: Setting up package.json and TypeScript...');
252
+ // 既存の package.json があるかチェック(リポジトリルート)
253
+ const hasPackageJson = existsSync(join(repoRoot, 'package.json'));
254
+ if (!hasPackageJson) {
255
+ // package.json がない場合はリポジトリルートにコピー
256
+ const src = join(config.michiPath, 'package.json');
257
+ const dest = join(repoRoot, 'package.json');
258
+ if (existsSync(src)) {
259
+ cpSync(src, dest);
260
+ console.log(' ✅ package.json created (in repository root)');
261
+ }
205
262
  }
206
- }
207
- else {
208
- console.log(' ℹ️ Existing tsconfig.json found (kept)');
209
- }
210
- // Step 10: .env テンプレート作成
211
- console.log('\n🔐 Step 10: Creating .env template...');
212
- const envTemplate = `# Atlassian設定(MCP + REST API共通)
263
+ else {
264
+ // 既存の package.json にスクリプトを追加
265
+ console.log(' ℹ️ Existing package.json found');
266
+ console.log(' 📝 手動で以下のスクリプトを追加してください:');
267
+ console.log('');
268
+ console.log(' "scripts": {');
269
+ console.log(' "jira:sync": "npx @sk8metal/michi-cli jira:sync",');
270
+ console.log(' "confluence:sync": "npx @sk8metal/michi-cli confluence:sync",');
271
+ console.log(' "phase:run": "npx @sk8metal/michi-cli phase:run",');
272
+ console.log(' "validate:phase": "npx @sk8metal/michi-cli validate:phase",');
273
+ console.log(' "preflight": "npx @sk8metal/michi-cli preflight",');
274
+ console.log(' "project:list": "npx @sk8metal/michi-cli project:list",');
275
+ console.log(' "project:dashboard": "npx @sk8metal/michi-cli project:dashboard",');
276
+ console.log(' "workflow:run": "npx @sk8metal/michi-cli workflow:run"');
277
+ console.log(' }');
278
+ console.log('');
279
+ }
280
+ // tsconfig.json をリポジトリルートにコピー
281
+ if (!existsSync(join(repoRoot, 'tsconfig.json'))) {
282
+ const src = join(config.michiPath, 'tsconfig.json');
283
+ const dest = join(repoRoot, 'tsconfig.json');
284
+ if (existsSync(src)) {
285
+ cpSync(src, dest);
286
+ console.log(' ✅ tsconfig.json created (in repository root)');
287
+ }
288
+ }
289
+ else {
290
+ console.log(' ℹ️ Existing tsconfig.json found (kept)');
291
+ }
292
+ // Step 9: .env テンプレート作成(プロジェクトディレクトリに)
293
+ console.log('\n🔐 Step 9: Creating .env template...');
294
+ const envTemplate = `# Atlassian設定(MCP + REST API共通)
213
295
  ATLASSIAN_URL=https://your-domain.atlassian.net
214
296
  ATLASSIAN_EMAIL=your-email@company.com
215
297
  ATLASSIAN_API_TOKEN=your-token-here
@@ -227,20 +309,20 @@ CONFLUENCE_RELEASE_SPACE=RELEASE
227
309
  # JIRAプロジェクトキー
228
310
  JIRA_PROJECT_KEYS=${config.jiraKey}
229
311
  `;
230
- if (!existsSync('.env')) {
231
- writeFileSync('.env', envTemplate);
232
- console.log(' ✅ .env template created');
233
- }
234
- else {
235
- console.log(' ℹ️ .env already exists (kept)');
236
- }
237
- // Step 11: README.md を更新(オプション)
238
- console.log('\n📖 Step 11: Updating documentation...');
239
- const readmePath = 'README.md';
240
- if (existsSync(readmePath)) {
241
- const currentReadme = readFileSync(readmePath, 'utf-8');
242
- // Michiワークフロー情報を追加
243
- const workflowSection = `
312
+ if (!existsSync(join(projectDir, '.env'))) {
313
+ writeFileSync(join(projectDir, '.env'), envTemplate);
314
+ console.log(' ✅ .env template created');
315
+ }
316
+ else {
317
+ console.log(' ℹ️ .env already exists (kept)');
318
+ }
319
+ // Step 10: README.md を更新(オプション、プロジェクトディレクトリに)
320
+ console.log('\n📖 Step 10: Updating documentation...');
321
+ const readmePath = join(projectDir, 'README.md');
322
+ if (existsSync(readmePath)) {
323
+ const currentReadme = readFileSync(readmePath, 'utf-8');
324
+ // Michiワークフロー情報を追加
325
+ const workflowSection = `
244
326
 
245
327
  ## AI開発ワークフロー
246
328
 
@@ -266,64 +348,71 @@ npm run github:create-pr <branch> # PR作成
266
348
 
267
349
  詳細: [Michi Documentation](https://github.com/sk8metalme/michi)
268
350
  `;
269
- if (!currentReadme.includes('AI開発ワークフロー')) {
270
- writeFileSync(readmePath, currentReadme + workflowSection);
271
- console.log(' ✅ README.md updated');
351
+ if (!currentReadme.includes('AI開発ワークフロー')) {
352
+ writeFileSync(readmePath, currentReadme + workflowSection);
353
+ console.log(' ✅ README.md updated');
354
+ }
355
+ else {
356
+ console.log(' ℹ️ README.md already has workflow section');
357
+ }
272
358
  }
273
- else {
274
- console.log(' ℹ️ README.md already has workflow section');
359
+ // Step 11: .gitignore 更新(リポジトリルートに)
360
+ console.log('\n🚫 Step 11: Updating .gitignore...');
361
+ const gitignoreEntries = [
362
+ '# AI Development Workflow',
363
+ 'node_modules/',
364
+ '.env',
365
+ '.env.local',
366
+ 'dist/',
367
+ '*.log'
368
+ ];
369
+ const gitignorePath = join(repoRoot, '.gitignore');
370
+ let gitignore = '';
371
+ if (existsSync(gitignorePath)) {
372
+ gitignore = readFileSync(gitignorePath, 'utf-8');
275
373
  }
276
- }
277
- // Step 12: .gitignore 更新
278
- console.log('\n🚫 Step 12: Updating .gitignore...');
279
- const gitignoreEntries = [
280
- '# AI Development Workflow',
281
- 'node_modules/',
282
- '.env',
283
- '.env.local',
284
- 'dist/',
285
- '*.log'
286
- ];
287
- let gitignore = '';
288
- if (existsSync('.gitignore')) {
289
- gitignore = readFileSync('.gitignore', 'utf-8');
290
- }
291
- let updated = false;
292
- for (const entry of gitignoreEntries) {
293
- if (!gitignore.includes(entry)) {
294
- gitignore += `\n${entry}`;
295
- updated = true;
374
+ let updated = false;
375
+ for (const entry of gitignoreEntries) {
376
+ if (!gitignore.includes(entry)) {
377
+ gitignore += `\n${entry}`;
378
+ updated = true;
379
+ }
296
380
  }
381
+ if (updated) {
382
+ writeFileSync(gitignorePath, gitignore);
383
+ console.log(' ✅ .gitignore updated (in repository root)');
384
+ }
385
+ else {
386
+ console.log(' ℹ️ .gitignore already up to date');
387
+ }
388
+ // 完了メッセージ
389
+ console.log('\n');
390
+ console.log('🎉 セットアップ完了!');
391
+ console.log('');
392
+ console.log('次のステップ:');
393
+ console.log(` 1. cd ${projectDir}`);
394
+ console.log(' 2. .env ファイルを編集して認証情報を設定');
395
+ console.log(' 3. package.json が既存の場合、スクリプトを手動追加');
396
+ console.log(' 4. npm install で依存関係をインストール(リポジトリルートで実行)');
397
+ console.log(` 5. cc-sddを導入: npx cc-sdd@latest --lang ${config.langCode} --${config.environment}`);
398
+ console.log(' 6. jj commit でセットアップをコミット');
399
+ console.log(' 7. Cursor で開く: cursor .');
400
+ console.log(' 8. /kiro:spec-init <機能説明> で開発開始');
401
+ console.log('');
402
+ console.log('作成されたファイル:');
403
+ console.log(` - ${projectDir}/.kiro/project.json`);
404
+ console.log(` - ${projectDir}/${envConfig.rulesDir}/`);
405
+ console.log(` - ${projectDir}/${envConfig.commandsDir}/`);
406
+ console.log(` - ${projectDir}/.kiro/steering/ (3ファイル)`);
407
+ console.log(` - ${projectDir}/.kiro/settings/templates/ (3ファイル)`);
408
+ console.log(` - ${repoRoot}/package.json (新規の場合)`);
409
+ console.log(` - ${repoRoot}/tsconfig.json (新規の場合)`);
410
+ console.log(` - ${projectDir}/.env (テンプレート)`);
297
411
  }
298
- if (updated) {
299
- writeFileSync('.gitignore', gitignore);
300
- console.log(' ✅ .gitignore updated');
301
- }
302
- else {
303
- console.log(' ℹ️ .gitignore already up to date');
412
+ finally {
413
+ // 元の作業ディレクトリに戻る
414
+ process.chdir(originalCwd);
304
415
  }
305
- // 完了メッセージ
306
- console.log('\n');
307
- console.log('🎉 セットアップ完了!');
308
- console.log('');
309
- console.log('次のステップ:');
310
- console.log(' 1. .env ファイルを編集して認証情報を設定');
311
- console.log(' 2. package.json が既存の場合、スクリプトを手動追加');
312
- console.log(' 3. npm install で依存関係をインストール');
313
- console.log(' 4. jj commit でセットアップをコミット');
314
- console.log(' 5. Cursor で開く: cursor .');
315
- console.log(' 6. /kiro:spec-init <機能説明> で開発開始');
316
- console.log('');
317
- console.log('作成されたファイル:');
318
- console.log(' - .kiro/project.json');
319
- console.log(' - .cursor/rules/ (3ファイル)');
320
- console.log(' - .cursor/commands/kiro/ (2ファイル)');
321
- console.log(' - .kiro/steering/ (3ファイル)');
322
- console.log(' - .kiro/settings/templates/ (3ファイル)');
323
- console.log(' - scripts/ (7+ ファイル)');
324
- console.log(' - package.json (新規の場合)');
325
- console.log(' - tsconfig.json (新規の場合)');
326
- console.log(' - .env (テンプレート)');
327
416
  }
328
417
  // 実行
329
418
  const config = parseArgs();