bmad-method 4.28.0 → 4.29.0
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 +7 -0
- package/bmad-core/agents/bmad-master.md +0 -2
- package/bmad-core/agents/bmad-orchestrator.md +0 -3
- package/bmad-core/core-config.yaml +1 -5
- package/bmad-core/data/bmad-kb.md +2 -2
- package/bmad-core/tasks/correct-course.md +9 -12
- package/bmad-core/tasks/create-brownfield-story.md +10 -61
- package/bmad-core/tasks/create-deep-research-prompt.md +5 -17
- package/bmad-core/tasks/create-next-story.md +3 -4
- package/bmad-core/tasks/document-project.md +37 -13
- package/bmad-core/tasks/facilitate-brainstorming-session.md +1 -1
- package/bmad-core/tasks/generate-ai-frontend-prompt.md +1 -1
- package/bmad-core/tasks/kb-mode-interaction.md +8 -3
- package/bmad-core/tasks/review-story.md +3 -3
- package/bmad-core/tasks/shard-doc.md +5 -9
- package/common/tasks/create-doc.md +4 -0
- package/dist/agents/analyst.txt +43 -31
- package/dist/agents/architect.txt +42 -30
- package/dist/agents/bmad-master.txt +61 -602
- package/dist/agents/bmad-orchestrator.txt +7 -548
- package/dist/agents/pm.txt +19 -38
- package/dist/agents/po.txt +14 -21
- package/dist/agents/qa.txt +3 -3
- package/dist/agents/sm.txt +11 -15
- package/dist/agents/ux-expert.txt +6 -18
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +5 -17
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +50 -579
- package/dist/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.txt +5 -17
- package/dist/teams/team-all.txt +70 -607
- package/dist/teams/team-fullstack.txt +65 -601
- package/dist/teams/team-ide-minimal.txt +26 -575
- package/dist/teams/team-no-ui.txt +64 -600
- package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +1 -0
- package/expansion-packs/bmad-creator-tools/config.yaml +1 -0
- package/expansion-packs/bmad-infrastructure-devops/config.yaml +1 -0
- package/package.json +1 -1
- package/tools/installer/lib/ide-setup.js +325 -12
- package/tools/installer/package.json +1 -1
- package/bmad-core/tasks/create-workflow-plan.md +0 -289
- package/bmad-core/tasks/doc-migration-task.md +0 -143
- package/bmad-core/tasks/update-workflow-plan.md +0 -248
package/package.json
CHANGED
|
@@ -131,19 +131,64 @@ class IdeSetup {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
async setupClaudeCode(installDir, selectedAgent) {
|
|
134
|
-
|
|
135
|
-
const
|
|
134
|
+
// Setup bmad-core commands
|
|
135
|
+
const coreSlashPrefix = await this.getCoreSlashPrefix(installDir);
|
|
136
|
+
const coreAgents = selectedAgent ? [selectedAgent] : await this.getCoreAgentIds(installDir);
|
|
137
|
+
const coreTasks = await this.getCoreTaskIds(installDir);
|
|
138
|
+
await this.setupClaudeCodeForPackage(installDir, "core", coreSlashPrefix, coreAgents, coreTasks, ".bmad-core");
|
|
139
|
+
|
|
140
|
+
// Setup expansion pack commands
|
|
141
|
+
const expansionPacks = await this.getInstalledExpansionPacks(installDir);
|
|
142
|
+
for (const packInfo of expansionPacks) {
|
|
143
|
+
const packSlashPrefix = await this.getExpansionPackSlashPrefix(packInfo.path);
|
|
144
|
+
const packAgents = await this.getExpansionPackAgents(packInfo.path);
|
|
145
|
+
const packTasks = await this.getExpansionPackTasks(packInfo.path);
|
|
146
|
+
|
|
147
|
+
if (packAgents.length > 0 || packTasks.length > 0) {
|
|
148
|
+
// Use the actual directory name where the expansion pack is installed
|
|
149
|
+
const rootPath = path.relative(installDir, packInfo.path);
|
|
150
|
+
await this.setupClaudeCodeForPackage(installDir, packInfo.name, packSlashPrefix, packAgents, packTasks, rootPath);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
136
153
|
|
|
137
|
-
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
138
156
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
157
|
+
async setupClaudeCodeForPackage(installDir, packageName, slashPrefix, agentIds, taskIds, rootPath) {
|
|
158
|
+
const commandsBaseDir = path.join(installDir, ".claude", "commands", slashPrefix);
|
|
159
|
+
const agentsDir = path.join(commandsBaseDir, "agents");
|
|
160
|
+
const tasksDir = path.join(commandsBaseDir, "tasks");
|
|
161
|
+
|
|
162
|
+
// Ensure directories exist
|
|
163
|
+
await fileManager.ensureDirectory(agentsDir);
|
|
164
|
+
await fileManager.ensureDirectory(tasksDir);
|
|
165
|
+
|
|
166
|
+
// Setup agents
|
|
167
|
+
for (const agentId of agentIds) {
|
|
168
|
+
// Find the agent file - for expansion packs, prefer the expansion pack version
|
|
169
|
+
let agentPath;
|
|
170
|
+
if (packageName !== "core") {
|
|
171
|
+
// For expansion packs, first try to find the agent in the expansion pack directory
|
|
172
|
+
const expansionPackPath = path.join(installDir, rootPath, "agents", `${agentId}.md`);
|
|
173
|
+
if (await fileManager.pathExists(expansionPackPath)) {
|
|
174
|
+
agentPath = expansionPackPath;
|
|
175
|
+
} else {
|
|
176
|
+
// Fall back to core if not found in expansion pack
|
|
177
|
+
agentPath = await this.findAgentPath(agentId, installDir);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
// For core, use the normal search
|
|
181
|
+
agentPath = await this.findAgentPath(agentId, installDir);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const commandPath = path.join(agentsDir, `${agentId}.md`);
|
|
143
185
|
|
|
144
186
|
if (agentPath) {
|
|
145
187
|
// Create command file with agent content
|
|
146
|
-
|
|
188
|
+
let agentContent = await fileManager.readFile(agentPath);
|
|
189
|
+
|
|
190
|
+
// Replace {root} placeholder with the appropriate root path for this context
|
|
191
|
+
agentContent = agentContent.replace(/{root}/g, rootPath);
|
|
147
192
|
|
|
148
193
|
// Add command header
|
|
149
194
|
let commandContent = `# /${agentId} Command\n\n`;
|
|
@@ -151,13 +196,50 @@ class IdeSetup {
|
|
|
151
196
|
commandContent += agentContent;
|
|
152
197
|
|
|
153
198
|
await fileManager.writeFile(commandPath, commandContent);
|
|
154
|
-
console.log(chalk.green(`✓ Created command: /${agentId}`));
|
|
199
|
+
console.log(chalk.green(`✓ Created agent command: /${agentId}`));
|
|
155
200
|
}
|
|
156
201
|
}
|
|
157
202
|
|
|
158
|
-
|
|
203
|
+
// Setup tasks
|
|
204
|
+
for (const taskId of taskIds) {
|
|
205
|
+
// Find the task file - for expansion packs, prefer the expansion pack version
|
|
206
|
+
let taskPath;
|
|
207
|
+
if (packageName !== "core") {
|
|
208
|
+
// For expansion packs, first try to find the task in the expansion pack directory
|
|
209
|
+
const expansionPackPath = path.join(installDir, rootPath, "tasks", `${taskId}.md`);
|
|
210
|
+
if (await fileManager.pathExists(expansionPackPath)) {
|
|
211
|
+
taskPath = expansionPackPath;
|
|
212
|
+
} else {
|
|
213
|
+
// Fall back to core if not found in expansion pack
|
|
214
|
+
taskPath = await this.findTaskPath(taskId, installDir);
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
// For core, use the normal search
|
|
218
|
+
taskPath = await this.findTaskPath(taskId, installDir);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const commandPath = path.join(tasksDir, `${taskId}.md`);
|
|
159
222
|
|
|
160
|
-
|
|
223
|
+
if (taskPath) {
|
|
224
|
+
// Create command file with task content
|
|
225
|
+
let taskContent = await fileManager.readFile(taskPath);
|
|
226
|
+
|
|
227
|
+
// Replace {root} placeholder with the appropriate root path for this context
|
|
228
|
+
taskContent = taskContent.replace(/{root}/g, rootPath);
|
|
229
|
+
|
|
230
|
+
// Add command header
|
|
231
|
+
let commandContent = `# /${taskId} Task\n\n`;
|
|
232
|
+
commandContent += `When this command is used, execute the following task:\n\n`;
|
|
233
|
+
commandContent += taskContent;
|
|
234
|
+
|
|
235
|
+
await fileManager.writeFile(commandPath, commandContent);
|
|
236
|
+
console.log(chalk.green(`✓ Created task command: /${taskId}`));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
console.log(chalk.green(`\n✓ Created Claude Code commands for ${packageName} in ${commandsBaseDir}`));
|
|
241
|
+
console.log(chalk.dim(` - Agents in: ${agentsDir}`));
|
|
242
|
+
console.log(chalk.dim(` - Tasks in: ${tasksDir}`));
|
|
161
243
|
}
|
|
162
244
|
|
|
163
245
|
async setupWindsurf(installDir, selectedAgent) {
|
|
@@ -311,6 +393,49 @@ class IdeSetup {
|
|
|
311
393
|
return [...new Set(allAgentIds)];
|
|
312
394
|
}
|
|
313
395
|
|
|
396
|
+
async getCoreAgentIds(installDir) {
|
|
397
|
+
const allAgentIds = [];
|
|
398
|
+
|
|
399
|
+
// Check core agents in .bmad-core or root only
|
|
400
|
+
let agentsDir = path.join(installDir, ".bmad-core", "agents");
|
|
401
|
+
if (!(await fileManager.pathExists(agentsDir))) {
|
|
402
|
+
agentsDir = path.join(installDir, "bmad-core", "agents");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (await fileManager.pathExists(agentsDir)) {
|
|
406
|
+
const glob = require("glob");
|
|
407
|
+
const agentFiles = glob.sync("*.md", { cwd: agentsDir });
|
|
408
|
+
allAgentIds.push(...agentFiles.map((file) => path.basename(file, ".md")));
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return [...new Set(allAgentIds)];
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
async getCoreTaskIds(installDir) {
|
|
415
|
+
const allTaskIds = [];
|
|
416
|
+
|
|
417
|
+
// Check core tasks in .bmad-core or root only
|
|
418
|
+
let tasksDir = path.join(installDir, ".bmad-core", "tasks");
|
|
419
|
+
if (!(await fileManager.pathExists(tasksDir))) {
|
|
420
|
+
tasksDir = path.join(installDir, "bmad-core", "tasks");
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (await fileManager.pathExists(tasksDir)) {
|
|
424
|
+
const glob = require("glob");
|
|
425
|
+
const taskFiles = glob.sync("*.md", { cwd: tasksDir });
|
|
426
|
+
allTaskIds.push(...taskFiles.map((file) => path.basename(file, ".md")));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Check common tasks
|
|
430
|
+
const commonTasksDir = path.join(installDir, "common", "tasks");
|
|
431
|
+
if (await fileManager.pathExists(commonTasksDir)) {
|
|
432
|
+
const commonTaskFiles = glob.sync("*.md", { cwd: commonTasksDir });
|
|
433
|
+
allTaskIds.push(...commonTaskFiles.map((file) => path.basename(file, ".md")));
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return [...new Set(allTaskIds)];
|
|
437
|
+
}
|
|
438
|
+
|
|
314
439
|
async getAgentTitle(agentId, installDir) {
|
|
315
440
|
// Try to find the agent file in various locations
|
|
316
441
|
const possiblePaths = [
|
|
@@ -350,6 +475,194 @@ class IdeSetup {
|
|
|
350
475
|
).join(' ');
|
|
351
476
|
}
|
|
352
477
|
|
|
478
|
+
async getAllTaskIds(installDir) {
|
|
479
|
+
const glob = require("glob");
|
|
480
|
+
const allTaskIds = [];
|
|
481
|
+
|
|
482
|
+
// Check core tasks in .bmad-core or root
|
|
483
|
+
let tasksDir = path.join(installDir, ".bmad-core", "tasks");
|
|
484
|
+
if (!(await fileManager.pathExists(tasksDir))) {
|
|
485
|
+
tasksDir = path.join(installDir, "bmad-core", "tasks");
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (await fileManager.pathExists(tasksDir)) {
|
|
489
|
+
const taskFiles = glob.sync("*.md", { cwd: tasksDir });
|
|
490
|
+
allTaskIds.push(...taskFiles.map((file) => path.basename(file, ".md")));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Check common tasks
|
|
494
|
+
const commonTasksDir = path.join(installDir, "common", "tasks");
|
|
495
|
+
if (await fileManager.pathExists(commonTasksDir)) {
|
|
496
|
+
const commonTaskFiles = glob.sync("*.md", { cwd: commonTasksDir });
|
|
497
|
+
allTaskIds.push(...commonTaskFiles.map((file) => path.basename(file, ".md")));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Also check for expansion pack tasks in dot folders
|
|
501
|
+
const expansionDirs = glob.sync(".*/tasks", { cwd: installDir });
|
|
502
|
+
for (const expDir of expansionDirs) {
|
|
503
|
+
const fullExpDir = path.join(installDir, expDir);
|
|
504
|
+
const expTaskFiles = glob.sync("*.md", { cwd: fullExpDir });
|
|
505
|
+
allTaskIds.push(...expTaskFiles.map((file) => path.basename(file, ".md")));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Check expansion-packs folder tasks
|
|
509
|
+
const expansionPacksDir = path.join(installDir, "expansion-packs");
|
|
510
|
+
if (await fileManager.pathExists(expansionPacksDir)) {
|
|
511
|
+
const expPackDirs = glob.sync("*/tasks", { cwd: expansionPacksDir });
|
|
512
|
+
for (const expDir of expPackDirs) {
|
|
513
|
+
const fullExpDir = path.join(expansionPacksDir, expDir);
|
|
514
|
+
const expTaskFiles = glob.sync("*.md", { cwd: fullExpDir });
|
|
515
|
+
allTaskIds.push(...expTaskFiles.map((file) => path.basename(file, ".md")));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Remove duplicates
|
|
520
|
+
return [...new Set(allTaskIds)];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
async findTaskPath(taskId, installDir) {
|
|
524
|
+
// Try to find the task file in various locations
|
|
525
|
+
const possiblePaths = [
|
|
526
|
+
path.join(installDir, ".bmad-core", "tasks", `${taskId}.md`),
|
|
527
|
+
path.join(installDir, "bmad-core", "tasks", `${taskId}.md`),
|
|
528
|
+
path.join(installDir, "common", "tasks", `${taskId}.md`)
|
|
529
|
+
];
|
|
530
|
+
|
|
531
|
+
// Also check expansion pack directories
|
|
532
|
+
const glob = require("glob");
|
|
533
|
+
|
|
534
|
+
// Check dot folder expansion packs
|
|
535
|
+
const expansionDirs = glob.sync(".*/tasks", { cwd: installDir });
|
|
536
|
+
for (const expDir of expansionDirs) {
|
|
537
|
+
possiblePaths.push(path.join(installDir, expDir, `${taskId}.md`));
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Check expansion-packs folder
|
|
541
|
+
const expansionPacksDir = path.join(installDir, "expansion-packs");
|
|
542
|
+
if (await fileManager.pathExists(expansionPacksDir)) {
|
|
543
|
+
const expPackDirs = glob.sync("*/tasks", { cwd: expansionPacksDir });
|
|
544
|
+
for (const expDir of expPackDirs) {
|
|
545
|
+
possiblePaths.push(path.join(expansionPacksDir, expDir, `${taskId}.md`));
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
for (const taskPath of possiblePaths) {
|
|
550
|
+
if (await fileManager.pathExists(taskPath)) {
|
|
551
|
+
return taskPath;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
async getCoreSlashPrefix(installDir) {
|
|
559
|
+
try {
|
|
560
|
+
const coreConfigPath = path.join(installDir, ".bmad-core", "core-config.yaml");
|
|
561
|
+
if (!(await fileManager.pathExists(coreConfigPath))) {
|
|
562
|
+
// Try bmad-core directory
|
|
563
|
+
const altConfigPath = path.join(installDir, "bmad-core", "core-config.yaml");
|
|
564
|
+
if (await fileManager.pathExists(altConfigPath)) {
|
|
565
|
+
const configContent = await fileManager.readFile(altConfigPath);
|
|
566
|
+
const config = yaml.load(configContent);
|
|
567
|
+
return config.slashPrefix || "BMad";
|
|
568
|
+
}
|
|
569
|
+
return "BMad"; // fallback
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const configContent = await fileManager.readFile(coreConfigPath);
|
|
573
|
+
const config = yaml.load(configContent);
|
|
574
|
+
return config.slashPrefix || "BMad";
|
|
575
|
+
} catch (error) {
|
|
576
|
+
console.warn(`Failed to read core slashPrefix, using default 'BMad': ${error.message}`);
|
|
577
|
+
return "BMad";
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
async getInstalledExpansionPacks(installDir) {
|
|
582
|
+
const expansionPacks = [];
|
|
583
|
+
|
|
584
|
+
// Check for dot-prefixed expansion packs in install directory
|
|
585
|
+
const glob = require("glob");
|
|
586
|
+
const dotExpansions = glob.sync(".bmad-*", { cwd: installDir });
|
|
587
|
+
|
|
588
|
+
for (const dotExpansion of dotExpansions) {
|
|
589
|
+
if (dotExpansion !== ".bmad-core") {
|
|
590
|
+
const packPath = path.join(installDir, dotExpansion);
|
|
591
|
+
const packName = dotExpansion.substring(1); // remove the dot
|
|
592
|
+
expansionPacks.push({
|
|
593
|
+
name: packName,
|
|
594
|
+
path: packPath
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Check for expansion-packs directory style
|
|
600
|
+
const expansionPacksDir = path.join(installDir, "expansion-packs");
|
|
601
|
+
if (await fileManager.pathExists(expansionPacksDir)) {
|
|
602
|
+
const packDirs = glob.sync("*", { cwd: expansionPacksDir });
|
|
603
|
+
|
|
604
|
+
for (const packDir of packDirs) {
|
|
605
|
+
const packPath = path.join(expansionPacksDir, packDir);
|
|
606
|
+
if ((await fileManager.pathExists(packPath)) &&
|
|
607
|
+
(await fileManager.pathExists(path.join(packPath, "config.yaml")))) {
|
|
608
|
+
expansionPacks.push({
|
|
609
|
+
name: packDir,
|
|
610
|
+
path: packPath
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
return expansionPacks;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
async getExpansionPackSlashPrefix(packPath) {
|
|
620
|
+
try {
|
|
621
|
+
const configPath = path.join(packPath, "config.yaml");
|
|
622
|
+
if (await fileManager.pathExists(configPath)) {
|
|
623
|
+
const configContent = await fileManager.readFile(configPath);
|
|
624
|
+
const config = yaml.load(configContent);
|
|
625
|
+
return config.slashPrefix || path.basename(packPath);
|
|
626
|
+
}
|
|
627
|
+
} catch (error) {
|
|
628
|
+
console.warn(`Failed to read expansion pack slashPrefix from ${packPath}: ${error.message}`);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return path.basename(packPath); // fallback to directory name
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
async getExpansionPackAgents(packPath) {
|
|
635
|
+
const agentsDir = path.join(packPath, "agents");
|
|
636
|
+
if (!(await fileManager.pathExists(agentsDir))) {
|
|
637
|
+
return [];
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
try {
|
|
641
|
+
const glob = require("glob");
|
|
642
|
+
const agentFiles = glob.sync("*.md", { cwd: agentsDir });
|
|
643
|
+
return agentFiles.map(file => path.basename(file, ".md"));
|
|
644
|
+
} catch (error) {
|
|
645
|
+
console.warn(`Failed to read expansion pack agents from ${packPath}: ${error.message}`);
|
|
646
|
+
return [];
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
async getExpansionPackTasks(packPath) {
|
|
651
|
+
const tasksDir = path.join(packPath, "tasks");
|
|
652
|
+
if (!(await fileManager.pathExists(tasksDir))) {
|
|
653
|
+
return [];
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
try {
|
|
657
|
+
const glob = require("glob");
|
|
658
|
+
const taskFiles = glob.sync("*.md", { cwd: tasksDir });
|
|
659
|
+
return taskFiles.map(file => path.basename(file, ".md"));
|
|
660
|
+
} catch (error) {
|
|
661
|
+
console.warn(`Failed to read expansion pack tasks from ${packPath}: ${error.message}`);
|
|
662
|
+
return [];
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
353
666
|
async setupRoo(installDir, selectedAgent) {
|
|
354
667
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
355
668
|
|
|
@@ -509,7 +822,7 @@ class IdeSetup {
|
|
|
509
822
|
return true;
|
|
510
823
|
}
|
|
511
824
|
|
|
512
|
-
async setupGeminiCli(installDir
|
|
825
|
+
async setupGeminiCli(installDir) {
|
|
513
826
|
await initializeModules();
|
|
514
827
|
const geminiDir = path.join(installDir, ".gemini");
|
|
515
828
|
const bmadMethodDir = path.join(geminiDir, "bmad-method");
|