feat: Introduce monorepo context logic for inline project overrides and dynamic path adjustments in workflows.
This commit is contained in:
parent
e7cc716e87
commit
a5bda6a80e
|
|
@ -34,3 +34,16 @@ Load and read full config from {main_config} and resolve basic variables.
|
|||
### 3. Verification
|
||||
|
||||
- Display the full resolved output path for confirmation.
|
||||
|
||||
## Inline Project Overrides
|
||||
|
||||
You can also temporarily run a command against a different project without changing the global context file. Use the `#project:NAME` or `#p:NAME` syntax in your command invocation.
|
||||
|
||||
**Examples:**
|
||||
- `/create-prd #project:my-app`
|
||||
- `/sprint-planning #p:admin-portal`
|
||||
|
||||
**Precedence:**
|
||||
1. **Inline Override** (`#p:NAME`)
|
||||
2. **Global Context File** (`_bmad/.current_project`)
|
||||
3. **Default Config** (if neither is present)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,11 @@
|
|||
|
||||
<flow>
|
||||
<step n="1" title="Load and Initialize Workflow">
|
||||
<substep n="1a" title="Load Configuration and Resolve Variables">
|
||||
<substep n="1a" title="Monorepo Context Injection">
|
||||
{{monorepo_context_logic}}
|
||||
</substep>
|
||||
|
||||
<substep n="1b" title="Load Configuration and Resolve Variables">
|
||||
<action>Read workflow.yaml from provided path</action>
|
||||
<mandate>Load config_source (REQUIRED for all modules)</mandate>
|
||||
<phase n="1">Load external config from config_source path</phase>
|
||||
|
|
@ -27,7 +31,7 @@
|
|||
<phase n="4">Ask user for input of any variables that are still unknown</phase>
|
||||
</substep>
|
||||
|
||||
<substep n="1b" title="Load Required Components">
|
||||
<substep n="1c" title="Load Required Components">
|
||||
<mandate>Instructions: Read COMPLETE file from path OR embedded list (REQUIRED)</mandate>
|
||||
<check>If template path → Read COMPLETE template file</check>
|
||||
<check>If validation path → Note path for later loading when needed</check>
|
||||
|
|
@ -35,7 +39,7 @@
|
|||
<note>Data files (csv, json) → Store paths only, load on-demand when instructions reference them</note>
|
||||
</substep>
|
||||
|
||||
<substep n="1c" title="Initialize Output" if="template-workflow">
|
||||
<substep n="1d" title="Initialize Output" if="template-workflow">
|
||||
<action>Resolve default_output_file path with all variables and {{date}}</action>
|
||||
<action>Create output directory if doesn't exist</action>
|
||||
<action>If template-workflow → Write template to output file with placeholders</action>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const { IdeConfigManager } = require('./ide-config-manager');
|
|||
const { CustomHandler } = require('../custom/handler');
|
||||
const prompts = require('../../../lib/prompts');
|
||||
const { BMAD_FOLDER_NAME } = require('../ide/shared/path-utils');
|
||||
const { MONOREPO_CONTEXT_LOGIC } = require('../ide/shared/context-logic');
|
||||
|
||||
class Installer {
|
||||
constructor() {
|
||||
|
|
@ -89,6 +90,10 @@ class Installer {
|
|||
// Read the file content
|
||||
let content = await fs.readFile(sourcePath, 'utf8');
|
||||
|
||||
// Apply replacements
|
||||
content = content.replaceAll('{{monorepo_context_logic}}', MONOREPO_CONTEXT_LOGIC);
|
||||
content = content.replaceAll('_bmad', this.bmadFolderName);
|
||||
|
||||
// Write to target with replaced content
|
||||
await fs.ensureDir(path.dirname(targetPath));
|
||||
await fs.writeFile(targetPath, content, 'utf8');
|
||||
|
|
|
|||
|
|
@ -391,12 +391,15 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|||
// No default
|
||||
}
|
||||
|
||||
const { MONOREPO_CONTEXT_LOGIC } = require('./shared/context-logic');
|
||||
|
||||
let rendered = template
|
||||
.replaceAll('{{name}}', artifact.name || '')
|
||||
.replaceAll('{{module}}', artifact.module || 'core')
|
||||
.replaceAll('{{path}}', pathToUse)
|
||||
.replaceAll('{{description}}', artifact.description || `${artifact.name} ${artifact.type || ''}`)
|
||||
.replaceAll('{{workflow_path}}', pathToUse);
|
||||
.replaceAll('{{workflow_path}}', pathToUse)
|
||||
.replaceAll('{{monorepo_context_logic}}', MONOREPO_CONTEXT_LOGIC);
|
||||
|
||||
// Replace _bmad placeholder with actual folder name
|
||||
rendered = rendered.replaceAll('_bmad', this.bmadFolderName);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Monorepo Context Logic XML Block
|
||||
*
|
||||
* robust, secure, and centralized logic for handling:
|
||||
* 1. Inline project overrides (#p:NAME)
|
||||
* 2. .current_project file fallback
|
||||
* 3. Path variable overrides
|
||||
*/
|
||||
const MONOREPO_CONTEXT_LOGIC = `
|
||||
<monorepo-context-check CRITICAL="TRUE" priority="before-config">
|
||||
<!-- Step 1: Check for inline project override in user invocation -->
|
||||
<!-- Supported syntax: #project:NAME (full) or #p:NAME (short alias) -->
|
||||
<action>Scan user's invocation message for pattern #project:NAME or #p:NAME (case-insensitive)</action>
|
||||
<check if="inline override found">
|
||||
<action>Set project_suffix = extracted NAME</action>
|
||||
<output>🎯 Inline project override: {project_suffix}</output>
|
||||
</check>
|
||||
|
||||
<!-- Step 2: Fall back to .current_project file -->
|
||||
<check if="project_suffix not yet set AND {project-root}/_bmad/.current_project exists">
|
||||
<action>Read {project-root}/_bmad/.current_project as project_suffix</action>
|
||||
</check>
|
||||
|
||||
<!-- Step 3: Validate -->
|
||||
<check if="project_suffix is set">
|
||||
<action>Trim whitespace and newlines from project_suffix</action>
|
||||
<!-- Security: Prevent path traversal and invalid chars -->
|
||||
<check if="project_suffix contains '..' OR starts with '/' OR starts with '\\'">
|
||||
<output>🚫 Security Error: Invalid project context — path traversal detected.</output>
|
||||
<action>HALT</action>
|
||||
</check>
|
||||
<check if="project_suffix matching regex [^a-zA-Z0-9._-]">
|
||||
<output>🚫 Error: project_suffix must only contain alphanumeric characters, dots, dashes, or underscores.</output>
|
||||
<action>HALT</action>
|
||||
</check>
|
||||
|
||||
<!-- Step 4: Override path variables -->
|
||||
<action>Override output_folder = {project-root}/_bmad-output/{project_suffix}</action>
|
||||
<action>Override planning_artifacts = {output_folder}/planning-artifacts</action>
|
||||
<action>Override implementation_artifacts = {output_folder}/implementation-artifacts</action>
|
||||
<action>Override project_knowledge = {output_folder}/knowledge</action>
|
||||
<action>Override sprint_status_file = {output_folder}/sprint-status.yaml</action>
|
||||
<output>🗂️ Monorepo context: {project_suffix} → outputs to {output_folder}</output>
|
||||
</check>
|
||||
</monorepo-context-check>
|
||||
`;
|
||||
|
||||
module.exports = { MONOREPO_CONTEXT_LOGIC };
|
||||
|
|
@ -151,12 +151,15 @@ class WorkflowCommandGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
const { MONOREPO_CONTEXT_LOGIC } = require('./context-logic');
|
||||
|
||||
// Replace template variables
|
||||
return template
|
||||
.replaceAll('{{name}}', workflow.name)
|
||||
.replaceAll('{{module}}', workflow.module)
|
||||
.replaceAll('{{description}}', workflow.description)
|
||||
.replaceAll('{{workflow_path}}', workflowPath)
|
||||
.replaceAll('{{monorepo_context_logic}}', MONOREPO_CONTEXT_LOGIC)
|
||||
.replaceAll('_bmad', this.bmadFolderName);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ name: '{{name}}'
|
|||
description: '{{description}}'
|
||||
---
|
||||
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}}
|
||||
|
||||
Follow all instructions in the workflow file exactly as written.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ disable-model-invocation: true
|
|||
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:
|
||||
|
||||
<steps CRITICAL="TRUE">
|
||||
0. {{monorepo_context_logic}}
|
||||
|
||||
1. Always LOAD the FULL @{project-root}/{{bmadFolderName}}/core/tasks/workflow.xml
|
||||
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config @{project-root}/{{bmadFolderName}}/{{path}}
|
||||
3. Pass the yaml path @{project-root}/{{bmadFolderName}}/{{path}} as 'workflow-config' parameter to the workflow.xml instructions
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ description: '{{description}}'
|
|||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ inclusion: manual
|
|||
|
||||
# {{name}}
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL #[[file:{{bmadFolderName}}/{{path}}]], READ its entire contents and follow its directions exactly!
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Execute the BMAD '{{name}}' workflow.
|
|||
CRITICAL: You must load and follow the workflow definition exactly.
|
||||
|
||||
WORKFLOW INSTRUCTIONS:
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ auto_execution_mode: "iterate"
|
|||
|
||||
# {{name}}
|
||||
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
Read the entire workflow file at {project-root}/_bmad/{{workflow_path}}
|
||||
|
||||
Follow all instructions in the workflow file exactly as written.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ description: '{{description}}'
|
|||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:
|
||||
|
||||
<steps CRITICAL="TRUE">
|
||||
|
|
|
|||
|
|
@ -3,4 +3,6 @@ description: '{{description}}'
|
|||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
{{monorepo_context_logic}}
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{{workflow_path}}, READ its entire contents and follow its directions exactly!
|
||||
|
|
|
|||
Loading…
Reference in New Issue