From dd8c54cc9f6075d501c47394e45479deb67dd301 Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Tue, 27 Jan 2026 23:08:26 -0800 Subject: [PATCH] no double agent files and .agent.md file extensions. --- .../cli/installers/lib/ide/_config-driven.js | 8 +- .../installers/lib/ide/platform-codes.yaml | 172 ++++++++---------- .../lib/ide/shared/agent-command-generator.js | 6 +- .../installers/lib/ide/shared/path-utils.js | 65 ++++--- .../ide/shared/task-tool-command-generator.js | 2 +- .../ide/shared/workflow-command-generator.js | 2 +- 6 files changed, 126 insertions(+), 129 deletions(-) diff --git a/tools/cli/installers/lib/ide/_config-driven.js b/tools/cli/installers/lib/ide/_config-driven.js index 4ebd173e..022bff7b 100644 --- a/tools/cli/installers/lib/ide/_config-driven.js +++ b/tools/cli/installers/lib/ide/_config-driven.js @@ -352,14 +352,14 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} // Clean up potential double extensions from source files (e.g. .yaml.md -> .md) const baseName = standardName.replace(/\.(yaml|yml)\.md$/, '.md'); - // If using default markdown, preserve original behavior (keeps .agent.md suffix) + // If using default markdown, preserve the bmad-agent- prefix for agents if (extension === '.md') { return baseName; } - // For other extensions (e.g., .toml), remove .agent suffix as well - // Gemini doesn't support double-dot patterns like .agent.toml - return baseName.replace(/(\.agent)?(\.md|\.yaml|\.yml)$/, extension); + // For other extensions (e.g., .toml), replace .md extension + // Note: agent prefix is preserved even with non-markdown extensions + return baseName.replace(/\.md$/, extension); } /** diff --git a/tools/cli/installers/lib/ide/platform-codes.yaml b/tools/cli/installers/lib/ide/platform-codes.yaml index e3aea054..6a9078a8 100644 --- a/tools/cli/installers/lib/ide/platform-codes.yaml +++ b/tools/cli/installers/lib/ide/platform-codes.yaml @@ -14,18 +14,14 @@ # installer: Installation configuration (optional - omit for custom installers) platforms: - # ============================================================================ - # CLI Tools - # ============================================================================ - - claude-code: - name: "Claude Code" - preferred: true - category: cli - description: "Anthropic's official CLI for Claude" + antigravity: + name: "Google Antigravity" + preferred: false + category: ide + description: "Google's AI development environment" installer: - target_dir: .claude/commands - template_type: default + target_dir: .agent/workflows + template_type: antigravity auggie: name: "Auggie" @@ -36,37 +32,15 @@ platforms: target_dir: .augment/commands template_type: default - gemini: - name: "Gemini CLI" - preferred: false + claude-code: + name: "Claude Code" + preferred: true category: cli - description: "Google's CLI for Gemini" + description: "Anthropic's official CLI for Claude" installer: - target_dir: .gemini/commands - template_type: gemini - - # ============================================================================ - # IDEs - # ============================================================================ - - cursor: - name: "Cursor" - preferred: true - category: ide - description: "AI-first code editor" - installer: - target_dir: .cursor/commands + target_dir: .claude/commands template_type: default - windsurf: - name: "Windsurf" - preferred: true - category: ide - description: "AI-powered IDE with cascade flows" - installer: - target_dir: .windsurf/workflows - template_type: windsurf - cline: name: "Cline" preferred: false @@ -76,15 +50,40 @@ platforms: target_dir: .clinerules/workflows template_type: windsurf - roo: - name: "Roo Cline" + codex: + name: "Codex" + preferred: false + category: cli + description: "OpenAI Codex integration" + # No installer config - uses custom codex.js + + crush: + name: "Crush" preferred: false category: ide - description: "Enhanced Cline fork" + description: "AI development assistant" installer: - target_dir: .roo/commands + target_dir: .crush/commands template_type: default + cursor: + name: "Cursor" + preferred: true + category: ide + description: "AI-first code editor" + installer: + target_dir: .cursor/commands + template_type: default + + gemini: + name: "Gemini CLI" + preferred: false + category: cli + description: "Google's CLI for Gemini" + installer: + target_dir: .gemini/commands + template_type: gemini + github-copilot: name: "GitHub Copilot" preferred: false @@ -99,24 +98,6 @@ platforms: template_type: vscode_settings artifact_types: [] - opencode: - name: "OpenCode" - preferred: false - category: ide - description: "OpenCode terminal coding assistant" - installer: - target_dir: .opencode/command - template_type: opencode - - crush: - name: "Crush" - preferred: false - category: ide - description: "AI development assistant" - installer: - target_dir: .crush/commands - template_type: default - iflow: name: "iFlow" preferred: false @@ -126,6 +107,29 @@ platforms: target_dir: .iflow/commands template_type: default + kilo: + name: "KiloCoder" + preferred: false + category: ide + description: "AI coding platform" + # No installer config - uses custom kilo.js (creates .kilocodemodes file) + + kiro-cli: + name: "Kiro CLI" + preferred: false + category: cli + description: "Kiro command-line interface" + # No installer config - uses custom kiro-cli.js (YAML→JSON conversion) + + opencode: + name: "OpenCode" + preferred: false + category: ide + description: "OpenCode terminal coding assistant" + installer: + target_dir: .opencode/command + template_type: opencode + qwen: name: "QwenCoder" preferred: false @@ -135,6 +139,15 @@ platforms: target_dir: .qwen/commands template_type: default + roo: + name: "Roo Cline" + preferred: false + category: ide + description: "Enhanced Cline fork" + installer: + target_dir: .roo/commands + template_type: default + rovo-dev: name: "Rovo Dev" preferred: false @@ -153,41 +166,14 @@ platforms: target_dir: .trae/rules template_type: trae - antigravity: - name: "Google Antigravity" - preferred: false + windsurf: + name: "Windsurf" + preferred: true category: ide - description: "Google's AI development environment" + description: "AI-powered IDE with cascade flows" installer: - target_dir: .agent/workflows - template_type: antigravity - # Note: Antigravity uses .agent/workflows/ directory (not .antigravity/) - - # ============================================================================ - # Custom Installers (no installer config - use custom file) - # These have unique installation logic that doesn't fit the config-driven model - # ============================================================================ - - codex: - name: "Codex" - preferred: false - category: cli - description: "OpenAI Codex integration" - # No installer config - uses custom codex.js - - kilo: - name: "KiloCoder" - preferred: false - category: ide - description: "AI coding platform" - # No installer config - uses custom kilo.js (creates .kilocodemodes file) - - kiro-cli: - name: "Kiro CLI" - preferred: false - category: cli - description: "Kiro command-line interface" - # No installer config - uses custom kiro-cli.js (YAML→JSON conversion) + target_dir: .windsurf/workflows + template_type: windsurf # ============================================================================ # Installer Config Schema diff --git a/tools/cli/installers/lib/ide/shared/agent-command-generator.js b/tools/cli/installers/lib/ide/shared/agent-command-generator.js index da8c1ef0..dec22a12 100644 --- a/tools/cli/installers/lib/ide/shared/agent-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/agent-command-generator.js @@ -134,9 +134,9 @@ class AgentCommandGenerator { /** * Write agent launcher artifacts using dash format (NEW STANDARD) - * Creates flat files like: bmad-bmm-pm.agent.md + * Creates flat files like: bmad-agent-bmm-pm.md * - * The .agent.md suffix distinguishes agents from workflows/tasks/tools. + * The bmad-agent- prefix distinguishes agents from workflows/tasks/tools. * * @param {string} baseCommandsDir - Base commands directory for the IDE * @param {Array} artifacts - Agent launcher artifacts @@ -147,7 +147,7 @@ class AgentCommandGenerator { for (const artifact of artifacts) { if (artifact.type === 'agent-launcher') { - // Convert relativePath to dash format: bmm/agents/pm.md → bmad-bmm-pm.agent.md + // Convert relativePath to dash format: bmm/agents/pm.md → bmad-agent-bmm-pm.md const flatName = toDashPath(artifact.relativePath); const launcherPath = path.join(baseCommandsDir, flatName); await fs.ensureDir(path.dirname(launcherPath)); diff --git a/tools/cli/installers/lib/ide/shared/path-utils.js b/tools/cli/installers/lib/ide/shared/path-utils.js index 7c335d4b..d6ad00f5 100644 --- a/tools/cli/installers/lib/ide/shared/path-utils.js +++ b/tools/cli/installers/lib/ide/shared/path-utils.js @@ -4,14 +4,14 @@ * Provides utilities to convert hierarchical paths to flat naming conventions. * * DASH-BASED NAMING (new standard): - * - Agents: bmad-module-name.agent.md (with .agent.md suffix) + * - Agents: bmad-agent-module-name.md (with bmad-agent- prefix) * - Workflows/Tasks/Tools: bmad-module-name.md * * Example outputs: - * - cis/agents/storymaster.md → bmad-cis-storymaster.agent.md + * - cis/agents/storymaster.md → bmad-agent-cis-storymaster.md * - bmm/workflows/plan-project.md → bmad-bmm-plan-project.md * - bmm/tasks/create-story.md → bmad-bmm-create-story.md - * - core/agents/brainstorming.md → bmad-brainstorming.agent.md + * - core/agents/brainstorming.md → bmad-agent-brainstorming.md (core agents skip module name) */ // Type segments - agents are included in naming, others are filtered out @@ -20,37 +20,38 @@ const AGENT_SEGMENT = 'agents'; /** * Convert hierarchical path to flat dash-separated name (NEW STANDARD) - * Converts: 'bmm', 'agents', 'pm' → 'bmad-bmm-pm.agent.md' + * Converts: 'bmm', 'agents', 'pm' → 'bmad-agent-bmm-pm.md' * Converts: 'bmm', 'workflows', 'correct-course' → 'bmad-bmm-correct-course.md' - * Converts: 'core', 'agents', 'brainstorming' → 'bmad-brainstorming.agent.md' (core items skip module prefix) + * Converts: 'core', 'agents', 'brainstorming' → 'bmad-agent-brainstorming.md' (core agents skip module name) * * @param {string} module - Module name (e.g., 'bmm', 'core') * @param {string} type - Artifact type ('agents', 'workflows', 'tasks', 'tools') * @param {string} name - Artifact name (e.g., 'pm', 'brainstorming') - * @returns {string} Flat filename like 'bmad-bmm-pm.agent.md' or 'bmad-bmm-correct-course.md' + * @returns {string} Flat filename like 'bmad-agent-bmm-pm.md' or 'bmad-bmm-correct-course.md' */ function toDashName(module, type, name) { const isAgent = type === AGENT_SEGMENT; - // For core module, skip the module prefix: use 'bmad-name.md' instead of 'bmad-core-name.md' + // For core module, skip the module name: use 'bmad-agent-name.md' instead of 'bmad-agent-core-name.md' if (module === 'core') { - return isAgent ? `bmad-${name}.agent.md` : `bmad-${name}.md`; + return isAgent ? `bmad-agent-${name}.md` : `bmad-${name}.md`; } - // Module artifacts: bmad-module-name.md or bmad-module-name.agent.md + // Module artifacts: bmad-module-name.md or bmad-agent-module-name.md // eslint-disable-next-line unicorn/prefer-string-replace-all -- regex replace is intentional here const dashName = name.replace(/\//g, '-'); // Flatten nested paths - return isAgent ? `bmad-${module}-${dashName}.agent.md` : `bmad-${module}-${dashName}.md`; + return isAgent ? `bmad-agent-${module}-${dashName}.md` : `bmad-${module}-${dashName}.md`; } /** * Convert relative path to flat dash-separated name - * Converts: 'bmm/agents/pm.md' → 'bmad-bmm-pm.agent.md' + * Converts: 'bmm/agents/pm.md' → 'bmad-agent-bmm-pm.md' + * Converts: 'bmm/agents/tech-writer/tech-writer.md' → 'bmad-agent-bmm-tech-writer.md' (uses folder name) * Converts: 'bmm/workflows/correct-course.md' → 'bmad-bmm-correct-course.md' - * Converts: 'core/agents/brainstorming.md' → 'bmad-brainstorming.agent.md' (core items skip module prefix) + * Converts: 'core/agents/brainstorming.md' → 'bmad-agent-brainstorming.md' (core agents skip module name) * * @param {string} relativePath - Path like 'bmm/agents/pm.md' - * @returns {string} Flat filename like 'bmad-bmm-pm.agent.md' or 'bmad-brainstorming.md' + * @returns {string} Flat filename like 'bmad-agent-bmm-pm.md' or 'bmad-brainstorming.md' */ function toDashPath(relativePath) { if (!relativePath || typeof relativePath !== 'string') { @@ -63,20 +64,30 @@ function toDashPath(relativePath) { const module = parts[0]; const type = parts[1]; - const name = parts.slice(2).join('-'); + let name; + + // For agents, if nested in a folder (more than 3 parts), use the folder name only + // e.g., 'bmm/agents/tech-writer/tech-writer' → 'tech-writer' (not 'tech-writer-tech-writer') + if (type === 'agents' && parts.length > 3) { + // Use the folder name (parts[2]) as the name, ignore the file name + name = parts[2]; + } else { + // For non-nested or non-agents, join all parts after type + name = parts.slice(2).join('-'); + } return toDashName(module, type, name); } /** * Create custom agent dash name - * Creates: 'bmad-custom-fred-commit-poet.agent.md' + * Creates: 'bmad-custom-agent-fred-commit-poet.md' * * @param {string} agentName - Custom agent name - * @returns {string} Flat filename like 'bmad-custom-fred-commit-poet.agent.md' + * @returns {string} Flat filename like 'bmad-custom-agent-fred-commit-poet.md' */ function customAgentDashName(agentName) { - return `bmad-custom-${agentName}.agent.md`; + return `bmad-custom-agent-${agentName}.md`; } /** @@ -90,9 +101,9 @@ function isDashFormat(filename) { /** * Extract parts from a dash-formatted filename - * Parses: 'bmad-bmm-pm.agent.md' → { prefix: 'bmad', module: 'bmm', type: 'agents', name: 'pm' } + * Parses: 'bmad-agent-bmm-pm.md' → { prefix: 'bmad', module: 'bmm', type: 'agents', name: 'pm' } * Parses: 'bmad-bmm-correct-course.md' → { prefix: 'bmad', module: 'bmm', type: 'workflows', name: 'correct-course' } - * Parses: 'bmad-brainstorming.agent.md' → { prefix: 'bmad', module: 'core', type: 'agents', name: 'brainstorming' } (core agents) + * Parses: 'bmad-agent-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'agents', name: 'brainstorming' } (core agents) * Parses: 'bmad-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'workflows', name: 'brainstorming' } (core workflows) * * @param {string} filename - Dash-formatted filename @@ -106,27 +117,27 @@ function parseDashName(filename) { return null; } - // Check if this is an agent file (has .agent suffix) - const isAgent = withoutExt.endsWith('.agent'); + // Check if this is an agent file (has 'agent' as second part) + const isAgent = parts[1] === 'agent'; if (isAgent) { // This is an agent file - // Format: bmad-name.agent (core) or bmad-module-name.agent + // Format: bmad-agent-name (core) or bmad-agent-module-name if (parts.length === 3) { - // Core agent: bmad-name.agent + // Core agent: bmad-agent-name return { prefix: parts[0], module: 'core', type: 'agents', - name: parts[1], + name: parts[2], }; } else { - // Module agent: bmad-module-name.agent + // Module agent: bmad-agent-module-name return { prefix: parts[0], - module: parts[1], + module: parts[2], type: 'agents', - name: parts.slice(2).join('-'), + name: parts.slice(3).join('-'), }; } } diff --git a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js index 0e54ad89..6b90de9f 100644 --- a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js @@ -242,7 +242,7 @@ Follow all instructions in the ${type} file exactly as written. * Write task/tool artifacts using dash format (NEW STANDARD) * Creates flat files like: bmad-bmm-bmad-help.md * - * Note: Tasks/tools do NOT have .agent.md suffix - only agents do. + * Note: Tasks/tools do NOT have bmad-agent- prefix - only agents do. * * @param {string} baseCommandsDir - Base commands directory for the IDE * @param {Array} artifacts - Task/tool artifacts with relativePath diff --git a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js index 42bad24a..6dab1a3f 100644 --- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js @@ -292,7 +292,7 @@ When running any workflow: * Write workflow command artifacts using dash format (NEW STANDARD) * Creates flat files like: bmad-bmm-correct-course.md * - * Note: Workflows do NOT have .agent.md suffix - only agents do. + * Note: Workflows do NOT have bmad-agent- prefix - only agents do. * * @param {string} baseCommandsDir - Base commands directory for the IDE * @param {Array} artifacts - Workflow artifacts