fix: optimize agent compiler and complete handler cleanup

- Add deployment-aware handler generation (filters web-only/ide-only commands)
- Remove unused run-workflow handler type (ghost handler cleanup)
- Implement missing validate-workflow and data handler generation
- Update schema validation to support exactly 6 active handler types
- Clean up activation templates and web bundler logic
- Prevent generation of unused handler instructions for better performance
- All 62 tests pass with backward compatibility maintained
This commit is contained in:
Brian Madison 2025-11-23 21:28:50 -06:00
parent cd98a7f5bb
commit 3740a554f0
15 changed files with 56 additions and 59 deletions

View File

@ -38,7 +38,7 @@
- [ ] Config values use {config_source}: pattern
- [ ] Agent follows naming conventions (kebab-case for files)
- [ ] ALL paths reference {project-root}/{bmad_folder}/{{module}}/ locations, NOT src/
- [ ] exec, data, run-workflow commands point to final BMAD installation paths
- [ ] exec, data, workflow commands point to final BMAD installation paths
### For Template/Workflow Conversions

View File

@ -156,7 +156,7 @@ For Modules:
<action>Example path conversions:
- exec="{project-root}/{bmad_folder}/{{target_module}}/tasks/task-name.md"
- run-workflow="{project-root}/{bmad_folder}/{{target_module}}/workflows/workflow-name/workflow.yaml"
- workflow="{project-root}/{bmad_folder}/{{target_module}}/workflows/workflow-name/workflow.yaml"
- data="{project-root}/{bmad_folder}/{{target_module}}/data/data-file.yaml"
</action>
<action>Save to: {bmad_folder}/{{target_module}}/agents/{{agent_name}}.agent.yaml (physical location)</action>

View File

@ -20,19 +20,19 @@ agent:
menu:
- trigger: brainstorm-project
workflow: "{project-root}/{bmad_folder}/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml"
description: Guided Brainstorming
description: Guided Brainstorming scoped to product development ideation and problem discovery
- trigger: research
workflow: "{project-root}/{bmad_folder}/bmm/workflows/1-analysis/research/workflow.yaml"
description: Guided Research
description: Guided Research scoped to market and competitive analysis of a product or feature
- trigger: product-brief
workflow: "{project-root}/{bmad_folder}/bmm/workflows/1-analysis/product-brief/workflow.yaml"
description: Create a Product Brief
description: Create a Product Brief, a great input to then drive a PRD
- trigger: document-project
workflow: "{project-root}/{bmad_folder}/bmm/workflows/document-project/workflow.yaml"
description: Generate comprehensive documentation of an existing Project
description: Generate comprehensive documentation of an existing codebase, including architecture, data flows, and API contracts, and other details to aid project understanding.
- trigger: party-mode
workflow: "{project-root}/{bmad_folder}/core/workflows/party-mode/workflow.yaml"

View File

@ -24,7 +24,6 @@ agent:
- trigger: validate-architecture
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/architecture/workflow.yaml"
checklist: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/architecture/checklist.md"
description: Validate Architecture Document
- trigger: implementation-readiness

View File

@ -25,13 +25,11 @@ agent:
- trigger: validate-prd
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/prd/workflow.yaml"
checklist: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/prd/checklist.md"
document: "{output_folder}/PRD.md"
description: Validate PRD + Epics + Stories completeness and quality
description: Validate PRD
- trigger: create-epics-and-stories
workflow: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.yaml"
description: Break PRD requirements into implementable epics and stories after the architecture is defined
description: Create Epics and User Stories from PRD (Its recommended to not do this until the architecture is complete)
- trigger: correct-course
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/correct-course/workflow.yaml"

View File

@ -19,7 +19,6 @@ agent:
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md ``
menu:
# Quick-Flow workflows - Barry owns the entire quick-flow path from spec to ship
- trigger: create-tech-spec
workflow: "{project-root}/{bmad_folder}/bmm/workflows/bmad-quick-flow/create-tech-spec/workflow.yaml"
description: Architect a technical spec with implementation-ready stories

View File

@ -25,12 +25,10 @@ agent:
menu:
- trigger: create-ux-design
workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml"
description: Conduct Design Thinking Workshop to Define the User Specification
description: Conduct Design Thinking Workshop to Define the User Specification with PRD as input
- trigger: validate-design
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml"
checklist: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/checklist.md"
document: "{output_folder}/ux-spec.md"
description: Validate UX Specification and Design Artifacts
- trigger: create-excalidraw-wireframe

View File

