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