mirror of
https://github.com/bmadcode/BMAD-METHOD.git
synced 2025-12-29 16:14:59 +00:00
* feat(bmgd): comprehensive BMGD module upgrade ## New Agents - **Game QA (GLaDOS)**: Game QA Architect + Test Automation Specialist - Engine-specific testing (Unity, Unreal, Godot) - Knowledge base with 15+ testing topics - Workflows: test-framework, test-design, automate, playtest-plan, performance-test, test-review - **Game Solo Dev (Indie)**: Elite Indie Game Developer + Quick Flow Specialist - Rapid prototyping and iteration focused - Quick-flow workflows for solo/small team development ## Production Workflow Alignment Aligned BMGD 4-production workflows with BMM 4-implementation: ### Removed Obsolete Workflows - story-done (merged into dev-story) - story-ready (merged into create-story) - story-context (merged into create-story) - epic-tech-context (no longer separate workflow) ### Added Workflows - sprint-status: View sprint progress, surface risks, recommend next action ### Updated Workflows (now standalone, copied from BMM) - code-review: Adversarial review with instructions.xml - correct-course: Sprint change management - create-story: Direct ready-for-dev marking - dev-story: TDD implementation with instructions.xml - retrospective: Epic completion review - sprint-planning: Sprint status generation ## Game Testing Architecture (gametest/) New knowledge base for game-specific testing: - qa-index.csv: Knowledge fragment index - 15 knowledge files covering: - Engine-specific: Unity, Unreal, Godot testing - Game-specific: Playtesting, balance, save systems, multiplayer - Platform: Certification (TRC/XR), localization, input - General QA: Automation, performance, regression, smoke tests ## Quick-Flow Workflows (bmgd-quick-flow/) - quick-prototype: Rapid mechanic testing - quick-dev: Flexible feature implementation ## Documentation Complete documentation suite in docs/: - README.md: Documentation index - quick-start.md: Getting started guide - agents-guide.md: All 6 agents reference - workflows-guide.md: Complete workflow reference - quick-flow-guide.md: Rapid development guide - game-types-guide.md: 24 game type templates - glossary.md: Game dev terminology - troubleshooting.md: Common issues ## Teams & Installer - Updated team-gamedev.yaml with all 6 agents and workflows - Updated default-party.csv with Game QA and Game Solo Dev - Created _module-installer/ with: - installer.js: Creates directories, logs engine selection - platform-specifics/: Claude Code and Windsurf handlers ## Agent Updates All agents now reference standalone BMGD workflows: - game-architect: correct-course → BMGD - game-dev: dev-story, code-review → BMGD - game-scrum-master: All production workflows → BMGD - game-solo-dev: code-review → BMGD ## Module Configuration - Added sprint_artifacts alias for workflow compatibility - All workflows use bmgd/config.yaml * fix(bmgd): update sprint-status workflow to reference bmgd instead of bmm Replace all /bmad:bmm:workflows references with /bmad:bmgd:workflows in the sprint-status workflow instructions. * feat(bmgd): add workflow-status and create-tech-spec workflows Add BMGD-native workflow-status and create-tech-spec workflows, replacing all BMM references with BMGD paths. ## New Workflows ### workflow-status - Multi-mode status checker for game projects - Game-specific project levels (Game Jam → AAA) - Workflow paths: gamedev-greenfield, gamedev-brownfield, quickflow-greenfield, quickflow-brownfield - Init workflow for new game project setup ### create-tech-spec - Game-focused spec engineering workflow - Engine-aware (Unity/Unreal/Godot) - Performance and gameplay feel considerations ## Agent Updates Updated all BMGD agents to reference BMGD workflows: - game-architect, game-designer, game-dev, game-qa, game-scrum-master, game-solo-dev All agents now use /bmad:bmgd:workflows instead of /bmad:bmm:workflows * fix(bmgd): address PR review findings and enhance playtesting docs ## PR Review Fixes (F1-F20) ### Configuration & Naming - F1: Changed user_skill_level to game_dev_experience in module.yaml - F3: Renamed gametest/framework to gametest/test-framework ### Cleanup - F2: Deleted 4 orphaned root-level template files - F6: Removed duplicate code block in create-story/instructions.xml - F9: Removed trailing empty line from qa-index.csv - F20: Deleted orphaned docs/unnamed.jpg ### Installer Improvements - F7: Simplified platform handler stubs (removed unused code) - F8: Added return value checking for platform handlers - F13: Added path traversal validation (isWithinProjectRoot) - F18: Added type validation for config string values ### Agent Fixes - F10: Added workflow-status and advanced-elicitation to game-solo-dev - F12: Fixed "GOTO step 2a" → "GOTO step 2" references - F14: Removed duplicate project-context.md from principles in 5 agents ### Workflow Updates - F17: Added input_file_patterns to playtest-plan workflow ### Documentation - F4-F5: Updated quick-start.md with 6 agents and fixed table - Updated workflows-guide.md with test-framework reference ### Knowledge Base Updates (from earlier CodeRabbit comments) - Updated unity-testing.md to Test Framework 1.6.0 - Fixed unreal-testing.md (MarkAsGarbage, UnrealEditor.exe) - Added FVerifyPlayerMoved note to smoke-testing.md - Fixed certification-testing.md table formatting ### Playtesting Documentation Enhancement - Added "Playtesting by Game Type" section (7 genres) - Added "Processing Feedback Effectively" section - Expanded from ~138 to ~340 lines * refactor(bmgd): use exec for step-file workflows and multi format Update agent menu items to use correct notation for step-file workflows: **game-designer.agent.yaml:** - Convert 4 step-file workflows to multi format with shortcodes: - [BG] brainstorm-game - [GB] create-game-brief - [GDD] create-gdd - [ND] narrative - Changed from workflow: .yaml to exec: .md **game-architect.agent.yaml:** - Changed create-architecture from workflow: to exec: with workflow.md --------- Co-authored-by: Scott Jennings <scott.jennings+CIGINT@cloudimperiumgames.com>
161 lines
6.4 KiB
JavaScript
161 lines
6.4 KiB
JavaScript
const fs = require('fs-extra');
|
|
const path = require('node:path');
|
|
const chalk = require('chalk');
|
|
const platformCodes = require(path.join(__dirname, '../../../../tools/cli/lib/platform-codes'));
|
|
|
|
/**
|
|
* Validate that a resolved path is within the project root (prevents path traversal)
|
|
* @param {string} resolvedPath - The fully resolved absolute path
|
|
* @param {string} projectRoot - The project root directory
|
|
* @returns {boolean} - True if path is within project root
|
|
*/
|
|
function isWithinProjectRoot(resolvedPath, projectRoot) {
|
|
const normalizedResolved = path.normalize(resolvedPath);
|
|
const normalizedRoot = path.normalize(projectRoot);
|
|
return normalizedResolved.startsWith(normalizedRoot + path.sep) || normalizedResolved === normalizedRoot;
|
|
}
|
|
|
|
/**
|
|
* BMGD Module Installer
|
|
* Standard module installer function that executes after IDE installations
|
|
*
|
|
* @param {Object} options - Installation options
|
|
* @param {string} options.projectRoot - The root directory of the target project
|
|
* @param {Object} options.config - Module configuration from module.yaml
|
|
* @param {Array<string>} options.installedIDEs - Array of IDE codes that were installed
|
|
* @param {Object} options.logger - Logger instance for output
|
|
* @returns {Promise<boolean>} - Success status
|
|
*/
|
|
async function install(options) {
|
|
const { projectRoot, config, installedIDEs, logger } = options;
|
|
|
|
try {
|
|
logger.log(chalk.blue('🎮 Installing BMGD Module...'));
|
|
|
|
// Create planning artifacts directory (for GDDs, game briefs, architecture)
|
|
if (config['planning_artifacts'] && typeof config['planning_artifacts'] === 'string') {
|
|
// Strip project-root prefix variations
|
|
const planningConfig = config['planning_artifacts'].replace(/^\{project-root\}\/?/, '');
|
|
const planningPath = path.join(projectRoot, planningConfig);
|
|
if (!isWithinProjectRoot(planningPath, projectRoot)) {
|
|
logger.warn(chalk.yellow(`Warning: planning_artifacts path escapes project root, skipping: ${planningConfig}`));
|
|
} else if (!(await fs.pathExists(planningPath))) {
|
|
logger.log(chalk.yellow(`Creating game planning artifacts directory: ${planningConfig}`));
|
|
await fs.ensureDir(planningPath);
|
|
}
|
|
}
|
|
|
|
// Create implementation artifacts directory (sprint status, stories, reviews)
|
|
// Check both implementation_artifacts and sprint_artifacts for compatibility
|
|
const implConfig = config['implementation_artifacts'] || config['sprint_artifacts'];
|
|
if (implConfig && typeof implConfig === 'string') {
|
|
// Strip project-root prefix variations
|
|
const implConfigClean = implConfig.replace(/^\{project-root\}\/?/, '');
|
|
const implPath = path.join(projectRoot, implConfigClean);
|
|
if (!isWithinProjectRoot(implPath, projectRoot)) {
|
|
logger.warn(chalk.yellow(`Warning: implementation_artifacts path escapes project root, skipping: ${implConfigClean}`));
|
|
} else if (!(await fs.pathExists(implPath))) {
|
|
logger.log(chalk.yellow(`Creating implementation artifacts directory: ${implConfigClean}`));
|
|
await fs.ensureDir(implPath);
|
|
}
|
|
}
|
|
|
|
// Create project knowledge directory
|
|
if (config['project_knowledge'] && typeof config['project_knowledge'] === 'string') {
|
|
// Strip project-root prefix variations
|
|
const knowledgeConfig = config['project_knowledge'].replace(/^\{project-root\}\/?/, '');
|
|
const knowledgePath = path.join(projectRoot, knowledgeConfig);
|
|
if (!isWithinProjectRoot(knowledgePath, projectRoot)) {
|
|
logger.warn(chalk.yellow(`Warning: project_knowledge path escapes project root, skipping: ${knowledgeConfig}`));
|
|
} else if (!(await fs.pathExists(knowledgePath))) {
|
|
logger.log(chalk.yellow(`Creating project knowledge directory: ${knowledgeConfig}`));
|
|
await fs.ensureDir(knowledgePath);
|
|
}
|
|
}
|
|
|
|
// Log selected game engine(s)
|
|
if (config['primary_platform']) {
|
|
const platforms = Array.isArray(config['primary_platform']) ? config['primary_platform'] : [config['primary_platform']];
|
|
|
|
const platformNames = platforms.map((p) => {
|
|
switch (p) {
|
|
case 'unity': {
|
|
return 'Unity';
|
|
}
|
|
case 'unreal': {
|
|
return 'Unreal Engine';
|
|
}
|
|
case 'godot': {
|
|
return 'Godot';
|
|
}
|
|
default: {
|
|
return p;
|
|
}
|
|
}
|
|
});
|
|
|
|
logger.log(chalk.cyan(`Game engine support configured for: ${platformNames.join(', ')}`));
|
|
}
|
|
|
|
// Handle IDE-specific configurations if needed
|
|
if (installedIDEs && installedIDEs.length > 0) {
|
|
logger.log(chalk.cyan(`Configuring BMGD for IDEs: ${installedIDEs.join(', ')}`));
|
|
|
|
for (const ide of installedIDEs) {
|
|
await configureForIDE(ide, projectRoot, config, logger);
|
|
}
|
|
}
|
|
|
|
logger.log(chalk.green('✓ BMGD Module installation complete'));
|
|
logger.log(chalk.dim(' Game development workflows ready'));
|
|
logger.log(chalk.dim(' Agents: Game Designer, Game Dev, Game Architect, Game SM, Game QA, Game Solo Dev'));
|
|
|
|
return true;
|
|
} catch (error) {
|
|
logger.error(chalk.red(`Error installing BMGD module: ${error.message}`));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Configure BMGD module for specific platform/IDE
|
|
* @private
|
|
*/
|
|
async function configureForIDE(ide, projectRoot, config, logger) {
|
|
// Validate platform code
|
|
if (!platformCodes.isValidPlatform(ide)) {
|
|
logger.warn(chalk.yellow(` Warning: Unknown platform code '${ide}'. Skipping BMGD configuration.`));
|
|
return;
|
|
}
|
|
|
|
const platformName = platformCodes.getDisplayName(ide);
|
|
|
|
// Try to load platform-specific handler
|
|
const platformSpecificPath = path.join(__dirname, 'platform-specifics', `${ide}.js`);
|
|
|
|
try {
|
|
if (await fs.pathExists(platformSpecificPath)) {
|
|
const platformHandler = require(platformSpecificPath);
|
|
|
|
if (typeof platformHandler.install === 'function') {
|
|
const success = await platformHandler.install({
|
|
projectRoot,
|
|
config,
|
|
logger,
|
|
platformInfo: platformCodes.getPlatform(ide),
|
|
});
|
|
if (!success) {
|
|
logger.warn(chalk.yellow(` Warning: BMGD platform handler for ${platformName} returned failure`));
|
|
}
|
|
}
|
|
} else {
|
|
// No platform-specific handler for this IDE
|
|
logger.log(chalk.dim(` No BMGD-specific configuration for ${platformName}`));
|
|
}
|
|
} catch (error) {
|
|
logger.warn(chalk.yellow(` Warning: Could not load BMGD platform-specific handler for ${platformName}: ${error.message}`));
|
|
}
|
|
}
|
|
|
|
module.exports = { install };
|