@ -83,7 +83,7 @@ Master storyteller with 50+ years crafting compelling narratives across multiple
All CIS agents are **Module Agents** with:
- Integration with CIS module configuration
- Access to workflow invocation via `run-workflow` or `exec` attributes
- Access to workflow invocation via `workflow` or `exec` attributes
- Standard critical actions for config loading and user context
- Simple command structure focused on workflow facilitation

View File

@ -8,16 +8,8 @@
</init>
<commands critical="MANDATORY">
<input>Number → cmd[n] | Text → fuzzy match *commands</input>
<extract>exec, tmpl, data, action, run-workflow, validate-workflow</extract>
<extract>exec, tmpl, data, action, validate-workflow</extract>
<handlers>
<handler type="run-workflow">
When command has: run-workflow="path/to/x.yaml" You MUST:
1. CRITICAL: Always LOAD {project-root}/{bmad_folder}/core/tasks/workflow.xml
2. READ its entire contents - the is the CORE OS for EXECUTING workflows
3. Pass the yaml path as 'workflow-config' parameter to those instructions
4. Follow workflow.xml instructions EXACTLY as written
5. Save outputs after EACH section (never batch)
</handler>
<handler type="progressive-workflow">
When command has: run-progressive-workflow="path/to/x.yaml" You MUST:
1. CRITICAL: Always LOAD {project-root}/{bmad_folder}/core/tasks/workflow.xml

View File

@ -21,18 +21,8 @@
</bundled-files>
<commands critical="MANDATORY">
<input>Number → cmd[n] | Text → fuzzy match *commands</input>
<extract>exec, tmpl, data, action, run-workflow, validate-workflow</extract>
<extract>exec, tmpl, data, action, validate-workflow</extract>
<handlers>
<handler type="run-workflow">
When command has: run-workflow="path/to/x.yaml" You MUST:
1. CRITICAL: Locate &lt;file id="{bmad_folder}/core/tasks/workflow.xml"&gt; in this XML bundle
2. Extract and READ its CDATA content - this is the CORE OS for EXECUTING workflows
3. Locate &lt;file id="path/to/x.yaml"&gt; for the workflow config
4. Pass the yaml content as 'workflow-config' parameter to workflow.xml instructions
5. Follow workflow.xml instructions EXACTLY as written
6. When workflow references other files, locate them by id in &lt;file&gt; elements
7. Save outputs after EACH section (never batch)
</handler>
<handler type="action">
When command has: action="#id" → Find prompt with id="id" in current agent XML, execute its content
When command has: action="text" → Execute the text directly as a critical action prompt

View File

@ -116,7 +116,7 @@ Tests required menu structure:
Tests menu item command targets:
- ✅ Valid: All 7 command types (`workflow`, `validate-workflow`, `exec`, `action`, `tmpl`, `data`, `run-workflow`)
- ✅ Valid: All 6 command types (`workflow`, `validate-workflow`, `exec`, `action`, `tmpl`, `data`)
- ✅ Valid: Multiple command targets in one menu item
- ❌ Invalid: No command target fields
- ❌ Invalid: Empty string command targets

View File

@ -34,6 +34,4 @@ agent:
- trigger: data-test
description: Test data command
data: path/to/data
- trigger: run-workflow-test
description: Test run-workflow command
run-workflow: path/to/workflow

View File

@ -748,10 +748,9 @@ class WebBundler {
}
}
// Extract workflow references - both 'workflow' and 'run-workflow' attributes
// Extract workflow references from agent files
const workflowPatterns = [
/workflow="([^"]+)"/g, // Menu items with workflow attribute
/run-workflow="([^"]+)"/g, // Commands with run-workflow attribute
/validate-workflow="([^"]+)"/g, // Validation workflow references
];
@ -789,16 +788,6 @@ class WebBundler {
// Match: <item cmd="..." workflow="workflowPath">...</item>
const itemWorkflowPattern = new RegExp(`\\s*<item\\s+[^>]*workflow="[^"]*${escapedPath}"[^>]*>.*?</item>\\s*`, 'gs');
modifiedXml = modifiedXml.replace(itemWorkflowPattern, '');
// Pattern 2: Remove <item> tags with run-workflow attribute
// Match: <item cmd="..." run-workflow="workflowPath">...</item>
const itemRunWorkflowPattern = new RegExp(`\\s*<item\\s+[^>]*run-workflow="[^"]*${escapedPath}"[^>]*>.*?</item>\\s*`, 'gs');
modifiedXml = modifiedXml.replace(itemRunWorkflowPattern, '');
// Pattern 3: Remove <c> tags with run-workflow attribute (legacy)
// Match: <c cmd="..." run-workflow="workflowPath">...</c>
const cPattern = new RegExp(`\\s*<c\\s+[^>]*run-workflow="[^"]*${escapedPath}"[^>]*>.*?</c>\\s*`, 'gs');
modifiedXml = modifiedXml.replace(cPattern, '');
}
return modifiedXml;

