@zeyue0329/xiaoma-cli 1.0.37 → 1.0.39
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/.idea/workspace.xml +27 -26
- package/JAVA-BACKEND-COMMANDS-REFERENCE.md +62 -52
- package/JAVA-BACKEND-ITERATION-GUIDE.md +125 -18
- package/README.md +1 -1
- package/common/utils/bmad-doc-template.md +5 -5
- package/dist/agents/analyst.txt +35 -5
- package/dist/agents/architect.txt +217 -31
- package/dist/agents/automation-orchestrator.txt +4 -4
- package/dist/agents/dev.txt +3 -3
- package/dist/agents/full-requirement-orchestrator.txt +11 -11
- package/dist/agents/qa.txt +102 -102
- package/dist/agents/sm.txt +6 -6
- package/dist/agents/ux-expert.txt +6 -1
- package/dist/agents/workflow-executor.txt +879 -0
- package/dist/agents/xiaoma-master.txt +258 -37
- package/dist/teams/team-all.txt +1223 -445
- package/dist/teams/team-fullstack-with-database.txt +384 -446
- package/dist/teams/team-fullstack.txt +258 -37
- package/dist/teams/team-ide-minimal.txt +111 -111
- package/dist/teams/team-no-ui.txt +252 -36
- package/docs/architecture-sharding-modification.md +623 -0
- package/docs/automated-requirements-analysis-outputs.md +896 -0
- package/package.json +1 -1
- package/tools/builders/web-builder.js +292 -142
- package/tools/bump-all-versions.js +50 -32
- package/tools/cli.js +52 -47
- package/tools/flattener/aggregate.js +30 -12
- package/tools/flattener/binary.js +46 -43
- package/tools/flattener/discovery.js +23 -15
- package/tools/flattener/files.js +6 -6
- package/tools/flattener/ignoreRules.js +122 -121
- package/tools/flattener/main.js +249 -144
- package/tools/flattener/projectRoot.js +74 -69
- package/tools/flattener/prompts.js +12 -10
- package/tools/flattener/stats.helpers.js +90 -61
- package/tools/flattener/stats.js +1 -1
- package/tools/flattener/test-matrix.js +225 -170
- package/tools/flattener/xml.js +31 -23
- package/tools/installer/bin/xiaoma.js +199 -153
- package/tools/installer/lib/config-loader.js +76 -47
- package/tools/installer/lib/file-manager.js +101 -44
- package/tools/installer/lib/ide-base-setup.js +49 -39
- package/tools/installer/lib/ide-setup.js +694 -380
- package/tools/installer/lib/installer.js +802 -469
- package/tools/installer/lib/memory-profiler.js +22 -12
- package/tools/installer/lib/module-manager.js +16 -14
- package/tools/installer/lib/resource-locator.js +61 -35
- package/tools/lib/dependency-resolver.js +34 -23
- package/tools/lib/yaml-utils.js +7 -2
- package/tools/preview-release-notes.js +33 -25
- package/tools/shared/bannerArt.js +3 -3
- package/tools/sync-installer-version.js +16 -7
- package/tools/upgraders/v3-to-v4-upgrader.js +244 -163
- package/tools/version-bump.js +24 -18
- package/tools/xiaoma-npx-wrapper.js +15 -10
- package/tools/yaml-format.js +60 -36
- package/xiaoma-core/agent-teams/team-fullstack-with-database.yaml +0 -1
- package/xiaoma-core/agents/automated-fix-validator.yaml +2 -1
- package/xiaoma-core/agents/automated-quality-validator.yaml +10 -5
- package/xiaoma-core/agents/automation-orchestrator.md +4 -4
- package/xiaoma-core/agents/dev.md +4 -4
- package/xiaoma-core/agents/enhanced-workflow-orchestrator.yaml +2 -1
- package/xiaoma-core/agents/full-requirement-orchestrator.md +11 -11
- package/xiaoma-core/agents/global-requirements-auditor.yaml +11 -3
- package/xiaoma-core/agents/intelligent-template-adapter.yaml +19 -5
- package/xiaoma-core/agents/master-execution-engine.yaml +19 -5
- package/xiaoma-core/agents/workflow-executor.md +8 -4
- package/xiaoma-core/agents/xiaoma-master.md +1 -1
- package/xiaoma-core/data/test-levels-framework.md +12 -12
- package/xiaoma-core/tasks/analyze-existing-database.md +1 -1
- package/xiaoma-core/tasks/apply-qa-fixes.md +3 -3
- package/xiaoma-core/tasks/batch-story-generation.md +22 -22
- package/xiaoma-core/tasks/create-enhanced-story-with-database.md +6 -6
- package/xiaoma-core/tasks/nfr-assess.md +6 -6
- package/xiaoma-core/tasks/project-integration-testing.md +42 -42
- package/xiaoma-core/tasks/qa-gate.md +23 -23
- package/xiaoma-core/tasks/review-story.md +18 -18
- package/xiaoma-core/tasks/risk-profile.md +25 -25
- package/xiaoma-core/tasks/serial-development-orchestration.md +51 -51
- package/xiaoma-core/tasks/test-design.md +9 -9
- package/xiaoma-core/tasks/trace-requirements.md +21 -21
- package/xiaoma-core/templates/competitor-analysis-tmpl.yaml +35 -5
- package/xiaoma-core/templates/front-end-architecture-tmpl.yaml +77 -11
- package/xiaoma-core/templates/front-end-spec-tmpl.yaml +6 -1
- package/xiaoma-core/templates/fullstack-architecture-tmpl.yaml +140 -20
- package/xiaoma-core/templates/global-qa-monitoring-tmpl.yaml +2 -1
- package/xiaoma-core/templates/requirements-coverage-audit.yaml +2 -1
- package/xiaoma-core/workflows/automated-requirements-analysis.yaml +283 -6
- package/dist/agents/database-architect.txt +0 -322
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const { glob } = require(
|
|
1
|
+
const fs = require("node:fs").promises;
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const { glob } = require("glob");
|
|
4
4
|
|
|
5
5
|
// Dynamic imports for ES modules
|
|
6
6
|
let chalk, ora, inquirer;
|
|
7
7
|
|
|
8
8
|
// Initialize ES modules
|
|
9
9
|
async function initializeModules() {
|
|
10
|
-
chalk = (await import(
|
|
11
|
-
ora = (await import(
|
|
12
|
-
inquirer = (await import(
|
|
10
|
+
chalk = (await import("chalk")).default;
|
|
11
|
+
ora = (await import("ora")).default;
|
|
12
|
+
inquirer = (await import("inquirer")).default;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
class V3ToV4Upgrader {
|
|
@@ -25,15 +25,23 @@ class V3ToV4Upgrader {
|
|
|
25
25
|
process.stdin.resume();
|
|
26
26
|
|
|
27
27
|
// 1. Welcome message
|
|
28
|
-
console.log(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
console.log(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
console.log(chalk.
|
|
35
|
-
console.log(
|
|
36
|
-
console.log(
|
|
28
|
+
console.log(
|
|
29
|
+
chalk.bold("\nWelcome to XiaoMa-Cli V3 to V4 Upgrade Tool\n"),
|
|
30
|
+
);
|
|
31
|
+
console.log(
|
|
32
|
+
"This tool will help you upgrade your XiaoMa-Cli V3 project to V4.\n",
|
|
33
|
+
);
|
|
34
|
+
console.log(chalk.cyan("What this tool does:"));
|
|
35
|
+
console.log("- Creates a backup of your V3 files (.bmad-v3-backup/)");
|
|
36
|
+
console.log("- Installs the new V4 .xiaoma-core structure");
|
|
37
|
+
console.log(
|
|
38
|
+
"- Preserves your PRD, Architecture, and Stories in the new format\n",
|
|
39
|
+
);
|
|
40
|
+
console.log(chalk.yellow("What this tool does NOT do:"));
|
|
41
|
+
console.log(
|
|
42
|
+
"- Modify your document content (use doc-migration-task after upgrade)",
|
|
43
|
+
);
|
|
44
|
+
console.log("- Touch any files outside bmad-agent/ and docs/\n");
|
|
37
45
|
|
|
38
46
|
// 2. Get project path
|
|
39
47
|
const projectPath = await this.getProjectPath(options.projectPath);
|
|
@@ -41,11 +49,15 @@ class V3ToV4Upgrader {
|
|
|
41
49
|
// 3. Validate V3 structure
|
|
42
50
|
const validation = await this.validateV3Project(projectPath);
|
|
43
51
|
if (!validation.isValid) {
|
|
44
|
-
console.error(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
console.error(
|
|
48
|
-
console.error("
|
|
52
|
+
console.error(
|
|
53
|
+
chalk.red("\nError: This doesn't appear to be a V3 project."),
|
|
54
|
+
);
|
|
55
|
+
console.error("Expected to find:");
|
|
56
|
+
console.error("- bmad-agent/ directory");
|
|
57
|
+
console.error("- docs/ directory\n");
|
|
58
|
+
console.error(
|
|
59
|
+
"Please check you're in the correct directory and try again.",
|
|
60
|
+
);
|
|
49
61
|
return;
|
|
50
62
|
}
|
|
51
63
|
|
|
@@ -56,15 +68,15 @@ class V3ToV4Upgrader {
|
|
|
56
68
|
if (!options.dryRun) {
|
|
57
69
|
const { confirm } = await inquirer.prompt([
|
|
58
70
|
{
|
|
59
|
-
type:
|
|
60
|
-
name:
|
|
61
|
-
message:
|
|
71
|
+
type: "confirm",
|
|
72
|
+
name: "confirm",
|
|
73
|
+
message: "Continue with upgrade?",
|
|
62
74
|
default: true,
|
|
63
75
|
},
|
|
64
76
|
]);
|
|
65
77
|
|
|
66
78
|
if (!confirm) {
|
|
67
|
-
console.log(
|
|
79
|
+
console.log("Upgrade cancelled.");
|
|
68
80
|
return;
|
|
69
81
|
}
|
|
70
82
|
}
|
|
@@ -94,7 +106,7 @@ class V3ToV4Upgrader {
|
|
|
94
106
|
|
|
95
107
|
process.exit(0);
|
|
96
108
|
} catch (error) {
|
|
97
|
-
console.error(chalk.red(
|
|
109
|
+
console.error(chalk.red("\nUpgrade error:"), error.message);
|
|
98
110
|
process.exit(1);
|
|
99
111
|
}
|
|
100
112
|
}
|
|
@@ -106,9 +118,9 @@ class V3ToV4Upgrader {
|
|
|
106
118
|
|
|
107
119
|
const { projectPath } = await inquirer.prompt([
|
|
108
120
|
{
|
|
109
|
-
type:
|
|
110
|
-
name:
|
|
111
|
-
message:
|
|
121
|
+
type: "input",
|
|
122
|
+
name: "projectPath",
|
|
123
|
+
message: "Please enter the path to your V3 project:",
|
|
112
124
|
default: process.cwd(),
|
|
113
125
|
},
|
|
114
126
|
]);
|
|
@@ -117,45 +129,45 @@ class V3ToV4Upgrader {
|
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
async validateV3Project(projectPath) {
|
|
120
|
-
const spinner = ora(
|
|
132
|
+
const spinner = ora("Validating project structure...").start();
|
|
121
133
|
|
|
122
134
|
try {
|
|
123
|
-
const bmadAgentPath = path.join(projectPath,
|
|
124
|
-
const docsPath = path.join(projectPath,
|
|
135
|
+
const bmadAgentPath = path.join(projectPath, "bmad-agent");
|
|
136
|
+
const docsPath = path.join(projectPath, "docs");
|
|
125
137
|
|
|
126
138
|
const hasBmadAgent = await this.pathExists(bmadAgentPath);
|
|
127
139
|
const hasDocs = await this.pathExists(docsPath);
|
|
128
140
|
|
|
129
141
|
if (hasBmadAgent) {
|
|
130
|
-
spinner.text =
|
|
131
|
-
console.log(chalk.green(
|
|
142
|
+
spinner.text = "✓ Found bmad-agent/ directory";
|
|
143
|
+
console.log(chalk.green("\n✓ Found bmad-agent/ directory"));
|
|
132
144
|
}
|
|
133
145
|
|
|
134
146
|
if (hasDocs) {
|
|
135
|
-
console.log(chalk.green(
|
|
147
|
+
console.log(chalk.green("✓ Found docs/ directory"));
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
const isValid = hasBmadAgent && hasDocs;
|
|
139
151
|
|
|
140
152
|
if (isValid) {
|
|
141
|
-
spinner.succeed(
|
|
153
|
+
spinner.succeed("This appears to be a valid V3 project");
|
|
142
154
|
} else {
|
|
143
|
-
spinner.fail(
|
|
155
|
+
spinner.fail("Invalid V3 project structure");
|
|
144
156
|
}
|
|
145
157
|
|
|
146
158
|
return { isValid, hasBmadAgent, hasDocs };
|
|
147
159
|
} catch (error) {
|
|
148
|
-
spinner.fail(
|
|
160
|
+
spinner.fail("Validation failed");
|
|
149
161
|
throw error;
|
|
150
162
|
}
|
|
151
163
|
}
|
|
152
164
|
|
|
153
165
|
async analyzeProject(projectPath) {
|
|
154
|
-
const docsPath = path.join(projectPath,
|
|
155
|
-
const bmadAgentPath = path.join(projectPath,
|
|
166
|
+
const docsPath = path.join(projectPath, "docs");
|
|
167
|
+
const bmadAgentPath = path.join(projectPath, "bmad-agent");
|
|
156
168
|
|
|
157
169
|
// Find PRD
|
|
158
|
-
const prdCandidates = [
|
|
170
|
+
const prdCandidates = ["prd.md", "PRD.md", "product-requirements.md"];
|
|
159
171
|
let prdFile = null;
|
|
160
172
|
for (const candidate of prdCandidates) {
|
|
161
173
|
const candidatePath = path.join(docsPath, candidate);
|
|
@@ -166,7 +178,11 @@ class V3ToV4Upgrader {
|
|
|
166
178
|
}
|
|
167
179
|
|
|
168
180
|
// Find Architecture
|
|
169
|
-
const archCandidates = [
|
|
181
|
+
const archCandidates = [
|
|
182
|
+
"architecture.md",
|
|
183
|
+
"Architecture.md",
|
|
184
|
+
"technical-architecture.md",
|
|
185
|
+
];
|
|
170
186
|
let archFile = null;
|
|
171
187
|
for (const candidate of archCandidates) {
|
|
172
188
|
const candidatePath = path.join(docsPath, candidate);
|
|
@@ -178,9 +194,9 @@ class V3ToV4Upgrader {
|
|
|
178
194
|
|
|
179
195
|
// Find Front-end Architecture (V3 specific)
|
|
180
196
|
const frontEndCandidates = [
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
197
|
+
"front-end-architecture.md",
|
|
198
|
+
"frontend-architecture.md",
|
|
199
|
+
"ui-architecture.md",
|
|
184
200
|
];
|
|
185
201
|
let frontEndArchFile = null;
|
|
186
202
|
for (const candidate of frontEndCandidates) {
|
|
@@ -193,10 +209,10 @@ class V3ToV4Upgrader {
|
|
|
193
209
|
|
|
194
210
|
// Find UX/UI spec
|
|
195
211
|
const uxSpecCandidates = [
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
212
|
+
"ux-ui-spec.md",
|
|
213
|
+
"ux-ui-specification.md",
|
|
214
|
+
"ui-spec.md",
|
|
215
|
+
"ux-spec.md",
|
|
200
216
|
];
|
|
201
217
|
let uxSpecFile = null;
|
|
202
218
|
for (const candidate of uxSpecCandidates) {
|
|
@@ -208,7 +224,12 @@ class V3ToV4Upgrader {
|
|
|
208
224
|
}
|
|
209
225
|
|
|
210
226
|
// Find v0 prompt or UX prompt
|
|
211
|
-
const uxPromptCandidates = [
|
|
227
|
+
const uxPromptCandidates = [
|
|
228
|
+
"v0-prompt.md",
|
|
229
|
+
"ux-prompt.md",
|
|
230
|
+
"ui-prompt.md",
|
|
231
|
+
"design-prompt.md",
|
|
232
|
+
];
|
|
212
233
|
let uxPromptFile = null;
|
|
213
234
|
for (const candidate of uxPromptCandidates) {
|
|
214
235
|
const candidatePath = path.join(docsPath, candidate);
|
|
@@ -219,19 +240,19 @@ class V3ToV4Upgrader {
|
|
|
219
240
|
}
|
|
220
241
|
|
|
221
242
|
// Find epic files
|
|
222
|
-
const epicFiles = await glob(
|
|
243
|
+
const epicFiles = await glob("epic*.md", { cwd: docsPath });
|
|
223
244
|
|
|
224
245
|
// Find story files
|
|
225
|
-
const storiesPath = path.join(docsPath,
|
|
246
|
+
const storiesPath = path.join(docsPath, "stories");
|
|
226
247
|
let storyFiles = [];
|
|
227
248
|
if (await this.pathExists(storiesPath)) {
|
|
228
|
-
storyFiles = await glob(
|
|
249
|
+
storyFiles = await glob("*.md", { cwd: storiesPath });
|
|
229
250
|
}
|
|
230
251
|
|
|
231
252
|
// Count custom files in bmad-agent
|
|
232
|
-
const bmadAgentFiles = await glob(
|
|
253
|
+
const bmadAgentFiles = await glob("**/*.md", {
|
|
233
254
|
cwd: bmadAgentPath,
|
|
234
|
-
ignore: [
|
|
255
|
+
ignore: ["node_modules/**"],
|
|
235
256
|
});
|
|
236
257
|
|
|
237
258
|
return {
|
|
@@ -247,133 +268,157 @@ class V3ToV4Upgrader {
|
|
|
247
268
|
}
|
|
248
269
|
|
|
249
270
|
async showPreflightCheck(analysis, options) {
|
|
250
|
-
console.log(chalk.bold(
|
|
271
|
+
console.log(chalk.bold("\nProject Analysis:"));
|
|
251
272
|
console.log(
|
|
252
|
-
`- PRD found: ${analysis.prdFile ? `docs/${analysis.prdFile}` : chalk.yellow(
|
|
273
|
+
`- PRD found: ${analysis.prdFile ? `docs/${analysis.prdFile}` : chalk.yellow("Not found")}`,
|
|
253
274
|
);
|
|
254
275
|
console.log(
|
|
255
276
|
`- Architecture found: ${
|
|
256
|
-
analysis.archFile
|
|
277
|
+
analysis.archFile
|
|
278
|
+
? `docs/${analysis.archFile}`
|
|
279
|
+
: chalk.yellow("Not found")
|
|
257
280
|
}`,
|
|
258
281
|
);
|
|
259
282
|
if (analysis.frontEndArchFile) {
|
|
260
|
-
console.log(
|
|
283
|
+
console.log(
|
|
284
|
+
`- Front-end Architecture found: docs/${analysis.frontEndArchFile}`,
|
|
285
|
+
);
|
|
261
286
|
}
|
|
262
287
|
console.log(
|
|
263
288
|
`- UX/UI Spec found: ${
|
|
264
|
-
analysis.uxSpecFile
|
|
289
|
+
analysis.uxSpecFile
|
|
290
|
+
? `docs/${analysis.uxSpecFile}`
|
|
291
|
+
: chalk.yellow("Not found")
|
|
265
292
|
}`,
|
|
266
293
|
);
|
|
267
294
|
console.log(
|
|
268
295
|
`- UX/Design Prompt found: ${
|
|
269
|
-
analysis.uxPromptFile
|
|
296
|
+
analysis.uxPromptFile
|
|
297
|
+
? `docs/${analysis.uxPromptFile}`
|
|
298
|
+
: chalk.yellow("Not found")
|
|
270
299
|
}`,
|
|
271
300
|
);
|
|
272
|
-
console.log(
|
|
273
|
-
|
|
301
|
+
console.log(
|
|
302
|
+
`- Epic files found: ${analysis.epicFiles.length} files (epic*.md)`,
|
|
303
|
+
);
|
|
304
|
+
console.log(
|
|
305
|
+
`- Stories found: ${analysis.storyFiles.length} files in docs/stories/`,
|
|
306
|
+
);
|
|
274
307
|
console.log(`- Custom files in bmad-agent/: ${analysis.customFileCount}`);
|
|
275
308
|
|
|
276
309
|
if (!options.dryRun) {
|
|
277
|
-
console.log(
|
|
278
|
-
console.log(
|
|
279
|
-
console.log(
|
|
310
|
+
console.log("\nThe following will be backed up to .bmad-v3-backup/:");
|
|
311
|
+
console.log("- bmad-agent/ (entire directory)");
|
|
312
|
+
console.log("- docs/ (entire directory)");
|
|
280
313
|
|
|
281
314
|
if (analysis.epicFiles.length > 0) {
|
|
282
315
|
console.log(
|
|
283
316
|
chalk.green(
|
|
284
|
-
|
|
317
|
+
"\nNote: Epic files found! They will be placed in docs/prd/ with an index.md file.",
|
|
285
318
|
),
|
|
286
319
|
);
|
|
287
320
|
console.log(
|
|
288
|
-
chalk.green(
|
|
321
|
+
chalk.green(
|
|
322
|
+
"Since epic files exist, you won't need to shard the PRD after upgrade.",
|
|
323
|
+
),
|
|
289
324
|
);
|
|
290
325
|
}
|
|
291
326
|
}
|
|
292
327
|
}
|
|
293
328
|
|
|
294
329
|
async createBackup(projectPath) {
|
|
295
|
-
const spinner = ora(
|
|
330
|
+
const spinner = ora("Creating backup...").start();
|
|
296
331
|
|
|
297
332
|
try {
|
|
298
|
-
const backupPath = path.join(projectPath,
|
|
333
|
+
const backupPath = path.join(projectPath, ".bmad-v3-backup");
|
|
299
334
|
|
|
300
335
|
// Check if backup already exists
|
|
301
336
|
if (await this.pathExists(backupPath)) {
|
|
302
|
-
spinner.fail(
|
|
303
|
-
console.error(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
337
|
+
spinner.fail("Backup directory already exists");
|
|
338
|
+
console.error(
|
|
339
|
+
chalk.red(
|
|
340
|
+
"\nError: Backup directory .bmad-v3-backup/ already exists.",
|
|
341
|
+
),
|
|
342
|
+
);
|
|
343
|
+
console.error("\nThis might mean an upgrade was already attempted.");
|
|
344
|
+
console.error(
|
|
345
|
+
"Please remove or rename the existing backup and try again.",
|
|
346
|
+
);
|
|
347
|
+
throw new Error("Backup already exists");
|
|
307
348
|
}
|
|
308
349
|
|
|
309
350
|
// Create backup directory
|
|
310
351
|
await fs.mkdir(backupPath, { recursive: true });
|
|
311
|
-
spinner.text =
|
|
312
|
-
console.log(chalk.green(
|
|
352
|
+
spinner.text = "✓ Created .bmad-v3-backup/";
|
|
353
|
+
console.log(chalk.green("\n✓ Created .bmad-v3-backup/"));
|
|
313
354
|
|
|
314
355
|
// Move bmad-agent
|
|
315
|
-
const bmadAgentSource = path.join(projectPath,
|
|
316
|
-
const bmadAgentDestination = path.join(backupPath,
|
|
356
|
+
const bmadAgentSource = path.join(projectPath, "bmad-agent");
|
|
357
|
+
const bmadAgentDestination = path.join(backupPath, "bmad-agent");
|
|
317
358
|
await fs.rename(bmadAgentSource, bmadAgentDestination);
|
|
318
|
-
console.log(chalk.green(
|
|
359
|
+
console.log(chalk.green("✓ Moved bmad-agent/ to backup"));
|
|
319
360
|
|
|
320
361
|
// Move docs
|
|
321
|
-
const docsSrc = path.join(projectPath,
|
|
322
|
-
const docsDest = path.join(backupPath,
|
|
362
|
+
const docsSrc = path.join(projectPath, "docs");
|
|
363
|
+
const docsDest = path.join(backupPath, "docs");
|
|
323
364
|
await fs.rename(docsSrc, docsDest);
|
|
324
|
-
console.log(chalk.green(
|
|
365
|
+
console.log(chalk.green("✓ Moved docs/ to backup"));
|
|
325
366
|
|
|
326
|
-
spinner.succeed(
|
|
367
|
+
spinner.succeed("Backup created successfully");
|
|
327
368
|
} catch (error) {
|
|
328
|
-
spinner.fail(
|
|
369
|
+
spinner.fail("Backup failed");
|
|
329
370
|
throw error;
|
|
330
371
|
}
|
|
331
372
|
}
|
|
332
373
|
|
|
333
374
|
async installV4Structure(projectPath) {
|
|
334
|
-
const spinner = ora(
|
|
375
|
+
const spinner = ora("Installing V4 structure...").start();
|
|
335
376
|
|
|
336
377
|
try {
|
|
337
378
|
// Get the source xiaoma-core directory (without dot prefix)
|
|
338
|
-
const sourcePath = path.join(__dirname,
|
|
339
|
-
const destinationPath = path.join(projectPath,
|
|
379
|
+
const sourcePath = path.join(__dirname, "..", "..", "xiaoma-core");
|
|
380
|
+
const destinationPath = path.join(projectPath, ".xiaoma-core");
|
|
340
381
|
|
|
341
382
|
// Copy .xiaoma-core
|
|
342
383
|
await this.copyDirectory(sourcePath, destinationPath);
|
|
343
|
-
spinner.text =
|
|
344
|
-
console.log(
|
|
384
|
+
spinner.text = "✓ Copied fresh .xiaoma-core/ directory from V4";
|
|
385
|
+
console.log(
|
|
386
|
+
chalk.green("\n✓ Copied fresh .xiaoma-core/ directory from V4"),
|
|
387
|
+
);
|
|
345
388
|
|
|
346
389
|
// Create docs directory
|
|
347
|
-
const docsPath = path.join(projectPath,
|
|
390
|
+
const docsPath = path.join(projectPath, "docs");
|
|
348
391
|
await fs.mkdir(docsPath, { recursive: true });
|
|
349
|
-
console.log(chalk.green(
|
|
392
|
+
console.log(chalk.green("✓ Created new docs/ directory"));
|
|
350
393
|
|
|
351
394
|
// Create install manifest for future updates
|
|
352
395
|
await this.createInstallManifest(projectPath);
|
|
353
|
-
console.log(chalk.green(
|
|
396
|
+
console.log(chalk.green("✓ Created install manifest"));
|
|
354
397
|
|
|
355
398
|
console.log(
|
|
356
|
-
chalk.yellow(
|
|
399
|
+
chalk.yellow(
|
|
400
|
+
"\nNote: Your V3 bmad-agent content has been backed up and NOT migrated.",
|
|
401
|
+
),
|
|
357
402
|
);
|
|
358
403
|
console.log(
|
|
359
404
|
chalk.yellow(
|
|
360
|
-
|
|
405
|
+
"The new V4 agents are completely different and look for different file structures.",
|
|
361
406
|
),
|
|
362
407
|
);
|
|
363
408
|
|
|
364
|
-
spinner.succeed(
|
|
409
|
+
spinner.succeed("V4 structure installed successfully");
|
|
365
410
|
} catch (error) {
|
|
366
|
-
spinner.fail(
|
|
411
|
+
spinner.fail("V4 installation failed");
|
|
367
412
|
throw error;
|
|
368
413
|
}
|
|
369
414
|
}
|
|
370
415
|
|
|
371
416
|
async migrateDocuments(projectPath, analysis) {
|
|
372
|
-
const spinner = ora(
|
|
417
|
+
const spinner = ora("Migrating your project documents...").start();
|
|
373
418
|
|
|
374
419
|
try {
|
|
375
|
-
const backupDocsPath = path.join(projectPath,
|
|
376
|
-
const newDocsPath = path.join(projectPath,
|
|
420
|
+
const backupDocsPath = path.join(projectPath, ".bmad-v3-backup", "docs");
|
|
421
|
+
const newDocsPath = path.join(projectPath, "docs");
|
|
377
422
|
let copiedCount = 0;
|
|
378
423
|
|
|
379
424
|
// Copy PRD
|
|
@@ -390,7 +435,9 @@ class V3ToV4Upgrader {
|
|
|
390
435
|
const source = path.join(backupDocsPath, analysis.archFile);
|
|
391
436
|
const destination = path.join(newDocsPath, analysis.archFile);
|
|
392
437
|
await fs.copyFile(source, destination);
|
|
393
|
-
console.log(
|
|
438
|
+
console.log(
|
|
439
|
+
chalk.green(`✓ Copied Architecture to docs/${analysis.archFile}`),
|
|
440
|
+
);
|
|
394
441
|
copiedCount++;
|
|
395
442
|
}
|
|
396
443
|
|
|
@@ -400,11 +447,13 @@ class V3ToV4Upgrader {
|
|
|
400
447
|
const destination = path.join(newDocsPath, analysis.frontEndArchFile);
|
|
401
448
|
await fs.copyFile(source, destination);
|
|
402
449
|
console.log(
|
|
403
|
-
chalk.green(
|
|
450
|
+
chalk.green(
|
|
451
|
+
`✓ Copied Front-end Architecture to docs/${analysis.frontEndArchFile}`,
|
|
452
|
+
),
|
|
404
453
|
);
|
|
405
454
|
console.log(
|
|
406
455
|
chalk.yellow(
|
|
407
|
-
|
|
456
|
+
"Note: V4 uses a single full-stack-architecture.md - use doc-migration-task to merge",
|
|
408
457
|
),
|
|
409
458
|
);
|
|
410
459
|
copiedCount++;
|
|
@@ -415,7 +464,9 @@ class V3ToV4Upgrader {
|
|
|
415
464
|
const source = path.join(backupDocsPath, analysis.uxSpecFile);
|
|
416
465
|
const destination = path.join(newDocsPath, analysis.uxSpecFile);
|
|
417
466
|
await fs.copyFile(source, destination);
|
|
418
|
-
console.log(
|
|
467
|
+
console.log(
|
|
468
|
+
chalk.green(`✓ Copied UX/UI Spec to docs/${analysis.uxSpecFile}`),
|
|
469
|
+
);
|
|
419
470
|
copiedCount++;
|
|
420
471
|
}
|
|
421
472
|
|
|
@@ -424,29 +475,35 @@ class V3ToV4Upgrader {
|
|
|
424
475
|
const source = path.join(backupDocsPath, analysis.uxPromptFile);
|
|
425
476
|
const destination = path.join(newDocsPath, analysis.uxPromptFile);
|
|
426
477
|
await fs.copyFile(source, destination);
|
|
427
|
-
console.log(
|
|
478
|
+
console.log(
|
|
479
|
+
chalk.green(
|
|
480
|
+
`✓ Copied UX/Design Prompt to docs/${analysis.uxPromptFile}`,
|
|
481
|
+
),
|
|
482
|
+
);
|
|
428
483
|
copiedCount++;
|
|
429
484
|
}
|
|
430
485
|
|
|
431
486
|
// Copy stories
|
|
432
487
|
if (analysis.storyFiles.length > 0) {
|
|
433
|
-
const storiesDir = path.join(newDocsPath,
|
|
488
|
+
const storiesDir = path.join(newDocsPath, "stories");
|
|
434
489
|
await fs.mkdir(storiesDir, { recursive: true });
|
|
435
490
|
|
|
436
491
|
for (const storyFile of analysis.storyFiles) {
|
|
437
|
-
const source = path.join(backupDocsPath,
|
|
492
|
+
const source = path.join(backupDocsPath, "stories", storyFile);
|
|
438
493
|
const destination = path.join(storiesDir, storyFile);
|
|
439
494
|
await fs.copyFile(source, destination);
|
|
440
495
|
}
|
|
441
496
|
console.log(
|
|
442
|
-
chalk.green(
|
|
497
|
+
chalk.green(
|
|
498
|
+
`✓ Copied ${analysis.storyFiles.length} story files to docs/stories/`,
|
|
499
|
+
),
|
|
443
500
|
);
|
|
444
501
|
copiedCount += analysis.storyFiles.length;
|
|
445
502
|
}
|
|
446
503
|
|
|
447
504
|
// Copy epic files to prd subfolder
|
|
448
505
|
if (analysis.epicFiles.length > 0) {
|
|
449
|
-
const prdDir = path.join(newDocsPath,
|
|
506
|
+
const prdDir = path.join(newDocsPath, "prd");
|
|
450
507
|
await fs.mkdir(prdDir, { recursive: true });
|
|
451
508
|
|
|
452
509
|
for (const epicFile of analysis.epicFiles) {
|
|
@@ -455,25 +512,31 @@ class V3ToV4Upgrader {
|
|
|
455
512
|
await fs.copyFile(source, destination);
|
|
456
513
|
}
|
|
457
514
|
console.log(
|
|
458
|
-
chalk.green(
|
|
515
|
+
chalk.green(
|
|
516
|
+
`✓ Found and copied ${analysis.epicFiles.length} epic files to docs/prd/`,
|
|
517
|
+
),
|
|
459
518
|
);
|
|
460
519
|
|
|
461
520
|
// Create index.md for the prd folder
|
|
462
521
|
await this.createPrdIndex(projectPath, analysis);
|
|
463
|
-
console.log(chalk.green(
|
|
522
|
+
console.log(chalk.green("✓ Created index.md in docs/prd/"));
|
|
464
523
|
|
|
465
524
|
console.log(
|
|
466
525
|
chalk.green(
|
|
467
|
-
|
|
526
|
+
"\nNote: Epic files detected! These are compatible with V4 and have been copied.",
|
|
527
|
+
),
|
|
528
|
+
);
|
|
529
|
+
console.log(
|
|
530
|
+
chalk.green(
|
|
531
|
+
"You won't need to shard the PRD since epics already exist.",
|
|
468
532
|
),
|
|
469
533
|
);
|
|
470
|
-
console.log(chalk.green("You won't need to shard the PRD since epics already exist."));
|
|
471
534
|
copiedCount += analysis.epicFiles.length;
|
|
472
535
|
}
|
|
473
536
|
|
|
474
537
|
spinner.succeed(`Migrated ${copiedCount} documents successfully`);
|
|
475
538
|
} catch (error) {
|
|
476
|
-
spinner.fail(
|
|
539
|
+
spinner.fail("Document migration failed");
|
|
477
540
|
throw error;
|
|
478
541
|
}
|
|
479
542
|
}
|
|
@@ -481,21 +544,21 @@ class V3ToV4Upgrader {
|
|
|
481
544
|
async setupIDE(projectPath, selectedIdes) {
|
|
482
545
|
// Use the IDE selections passed from the installer
|
|
483
546
|
if (!selectedIdes || selectedIdes.length === 0) {
|
|
484
|
-
console.log(chalk.dim(
|
|
547
|
+
console.log(chalk.dim("No IDE setup requested - skipping"));
|
|
485
548
|
return;
|
|
486
549
|
}
|
|
487
550
|
|
|
488
|
-
const ideSetup = require(
|
|
489
|
-
const spinner = ora(
|
|
551
|
+
const ideSetup = require("../installer/lib/ide-setup");
|
|
552
|
+
const spinner = ora("Setting up IDE rules for all agents...").start();
|
|
490
553
|
|
|
491
554
|
try {
|
|
492
555
|
const ideMessages = {
|
|
493
|
-
cursor:
|
|
494
|
-
|
|
495
|
-
windsurf:
|
|
496
|
-
trae:
|
|
497
|
-
roo:
|
|
498
|
-
cline:
|
|
556
|
+
cursor: "Rules created in .cursor/rules/bmad/",
|
|
557
|
+
"claude-code": "Commands created in .claude/commands/BMad/",
|
|
558
|
+
windsurf: "Rules created in .windsurf/workflows/",
|
|
559
|
+
trae: "Rules created in.trae/rules/",
|
|
560
|
+
roo: "Custom modes created in .roomodes",
|
|
561
|
+
cline: "Rules created in .clinerules/",
|
|
499
562
|
};
|
|
500
563
|
|
|
501
564
|
// Setup each selected IDE
|
|
@@ -507,14 +570,14 @@ class V3ToV4Upgrader {
|
|
|
507
570
|
|
|
508
571
|
spinner.succeed(`IDE setup complete for ${selectedIdes.length} IDE(s)!`);
|
|
509
572
|
} catch {
|
|
510
|
-
spinner.fail(
|
|
511
|
-
console.error(chalk.yellow(
|
|
573
|
+
spinner.fail("IDE setup failed");
|
|
574
|
+
console.error(chalk.yellow("IDE setup failed, but upgrade is complete."));
|
|
512
575
|
}
|
|
513
576
|
}
|
|
514
577
|
|
|
515
578
|
showCompletionReport(projectPath, analysis) {
|
|
516
|
-
console.log(chalk.bold.green(
|
|
517
|
-
console.log(chalk.bold(
|
|
579
|
+
console.log(chalk.bold.green("\n✓ Upgrade Complete!\n"));
|
|
580
|
+
console.log(chalk.bold("Summary:"));
|
|
518
581
|
console.log(`- V3 files backed up to: .bmad-v3-backup/`);
|
|
519
582
|
console.log(`- V4 structure installed: .xiaoma-core/ (fresh from V4)`);
|
|
520
583
|
|
|
@@ -527,36 +590,50 @@ class V3ToV4Upgrader {
|
|
|
527
590
|
analysis.storyFiles.length;
|
|
528
591
|
console.log(
|
|
529
592
|
`- Documents migrated: ${totalDocs} files${
|
|
530
|
-
analysis.epicFiles.length > 0
|
|
593
|
+
analysis.epicFiles.length > 0
|
|
594
|
+
? ` + ${analysis.epicFiles.length} epics`
|
|
595
|
+
: ""
|
|
531
596
|
}`,
|
|
532
597
|
);
|
|
533
598
|
|
|
534
|
-
console.log(chalk.bold(
|
|
535
|
-
console.log(
|
|
536
|
-
|
|
599
|
+
console.log(chalk.bold("\nImportant Changes:"));
|
|
600
|
+
console.log(
|
|
601
|
+
"- The V4 agents (sm, dev, etc.) expect different file structures than V3",
|
|
602
|
+
);
|
|
603
|
+
console.log(
|
|
604
|
+
"- Your V3 bmad-agent content was NOT migrated (it's incompatible)",
|
|
605
|
+
);
|
|
537
606
|
if (analysis.epicFiles.length > 0) {
|
|
538
|
-
console.log(
|
|
607
|
+
console.log(
|
|
608
|
+
"- Epic files were found and copied - no PRD sharding needed!",
|
|
609
|
+
);
|
|
539
610
|
}
|
|
540
611
|
if (analysis.frontEndArchFile) {
|
|
541
612
|
console.log(
|
|
542
|
-
|
|
613
|
+
"- Front-end architecture found - V4 uses full-stack-architecture.md, migration needed",
|
|
543
614
|
);
|
|
544
615
|
}
|
|
545
616
|
if (analysis.uxSpecFile || analysis.uxPromptFile) {
|
|
546
|
-
console.log(
|
|
617
|
+
console.log(
|
|
618
|
+
"- UX/UI design files found and copied - ready for use with V4",
|
|
619
|
+
);
|
|
547
620
|
}
|
|
548
621
|
|
|
549
|
-
console.log(chalk.bold(
|
|
550
|
-
console.log(
|
|
622
|
+
console.log(chalk.bold("\nNext Steps:"));
|
|
623
|
+
console.log("1. Review your documents in the new docs/ folder");
|
|
551
624
|
console.log(
|
|
552
|
-
|
|
625
|
+
"2. Use @bmad-master agent to run the doc-migration-task to align your documents with V4 templates",
|
|
553
626
|
);
|
|
554
627
|
if (analysis.epicFiles.length === 0) {
|
|
555
|
-
console.log(
|
|
628
|
+
console.log(
|
|
629
|
+
"3. Use @bmad-master agent to shard the PRD to create epic files",
|
|
630
|
+
);
|
|
556
631
|
}
|
|
557
632
|
|
|
558
633
|
console.log(
|
|
559
|
-
chalk.dim(
|
|
634
|
+
chalk.dim(
|
|
635
|
+
"\nYour V3 backup is preserved in .bmad-v3-backup/ and can be restored if needed.",
|
|
636
|
+
),
|
|
560
637
|
);
|
|
561
638
|
}
|
|
562
639
|
|
|
@@ -584,38 +661,42 @@ class V3ToV4Upgrader {
|
|
|
584
661
|
}
|
|
585
662
|
|
|
586
663
|
async createPrdIndex(projectPath, analysis) {
|
|
587
|
-
const prdIndexPath = path.join(projectPath,
|
|
588
|
-
const prdPath = path.join(
|
|
664
|
+
const prdIndexPath = path.join(projectPath, "docs", "prd", "index.md");
|
|
665
|
+
const prdPath = path.join(
|
|
666
|
+
projectPath,
|
|
667
|
+
"docs",
|
|
668
|
+
analysis.prdFile || "prd.md",
|
|
669
|
+
);
|
|
589
670
|
|
|
590
|
-
let indexContent =
|
|
671
|
+
let indexContent = "# Product Requirements Document\n\n";
|
|
591
672
|
|
|
592
673
|
// Try to read the PRD to get the title and intro content
|
|
593
674
|
if (analysis.prdFile && (await this.pathExists(prdPath))) {
|
|
594
675
|
try {
|
|
595
|
-
const prdContent = await fs.readFile(prdPath,
|
|
596
|
-
const lines = prdContent.split(
|
|
676
|
+
const prdContent = await fs.readFile(prdPath, "utf8");
|
|
677
|
+
const lines = prdContent.split("\n");
|
|
597
678
|
|
|
598
679
|
// Find the first heading
|
|
599
|
-
const titleMatch = lines.find((line) => line.startsWith(
|
|
680
|
+
const titleMatch = lines.find((line) => line.startsWith("# "));
|
|
600
681
|
if (titleMatch) {
|
|
601
|
-
indexContent = titleMatch +
|
|
682
|
+
indexContent = titleMatch + "\n\n";
|
|
602
683
|
}
|
|
603
684
|
|
|
604
685
|
// Get any content before the first ## section
|
|
605
|
-
let introContent =
|
|
686
|
+
let introContent = "";
|
|
606
687
|
let foundFirstSection = false;
|
|
607
688
|
for (const line of lines) {
|
|
608
|
-
if (line.startsWith(
|
|
689
|
+
if (line.startsWith("## ")) {
|
|
609
690
|
foundFirstSection = true;
|
|
610
691
|
break;
|
|
611
692
|
}
|
|
612
|
-
if (!line.startsWith(
|
|
613
|
-
introContent += line +
|
|
693
|
+
if (!line.startsWith("# ")) {
|
|
694
|
+
introContent += line + "\n";
|
|
614
695
|
}
|
|
615
696
|
}
|
|
616
697
|
|
|
617
698
|
if (introContent.trim()) {
|
|
618
|
-
indexContent += introContent.trim() +
|
|
699
|
+
indexContent += introContent.trim() + "\n\n";
|
|
619
700
|
}
|
|
620
701
|
} catch {
|
|
621
702
|
// If we can't read the PRD, just use default content
|
|
@@ -623,7 +704,7 @@ class V3ToV4Upgrader {
|
|
|
623
704
|
}
|
|
624
705
|
|
|
625
706
|
// Add sections list
|
|
626
|
-
indexContent +=
|
|
707
|
+
indexContent += "## Sections\n\n";
|
|
627
708
|
|
|
628
709
|
// Sort epic files for consistent ordering
|
|
629
710
|
const sortedEpics = [...analysis.epicFiles].sort();
|
|
@@ -631,36 +712,36 @@ class V3ToV4Upgrader {
|
|
|
631
712
|
for (const epicFile of sortedEpics) {
|
|
632
713
|
// Extract epic name from filename
|
|
633
714
|
const epicName = epicFile
|
|
634
|
-
.replace(/\.md$/,
|
|
635
|
-
.replace(/^epic-?/i,
|
|
636
|
-
.replaceAll(
|
|
637
|
-
.replace(/^\d+\s*/,
|
|
715
|
+
.replace(/\.md$/, "")
|
|
716
|
+
.replace(/^epic-?/i, "")
|
|
717
|
+
.replaceAll("-", " ")
|
|
718
|
+
.replace(/^\d+\s*/, "") // Remove leading numbers
|
|
638
719
|
.trim();
|
|
639
720
|
|
|
640
721
|
const displayName = epicName.charAt(0).toUpperCase() + epicName.slice(1);
|
|
641
|
-
indexContent += `- [${displayName || epicFile.replace(
|
|
722
|
+
indexContent += `- [${displayName || epicFile.replace(".md", "")}](./${epicFile})\n`;
|
|
642
723
|
}
|
|
643
724
|
|
|
644
725
|
await fs.writeFile(prdIndexPath, indexContent);
|
|
645
726
|
}
|
|
646
727
|
|
|
647
728
|
async createInstallManifest(projectPath) {
|
|
648
|
-
const fileManager = require(
|
|
649
|
-
const { glob } = require(
|
|
729
|
+
const fileManager = require("../installer/lib/file-manager");
|
|
730
|
+
const { glob } = require("glob");
|
|
650
731
|
|
|
651
732
|
// Get all files in .xiaoma-core for the manifest
|
|
652
|
-
const bmadCorePath = path.join(projectPath,
|
|
653
|
-
const files = await glob(
|
|
733
|
+
const bmadCorePath = path.join(projectPath, ".xiaoma-core");
|
|
734
|
+
const files = await glob("**/*", {
|
|
654
735
|
cwd: bmadCorePath,
|
|
655
736
|
nodir: true,
|
|
656
|
-
ignore: [
|
|
737
|
+
ignore: ["**/.git/**", "**/node_modules/**"],
|
|
657
738
|
});
|
|
658
739
|
|
|
659
740
|
// Prepend .xiaoma-core/ to file paths for manifest
|
|
660
|
-
const manifestFiles = files.map((file) => path.join(
|
|
741
|
+
const manifestFiles = files.map((file) => path.join(".xiaoma-core", file));
|
|
661
742
|
|
|
662
743
|
const config = {
|
|
663
|
-
installType:
|
|
744
|
+
installType: "full",
|
|
664
745
|
agent: null,
|
|
665
746
|
ide: null, // Will be set if IDE setup is done later
|
|
666
747
|
};
|