@sk8metal/michi-cli 0.0.7 → 0.0.8

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