View File

@ -49,9 +49,10 @@ You must fully embody this agent's persona and follow all activation instruction
* Build simple activation block for custom agents
* @param {Array} criticalActions - Agent-specific critical actions
* @param {Array} menuItems - Menu items to determine which handlers to include
* @param {string} deploymentType - 'ide' or 'web' - filters commands based on ide-only/web-only flags
* @returns {string} Activation XML
*/
function buildSimpleActivation(criticalActions = [], menuItems = []) {
function buildSimpleActivation(criticalActions = [], menuItems = [], deploymentType = 'ide') {
let activation = '<activation critical="MANDATORY">\n';
let stepNum = 1;
@ -75,13 +76,28 @@ function buildSimpleActivation(criticalActions = [], menuItems = []) {
activation += ` <step n="${stepNum++}">On user input: Number → execute menu item[n] | Text → case-insensitive substring match | Multiple matches → ask user
to clarify | No match show "Not recognized"</step>\n`;
// Detect which handlers are actually used
// Filter menu items based on deployment type
const filteredMenuItems = menuItems.filter((item) => {
// Skip web-only commands for IDE deployment
if (deploymentType === 'ide' && item['web-only'] === true) {
return false;
}
// Skip ide-only commands for web deployment
if (deploymentType === 'web' && item['ide-only'] === true) {
return false;
}
return true;
});
// Detect which handlers are actually used in the filtered menu
const usedHandlers = new Set();
for (const item of menuItems) {
for (const item of filteredMenuItems) {
if (item.action) usedHandlers.add('action');
if (item.workflow) usedHandlers.add('workflow');
if (item.exec) usedHandlers.add('exec');
if (item.tmpl) usedHandlers.add('tmpl');
if (item.data) usedHandlers.add('data');
if (item['validate-workflow']) usedHandlers.add('validate-workflow');
}
// Only include menu-handlers section if handlers are used
@ -124,6 +140,25 @@ function buildSimpleActivation(criticalActions = [], menuItems = []) {
</handler>\n`;
}
if (usedHandlers.has('data')) {
activation += ` <handler type="data">
When menu item has: data="path/to/x.json|yaml|yml"
Load the file, parse as JSON/YAML, make available as {data} to subsequent operations
</handler>\n`;
}
if (usedHandlers.has('validate-workflow')) {
activation += ` <handler type="validate-workflow">
When menu item has: validate-workflow="path/to/workflow.yaml"
1. CRITICAL: Always LOAD {project-root}/{bmad_folder}/core/tasks/validate-workflow.xml
2. Read the complete file - this is the CORE OS for validating BMAD workflows
3. Pass the workflow.yaml path as 'workflow' parameter to those instructions
4. Pass any checklist.md from the workflow location as 'checklist' parameter if available
5. Execute validate-workflow.xml instructions precisely following all steps
6. Generate validation report with thorough analysis
</handler>\n`;
}
activation += ` </handlers>
</menu-handlers>\n`;
}
@ -275,8 +310,8 @@ function compileToXml(agentYaml, agentName = '', targetPath = '') {
xml += `<agent ${agentAttrs.join(' ')}>\n`;
// Activation block - pass menu items to determine which handlers to include
xml += buildSimpleActivation(agent.critical_actions || [], agent.menu || []);
// Activation block - pass menu items and deployment type to determine which handlers to include
xml += buildSimpleActivation(agent.critical_actions || [], agent.menu || [], 'ide');
// Persona section
xml += buildPersonaXml(agent.persona);

View File

@ -2,7 +2,7 @@
const assert = require('node:assert');
const { z } = require('zod');
const COMMAND_TARGET_KEYS = ['workflow', 'validate-workflow', 'exec', 'action', 'tmpl', 'data', 'run-workflow'];
const COMMAND_TARGET_KEYS = ['workflow', 'validate-workflow', 'exec', 'action', 'tmpl', 'data'];
const TRIGGER_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
// Public API ---------------------------------------------------------------
@ -180,7 +180,6 @@ function buildMenuItemSchema() {
action: createNonEmptyString('agent.menu[].action').optional(),
tmpl: createNonEmptyString('agent.menu[].tmpl').optional(),
data: createNonEmptyString('agent.menu[].data').optional(),
'run-workflow': createNonEmptyString('agent.menu[].run-workflow').optional(),
checklist: createNonEmptyString('agent.menu[].checklist').optional(),
document: createNonEmptyString('agent.menu[].document').optional(),
'ide-only': z.boolean().optional(),