diff --git a/docs/tutorials/getting-started.md b/docs/tutorials/getting-started.md
index 2d959bc92..dee65a26d 100644
--- a/docs/tutorials/getting-started.md
+++ b/docs/tutorials/getting-started.md
@@ -78,15 +78,15 @@ Work through phases 1-3. **Use fresh chats for each workflow.**
### Phase 1: Analysis (Optional)
All workflows in this phase are optional:
-- **brainstorming** — Guided ideation
-- **research** — Market and technical research
-- **create-product-brief** — Recommended foundation document
+- **brainstorming** (`bmad-bmm-brainstorming`) — Guided ideation
+- **research** (`bmad-bmm-research`) — Market and technical research
+- **create-product-brief** (`bmad-bmm-create-product-brief`) — Recommended foundation document
### Phase 2: Planning (Required)
**For BMad Method and Enterprise tracks:**
1. Load the **PM agent** in a new chat
-2. Run the `prd` workflow
+2. Run the `create-prd` workflow (`bmad-bmm-create-prd`)
3. Output: `PRD.md`
**For Quick Flow track:**
@@ -100,7 +100,7 @@ If your project has a user interface, load the **UX-Designer agent** and run the
**Create Architecture**
1. Load the **Architect agent** in a new chat
-2. Run `create-architecture`
+2. Run `create-architecture` (`bmad-bmm-create-architecture`)
3. Output: Architecture document with technical decisions
**Create Epics and Stories**
@@ -110,12 +110,12 @@ Epics and stories are now created *after* architecture. This produces better qua
:::
1. Load the **PM agent** in a new chat
-2. Run `create-epics-and-stories`
+2. Run `create-epics-and-stories` (`bmad-bmm-create-epics-and-stories`)
3. The workflow uses both PRD and Architecture to create technically-informed stories
**Implementation Readiness Check** *(Highly Recommended)*
1. Load the **Architect agent** in a new chat
-2. Run `check-implementation-readiness`
+2. Run `check-implementation-readiness` (`bmad-bmm-check-implementation-readiness`)
3. Validates cohesion across all planning documents
## Step 2: Build Your Project
@@ -124,7 +124,7 @@ Once planning is complete, move to implementation. **Each workflow should run in
### Initialize Sprint Planning
-Load the **SM agent** and run `sprint-planning`. This creates `sprint-status.yaml` to track all epics and stories.
+Load the **SM agent** and run `sprint-planning` (`bmad-bmm-sprint-planning`). This creates `sprint-status.yaml` to track all epics and stories.
### The Build Cycle
@@ -132,11 +132,11 @@ For each story, repeat this cycle with fresh chats:
| Step | Agent | Workflow | Purpose |
| ---- | ----- | -------------- | ---------------------------------- |
-| 1 | SM | `create-story` | Create story file from epic |
-| 2 | DEV | `dev-story` | Implement the story |
-| 3 | DEV | `code-review` | Quality validation *(recommended)* |
+| 1 | SM | `create-story` (`bmad-bmm-create-story`) | Create story file from epic |
+| 2 | DEV | `dev-story` (`bmad-bmm-dev-story`) | Implement the story |
+| 3 | DEV | `code-review` (`bmad-bmm-code-review`) | Quality validation *(recommended)* |
-After completing all stories in an epic, load the **SM agent** and run `retrospective`.
+After completing all stories in an epic, load the **SM agent** and run `retrospective` (`bmad-bmm-retrospective`).
## What You've Accomplished
@@ -162,17 +162,17 @@ your-project/
## Quick Reference
-| Workflow | Agent | Purpose |
-| -------------------------------- | --------- | ------------------------------------ |
-| `help` | Any | Get guidance on what to do next |
-| `prd` | PM | Create Product Requirements Document |
-| `create-architecture` | Architect | Create architecture document |
-| `create-epics-and-stories` | PM | Break down PRD into epics |
-| `check-implementation-readiness` | Architect | Validate planning cohesion |
-| `sprint-planning` | SM | Initialize sprint tracking |
-| `create-story` | SM | Create a story file |
-| `dev-story` | DEV | Implement a story |
-| `code-review` | DEV | Review implemented code |
+| Workflow | Slash Command | Agent | Purpose |
+| -------------------------------- | ------------------------------------- | --------- | ------------------------------------ |
+| `help` | `bmad-help` | Any | Get guidance on what to do next |
+| `create-prd` | `bmad-bmm-create-prd` | PM | Create Product Requirements Document |
+| `create-architecture` | `bmad-bmm-create-architecture` | Architect | Create architecture document |
+| `create-epics-and-stories` | `bmad-bmm-create-epics-and-stories` | PM | Break down PRD into epics |
+| `check-implementation-readiness` | `bmad-bmm-check-implementation-readiness` | Architect | Validate planning cohesion |
+| `sprint-planning` | `bmad-bmm-sprint-planning` | SM | Initialize sprint tracking |
+| `create-story` | `bmad-bmm-create-story` | SM | Create a story file |
+| `dev-story` | `bmad-bmm-dev-story` | DEV | Implement a story |
+| `code-review` | `bmad-bmm-code-review` | DEV | Review implemented code |
## Common Questions
@@ -183,7 +183,7 @@ Only for BMad Method and Enterprise tracks. Quick Flow skips from tech-spec to i
Yes. The SM agent has a `correct-course` workflow for handling scope changes.
**What if I want to brainstorm first?**
-Load the Analyst agent and run `brainstorming` before starting your PRD.
+Load the Analyst agent and run `brainstorming` (`bmad-bmm-brainstorming`) before starting your PRD.
**Do I need to follow a strict order?**
Not strictly. Once you learn the flow, you can run workflows directly using the Quick Reference above.
@@ -192,7 +192,7 @@ Not strictly. Once you learn the flow, you can run workflows directly using the
- **During workflows** — Agents guide you with questions and explanations
- **Community** — [Discord](https://discord.gg/gk8jAdXWmj) (#bmad-method-help, #report-bugs-and-issues)
-- **Stuck?** — Run `help` to see what to do next
+- **Stuck?** — Run `help` (`bmad-help` on most platforms) to see what to do next
## Key Takeaways
diff --git a/src/bmm/workflows/4-implementation/create-story/workflow.md b/src/bmm/workflows/4-implementation/create-story/workflow.md
index bf226c4d3..219a885e6 100644
--- a/src/bmm/workflows/4-implementation/create-story/workflow.md
+++ b/src/bmm/workflows/4-implementation/create-story/workflow.md
@@ -59,7 +59,7 @@ input_file_patterns:
Parse user-provided story path: extract epic_num, story_num, story_title from format like "1-2-user-auth"
Set {{epic_num}}, {{story_num}}, {{story_key}} from user input
- GOTO step 2a
+ GOTO step 2
Check if {{sprint_status}} file exists for auto discover
@@ -85,12 +85,12 @@ input_file_patterns:
Parse user input: extract epic_num, story_num, story_title
Set {{epic_num}}, {{story_num}}, {{story_key}} from user input
- GOTO step 2a
+ GOTO step 2
Use user-provided path for story documents
- GOTO step 2a
+ GOTO step 2
@@ -152,7 +152,7 @@ input_file_patterns:
- GOTO step 2a
+ GOTO step 2
@@ -174,6 +174,7 @@ input_file_patterns:
(As a, I want, so that) - Detailed acceptance criteria (already BDD formatted) - Technical requirements specific to this story -
Business context and value - Success criteria
+ Set {{previous_story_num}} = {{story_num}} - 1
Load previous story file: {{story_dir}}/{{epic_num}}-{{previous_story_num}}-*.md **PREVIOUS STORY INTELLIGENCE:** -
Dev notes and learnings from previous story - Review feedback and corrections needed - Files that were created/modified and their
patterns - Testing approaches that worked/didn't work - Problems encountered and solutions found - Code patterns established Extract
diff --git a/src/bmm/workflows/document-project/instructions.md b/src/bmm/workflows/document-project/instructions.md
index 8b2269913..a8315fcd9 100644
--- a/src/bmm/workflows/document-project/instructions.md
+++ b/src/bmm/workflows/document-project/instructions.md
@@ -18,6 +18,13 @@
- Set suggestion = ""
- Set next_workflow = ""
- Set next_agent = ""
+ - Set status_file_path = ""
+ - Set field_type = ""
+ - Set workflow_mode = ""
+ - Set scan_level = ""
+ - Set subworkflow_success = false
+ - Set status_update_success = false
+ - Set cached_project_types = ""
Attempt to load workflow status directly from `{output_folder}/bmm-workflow-status.yaml`:
@@ -29,10 +36,18 @@
- Extract field_type, warning, suggestion, next_workflow, next_agent if present
- If file is missing, unreadable, or malformed:
- Keep defaults and continue in standalone mode
+ - Set status_load_error_reason from the caught file/parse error (e.g., missing file, permission denied, YAML parse error)
+ - Set warning = "Unable to load workflow status from {output_folder}/bmm-workflow-status.yaml: {{status_load_error_reason}}"
+ - Output warning and continue in standalone mode
-
+
+
+
+
+
+
Set standalone_mode = true
Set status_file_found = false
@@ -62,7 +77,9 @@
Continue with documentation? (y/n)
-
+
+
+
Exit workflow
@@ -78,14 +95,33 @@
Read state file and extract: timestamps, mode, scan_level, current_step, completed_steps, project_classification
+ Validate last_updated from state file:
+ - If last_updated is missing or invalid, set state_age_hours = 999 and mark state as stale
+ - Otherwise parse timestamp and continue
+
Extract cached project_type_id(s) from state file if present
Calculate age of state file (current time - last_updated)
Display: "Found old state file (>24 hours). Starting fresh scan."
- Create archive directory: {output_folder}/.archive/
- Archive old state file to: {output_folder}/.archive/project-scan-report-{{timestamp}}.json
+ Attempt to create archive directory: {output_folder}/.archive/
+
+
+ Set resume_mode = true
+ Exit workflow
+
+ Attempt to archive old state file to: {output_folder}/.archive/project-scan-report-{{timestamp}}.json
+
+
+ Set resume_mode = true
+ Exit workflow
+
Set resume_mode = false
+ Set workflow_mode = ""
+ Set scan_level = ""
+ Set cached_project_types = ""
+ Set current_step = ""
+ Set subworkflow_success = false
Continue to Step 3
@@ -112,15 +148,25 @@ Your choice [1/2/3]:
Set resume_mode = true
- Set workflow_mode = {{mode}}
+ Validate persisted mode before assigning workflow_mode:
+ - If mode is one of [deep_dive, initial_scan, full_rescan], set workflow_mode = {{mode}}
+ - Otherwise set workflow_mode = "full_rescan", set resume_mode = false, and continue as fresh scan
+
Set subworkflow_success = false
Load findings summaries from state file
Load cached project_type_id(s) from state file
CONDITIONAL CSV LOADING FOR RESUME:
+
+
+ Load project-types.csv and architecture_registry.csv
+ Load documentation_requirements_csv for active project classification
+
+
For each cached project_type_id, load ONLY the corresponding row from: {documentation_requirements_csv}
Skip loading project-types.csv and architecture_registry.csv (not needed on resume)
Store loaded doc requirements for use in remaining steps
+
Display: "Resuming {{workflow_mode}} from {{current_step}} with cached project type(s): {{cached_project_types}}"
@@ -152,9 +198,21 @@ Your choice [1/2/3]:
- Create archive directory: {output_folder}/.archive/
- Move old state file to: {output_folder}/.archive/project-scan-report-{{timestamp}}.json
+ Attempt to create archive directory: {output_folder}/.archive/
+
+
+ Set resume_mode = true
+ Exit workflow
+
+ Attempt to move old state file to: {output_folder}/.archive/project-scan-report-{{timestamp}}.json
+
+
+ Set resume_mode = true
+ Exit workflow
+
Set resume_mode = false
+ Reset workflow_mode, scan_level, cached_project_types, current_step to defaults
+ Set subworkflow_success = false
Continue to Step 3
@@ -198,6 +256,7 @@ Your choice [1/2/3]:
Set workflow_mode = "full_rescan"
+ Set scan_level = "standard"
Display: "Starting full project rescan..."
Read fully and follow: {installed_path}/workflows/full-scan-instructions.md
Set subworkflow_success = true only if delegated workflow completed without HALT/error
@@ -234,6 +293,7 @@ Your choice [1/2/3]:
Set workflow_mode = "initial_scan"
+ Set scan_level = "initial"
Display: "No existing documentation found. Starting initial project scan..."
Read fully and follow: {installed_path}/workflows/full-scan-instructions.md
Set subworkflow_success = true only if delegated workflow completed without HALT/error
@@ -282,8 +342,13 @@ Your choice [1/2/3]:
+
+
+
+
+
+
diff --git a/src/core/tasks/validate-workflow.md b/src/core/tasks/validate-workflow.md
index 1ffac96e6..65846e0f4 100644
--- a/src/core/tasks/validate-workflow.md
+++ b/src/core/tasks/validate-workflow.md
@@ -31,7 +31,7 @@ Execute a validation checklist against a target file and report findings clearly
- Path-like tokens in checklist items
- First matching path from glob patterns supplied by checklist/input
- Normalize all candidate paths relative to repo root and resolve `.`/`..`.
- - Validate candidate existence and expected file type (`.yaml`, `.yml`, `.json`, or checklist-defined extension).
+ - Validate candidate existence and expected file type (`.md`, `.yaml`, `.yml`, `.json`, or checklist-defined extension).
- If multiple valid candidates remain, prefer explicit key fields over inferred tokens.
- If no valid candidate is found, prompt user with schema example:
- `Please provide the exact file path (relative to repo root), e.g. ./workflows/ci.yml`
@@ -50,11 +50,17 @@ Execute a validation checklist against a target file and report findings clearly
- If checklist requires edits/auto-fixes, follow safe-edit protocol:
- Ask for confirmation before editing.
- Create backup snapshot of target file before changes.
+ - Use deterministic backup location: `{project-root}/.bmad-tmp/validate-workflow/`.
+ - Name backup as `{target-file-name}.{timestamp}.bak` and diff as `{target-file-name}.{timestamp}.diff`.
+ - If temp backup directory cannot be created, fall back to adjacent backup file `{target-file}.bak`.
- Generate reversible diff preview and show it to user.
- Apply edits only after user approval.
- Run syntax/validation checks against edited file.
- If validation fails or user cancels, rollback from backup and report rollback status.
- - Record backup/diff locations in task output.
+ - Record full backup and diff paths in task output.
+ - Support `retain_artifacts` flag (default `false`) to keep backup/diff artifacts when requested.
6. **Finalize**
- Confirm completion and provide the final validation summary.
+ - If edits succeeded and `retain_artifacts` is `false`, delete backup/diff artifacts and report cleanup status.
+ - If edits failed or rollback occurred, preserve backup/diff artifacts and report rollback path explicitly.
diff --git a/test/test-installation-components.js b/test/test-installation-components.js
index 17bed97ee..12bd0e211 100644
--- a/test/test-installation-components.js
+++ b/test/test-installation-components.js
@@ -114,6 +114,12 @@ async function runTests() {
console.log(`========================================${colors.reset}\n`);
const projectRoot = path.join(__dirname, '..');
+ const tmpRoots = [];
+ const trackTmp = async (prefix) => {
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
+ tmpRoots.push(dir);
+ return dir;
+ };
// ============================================================
// Test 1: YAML → XML Agent Compilation (In-Memory)
@@ -432,7 +438,7 @@ async function runTests() {
console.log(`${colors.yellow}Test Suite 11: Gemini Template Extension Guard${colors.reset}\n`);
try {
- const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-gemini-install-'));
+ const tmpRoot = await trackTmp('bmad-gemini-install-');
const projectDir = path.join(tmpRoot, 'project');
const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME);
await fs.ensureDir(projectDir);
@@ -470,7 +476,7 @@ async function runTests() {
console.log(`${colors.yellow}Test Suite 12: Manifest Stale Entry Cleanup Guard${colors.reset}\n`);
try {
- const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-manifest-clean-'));
+ const tmpRoot = await trackTmp('bmad-manifest-clean-');
const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME);
await fs.copy(path.join(projectRoot, 'src', 'core'), path.join(bmadDir, 'core'));
await fs.copy(path.join(projectRoot, 'src', 'bmm'), path.join(bmadDir, 'bmm'));
@@ -505,7 +511,7 @@ async function runTests() {
console.log(`${colors.yellow}Test Suite 13: Internal Task Exposure Guard${colors.reset}\n`);
try {
- const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-task-filter-'));
+ const tmpRoot = await trackTmp('bmad-task-filter-');
const projectDir = path.join(tmpRoot, 'project');
const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME);
const commandsDir = path.join(tmpRoot, 'commands');
@@ -592,7 +598,7 @@ web_bundle:
console.log(`${colors.yellow}Test Suite 16: Task/Tool Standalone + CRLF Guard${colors.reset}\n`);
try {
- const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-standalone-crlf-'));
+ const tmpRoot = await trackTmp('bmad-standalone-crlf-');
const coreTasksDir = path.join(tmpRoot, '_bmad', 'core', 'tasks');
const coreToolsDir = path.join(tmpRoot, '_bmad', 'core', 'tools');
await fs.ensureDir(coreTasksDir);
@@ -717,7 +723,7 @@ internal: true
console.log(`${colors.yellow}Test Suite 18: Codex Task Visibility Guard${colors.reset}\n`);
try {
- const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-codex-visibility-'));
+ const tmpRoot = await trackTmp('bmad-codex-visibility-');
const projectDir = path.join(tmpRoot, 'project');
const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME);
await fs.ensureDir(projectDir);
@@ -751,7 +757,7 @@ internal: true
console.log(`${colors.yellow}Test Suite 19: Empty Artifact Target Guard${colors.reset}\n`);
try {
- const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-empty-target-'));
+ const tmpRoot = await trackTmp('bmad-empty-target-');
const projectDir = path.join(tmpRoot, 'project');
const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME);
await fs.ensureDir(projectDir);
@@ -856,6 +862,10 @@ internal: true
console.log('');
+ for (const tmpRoot of tmpRoots) {
+ await fs.remove(tmpRoot).catch(() => {});
+ }
+
// ============================================================
// Summary
// ============================================================
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 8ce9ae3e9..75151e167 100644
--- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js
+++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js
@@ -75,10 +75,10 @@ class WorkflowCommandGenerator {
if (workflowRelPath.includes('_bmad/')) {
const parts = workflowRelPath.split(/_bmad\//);
if (parts.length > 1) {
- workflowRelPath = parts.slice(1).join('/');
+ workflowRelPath = parts.at(-1);
}
- } else if (workflowRelPath.includes('/src/')) {
- const match = workflowRelPath.match(/\/src\/([^/]+)\/(.+)/);
+ } else if (workflowRelPath.includes('/src/') || workflowRelPath.startsWith('src/')) {
+ const match = workflowRelPath.match(/(?:^|\/)src\/([^/]+)\/(.+)/);
if (match) {
workflowRelPath = `${match[1]}/${match[2]}`;
}
@@ -119,30 +119,9 @@ class WorkflowCommandGenerator {
* Generate command content for a workflow
*/
async generateCommandContent(workflow, bmadDir) {
- // Determine template based on workflow file type
- const templatePath = path.join(path.dirname(this.templatePath), 'workflow-commander.md');
-
- // Load the appropriate template
- const template = await fs.readFile(templatePath, 'utf8');
-
- // Convert source path to installed path
- // From: /Users/.../src/bmm/workflows/.../workflow.md
- // To: {project-root}/_bmad/bmm/workflows/.../workflow.md
- let workflowPath = workflow.path;
-
- // Extract the relative path from source
- if (workflowPath.includes('/src/bmm/')) {
- // bmm is directly under src/
- const match = workflowPath.match(/\/src\/bmm\/(.+)/);
- if (match) {
- workflowPath = `${this.bmadFolderName}/bmm/${match[1]}`;
- }
- } else if (workflowPath.includes('/src/core/')) {
- const match = workflowPath.match(/\/src\/core\/(.+)/);
- if (match) {
- workflowPath = `${this.bmadFolderName}/core/${match[1]}`;
- }
- }
+ // Load the workflow command template
+ const template = await fs.readFile(this.templatePath, 'utf8');
+ const workflowPath = this.mapSourcePathToInstalled(workflow.path);
// Replace template variables
return template
@@ -212,14 +191,15 @@ class WorkflowCommandGenerator {
When running any workflow:
1. Resolve loader paths:
- Primary: {project-root}/${this.bmadFolderName}/core/tasks/workflow.md
- - Fallback: {project-root}/src/core/tasks/workflow.md
+ - Optional dev fallback: {project-root}/src/core/tasks/workflow.md (only if it exists and is readable)
2. Check the primary path exists and is readable before loading
-3. If primary is missing/unreadable, log a warning with the path and error, then try fallback
-4. If fallback is also missing/unreadable, log an error with both attempted paths and stop
-5. LOAD the resolved workflow loader file
-6. Pass the workflow path as 'workflow-config' parameter
-7. Follow workflow.md instructions EXACTLY
-8. Save outputs after EACH section
+3. If primary is missing/unreadable, log a warning with the primary path and error
+4. Only if the dev fallback exists and is readable, try the fallback path; otherwise skip it
+5. If no readable loader is found, log an error with all attempted readable paths and stop
+6. LOAD the resolved workflow loader file
+7. Pass the workflow path as 'workflow-config' parameter
+8. Follow workflow.md instructions EXACTLY
+9. Save outputs after EACH section
## Modes
- Normal: Full interaction
@@ -230,21 +210,33 @@ When running any workflow:
}
transformWorkflowPath(workflowPath) {
- let transformed = workflowPath;
+ return this.mapSourcePathToInstalled(workflowPath, true);
+ }
- if (workflowPath.includes('/src/bmm/')) {
- const match = workflowPath.match(/\/src\/bmm\/(.+)/);
- if (match) {
- transformed = `{project-root}/${this.bmadFolderName}/bmm/${match[1]}`;
- }
- } else if (workflowPath.includes('/src/core/')) {
- const match = workflowPath.match(/\/src\/core\/(.+)/);
- if (match) {
- transformed = `{project-root}/${this.bmadFolderName}/core/${match[1]}`;
- }
+ mapSourcePathToInstalled(sourcePath, includeProjectRootPrefix = false) {
+ if (!sourcePath) {
+ return sourcePath;
}
- return transformed;
+ const normalized = sourcePath.replaceAll('\\', '/');
+ const srcMatch = normalized.match(/(?:^|\/)src\/([^/]+)\/(.+)/);
+ if (srcMatch) {
+ const mapped = `${this.bmadFolderName}/${srcMatch[1]}/${srcMatch[2]}`;
+ return includeProjectRootPrefix ? `{project-root}/${mapped}` : mapped;
+ }
+
+ if (normalized.includes('_bmad/')) {
+ const parts = normalized.split(/_bmad\//);
+ const relative = parts.at(-1);
+ const mapped = `${this.bmadFolderName}/${relative}`;
+ return includeProjectRootPrefix ? `{project-root}/${mapped}` : mapped;
+ }
+
+ if (normalized.startsWith(`${this.bmadFolderName}/`)) {
+ return includeProjectRootPrefix ? `{project-root}/${normalized}` : normalized;
+ }
+
+ return sourcePath;
}
async loadWorkflowManifest(bmadDir) {
diff --git a/tools/cli/installers/lib/modules/manager.js b/tools/cli/installers/lib/modules/manager.js
index 05109dbca..a81c7b15c 100644
--- a/tools/cli/installers/lib/modules/manager.js
+++ b/tools/cli/installers/lib/modules/manager.js
@@ -813,7 +813,6 @@ class ModuleManager {
const newline = frontmatterMatch[0].includes('\r\n') ? '\r\n' : '\n';
try {
- const yaml = require('yaml');
const parsed = yaml.parse(frontmatterMatch[1]);
if (!parsed || typeof parsed !== 'object' || !Object.prototype.hasOwnProperty.call(parsed, 'web_bundle')) {
@@ -897,7 +896,6 @@ class ModuleManager {
let manifestData = {};
if (await fs.pathExists(manifestPath)) {
const manifestContent = await fs.readFile(manifestPath, 'utf8');
- const yaml = require('yaml');
manifestData = yaml.parse(manifestContent);
}
if (!manifestData.agentCustomizations) {
@@ -906,7 +904,6 @@ class ModuleManager {
manifestData.agentCustomizations[path.relative(bmadDir, customizePath)] = originalHash;
// Write back to manifest
- const yaml = require('yaml');
// Clean the manifest data to remove any non-serializable values
const cleanManifestData = structuredClone(manifestData);