@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.
- package/CHANGELOG.md +55 -0
- package/README.md +205 -11
- package/dist/scripts/__tests__/create-project.test.d.ts +2 -0
- package/dist/scripts/__tests__/create-project.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/create-project.test.js +247 -0
- package/dist/scripts/__tests__/create-project.test.js.map +1 -0
- package/dist/scripts/__tests__/multi-project-estimate.test.d.ts +2 -0
- package/dist/scripts/__tests__/multi-project-estimate.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/multi-project-estimate.test.js +119 -0
- package/dist/scripts/__tests__/multi-project-estimate.test.js.map +1 -0
- package/dist/scripts/__tests__/setup-existing-project.test.d.ts +2 -0
- package/dist/scripts/__tests__/setup-existing-project.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/setup-existing-project.test.js +129 -0
- package/dist/scripts/__tests__/setup-existing-project.test.js.map +1 -0
- package/dist/scripts/__tests__/setup-interactive.test.d.ts +2 -0
- package/dist/scripts/__tests__/setup-interactive.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/setup-interactive.test.js +160 -0
- package/dist/scripts/__tests__/setup-interactive.test.js.map +1 -0
- package/dist/scripts/config/default-config.json +57 -0
- package/dist/scripts/confluence-sync.d.ts +4 -0
- package/dist/scripts/confluence-sync.d.ts.map +1 -1
- package/dist/scripts/confluence-sync.js +12 -23
- package/dist/scripts/confluence-sync.js.map +1 -1
- package/dist/scripts/constants/__tests__/environments.test.d.ts +2 -0
- package/dist/scripts/constants/__tests__/environments.test.d.ts.map +1 -0
- package/dist/scripts/constants/__tests__/environments.test.js +91 -0
- package/dist/scripts/constants/__tests__/environments.test.js.map +1 -0
- package/dist/scripts/constants/__tests__/languages.test.d.ts +2 -0
- package/dist/scripts/constants/__tests__/languages.test.d.ts.map +1 -0
- package/dist/scripts/constants/__tests__/languages.test.js +82 -0
- package/dist/scripts/constants/__tests__/languages.test.js.map +1 -0
- package/dist/scripts/constants/environments.d.ts +33 -0
- package/dist/scripts/constants/environments.d.ts.map +1 -0
- package/dist/scripts/constants/environments.js +49 -0
- package/dist/scripts/constants/environments.js.map +1 -0
- package/dist/scripts/constants/languages.d.ts +23 -0
- package/dist/scripts/constants/languages.d.ts.map +1 -0
- package/dist/scripts/constants/languages.js +53 -0
- package/dist/scripts/constants/languages.js.map +1 -0
- package/dist/scripts/create-project.d.ts +4 -0
- package/dist/scripts/create-project.d.ts.map +1 -1
- package/dist/scripts/create-project.js +227 -137
- package/dist/scripts/create-project.js.map +1 -1
- package/dist/scripts/jira-sync.d.ts.map +1 -1
- package/dist/scripts/jira-sync.js +15 -0
- package/dist/scripts/jira-sync.js.map +1 -1
- package/dist/scripts/list-projects.d.ts.map +1 -1
- package/dist/scripts/list-projects.js +42 -15
- package/dist/scripts/list-projects.js.map +1 -1
- package/dist/scripts/multi-project-estimate.d.ts.map +1 -1
- package/dist/scripts/multi-project-estimate.js +56 -21
- package/dist/scripts/multi-project-estimate.js.map +1 -1
- package/dist/scripts/resource-dashboard.d.ts.map +1 -1
- package/dist/scripts/resource-dashboard.js +74 -17
- package/dist/scripts/resource-dashboard.js.map +1 -1
- package/dist/scripts/setup-existing-project.d.ts +3 -1
- package/dist/scripts/setup-existing-project.d.ts.map +1 -1
- package/dist/scripts/setup-existing-project.js +306 -217
- package/dist/scripts/setup-existing-project.js.map +1 -1
- package/dist/scripts/setup-interactive.d.ts +10 -0
- package/dist/scripts/setup-interactive.d.ts.map +1 -0
- package/dist/scripts/setup-interactive.js +413 -0
- package/dist/scripts/setup-interactive.js.map +1 -0
- package/dist/scripts/template/__tests__/renderer.test.d.ts +2 -0
- package/dist/scripts/template/__tests__/renderer.test.d.ts.map +1 -0
- package/dist/scripts/template/__tests__/renderer.test.js +165 -0
- package/dist/scripts/template/__tests__/renderer.test.js.map +1 -0
- package/dist/scripts/template/renderer.d.ts +70 -0
- package/dist/scripts/template/renderer.d.ts.map +1 -0
- package/dist/scripts/template/renderer.js +99 -0
- package/dist/scripts/template/renderer.js.map +1 -0
- package/dist/scripts/utils/__tests__/config-validator.test.js +5 -0
- package/dist/scripts/utils/__tests__/config-validator.test.js.map +1 -1
- package/dist/scripts/utils/__tests__/spec-updater.test.d.ts +5 -0
- package/dist/scripts/utils/__tests__/spec-updater.test.d.ts.map +1 -0
- package/dist/scripts/utils/__tests__/spec-updater.test.js +158 -0
- package/dist/scripts/utils/__tests__/spec-updater.test.js.map +1 -0
- package/dist/scripts/utils/confluence-hierarchy.d.ts +2 -1
- package/dist/scripts/utils/confluence-hierarchy.d.ts.map +1 -1
- package/dist/scripts/utils/confluence-hierarchy.js +5 -0
- package/dist/scripts/utils/confluence-hierarchy.js.map +1 -1
- package/dist/scripts/utils/project-finder.d.ts +30 -0
- package/dist/scripts/utils/project-finder.d.ts.map +1 -0
- package/dist/scripts/utils/project-finder.js +147 -0
- package/dist/scripts/utils/project-finder.js.map +1 -0
- package/dist/scripts/utils/spec-updater.d.ts +72 -0
- package/dist/scripts/utils/spec-updater.d.ts.map +1 -0
- package/dist/scripts/utils/spec-updater.js +141 -0
- package/dist/scripts/utils/spec-updater.js.map +1 -0
- package/dist/scripts/utils/template-finder.d.ts +37 -0
- package/dist/scripts/utils/template-finder.d.ts.map +1 -0
- package/dist/scripts/utils/template-finder.js +63 -0
- package/dist/scripts/utils/template-finder.js.map +1 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.js +125 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/claude.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/claude.test.js +111 -0
- package/dist/src/__tests__/integration/setup/claude.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/cursor.test.js +162 -0
- package/dist/src/__tests__/integration/setup/cursor.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +32 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +72 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +38 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.js +83 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +1 -0
- package/dist/src/__tests__/integration/setup/validation.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/validation.test.js +318 -0
- package/dist/src/__tests__/integration/setup/validation.test.js.map +1 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +20 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/setup-existing.d.ts +22 -0
- package/dist/src/commands/setup-existing.d.ts.map +1 -0
- package/dist/src/commands/setup-existing.js +408 -0
- package/dist/src/commands/setup-existing.js.map +1 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +9 -6
- package/dist/vitest.config.js.map +1 -1
- package/docs/README.md +2 -2
- package/docs/contributing/development.md +37 -0
- package/docs/getting-started/{new-project-setup.md → new-repository-setup.md} +165 -38
- package/docs/getting-started/quick-start.md +57 -6
- package/docs/getting-started/setup.md +551 -180
- package/docs/guides/customization.md +4 -4
- package/docs/guides/multi-project.md +12 -9
- package/docs/reference/quick-reference.md +27 -18
- package/docs/testing/integration-tests.md +297 -0
- package/docs/testing-strategy.md +87 -0
- package/package.json +23 -6
- package/scripts/__tests__/create-project.test.ts +292 -0
- package/scripts/__tests__/multi-project-estimate.test.ts +145 -0
- package/scripts/__tests__/setup-existing-project.test.ts +147 -0
- package/scripts/__tests__/setup-interactive.test.ts +199 -0
- package/scripts/confluence-sync.ts +17 -29
- package/scripts/constants/__tests__/environments.test.ts +110 -0
- package/scripts/constants/__tests__/languages.test.ts +100 -0
- package/scripts/constants/environments.ts +61 -0
- package/scripts/constants/languages.ts +70 -0
- package/scripts/copy-static-assets.js +50 -0
- package/scripts/create-project.ts +251 -158
- package/scripts/jira-sync.ts +16 -1
- package/scripts/list-projects.ts +51 -24
- package/scripts/multi-project-estimate.ts +58 -22
- package/scripts/resource-dashboard.ts +91 -26
- package/scripts/setup-existing-project.ts +350 -230
- package/scripts/setup-existing.sh +159 -25
- package/scripts/setup-interactive.ts +565 -0
- package/scripts/template/__tests__/renderer.test.ts +207 -0
- package/scripts/template/renderer.ts +133 -0
- package/scripts/utils/__tests__/config-validator.test.ts +6 -0
- package/scripts/utils/__tests__/spec-updater.test.ts +220 -0
- package/scripts/utils/confluence-hierarchy.ts +7 -1
- package/scripts/utils/project-finder.ts +184 -0
- package/scripts/utils/spec-updater.ts +212 -0
- package/scripts/utils/template-finder.ts +75 -0
- package/templates/claude/commands/michi/confluence-sync.md +38 -0
- package/templates/claude/commands/michi/project-switch.md +36 -0
- package/templates/claude/rules/atlassian-integration.md +35 -0
- package/templates/claude/rules/michi-core.md +54 -0
- package/templates/claude-agent/README.md +25 -0
- package/templates/cursor/commands/michi/confluence-sync.md +76 -0
- package/templates/cursor/commands/michi/project-switch.md +69 -0
- package/templates/cursor/rules/atlassian-mcp.mdc +188 -0
- package/templates/cursor/rules/github-ssot.mdc +151 -0
- package/templates/cursor/rules/multi-project.mdc +81 -0
- 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
|
-
//
|
|
71
|
-
|
|
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
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
88
|
-
console.log(
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
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
|
-
|
|
105
|
-
|
|
214
|
+
const projectLabel = projectId.toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
215
|
+
const labelSet = new Set([`project:${projectLabel}`]);
|
|
106
216
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
115
|
-
|
|
223
|
+
// サービスラベルがプロジェクトラベルと異なる場合のみ追加
|
|
224
|
+
if (serviceLabel !== projectLabel) {
|
|
225
|
+
labelSet.add(`service:${serviceLabel}`);
|
|
226
|
+
}
|
|
116
227
|
}
|
|
117
|
-
}
|
|
118
228
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
175
|
-
|
|
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
|
-
|
|
184
|
-
|
|
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
|
-
|
|
187
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
219
|
-
//
|
|
220
|
-
console.log('
|
|
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('
|
|
224
|
-
console.log('
|
|
225
|
-
console.log('
|
|
226
|
-
console.log('
|
|
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
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
-
|
|
248
|
-
|
|
361
|
+
// Step 9: .env テンプレート作成(プロジェクトディレクトリに)
|
|
362
|
+
console.log('\n🔐 Step 9: Creating .env template...');
|
|
249
363
|
|
|
250
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
277
|
-
|
|
390
|
+
// Step 10: README.md を更新(オプション、プロジェクトディレクトリに)
|
|
391
|
+
console.log('\n📖 Step 10: Updating documentation...');
|
|
278
392
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
393
|
+
const readmePath = join(projectDir, 'README.md');
|
|
394
|
+
if (existsSync(readmePath)) {
|
|
395
|
+
const currentReadme = readFileSync(readmePath, 'utf-8');
|
|
282
396
|
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
|