`decision-needed`, `patch`, `defer`, dismissed as noise.
+
+If `{spec_file}` is set, add: `Findings written to the review findings section in {spec_file}.`
+Otherwise add: `Findings are listed above. No story file was provided, so nothing was persisted.`
+
+### 4. Resolve decision-needed findings
+
+If `decision_needed` findings exist, present each one with its detail and the options available. The user must decide — the correct fix is ambiguous without their input. Walk through each finding (or batch related ones) and get the user's call. Once resolved, each becomes a `patch`, `defer`, or is dismissed.
+
+If the user chooses to defer, ask: Quick one-line reason for deferring this item? (helps future reviews): — then append that reason to both the story file bullet and the `{deferred_work_file}` entry.
+
+**HALT** — I am waiting for your numbered choice. Reply with only the number. Do not proceed until you select an option.
+
+### 5. Handle `patch` findings
+
+If `patch` findings exist (including any resolved from step 4), HALT. Ask the user:
+
+If `{spec_file}` is set, present all three options:
+
+> **How would you like to handle the `` `patch` findings?**
+> 1. **Apply every patch** — fix all of them now, no per-finding confirmation. Defer and decision-needed items are not touched.
+> 2. **Leave as action items** — they are already in the story file
+> 3. **Walk through each patch** — show details for each before deciding
+
+If `{spec_file}` is **not** set, present only options 1 and 2 (omit "Leave as action items" — findings were not written to a file):
+
+> **How would you like to handle the `
` `patch` findings?**
+> 1. **Apply every patch** — fix all of them now, no per-finding confirmation. Defer and decision-needed items are not touched.
+> 2. **Walk through each patch** — show details for each before deciding
+
+**HALT** — I am waiting for your numbered choice. Reply with only the number. Do not proceed until you select an option.
+
+- **Apply every patch**: Apply every patch finding without per-finding confirmation. Do not modify defer or decision-needed items. After all patches are applied, present a summary of changes made. If `{spec_file}` is set, check off the patch items in the story file (leave defer items as-is).
+- **Leave as action items** (only when `{spec_file}` is set): Done — findings are already written to the story.
+- **Walk through each patch**: Present each finding with full detail, diff context, and suggested fix. After walkthrough, re-offer the applicable options above.
+
+ **HALT** — I am waiting for your numbered choice. Do not proceed until you select an option.
+
+**✅ Code review actions complete**
+
+- Decision-needed resolved:
+- Patches handled:
+- Deferred:
+- Dismissed:
+
+### 6. Update story status and sync sprint tracking
+
+Skip this section if `{spec_file}` is not set.
+
+#### Determine new status based on review outcome
+
+- If all `decision-needed` and `patch` findings were resolved (fixed or dismissed) AND no unresolved HIGH/MEDIUM issues remain: set `{new_status}` = `done`. Update the story file Status section to `done`.
+- If `patch` findings were left as action items, or unresolved issues remain: set `{new_status}` = `in-progress`. Update the story file Status section to `in-progress`.
+
+Save the story file.
+
+#### Sync sprint-status.yaml
+
+If `{story_key}` is not set, skip this subsection and note that sprint status was not synced because no story key was available.
+
+If `{sprint_status}` file exists:
+
+1. Load the FULL `{sprint_status}` file.
+2. Find the `development_status` entry matching `{story_key}`.
+3. If found: update `development_status[{story_key}]` to `{new_status}`. Update `last_updated` to current date. Save the file, preserving ALL comments and structure including STATUS DEFINITIONS.
+4. If `{story_key}` not found in sprint status: warn the user that the story file was updated but sprint-status sync failed.
+
+If `{sprint_status}` file does not exist, note that story status was updated in the story file only.
+
+#### Completion summary
+
+> **Review Complete!**
+>
+> **Story Status:** `{new_status}`
+> **Issues Fixed:**
+> **Action Items Created:**
+> **Deferred:**
+> **Dismissed:**
+
+### 7. Next steps
+
+Present the user with follow-up options:
+
+> **What would you like to do next?**
+> 1. **Start the next story** — run `dev-story` to pick up the next `ready-for-dev` story
+> 2. **Re-run code review** — address findings and review again
+> 3. **Done** — end the workflow
+
+**HALT** — I am waiting for your choice. Do not proceed until the user selects an option.
+
+## On Complete
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
+
+If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
diff --git a/80_bmad/base/.agents/skills/bmad-correct-course/SKILL.md b/80_bmad/base/.agents/skills/bmad-correct-course/SKILL.md
new file mode 100644
index 0000000..f62b917
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-correct-course/SKILL.md
@@ -0,0 +1,301 @@
+---
+name: bmad-correct-course
+description: 'Manage significant changes during sprint execution. Use when the user says "correct course" or "propose sprint change"'
+---
+
+# Correct Course - Sprint Change Management Workflow
+
+**Goal:** Manage significant changes during sprint execution by analyzing impact across all project artifacts and producing a structured Sprint Change Proposal.
+
+**Your Role:** You are a Developer navigating change management. Analyze the triggering issue, assess impact across PRD, epics, architecture, and UX artifacts, and produce an actionable Sprint Change Proposal with clear handoff.
+
+## Conventions
+
+- Bare paths (e.g. `checklist.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+
+- `project_name`, `user_name`
+- `communication_language`, `document_output_language`
+- `user_skill_level`
+- `implementation_artifacts`
+- `planning_artifacts`
+- `project_knowledge`
+- `date` as system-generated current datetime
+- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
+- Language MUST be tailored to `{user_skill_level}`
+- Generate all documents in `{document_output_language}`
+- DOCUMENT OUTPUT: Updated epics, stories, or PRD sections. Clear, actionable changes. User skill level (`{user_skill_level}`) affects conversation style ONLY, not document updates.
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Paths
+
+- `default_output_file` = `{planning_artifacts}/sprint-change-proposal-{date}.md`
+
+## Input Files
+
+| Input | Path | Load Strategy |
+|-------|------|---------------|
+| PRD | `{planning_artifacts}/*prd*.md` (whole) or `{planning_artifacts}/*prd*/*.md` (sharded) | FULL_LOAD |
+| Epics | `{planning_artifacts}/*epic*.md` (whole) or `{planning_artifacts}/*epic*/*.md` (sharded) | FULL_LOAD |
+| Architecture | `{planning_artifacts}/*architecture*.md` (whole) or `{planning_artifacts}/*architecture*/*.md` (sharded) | FULL_LOAD |
+| UX Design | `{planning_artifacts}/*ux*.md` (whole) or `{planning_artifacts}/*ux*/*.md` (sharded) | FULL_LOAD |
+| Spec | `{planning_artifacts}/*spec-*.md` (whole) | FULL_LOAD |
+| Document Project | `{project_knowledge}/index.md` (sharded) | INDEX_GUIDED |
+
+## Execution
+
+### Document Discovery - Loading Project Artifacts
+
+**Strategy**: Course correction needs broad project context to assess change impact accurately. Load all available planning artifacts.
+
+**Discovery Process for FULL_LOAD documents (PRD, Epics, Architecture, UX Design, Spec):**
+
+1. **Search for whole document first** - Look for files matching the whole-document pattern (e.g., `*prd*.md`, `*epic*.md`, `*architecture*.md`, `*ux*.md`, `*spec-*.md`)
+2. **Check for sharded version** - If whole document not found, look for a directory with `index.md` (e.g., `prd/index.md`, `epics/index.md`)
+3. **If sharded version found**:
+ - Read `index.md` to understand the document structure
+ - Read ALL section files listed in the index
+ - Process the combined content as a single document
+4. **Priority**: If both whole and sharded versions exist, use the whole document
+
+**Discovery Process for INDEX_GUIDED documents (Document Project):**
+
+1. **Search for index file** - Look for `{project_knowledge}/index.md`
+2. **If found**: Read the index to understand available documentation sections
+3. **Selectively load sections** based on relevance to the change being analyzed — do NOT load everything, only sections that relate to the impacted areas
+4. **This document is optional** — skip if `{project_knowledge}` does not exist (greenfield projects)
+
+**Fuzzy matching**: Be flexible with document names — users may use variations like `prd.md`, `bmm-prd.md`, `product-requirements.md`, etc.
+
+**Missing documents**: Not all documents may exist. PRD and Epics are essential; Architecture, UX Design, Spec, and Document Project are loaded if available. HALT if PRD or Epics cannot be found.
+
+
+
+
+ Confirm change trigger and gather user description of the issue
+ Ask: "What specific issue or change has been identified that requires navigation?"
+ Verify access to project documents:
+ - PRD (Product Requirements Document) — required
+ - Current Epics and Stories — required
+ - Architecture documentation — optional, load if available
+ - UI/UX specifications — optional, load if available
+ Ask user for mode preference:
+ - **Incremental** (recommended): Refine each edit collaboratively
+ - **Batch**: Present all changes at once for review
+ Store mode selection for use throughout workflow
+
+HALT: "Cannot navigate change without clear understanding of the triggering issue. Please provide specific details about what needs to change and why."
+
+HALT: "Need access to PRD and Epics to assess change impact. Please ensure these documents are accessible. Architecture and UI/UX will be used if available."
+
+
+
+ Read fully and follow the systematic analysis from: checklist.md
+ Work through each checklist section interactively with the user
+ Record status for each checklist item:
+ - [x] Done - Item completed successfully
+ - [N/A] Skip - Item not applicable to this change
+ - [!] Action-needed - Item requires attention or follow-up
+ Maintain running notes of findings and impacts discovered
+ Present checklist progress after each major section
+
+Identify blocking issues and work with user to resolve before continuing
+
+
+
+Based on checklist findings, create explicit edit proposals for each identified artifact
+
+For Story changes:
+
+- Show old → new text format
+- Include story ID and section being modified
+- Provide rationale for each change
+- Example format:
+
+ ```
+ Story: [STORY-123] User Authentication
+ Section: Acceptance Criteria
+
+ OLD:
+ - User can log in with email/password
+
+ NEW:
+ - User can log in with email/password
+ - User can enable 2FA via authenticator app
+
+ Rationale: Security requirement identified during implementation
+ ```
+
+For PRD modifications:
+
+- Specify exact sections to update
+- Show current content and proposed changes
+- Explain impact on MVP scope and requirements
+
+For Architecture changes:
+
+- Identify affected components, patterns, or technology choices
+- Describe diagram updates needed
+- Note any ripple effects on other components
+
+For UI/UX specification updates:
+
+- Reference specific screens or components
+- Show wireframe or flow changes needed
+- Connect changes to user experience impact
+
+
+ Present each edit proposal individually
+ Review and refine this change? Options: Approve [a], Edit [e], Skip [s]
+ Iterate on each proposal based on user feedback
+
+
+Collect all edit proposals and present together at end of step
+
+
+
+
+Compile comprehensive Sprint Change Proposal document with following sections:
+
+Section 1: Issue Summary
+
+- Clear problem statement describing what triggered the change
+- Context about when/how the issue was discovered
+- Evidence or examples demonstrating the issue
+
+Section 2: Impact Analysis
+
+- Epic Impact: Which epics are affected and how
+- Story Impact: Current and future stories requiring changes
+- Artifact Conflicts: PRD, Architecture, UI/UX documents needing updates
+- Technical Impact: Code, infrastructure, or deployment implications
+
+Section 3: Recommended Approach
+
+- Present chosen path forward from checklist evaluation:
+ - Direct Adjustment: Modify/add stories within existing plan
+ - Potential Rollback: Revert completed work to simplify resolution
+ - MVP Review: Reduce scope or modify goals
+- Provide clear rationale for recommendation
+- Include effort estimate, risk assessment, and timeline impact
+
+Section 4: Detailed Change Proposals
+
+- Include all refined edit proposals from Step 3
+- Group by artifact type (Stories, PRD, Architecture, UI/UX)
+- Ensure each change includes before/after and justification
+
+Section 5: Implementation Handoff
+
+- Categorize change scope:
+ - Minor: Direct implementation by Developer agent
+ - Moderate: Backlog reorganization needed (PO/DEV)
+ - Major: Fundamental replan required (PM/Architect)
+- Specify handoff recipients and their responsibilities
+- Define success criteria for implementation
+
+Present complete Sprint Change Proposal to user
+Write Sprint Change Proposal document to {default_output_file}
+Review complete proposal. Continue [c] or Edit [e]?
+
+
+
+Get explicit user approval for complete proposal
+Do you approve this Sprint Change Proposal for implementation? (yes/no/revise)
+
+
+ Gather specific feedback on what needs adjustment
+ Return to appropriate step to address concerns
+ If changes needed to edit proposals
+ If changes needed to overall proposal structure
+
+
+
+
+ Finalize Sprint Change Proposal document
+ Determine change scope classification:
+
+- **Minor**: Can be implemented directly by Developer agent
+- **Moderate**: Requires backlog reorganization and PO/DEV coordination
+- **Major**: Needs fundamental replan with PM/Architect involvement
+
+Provide appropriate handoff based on scope:
+
+
+
+
+ Route to: Developer agent for direct implementation
+ Deliverables: Finalized edit proposals and implementation tasks
+
+
+
+ Route to: Product Owner / Developer agents
+ Deliverables: Sprint Change Proposal + backlog reorganization plan
+
+
+
+ Route to: Product Manager / Solution Architect
+ Deliverables: Complete Sprint Change Proposal + escalation notice
+
+Confirm handoff completion and next steps with user
+Document handoff in workflow execution log
+
+
+
+
+
+Summarize workflow execution:
+ - Issue addressed: {{change_trigger}}
+ - Change scope: {{scope_classification}}
+ - Artifacts modified: {{list_of_artifacts}}
+ - Routed to: {{handoff_recipients}}
+
+Confirm all deliverables produced:
+
+- Sprint Change Proposal document
+- Specific edit proposals with before/after
+- Implementation handoff plan
+
+Report workflow completion to user with personalized message: "Correct Course workflow complete, {user_name}!"
+Remind user of success criteria and next steps for Developer agent
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.
+
+
+
diff --git a/80_bmad/base/_bmad/bmm/workflows/4-implementation/correct-course/checklist.md b/80_bmad/base/.agents/skills/bmad-correct-course/checklist.md
similarity index 97%
rename from 80_bmad/base/_bmad/bmm/workflows/4-implementation/correct-course/checklist.md
rename to 80_bmad/base/.agents/skills/bmad-correct-course/checklist.md
index f13ab9b..b56feb6 100644
--- a/80_bmad/base/_bmad/bmm/workflows/4-implementation/correct-course/checklist.md
+++ b/80_bmad/base/.agents/skills/bmad-correct-course/checklist.md
@@ -1,6 +1,6 @@
# Change Navigation Checklist
-This checklist is executed as part of: {project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml
+This checklist is executed as part of: ./workflow.md
Work through each section systematically with the user, recording findings and impacts
@@ -217,8 +217,8 @@
Establish agent handoff plan
Identify which roles/agents will execute the changes:
- - Development team (for implementation)
- - Product Owner / Scrum Master (for backlog changes)
+ - Developer agent (for implementation)
+ - Product Owner / Developer (for backlog changes)
- Product Manager / Architect (for strategic changes)
Define responsibilities for each role
[ ] Done / [ ] N/A / [ ] Action-needed
diff --git a/80_bmad/base/.agents/skills/bmad-correct-course/customize.toml b/80_bmad/base/.agents/skills/bmad-correct-course/customize.toml
new file mode 100644
index 0000000..d23577e
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-correct-course/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-correct-course. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All sprint changes require PO sign-off before execution."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step 6 (Workflow Completion),
+# after the Sprint Change Proposal is finalized and handoff is confirmed. Override wins.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-create-architecture/SKILL.md b/80_bmad/base/.agents/skills/bmad-create-architecture/SKILL.md
new file mode 100644
index 0000000..b1a77e0
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-architecture/SKILL.md
@@ -0,0 +1,30 @@
+---
+name: bmad-create-architecture
+description: 'DEPRECATED — consolidated into bmad-architecture create intent - this skill will be removed in v7 in favor of `bmad-architecture`.'
+---
+
+# DEPRECATED — forwards to bmad-architecture (create intent)
+
+This skill was consolidated into `bmad-architecture`. It is retained as a thin compatibility shim so existing invocations by name and `_bmad/custom/bmad-create-architecture.toml` override files keep working. New work should invoke `bmad-architecture` directly — it detects create / update / validate intent from the conversation.
+
+## On Activation
+
+1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-architecture.toml` and `bmad-create-architecture.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
+
+2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
+
+3. Emit a deprecation notice to the user in `{communication_language}`:
+
+ > Notice: `bmad-create-architecture` is deprecated and will be removed in a future release. It now forwards to `bmad-architecture` with create intent. To silence this notice and access the full new customization surface (`spine_template`, `spine_output_path`, `run_folder_pattern`, `doc_standards`, `external_sources`, `external_handoffs`, `finalize_reviewers`), migrate `_bmad/custom/bmad-create-architecture.toml` to `_bmad/custom/bmad-architecture.toml` and invoke `bmad-architecture` directly next time. Customization fields that were in this version still remain in the new version and will be respected if present in `_bmad/custom/bmad-architecture.toml`, but the new version also supports additional fields that you can take advantage of by migrating.
+
+4. Invoke `bmad-architecture` with the following context. Pass these as the activating context so `bmad-architecture` honors them instead of resolving its own customization from scratch:
+
+ - **Intent:** `create` — skip `bmad-architecture`'s usual intent detection step.
+ - **Pre-resolved legacy customization** — use these in place of resolving from `bmad-architecture`'s own `customize.toml` for the four legacy fields. For everything else (`spine_template`, `spine_output_path`, `run_folder_pattern`, `doc_standards`, `external_sources`, `external_handoffs`, `finalize_reviewers`), use `bmad-architecture`'s own defaults and overrides as normal:
+ - `activation_steps_prepend` = the resolved value from step 1
+ - `activation_steps_append` = the resolved value from step 1
+ - `persistent_facts` = the resolved value from step 1
+ - `on_complete` = the resolved value from step 1
+ - **Original user input:** forward whatever the user said when invoking this skill verbatim.
+
+ `bmad-architecture` takes the workflow from here. Do not execute any further steps in this shim.
diff --git a/80_bmad/base/.agents/skills/bmad-create-architecture/customize.toml b/80_bmad/base/.agents/skills/bmad-create-architecture/customize.toml
new file mode 100644
index 0000000..3275612
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-architecture/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-create-architecture. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "Our org is AWS-only -- do not propose GCP or Azure."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step 8 (Architecture Completion & Handoff),
+# after the architecture document frontmatter is updated and next-steps guidance is given.
+# Override wins. Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/SKILL.md b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/SKILL.md
new file mode 100644
index 0000000..a97bc24
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/SKILL.md
@@ -0,0 +1,93 @@
+---
+name: bmad-create-epics-and-stories
+description: 'Break requirements into epics and user stories. Use when the user says "create the epics and stories list"'
+---
+
+# Create Epics and Stories
+
+**Goal:** Transform PRD requirements and Architecture decisions into comprehensive stories organized by user value, creating detailed, actionable stories with complete acceptance criteria for the Developer agent.
+
+**Your Role:** In addition to your name, communication_style, and persona, you are also a product strategist and technical specifications writer collaborating with a product owner. This is a partnership, not a client-vendor relationship. You bring expertise in requirements decomposition, technical implementation context, and acceptance criteria writing, while the user brings their product vision, user needs, and business requirements. Work together as equals.
+
+## Conventions
+
+- Bare paths (e.g. `steps/step-01-validate-prerequisites.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## WORKFLOW ARCHITECTURE
+
+This uses **step-file architecture** for disciplined execution:
+
+### Core Principles
+
+- **Micro-file Design**: Each step toward the overall goal is a self-contained instruction file; adhere to one file at a time, as directed
+- **Just-In-Time Loading**: Only 1 current step file will be loaded and followed to completion - never load future step files until told to do so
+- **Sequential Enforcement**: Sequence within the step files must be completed in order, no skipping or optimization allowed
+- **State Tracking**: Document progress in output file frontmatter using `stepsCompleted` array when a workflow produces a document
+- **Append-Only Building**: Build documents by appending content as directed to the output file
+
+### Step Processing Rules
+
+1. **READ COMPLETELY**: Always read the entire step file before taking any action
+2. **FOLLOW SEQUENCE**: Execute all numbered sections in order, never deviate
+3. **WAIT FOR INPUT**: If a menu is presented, halt and wait for user selection
+4. **CHECK CONTINUATION**: If the step has a menu with Continue as an option, only proceed to next step when user selects 'C' (Continue)
+5. **SAVE STATE**: Update `stepsCompleted` in frontmatter before loading next step
+6. **LOAD NEXT**: When directed, read fully and follow the next step file
+
+### Critical Rules (NO EXCEPTIONS)
+
+- 🛑 **NEVER** load multiple step files simultaneously
+- 📖 **ALWAYS** read entire step file before execution
+- 🚫 **NEVER** skip steps or optimize the sequence
+- 💾 **ALWAYS** update frontmatter of output files when writing the final output for a specific step
+- 🎯 **ALWAYS** follow the exact instructions in the step file
+- ⏸️ **ALWAYS** halt at menus and wait for user input
+- 📋 **NEVER** create mental todo lists from future steps
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+- Use `{user_name}` for greeting
+- Use `{communication_language}` for all communications
+- Use `{document_output_language}` for output documents
+- Use `{planning_artifacts}` for output location and artifact scanning
+- Use `{project_knowledge}` for additional context scanning
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Execution
+
+Read fully and follow: `./steps/step-01-validate-prerequisites.md` to begin the workflow.
diff --git a/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/customize.toml b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/customize.toml
new file mode 100644
index 0000000..fb05efa
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-create-epics-and-stories. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All epics must deliver complete end-to-end user value."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step 4 (Final Validation) and the
+# user confirms [C] Complete — after the epics.md is saved and bmad-help is invoked.
+# Override wins. Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md
similarity index 64%
rename from 80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md
rename to 80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md
index c8d6b13..5930a77 100644
--- a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md
@@ -1,25 +1,3 @@
----
-name: 'step-01-validate-prerequisites'
-description: 'Validate required documents exist and extract all requirements for epic and story creation'
-
-# Path Definitions
-workflow_path: '{project-root}/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories'
-
-# File References
-thisStepFile: './step-01-validate-prerequisites.md'
-nextStepFile: './step-02-design-epics.md'
-workflowFile: '{workflow_path}/workflow.md'
-outputFile: '{planning_artifacts}/epics.md'
-epicsTemplate: '{workflow_path}/templates/epics-template.md'
-
-# Task References
-advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
-partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
-
-# Template References
-epicsTemplate: '{workflow_path}/templates/epics-template.md'
----
-
# Step 1: Validate Prerequisites and Extract Requirements
## STEP GOAL:
@@ -54,7 +32,7 @@ To validate that all required input documents exist and extract all requirements
## EXECUTION PROTOCOLS:
- 🎯 Extract requirements systematically from all documents
-- 💾 Populate {outputFile} with extracted requirements
+- 💾 Populate {planning_artifacts}/epics.md with extracted requirements
- 📖 Update frontmatter with extraction progress
- 🚫 FORBIDDEN to load next step until user selects 'C' and requirements are extracted
@@ -70,7 +48,7 @@ Verify required documents exist and are complete:
1. **PRD.md** - Contains requirements (FRs and NFRs) and product scope
2. **Architecture.md** - Contains technical decisions, API contracts, data models
-3. **UX Design.md** (if UI exists) - Contains interaction patterns, mockups, user flows
+3. **UX design contract** (if UI exists) - Contains visual identity, interaction patterns, mockups, and user flows
### 2. Document Discovery and Validation
@@ -88,10 +66,18 @@ Search for required documents using these patterns (sharded means a large docume
**UX Design Document Search (Optional):**
-1. `{planning_artifacts}/*ux*.md` (whole document)
-2. `{planning_artifacts}/*ux*/index.md` (sharded version)
+1. `{planning_artifacts}/ux-designs/ux-*/DESIGN.md` and `{planning_artifacts}/ux-designs/ux-*/EXPERIENCE.md` (bmad-ux spine pair)
+2. `{planning_artifacts}/*ux*.md` (legacy whole document)
+3. `{planning_artifacts}/*ux*/index.md` (legacy sharded version)
-Before proceeding, Ask the user if there are any other documents to include for analysis, and if anything found should be excluded. Wait for user confirmation. Once confirmed, create the {outputFile} from the {epicsTemplate} and in the front matter list the files in the array of `inputDocuments: []`.
+For each matching bmad-ux run folder, treat `DESIGN.md` and `EXPERIENCE.md` as one UX design contract:
+
+- Confirm and load both files together. `DESIGN.md` owns visual identity and design tokens; `EXPERIENCE.md` owns information architecture, behavior, states, interactions, accessibility, and journeys.
+- Add both files to the `inputDocuments: []` frontmatter array.
+- If only one spine exists, report the incomplete pair and ask whether the user wants to include the partial UX handoff.
+- If multiple run folders match, show each run folder with the spine frontmatter `status` and `updated` values when available, then ask the user which UX design contract to include.
+
+Before proceeding, Ask the user if there are any other documents to include for analysis, and if anything found should be excluded. Wait for user confirmation. Once confirmed, create the {planning_artifacts}/epics.md from the ../templates/epics-template.md and in the front matter list the files in the array of `inputDocuments: []`.
### 3. Extract Functional Requirements (FRs)
@@ -154,31 +140,43 @@ Review the Architecture document for technical requirements that impact epic and
...
```
-### 6. Extract Additional Requirements from UX (if exists)
+### 6. Extract UX Design Requirements (if UX document exists)
-Review the UX document for requirements that affect epic and story creation:
+**IMPORTANT**: The UX Design Specification is a first-class input document, not supplementary material. Requirements from the UX spec must be extracted with the same rigor as PRD functional requirements.
+
+Read the FULL UX design contract and extract ALL actionable work items. For a bmad-ux spine pair, read both `DESIGN.md` and `EXPERIENCE.md`:
**Look for:**
-- Responsive design requirements
-- Accessibility requirements
-- Browser/device compatibility
-- User interaction patterns that need implementation
-- Animation or transition requirements
-- Error handling UX requirements
+- **Design token work**: Color systems, spacing scales, typography tokens that need implementation or consolidation
+- **Component proposals**: Reusable UI components identified in the UX spec (e.g., ConfirmActions, StatusMessage, EmptyState, FocusIndicator)
+- **Visual standardization**: Semantic CSS classes, consistent color palette usage, design pattern consolidation
+- **Accessibility requirements**: Contrast audit fixes, ARIA patterns, keyboard navigation, screen reader support
+- **Responsive design requirements**: Breakpoints, layout adaptations, mobile-specific interactions
+- **Interaction patterns**: Animations, transitions, loading states, error handling UX
+- **Browser/device compatibility**: Target platforms, progressive enhancement requirements
-**Add these to Additional Requirements list.**
+**Format UX Design Requirements as a SEPARATE section (not merged into Additional Requirements):**
+
+```
+UX-DR1: [Actionable UX design requirement with clear implementation scope]
+UX-DR2: [Actionable UX design requirement with clear implementation scope]
+...
+```
+
+**🚨 CRITICAL**: Do NOT reduce UX requirements to vague summaries. Each UX-DR must be specific enough to generate a story with testable acceptance criteria. If the UX spec identifies 6 reusable components, list all 6 — not "create reusable components."
### 7. Load and Initialize Template
-Load {epicsTemplate} and initialize {outputFile}:
+Load ../templates/epics-template.md and initialize {planning_artifacts}/epics.md:
-1. Copy the entire template to {outputFile}
+1. Copy the entire template to {planning_artifacts}/epics.md
2. Replace {{project_name}} with the actual project name
3. Replace placeholder sections with extracted requirements:
- {{fr_list}} → extracted FRs
- {{nfr_list}} → extracted NFRs
- - {{additional_requirements}} → extracted additional requirements
+ - {{additional_requirements}} → extracted additional requirements (from Architecture)
+ - {{ux_design_requirements}} → extracted UX Design Requirements (if UX document exists)
4. Leave {{requirements_coverage_map}} and {{epics_list}} as placeholders for now
### 8. Present Extracted Requirements
@@ -197,12 +195,17 @@ Display to user:
- Display key NFRs
- Ask if any constraints were missed
-**Additional Requirements:**
+**Additional Requirements (Architecture):**
- Summarize technical requirements from Architecture
-- Summarize UX requirements (if applicable)
- Verify completeness
+**UX Design Requirements (if applicable):**
+
+- Show count of UX-DRs found
+- Display key UX Design requirements (design tokens, components, accessibility)
+- Verify each UX-DR is specific enough for story creation
+
### 9. Get User Confirmation
Ask: "Do these extracted requirements accurately represent what needs to be built? Any additions or corrections?"
@@ -211,11 +214,12 @@ Update the requirements based on user feedback until confirmation is received.
## CONTENT TO SAVE TO DOCUMENT:
-After extraction and confirmation, update {outputFile} with:
+After extraction and confirmation, update {planning_artifacts}/epics.md with:
- Complete FR list in {{fr_list}} section
- Complete NFR list in {{nfr_list}} section
- All additional requirements in {{additional_requirements}} section
+- UX Design requirements in {{ux_design_requirements}} section (if UX document exists)
### 10. Present MENU OPTIONS
@@ -229,12 +233,12 @@ Display: `**Confirm the Requirements are complete and correct to [C] continue:**
#### Menu Handling Logic:
-- IF C: Save all to {outputFile}, update frontmatter, then read fully and follow: {nextStepFile}
+- IF C: Save all to {planning_artifacts}/epics.md, update frontmatter, then read fully and follow: ./step-02-design-epics.md
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#10-present-menu-options)
## CRITICAL STEP COMPLETION NOTE
-ONLY WHEN C is selected and all requirements are saved to document and frontmatter is updated, will you then read fully and follow: {nextStepFile} to begin epic design step.
+ONLY WHEN C is selected and all requirements are saved to document and frontmatter is updated, will you then read fully and follow: ./step-02-design-epics.md to begin epic design step.
---
diff --git a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-02-design-epics.md
similarity index 74%
rename from 80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md
rename to 80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-02-design-epics.md
index 1b497c2..937f2df 100644
--- a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-02-design-epics.md
@@ -1,24 +1,3 @@
----
-name: 'step-02-design-epics'
-description: 'Design and approve the epics_list that will organize all requirements into user-value-focused epics'
-
-# Path Definitions
-workflow_path: '{project-root}/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories'
-
-# File References
-thisStepFile: './step-02-design-epics.md'
-nextStepFile: './step-03-create-stories.md'
-workflowFile: '{workflow_path}/workflow.md'
-outputFile: '{planning_artifacts}/epics.md'
-
-# Task References
-advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
-partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
-
-# Template References
-epicsTemplate: '{workflow_path}/templates/epics-template.md'
----
-
# Step 2: Design Epic List
## STEP GOAL:
@@ -54,7 +33,7 @@ To design and get approval for the epics_list that will organize all requirement
## EXECUTION PROTOCOLS:
- 🎯 Design epics collaboratively based on extracted requirements
-- 💾 Update {{epics_list}} in {outputFile}
+- 💾 Update {{epics_list}} in {planning_artifacts}/epics.md
- 📖 Document the FR coverage mapping
- 🚫 FORBIDDEN to load next step until user approves epics_list
@@ -62,7 +41,7 @@ To design and get approval for the epics_list that will organize all requirement
### 1. Review Extracted Requirements
-Load {outputFile} and review:
+Load {planning_artifacts}/epics.md and review:
- **Functional Requirements:** Count and review FRs from Step 1
- **Non-Functional Requirements:** Review NFRs that need to be addressed
@@ -76,7 +55,8 @@ Load {outputFile} and review:
2. **Requirements Grouping**: Group related FRs that deliver cohesive user outcomes
3. **Incremental Delivery**: Each epic should deliver value independently
4. **Logical Flow**: Natural progression from user's perspective
-5. **🔗 Dependency-Free Within Epic**: Stories within an epic must NOT depend on future stories
+5. **Dependency-Free Within Epic**: Stories within an epic must NOT depend on future stories
+6. **Implementation Efficiency**: Consider consolidating epics that all modify the same core files into fewer epics
**⚠️ CRITICAL PRINCIPLE:**
Organize by USER VALUE, not technical layers:
@@ -95,6 +75,18 @@ Organize by USER VALUE, not technical layers:
- Epic 3: Frontend Components (creates reusable components) - **No user value**
- Epic 4: Deployment Pipeline (CI/CD setup) - **No user value**
+**❌ WRONG Epic Examples (File Churn on Same Component):**
+
+- Epic 1: File Upload (modifies model, controller, web form, web API)
+- Epic 2: File Status (modifies model, controller, web form, web API)
+- Epic 3: File Access permissions (modifies model, controller, web form, web API)
+- All three epics touch the same files — consolidate into one epic with ordered stories
+
+**✅ CORRECT Alternative:**
+
+- Epic 1: File Management Enhancement (upload, status, permissions as stories within one epic)
+- Rationale: Single component, fully pre-designed, no feedback loop between epics
+
**🔗 DEPENDENCY RULES:**
- Each epic must deliver COMPLETE functionality for its domain
@@ -103,21 +95,38 @@ Organize by USER VALUE, not technical layers:
### 3. Design Epic Structure Collaboratively
-**Step A: Identify User Value Themes**
+**Step A: Assess Context and Identify Themes**
+
+First, assess how much of the solution design is already validated (Architecture, UX, Test Design).
+When the outcome is certain and direction changes between epics are unlikely, prefer fewer but larger epics.
+Split into multiple epics when there is a genuine risk boundary or when early feedback could change direction
+of following epics.
+
+Then, identify user value themes:
- Look for natural groupings in the FRs
- Identify user journeys or workflows
- Consider user types and their goals
**Step B: Propose Epic Structure**
-For each proposed epic:
+
+For each proposed epic (considering whether epics share the same core files):
1. **Epic Title**: User-centric, value-focused
2. **User Outcome**: What users can accomplish after this epic
3. **FR Coverage**: Which FR numbers this epic addresses
4. **Implementation Notes**: Any technical or UX considerations
-**Step C: Create the epics_list**
+**Step C: Review for File Overlap**
+
+Assess whether multiple proposed epics repeatedly target the same core files. If overlap is significant:
+
+- Distinguish meaningful overlap (same component end-to-end) from incidental sharing
+- Ask whether to consolidate into one epic with ordered stories
+- If confirmed, merge the epic FRs into a single epic, preserving dependency flow: each story must still fit within
+ a single dev agent's context
+
+**Step D: Create the epics_list**
Format the epics_list as:
@@ -182,7 +191,7 @@ If user wants changes:
## CONTENT TO UPDATE IN DOCUMENT:
-After approval, update {outputFile}:
+After approval, update {planning_artifacts}/epics.md:
1. Replace {{epics_list}} placeholder with the approved epic list
2. Replace {{requirements_coverage_map}} with the coverage map
@@ -194,9 +203,9 @@ Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Cont
#### Menu Handling Logic:
-- IF A: Read fully and follow: {advancedElicitationTask}
-- IF P: Read fully and follow: {partyModeWorkflow}
-- IF C: Save approved epics_list to {outputFile}, update frontmatter, then read fully and follow: {nextStepFile}
+- IF A: Invoke the `bmad-advanced-elicitation` skill
+- IF P: Invoke the `bmad-party-mode` skill
+- IF C: Save approved epics_list to {planning_artifacts}/epics.md, update frontmatter, then read fully and follow: ./step-03-create-stories.md
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#8-present-menu-options)
#### EXECUTION RULES:
@@ -208,7 +217,7 @@ Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Cont
## CRITICAL STEP COMPLETION NOTE
-ONLY WHEN C is selected and the approved epics_list is saved to document, will you then read fully and follow: {nextStepFile} to begin story creation step.
+ONLY WHEN C is selected and the approved epics_list is saved to document, will you then read fully and follow: ./step-03-create-stories.md to begin story creation step.
---
diff --git a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-03-create-stories.md
similarity index 85%
rename from 80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md
rename to 80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-03-create-stories.md
index 2e13f9b..14caafe 100644
--- a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-03-create-stories.md
@@ -1,24 +1,3 @@
----
-name: 'step-03-create-stories'
-description: 'Generate all epics with their stories following the template structure'
-
-# Path Definitions
-workflow_path: '{project-root}/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories'
-
-# File References
-thisStepFile: './step-03-create-stories.md'
-nextStepFile: './step-04-final-validation.md'
-workflowFile: '{workflow_path}/workflow.md'
-outputFile: '{planning_artifacts}/epics.md'
-
-# Task References
-advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
-partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
-
-# Template References
-epicsTemplate: '{workflow_path}/templates/epics-template.md'
----
-
# Step 3: Generate Epics and Stories
## STEP GOAL:
@@ -54,7 +33,7 @@ To generate all epics with their stories based on the approved epics_list, follo
## EXECUTION PROTOCOLS:
- 🎯 Generate stories collaboratively with user input
-- 💾 Append epics and stories to {outputFile} following template
+- 💾 Append epics and stories to {planning_artifacts}/epics.md following template
- 📖 Process epics one at a time in sequence
- 🚫 FORBIDDEN to skip any epic or rush through stories
@@ -62,13 +41,15 @@ To generate all epics with their stories based on the approved epics_list, follo
### 1. Load Approved Epic Structure
-Load {outputFile} and review:
+Load {planning_artifacts}/epics.md and review:
- Approved epics_list from Step 2
- FR coverage map
-- All requirements (FRs, NFRs, additional)
+- All requirements (FRs, NFRs, additional, **UX Design requirements if present**)
- Template structure at the end of the document
+**UX Design Integration**: If UX Design Requirements (UX-DRs) were extracted in Step 1, ensure they are visible during story creation. UX-DRs must be covered by stories — either within existing epics (e.g., accessibility fixes for a feature epic) or in a dedicated "Design System / UX Polish" epic.
+
### 2. Explain Story Creation Approach
**STORY CREATION GUIDELINES:**
@@ -146,6 +127,7 @@ Display:
- Epic goal statement
- FRs covered by this epic
- Any NFRs or additional requirements relevant
+- Any UX Design Requirements (UX-DRs) relevant to this epic
#### B. Story Breakdown
@@ -183,7 +165,7 @@ After writing each story:
When story is approved:
-- Append it to {outputFile} following template structure
+- Append it to {planning_artifacts}/epics.md following template structure
- Use correct numbering (Epic N, Story M)
- Maintain proper markdown formatting
@@ -207,11 +189,12 @@ After all epics and stories are generated:
- Verify the document follows template structure exactly
- Ensure all placeholders are replaced
- Confirm all FRs are covered
+- **Confirm all UX Design Requirements (UX-DRs) are covered by at least one story** (if UX document was an input)
- Check formatting consistency
## TEMPLATE STRUCTURE COMPLIANCE:
-The final {outputFile} must follow this structure exactly:
+The final {planning_artifacts}/epics.md must follow this structure exactly:
1. **Overview** section with project name
2. **Requirements Inventory** with all three subsections populated
@@ -231,9 +214,9 @@ Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Cont
#### Menu Handling Logic:
-- IF A: Read fully and follow: {advancedElicitationTask}
-- IF P: Read fully and follow: {partyModeWorkflow}
-- IF C: Save content to {outputFile}, update frontmatter, then read fully and follow: {nextStepFile}
+- IF A: Invoke the `bmad-advanced-elicitation` skill
+- IF P: Invoke the `bmad-party-mode` skill
+- IF C: Save content to {planning_artifacts}/epics.md, update frontmatter, then read fully and follow: ./step-04-final-validation.md
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#7-present-final-menu-options)
#### EXECUTION RULES:
@@ -245,7 +228,7 @@ Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Cont
## CRITICAL STEP COMPLETION NOTE
-ONLY WHEN [C continue option] is selected and [all epics and stories saved to document following the template structure exactly], will you then read fully and follow: `{nextStepFile}` to begin final validation phase.
+ONLY WHEN [C continue option] is selected and [all epics and stories saved to document following the template structure exactly], will you then read fully and follow: `./step-04-final-validation.md` to begin final validation phase.
---
diff --git a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-04-final-validation.md
similarity index 82%
rename from 80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md
rename to 80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-04-final-validation.md
index 4ee791a..6d2dd9d 100644
--- a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/steps/step-04-final-validation.md
@@ -1,23 +1,3 @@
----
-name: 'step-04-final-validation'
-description: 'Validate complete coverage of all requirements and ensure implementation readiness'
-
-# Path Definitions
-workflow_path: '{project-root}/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories'
-
-# File References
-thisStepFile: './step-04-final-validation.md'
-workflowFile: '{workflow_path}/workflow.md'
-outputFile: '{planning_artifacts}/epics.md'
-
-# Task References
-advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
-partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
-
-# Template References
-epicsTemplate: '{workflow_path}/templates/epics-template.md'
----
-
# Step 4: Final Validation
## STEP GOAL:
@@ -110,6 +90,12 @@ Review the complete epic and story breakdown to ensure EVERY FR is covered:
- Dependencies flow naturally
- Foundation stories only setup what's needed
- No big upfront technical work
+- **File Churn Check:** Do multiple epics repeatedly modify the same core files?
+ - Assess whether the overlap pattern suggests unnecessary churn or is incidental
+ - If overlap is significant: Validate that splitting provides genuine value (risk mitigation, feedback loops, context size limits)
+ - If no justification for the split: Recommend consolidation into fewer epics
+ - ❌ WRONG: Multiple epics each modify the same core files with no feedback loop between them
+ - ✅ RIGHT: Epics target distinct files/components, OR consolidation was explicitly considered and rejected with rationale
### 5. Dependency Validation (CRITICAL)
@@ -142,8 +128,16 @@ If all validations pass:
**Present Final Menu:**
**All validations complete!** [C] Complete Workflow
+HALT — wait for user input before proceeding.
+
When C is selected, the workflow is complete and the epics.md is ready for development.
-Epics and Stories complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md`
+Epics and Stories complete. Invoke the `bmad-help` skill.
Upon Completion of task output: offer to answer any questions about the Epics and Stories.
+
+## On Complete
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
+
+If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
diff --git a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/templates/epics-template.md
similarity index 94%
rename from 80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md
rename to 80_bmad/base/.agents/skills/bmad-create-epics-and-stories/templates/epics-template.md
index 05afe1f..bf80c7f 100644
--- a/80_bmad/base/_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md
+++ b/80_bmad/base/.agents/skills/bmad-create-epics-and-stories/templates/epics-template.md
@@ -23,6 +23,10 @@ This document provides the complete epic and story breakdown for {{project_name}
{{additional_requirements}}
+### UX Design Requirements
+
+{{ux_design_requirements}}
+
### FR Coverage Map
{{requirements_coverage_map}}
diff --git a/80_bmad/base/.agents/skills/bmad-create-prd/SKILL.md b/80_bmad/base/.agents/skills/bmad-create-prd/SKILL.md
new file mode 100644
index 0000000..7062d0e
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-prd/SKILL.md
@@ -0,0 +1,30 @@
+---
+name: bmad-create-prd
+description: 'DEPRECATED — consolidated into bmad-prd create intent - this skill will be removed in v7 in favor of `bmad-prd`.'
+---
+
+# DEPRECATED — forwards to bmad-prd (create intent)
+
+This skill was consolidated into `bmad-prd`. It is retained as a thin compatibility shim so existing invocations by name and `_bmad/custom/bmad-create-prd.toml` override files keep working. New work should invoke `bmad-prd` directly — it detects create / update / validate intent from the conversation.
+
+## On Activation
+
+1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-prd.toml` and `bmad-create-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
+
+2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
+
+3. Emit a deprecation notice to the user in `{communication_language}`:
+
+ > Notice: `bmad-create-prd` is deprecated and will be removed in a future release. It now forwards to `bmad-prd` with create intent. To silence this notice and access the full new customization surface (`prd_template`, `validation_checklist`, `doc_standards`, `external_sources`, `external_handoffs`, `output_dir`, `output_folder_name`), migrate `_bmad/custom/bmad-create-prd.toml` to `_bmad/custom/bmad-prd.toml` and invoke `bmad-prd` directly next time. Customization fields that were in this version still remain in the new version and will be respected if present in `_bmad/custom/bmad-prd.toml`, but the new version also supports additional fields that you can take advantage of by migrating.
+
+4. Invoke `bmad-prd` with the following context. Pass these as the activating context so `bmad-prd` honors them instead of resolving its own customization from scratch:
+
+ - **Intent:** `create` — skip `bmad-prd`'s usual intent detection step.
+ - **Pre-resolved legacy customization** — use these in place of resolving from `bmad-prd`'s own `customize.toml` for the four legacy fields. For everything else (`prd_template`, `validation_checklist`, `validation_report_template`, `doc_standards`, `output_dir`, `output_folder_name`, `external_sources`, `external_handoffs`), use `bmad-prd`'s own defaults and overrides as normal:
+ - `activation_steps_prepend` = the resolved value from step 1
+ - `activation_steps_append` = the resolved value from step 1
+ - `persistent_facts` = the resolved value from step 1
+ - `on_complete` = the resolved value from step 1
+ - **Original user input:** forward whatever the user said when invoking this skill verbatim.
+
+ `bmad-prd` takes the workflow from here. Do not execute any further steps in this shim.
diff --git a/80_bmad/base/.agents/skills/bmad-create-prd/customize.toml b/80_bmad/base/.agents/skills/bmad-create-prd/customize.toml
new file mode 100644
index 0000000..fde1ba1
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-prd/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-create-prd. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All PRDs must include a regulatory-risk section."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step 12 (Workflow Completion),
+# after the PRD is finalized and workflow status is updated. Override wins.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-create-story/SKILL.md b/80_bmad/base/.agents/skills/bmad-create-story/SKILL.md
new file mode 100644
index 0000000..7273ec8
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-story/SKILL.md
@@ -0,0 +1,432 @@
+---
+name: bmad-create-story
+description: 'Creates a dedicated story file with all the context the agent will need to implement it later. Use when the user says "create the next story" or "create story [story identifier]"'
+---
+
+# Create Story Workflow
+
+**Goal:** Create a comprehensive story file that gives the dev agent everything needed for flawless implementation.
+
+**Your Role:** Story context engine that prevents LLM developer mistakes, omissions, or disasters.
+- Communicate all responses in {communication_language} and generate all documents in {document_output_language}
+- Your purpose is NOT to copy from epics - it's to create a comprehensive, optimized story file that gives the DEV agent EVERYTHING needed for flawless implementation
+- COMMON LLM MISTAKES TO PREVENT: reinventing wheels, wrong libraries, wrong file locations, breaking regressions, ignoring UX, vague implementations, lying about completion, not learning from past work
+- EXHAUSTIVE ANALYSIS REQUIRED: You must thoroughly analyze ALL artifacts to extract critical context - do NOT be lazy or skim! This is the most important function in the entire development process!
+- UTILIZE SUBPROCESSES AND SUBAGENTS: Use research subagents, subprocesses or parallel processing if available to thoroughly analyze different artifacts simultaneously and thoroughly
+- SAVE QUESTIONS: If you think of questions or clarifications during analysis, save them for the end after the complete story is written
+- ZERO USER INTERVENTION: Process should be fully automated except for initial epic/story selection or missing documents
+
+Subagents, when the capability is available, are an important part of this workflow. Use them as directed by the workflow steps.
+If you need an explicit user instruction to run them, ask once now for the whole workflow run.
+
+## Conventions
+
+- Bare paths (e.g. `discover-inputs.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+
+- `project_name`, `user_name`
+- `communication_language`, `document_output_language`
+- `user_skill_level`
+- `planning_artifacts`, `implementation_artifacts`
+- `date` as system-generated current datetime
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Paths
+
+- `sprint_status` = `{implementation_artifacts}/sprint-status.yaml`
+- `epics_file` = `{planning_artifacts}/epics.md`
+- `prd_file` = `{planning_artifacts}/prd.md`
+- `architecture_file` = `{planning_artifacts}/architecture.md`
+- `ux_file` = `{planning_artifacts}/*ux*.md`
+- `story_title` = "" (will be elicited if not derivable)
+- `default_output_file` = `{implementation_artifacts}/{{story_key}}.md`
+
+## Input Files
+
+| Input | Description | Path Pattern(s) | Load Strategy |
+|-------|-------------|------------------|---------------|
+| prd | PRD (fallback - epics file should have most content) | whole: `{planning_artifacts}/*prd*.md`, sharded: `{planning_artifacts}/*prd*/*.md` | SELECTIVE_LOAD |
+| architecture | Architecture (fallback - epics file should have relevant sections) | whole: `{planning_artifacts}/*architecture*.md`, sharded: `{planning_artifacts}/*architecture*/*.md` | SELECTIVE_LOAD |
+| ux | UX design (fallback - epics file should have relevant sections) | whole: `{planning_artifacts}/*ux*.md`, sharded: `{planning_artifacts}/*ux*/*.md` | SELECTIVE_LOAD |
+| epics | Enhanced epics+stories file with BDD and source hints | whole: `{planning_artifacts}/*epic*.md`, sharded: `{planning_artifacts}/*epic*/*.md` | SELECTIVE_LOAD |
+
+## Execution
+
+
+
+
+
+ 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
+
+
+ Check if {{sprint_status}} file exists for auto discover
+
+
+
+ Choose option [1], provide epic-story number, path to story docs, or [q] to quit:
+
+
+ HALT - No work needed
+
+
+
+
+ HALT - User needs to run sprint-planning
+
+
+
+ Parse user input: extract epic_num, story_num, story_title
+ Set {{epic_num}}, {{story_num}}, {{story_key}} from user input
+ GOTO step 2a
+
+
+
+ Use user-provided path for story documents
+ GOTO step 2a
+
+
+
+
+
+ MUST read COMPLETE {sprint_status} file from start to end to preserve order
+ Load the FULL file: {{sprint_status}}
+ Read ALL lines from beginning to end - do not skip any content
+ Parse the development_status section completely
+
+ Find the FIRST story (by reading in order from top to bottom) where:
+ - Key matches pattern: number-number-name (e.g., "1-2-user-auth")
+ - NOT an epic key (epic-X) or retrospective (epic-X-retrospective)
+ - Status value equals "backlog"
+
+
+
+
+ HALT
+
+
+ Extract from found story key (e.g., "1-2-user-authentication"):
+ - epic_num: first number before dash (e.g., "1")
+ - story_num: second number after first dash (e.g., "2")
+ - story_title: remainder after second dash (e.g., "user-authentication")
+
+ Set {{story_id}} = "{{epic_num}}.{{story_num}}"
+ Store story_key for later use (e.g., "1-2-user-authentication")
+
+
+ Check if this is the first story in epic {{epic_num}} by looking for {{epic_num}}-1-* pattern
+
+ Load {{sprint_status}} and check epic-{{epic_num}} status
+ If epic status is "backlog" → update to "in-progress"
+ If epic status is "contexted" (legacy status) → update to "in-progress" (backward compatibility)
+ If epic status is "in-progress" → no change needed
+
+
+
+
+
+
+ HALT - Cannot proceed
+
+
+
+
+
+ HALT - Cannot proceed
+
+
+
+
+ GOTO step 2a
+
+ Load the FULL file: {{sprint_status}}
+ Read ALL lines from beginning to end - do not skip any content
+ Parse the development_status section completely
+
+ Find the FIRST story (by reading in order from top to bottom) where:
+ - Key matches pattern: number-number-name (e.g., "1-2-user-auth")
+ - NOT an epic key (epic-X) or retrospective (epic-X-retrospective)
+ - Status value equals "backlog"
+
+
+
+
+ HALT
+
+
+ Extract from found story key (e.g., "1-2-user-authentication"):
+ - epic_num: first number before dash (e.g., "1")
+ - story_num: second number after first dash (e.g., "2")
+ - story_title: remainder after second dash (e.g., "user-authentication")
+
+ Set {{story_id}} = "{{epic_num}}.{{story_num}}"
+ Store story_key for later use (e.g., "1-2-user-authentication")
+
+
+ Check if this is the first story in epic {{epic_num}} by looking for {{epic_num}}-1-* pattern
+
+ Load {{sprint_status}} and check epic-{{epic_num}} status
+ If epic status is "backlog" → update to "in-progress"
+ If epic status is "contexted" (legacy status) → update to "in-progress" (backward compatibility)
+ If epic status is "in-progress" → no change needed
+
+
+
+
+
+
+ HALT - Cannot proceed
+
+
+
+
+
+ HALT - Cannot proceed
+
+
+
+
+ GOTO step 2a
+
+
+
+ 🔬 EXHAUSTIVE ARTIFACT ANALYSIS - This is where you prevent future developer mistakes!
+
+
+ Read fully and follow `./discover-inputs.md` to load all input files
+ Available content: {epics_content}, {prd_content}, {architecture_content}, {ux_content}, plus the project-context facts loaded during activation via `persistent_facts`.
+
+
+ From {epics_content}, extract Epic {{epic_num}} complete context: **EPIC ANALYSIS:** - Epic
+ objectives and business value - ALL stories in this epic for cross-story context - Our specific story's requirements, user story
+ statement, acceptance criteria - Technical requirements and constraints - Dependencies on other stories/epics - Source hints pointing to
+ original documents
+ Extract our story ({{epic_num}}-{{story_num}}) details: **STORY FOUNDATION:** - User story statement
+ (As a, I want, so that) - Detailed acceptance criteria (already BDD formatted) - Technical requirements specific to this story -
+ Business context and value - Success criteria
+
+ Find {{previous_story_num}}: scan {implementation_artifacts} for the story file in epic {{epic_num}} with the highest story number less than {{story_num}}
+ Load previous story file: {implementation_artifacts}/{{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
+ all learnings that could impact current story implementation
+
+
+
+
+ Get last 5 commit titles to understand recent work patterns
+ Analyze 1-5 most recent commits for relevance to current story:
+ - Files created/modified
+ - Code patterns and conventions used
+ - Library dependencies added/changed
+ - Architecture decisions implemented
+ - Testing approaches used
+
+ Extract actionable insights for current story implementation
+
+
+
+
+ 🏗️ ARCHITECTURE INTELLIGENCE - Extract everything the developer MUST follow! **ARCHITECTURE DOCUMENT ANALYSIS:** Systematically
+ analyze architecture content for story-relevant requirements:
+
+
+
+ Load complete {architecture_content}
+
+
+ Load architecture index and scan all architecture files
+ **CRITICAL ARCHITECTURE EXTRACTION:** For
+ each architecture section, determine if relevant to this story: - **Technical Stack:** Languages, frameworks, libraries with
+ versions - **Code Structure:** Folder organization, naming conventions, file patterns - **API Patterns:** Service structure, endpoint
+ patterns, data contracts - **Database Schemas:** Tables, relationships, constraints relevant to story - **Security Requirements:**
+ Authentication patterns, authorization rules - **Performance Requirements:** Caching strategies, optimization patterns - **Testing
+ Standards:** Testing frameworks, coverage expectations, test patterns - **Deployment Patterns:** Environment configurations, build
+ processes - **Integration Patterns:** External service integrations, data flows Extract any story-specific requirements that the
+ developer MUST follow
+ Identify any architectural decisions that override previous patterns
+
+
+ 📂 READ FILES BEING MODIFIED — skipping this is the primary cause of implementation failures and review cycles
+ From the architecture directory structure, identify every file marked UPDATE (not NEW) that this story will touch
+ Read each relevant UPDATE file completely. For each one, document in dev notes:
+ - Current state: what it does today (state machine, API calls, data shapes, existing behaviors)
+ - What this story changes: the specific sections or behaviors being modified
+ - What must be preserved: existing interactions and behaviors the story must not break
+
+ A story implementation must leave the system working end-to-end — not just satisfy its stated ACs.
+ If a behavior is required for the feature to work correctly in the existing system, it is a requirement
+ whether or not it is explicitly written in the story. The dev agent owns this.
+
+
+
+ 🌐 ENSURE LATEST TECH KNOWLEDGE - Prevent outdated implementations! **WEB INTELLIGENCE:** Identify specific
+ technical areas that require latest version knowledge:
+
+
+ From architecture analysis, identify specific libraries, APIs, or
+ frameworks
+ For each critical technology, research latest stable version and key changes:
+ - Latest API documentation and breaking changes
+ - Security vulnerabilities or updates
+ - Performance improvements or deprecations
+ - Best practices for current version
+
+ **EXTERNAL CONTEXT INCLUSION:** Include in story any critical latest information the developer needs:
+ - Specific library versions and why chosen
+ - API endpoints with parameters and authentication
+ - Recent security patches or considerations
+ - Performance optimization techniques
+ - Migration considerations if upgrading
+
+
+
+
+ 📝 CREATE ULTIMATE STORY FILE - The developer's master implementation guide!
+
+ Initialize from template.md:
+ {default_output_file}
+ story_header
+
+
+ story_requirements
+
+
+
+ developer_context_section **DEV AGENT GUARDRAILS:**
+ technical_requirements
+ architecture_compliance
+ library_framework_requirements
+
+ file_structure_requirements
+ testing_requirements
+
+
+
+ previous_story_intelligence
+
+
+
+
+ git_intelligence_summary
+
+
+
+
+ latest_tech_information
+
+
+
+ project_context_reference
+
+
+
+ story_completion_status
+
+
+ Set story Status to: "ready-for-dev"
+ Add completion note: "Ultimate
+ context engine analysis completed - comprehensive developer guide created"
+
+
+
+ Validate the newly created story file {default_output_file} against `./checklist.md` and apply any required fixes before finalizing
+ Save story document unconditionally
+
+
+
+ Update {{sprint_status}}
+ Load the FULL file and read all development_status entries
+ Find development_status key matching {{story_key}}
+ Verify current status is "backlog" (expected previous state)
+ Update development_status[{{story_key}}] = "ready-for-dev"
+ Update last_updated field to current date
+ Save file, preserving ALL comments and structure including STATUS DEFINITIONS
+
+
+ Report completion
+
+ Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.
+
+
+
diff --git a/80_bmad/base/_bmad/bmm/workflows/4-implementation/create-story/checklist.md b/80_bmad/base/.agents/skills/bmad-create-story/checklist.md
similarity index 94%
rename from 80_bmad/base/_bmad/bmm/workflows/4-implementation/create-story/checklist.md
rename to 80_bmad/base/.agents/skills/bmad-create-story/checklist.md
index d9ed063..e47cc0f 100644
--- a/80_bmad/base/_bmad/bmm/workflows/4-implementation/create-story/checklist.md
+++ b/80_bmad/base/.agents/skills/bmad-create-story/checklist.md
@@ -33,25 +33,25 @@ This is a COMPETITION to create the **ULTIMATE story context** that makes LLM de
### **When Running from Create-Story Workflow:**
-- The `{project-root}/_bmad/core/tasks/workflow.xml` framework will automatically:
+- The workflow framework will automatically:
- Load this checklist file
- Load the newly created story file (`{story_file_path}`)
- - Load workflow variables from `{installed_path}/workflow.yaml`
+ - Load workflow variables from `./workflow.md`
- Execute the validation process
### **When Running in Fresh Context:**
- User should provide the story file path being reviewed
- Load the story file directly
-- Load the corresponding workflow.yaml for variable context
+- Load the corresponding workflow.md for variable context
- Proceed with systematic analysis
### **Required Inputs:**
- **Story file**: The story file to review and improve
-- **Workflow variables**: From workflow.yaml (implementation_artifacts, epics_file, etc.)
+- **Workflow variables**: From workflow.md (implementation_artifacts, epics_file, etc.)
- **Source documents**: Epics, architecture, etc. (discovered or provided)
-- **Validation framework**: `validate-workflow.xml` (handles checklist execution)
+- **Validation framework**: The workflow's checklist execution system
---
@@ -61,12 +61,11 @@ You will systematically re-do the entire story creation process, but with a crit
### **Step 1: Load and Understand the Target**
-1. **Load the workflow configuration**: `{installed_path}/workflow.yaml` for variable inclusion
+1. **Load the workflow configuration**: `./workflow.md` for variable inclusion
2. **Load the story file**: `{story_file_path}` (provided by user or discovered)
-3. **Load validation framework**: `{project-root}/_bmad/core/tasks/workflow.xml`
-4. **Extract metadata**: epic_num, story_num, story_key, story_title from story file
-5. **Resolve all workflow variables**: implementation_artifacts, epics_file, architecture_file, etc.
-6. **Understand current status**: What story implementation guidance is currently provided?
+3. **Extract metadata**: epic_num, story_num, story_key, story_title from story file
+4. **Resolve all workflow variables**: implementation_artifacts, epics_file, architecture_file, etc.
+5. **Understand current status**: What story implementation guidance is currently provided?
**Note:** If running in fresh context, user should provide the story file path being reviewed. If running from create-story workflow, the validation framework will automatically discover the checklist and story file.
diff --git a/80_bmad/base/.agents/skills/bmad-create-story/customize.toml b/80_bmad/base/.agents/skills/bmad-create-story/customize.toml
new file mode 100644
index 0000000..fbd4a78
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-story/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-create-story. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All stories must include testable acceptance criteria."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step 6 (Update sprint status and finalize),
+# after the story file is saved and sprint-status.yaml is updated. Override wins.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-create-story/discover-inputs.md b/80_bmad/base/.agents/skills/bmad-create-story/discover-inputs.md
new file mode 100644
index 0000000..2c313db
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-create-story/discover-inputs.md
@@ -0,0 +1,88 @@
+# Discover Inputs Protocol
+
+**Objective:** Intelligently load project files (whole or sharded) based on the workflow's Input Files configuration.
+
+**Prerequisite:** Only execute this protocol if the workflow defines an Input Files section. If no input file patterns are configured, skip this entirely.
+
+---
+
+## Step 1: Parse Input File Patterns
+
+- Read the Input Files table from the workflow configuration.
+- For each input group (prd, architecture, epics, ux, etc.), note the **load strategy** if specified.
+
+## Step 2: Load Files Using Smart Strategies
+
+For each pattern in the Input Files table, work through the following substeps in order:
+
+### 2a: Try Sharded Documents First
+
+If a sharded pattern exists for this input, determine the load strategy (defaults to **FULL_LOAD** if not specified), then apply the matching strategy:
+
+#### FULL_LOAD Strategy
+
+Load ALL files in the sharded directory. Use this for PRD, Architecture, UX, brownfield docs, or whenever the full picture is needed.
+
+1. Use the glob pattern to find ALL `.md` files (e.g., `{planning_artifacts}/*architecture*/*.md`).
+2. Load EVERY matching file completely.
+3. Concatenate content in logical order: `index.md` first if it exists, then alphabetical.
+4. Store the combined result in a variable named `{pattern_name_content}` (e.g., `{architecture_content}`).
+
+#### SELECTIVE_LOAD Strategy
+
+Load a specific shard using a template variable. Example: used for epics with `{{epic_num}}`.
+
+1. Check for template variables in the sharded pattern (e.g., `{{epic_num}}`).
+2. If the variable is undefined, ask the user for the value OR infer it from context.
+3. Resolve the template to a specific file path.
+4. Load that specific file.
+5. Store in variable: `{pattern_name_content}`.
+
+#### INDEX_GUIDED Strategy
+
+Load index.md, analyze the structure and description of each doc in the index, then intelligently load relevant docs.
+
+**DO NOT BE LAZY** -- use best judgment to load documents that might have relevant information, even if there is only a 5% chance of relevance.
+
+1. Load `index.md` from the sharded directory.
+2. Parse the table of contents, links, and section headers.
+3. Analyze the workflow's purpose and objective.
+4. Identify which linked/referenced documents are likely relevant.
+ - *Example:* If the workflow is about authentication and the index shows "Auth Overview", "Payment Setup", "Deployment" -- load the auth docs, consider deployment docs, skip payment.
+5. Load all identified relevant documents.
+6. Store combined content in variable: `{pattern_name_content}`.
+
+**When in doubt, LOAD IT** -- context is valuable, and being thorough is better than missing critical info.
+
+---
+
+After applying the matching strategy, mark the pattern as **RESOLVED** and move to the next pattern.
+
+### 2b: Try Whole Document if No Sharded Found
+
+If no sharded matches were found OR no sharded pattern exists for this input:
+
+1. Attempt a glob match on the "whole" pattern (e.g., `{planning_artifacts}/*prd*.md`).
+2. If matches are found, load ALL matching files completely (no offset/limit).
+3. Store content in variable: `{pattern_name_content}` (e.g., `{prd_content}`).
+4. Mark pattern as **RESOLVED** and move to the next pattern.
+
+### 2c: Handle Not Found
+
+If no matches were found for either sharded or whole patterns:
+
+1. Set `{pattern_name_content}` to empty string.
+2. Note in session: "No {pattern_name} files found" -- this is not an error, just unavailable. Offer the user a chance to provide the file.
+
+## Step 3: Report Discovery Results
+
+List all loaded content variables with file counts. Example:
+
+```
+OK Loaded {prd_content} from 5 sharded files: prd/index.md, prd/requirements.md, ...
+OK Loaded {architecture_content} from 1 file: Architecture.md
+OK Loaded {epics_content} from selective load: epics/epic-3.md
+-- No ux_design files found
+```
+
+This gives the workflow transparency into what context is available.
diff --git a/80_bmad/base/_bmad/bmm/workflows/4-implementation/create-story/template.md b/80_bmad/base/.agents/skills/bmad-create-story/template.md
similarity index 94%
rename from 80_bmad/base/_bmad/bmm/workflows/4-implementation/create-story/template.md
rename to 80_bmad/base/.agents/skills/bmad-create-story/template.md
index 17953f0..c4e129f 100644
--- a/80_bmad/base/_bmad/bmm/workflows/4-implementation/create-story/template.md
+++ b/80_bmad/base/.agents/skills/bmad-create-story/template.md
@@ -1,9 +1,6 @@
# Story {{epic_num}}.{{story_num}}: {{story_title}}
Status: ready-for-dev
-Parallel-safe: false
-Depends-on: ~
-Can-run-with: ~
diff --git a/80_bmad/base/.agents/skills/bmad-customize/SKILL.md b/80_bmad/base/.agents/skills/bmad-customize/SKILL.md
new file mode 100644
index 0000000..0581826
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-customize/SKILL.md
@@ -0,0 +1,111 @@
+---
+name: bmad-customize
+description: Authors and updates customization overrides for installed BMad skills. Use when the user says 'customize bmad', 'override a skill', 'change agent behavior', or 'customize a workflow'.
+---
+
+# BMad Customize
+
+Translate the user's intent into a correctly-placed TOML override file under `{project-root}/_bmad/custom/` for a customizable agent or workflow skill. Discover, route, author, write, verify.
+
+Scope v1: per-skill `[agent]` overrides (`bmad-agent-.toml` / `.user.toml`) and per-skill `[workflow]` overrides (`bmad-.toml` / `.user.toml`). Central config (`{project-root}/_bmad/custom/config.toml`) is out of scope — point users at the [How to Customize BMad guide](https://docs.bmad-method.org/how-to/customize-bmad/).
+
+When the target's `customize.toml` doesn't expose what the user wants, say so plainly. Don't invent fields.
+
+## Preflight
+
+- No `{project-root}/_bmad/` → BMad isn't installed. Say so, stop.
+- `{project-root}/_bmad/scripts/resolve_customization.py` missing → continue, but Step 6 verify falls back to manual merge.
+- Both present → proceed.
+
+## Activation
+
+Load `_bmad/config.toml` and `_bmad/config.user.toml` from `{project-root}` for `user_name` (default `BMad`) and `communication_language` (default `English`). Greet. If the user's invocation already names a target skill AND a specific change, jump to Step 3.
+
+## Step 1: Classify intent
+
+- **Directed** — specific skill + specific change → Step 3.
+- **Exploratory** — "what can I customize?" → Step 2.
+- **Audit/iterate** — wants to review or change something already customized → Step 2, lead with skills that have existing overrides; read the existing override in Step 3 before composing.
+- **Cross-cutting** — could live on multiple surfaces → Step 3, choose agent vs workflow explicitly with the user.
+
+## Step 2: Discovery
+
+```
+python3 {skill-root}/scripts/list_customizable_skills.py --project-root {project-root}
+```
+
+Use `--extra-root ` (repeatable) if the user has skills installed in additional locations.
+
+Group the returned `agents` and `workflows` for the user; for each show name, description, whether `has_team_override` or `has_user_override` is true. Surface any `errors[]`. For audit/iterate intents, lead with already-overridden entries.
+
+Empty list: show `scanned_roots`, ask whether skills live elsewhere (offer `--extra-root`); otherwise stop.
+
+## Step 3: Determine the right surface
+
+Read the target's `customize.toml`. Top-level `[agent]` or `[workflow]` block defines the surface.
+
+If a team or user override already exists, read it first and summarize what's already overridden before composing.
+
+**Cross-cutting intent — walk both surfaces with the user:**
+- Every workflow a given agent runs → agent surface (e.g. `bmad-agent-pm.toml` with `persistent_facts`, `principles`).
+- One workflow only → workflow surface (e.g. `bmad-prd.toml` with `activation_steps_prepend`).
+- Several specific workflows → multiple workflow overrides in sequence, not an agent override.
+
+**Single-surface heuristic:**
+- Workflow-level: template swap, output path, step-specific behavior, or a named scalar already exposed (`*_template`, `on_complete`). Surgical, reliable.
+- Agent-level: persona, communication style, org-wide facts, menu changes, behavior that should apply to every workflow the agent dispatches.
+
+When ambiguous, present both with tradeoff, recommend one, let the user decide.
+
+Intent outside the exposed surface (step logic, ordering, anything not in `customize.toml`): say so; offer `activation_steps_prepend`/`append` or `persistent_facts` as approximations, or recommend `bmad-builder` to create a custom skill.
+
+## Step 4: Compose the override
+
+Translate plain-English into TOML against the target's `customize.toml` fields. If an existing override was read, frame the change as additive.
+
+Merge semantics:
+- **Scalars** (`icon`, `role`, `*_template`, `on_complete`) — override wins.
+- **Append arrays** (`persistent_facts`, `activation_steps_prepend`/`append`, `principles`) — team/user entries append in order.
+- **Keyed arrays of tables** (menu items with `code` or `id`) — matching keys replace, new keys append.
+
+Overrides are sparse: only the fields being changed. Never copy the whole `customize.toml`.
+
+**Template swap** (`*_template` scalar): offer to copy the default template to `{project-root}/_bmad/custom/{skill-name}-{purpose}-template.md`, point the override at the new path, offer to help edit it.
+
+## Step 5: Team or user placement
+
+Under `{project-root}/_bmad/custom/`:
+- `{skill-name}.toml` — team, committed. Policies, org conventions, compliance.
+- `{skill-name}.user.toml` — user, gitignored. Personal tone, private facts, shortcuts.
+
+Default by character (policy → team, personal → user), confirm before writing.
+
+## Step 6: Show, confirm, write, verify
+
+1. Show the full TOML. If the file exists, show a diff. Never silently overwrite.
+2. Wait for explicit yes.
+3. Write. Create `{project-root}/_bmad/custom/` if needed.
+4. Verify:
+ ```
+ python3 {project-root}/_bmad/scripts/resolve_customization.py --skill --key
+ ```
+ Show the merged output, point out the changed fields.
+
+ **Resolver missing or fails:** read whichever layers exist — `/customize.toml` (base), `{project-root}/_bmad/custom/{skill-name}.toml` (team), `{project-root}/_bmad/custom/{skill-name}.user.toml` (user) — apply base → team → user with the same merge rules (scalars override, tables deep-merge, `code`/`id`-keyed arrays merge by key, all other arrays append), describe how the changed fields resolve.
+
+ **Verify shows override didn't land** (field unchanged, merge conflict, file not picked up): re-enter Step 4 with the verify output as context. Usually wrong field name, wrong merge mode (scalar vs array), or wrong scope.
+5. Summarize what changed, where the file lives, how to iterate. Remind the user to commit team overrides.
+
+## Complete when
+
+- Override file written (or user explicitly aborted).
+- User has seen resolver output (or manual fallback merge summary).
+- User has acknowledged the summary.
+
+Otherwise the skill isn't done — finish or tell the user they're exiting incomplete.
+
+## When this skill can't help
+
+- **Central config** (`{project-root}/_bmad/custom/config.toml`) — see the [How to Customize BMad guide](https://docs.bmad-method.org/how-to/customize-bmad/).
+- **Step logic, ordering, behavior not in `customize.toml`** — open a feature request, or use `bmad-builder` to create a custom skill. Offer to help with either.
+- **Skills without a `customize.toml`** — not customizable.
diff --git a/80_bmad/base/.agents/skills/bmad-customize/scripts/list_customizable_skills.py b/80_bmad/base/.agents/skills/bmad-customize/scripts/list_customizable_skills.py
new file mode 100644
index 0000000..86fd82a
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-customize/scripts/list_customizable_skills.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python3
+# /// script
+# requires-python = ">=3.11"
+# ///
+"""Enumerate customizable BMad skills installed alongside this one.
+
+Scans a skills directory (by default: the directory this script's own skill
+lives in, derived from __file__), finds every sibling directory containing a
+`customize.toml`, classifies each as agent and/or workflow based on its
+top-level blocks, reads the skill's SKILL.md frontmatter description for a
+one-liner, and checks whether override files already exist in
+`{project-root}/_bmad/custom/`.
+
+Skills in BMad are loaded either from a project-local location (e.g. the
+project's `.claude/skills/` or `.cursor/skills/`) or from a user-global
+location (e.g. `~/.claude/skills/`). We do not hardcode those paths — the
+running skill's own location is the source of truth for sibling discovery.
+`--extra-root` is available for the rare case where skills live in multiple
+locations on the same machine.
+
+Output: JSON to stdout. Non-empty `errors[]` in the payload is non-fatal
+by contract — the scanner surfaces malformed TOML, missing roots, and
+skills with no customization block as data for the caller to display,
+and still exits 0. Exit 2 is reserved for invocation errors (e.g.
+missing or unreadable `--project-root`) where no useful payload can be
+produced.
+"""
+
+from __future__ import annotations
+
+import argparse
+import json
+import re
+import sys
+import tomllib
+from pathlib import Path
+
+# Top-level TOML blocks that indicate a customization surface.
+SURFACE_KEYS = ("agent", "workflow")
+
+FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
+
+
+def default_skills_root() -> Path:
+ """Derive the skills root from this script's location.
+
+ Layout assumption: {skills_root}/bmad-customize/scripts/list_customizable_skills.py.
+ So the skills root is three parents up from this file.
+ """
+ return Path(__file__).resolve().parent.parent.parent
+
+
+def read_frontmatter_description(skill_md: Path) -> str:
+ """Extract the `description:` value from a SKILL.md YAML frontmatter block.
+
+ Returns an empty string if the file is missing, unreadable, or has no
+ description field. Intentionally permissive — this is metadata for a
+ human-facing list, not a validation target.
+ """
+ if not skill_md.is_file():
+ return ""
+ try:
+ text = skill_md.read_text(encoding="utf-8")
+ except (OSError, UnicodeDecodeError):
+ return ""
+ m = FRONTMATTER_RE.match(text)
+ if not m:
+ return ""
+ for line in m.group(1).splitlines():
+ stripped = line.strip()
+ if stripped.startswith("description:"):
+ value = stripped[len("description:") :].strip()
+ # Strip surrounding quotes if present.
+ if (value.startswith("'") and value.endswith("'")) or (
+ value.startswith('"') and value.endswith('"')
+ ):
+ value = value[1:-1]
+ return value
+ return ""
+
+
+def load_customize(toml_path: Path) -> dict | None:
+ """Return the parsed TOML, or None if unreadable."""
+ try:
+ with toml_path.open("rb") as f:
+ return tomllib.load(f)
+ except (OSError, tomllib.TOMLDecodeError):
+ return None
+
+
+def scan_skills(
+ skills_roots: list[Path],
+ project_root: Path,
+) -> dict:
+ """Scan each skills root for directories that contain a customize.toml."""
+ agents: list[dict] = []
+ workflows: list[dict] = []
+ errors: list[str] = []
+ scanned_roots: list[str] = []
+ seen_names: set[str] = set()
+ custom_dir = project_root / "_bmad" / "custom"
+
+ for root in skills_roots:
+ if not root.is_dir():
+ errors.append(f"skills root does not exist: {root}")
+ continue
+ scanned_roots.append(str(root))
+
+ for skill_dir in sorted(p for p in root.iterdir() if p.is_dir()):
+ customize_toml = skill_dir / "customize.toml"
+ if not customize_toml.is_file():
+ continue
+
+ data = load_customize(customize_toml)
+ if data is None:
+ errors.append(f"failed to parse {customize_toml}")
+ continue
+
+ skill_name = skill_dir.name
+ # If a skill with this name was already found in an earlier
+ # root, skip it — roots are scanned in the order provided, so
+ # the first occurrence wins.
+ if skill_name in seen_names:
+ continue
+ seen_names.add(skill_name)
+
+ description = read_frontmatter_description(skill_dir / "SKILL.md")
+ team_override = custom_dir / f"{skill_name}.toml"
+ user_override = custom_dir / f"{skill_name}.user.toml"
+
+ entry_base = {
+ "name": skill_name,
+ "install_path": str(skill_dir),
+ "skills_root": str(root),
+ "description": description,
+ "has_team_override": team_override.is_file(),
+ "has_user_override": user_override.is_file(),
+ "team_override_path": str(team_override),
+ "user_override_path": str(user_override),
+ }
+
+ # A skill may expose an agent surface, a workflow surface, or
+ # both. Emit one entry per surface so the caller can group cleanly.
+ surfaces_found = [k for k in SURFACE_KEYS if k in data]
+ if not surfaces_found:
+ errors.append(
+ f"no [agent] or [workflow] block in {customize_toml}"
+ )
+ continue
+ for surface in surfaces_found:
+ entry = dict(entry_base)
+ entry["surface"] = surface
+ if surface == "agent":
+ agents.append(entry)
+ else:
+ workflows.append(entry)
+
+ return {
+ "project_root": str(project_root),
+ "scanned_roots": scanned_roots,
+ "custom_dir": str(custom_dir),
+ "agents": agents,
+ "workflows": workflows,
+ "errors": errors,
+ }
+
+
+def parse_args(argv: list[str]) -> argparse.Namespace:
+ parser = argparse.ArgumentParser(
+ description=(
+ "List customizable BMad skills installed alongside this one, "
+ "grouped by surface (agent vs workflow), with override status "
+ "looked up against {project-root}/_bmad/custom/."
+ )
+ )
+ parser.add_argument(
+ "--project-root",
+ required=True,
+ help="Absolute path to the project root (the folder containing _bmad/).",
+ )
+ parser.add_argument(
+ "--skills-root",
+ default=None,
+ help=(
+ "Override the primary skills directory to scan. Defaults to the "
+ "directory this script's own skill lives in."
+ ),
+ )
+ parser.add_argument(
+ "--extra-root",
+ action="append",
+ default=[],
+ metavar="PATH",
+ help=(
+ "Additional skills directory to include (repeatable). Useful "
+ "when skills live in multiple locations on the same machine "
+ "(e.g. project-local plus a user-global install)."
+ ),
+ )
+ return parser.parse_args(argv)
+
+
+def main(argv: list[str]) -> int:
+ args = parse_args(argv)
+ project_root = Path(args.project_root).expanduser().resolve()
+ if not project_root.is_dir():
+ print(
+ f"error: project-root does not exist or is not a directory: {project_root}",
+ file=sys.stderr,
+ )
+ return 2
+
+ primary = (
+ Path(args.skills_root).expanduser().resolve()
+ if args.skills_root
+ else default_skills_root()
+ )
+ extras = [Path(p).expanduser().resolve() for p in args.extra_root]
+ # Deduplicate in order of appearance.
+ roots: list[Path] = []
+ for root in [primary, *extras]:
+ if root not in roots:
+ roots.append(root)
+
+ result = scan_skills(roots, project_root)
+ print(json.dumps(result, indent=2, sort_keys=True))
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
diff --git a/80_bmad/base/.agents/skills/bmad-customize/scripts/tests/test_list_customizable_skills.py b/80_bmad/base/.agents/skills/bmad-customize/scripts/tests/test_list_customizable_skills.py
new file mode 100644
index 0000000..916b7c3
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-customize/scripts/tests/test_list_customizable_skills.py
@@ -0,0 +1,249 @@
+#!/usr/bin/env python3
+# /// script
+# requires-python = ">=3.11"
+# ///
+"""Unit tests for list_customizable_skills.py.
+
+Exercises the scanner against a synthesized install tree:
+- an agent-only customize.toml
+- a workflow-only customize.toml
+- a customize.toml that exposes both surfaces
+- a skill directory with no customize.toml (ignored)
+- a pre-existing team override in _bmad/custom/
+- malformed TOML (surfaces as an error without aborting)
+- multiple skills roots (e.g. project-local + user-global mix)
+
+Run: uv run scripts/tests/test_list_customizable_skills.py
+"""
+
+from __future__ import annotations
+
+import importlib.util
+import json
+import subprocess
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+SCRIPT = Path(__file__).resolve().parent.parent / "list_customizable_skills.py"
+
+
+def _load_module():
+ spec = importlib.util.spec_from_file_location("list_customizable_skills", SCRIPT)
+ module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(module) # type: ignore[union-attr]
+ return module
+
+
+MODULE = _load_module()
+
+
+def _make_skill(parent: Path, name: str, body: str, skill_md: str | None = None) -> Path:
+ skill_dir = parent / name
+ skill_dir.mkdir(parents=True, exist_ok=True)
+ (skill_dir / "customize.toml").write_text(body, encoding="utf-8")
+ if skill_md is not None:
+ (skill_dir / "SKILL.md").write_text(skill_md, encoding="utf-8")
+ return skill_dir
+
+
+class ScannerTest(unittest.TestCase):
+ def setUp(self):
+ self.tmp = tempfile.TemporaryDirectory()
+ self.root = Path(self.tmp.name)
+ self.skills = self.root / "skills"
+ self.skills.mkdir(parents=True)
+ self.custom = self.root / "_bmad" / "custom"
+ self.custom.mkdir(parents=True)
+
+ def tearDown(self):
+ self.tmp.cleanup()
+
+ def test_agent_only_skill_detected(self):
+ _make_skill(
+ self.skills,
+ "bmad-agent-pm",
+ "[agent]\nicon = \"🧠\"\n",
+ "---\nname: bmad-agent-pm\ndescription: Product manager.\n---\n",
+ )
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(len(result["agents"]), 1)
+ self.assertEqual(len(result["workflows"]), 0)
+ entry = result["agents"][0]
+ self.assertEqual(entry["name"], "bmad-agent-pm")
+ self.assertEqual(entry["surface"], "agent")
+ self.assertEqual(entry["description"], "Product manager.")
+ self.assertFalse(entry["has_team_override"])
+ self.assertFalse(entry["has_user_override"])
+
+ def test_workflow_only_skill_detected(self):
+ _make_skill(
+ self.skills,
+ "bmad-create-prd",
+ "[workflow]\npersistent_facts = []\n",
+ "---\nname: bmad-create-prd\ndescription: 'Create a PRD.'\n---\n",
+ )
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(len(result["agents"]), 0)
+ self.assertEqual(len(result["workflows"]), 1)
+ entry = result["workflows"][0]
+ self.assertEqual(entry["description"], "Create a PRD.")
+
+ def test_dual_surface_skill_emits_two_entries(self):
+ _make_skill(
+ self.skills,
+ "bmad-dual",
+ "[agent]\nicon = \"x\"\n\n[workflow]\npersistent_facts = []\n",
+ "---\nname: bmad-dual\ndescription: Dual.\n---\n",
+ )
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(len(result["agents"]), 1)
+ self.assertEqual(len(result["workflows"]), 1)
+ self.assertEqual(result["agents"][0]["name"], "bmad-dual")
+ self.assertEqual(result["workflows"][0]["name"], "bmad-dual")
+
+ def test_skill_without_customize_toml_ignored(self):
+ (self.skills / "bmad-plain").mkdir()
+ (self.skills / "bmad-plain" / "SKILL.md").write_text("# plain\n")
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(len(result["agents"]) + len(result["workflows"]), 0)
+ self.assertEqual(result["errors"], [])
+
+ def test_existing_team_override_flagged(self):
+ _make_skill(
+ self.skills,
+ "bmad-agent-pm",
+ "[agent]\nicon = \"x\"\n",
+ "---\nname: bmad-agent-pm\ndescription: PM.\n---\n",
+ )
+ (self.custom / "bmad-agent-pm.toml").write_text("[agent]\n")
+ result = MODULE.scan_skills([self.skills], self.root)
+ entry = result["agents"][0]
+ self.assertTrue(entry["has_team_override"])
+ self.assertFalse(entry["has_user_override"])
+
+ def test_missing_surface_block_reports_error(self):
+ _make_skill(self.skills, "bmad-broken", "[not_a_surface]\nfoo = 1\n")
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(len(result["agents"]) + len(result["workflows"]), 0)
+ self.assertEqual(len(result["errors"]), 1)
+ self.assertIn("no [agent] or [workflow] block", result["errors"][0])
+
+ def test_malformed_toml_reports_error_without_aborting(self):
+ skill_dir = self.skills / "bmad-bad"
+ skill_dir.mkdir()
+ (skill_dir / "customize.toml").write_text("this is not [valid toml\n")
+ # Plus a good sibling to confirm scanning continues.
+ _make_skill(
+ self.skills,
+ "bmad-good",
+ "[agent]\nicon = \"x\"\n",
+ "---\nname: bmad-good\ndescription: Good.\n---\n",
+ )
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(len(result["agents"]), 1)
+ self.assertEqual(result["agents"][0]["name"], "bmad-good")
+ self.assertTrue(any("failed to parse" in e for e in result["errors"]))
+
+ def test_description_with_double_quotes_stripped(self):
+ _make_skill(
+ self.skills,
+ "bmad-q",
+ "[agent]\nicon = \"x\"\n",
+ '---\nname: bmad-q\ndescription: "Double-quoted desc."\n---\n',
+ )
+ result = MODULE.scan_skills([self.skills], self.root)
+ self.assertEqual(result["agents"][0]["description"], "Double-quoted desc.")
+
+ def test_multiple_skills_roots_are_merged(self):
+ extra_root = self.root / "extra-skills"
+ extra_root.mkdir()
+ _make_skill(
+ self.skills,
+ "bmad-agent-pm",
+ "[agent]\nicon = \"x\"\n",
+ "---\nname: bmad-agent-pm\ndescription: PM.\n---\n",
+ )
+ _make_skill(
+ extra_root,
+ "bmad-agent-dev",
+ "[agent]\nicon = \"y\"\n",
+ "---\nname: bmad-agent-dev\ndescription: Dev.\n---\n",
+ )
+ result = MODULE.scan_skills([self.skills, extra_root], self.root)
+ names = {a["name"] for a in result["agents"]}
+ self.assertEqual(names, {"bmad-agent-pm", "bmad-agent-dev"})
+ self.assertEqual(len(result["scanned_roots"]), 2)
+
+ def test_duplicate_skill_name_across_roots_first_wins(self):
+ extra_root = self.root / "extra-skills"
+ extra_root.mkdir()
+ _make_skill(
+ self.skills,
+ "bmad-agent-pm",
+ "[agent]\nicon = \"primary\"\n",
+ "---\nname: bmad-agent-pm\ndescription: Primary.\n---\n",
+ )
+ _make_skill(
+ extra_root,
+ "bmad-agent-pm",
+ "[agent]\nicon = \"duplicate\"\n",
+ "---\nname: bmad-agent-pm\ndescription: Duplicate.\n---\n",
+ )
+ result = MODULE.scan_skills([self.skills, extra_root], self.root)
+ self.assertEqual(len(result["agents"]), 1)
+ self.assertEqual(result["agents"][0]["description"], "Primary.")
+ self.assertEqual(result["agents"][0]["skills_root"], str(self.skills))
+
+ def test_missing_skills_root_reports_error(self):
+ result = MODULE.scan_skills(
+ [self.root / "does-not-exist", self.skills],
+ self.root,
+ )
+ self.assertTrue(any("skills root does not exist" in e for e in result["errors"]))
+
+ def test_cli_emits_valid_json_and_exits_zero(self):
+ _make_skill(
+ self.skills,
+ "bmad-agent-pm",
+ "[agent]\nicon = \"x\"\n",
+ "---\nname: bmad-agent-pm\ndescription: PM.\n---\n",
+ )
+ proc = subprocess.run(
+ [
+ sys.executable,
+ str(SCRIPT),
+ "--project-root",
+ str(self.root),
+ "--skills-root",
+ str(self.skills),
+ ],
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+ self.assertEqual(proc.returncode, 0, proc.stderr)
+ payload = json.loads(proc.stdout)
+ self.assertEqual(len(payload["agents"]), 1)
+
+ def test_cli_exits_two_on_missing_project_root(self):
+ proc = subprocess.run(
+ [
+ sys.executable,
+ str(SCRIPT),
+ "--project-root",
+ str(self.root / "does-not-exist"),
+ "--skills-root",
+ str(self.skills),
+ ],
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+ self.assertEqual(proc.returncode, 2)
+ self.assertIn("does not exist", proc.stderr)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/80_bmad/base/_bmad/bmm/workflows/4-implementation/dev-story/instructions.xml b/80_bmad/base/.agents/skills/bmad-dev-story/SKILL.md
similarity index 78%
rename from 80_bmad/base/_bmad/bmm/workflows/4-implementation/dev-story/instructions.xml
rename to 80_bmad/base/.agents/skills/bmad-dev-story/SKILL.md
index 27da4ce..a55bc2f 100644
--- a/80_bmad/base/_bmad/bmm/workflows/4-implementation/dev-story/instructions.xml
+++ b/80_bmad/base/.agents/skills/bmad-dev-story/SKILL.md
@@ -1,21 +1,91 @@
+---
+name: bmad-dev-story
+description: 'Execute story implementation following a context filled story spec file. Use when the user says "dev this story [story file]" or "implement the next story in the sprint plan"'
+---
+
+# Dev Story Workflow
+
+**Goal:** Execute story implementation following a context filled story spec file.
+
+**Your Role:** Developer implementing the story.
+- Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level}
+- Generate all documents in {document_output_language}
+- Only modify the story file in these areas: YAML frontmatter `baseline_commit`, Tasks/Subtasks checkboxes, Dev Agent Record (Debug Log, Completion Notes), File List, Change Log, and Status
+- Execute ALL steps in exact order; do NOT skip steps
+- Absolutely DO NOT stop because of "milestones", "significant progress", or "session boundaries". Continue in a single execution until the story is COMPLETE (all ACs satisfied and all tasks/subtasks checked) UNLESS a HALT condition is triggered or the USER gives other instruction.
+- Do NOT schedule a "next session" or request review pauses unless a HALT condition applies. Only Step 9 decides completion.
+- User skill level ({user_skill_level}) affects conversation style ONLY, not code updates.
+
+## Conventions
+
+- Bare paths (e.g. `steps/step-01-init.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+
+- `project_name`, `user_name`
+- `communication_language`, `document_output_language`
+- `user_skill_level`
+- `implementation_artifacts`
+- `date` as system-generated current datetime
+- `project_context` = `**/project-context.md` (load if exists)
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Paths
+
+- `story_file` = `` (explicit story path; auto-discovered if empty)
+- `sprint_status` = `{implementation_artifacts}/sprint-status.yaml`
+
+## Execution
+
- The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml
- You MUST have already loaded and processed: {installed_path}/workflow.yaml
Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level}
Generate all documents in {document_output_language}
- Only modify the story file in these areas: Tasks/Subtasks checkboxes, Dev Agent Record (Debug Log, Completion Notes), File List,
+ Only modify the story file in these areas: YAML frontmatter `baseline_commit`, Tasks/Subtasks checkboxes, Dev Agent Record (Debug Log, Completion Notes), File List,
Change Log, and Status
Execute ALL steps in exact order; do NOT skip steps
Absolutely DO NOT stop because of "milestones", "significant progress", or "session boundaries". Continue in a single execution
until the story is COMPLETE (all ACs satisfied and all tasks/subtasks checked) UNLESS a HALT condition is triggered or the USER gives
other instruction.
- Do NOT schedule a "next session" or request review pauses unless a HALT condition applies. Only Step 6 decides completion.
+ Do NOT schedule a "next session" or request review pauses unless a HALT condition applies. Only Step 9 decides completion.
User skill level ({user_skill_level}) affects conversation style ONLY, not code updates.
- Before any implementation work, synchronize Lead_tech project registry via: `bash $LEADTECH/scripts/sync-projects-conf.sh --project-root {project-root} --sync-existing`.
- Run: `bash $LEADTECH/scripts/sync-projects-conf.sh --project-root {project-root} --sync-existing`
- Output warning and continue only if story work can proceed safely.
Use {{story_path}} directly
Read COMPLETE story file
@@ -131,7 +201,7 @@
Identify first incomplete task (unchecked [ ]) in Tasks/Subtasks
- Completion sequence
+ Completion sequence
HALT: "Cannot develop story without access to story file"
ASK user to clarify or HALT
@@ -191,25 +261,40 @@
+ If story file YAML frontmatter already contains `baseline_commit`, preserve the existing value and do not overwrite it
+
Load the FULL file: {{sprint_status}}
Read all development_status entries to find {{story_key}}
- Get current status value for development_status[{{story_key}}]
+ Set {{current_status}} to development_status[{{story_key}}]
+
-
+
+ Set {{current_status}} to the story file Status section value
+
+
+
+ Run `git rev-parse HEAD` to capture current commit into {{baseline_commit}}; if git/version control is unavailable, set {{baseline_commit}} = `NO_VCS`
+ If story file YAML frontmatter exists, add `baseline_commit: {{baseline_commit}}` to the frontmatter
+ If story file has no YAML frontmatter, create frontmatter at the top containing only `baseline_commit: {{baseline_commit}}`
+
+
+
+
Update the story in the sprint status report to = "in-progress"
+ Update last_updated field to current date
-
+
-
+
@@ -224,27 +309,6 @@
-
- Before implementation, read `Parallel-safe`, `Depends-on`, and `Can-run-with` from the story file.
- If metadata conflicts with the actual code state or branch reality, stop and reconcile the story before coding.
-
-
-
- Extract domain from story file (backend|frontend|ux|n8n|product|workflow)
- Build plan_text: concatenate story tasks/subtasks and Dev Notes sections
- Call MCP tool: validate_plan(domain={{domain}}, plan_text={{plan_text}}, agent_role="builder", strict=true)
- Write gate result into story section "Leadtech MCP Gates": { tool: "validate_plan", timestamp: now, must_do, red_flags, blocking_issues }
- Si blocking_issues est non vide: HALT — corriger le plan avant de commencer l'implémentation
-
-
- Scan must_do and red_flags for URIs of the form "leadtech://knowledge/..." or "leadtech://global/...".
- For each URI found: read the full document via the corresponding MCP resource.
- Use the content to reinforce implementation constraints — treat it as authoritative Lead_tech guidance.
-
-
- Appliquer chaque must_do du résultat comme contrainte d'implémentation
-
-
FOLLOW THE STORY FILE TASKS/SUBTASKS SEQUENCE EXACTLY AS WRITTEN - NO DEVIATION
@@ -348,17 +412,6 @@
Verify ALL tasks and subtasks are marked [x] (re-scan the story document now)
Run the full regression suite (do not skip)
Confirm File List includes every changed file
-
-
-
- Produce diff_text: concatenate git diff or list of changes made during implementation
- Extract changed_files list from story File List section
- Call MCP tool: validate_patch(domain={{domain}}, diff_text={{diff_text}}, changed_files={{changed_files}}, strict=true)
- Write gate result into story section "Leadtech MCP Gates": { tool: "validate_patch", timestamp: now, must_do, red_flags, blocking_issues }
- Si blocking_issues est non vide: HALT — corriger avant de passer en review
- Si must_do non vide et non déjà couverts: traiter comme tâches complémentaires avant review
-
-
Execute enhanced definition-of-done validation
Update the story Status to: "review"
@@ -383,6 +436,7 @@
Find development_status key matching {{story_key}}
Verify current status is "in-progress" (expected previous state)
Update development_status[{{story_key}}] = "review"
+ Update last_updated field to current date
Save file, preserving ALL comments and structure including STATUS DEFINITIONS
@@ -440,6 +494,7 @@
Suggest checking {sprint_status} to see project progress
Remain flexible - allow user to choose their own path or ask for other assistance
+ Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.
diff --git a/80_bmad/base/_bmad/bmm/workflows/4-implementation/dev-story/checklist.md b/80_bmad/base/.agents/skills/bmad-dev-story/checklist.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/4-implementation/dev-story/checklist.md
rename to 80_bmad/base/.agents/skills/bmad-dev-story/checklist.md
diff --git a/80_bmad/base/.agents/skills/bmad-dev-story/customize.toml b/80_bmad/base/.agents/skills/bmad-dev-story/customize.toml
new file mode 100644
index 0000000..84f5dcb
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-dev-story/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-dev-story. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All stories must include testable acceptance criteria."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches its final step,
+# after the story implementation is complete and status is updated. Override wins.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-document-project/SKILL.md b/80_bmad/base/.agents/skills/bmad-document-project/SKILL.md
new file mode 100644
index 0000000..045ffb2
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-document-project/SKILL.md
@@ -0,0 +1,62 @@
+---
+name: bmad-document-project
+description: 'Document brownfield projects for AI context. Use when the user says "document this project" or "generate project docs"'
+---
+
+# Document Project Workflow
+
+**Goal:** Document brownfield projects for AI context.
+
+**Your Role:** Project documentation specialist.
+
+## Conventions
+
+- Bare paths (e.g. `instructions.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+- Use `{user_name}` for greeting
+- Use `{communication_language}` for all communications
+- Use `{document_output_language}` for output documents
+- Use `{planning_artifacts}` for output location and artifact scanning
+- Use `{project_knowledge}` for additional context scanning
+
+### Step 5: Greet the User
+
+Greet `{user_name}` (if you have not already), speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Execution
+
+Read fully and follow: `./instructions.md`
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/checklist.md b/80_bmad/base/.agents/skills/bmad-document-project/checklist.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/checklist.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/checklist.md
diff --git a/80_bmad/base/.agents/skills/bmad-document-project/customize.toml b/80_bmad/base/.agents/skills/bmad-document-project/customize.toml
new file mode 100644
index 0000000..fa21eff
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-document-project/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-document-project. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All briefs must include a regulatory-risk section."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches its terminal stage, after
+# the main output has been delivered. Override wins. Leave empty for
+# no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/documentation-requirements.csv b/80_bmad/base/.agents/skills/bmad-document-project/documentation-requirements.csv
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/documentation-requirements.csv
rename to 80_bmad/base/.agents/skills/bmad-document-project/documentation-requirements.csv
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/instructions.md b/80_bmad/base/.agents/skills/bmad-document-project/instructions.md
similarity index 84%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/instructions.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/instructions.md
index 0354be6..4a57b88 100644
--- a/80_bmad/base/_bmad/bmm/workflows/document-project/instructions.md
+++ b/80_bmad/base/.agents/skills/bmad-document-project/instructions.md
@@ -1,7 +1,5 @@
# Document Project Workflow Router
-The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml
-You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/document-project/workflow.yaml
Communicate all responses in {communication_language}
@@ -42,18 +40,18 @@
Load cached project_type_id(s) from state file
CONDITIONAL CSV LOADING FOR RESUME:
- For each cached project_type_id, load ONLY the corresponding row from: {documentation_requirements_csv}
+ 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}}"
- Read fully and follow: {installed_path}/workflows/deep-dive-instructions.md with resume context
+ Read fully and follow: ./workflows/deep-dive-workflow.md with resume context
- Read fully and follow: {installed_path}/workflows/full-scan-instructions.md with resume context
+ Read fully and follow: ./workflows/full-scan-workflow.md with resume context
@@ -100,7 +98,7 @@ Your choice [1/2/3]:
Set workflow_mode = "full_rescan"
Display: "Starting full project rescan..."
- Read fully and follow: {installed_path}/workflows/full-scan-instructions.md
+ Read fully and follow: ./workflows/full-scan-workflow.md
After sub-workflow completes, continue to Step 4
@@ -108,7 +106,7 @@ Your choice [1/2/3]:
Set workflow_mode = "deep_dive"
Set scan_level = "exhaustive"
Display: "Starting deep-dive documentation mode..."
- Read fully and follow: {installed_path}/workflows/deep-dive-instructions.md
+ Read fully and follow: ./workflows/deep-dive-workflow.md
After sub-workflow completes, continue to Step 4
@@ -121,7 +119,7 @@ Your choice [1/2/3]:
Set workflow_mode = "initial_scan"
Display: "No existing documentation found. Starting initial project scan..."
- Read fully and follow: {installed_path}/workflows/full-scan-instructions.md
+ Read fully and follow: ./workflows/full-scan-workflow.md
After sub-workflow completes, continue to Step 4
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/templates/deep-dive-template.md b/80_bmad/base/.agents/skills/bmad-document-project/templates/deep-dive-template.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/templates/deep-dive-template.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/templates/deep-dive-template.md
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/templates/index-template.md b/80_bmad/base/.agents/skills/bmad-document-project/templates/index-template.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/templates/index-template.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/templates/index-template.md
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/templates/project-overview-template.md b/80_bmad/base/.agents/skills/bmad-document-project/templates/project-overview-template.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/templates/project-overview-template.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/templates/project-overview-template.md
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/templates/project-scan-report-schema.json b/80_bmad/base/.agents/skills/bmad-document-project/templates/project-scan-report-schema.json
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/templates/project-scan-report-schema.json
rename to 80_bmad/base/.agents/skills/bmad-document-project/templates/project-scan-report-schema.json
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/templates/source-tree-template.md b/80_bmad/base/.agents/skills/bmad-document-project/templates/source-tree-template.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/templates/source-tree-template.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/templates/source-tree-template.md
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/workflows/deep-dive-instructions.md b/80_bmad/base/.agents/skills/bmad-document-project/workflows/deep-dive-instructions.md
similarity index 95%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/workflows/deep-dive-instructions.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/workflows/deep-dive-instructions.md
index 637621c..9ab07ee 100644
--- a/80_bmad/base/_bmad/bmm/workflows/document-project/workflows/deep-dive-instructions.md
+++ b/80_bmad/base/.agents/skills/bmad-document-project/workflows/deep-dive-instructions.md
@@ -3,8 +3,9 @@
This workflow performs exhaustive deep-dive documentation of specific areas
-Called by: ../document-project/instructions.md router
Handles: deep_dive mode only
+YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the configured `{communication_language}`
+YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`
Deep-dive mode requires literal full-file review. Sampling, guessing, or relying solely on tooling output is FORBIDDEN.
@@ -192,7 +193,7 @@ This will read EVERY file in this area. Proceed? [y/n]
- Combine recommended test commands into {{suggested_tests}}
-Load complete deep-dive template from: {installed_path}/templates/deep-dive-template.md
+Load complete deep-dive template from: ../templates/deep-dive-template.md
Fill template with all collected data from steps 13b-13d
Write filled template to: {project_knowledge}/deep-dive-{{sanitized_target_name}}.md
Validate deep-dive document completeness
@@ -290,6 +291,7 @@ These comprehensive docs are now ready for:
Thank you for using the document-project workflow!
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.
Exit workflow
diff --git a/80_bmad/base/.agents/skills/bmad-document-project/workflows/deep-dive-workflow.md b/80_bmad/base/.agents/skills/bmad-document-project/workflows/deep-dive-workflow.md
new file mode 100644
index 0000000..c55f036
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-document-project/workflows/deep-dive-workflow.md
@@ -0,0 +1,34 @@
+# Deep-Dive Documentation Sub-Workflow
+
+**Goal:** Exhaustive deep-dive documentation of specific project areas.
+
+**Your Role:** Deep-dive documentation specialist.
+- Deep-dive mode requires literal full-file review. Sampling, guessing, or relying solely on tooling output is FORBIDDEN.
+
+---
+
+## INITIALIZATION
+
+### Configuration Loading
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+
+- `project_knowledge`
+- `user_name`
+- `communication_language`, `document_output_language`
+- `date` as system-generated current datetime
+
+✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the configured `{communication_language}`.
+✅ YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`.
+
+### Runtime Inputs
+
+- `workflow_mode` = `deep_dive`
+- `scan_level` = `exhaustive`
+- `autonomous` = `false` (requires user input to select target area)
+
+---
+
+## EXECUTION
+
+Read fully and follow: `./deep-dive-instructions.md`
diff --git a/80_bmad/base/_bmad/bmm/workflows/document-project/workflows/full-scan-instructions.md b/80_bmad/base/.agents/skills/bmad-document-project/workflows/full-scan-instructions.md
similarity index 98%
rename from 80_bmad/base/_bmad/bmm/workflows/document-project/workflows/full-scan-instructions.md
rename to 80_bmad/base/.agents/skills/bmad-document-project/workflows/full-scan-instructions.md
index 8a3621d..3569725 100644
--- a/80_bmad/base/_bmad/bmm/workflows/document-project/workflows/full-scan-instructions.md
+++ b/80_bmad/base/.agents/skills/bmad-document-project/workflows/full-scan-instructions.md
@@ -3,8 +3,9 @@
This workflow performs complete project documentation (Steps 1-12)
-Called by: document-project/instructions.md router
Handles: initial_scan and full_rescan modes
+YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the configured `{communication_language}`
+YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`
DATA LOADING STRATEGY - Understanding the Documentation Requirements System:
@@ -15,7 +16,7 @@
This workflow uses a single comprehensive CSV file to intelligently document your project:
-**documentation-requirements.csv** ({documentation_requirements_csv})
+**documentation-requirements.csv** (../documentation-requirements.csv)
- Contains 12 project types (web, mobile, backend, cli, library, desktop, game, data, extension, infra, embedded)
- 24-column schema combining project type detection AND documentation requirements
@@ -35,7 +36,7 @@ This workflow uses a single comprehensive CSV file to intelligently document you
Now loading documentation requirements data for fresh start...
-Load documentation-requirements.csv from: {documentation_requirements_csv}
+Load documentation-requirements.csv from: ../documentation-requirements.csv
Store all 12 rows indexed by project_type_id for project detection and requirements lookup
Display: "Loaded documentation requirements for 12 project types (web, mobile, backend, cli, library, desktop, game, data, extension, infra, embedded)"
@@ -809,7 +810,7 @@ Generated in {{project_knowledge}}/:
{{file_list_with_sizes}}
-Run validation checklist from {validation}
+Run validation checklist from ../checklist.md
INCOMPLETE DOCUMENTATION DETECTION:
@@ -1102,5 +1103,6 @@ When ready to plan new features, run the PRD workflow and provide this index as
Display: "State file saved: {{project_knowledge}}/project-scan-report.json"
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.
diff --git a/80_bmad/base/.agents/skills/bmad-document-project/workflows/full-scan-workflow.md b/80_bmad/base/.agents/skills/bmad-document-project/workflows/full-scan-workflow.md
new file mode 100644
index 0000000..5aaf4a5
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-document-project/workflows/full-scan-workflow.md
@@ -0,0 +1,34 @@
+# Full Project Scan Sub-Workflow
+
+**Goal:** Complete project documentation (initial scan or full rescan).
+
+**Your Role:** Full project scan documentation specialist.
+
+---
+
+## INITIALIZATION
+
+### Configuration Loading
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+
+- `project_knowledge`
+- `user_name`
+- `communication_language`, `document_output_language`
+- `date` as system-generated current datetime
+
+✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the configured `{communication_language}`.
+✅ YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`.
+
+### Runtime Inputs
+
+- `workflow_mode` = `""` (set by parent: `initial_scan` or `full_rescan`)
+- `scan_level` = `""` (set by parent: `quick`, `deep`, or `exhaustive`)
+- `resume_mode` = `false`
+- `autonomous` = `false` (requires user input at key decision points)
+
+---
+
+## EXECUTION
+
+Read fully and follow: `./full-scan-instructions.md`
diff --git a/80_bmad/base/.agents/skills/bmad-domain-research/SKILL.md b/80_bmad/base/.agents/skills/bmad-domain-research/SKILL.md
new file mode 100644
index 0000000..9ea915f
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/SKILL.md
@@ -0,0 +1,96 @@
+---
+name: bmad-domain-research
+description: 'Conduct domain and industry research. Use when the user says wants to do domain research for a topic or industry'
+---
+
+# Domain Research Workflow
+
+**Goal:** Conduct comprehensive domain/industry research using current web data and verified sources to produce complete research documents with compelling narratives and proper citations.
+
+**Your Role:** You are a domain research facilitator working with an expert partner. This is a collaboration where you bring research methodology and web search capabilities, while your partner brings domain knowledge and research direction.
+
+## Conventions
+
+- Bare paths (e.g. `domain-steps/step-01-init.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## PREREQUISITE
+
+**⛔ Web search required.** If unavailable, abort and tell the user.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+- Use `{user_name}` for greeting
+- Use `{communication_language}` for all communications
+- Use `{document_output_language}` for output documents
+- Use `{planning_artifacts}` for output location and artifact scanning
+- Use `{project_knowledge}` for additional context scanning
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## QUICK TOPIC DISCOVERY
+
+"Welcome {{user_name}}! Let's get started with your **domain/industry research**.
+
+**What domain, industry, or sector do you want to research?**
+
+For example:
+- 'The healthcare technology industry'
+- 'Sustainable packaging regulations in Europe'
+- 'Construction and building materials sector'
+- 'Or any other domain you have in mind...'"
+
+### Topic Clarification
+
+Based on the user's topic, briefly clarify:
+1. **Core Domain**: "What specific aspect of [domain] are you most interested in?"
+2. **Research Goals**: "What do you hope to achieve with this research?"
+3. **Scope**: "Should we focus broadly or dive deep into specific aspects?"
+
+## ROUTE TO DOMAIN RESEARCH STEPS
+
+After gathering the topic and goals:
+
+1. Set `research_type = "domain"`
+2. Set `research_topic = [discovered topic from discussion]`
+3. Set `research_goals = [discovered goals from discussion]`
+4. Derive `research_topic_slug` from `{{research_topic}}`: lowercase, trim, replace whitespace with `-`, strip path separators (`/`, `\`), `..`, and any character that is not alphanumeric, `-`, or `_`. Collapse repeated `-` and strip leading/trailing `-`. If the result is empty, use `untitled`.
+5. Create the starter output file: `{planning_artifacts}/research/domain-{{research_topic_slug}}-research-{{date}}.md` with exact copy of the `./research.template.md` contents
+6. Load: `./domain-steps/step-01-init.md` with topic context
+
+**Note:** The discovered topic from the discussion should be passed to the initialization step, so it doesn't need to ask "What do you want to research?" again - it can focus on refining the scope for domain research.
+
+**✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`**
diff --git a/80_bmad/base/.agents/skills/bmad-domain-research/customize.toml b/80_bmad/base/.agents/skills/bmad-domain-research/customize.toml
new file mode 100644
index 0000000..d401cf3
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-domain-research. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All briefs must include a regulatory-risk section."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches its terminal stage (Step 6: Research Synthesis),
+# after the domain research document has been saved and the user selects [C] Complete.
+# Override wins. Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-01-init.md
similarity index 95%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-01-init.md
index 5009318..27d056b 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-01-init.md
@@ -78,7 +78,7 @@ For **{{research_topic}}**, I will research:
- Document scope confirmation in research file
- Update frontmatter: `stepsCompleted: [1]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md`
+- Load: `./step-02-domain-analysis.md`
## APPEND TO DOCUMENT:
@@ -132,6 +132,6 @@ When user selects 'C', append scope confirmation:
## NEXT STEP:
-After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md` to begin industry analysis.
+After user selects 'C', load `./step-02-domain-analysis.md` to begin industry analysis.
Remember: This is SCOPE CONFIRMATION ONLY - no actual domain research yet, just confirming the research approach and scope!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-02-domain-analysis.md
similarity index 96%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-02-domain-analysis.md
index ed5c78f..bb4cbb6 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-02-domain-analysis.md
@@ -171,7 +171,7 @@ _Source: [URL]_
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md`
+- Load: `./step-03-competitive-landscape.md`
## APPEND TO DOCUMENT:
@@ -224,6 +224,6 @@ Content is already written to document when generated in step 4. No additional a
## NEXT STEP:
-After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md` to analyze competitive landscape, key players, and ecosystem analysis for {{research_topic}}.
+After user selects 'C', load `./step-03-competitive-landscape.md` to analyze competitive landscape, key players, and ecosystem analysis for {{research_topic}}.
Remember: Always write research content to document immediately and search the web to verify facts!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-03-competitive-landscape.md
similarity index 96%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-03-competitive-landscape.md
index 6970ad8..0dc2de6 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-03-competitive-landscape.md
@@ -180,7 +180,7 @@ _Source: [URL]_
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2, 3]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md`
+- Load: `./step-04-regulatory-focus.md`
## APPEND TO DOCUMENT:
@@ -233,6 +233,6 @@ Content is already written to document when generated in step 4. No additional a
## NEXT STEP:
-After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md` to analyze regulatory requirements, compliance frameworks, and legal considerations for {{research_topic}}.
+After user selects 'C', load `./step-04-regulatory-focus.md` to analyze regulatory requirements, compliance frameworks, and legal considerations for {{research_topic}}.
Remember: Always write research content to document immediately and search the web to verify facts!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-04-regulatory-focus.md
similarity index 95%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-04-regulatory-focus.md
index 3fd24b0..e98010c 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-04-regulatory-focus.md
@@ -155,7 +155,7 @@ Show the generated regulatory analysis and present continue option:
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md`
+- Load: `./step-05-technical-trends.md`
## APPEND TO DOCUMENT:
@@ -201,6 +201,6 @@ Content is already written to document when generated in step 5. No additional a
## NEXT STEP:
-After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md` to analyze technical trends and innovations in the domain.
+After user selects 'C' and content is saved to document, load `./step-05-technical-trends.md` to analyze technical trends and innovations in the domain.
Remember: Search the web to verify regulatory facts and provide practical implementation considerations!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-05-technical-trends.md
similarity index 98%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-05-technical-trends.md
index caf69e1..55e834c 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-05-technical-trends.md
@@ -174,7 +174,7 @@ Show the generated technical analysis and present complete option:
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md`
+- Load: `./step-06-research-synthesis.md`
## APPEND TO DOCUMENT:
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-06-research-synthesis.md
similarity index 98%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-06-research-synthesis.md
index 9e2261f..07d2123 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md
+++ b/80_bmad/base/.agents/skills/bmad-domain-research/domain-steps/step-06-research-synthesis.md
@@ -441,4 +441,10 @@ Complete authoritative research document on {{research_topic}} that:
- Serves as reference document for continued use
- Maintains highest research quality standards
+## On Complete
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
+
+If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
+
Congratulations on completing comprehensive domain research! 🎉
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/research.template.md b/80_bmad/base/.agents/skills/bmad-domain-research/research.template.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/research.template.md
rename to 80_bmad/base/.agents/skills/bmad-domain-research/research.template.md
diff --git a/80_bmad/base/.agents/skills/bmad-edit-prd/SKILL.md b/80_bmad/base/.agents/skills/bmad-edit-prd/SKILL.md
new file mode 100644
index 0000000..ee952e6
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-edit-prd/SKILL.md
@@ -0,0 +1,30 @@
+---
+name: bmad-edit-prd
+description: 'DEPRECATED — consolidated into bmad-prd update intent - this skill will be removed in v7 in favor of `bmad-prd`.'
+---
+
+# DEPRECATED — forwards to bmad-prd (update intent)
+
+This skill was consolidated into `bmad-prd`. It is retained as a thin compatibility shim so existing invocations by name and `_bmad/custom/bmad-edit-prd.toml` override files keep working. New work should invoke `bmad-prd` directly — it detects create / update / validate intent from the conversation.
+
+## On Activation
+
+1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-edit-prd.toml` and `bmad-edit-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
+
+2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
+
+3. Emit a deprecation notice to the user in `{communication_language}`:
+
+ > Notice: `bmad-edit-prd` is deprecated and will be removed in a future release. It now forwards to `bmad-prd` with update intent. To silence this notice and access the full new customization surface (`prd_template`, `validation_checklist`, `doc_standards`, `external_sources`, `external_handoffs`, `output_dir`, `output_folder_name`), migrate `_bmad/custom/bmad-edit-prd.toml` to `_bmad/custom/bmad-prd.toml` and invoke `bmad-prd` directly next time. Customization fields that were in this version still remain in the new version and will be respected if present in `_bmad/custom/bmad-prd.toml`, but the new version also supports additional fields that you can take advantage of by migrating.
+
+4. Invoke `bmad-prd` with the following context. Pass these as the activating context so `bmad-prd` honors them instead of resolving its own customization from scratch:
+
+ - **Intent:** `update` — skip `bmad-prd`'s usual intent detection step.
+ - **Pre-resolved legacy customization** — use these in place of resolving from `bmad-prd`'s own `customize.toml` for the four legacy fields. For everything else (`prd_template`, `validation_checklist`, `validation_report_template`, `doc_standards`, `output_dir`, `output_folder_name`, `external_sources`, `external_handoffs`), use `bmad-prd`'s own defaults and overrides as normal:
+ - `activation_steps_prepend` = the resolved value from step 1
+ - `activation_steps_append` = the resolved value from step 1
+ - `persistent_facts` = the resolved value from step 1
+ - `on_complete` = the resolved value from step 1
+ - **Original user input:** forward whatever the user said when invoking this skill verbatim (the target PRD path, the change signal, etc.).
+
+ `bmad-prd` takes the workflow from here. Do not execute any further steps in this shim.
diff --git a/80_bmad/base/.agents/skills/bmad-edit-prd/customize.toml b/80_bmad/base/.agents/skills/bmad-edit-prd/customize.toml
new file mode 100644
index 0000000..1886d4a
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-edit-prd/customize.toml
@@ -0,0 +1,42 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-edit-prd. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All PRDs must include a regulatory-risk section."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step E-4 (Complete & Validate) and the
+# user exits via [S] Summary or [X] Exit — not on [V] Validate (which chains to
+# bmad-validate-prd) or [E] Edit More (which loops back). Override wins.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-editorial-review-prose/SKILL.md b/80_bmad/base/.agents/skills/bmad-editorial-review-prose/SKILL.md
index 0330f9b..3498f92 100644
--- a/80_bmad/base/.agents/skills/bmad-editorial-review-prose/SKILL.md
+++ b/80_bmad/base/.agents/skills/bmad-editorial-review-prose/SKILL.md
@@ -1,10 +1,86 @@
---
name: bmad-editorial-review-prose
-description: Execute editorial-review-prose
+description: 'Clinical copy-editor that reviews text for communication issues. Use when user says review for prose or improve the prose'
---
-# editorial-review-prose
+# Editorial Review - Prose
-Read the entire task file at: {project-root}/_bmad/core/tasks/editorial-review-prose.xml
+**Goal:** Review text for communication issues that impede comprehension and output suggested fixes in a three-column table.
-Follow all instructions in the task file exactly as written.
+**Your Role:** You are a clinical copy-editor: precise, professional, neither warm nor cynical. Apply Microsoft Writing Style Guide principles as your baseline. Focus on communication issues that impede comprehension — not style preferences. NEVER rewrite for preference — only fix genuine issues. Follow ALL steps in the STEPS section IN EXACT ORDER. DO NOT skip steps or change the sequence. HALT immediately when halt-conditions are met. Each action within a step is a REQUIRED action to complete that step.
+
+**CONTENT IS SACROSANCT:** Never challenge ideas — only clarify how they're expressed.
+
+**Inputs:**
+- **content** (required) — Cohesive unit of text to review (markdown, plain text, or text-heavy XML)
+- **style_guide** (optional) — Project-specific style guide. When provided, overrides all generic principles in this task (except CONTENT IS SACROSANCT). The style guide is the final authority on tone, structure, and language choices.
+- **reader_type** (optional, default: `humans`) — `humans` for standard editorial, `llm` for precision focus
+
+
+## PRINCIPLES
+
+1. **Minimal intervention:** Apply the smallest fix that achieves clarity
+2. **Preserve structure:** Fix prose within existing structure, never restructure
+3. **Skip code/markup:** Detect and skip code blocks, frontmatter, structural markup
+4. **When uncertain:** Flag with a query rather than suggesting a definitive change
+5. **Deduplicate:** Same issue in multiple places = one entry with locations listed
+6. **No conflicts:** Merge overlapping fixes into single entries
+7. **Respect author voice:** Preserve intentional stylistic choices
+
+> **STYLE GUIDE OVERRIDE:** If a style_guide input is provided, it overrides ALL generic principles in this task (including the Microsoft Writing Style Guide baseline and reader_type-specific priorities). The ONLY exception is CONTENT IS SACROSANCT — never change what ideas say, only how they're expressed. When style guide conflicts with this task, style guide wins.
+
+
+## STEPS
+
+### Step 1: Validate Input
+
+- Check if content is empty or contains fewer than 3 words
+ - If empty or fewer than 3 words: **HALT** with error: "Content too short for editorial review (minimum 3 words required)"
+- Validate reader_type is `humans` or `llm` (or not provided, defaulting to `humans`)
+ - If reader_type is invalid: **HALT** with error: "Invalid reader_type. Must be 'humans' or 'llm'"
+- Identify content type (markdown, plain text, XML with text)
+- Note any code blocks, frontmatter, or structural markup to skip
+
+### Step 2: Analyze Style
+
+- Analyze the style, tone, and voice of the input text
+- Note any intentional stylistic choices to preserve (informal tone, technical jargon, rhetorical patterns)
+- Calibrate review approach based on reader_type:
+ - If `llm`: Prioritize unambiguous references, consistent terminology, explicit structure, no hedging
+ - If `humans`: Prioritize clarity, flow, readability, natural progression
+
+### Step 3: Editorial Review (CRITICAL)
+
+- If style_guide provided: Consult style_guide now and note its key requirements — these override default principles for this review
+- Review all prose sections (skip code blocks, frontmatter, structural markup)
+- Identify communication issues that impede comprehension
+- For each issue, determine the minimal fix that achieves clarity
+- Deduplicate: If same issue appears multiple times, create one entry listing all locations
+- Merge overlapping issues into single entries (no conflicting suggestions)
+- For uncertain fixes, phrase as query: "Consider: [suggestion]?" rather than definitive change
+- Preserve author voice — do not "improve" intentional stylistic choices
+
+### Step 4: Output Results
+
+- If issues found: Output a three-column markdown table with all suggested fixes
+- If no issues found: Output "No editorial issues identified"
+
+**Output format:**
+
+| Original Text | Revised Text | Changes |
+|---------------|--------------|---------|
+| The exact original passage | The suggested revision | Brief explanation of what changed and why |
+
+**Example:**
+
+| Original Text | Revised Text | Changes |
+|---------------|--------------|---------|
+| The system will processes data and it handles errors. | The system processes data and handles errors. | Fixed subject-verb agreement ("will processes" to "processes"); removed redundant "it" |
+| Users can chose from options (lines 12, 45, 78) | Users can choose from options | Fixed spelling: "chose" to "choose" (appears in 3 locations) |
+
+
+## HALT CONDITIONS
+
+- HALT with error if content is empty or fewer than 3 words
+- HALT with error if reader_type is not `humans` or `llm`
+- If no issues found after thorough review, output "No editorial issues identified" (this is valid completion, not an error)
diff --git a/80_bmad/base/.agents/skills/bmad-editorial-review-structure/SKILL.md b/80_bmad/base/.agents/skills/bmad-editorial-review-structure/SKILL.md
index 6bcef21..c931831 100644
--- a/80_bmad/base/.agents/skills/bmad-editorial-review-structure/SKILL.md
+++ b/80_bmad/base/.agents/skills/bmad-editorial-review-structure/SKILL.md
@@ -1,10 +1,179 @@
---
name: bmad-editorial-review-structure
-description: Execute editorial-review-structure
+description: 'Structural editor that proposes cuts, reorganization, and simplification while preserving comprehension. Use when user requests structural review or editorial review of structure'
---
-# editorial-review-structure
+# Editorial Review - Structure
-Read the entire task file at: {project-root}/_bmad/core/tasks/editorial-review-structure.xml
+**Goal:** Review document structure and propose substantive changes to improve clarity and flow -- run this BEFORE copy editing.
-Follow all instructions in the task file exactly as written.
+**Your Role:** You are a structural editor focused on HIGH-VALUE DENSITY. Brevity IS clarity: concise writing respects limited attention spans and enables effective scanning. Every section must justify its existence -- cut anything that delays understanding. True redundancy is failure. Follow ALL steps in the STEPS section IN EXACT ORDER. DO NOT skip steps or change the sequence. HALT immediately when halt-conditions are met. Each action within a step is a REQUIRED action to complete that step.
+
+> **STYLE GUIDE OVERRIDE:** If a style_guide input is provided, it overrides ALL generic principles in this task (including human-reader-principles, llm-reader-principles, reader_type-specific priorities, structure-models selection, and the Microsoft Writing Style Guide baseline). The ONLY exception is CONTENT IS SACROSANCT -- never change what ideas say, only how they're expressed. When style guide conflicts with this task, style guide wins.
+
+**Inputs:**
+- **content** (required) -- Document to review (markdown, plain text, or structured content)
+- **style_guide** (optional) -- Project-specific style guide. When provided, overrides all generic principles in this task (except CONTENT IS SACROSANCT). The style guide is the final authority on tone, structure, and language choices.
+- **purpose** (optional) -- Document's intended purpose (e.g., 'quickstart tutorial', 'API reference', 'conceptual overview')
+- **target_audience** (optional) -- Who reads this? (e.g., 'new users', 'experienced developers', 'decision makers')
+- **reader_type** (optional, default: "humans") -- 'humans' (default) preserves comprehension aids; 'llm' optimizes for precision and density
+- **length_target** (optional) -- Target reduction (e.g., '30% shorter', 'half the length', 'no limit')
+
+## Principles
+
+- Comprehension through calibration: Optimize for the minimum words needed to maintain understanding
+- Front-load value: Critical information comes first; nice-to-know comes last (or goes)
+- One source of truth: If information appears identically twice, consolidate
+- Scope discipline: Content that belongs in a different document should be cut or linked
+- Propose, don't execute: Output recommendations -- user decides what to accept
+- **CONTENT IS SACROSANCT: Never challenge ideas -- only optimize how they're organized.**
+
+## Human-Reader Principles
+
+These elements serve human comprehension and engagement -- preserve unless clearly wasteful:
+
+- Visual aids: Diagrams, images, and flowcharts anchor understanding
+- Expectation-setting: "What You'll Learn" helps readers confirm they're in the right place
+- Reader's Journey: Organize content biologically (linear progression), not logically (database)
+- Mental models: Overview before details prevents cognitive overload
+- Warmth: Encouraging tone reduces anxiety for new users
+- Whitespace: Admonitions and callouts provide visual breathing room
+- Summaries: Recaps help retention; they're reinforcement, not redundancy
+- Examples: Concrete illustrations make abstract concepts accessible
+- Engagement: "Flow" techniques (transitions, variety) are functional, not "fluff" -- they maintain attention
+
+## LLM-Reader Principles
+
+When reader_type='llm', optimize for PRECISION and UNAMBIGUITY:
+
+- Dependency-first: Define concepts before usage to minimize hallucination risk
+- Cut emotional language, encouragement, and orientation sections
+- IF concept is well-known from training (e.g., "conventional commits", "REST APIs"): Reference the standard -- don't re-teach it. ELSE: Be explicit -- don't assume the LLM will infer correctly.
+- Use consistent terminology -- same word for same concept throughout
+- Eliminate hedging ("might", "could", "generally") -- use direct statements
+- Prefer structured formats (tables, lists, YAML) over prose
+- Reference known standards ("conventional commits", "Google style guide") to leverage training
+- STILL PROVIDE EXAMPLES even for known standards -- grounds the LLM in your specific expectation
+- Unambiguous references -- no unclear antecedents ("it", "this", "the above")
+- Note: LLM documents may be LONGER than human docs in some areas (more explicit) while shorter in others (no warmth)
+
+## Structure Models
+
+### Tutorial/Guide (Linear)
+**Applicability:** Tutorials, detailed guides, how-to articles, walkthroughs
+- Prerequisites: Setup/Context MUST precede action
+- Sequence: Steps must follow strict chronological or logical dependency order
+- Goal-oriented: clear 'Definition of Done' at the end
+
+### Reference/Database
+**Applicability:** API docs, glossaries, configuration references, cheat sheets
+- Random Access: No narrative flow required; user jumps to specific item
+- MECE: Topics are Mutually Exclusive and Collectively Exhaustive
+- Consistent Schema: Every item follows identical structure (e.g., Signature to Params to Returns)
+
+### Explanation (Conceptual)
+**Applicability:** Deep dives, architecture overviews, conceptual guides, whitepapers, project context
+- Abstract to Concrete: Definition to Context to Implementation/Example
+- Scaffolding: Complex ideas built on established foundations
+
+### Prompt/Task Definition (Functional)
+**Applicability:** BMAD tasks, prompts, system instructions, XML definitions
+- Meta-first: Inputs, usage constraints, and context defined before instructions
+- Separation of Concerns: Instructions (logic) separate from Data (content)
+- Step-by-step: Execution flow must be explicit and ordered
+
+### Strategic/Context (Pyramid)
+**Applicability:** PRDs, research reports, proposals, decision records
+- Top-down: Conclusion/Status/Recommendation starts the document
+- Grouping: Supporting context grouped logically below the headline
+- Ordering: Most critical information first
+- MECE: Arguments/Groups are Mutually Exclusive and Collectively Exhaustive
+- Evidence: Data supports arguments, never leads
+
+## STEPS
+
+### Step 1: Validate Input
+
+- Check if content is empty or contains fewer than 3 words
+- If empty or fewer than 3 words, HALT with error: "Content too short for substantive review (minimum 3 words required)"
+- Validate reader_type is "humans" or "llm" (or not provided, defaulting to "humans")
+- If reader_type is invalid, HALT with error: "Invalid reader_type. Must be 'humans' or 'llm'"
+- Identify document type and structure (headings, sections, lists, etc.)
+- Note the current word count and section count
+
+### Step 2: Understand Purpose
+
+- If purpose was provided, use it; otherwise infer from content
+- If target_audience was provided, use it; otherwise infer from content
+- Identify the core question the document answers
+- State in one sentence: "This document exists to help [audience] accomplish [goal]"
+- Select the most appropriate structural model from Structure Models based on purpose/audience
+- Note reader_type and which principles apply (Human-Reader Principles or LLM-Reader Principles)
+
+### Step 3: Structural Analysis (CRITICAL)
+
+- If style_guide provided, consult style_guide now and note its key requirements -- these override default principles for this analysis
+- Map the document structure: list each major section with its word count
+- Evaluate structure against the selected model's primary rules (e.g., 'Does recommendation come first?' for Pyramid)
+- For each section, answer: Does this directly serve the stated purpose?
+- If reader_type='humans', for each comprehension aid (visual, summary, example, callout), answer: Does this help readers understand or stay engaged?
+- Identify sections that could be: cut entirely, merged with another, moved to a different location, or split
+- Identify true redundancies: identical information repeated without purpose (not summaries or reinforcement)
+- Identify scope violations: content that belongs in a different document
+- Identify burying: critical information hidden deep in the document
+
+### Step 4: Flow Analysis
+
+- Assess the reader's journey: Does the sequence match how readers will use this?
+- Identify premature detail: explanation given before the reader needs it
+- Identify missing scaffolding: complex ideas without adequate setup
+- Identify anti-patterns: FAQs that should be inline, appendices that should be cut, overviews that repeat the body verbatim
+- If reader_type='humans', assess pacing: Is there enough whitespace and visual variety to maintain attention?
+
+### Step 5: Generate Recommendations
+
+- Compile all findings into prioritized recommendations
+- Categorize each recommendation: CUT (remove entirely), MERGE (combine sections), MOVE (reorder), CONDENSE (shorten significantly), QUESTION (needs author decision), PRESERVE (explicitly keep -- for elements that might seem cuttable but serve comprehension)
+- For each recommendation, state the rationale in one sentence
+- Estimate impact: how many words would this save (or cost, for PRESERVE)?
+- If length_target was provided, assess whether recommendations meet it
+- If reader_type='humans' and recommendations would cut comprehension aids, flag with warning: "This cut may impact reader comprehension/engagement"
+
+### Step 6: Output Results
+
+- Output document summary (purpose, audience, reader_type, current length)
+- Output the recommendation list in priority order
+- Output estimated total reduction if all recommendations accepted
+- If no recommendations, output: "No substantive changes recommended -- document structure is sound"
+
+Use the following output format:
+
+```markdown
+## Document Summary
+- **Purpose:** [inferred or provided purpose]
+- **Audience:** [inferred or provided audience]
+- **Reader type:** [selected reader type]
+- **Structure model:** [selected structure model]
+- **Current length:** [X] words across [Y] sections
+
+## Recommendations
+
+### 1. [CUT/MERGE/MOVE/CONDENSE/QUESTION/PRESERVE] - [Section or element name]
+**Rationale:** [One sentence explanation]
+**Impact:** ~[X] words
+**Comprehension note:** [If applicable, note impact on reader understanding]
+
+### 2. ...
+
+## Summary
+- **Total recommendations:** [N]
+- **Estimated reduction:** [X] words ([Y]% of original)
+- **Meets length target:** [Yes/No/No target specified]
+- **Comprehension trade-offs:** [Note any cuts that sacrifice reader engagement for brevity]
+```
+
+## HALT CONDITIONS
+
+- HALT with error if content is empty or fewer than 3 words
+- HALT with error if reader_type is not "humans" or "llm"
+- If no structural issues found, output "No substantive changes recommended" (this is valid completion, not an error)
diff --git a/80_bmad/base/.agents/skills/bmad-forge-idea/SKILL.md b/80_bmad/base/.agents/skills/bmad-forge-idea/SKILL.md
new file mode 100644
index 0000000..e4d3094
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-forge-idea/SKILL.md
@@ -0,0 +1,79 @@
+---
+name: bmad-forge-idea
+description: Pressure-test an idea through persona-driven interrogation until it hardens, proves out, or dies cheaply. Use when the user says 'forge an idea', 'pressure-test this idea', 'stress-test my thinking', or 'harden this idea'.
+---
+
+# BMad Forge Idea
+
+## Overview
+
+Take a half-formed idea out of the user's head and pressure-test it now, in conversation, where changing your mind is free — until what survives is something they can act on with earned conviction, or it dies cheaply. The enemy is the hole you cannot see in your own idea: every unexamined assumption and unresolved branch is a crack that otherwise surfaces later, in the build or the launch, when it costs far more to fix.
+
+The product is the quality of the user's thinking, not an artifact. Hardening an idea, proving or disproving it, or just being an unsparing thinking partner are each a complete outcome. A distilled `forged-idea.md` and a handoff downstream are one optional exit, never the destination — so never herd the user toward "shall we build it?"
+
+This is domain-agnostic — the idea may be software, a business model, a creative concept, a research hypothesis, a life decision, or a frivolous thought experiment. When it's a product or feature — net-new or a change inside an existing project — the forge stands in as an alternative analysis-and-definition tool, and what survives distills into `forged-idea.md` for downstream planning.
+
+Act as an exacting interrogator who would rather find the crack than spare the feelings. This is interactive and socratic by nature; there is no headless mode.
+
+## Conventions
+
+- Scripts live in two places — run each from the exact path written, never assume co-location: the shared core scripts (`memlog.py`, `resolve_customization.py`, `resolve_config.py`) are installed by BMad core at `{project-root}/_bmad/scripts/` and are never bundled here; this skill's own `resolve_personas.py` is at `{skill-root}/scripts/`.
+- `{workflow.}` resolves to fields in the merged `customize.toml` `[workflow]` table.
+
+## On Activation
+
+1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly with defaults. Apply the resolved `{workflow.*}` values throughout.
+2. Run each `{workflow.activation_steps_prepend}` entry; treat each `{workflow.persistent_facts}` entry as foundational context (`file:` entries load their contents, `skill:` names a skill to consult, others are facts verbatim).
+3. Load `{project-root}/_bmad/core/config.yaml` (and `config.user.yaml` if present); resolve `{user_name}`, `{communication_language}`, `{output_folder}`. Missing → neutral defaults; never block. Greet `{user_name}` in `{communication_language}` and stay in it.
+4. Note whether a BMad persona is already active in this conversation — the user loaded one (e.g. the analyst, the storyteller) and invoked the forge from within it. If so, that persona leads the session, in voice, throughout.
+5. Resume: glob `{workflow.forge_output_path}/**/.memlog.md` (recursive, so it still finds sessions when `run_folder_pattern` is overridden to nest paths) and read only each match's frontmatter to find any whose `status` is not `complete`. Offer to resume one — then read its full memlog once to rebuild state and continue append-only — or to start fresh.
+6. Run each `{workflow.activation_steps_append}` entry.
+
+## Open the session
+
+Open cold. Acknowledging the idea is not endorsing it — do not praise it before it has survived anything, on this turn or any turn. The pull to validate the idea up front to build rapport is the exact reflex this skill exists to refuse.
+
+Determine the goal before pressing (if a persona is already active with an idea on the table, confirm it in a line rather than asking). Otherwise ask in one message: what is the idea, and what do you want — harden it, prove or kill it, or just think it through? The goal steers the push: proving goes for the load-bearing claim first; hardening drives each branch to a resolved answer. Note whether the idea is net-new or a change inside an existing project.
+
+Tell the user the gear they can call anytime: **"adversarial on this"** (attacked to destruction — you attack, they defend; "switch roles," "you defend now, they attack"). The room is always in play once the topic is set (see The personas) — they can name any persona or call a whole party by name to steer who's at the table.
+
+Derive a kebab-case `{slug}` for the idea and bind the session workspace `{workspace} = {workflow.forge_output_path}/{workflow.run_folder_pattern}` (the pattern fills with `{slug}`). Create the memlog once the goal is known:
+`uv run {project-root}/_bmad/scripts/memlog.py init --workspace {workspace} --field idea="" --field goal=""`
+Tell the user the path; state is on disk now, so the session survives interruption. If init fails, don't abort — run the forge in-conversation and tell the user state won't persist this session.
+
+## The forge
+
+Work one question at a time, in dependency order. Put your own recommended answer on the table each time — a position to push against gets further than an open prompt. Find discoverable answers yourself rather than asking. Treat the user's own words as suspect too: when a term is fuzzy or carries two meanings — a business 'user' versus 'buyer' versus 'payer', not just a code noun — name the ambiguity and force a precise choice before the branch resolves, because a branch built on an overloaded word resolves falsely. When the idea lands inside an existing project, that project's material is your ground truth, and a label is not a move: find the relevant material yourself, check the claim against it, and when it contradicts, make the contradiction the next question. When a branch resolves, give the user a beat before moving on — the crack they were holding back surfaces in that opening.
+
+**Never default-agree.** Reflexive agreement lowers the pressure and the user thinks shallower for it. Attack the weak point or build on the strong one — whichever drives deeper thinking — and praise only what genuinely earns it. The objective is the best idea, not a comfortable user.
+
+Capture as you go — each decision, assumption, crack, kill, and locked idea, one bullet in the user's meaning:
+`uv run {project-root}/_bmad/scripts/memlog.py append --workspace {workspace} --type --text ""`
+A `lock` is an idea the user hardens — settled, not to be reopened; locks are what `forged-idea.md` is distilled from. Don't read the memlog back except on resume. If the user raises a different branch, capture it and stay put — the loop and the stray insight both survive.
+
+## The personas
+
+The forge is voiced, not generic — and once the topic is set it always runs with the room, because a branch worked by two sharp characters goes deeper and lands harder than a faceless assistant ever could. A persona loaded at activation leads throughout and holds character.
+
+Resolve the pool once, as soon as the goal is known:
+`uv run {skill-root}/scripts/resolve_personas.py --project-root {project-root} --skill {skill-root}`
+It returns the installed BMad roster (`agents`), any custom personas the user authored (`members`), and their saved party groups (`parties` — each with an optional `scene` to play, open-cast rooms flagged) — everything `bmad-party-mode` knows, without invoking it.
+
+From then on, every turn brings two voices to the branch — witnesses you cross-examine, not a panel that debates:
+- **One from the user's pool** — an installed agent or custom persona they'll recognize, whose expertise fits the branch in play. Vary who shows up every few turns to keep the pressure high and the angles fresh; don't let the same voice dominate. If the user calls a specific name, bring them in. If the pool resolves empty (a core-only install with no roster), generate both voices on the fly so every branch still arrives with two.
+- **One you generate on the fly** — a fresh persona the topic conjures (a hostile competitor, a skeptical CFO, a domain specialist, a historical persona or expert), named and characterized so it's unmistakably itself.
+
+They hammer the branch in character; you synthesize their hits into your next question and drive it to a resolved answer. The user steers anytime — name a specific person, call a whole saved party for its scene, or go one-on-one. Voice them yourself by default; spawn separate agents (as `bmad-party-mode` does) only when a branch needs genuinely independent minds — a verdict that shouldn't be colored by one voice speaking for all.
+
+## Exits
+
+The session ends however the thinking lands, and every landing is a real outcome:
+
+- **Hardened** — the idea survived. Distill the memlog into `{workspace}/forged-idea.md`: super succinct — the locked items and what was killed and why, in the user's meaning. Not a prose retelling, not a template, not the conversation replayed — the load-bearing residue, nothing else. If it reads like a document, it's too long. Note it can feed `bmad-spec`, `bmad-prd`, or `bmad-prfaq`.
+- **Killed** — the idea did not survive. Say so plainly and record why. Finding this cheaply is a win, not a failure.
+- **Clearer** — the user simply thinks straighter now. The memlog stands on its own; no `forged-idea.md` needed (the report below still renders).
+
+However it lands, render the verdict as a self-contained HTML report the user can open — `{workspace}/forge-report.html`, written every time, no asking. Strike it with a bespoke wax-seal/stamp matched to the outcome: **HARDENED** for a survivor, an **Idea Death Certificate** stamped **KILLED** (with the cause of death) for one that didn't, or a fitting bespoke seal for wherever else it landed (e.g. **CLARIFIED**). Lay out the load-bearing residue — the locked items, what was killed and why, the cracks that held — in the user's meaning, and credit the room: the personas and parties that pressure-tested it, by name, icon, and voice. One nicely-styled page (inline CSS, an inline-SVG seal, light flourish only where it lifts the piece) — a genuine keepsake, not a templated dump. Tell the user the path.
+
+Flip the status at the end: `uv run {project-root}/_bmad/scripts/memlog.py set --workspace {workspace} --key status --value complete`.
+If `{workflow.on_complete}` is non-empty, run all instructions in order.
diff --git a/80_bmad/base/.agents/skills/bmad-forge-idea/customize.toml b/80_bmad/base/.agents/skills/bmad-forge-idea/customize.toml
new file mode 100644
index 0000000..98949e2
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-forge-idea/customize.toml
@@ -0,0 +1,42 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-forge-idea.
+#
+# Override files (not edited here):
+# {project-root}/_bmad/custom/bmad-forge-idea.toml (team)
+# {project-root}/_bmad/custom/bmad-forge-idea.user.toml (personal)
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays: append
+
+# Steps to run before the standard activation (config load, greet).
+activation_steps_prepend = []
+
+# Steps to run after greet but before the session begins.
+activation_steps_append = []
+
+# Persistent facts the interrogator keeps in mind for the whole session
+# (domain constraints, house rules, what's off the table). Each entry is a
+# literal sentence, a skill prefixed with `skill:`, or a `file:`-prefixed
+# path/glob whose contents are loaded as facts. Default loads project-context.md
+# when one exists (e.g. from bmad-generate-project-context), so the forge grounds
+# in the project's tech, domain, and constraints without re-asking.
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Executed when the session completes. Scalar or array of instructions. Empty for none.
+on_complete = []
+
+# Parent folder for all forge sessions. Each session gets its own run
+# folder underneath (see run_folder_pattern). Lands directly under
+# {output_folder} so the forge works in core-only installs.
+forge_output_path = "{output_folder}/forge"
+
+# Run-folder pattern inside forge_output_path. Resolved against the
+# idea-derived slug at activation. Same slug = same folder, so resuming
+# an idea reuses its memlog. Override to add {date} or other components
+# if a fresh dated history per run is preferred.
+run_folder_pattern = "{slug}"
diff --git a/80_bmad/base/.agents/skills/bmad-forge-idea/scripts/resolve_personas.py b/80_bmad/base/.agents/skills/bmad-forge-idea/scripts/resolve_personas.py
new file mode 100644
index 0000000..f1d5d5c
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-forge-idea/scripts/resolve_personas.py
@@ -0,0 +1,270 @@
+#!/usr/bin/env python3
+# /// script
+# requires-python = ">=3.11"
+# ///
+"""Resolve the personas and parties the forge can bring into the room.
+
+The forge cross-examines witnesses: the installed BMAD agents, plus any
+custom personas and party groups the user has authored for `bmad-party-mode`.
+This surfaces all of them in one shot so the orchestrator never has to ask
+"who's available?" — it just intermixes whoever fits the branch, alongside
+any persona the user names on the fly.
+
+What it returns (JSON, stdout):
+ * agents — the installed BMAD roster: the default room, always present.
+ * members — extra custom personas in the pool (party_members the user
+ defined that aren't already an installed slot).
+ * parties — the user's named party groups, members resolved to brief
+ entries; open-cast groups (scene names a pool, no roster)
+ are flagged.
+ * default_party — the group id pinned as party-mode's default, if any.
+
+Discovery is best-effort and never blocks the forge. The installed roster
+comes from the core resolver; custom personas/parties come from
+`bmad-party-mode`'s resolved customization when that skill is found beside
+this one, else from the user's override TOMLs read directly. Anything that
+can't be resolved is simply omitted and flagged, never fatal.
+
+Stdlib only (Python 3.11+ for tomllib).
+
+ resolve_personas.py --project-root P --skill S
+"""
+
+import argparse
+import json
+import subprocess
+import sys
+from pathlib import Path
+
+try:
+ import tomllib
+except ImportError: # pragma: no cover - guarded for <3.11
+ sys.stderr.write("error: Python 3.11+ is required (stdlib `tomllib`).\n")
+ sys.exit(3)
+
+PARTY_SKILL = "bmad-party-mode"
+
+
+def _run_json(cmd):
+ """Run a resolver script and parse its JSON stdout. None on any failure."""
+ try:
+ out = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
+ except (OSError, subprocess.SubprocessError):
+ return None
+ if out.returncode != 0 or not out.stdout.strip():
+ return None
+ try:
+ return json.loads(out.stdout)
+ except json.JSONDecodeError:
+ return None
+
+
+def _load_toml(path: Path):
+ if not path.exists():
+ return {}
+ try:
+ with path.open("rb") as f:
+ data = tomllib.load(f)
+ return data if isinstance(data, dict) else {}
+ except (OSError, tomllib.TOMLDecodeError):
+ return {}
+
+
+def load_agents(project_root: Path):
+ """Installed BMAD agents as {code: entry}. (dict, resolved_ok).
+
+ The core resolver may emit agents as a dict keyed by code or as an array
+ of tables (depending on how the layers merged); normalize both to a dict.
+ """
+ script = project_root / "_bmad" / "scripts" / "resolve_config.py"
+ data = _run_json([sys.executable, str(script), "--project-root", str(project_root), "--key", "agents"])
+ if data is None:
+ return {}, False
+ agents = data.get("agents", {}) or {}
+ if isinstance(agents, list):
+ agents = {a["code"]: a for a in agents if isinstance(a, dict) and a.get("code")}
+ elif not isinstance(agents, dict):
+ agents = {}
+ return agents, True
+
+
+def find_party_skill(project_root: Path, skill_root: Path):
+ """Locate the installed bmad-party-mode skill dir, or None.
+
+ Skills install as siblings, so the party skill is almost always next to
+ this one. A couple of common install roots cover the rest.
+ """
+ candidates = [
+ skill_root.parent / PARTY_SKILL,
+ project_root / ".claude" / "skills" / PARTY_SKILL,
+ project_root / "_bmad" / "skills" / PARTY_SKILL,
+ ]
+ for c in candidates:
+ if (c / "customize.toml").exists():
+ return c
+ return None
+
+
+def load_party_workflow(project_root: Path, party_skill: Path):
+ """Merged [workflow] table for bmad-party-mode (base + user overrides)."""
+ resolver = project_root / "_bmad" / "scripts" / "resolve_customization.py"
+ data = _run_json([sys.executable, str(resolver), "--skill", str(party_skill), "--key", "workflow"])
+ if data is not None and isinstance(data.get("workflow"), dict):
+ return data["workflow"]
+ # Fallback: base customize.toml directly, no override merge.
+ wf = _load_toml(party_skill / "customize.toml").get("workflow", {})
+ return wf if isinstance(wf, dict) else {}
+
+
+def load_party_overrides(project_root: Path):
+ """Custom personas/parties when party-mode itself isn't installed.
+
+ Reads only the user's override TOMLs (team then personal, personal wins on
+ scalars). No base roster exists in this path, so a shallow merge is enough.
+ """
+ custom = project_root / "_bmad" / "custom"
+ team = _load_toml(custom / f"{PARTY_SKILL}.toml").get("workflow", {})
+ user = _load_toml(custom / f"{PARTY_SKILL}.user.toml").get("workflow", {})
+ team = team if isinstance(team, dict) else {}
+ user = user if isinstance(user, dict) else {}
+ merged = dict(team)
+ for key, val in user.items():
+ if isinstance(val, list) and isinstance(merged.get(key), list):
+ merged[key] = merged[key] + val
+ else:
+ merged[key] = val
+ return merged
+
+
+def _alias(code: str) -> str:
+ """Short alias for an installed agent code: bmad-agent-analyst -> analyst."""
+ for prefix in ("bmad-agent-", "bmad-"):
+ if code.startswith(prefix):
+ return code[len(prefix):]
+ return code
+
+
+def build_pool(agents: dict, party_members: list):
+ """One pool keyed by code; custom members override matching installed slots.
+
+ Returns (pool, index, installed_codes, custom_codes):
+ * installed_codes — the default room (installed agents, overrides applied
+ in place); custom-only additions stay in the pool but don't crowd it.
+ * custom_codes — pure-custom personas (no installed slot), the extra
+ faces the forge can summon by name or via a party group.
+ """
+ pool, index, installed_codes, custom_codes = {}, {}, [], []
+
+ def register(code, entry):
+ pool[code] = entry
+ index[code] = code
+ index[code.lower()] = code
+ index[_alias(code).lower()] = code
+ name = entry.get("name")
+ if name:
+ key = name.lower()
+ # A custom rename must not hijack another agent's name lookup.
+ if index.get(key, code) == code:
+ index[key] = code
+
+ for code, info in (agents or {}).items():
+ register(code, {
+ "code": code,
+ "name": info.get("name", code),
+ "icon": info.get("icon", ""),
+ "title": info.get("title", ""),
+ "description": info.get("description", ""),
+ "source": "installed",
+ })
+ installed_codes.append(code)
+
+ for m in (party_members if isinstance(party_members, list) else []):
+ if not isinstance(m, dict):
+ continue
+ code = m.get("code")
+ if not code:
+ continue
+ canonical = index.get(code) or index.get(code.lower()) or code
+ was_installed = canonical in pool
+ entry = {"code": canonical, "source": "custom"}
+ for field in ("name", "icon", "title", "persona", "capabilities", "model"):
+ if m.get(field) is not None:
+ entry[field] = m[field]
+ entry.setdefault("name", canonical)
+ register(canonical, entry)
+ if not was_installed:
+ custom_codes.append(canonical)
+
+ return pool, index, installed_codes, custom_codes
+
+
+def _brief(entry):
+ """The slim card the orchestrator needs to cast a persona."""
+ out = {k: entry[k] for k in ("code", "name", "icon", "title", "source") if entry.get(k)}
+ for k in ("description", "persona", "capabilities", "model"):
+ if entry.get(k):
+ out[k] = entry[k]
+ return out
+
+
+def resolve_parties(groups, pool, index):
+ out = []
+ for g in groups or []:
+ if not isinstance(g, dict) or not g.get("id"):
+ continue
+ raw = g.get("members", []) or []
+ members = []
+ for t in raw:
+ key = t if isinstance(t, str) else str(t)
+ code = index.get(key) or index.get(key.lower())
+ if code in pool:
+ members.append(_brief(pool[code]))
+ party = {"id": g["id"], "name": g.get("name", g["id"]), "members": members}
+ if g.get("scene"):
+ party["scene"] = g["scene"]
+ if not raw:
+ party["open_cast"] = True
+ out.append(party)
+ return out
+
+
+def main():
+ ap = argparse.ArgumentParser(description="Resolve forge personas and parties.")
+ ap.add_argument("--project-root", required=True)
+ ap.add_argument("--skill", required=True, help="Path to the bmad-forge-idea skill dir")
+ args = ap.parse_args()
+
+ project_root = Path(args.project_root).resolve()
+ skill_root = Path(args.skill).resolve()
+
+ agents, agents_ok = load_agents(project_root)
+
+ party_skill = find_party_skill(project_root, skill_root)
+ if party_skill is not None:
+ workflow = load_party_workflow(project_root, party_skill)
+ else:
+ workflow = load_party_overrides(project_root)
+
+ pool, index, installed_codes, custom_codes = build_pool(
+ agents, workflow.get("party_members", []))
+ parties = resolve_parties(workflow.get("party_groups", []), pool, index)
+
+ _emit({
+ "agents": [_brief(pool[c]) for c in installed_codes],
+ "members": [_brief(pool[c]) for c in custom_codes],
+ "parties": parties,
+ "default_party": workflow.get("default_party", "") or "",
+ "party_mode_found": party_skill is not None,
+ "agents_resolved": agents_ok,
+ })
+
+
+def _emit(obj):
+ reconfigure = getattr(sys.stdout, "reconfigure", None)
+ if reconfigure is not None:
+ reconfigure(encoding="utf-8")
+ sys.stdout.write(json.dumps(obj, indent=2, ensure_ascii=False) + "\n")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/80_bmad/base/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py b/80_bmad/base/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py
new file mode 100644
index 0000000..4867b0d
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python3
+# /// script
+# requires-python = ">=3.11"
+# ///
+"""Unit tests for resolve_personas.py — pool merge, alias, party resolution."""
+
+import sys
+import unittest
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
+import resolve_personas as rp # noqa: E402
+
+AGENTS = {
+ "bmad-agent-analyst": {"name": "Mary", "icon": "📊", "title": "Analyst"},
+ "bmad-agent-pm": {"name": "John", "icon": "📋", "title": "PM"},
+}
+
+
+class TestAlias(unittest.TestCase):
+ def test_strips_known_prefixes(self):
+ self.assertEqual(rp._alias("bmad-agent-analyst"), "analyst")
+ self.assertEqual(rp._alias("bmad-foo"), "foo")
+
+ def test_passes_through_unprefixed(self):
+ self.assertEqual(rp._alias("morpheus"), "morpheus")
+
+
+class TestBuildPool(unittest.TestCase):
+ def test_installed_become_default_room_indexed_every_way(self):
+ pool, idx, installed, custom = rp.build_pool(AGENTS, [])
+ self.assertEqual(installed, ["bmad-agent-analyst", "bmad-agent-pm"])
+ self.assertEqual(custom, [])
+ self.assertEqual(idx["analyst"], "bmad-agent-analyst") # alias
+ self.assertEqual(idx["mary"], "bmad-agent-analyst") # name (ci)
+ self.assertEqual(pool["bmad-agent-analyst"]["source"], "installed")
+
+ def test_pure_custom_member_stays_out_of_default_room(self):
+ pool, _, installed, custom = rp.build_pool(
+ AGENTS, [{"code": "morpheus", "name": "Morpheus", "persona": "riddles"}])
+ self.assertEqual(custom, ["morpheus"])
+ self.assertNotIn("morpheus", installed)
+ self.assertEqual(pool["morpheus"]["persona"], "riddles")
+
+ def test_custom_override_lands_on_installed_slot_not_a_new_face(self):
+ pool, _, installed, custom = rp.build_pool(
+ AGENTS, [{"code": "analyst", "name": "Mary-Custom", "persona": "p"}])
+ self.assertNotIn("analyst", pool)
+ self.assertEqual(custom, []) # an override is not a new face
+ self.assertEqual(pool["bmad-agent-analyst"]["source"], "custom")
+ self.assertEqual(pool["bmad-agent-analyst"]["name"], "Mary-Custom")
+
+ def test_member_without_code_skipped(self):
+ pool, _, _, custom = rp.build_pool(AGENTS, [{"name": "Nameless"}])
+ self.assertEqual(custom, [])
+ self.assertEqual(set(pool), {"bmad-agent-analyst", "bmad-agent-pm"})
+
+ def test_custom_rename_does_not_hijack_another_agents_name(self):
+ # Override the analyst slot, renaming it to "John" — the PM's name.
+ # The PM's name lookup must survive (last-writer-wins would corrupt it).
+ _, idx, _, _ = rp.build_pool(AGENTS, [{"code": "analyst", "name": "John"}])
+ self.assertEqual(idx["john"], "bmad-agent-pm")
+
+ def test_brief_carries_model_and_capabilities(self):
+ pool, _, _, _ = rp.build_pool(
+ AGENTS, [{"code": "neo", "name": "Neo", "model": "opus", "capabilities": ["x"]}])
+ brief = rp._brief(pool["neo"])
+ self.assertEqual(brief["model"], "opus")
+ self.assertEqual(brief["capabilities"], ["x"])
+
+ def test_non_list_party_members_is_safe(self):
+ pool, _, installed, custom = rp.build_pool(AGENTS, "not-a-list")
+ self.assertEqual(custom, [])
+ self.assertEqual(set(pool), {"bmad-agent-analyst", "bmad-agent-pm"})
+
+
+class TestResolveParties(unittest.TestCase):
+ def setUp(self):
+ self.pool, self.idx, _, _ = rp.build_pool(
+ AGENTS, [{"code": "shark", "name": "Marcus", "title": "CFO"}])
+
+ def test_resolves_members_by_alias_and_custom_code(self):
+ parties = rp.resolve_parties(
+ [{"id": "tank", "name": "Tank", "scene": "hostile",
+ "members": ["shark", "analyst"]}], self.pool, self.idx)
+ self.assertEqual(len(parties), 1)
+ self.assertEqual([m["name"] for m in parties[0]["members"]], ["Marcus", "Mary"])
+ self.assertEqual(parties[0]["scene"], "hostile")
+
+ def test_unknown_member_dropped_silently(self):
+ parties = rp.resolve_parties(
+ [{"id": "g", "members": ["analyst", "ghost"]}], self.pool, self.idx)
+ self.assertEqual([m["name"] for m in parties[0]["members"]], ["Mary"])
+
+ def test_member_resolution_is_case_insensitive(self):
+ # A TOML author naturally writes "Analyst"/"Shark"; the filter accepts
+ # them via the lowercase index, so resolution must too (no KeyError).
+ parties = rp.resolve_parties(
+ [{"id": "g", "members": ["Analyst", "Shark"]}], self.pool, self.idx)
+ self.assertEqual([m["name"] for m in parties[0]["members"]], ["Mary", "Marcus"])
+
+ def test_non_string_member_does_not_crash(self):
+ # Malformed members (int, list) must drop silently, never raise.
+ parties = rp.resolve_parties(
+ [{"id": "g", "members": [123, ["x"], "analyst"]}], self.pool, self.idx)
+ self.assertEqual([m["name"] for m in parties[0]["members"]], ["Mary"])
+
+ def test_open_cast_group_flagged(self):
+ parties = rp.resolve_parties(
+ [{"id": "rebels", "name": "Rebels", "scene": "the Ghost"}], self.pool, self.idx)
+ self.assertTrue(parties[0]["open_cast"])
+ self.assertEqual(parties[0]["members"], [])
+
+ def test_group_without_id_skipped(self):
+ self.assertEqual(rp.resolve_parties([{"name": "no id"}], self.pool, self.idx), [])
+
+
+class TestOverrideMergeFallback(unittest.TestCase):
+ """When party-mode isn't installed, user override TOMLs are read directly."""
+
+ def test_arrays_append_scalars_override(self):
+ import tempfile, os
+ with tempfile.TemporaryDirectory() as d:
+ custom = Path(d) / "_bmad" / "custom"
+ custom.mkdir(parents=True)
+ (custom / "bmad-party-mode.toml").write_text(
+ '[workflow]\ndefault_party = "a"\n'
+ '[[workflow.party_members]]\ncode = "x"\nname = "X"\n')
+ (custom / "bmad-party-mode.user.toml").write_text(
+ '[workflow]\ndefault_party = "b"\n'
+ '[[workflow.party_members]]\ncode = "y"\nname = "Y"\n')
+ wf = rp.load_party_overrides(Path(d))
+ self.assertEqual(wf["default_party"], "b") # personal wins
+ self.assertEqual([m["code"] for m in wf["party_members"]], ["x", "y"]) # appended
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/80_bmad/base/.agents/skills/bmad-generate-project-context/SKILL.md b/80_bmad/base/.agents/skills/bmad-generate-project-context/SKILL.md
new file mode 100644
index 0000000..b452de5
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-generate-project-context/SKILL.md
@@ -0,0 +1,81 @@
+---
+name: bmad-generate-project-context
+description: 'Create project-context.md with AI rules. Use when the user says "generate project context" or "create project context"'
+---
+
+# Generate Project Context Workflow
+
+**Goal:** Create a concise, optimized `project-context.md` file containing critical rules, patterns, and guidelines that AI agents must follow when implementing code. This file focuses on unobvious details that LLMs need to be reminded of.
+
+**Your Role:** You are a technical facilitator working with a peer to capture the essential implementation rules that will ensure consistent, high-quality code generation across all AI agents working on the project.
+
+## Conventions
+
+- Bare paths (e.g. `steps/step-01-discover.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## WORKFLOW ARCHITECTURE
+
+This uses **micro-file architecture** for disciplined execution:
+
+- Each step is a self-contained file with embedded rules
+- Sequential progression with user control at each step
+- Document state tracked in frontmatter
+- Focus on lean, LLM-optimized content generation
+- You NEVER proceed to a step file if the current step file indicates the user must approve and indicate continuation.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+- Use `{user_name}` for greeting
+- Use `{communication_language}` for all communications
+- Use `{document_output_language}` for output documents
+- Use `{planning_artifacts}` for output location and artifact scanning
+- Use `{project_knowledge}` for additional context scanning
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Paths
+
+- `output_file` = `{output_folder}/project-context.md`
+
+## Execution
+
+- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
+- ✅ YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`
+
+Load and execute `./steps/step-01-discover.md` to begin the workflow.
+
+**Note:** Input document discovery and initialization protocols are handled in step-01-discover.md.
diff --git a/80_bmad/base/.agents/skills/bmad-generate-project-context/customize.toml b/80_bmad/base/.agents/skills/bmad-generate-project-context/customize.toml
new file mode 100644
index 0000000..8fd3291
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-generate-project-context/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-generate-project-context. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All artifacts must follow org naming conventions."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches Step 3 (Context Completion & Finalization),
+# after the project-context.md file is optimized and saved. Override wins.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/project-context-template.md b/80_bmad/base/.agents/skills/bmad-generate-project-context/project-context-template.md
similarity index 100%
rename from 80_bmad/base/_bmad/bmm/workflows/generate-project-context/project-context-template.md
rename to 80_bmad/base/.agents/skills/bmad-generate-project-context/project-context-template.md
diff --git a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-01-discover.md b/80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-01-discover.md
similarity index 96%
rename from 80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-01-discover.md
rename to 80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-01-discover.md
index 16f95e1..7c69b7e 100644
--- a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-01-discover.md
+++ b/80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-01-discover.md
@@ -123,7 +123,7 @@ Based on discovery, create or update the context document:
#### A. Fresh Document Setup (if no existing context)
-Copy template from `{installed_path}/project-context-template.md` to `{output_folder}/project-context.md`
+Copy template from `../project-context-template.md` to `{output_folder}/project-context.md`
Initialize frontmatter fields.
#### B. Existing Document Update
@@ -160,6 +160,8 @@ Ready to create/update your project context. This will help AI agents implement
[C] Continue to context generation"
+**HALT — wait for user selection before proceeding.**
+
## SUCCESS METRICS:
✅ Existing project context properly detected and handled
@@ -179,6 +181,6 @@ Ready to create/update your project context. This will help AI agents implement
## NEXT STEP:
-After user selects [C] to continue, load `{project-root}/_bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md` to collaboratively generate the specific project context rules.
+After user selects [C] to continue, load `./step-02-generate.md` to collaboratively generate the specific project context rules.
Remember: Do NOT proceed to step-02 until user explicitly selects [C] from the menu and discovery is confirmed and the initial file has been written as directed in this discovery step!
diff --git a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md b/80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-02-generate.md
similarity index 94%
rename from 80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md
rename to 80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-02-generate.md
index dcb2f00..2bc33c8 100644
--- a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md
+++ b/80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-02-generate.md
@@ -9,6 +9,7 @@
- 🎯 KEEP CONTENT LEAN - optimize for LLM context efficiency
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
+- ✅ YOU MUST ALWAYS WRITE all artifact and document content in `{document_output_language}`
## EXECUTION PROTOCOLS:
@@ -29,8 +30,8 @@ This step will generate content and present choices for each rule category:
## PROTOCOL INTEGRATION:
-- When 'A' selected: Execute {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml
-- When 'P' selected: Execute {project-root}/_bmad/core/workflows/party-mode
+- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
+- When 'P' selected: Invoke the `bmad-party-mode` skill
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
- User accepts/rejects protocol changes before proceeding
@@ -263,11 +264,13 @@ After each category, show the generated rules and present choices:
[P] Party Mode - Review from different implementation perspectives
[C] Continue - Save these rules and move to next category"
+**HALT — wait for user selection before proceeding.**
+
### 10. Handle Menu Selection
#### If 'A' (Advanced Elicitation):
-- Execute advanced-elicitation.xml with current category rules
+- Invoke the `bmad-advanced-elicitation` skill with current category rules
- Process enhanced rules that come back
- Ask user: "Accept these enhanced rules for {{category}}? (y/n)"
- If yes: Update content, then return to A/P/C menu
@@ -275,7 +278,7 @@ After each category, show the generated rules and present choices:
#### If 'P' (Party Mode):
-- Execute party-mode workflow with category rules context
+- Invoke the `bmad-party-mode` skill with category rules context
- Process collaborative insights on implementation patterns
- Ask user: "Accept these changes to {{category}} rules? (y/n)"
- If yes: Update content, then return to A/P/C menu
@@ -313,6 +316,6 @@ When user selects 'C' for a category, append the content directly to `{output_fo
## NEXT STEP:
-After completing all rule categories and user selects 'C' for the final category, load `{project-root}/_bmad/bmm/workflows/generate-project-context/steps/step-03-complete.md` to finalize the project context file.
+After completing all rule categories and user selects 'C' for the final category, load `./step-03-complete.md` to finalize the project context file.
Remember: Do NOT proceed to step-03 until all categories are complete and user explicitly selects 'C' for each!
diff --git a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-03-complete.md b/80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-03-complete.md
similarity index 97%
rename from 80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-03-complete.md
rename to 80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-03-complete.md
index 85dd4db..c739843 100644
--- a/80_bmad/base/_bmad/bmm/workflows/generate-project-context/steps/step-03-complete.md
+++ b/80_bmad/base/.agents/skills/bmad-generate-project-context/steps/step-03-complete.md
@@ -276,3 +276,9 @@ Your project context will help ensure high-quality, consistent implementation ac
This is the final step of the Generate Project Context workflow. The user now has a comprehensive, optimized project context file that will ensure consistent, high-quality implementation across all AI agents working on the project.
The project context file serves as the critical "rules of the road" that agents need to implement code consistently with the project's standards and patterns.
+
+## On Complete
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
+
+If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
diff --git a/80_bmad/base/.agents/skills/bmad-help/SKILL.md b/80_bmad/base/.agents/skills/bmad-help/SKILL.md
index 984227d..ffa392e 100644
--- a/80_bmad/base/.agents/skills/bmad-help/SKILL.md
+++ b/80_bmad/base/.agents/skills/bmad-help/SKILL.md
@@ -1,10 +1,75 @@
---
name: bmad-help
-description: Execute help
+description: 'Analyzes current state and user query to answer BMad questions or recommend the next skill(s) to use. Use when user asks for help, bmad help, what to do next, or what to start with in BMad.'
---
-# help
+# BMad Help
-Read the entire task file at: {project-root}/_bmad/core/tasks/help.md
+## Purpose
-Follow all instructions in the task file exactly as written.
+Help the user understand where they are in their BMad workflow and what to do next, and also answer broader questions when asked that could be augmented with remote sources such as module documentation sources.
+
+## Desired Outcomes
+
+When this skill completes, the user should:
+
+1. **Know where they are** — which module and phase they're in, what's already been completed
+2. **Know what to do next** — the next recommended and/or required step, with clear reasoning
+3. **Know how to invoke it** — skill name, menu code, action context, and any args that shortcut the conversation
+4. **Get offered a quick start** — when a single skill is the clear next step, offer to run it for the user right now rather than just listing it
+5. **Feel oriented, not overwhelmed** — surface only what's relevant to their current position; don't dump the entire catalog
+6. **Get answers to general questions** — when the question doesn't map to a specific skill, use the module's registered documentation to give a grounded answer
+
+## Data Sources
+
+- **Catalog**: `{project-root}/_bmad/_config/bmad-help.csv` — assembled manifest of all installed module skills
+- **Config**: `config.yaml` and `user-config.yaml` files in `{project-root}/_bmad/` and its subfolders — resolve `output-location` variables, provide `communication_language` and `project_knowledge`
+- **Artifacts**: Files matching `outputs` patterns at resolved `output-location` paths reveal which steps are possibly completed; their content may also provide grounding context for recommendations
+- **Project knowledge**: If `project_knowledge` resolves to an existing path, read it for grounding context. Never fabricate project-specific details.
+- **Module docs**: Rows with `_meta` in the `skill` column carry a URL or path in `output-location` pointing to the module's documentation (e.g., llms.txt). Fetch and use these to answer general questions about that module.
+
+## CSV Interpretation
+
+The catalog uses this format:
+
+```
+module,skill,display-name,menu-code,description,action,args,phase,preceded-by,followed-by,required,output-location,outputs
+```
+
+**Phases** determine the high-level flow:
+- `anytime` — available regardless of workflow state
+- Numbered phases (`1-analysis`, `2-planning`, etc.) flow in order; naming varies by module
+
+**Sequencing** determines recommended ordering within and across phases (these are soft suggestions, not hard gates — see `required` for gating):
+- `preceded-by` — skills that should ideally complete before this one
+- `followed-by` — skills that should ideally run after this one
+- Format: `skill-name` for single-action skills, `skill-name:action` for multi-action skills
+
+**Required gates**:
+- `required=true` items must complete before the user can meaningfully proceed to later phases
+- A phase with no required items is entirely optional — recommend it but be clear about what's actually required next
+
+**Completion detection**:
+- Search resolved output paths for `outputs` patterns
+- Fuzzy-match found files to catalog rows
+- User may also state completion explicitly, or it may be evident from the current conversation
+
+**Descriptions carry routing context** — some contain cycle info and alternate paths (e.g., "back to DS if fixes needed"). Read them as navigation hints, not just display text.
+
+## Response Format
+
+For each recommended item, present:
+- `[menu-code]` **Display name** — e.g., "[PR] PRD"
+- Skill name in backticks — e.g., `bmad-prd`
+- For multi-action skills: action invocation context — e.g., "tech-writer lets create a mermaid diagram!"
+- Description if present in CSV; otherwise your existing knowledge of the skill suffices
+- Args if available
+
+**Ordering**: Show optional items first, then the next required item. Make it clear which is which.
+
+## Constraints
+
+- Present all output in `{communication_language}`
+- Recommend running each skill in a **fresh context window**
+- Match the user's tone — conversational when they're casual, structured when they want specifics
+- If the active module is ambiguous, retrieve all meta rows remote sources to find relevant info also to help answer their question
diff --git a/80_bmad/base/.agents/skills/bmad-index-docs/SKILL.md b/80_bmad/base/.agents/skills/bmad-index-docs/SKILL.md
index 718460c..c92935b 100644
--- a/80_bmad/base/.agents/skills/bmad-index-docs/SKILL.md
+++ b/80_bmad/base/.agents/skills/bmad-index-docs/SKILL.md
@@ -1,10 +1,66 @@
---
name: bmad-index-docs
-description: Execute index-docs
+description: 'Generates or updates an index.md to reference all docs in the folder. Use if user requests to create or update an index of all files in a specific folder'
---
-# index-docs
+# Index Docs
-Read the entire task file at: {project-root}/_bmad/core/tasks/index-docs.xml
+**Goal:** Generate or update an index.md to reference all docs in a target folder.
-Follow all instructions in the task file exactly as written.
+
+## EXECUTION
+
+### Step 1: Scan Directory
+
+- List all files and subdirectories in the target location
+
+### Step 2: Group Content
+
+- Organize files by type, purpose, or subdirectory
+
+### Step 3: Generate Descriptions
+
+- Read each file to understand its actual purpose and create brief (3-10 word) descriptions based on the content, not just the filename
+
+### Step 4: Create/Update Index
+
+- Write or update index.md with organized file listings
+
+
+## OUTPUT FORMAT
+
+```markdown
+# Directory Index
+
+## Files
+
+- **[filename.ext](./filename.ext)** - Brief description
+- **[another-file.ext](./another-file.ext)** - Brief description
+
+## Subdirectories
+
+### subfolder/
+
+- **[file1.ext](./subfolder/file1.ext)** - Brief description
+- **[file2.ext](./subfolder/file2.ext)** - Brief description
+
+### another-folder/
+
+- **[file3.ext](./another-folder/file3.ext)** - Brief description
+```
+
+
+## HALT CONDITIONS
+
+- HALT if target directory does not exist or is inaccessible
+- HALT if user does not have write permissions to create index.md
+
+
+## VALIDATION
+
+- Use relative paths starting with ./
+- Group similar files together
+- Read file contents to generate accurate descriptions - don't guess from filenames
+- Keep descriptions concise but informative (3-10 words)
+- Sort alphabetically within groups
+- Skip hidden files (starting with .) unless specified
diff --git a/80_bmad/base/.agents/skills/bmad-investigate/SKILL.md b/80_bmad/base/.agents/skills/bmad-investigate/SKILL.md
new file mode 100644
index 0000000..50e4619
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-investigate/SKILL.md
@@ -0,0 +1,196 @@
+---
+name: bmad-investigate
+description: Forensic case investigation with evidence-graded findings, calibrated to the input. Use when the user asks to investigate a bug, trace what caused an incident, walk through unfamiliar code, or build a mental model of a code area before working on it.
+---
+
+# Investigate
+
+## Overview
+
+Reconstruct what's happening, or what an unfamiliar area does, from the available evidence. Produce a structured case
+file another engineer can pick up cold. Calibrate continuously between defect-chasing (symptom-driven) and
+area-exploration (no symptom); the same discipline applies on both ends.
+
+**Args:** A ticket ID, log file path, diagnostic archive, error message, code area name, problem description, or a path
+to an existing case file. The last form resumes a prior investigation; everything else opens a new case.
+
+**Output:** `{implementation_artifacts}/{workflow.case_file_subdir}/{workflow.case_file_filename}`. Reference inputs
+are recorded; raw content is not read into the parent context until an outcome calls for it.
+
+`{slug}` is the ticket ID when one is provided, otherwise a short descriptive name agreed with the user, sanitized to
+lowercase alphanumeric with hyphens. On collision with an existing case file at the resolved path, ask whether to
+rename to `slug-YYYY-MM-DD.md` or resume the existing file (resuming routes to Outcome 0).
+
+After every outcome, present what was learned and pause for the user before continuing.
+
+## Principles
+
+- **Evidence grading.**
+ - **Confirmed.** Directly observed; cite `path:line`, log timestamp, or commit hash.
+ - **Deduced.** Logically follows from Confirmed evidence; show the chain.
+ - **Hypothesized.** Plausible but unconfirmed; state what would confirm or refute it.
+- **Stronghold first.** Anchor in one Confirmed piece of evidence and expand outward. Never start from a theory and
+ hunt for support. When evidence is sparse, switch to evidence-light mode (Outcome 1 branch).
+- **Challenge the premise.** The user's description is a hypothesis, not a fact. Verify independently; if evidence
+ contradicts, say so.
+- **Follow the evidence, not the narrative.** When evidence contradicts the working theory, update the theory — never
+ the other way around. Resist confirmation bias even when the user is convinced.
+- **Hypotheses are never deleted.** Update Status (Open / Confirmed / Refuted) and add a Resolution. Wrong turns are
+ part of the deliverable.
+- **Missing evidence is itself a finding.** Document the gap, what it would resolve, and how to obtain it.
+- **Write it down early.** Initialize the case file as soon as the slug is agreed; it is the persistent state across
+ interruptions.
+- **Path:line citations** use CWD-relative format, no leading `/`, so they're clickable in IDE-embedded terminals.
+- **Delegation discipline.** When a step requires reading 5+ files or any file >10K tokens, delegate to a subagent
+ that returns structured JSON only. Cite `path:line` from the result; don't re-read in the parent.
+- **Issue independent operations in parallel** (multi-grep, multi-read, parallel inventories) — one message, multiple
+ tool calls.
+- **Communication.** Evidence-first language ("the evidence shows", "unconfirmed, requires X to verify"). No hedging,
+ no narrative.
+
+## On Activation
+
+### Step 1: Resolve the workflow block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+If the script fails, stop and surface the error.
+
+### Step 2: Execute prepend steps
+
+Run each entry in `{workflow.activation_steps_prepend}` in order.
+
+### Step 3: Load persistent facts
+
+Treat each entry in `{workflow.persistent_facts}` as foundational context. `file:` prefixes are paths or globs under
+`{project-root}` (load contents); other entries are facts verbatim.
+
+### Step 4: Load config
+
+Load `{project-root}/_bmad/bmm/config.yaml` and resolve `{user_name}`, `{communication_language}`,
+`{document_output_language}`, `{implementation_artifacts}`, `{project_knowledge}`. If `{implementation_artifacts}` is
+unresolved, fall back to `./investigations/` and surface the fallback before initializing.
+
+### Step 5: Greet
+
+Greet `{user_name}` in `{communication_language}`.
+
+### Step 6: Execute append steps
+
+Run each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+### Step 7: Acknowledge and route
+
+Acknowledge the input as a reference (record paths and IDs; don't read raw content). Path to an existing case file →
+Outcome 0. Otherwise → Outcome 1.
+
+## Procedure
+
+### Outcome 0: Existing case is loaded and surfaced
+
+Read the case file. Surface, in order: open hypotheses (Status = Open) with their confirm/refute criteria; open
+backlog (Status ≠ Done); missing-evidence rows; last Conclusion with confidence. Ask which thread to pull. New
+evidence opens a new `## Follow-up: {YYYY-MM-DD}` block (append `#2`, `#3` on same-day reentry). Pause for user with the recap above; wait for direction.
+
+### Outcome 1: Scope and stronghold are established
+
+Acknowledge each input shape — record location, scope, time window only; bulk reads happen in Outcome 2.
+
+- **Issue tracker ticket.** Fetch full details via available MCP tools.
+- **Diagnostic archive.** Record path, file count, time window.
+- **Log file or stack trace.** Record path and time window; only the stack frame already in the user's message is in
+ scope here.
+- **Free-text description.** Capture verbatim; treat as hypothesis.
+- **Code area name** (no symptom). Record entry point.
+- **Recent commit area.** Record commit range.
+
+If the user arrived with a hypothesis, register it as Hypothesis #1. Find the stronghold *independently*; the user's
+hypothesis is one of the things the stronghold validates or refutes.
+
+Find a stronghold: a Confirmed piece of evidence (error message, function name, HTTP route, config parameter, test
+case). Anchor here.
+
+**Initialize `{case_file}` before branching.** The path is
+`{implementation_artifacts}/{workflow.case_file_subdir}/{workflow.case_file_filename}` with `{slug}` substituted (slug
+and collision rules in Overview). Create the file from `{workflow.case_file_template}` and fill Hand-off Brief
+(rough), Case Info, Problem Statement, initial Evidence Inventory.
+
+**Evidence-light branch.** When no Confirmed evidence is reachable: mark the case evidence-light in the Hand-off
+Brief; populate the Investigation Backlog with prioritized data-collection items; record "to make progress, I need one
+of: …"; pause for the user to provide evidence or authorize Outcome 2 to scan more broadly.
+
+Otherwise present scope, stronghold, file path, proposed approach. Pause for user with the recap above; wait for direction.
+
+### Outcome 2: Evidence perimeter is mapped
+
+Survey the scene: inventory available evidence in parallel across these independent categories: diagnostic archives;
+issue tracker; version control; test results; static analysis; source code. For any category exceeding ~10K tokens,
+delegate to a subagent that returns a JSON manifest (paths, sizes, time windows, key fragments cited as `path:line`).
+
+Classify each Available, Partial, or Missing — Missing is itself a finding. Update Evidence Inventory and Investigation
+Backlog. Pause for user with the recap above; wait for direction.
+
+### Outcome 3: Cause is reasoned about with discipline
+
+- **Trace causality.** Symptom-driven: trace backward from the symptom to producing conditions and the state that
+ emerged. Exploration: trace backward from outputs (returns, side effects, messages sent) to producing conditions.
+ Same technique, different anchor.
+- **Reconstruct the timeline** by cross-referencing logs, system events, version control, user observations.
+- **Form and test hypotheses.** State, identify confirming/refuting evidence, search, grade
+ (Confirmed / Refuted / Open). Update Status. Never delete.
+- **Refutation pass.** Each time a hypothesis transitions toward Confirmed, actively look for refuting evidence first.
+ Record the attempt in Resolution.
+- **Verify the user's premise.** If evidence contradicts, say so explicitly.
+- **Add discovered paths to the backlog.** Stay focused on the current thread.
+
+Update Confirmed Findings, Deduced Conclusions, Hypothesized Paths, Backlog, Timeline. Highlight contradictions to the
+original premise. Pause for user with the recap above; wait for direction.
+
+### Outcome 4: Source has been traced where it matters
+
+Issue these first-pass scans as parallel tool calls in one message: grep for exact error strings; glob the affected
+directory for parallel implementations; `git log` for recent changes.
+
+Then sequentially: read the surrounding code; follow the caller chain; watch for language and process boundary
+crossings (compiled→scripts, IPC, host→device, configuration flow).
+
+Lean by case type:
+
+- **Exploration:** I/O mapping (triggers, outputs, dependencies); frequent-terms scan; control-flow filtering
+ (branches, loops, error handling, state-machine transitions).
+- **Symptom-driven:** depth assessment — is the root cause reachable from local context, or is a broader area model
+ required? Surface escalations; never silently expand scope. Trivial-fix assessment — off-by-one, missing null check,
+ swapped argument → one-line code suggestion or draft diff in the report; non-trivial → stop at the root cause area.
+
+Investigation stops at the diagnosis; implementation is out of scope. Update Source Code Trace (Error origin, Trigger,
+Condition, Related files; area model when broader). Pause for user with the recap above; wait for direction.
+
+### Outcome 5: Report is finalized and the hand-off is clean
+
+Update `{case_file}`:
+
+- **Hand-off Brief** rewritten to final form (3 sentences, 15-second read).
+- **Final Conclusion** with confidence: **High** (Confirmed root cause, deterministic repro), **Medium** (Deduced;
+ minor uncertainty), **Low** (Hypothesized; clear data gap).
+- **Fix direction** when applicable (categorize by mechanism if multiple combine).
+- **Diagnostic steps** if uncertainty remains.
+- **Reproduction Plan** when applicable, or a verification plan for exploration cases.
+- **Status:** Active / Concluded / Blocked on evidence.
+
+Present the conclusion, then a concrete next-steps menu: trivial fix → `bmad-quick-dev`; scope/plan adjustment →
+`bmad-correct-course`; tracked story → `bmad-create-story`; fresh review → `bmad-code-review`. Recommend the
+highest-value action. Mitigations and workarounds are generated only on explicit request — investigation stops at the
+diagnosis. Execute `{workflow.on_complete}` if non-empty. Pause for user with the recap above; wait for direction.
+
+## Follow-up Iterations
+
+Continue work by appending to `{case_file}` under a new `## Follow-up: {YYYY-MM-DD}` block (`#2`, `#3` on same-day
+reentry). The investigation is complete when:
+
+- Root cause is Confirmed.
+- Root cause is Hypothesized with a clear data gap.
+- The mental model is sufficient for the user's stated goal (exploration cases).
+- The backlog contains only items requiring unavailable evidence.
+- The user explicitly concludes.
diff --git a/80_bmad/base/.agents/skills/bmad-investigate/customize.toml b/80_bmad/base/.agents/skills/bmad-investigate/customize.toml
new file mode 100644
index 0000000..341084d
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-investigate/customize.toml
@@ -0,0 +1,62 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-investigate. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run.
+# Use for citation conventions (path:line vs path#L42), grading-scale
+# overrides (ITIL severity 1-5 instead of High/Medium/Low), tone
+# directives (engineering vs exec-facing), or compliance constraints
+# the case file must respect.
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "Use ITIL severity 1-5 instead of High/Medium/Low for confidence."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: path to the case-file template, resolved from the skill root.
+# Override to point at an org-shaped template (compliance sections,
+# SLA fields, post-mortem hooks, ITIL fields).
+
+case_file_template = "references/case-file-template.md"
+
+# Scalar: subdirectory under {implementation_artifacts} where case files land.
+# Override for org taxonomies (forensics/, cases/, incidents/, bug-bash/).
+
+case_file_subdir = "investigations"
+
+# Scalar: filename pattern for new case files. {slug} expands to the
+# ticket ID or a short user-agreed name.
+
+case_file_filename = "{slug}-investigation.md"
+
+# Scalar: executed when the workflow finalizes the case file at Outcome 5,
+# after the conclusion is presented. Override wins. Use for post-case
+# automation: post the case to Slack/Teams, push fields back to ticketing,
+# link the case to a sprint, trigger a follow-up retro.
+# Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-investigate/references/case-file-template.md b/80_bmad/base/.agents/skills/bmad-investigate/references/case-file-template.md
new file mode 100644
index 0000000..145fdfd
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-investigate/references/case-file-template.md
@@ -0,0 +1,127 @@
+# Investigation: {title}
+
+## Hand-off Brief
+
+1. **What happened.** {one-sentence problem statement, evidence-graded}
+2. **Where the case stands.** {status, last finding, what would unblock progress}
+3. **What's needed next.** {single recommended action with rationale}
+
+## Case Info
+
+| Field | Value |
+| ---------------- | -------------------------------------------------------------------------- |
+| Ticket | {ticket-id or "N/A"} |
+| Date opened | {date} |
+| Status | Active |
+| System | {OS, version, relevant environment details} |
+| Evidence sources | {diagnostic archive, logs, crash dump, code, version control, etc.} |
+
+## Problem Statement
+
+{User-reported description; the initial claim. May be refined or contradicted by evidence.}
+
+## Evidence Inventory
+
+| Source | Status | Notes |
+| -------- | ------------------------------- | --------- |
+| {source} | {Available / Partial / Missing} | {details} |
+
+## Investigation Backlog
+
+| # | Path to Explore | Priority | Status | Notes |
+| - | --------------- | --------------------- | ------------------------------------- | --------- |
+| 1 | {description} | {High / Medium / Low} | {Open / In Progress / Done / Blocked} | {context} |
+
+## Timeline of Events
+
+| Time | Event | Source | Confidence |
+| ----------- | ------------------- | --------------------- | --------------------- |
+| {timestamp} | {event description} | {log file, commit, …} | {Confirmed / Deduced} |
+
+## Confirmed Findings
+
+### Finding 1: {title}
+
+**Evidence:** {citation — `path:line`, log timestamp, or commit hash}
+
+**Detail:** {description}
+
+## Deduced Conclusions
+
+### Deduction 1: {title}
+
+**Based on:** {which Confirmed Findings}
+
+**Reasoning:** {logical chain}
+
+**Conclusion:** {what follows}
+
+## Hypothesized Paths
+
+### Hypothesis 1: {title}
+
+**Status:** {Open / Confirmed / Refuted}
+
+**Theory:** {description}
+
+**Supporting indicators:** {what makes this plausible}
+
+**Would confirm:** {specific evidence that would prove this}
+
+**Would refute:** {specific evidence that would disprove this}
+
+**Resolution:** {when Status changes from Open, what evidence settled it}
+
+## Missing Evidence
+
+| Gap | Impact | How to Obtain |
+| ---------------- | ------------------------------------ | --------------- |
+| {what's missing} | {what it would confirm or eliminate} | {how to get it} |
+
+## Source Code Trace
+
+| Element | Detail |
+| ------------- | ------------------------------------------- |
+| Error origin | {file:line, function name} |
+| Trigger | {what causes this code to execute} |
+| Condition | {what state produces the observed behavior} |
+| Related files | {other files in the same code path} |
+
+## Conclusion
+
+**Confidence:** {High / Medium / Low}
+
+{Summary stating what is Confirmed vs. what remains Hypothesized. If a root cause is identified, state it; otherwise
+name the most promising hypothesized paths and what would resolve the remaining uncertainty.}
+
+## Recommended Next Steps
+
+### Fix direction
+
+{What needs to change and why. Categorize by mechanism when multiple issues combine.}
+
+### Diagnostic
+
+{Steps to confirm the root cause: additional logging, targeted tests, data to collect.}
+
+## Reproduction Plan
+
+{Setup, trigger, expected results. Scale from isolated proof to full system reproduction.}
+
+## Side Findings
+
+Tangential observations surfaced during the investigation, evidence-graded, with citation when applicable.
+
+- {observation}
+
+## Follow-up: {date}
+
+### New Evidence
+
+### Additional Findings
+
+### Updated Hypotheses
+
+### Backlog Changes
+
+### Updated Conclusion
diff --git a/80_bmad/base/.agents/skills/bmad-market-research/SKILL.md b/80_bmad/base/.agents/skills/bmad-market-research/SKILL.md
new file mode 100644
index 0000000..29fefa4
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-market-research/SKILL.md
@@ -0,0 +1,96 @@
+---
+name: bmad-market-research
+description: 'Conduct market research on competition and customers. Use when the user says they need market research'
+---
+
+# Market Research Workflow
+
+**Goal:** Conduct comprehensive market research using current web data and verified sources to produce complete research documents with compelling narratives and proper citations.
+
+**Your Role:** You are a market research facilitator working with an expert partner. This is a collaboration where you bring research methodology and web search capabilities, while your partner brings domain knowledge and research direction.
+
+## Conventions
+
+- Bare paths (e.g. `steps/step-01-init.md`) resolve from the skill root.
+- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
+- `{project-root}`-prefixed paths resolve from the project working directory.
+- `{skill-name}` resolves to the skill directory's basename.
+
+## PREREQUISITE
+
+**⛔ Web search required.** If unavailable, abort and tell the user.
+
+## On Activation
+
+### Step 1: Resolve the Workflow Block
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
+
+**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
+
+1. `{skill-root}/customize.toml` — defaults
+2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
+3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
+
+Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
+
+### Step 2: Execute Prepend Steps
+
+Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
+
+### Step 3: Load Persistent Facts
+
+Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
+
+### Step 4: Load Config
+
+Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
+- Use `{user_name}` for greeting
+- Use `{communication_language}` for all communications
+- Use `{document_output_language}` for output documents
+- Use `{planning_artifacts}` for output location and artifact scanning
+- Use `{project_knowledge}` for additional context scanning
+
+### Step 5: Greet the User
+
+Greet `{user_name}`, speaking in `{communication_language}`.
+
+### Step 6: Execute Append Steps
+
+Execute each entry in `{workflow.activation_steps_append}` in order.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## QUICK TOPIC DISCOVERY
+
+"Welcome {{user_name}}! Let's get started with your **market research**.
+
+**What topic, problem, or area do you want to research?**
+
+For example:
+- 'The electric vehicle market in Europe'
+- 'Plant-based food alternatives market'
+- 'Mobile payment solutions in Southeast Asia'
+- 'Or anything else you have in mind...'"
+
+### Topic Clarification
+
+Based on the user's topic, briefly clarify:
+1. **Core Topic**: "What exactly about [topic] are you most interested in?"
+2. **Research Goals**: "What do you hope to achieve with this research?"
+3. **Scope**: "Should we focus broadly or dive deep into specific aspects?"
+
+## ROUTE TO MARKET RESEARCH STEPS
+
+After gathering the topic and goals:
+
+1. Set `research_type = "market"`
+2. Set `research_topic = [discovered topic from discussion]`
+3. Set `research_goals = [discovered goals from discussion]`
+4. Derive `research_topic_slug` from `{{research_topic}}`: lowercase, trim, replace whitespace with `-`, strip path separators (`/`, `\`), `..`, and any character that is not alphanumeric, `-`, or `_`. Collapse repeated `-` and strip leading/trailing `-`. If the result is empty, use `untitled`.
+5. Create the starter output file: `{planning_artifacts}/research/market-{{research_topic_slug}}-research-{{date}}.md` with exact copy of the `./research.template.md` contents
+6. Load: `./steps/step-01-init.md` with topic context
+
+**Note:** The discovered topic from the discussion should be passed to the initialization step, so it doesn't need to ask "What do you want to research?" again - it can focus on refining the scope for market research.
+
+**✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`**
diff --git a/80_bmad/base/.agents/skills/bmad-market-research/customize.toml b/80_bmad/base/.agents/skills/bmad-market-research/customize.toml
new file mode 100644
index 0000000..0fa8447
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-market-research/customize.toml
@@ -0,0 +1,41 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-market-research. Mirrors the
+# agent customization shape under the [workflow] namespace.
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
+# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
+
+# Steps to run before the standard activation (config load, greet).
+# Overrides append. Use for pre-flight loads, compliance checks, etc.
+
+activation_steps_prepend = []
+
+# Steps to run after greet but before the workflow begins.
+# Overrides append. Use for context-heavy setup that should happen
+# once the user has been acknowledged.
+
+activation_steps_append = []
+
+# Persistent facts the workflow keeps in mind for the whole run
+# (standards, compliance constraints, stylistic guardrails).
+# Distinct from the runtime memory sidecar — these are static context
+# loaded on activation. Overrides append.
+#
+# Each entry is either:
+# - a literal sentence, e.g. "All briefs must include a regulatory-risk section."
+# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
+# (glob patterns are supported; the file's contents are loaded and treated as facts).
+
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Scalar: executed when the workflow reaches its terminal stage (Step 6: Research Completion),
+# after the market research document has been saved and the user selects [C] Complete.
+# Override wins. Leave empty for no custom post-completion behavior.
+
+on_complete = ""
diff --git a/80_bmad/base/.agents/skills/bmad-market-research/research.template.md b/80_bmad/base/.agents/skills/bmad-market-research/research.template.md
new file mode 100644
index 0000000..1d99524
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-market-research/research.template.md
@@ -0,0 +1,29 @@
+---
+stepsCompleted: []
+inputDocuments: []
+workflowType: 'research'
+lastStep: 1
+research_type: '{{research_type}}'
+research_topic: '{{research_topic}}'
+research_goals: '{{research_goals}}'
+user_name: '{{user_name}}'
+date: '{{date}}'
+web_research_enabled: true
+source_verification: true
+---
+
+# Research Report: {{research_type}}
+
+**Date:** {{date}}
+**Author:** {{user_name}}
+**Research Type:** {{research_type}}
+
+---
+
+## Research Overview
+
+[Research overview and methodology will be appended here]
+
+---
+
+
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-01-init.md
similarity index 94%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md
rename to 80_bmad/base/.agents/skills/bmad-market-research/steps/step-01-init.md
index ba7563b..4cf6276 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md
+++ b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-01-init.md
@@ -132,13 +132,15 @@ Show initial scope document and present continue option:
[C] Continue - Confirm scope and proceed to customer insights analysis
[Modify] Suggest changes to research scope before proceeding
+**HALT — wait for user response before proceeding.**
+
### 5. Handle User Response
#### If 'C' (Continue):
- Update frontmatter: `stepsCompleted: [1]`
- Add confirmation note to document: "Scope confirmed by user on {{date}}"
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md`
+- Load: `./step-02-customer-behavior.md`
#### If 'Modify':
@@ -177,6 +179,6 @@ This step ensures:
## NEXT STEP:
-After user confirmation and scope finalization, load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md` to begin detailed market research with customer insights analysis.
+After user confirmation and scope finalization, load `./step-02-customer-behavior.md` to begin detailed market research with customer insights analysis.
Remember: Init steps confirm understanding and scope, not generate research content!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-02-customer-behavior.md
similarity index 96%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md
rename to 80_bmad/base/.agents/skills/bmad-market-research/steps/step-02-customer-behavior.md
index e5315e3..810e22d 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md
+++ b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-02-customer-behavior.md
@@ -173,13 +173,15 @@ _Source: [URL]_
**Ready to proceed to customer pain points?**
[C] Continue - Save this to document and proceed to pain points analysis
+**HALT — wait for user response before proceeding.**
+
### 6. Handle Continue Selection
#### If 'C' (Continue):
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md`
+- Load: `./step-03-customer-pain-points.md`
## APPEND TO DOCUMENT:
@@ -232,6 +234,6 @@ Content is already written to document when generated in step 4. No additional a
## NEXT STEP:
-After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md` to analyze customer pain points, challenges, and unmet needs for {{research_topic}}.
+After user selects 'C', load `./step-03-customer-pain-points.md` to analyze customer pain points, challenges, and unmet needs for {{research_topic}}.
Remember: Always write research content to document immediately and emphasize current customer data with rigorous source verification!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-03-customer-pain-points.md
similarity index 96%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md
rename to 80_bmad/base/.agents/skills/bmad-market-research/steps/step-03-customer-pain-points.md
index d740ae5..280730c 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md
+++ b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-03-customer-pain-points.md
@@ -184,13 +184,15 @@ _Source: [URL]_
**Ready to proceed to customer decision processes?**
[C] Continue - Save this to document and proceed to decision processes analysis
+**HALT — wait for user response before proceeding.**
+
### 6. Handle Continue Selection
#### If 'C' (Continue):
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2, 3]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md`
+- Load: `./step-04-customer-decisions.md`
## APPEND TO DOCUMENT:
@@ -244,6 +246,6 @@ Content is already written to document when generated in step 4. No additional a
## NEXT STEP:
-After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md` to analyze customer decision processes, journey mapping, and decision factors for {{research_topic}}.
+After user selects 'C', load `./step-04-customer-decisions.md` to analyze customer decision processes, journey mapping, and decision factors for {{research_topic}}.
Remember: Always write research content to document immediately and emphasize current customer pain points data with rigorous source verification!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-04-customer-decisions.md
similarity index 96%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md
rename to 80_bmad/base/.agents/skills/bmad-market-research/steps/step-04-customer-decisions.md
index 0f94f53..4f0e550 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md
+++ b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-04-customer-decisions.md
@@ -194,13 +194,15 @@ _Source: [URL]_
**Ready to proceed to competitive analysis?**
[C] Continue - Save this to document and proceed to competitive analysis
+**HALT — wait for user response before proceeding.**
+
### 6. Handle Continue Selection
#### If 'C' (Continue):
- **CONTENT ALREADY WRITTEN TO DOCUMENT**
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4]`
-- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md`
+- Load: `./step-05-competitive-analysis.md`
## APPEND TO DOCUMENT:
@@ -254,6 +256,6 @@ Content is already written to document when generated in step 4. No additional a
## NEXT STEP:
-After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md` to analyze competitive landscape, market positioning, and competitive strategies for {{research_topic}}.
+After user selects 'C', load `./step-05-competitive-analysis.md` to analyze competitive landscape, market positioning, and competitive strategies for {{research_topic}}.
Remember: Always write research content to document immediately and emphasize current customer decision data with rigorous source verification!
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-05-competitive-analysis.md
similarity index 91%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md
rename to 80_bmad/base/.agents/skills/bmad-market-research/steps/step-05-competitive-analysis.md
index d7387a4..868b124 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md
+++ b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-05-competitive-analysis.md
@@ -109,15 +109,17 @@ Show the generated competitive analysis and present complete option:
- Competitive threats and challenges documented
**Ready to complete the market research?**
-[C] Complete Research - Save final document and conclude
+[C] Complete Research - Save competitive analysis and proceed to research completion
+
+**HALT — wait for user response before proceeding.**
### 4. Handle Complete Selection
#### If 'C' (Complete Research):
- Append the final content to the research document
-- Update frontmatter: `stepsCompleted: [1, 2, 3]`
-- Complete the market research workflow
+- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]`
+- Load: `./step-06-research-completion.md`
## APPEND TO DOCUMENT:
@@ -166,12 +168,6 @@ When 'C' is selected:
- Market research workflow status updated
- Final recommendations provided to user
-## NEXT STEPS:
+## NEXT STEP:
-Market research workflow complete. User may:
-
-- Use market research to inform product development strategies
-- Conduct additional competitive research on specific companies
-- Combine market research with other research types for comprehensive insights
-
-Congratulations on completing comprehensive market research! 🎉
+After user selects 'C', load `./step-06-research-completion.md` to produce the final comprehensive market research document with strategic synthesis, executive summary, and complete document structure.
diff --git a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-06-research-completion.md
similarity index 98%
rename from 80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md
rename to 80_bmad/base/.agents/skills/bmad-market-research/steps/step-06-research-completion.md
index 0073b55..4878764 100644
--- a/80_bmad/base/_bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md
+++ b/80_bmad/base/.agents/skills/bmad-market-research/steps/step-06-research-completion.md
@@ -385,6 +385,8 @@ _This comprehensive market research document serves as an authoritative market r
**Ready to complete this comprehensive market research document?**
[C] Complete Research - Save final comprehensive market research document
+**HALT — wait for user response before proceeding.**
+
### 6. Handle Complete Selection
#### If 'C' (Complete Research):
@@ -473,4 +475,10 @@ Comprehensive market research workflow complete. User may:
- Combine market research with other research types for comprehensive insights
- Move forward with implementation based on strategic market recommendations
+## On Complete
+
+Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
+
+If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
+
Congratulations on completing comprehensive market research with professional documentation! 🎉
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/SKILL.md b/80_bmad/base/.agents/skills/bmad-party-mode/SKILL.md
index d4424ed..e1cf3c5 100644
--- a/80_bmad/base/.agents/skills/bmad-party-mode/SKILL.md
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/SKILL.md
@@ -1,6 +1,58 @@
---
name: bmad-party-mode
-description: Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations. Use when user requests party mode.
+description: 'Orchestrates lively group discussions between installed BMAD agents or custom personas, and helps author custom parties. Use when the user requests party mode, a roundtable, or multiple agent perspectives — or wants to create/configure a party, define personas, or build an AI focus-group panel.'
---
-IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL {project-root}/_bmad/core/workflows/party-mode/workflow.md, READ its entire contents and follow its directions exactly!
+# Party Mode
+
+Run a round-table where these agents talk to each other and to the user like real, distinct people in conversation. You're the orchestrator.
+
+## Conventions
+
+- **Paths:** bare paths (e.g. `references/create-party.md`) resolve from `{skill-root}` (where `customize.toml` lives); `{project-root}`-prefixed paths from the project working dir. `{workflow.}` resolves to `customize.toml`'s `[workflow]` table (overrides win).
+- **Scripts** (run via `uv run`): `{project-root}/_bmad/scripts/resolve_customization.py` resolves `{workflow.*}`; `{skill-root}/scripts/resolve_party.py` resolves the roster, `party_mode`, `memory_enabled`, and scene/`open_cast`; `{project-root}/_bmad/scripts/memlog.py` reads/writes per-party memory.
+- **File roles:** a party's memory is the per-party memlog at `{workflow.memory_dir}//.memlog.md`; custom members and groups live in the user's `customize.toml` overrides. Mechanics in `references/party-memory.md` (memory) and `references/create-party.md` (authoring).
+- **Search:** Web-search, don't guess — anything past your cutoff or unfamiliar; subagents too.
+
+## On Activation
+
+1. **Resolve customization:** `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults. Then run each `{workflow.activation_steps_prepend}` entry, and hold each `{workflow.persistent_facts}` entry as session-long context (`file:`-prefixed = paths/globs whose contents load as facts; `skill:`-prefixed = a skill to consult; others = literal facts).
+2. Load `{project-root}/_bmad/core/config.yaml`: greet with `{user_name}`, speak in `{communication_language}`, and resolve `{output_folder}` and `{date}`.
+3. **Detect intent and route.** If they want to create or configure a saved party setup (invent a cast, add a persona, distill customer data into a focus-group panel, set a default, or edit an existing custom party), load `references/create-party.md` and follow it. Otherwise run a party — continue below.
+4. **Resolve the roster:** `uv run {skill-root}/scripts/resolve_party.py --project-root {project-root} --skill {skill-root}`. It returns the active roster (`{workflow.default_party}` group if set, else the installed agents), the other group names, `party_mode`, `memory_enabled`, and any scene/`open_cast`. Apply them: `open` already in the scene and let it shape how the room behaves; cast `open_cast` rooms on the fly (whoever fits the moment, varying as the topic shifts); if `installed_agents_resolved` is false or codes come back `unresolved`, tell the user, carry on with what returned, and improvise. Overrides: an inline-named cast IS the roster for the session (conjure them, go straight in); `--party ` (alias `--group `) overrides the configured `default_party` (unknown id -> show the available names and ask); `--list-groups` for just the menu. Mid-session the same levers apply: switch rooms by re-running `resolve_party.py --party ` and carrying the thread over, or summon any collective member by name.
+5. **Memory.** If `memory_enabled` (from `resolve_party.py`), follow `references/party-memory.md` for the whole run.
+6. **Welcome the user:** show who's in the room (icon, name, one-line role); note other groups can be switched to. Then ask what they want to get into, unless it's already obvious from how the skill was launched.
+7. Run each `{workflow.activation_steps_append}` entry; if either hook list was non-empty, confirm every entry ran before continuing.
+
+## Keep It Feeling Like a Party
+
+This is the bar — strive for every one of these, every round. It's the difference between a party and a panel:
+
+- **It reads like people talking, not a report.** Short turns, real reactions, banter, momentum — a group chat, not a stack of memos. Brevity by default: a persona goes long only when asked. The instant it reads like answers being filed, the party's dead.
+- **Every voice is unmistakably itself.** Diction, humor, pet peeves, ethos, embedded capabilities — hide the labels and you'd still know who's speaking. Voices are unequal and idiosyncratic: someone dominates, someone keeps dragging it back to their pet topic. Vary who's in the spotlight round to round. A balanced panel is boring.
+- **They clash, and you don't resolve it.** Challenge, push back hard, get heated when it's warranted; alliances and factions form. Your instinct is to reconcile the voices and tie a bow — resist it. Clean consensus that took no effort is where the party dies.
+- **One exchange, woven — never softened.** Present a single conversation — turns as `{icon} **{name}:**`, back to back — not a row of answers. Add staging and connective tissue, but never change what a persona argued, and never paraphrase their speech in third person; let them say it. Weave the delivery, keep the substance.
+- **Pull the user into the room.** Characters talk *to* them (and each other) — challenge, tease, put a question back. They're a guest who got pulled into the argument, not someone running a panel from outside.
+- **Make the collision earn its keep.** Push the voices until their clash surfaces an angle no single one of them (or you) would've reached alone. That's the whole point of more than one mind in the room.
+- **Let a history form.** Grudges, alliances, a running bit, a callback to three turns back — let the relationships accrue so these people feel like they're becoming something across the session, not resetting each turn.
+- **Commit to the fiction.** The scene and each persona are binding — play the staging, the characters, and the world around the table (stage business, a non-verbal beat, an event that lands mid-sentence) exactly as written, and carry both into any spawned brief. Never break the fourth wall about the mechanism (no "you have 4 agents in the room"). Lean into the world when it heightens the moment; stay out when the scene is just a room.
+- **When it sags, change something — don't force it.** A flat turn? Move on, don't retry it. Drifting into Q&A or going in circles? Bring in a new voice, crack a joke, name the impasse, or ask where they want to take it. Never work in a summary or takeaways — they're there if the user asks.
+
+## How It Runs
+
+Use `{workflow.party_mode}` for the session unless the user passed `--mode ` (the older `--subagents` means `subagent`) — runtime intent always wins. One mode is active at a time; if its mechanism isn't available in your harness, fall back to `session` without comment.
+
+- **`session`** — voice every persona inline, one mind behind every voice. The floor every other mode degrades to; needs no extra instructions.
+- **`auto`** — voice inline for ordinary back-and-forth, spawn real agents only when independent thinking changes the outcome. Load `references/mode-auto.md` for that call; when it says to spawn, follow `references/mode-subagent.md`.
+- **`subagent`** — spawn a real agent per substantive round so each persona thinks independently. Load `references/mode-subagent.md`, favor faster cheaper models if available for each subagent.
+- **`agent-team`** — stand the personas up as a persistent team who address each other directly (Claude Code only). Load `references/mode-agent-team.md`.
+
+## Wrapping Up
+
+When the user signals done (read the room — don't wait for a magic word):
+
+- Read back the best takeaways.
+- If memory is on, top up the memlog with the final outcome and any memorable beat not yet captured (`references/party-memory.md`) — a top-up; memory accrued live.
+- Offer a keepsake: a single self-contained very creative HTML of the session, laid out by persona (icons, names, voice), genuinely nice remembrance, with inline SVG/light animation where it lifts the piece — written as a `{date}`-stamped `.html` into `{workflow.output_dir}/`, or wherever they ask.
+- If memory is on and new faces showed up who aren't in the party's roster (open-cast walk-ons, or members the user added on the fly), offer once to save them into the users party customization - if yes then follow the instruction in `references/create-party.md` (declinable; don't stall the close).
+- Run `{workflow.on_complete}` if non-empty, then drop back to normal mode.
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/customize.toml b/80_bmad/base/.agents/skills/bmad-party-mode/customize.toml
new file mode 100644
index 0000000..f98e87c
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/customize.toml
@@ -0,0 +1,175 @@
+# DO NOT EDIT -- overwritten on every update.
+#
+# Workflow customization surface for bmad-party-mode.
+#
+# Override files (not edited here):
+# {project-root}/_bmad/custom/bmad-party-mode.toml (team)
+# {project-root}/_bmad/custom/bmad-party-mode.user.toml (personal)
+
+[workflow]
+
+# --- Configurable below. Overrides merge per BMad structural rules: ---
+# scalars: override wins • plain arrays: append
+# arrays of tables keyed by `code`/`id`: matching key replaces, new keys append
+
+# Steps to run before the standard activation (config load, greet).
+# Use for pre-flight loads, compliance checks, etc.
+activation_steps_prepend = []
+
+# Steps to run after greet but before the room comes alive.
+activation_steps_append = []
+
+# Persistent facts the orchestrator keeps in mind for the whole session
+# (house rules, running gags, topics to avoid). Each entry is a literal
+# sentence, a `skill:`-prefixed reference, or a `file:`-prefixed path/glob whose
+# contents load as facts. Default picks up project-context.md if one exists.
+persistent_facts = [
+ "file:{project-root}/**/project-context.md",
+]
+
+# Which party loads when the user just says "party mode" with no override.
+# Empty = the installed BMAD agents — exactly the default behavior of a plain
+# install. Custom members defined below join the POOL (usable in groups, and
+# summonable by name) but do NOT crowd this default room. Set this to a
+# `party_groups` id to pin a curated room as the default instead. A runtime
+# `--party ` always wins.
+#
+# Example (set in team/user override TOML): default_party = "writers-room"
+default_party = ""
+
+# How the room is run — who does the talking. A runtime `--mode ` wins for
+# the session; an unsupported mode (e.g. agent-team outside Claude Code) falls back
+# to "session". SKILL.md "How It Runs" is the authority on what each mode does.
+# "session" (default) never spawn — one mind voices every persona inline
+# "auto" voice inline for light rounds, spawn subagents when independent thinking matters
+# "subagent" spawn a real subagent per substantive round, so each persona thinks independently
+# "agent-team" persistent agent team addressing each other directly (Claude Code only)
+party_mode = "session"
+
+# Where the optional end-of-session keepsake is written. The self-contained HTML
+# document lands in `{output_dir}/`. `{output_folder}` and `{date}` come from core
+# config; point this elsewhere in your team/user override to redirect keepsakes.
+output_dir = "{output_folder}/party-mode"
+
+# Memory for the DEFAULT room (the installed-agent party). When on, the room
+# keeps a succinct, append-only memlog (the memlog standard) that it reads on
+# entry and writes through the session, so the next time opens remembering the
+# last — dynamics carried forward, memorable moments, organic callbacks, where
+# things landed. It is memory, not a transcript. Set false to turn the default
+# room's memory off. NAMED groups do NOT follow this flag: each carries its own
+# `memory = true|false` (see party_groups below). Ad-hoc inline casts are always
+# ephemeral until saved as a party.
+party_memory = true
+
+# Root for the per-party memlogs. Each party stores at
+# `{memory_dir}//.memlog.md`, where `` is the group id (or
+# `installed` for the default room). `{output_folder}` comes from core config;
+# point this elsewhere in your team/user override to relocate memory.
+memory_dir = "{output_folder}/party-mode/memories"
+
+# Executed when the party wraps (after the read-back, before dropping to normal
+# mode). String scalar = one instruction; array = instructions run in order.
+on_complete = ""
+
+# ---------------------------------------------------------------------------
+# Custom party members — personas, added to the POOL alongside the installed
+# agents. The default room stays installed-only; a custom member shows up when a
+# group uses them or you summon one by name. Keyed by `code`: an override entry
+# with a matching code replaces the base one (retune a shipped member), a new
+# code appends. Fields:
+# code short unique handle, used in party_groups and to summon them
+# name display name
+# icon single emoji shown on their turns
+# title one-line role/identity
+# persona voice, humor, ethos, pet peeves, how they argue — the meat;
+# what makes them unmistakably themselves
+# capabilities (optional) what they can do when spawned as a real subagent;
+# woven into their spawn prompt as guidance, not a hard tool grant
+# model (optional) model to use when this member is spawned
+#
+# The members below ship the "Code Review Crew" (see the party_groups section).
+# They cost nothing until summoned — the default room never includes them.
+# ---------------------------------------------------------------------------
+
+[[workflow.party_members]]
+code = "sec-hawk"
+name = "Vex"
+icon = "🔒"
+title = "Security Engineer"
+persona = "Threat-models everything. Hunts injection, broken authz, leaked secrets, SSRF, supply-chain risk. Assumes every input is hostile and every dependency compromised until proven otherwise. Names the exploit path concretely — 'here's how I'd own this box' — never hand-waves 'might be insecure.'"
+capabilities = "Reads the code and traces data flow from untrusted input to sink before judging."
+
+[[workflow.party_members]]
+code = "adversary"
+name = "Grumbal"
+icon = "😤"
+title = "The Adversary"
+persona = "Assumes the code is broken and his job is to prove it. Grumpy, blunt, zero praise sandwiches. Starts from 'this will page someone at 3am' and works backward to the line that does it. Allergic to optimism and 'should be fine.'"
+
+[[workflow.party_members]]
+code = "edge-hunter"
+name = "Boundary"
+icon = "🌶️"
+title = "Edge-Case Hunter"
+persona = "Walks every branch and boundary. Empty input, null, the off-by-one, the huge payload, the concurrent call, the unicode name, the timezone, the retry storm. Method-driven, not mean: 'what happens when this is called twice at once?'"
+
+[[workflow.party_members]]
+code = "craftsman"
+name = "Yui"
+icon = "🎯"
+title = "The Craftsman"
+persona = "Cares about simplicity, naming, and reuse. Allergic to cleverness and duplication. 'You reimplemented something that already exists,' 'this name lies about what it does,' 'three nested abstractions where one would do.' Wants the boring, obvious, maintainable version."
+
+[[workflow.party_members]]
+code = "shipper"
+name = "Dana"
+icon = "🚢"
+title = "The Pragmatist"
+persona = "Counters the perfectionists so the room isn't a pile-on. 'Does this actually matter to a user? Ship the 80%, file the rest.' Pushes back on gold-plating and theoretical risks, forces everyone to rank what's real versus what's a nit."
+
+# ---------------------------------------------------------------------------
+# Named party groups — curated rooms picked at runtime with `--party `
+# (alias `--group `) or switched to mid-session. Keyed by `id`.
+#
+# `members` is a list of codes — installed agent codes, custom member codes, or
+# a mix. Override by `id` to retune a group; new ids append.
+#
+# An optional `scene` sets the stage: a freeform line (or a few) describing the
+# setting, what's happening, how the room behaves, and any in-the-moment
+# character notes — who's had a few, who's hostile to whom, who pressure-tests
+# hardest. The same members can power many scenes; define a member once, then
+# drop them into different rooms. No fixed vocabulary — the model reads it and
+# plays it.
+#
+# `members` is OPTIONAL. Leave it off and the group is open-cast: the `scene`
+# names a pool or universe and the room is cast on the fly — you don't enumerate
+# who shows up; the model picks who fits and can vary them by topic. List a few
+# members AND a scene to anchor some faces while the scene invites others in.
+#
+# `memory = true|false` is per group: true keeps the group's own memlog so it
+# remembers across sessions; false (the default when omitted) starts fresh each
+# time. The create/save/update-party flow asks when you don't say. Faces that
+# show up on the fly in a remembered party can be saved into its roster at the
+# end of a session.
+#
+# More examples to drop into your override TOML:
+# [[workflow.party_groups]] # anchored room with a scene
+# id = "writers-room"
+# name = "The Writers' Room"
+# scene = "Late-night room, everyone a little punchy. Pitch hard, kill darlings faster."
+# members = ["analyst", "tech-writer", "morpheus"]
+# memory = true
+#
+# [[workflow.party_groups]] # open-cast room (no roster; the scene casts it)
+# id = "star-wars-rebels"
+# name = "Star Wars Rebels"
+# scene = "Aboard the Ghost. Figures from the Rebels universe drop in depending on the situation — pick whoever fits the topic, and let the roster shift as the conversation moves."
+# memory = true
+# ---------------------------------------------------------------------------
+
+[[workflow.party_groups]]
+id = "code-review-crew"
+name = "Code Review Crew"
+scene = "Adversarial code review. Each reviewer attacks from their own lens and they argue with each other about what actually matters — security versus shipping, elegance versus pragmatism. No rubber-stamping, no praise sandwiches: surface the real problems before they ship. Point at the line, name the failure mode, and defend it when someone pushes back. Best run with `--mode subagent` so each lens reviews independently before they clash."
+members = ["sec-hawk", "adversary", "edge-hunter", "craftsman", "shipper"]
+memory = false # each review stands on its own; flip to true to remember past reviews
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/references/create-party.md b/80_bmad/base/.agents/skills/bmad-party-mode/references/create-party.md
new file mode 100644
index 0000000..a0f3334
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/references/create-party.md
@@ -0,0 +1,70 @@
+# Creating a Party
+
+A guided authoring flow that turns an idea — a themed cast, a one-off persona, or a pile of raw profile data — into custom party members and groups, written to the user's customize.toml override. The output is configuration; `bmad-customize` does the actual write.
+
+## What you're producing
+
+Sparse `[workflow]` override entries for `bmad-party-mode`:
+
+- `[[workflow.party_members]]` — one per persona: `code`, `name`, `icon`, `title`, `persona`, optional `capabilities`, optional `model`.
+- `[[workflow.party_groups]]` — when the personas form a named room: `id`, `name`, an optional freeform `scene`, `members` (codes), and `memory` (`true`/`false`). `members` is optional: leave it off for an open-cast room whose `scene` names a pool the model casts from on the fly. `memory` is whether the group remembers across sessions; ask the user when they don't say, default `false`.
+- `default_party` — set only if the user wants this group to load by default.
+
+A `scene` is one freeform line (or a few) that sets the stage for a room: the setting, what's happening, how the room behaves, and any in-the-moment character notes — who's three drinks in, who's hostile to whom, who pressure-tests hardest. It's how the same members power many different rooms (a bridge crew on duty vs. the same crew off-duty in the lounge vs. a hostile buyer panel). Define each member once; vary the `scene` per group rather than redefining people. There's no fixed vocabulary — write it plainly and the model plays it.
+
+The `persona` field is the whole game. A flat title produces a flat voice; the detail you elicit is what makes a member unmistakably themselves at the table.
+
+## Find the shape
+
+Open by understanding what they're building. Three common shapes — stay open, anything that yields distinct voices is fair game:
+
+- **A cast** — a themed ensemble ("the Star Trek TOS bridge crew", "a board of famous investors"). Several members plus a group that holds them.
+- **One-offs** — a persona or two added to the collective, no group needed.
+- **Distilled from data** — the user hands you source material (a spreadsheet of customer profiles, survey exports, interview notes) to compress into N stereotypical personas. This is how you stand up an AI focus group for product ideation or feedback.
+- **A panel of lenses** — purpose-built reviewers, each a sharp critical angle (a security engineer, an adversarial skeptic who assumes it's broken, an edge-case hunter, a craftsman who hates cleverness and duplication, a pragmatist who counters perfectionism). The group's `scene` tells them to attack from their lens and argue with each other about what actually matters. A great adversarial-review or red-team room.
+- **Open-cast** — no fixed roster at all. The group's `scene` names a pool or universe ("figures from the Star Wars Rebels universe drop in depending on the situation") and the room is cast on the fly. Leave `members` off; the model already knows the universe and picks who fits the moment. Anchor a face or two by listing them if some should always be present.
+
+Ask which they're after if it isn't obvious, then proceed.
+
+**Persisting a cast already in play.** When you arrive here from a live session — the user spun up an ad-hoc cast inline and wants to keep it — the personas are already drafted and voiced. Don't re-interrogate: capture them as they've been playing, give the group an `id` and name, ask the memory and default questions, and go straight to the write.
+
+## Editing an existing party
+
+When the user wants to change a party that already exists (retune a member's persona, add someone to a group, swap the default), read the current state first so you change rather than clobber: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` returns the merged `party_members`, `party_groups`, and `default_party`. Show the member or group being touched, capture only the delta with the user, and hand that sparse change to `bmad-customize` — it replaces a `party_members`/`party_groups` entry whose `code`/`id` matches and appends the rest, so an edit is just the changed entry, never a full rewrite.
+
+## Keeping new faces from a session
+
+At the end of a remembered party, the room offers to keep the faces that showed up but aren't in its roster — characters cast from an open-cast scene, or members the user added on the fly. They're already drafted and voiced, so don't re-interrogate: capture each as they played (`code`, `name`, `icon`, a one-line `title`, and a `persona` drawn from how they came across), then add them as `party_members`. For a fixed-roster group, also list their codes in the group's `members` so they return as regulars. For an open-cast room, leave `members` empty — listing any member turns the room into a fixed roster and kills its on-the-fly casting; the saved personas now live in the collective, so the scene still names them and they can return without locking the room down. Hand that sparse delta to `bmad-customize` — for a built-in party with no override yet it creates one; for an existing override it merges the new members in.
+
+## Distill from source data (when provided)
+
+When the user points you at data — a file path, a pasted table, exported profiles — read it and compress it into the requested number of representative personas. Cluster by what actually differentiates behavior (goals, budget, pains, adoption posture), not surface demographics alone. Each cluster becomes one persona with a real name and face. Name your reasoning: tell the user which segments you found and which traits drove the split, so they can correct the cut before you flesh the personas out. If they didn't say how many, propose a number from the spread in the data and let them adjust.
+
+For a focus-group panel, independent answers matter more than banter, so offer to set `party_mode` to `subagent` (or remind them `--mode subagent` does it per session) — otherwise one mind voices every customer and they bleed together.
+
+## Flesh out each persona
+
+Draft, don't interrogate. Propose a first cut of each persona and let the user react — far faster than a questionnaire. Push each one until it has a voice you could pick out blind. The dimensions that earn their place:
+
+- **Identity** — name, a one-line title, an emoji that fits.
+- **Voice & ethos** — how they talk, what they value, how they argue, their pet peeves.
+- **Agenda** — what they're really after in any conversation; what they push for.
+- **Quirks** — the specific, human details (a catchphrase, a bias, a blind spot).
+- For focus-group personas, also **likes and dislikes**: what would make them champion or reject an idea, and their relationship to the product space.
+- **Capabilities** (optional) — if this persona should research or read files when spawned, note it; it becomes soft guidance in their spawn prompt.
+
+Keep pushing for specificity. "Skeptical CFO" is a placeholder; "won't approve anything without a payback under 18 months, and says so in the first thirty seconds" is a persona.
+
+## Close it out
+
+- Ask straight: **anything else about this party to specify** before you write it — a house dynamic, a missing voice, a member who should lead.
+- Ask whether **this party should remember across sessions** (unless the user already said). Yes → `memory = true` on the group; no → `memory = false`. One-offs with no group skip this — memory is a group setting.
+- Ask whether **this group should be the default party going forward**. Yes → set `default_party` to the group's id. One-offs with no group can't be a default; skip the ask.
+
+## Write via bmad-customize
+
+**First, check for code collisions.** A custom member whose `code` matches an installed agent silently *overrides* that agent in the collective. Before composing, resolve the collective once — `uv run {skill-root}/scripts/resolve_party.py --project-root {project-root} --skill {skill-root}` — and check each new member's `code` against the returned members. On a collision, surface it ("`analyst` would override the installed Analyst — intended, or pick a different code?") and let the user confirm or rename. One check, not a gate.
+
+Compose the sparse override and hand it to `bmad-customize` to place, confirm, and write — target skill `bmad-party-mode`, `[workflow]` surface. Default to the **user** override (`bmad-party-mode.user.toml`); offer the **team** file when the party is meant to be shared. Hand it the exact entries: the `party_members` tables, any `party_groups` table (including its `memory` flag), and `default_party` if the user opted in. Keep it sparse — only the new entries, never a copy of the base customize.toml. `bmad-customize` shows the TOML, waits for an explicit yes, writes, and verifies the merge; don't write the file yourself.
+
+After it lands, tell the user how to use it: `--party ` to summon the group, or that it's now the default if they set it.
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-agent-team.md b/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-agent-team.md
new file mode 100644
index 0000000..821cd30
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-agent-team.md
@@ -0,0 +1,11 @@
+# Agent-Team Mode
+
+Active when `{workflow.party_mode}` resolves to `agent-team` (or a `--mode agent-team` override). Stand the personas up as a persistent agent team whose members address each other directly, so the back-and-forth happens for real instead of being stitched together after. Claude Code only — if your harness can't stand up a team, fall back to `subagent`, and if that fails too, to `session`.
+
+Your job shifts from weaving to hosting: kick off the topic, keep turns short and in character, pull the thread back when it wanders, and surface the exchange to the user. Voice, brevity, and clash still hold.
+
+In each member's standing brief, carry: their persona; the group's `scene` and any behavioral instructions in the persona as binding direction; their `model` if one is set (a session `--model` pin wins for everyone); and the instruction to check anything that could be stale since the model's training cutoff with web search rather than guessing.
+
+## Model choice
+
+Match the model to the work: something quick for banter, something stronger for deep work. A per-member `model` is used when set; a session `--model ` pin overrides it for everyone.
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-auto.md b/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-auto.md
new file mode 100644
index 0000000..f718221
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-auto.md
@@ -0,0 +1,13 @@
+# Auto Mode
+
+Active when `{workflow.party_mode}` resolves to `auto` (or a `--mode auto` override). The blend: voice the room inline by default — fast and conversational — and spawn real independent agents only for the rounds where independence changes the answer. When you do spawn, follow `references/mode-subagent.md` for the mechanics. If your harness can't spawn agents, auto is just `session`.
+
+## When to spawn vs. voice
+
+Spawn independent agents when divergent, uncolored thinking is the value of the round:
+
+- A genuine evaluation, review, or critique — the kind that fails if one mind voices every side and they drift into agreement (code review, red-team, a hard look at a plan).
+- The personas would plausibly reach *different* conclusions, and that divergence is the point.
+- The user asked someone to dig in, analyze, or research — depth earned by a direct ask.
+
+Voice inline for everything else: banter, reactions, quick takes, the connective back-and-forth that is most of a conversation. When in doubt, voice — spawning is the exception you reach for, not the default.
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-subagent.md b/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-subagent.md
new file mode 100644
index 0000000..b063fb8
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/references/mode-subagent.md
@@ -0,0 +1,19 @@
+# Subagent Mode
+
+Active when `{workflow.party_mode}` resolves to `subagent` (or a `--mode subagent` override). Spawn a real agent for every substantive round, the opening banter included, so each persona thinks independently — not one mind voicing them all. A standing directive: don't relitigate it round to round, and don't fall back to voicing because a moment felt light. If your harness can't spawn agents, fall back to `session`.
+
+## Spawning
+
+Give each agent the objective, their persona, the context, and what the others said if they're reacting. For a custom member, hand them their `persona` as their character and fold their `capabilities` note into the brief; spawn them with their `model` if one is set (a session `--model` pin wins for everyone). Always carry two things into the brief: the group's `scene` and any behavioral instructions in the persona are binding direction, and anything that could be stale since the model's training cutoff should be checked with web search rather than guessed.
+
+Trust their *thinking*: let them decide what to read and how to reach a view; don't script their substance with do-and-don't checklists — that's what produces lifeless blobs. But hold the *form*: a length cap (usually a sentence or three) and the instruction to react to what was just said rather than file a report. Constraining length and stance protects the conversation; constraining their reasoning kills it. Stay in character throughout; a persona goes long only when the user asked it to dig in.
+
+Spawn in parallel for independent first-takes; spawn sequentially when you want them reacting to each other's actual words. Keep it to a few voices a round — more reads as a crowd, not a conversation.
+
+## Weave the replies into one conversation
+
+Each agent saw only the user's message and the context you handed it, so left raw they reply in parallel and never to one another. Reorder turns so a rebuttal lands right after what it rebuts, add the connective phrasing real talk has ("Hold on, Winston, that's backwards", "Sally's right about the API, but she's missing the cost"), and let one persona pick up a thread another dropped. Never change what an agent argued — weave delivery, preserve substance.
+
+## Model choice
+
+Match the model to the round: something quick for banter, something stronger for deep work. A per-member `model` is used when set; a session `--model ` pin overrides it for everyone.
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/references/party-memory.md b/80_bmad/base/.agents/skills/bmad-party-mode/references/party-memory.md
new file mode 100644
index 0000000..78244d2
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/references/party-memory.md
@@ -0,0 +1,51 @@
+# Party Memory
+
+The room remembers its past sessions with this user and brings them back to life — in character. Memory is per-party and append-only.
+
+Memory is on when the active party's `memory_enabled` is true — the default room follows `{workflow.party_memory}`, a named group its own `memory` flag (both resolved by `resolve_party.py`); ad-hoc inline casts have none. Read on entry and on any mid-session room switch; write through the session.
+
+## Where it lives
+
+One memlog per party: `{workflow.memory_dir}/{active}/.memlog.md`, where `{active}` is the key `resolve_party.py` already returned — the group id (e.g. `code-review-crew`), or `installed` for the default room. The folder is named after the party.
+
+## Read it on entry — distill, don't dump
+
+The log is append-only and grows every session, so don't pull the raw file into the party. Hand a reader subagent the memlog path (`{workflow.memory_dir}/{active}/.memlog.md`) and have it return a compact brief — a few hundred tokens of *where things stand now*, ready to play in character.
+
+Then let the brief shape the room from the first beat, **in character**: behavioral state resumes (a cold pair opens cold, an alliance opens warm), threads pick up, callbacks land when they fit — organically, not recited on sight. Never break the fourth wall: the room *remembers*; it never announces it loaded anything, and forces nothing that doesn't fit.
+
+## When to write
+
+- **When a memorable beat lands** — a clash that shifts the room's temperature, an alliance forming, a line worth a future callback, a decision, an outcome.
+- **A floor.** Once a couple of real exchanges are in from the start, even if nothing dramatic happened, capture what it's about and the opening dynamic.
+
+At wrap-up, if the user does signal done, top up with the final outcome and anything memorable not yet captured.
+
+Writes are silent. The room never announces "noted" or "I'll remember".
+
+## What's worth remembering
+
+The test for every entry: *would this color a future session, or make a callback land, or improve the party?* If not, leave it out. A handful of entries, never a recap, never a transcript. keep each entry as brief as possible but usable by future llm.
+
+## New faces
+
+When a character shows up who isn't in the party's roster — cast from an open-cast scene, or one the user adds on the fly — name them in the entry that captures the moment (" turned up and …") so a recurring face can return next session. At wrap-up these are the faces the room offers to keep, saved into the party's roster through `references/create-party.md` (which writes via `bmad-customize`). Until saved they live only in the memlog, and the room re-conjures them from there.
+
+## Write it
+
+```
+uv run {project-root}/_bmad/scripts/memlog.py append \
+ --workspace {workflow.memory_dir}/{active} \
+ --type \
+ --text ""
+```
+
+Add `--by ` when a memory belongs to one character. Choose `init` vs `append` from the existence fact you already hold: the entry-read (and, on a mid-session room switch, that room's read) told you whether the memlog exists — `init --workspace {workflow.memory_dir}/{active}` once before the first append when it doesn't, plain `append` when it does. (`init` errors if the file already exists, so don't call it blind.)
+
+If `memlog.py` is unavailable or a write errors, skip it silently and never stall the party on a failed write.
+
+## Forget
+
+The memlog is append-only by design — no surgical delete. To wipe a party's memory, delete its folder (`{workflow.memory_dir}/{active}/`). To correct a wrong memory, append a new entry that supersedes it; the room reads the latest state.
+
+Keep entries sparse. The distilled read keeps the *room* lean no matter how big the log gets, but the on-disk file still grows append-only.
\ No newline at end of file
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/scripts/resolve_party.py b/80_bmad/base/.agents/skills/bmad-party-mode/scripts/resolve_party.py
new file mode 100644
index 0000000..abee93c
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/scripts/resolve_party.py
@@ -0,0 +1,272 @@
+#!/usr/bin/env python3
+# /// script
+# requires-python = ">=3.11"
+# ///
+"""Resolve the party-mode roster, lazily.
+
+Merges the installed BMAD agents with the user's custom `party_members`
+into one collective, then projects only what the moment needs:
+
+ * default (no flag) — the active roster to load on entry: the
+ `default_party` group if one is configured, else the whole collective.
+ Other groups come back as names only, so nothing you aren't using is
+ loaded into the party.
+ * --list-groups — just id + name + size for every configured group. The
+ cheap menu for "which room?", with no member detail.
+ * --party — full member detail for one chosen group, on demand
+ (e.g. when the user switches rooms). Unknown id returns the available
+ names instead of an error wall.
+
+The merge is deterministic (a keyed union; a custom member whose code
+matches an installed agent overrides it), so the orchestrator consumes a
+resolved roster instead of re-deriving it every session.
+
+Stdlib only (Python 3.11+ for tomllib). Shells out to the project's
+resolve_config.py and resolve_customization.py; falls back to reading
+customize.toml directly if the customization resolver is unavailable.
+
+ resolve_party.py --project-root P --skill S
+ resolve_party.py --project-root P --skill S --list-groups
+ resolve_party.py --project-root P --skill S --party writers-room
+"""
+
+import argparse
+import json
+import subprocess
+import sys
+from pathlib import Path
+
+try:
+ import tomllib
+except ImportError: # pragma: no cover - guarded for <3.11
+ sys.stderr.write("error: Python 3.11+ is required (stdlib `tomllib`).\n")
+ sys.exit(3)
+
+
+def _run_json(cmd):
+ """Run a resolver script and parse its JSON stdout. None on any failure."""
+ try:
+ out = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
+ except (OSError, subprocess.SubprocessError):
+ return None
+ if out.returncode != 0 or not out.stdout.strip():
+ return None
+ try:
+ return json.loads(out.stdout)
+ except json.JSONDecodeError:
+ return None
+
+
+def load_agents(project_root: Path):
+ """Installed agents as {code: entry}. Empty dict (with a flag) on failure."""
+ script = project_root / "_bmad" / "scripts" / "resolve_config.py"
+ data = _run_json([sys.executable, str(script), "--project-root", str(project_root), "--key", "agents"])
+ if data is None:
+ return {}, False
+ return data.get("agents", {}) or {}, True
+
+
+def load_workflow(project_root: Path, skill_root: Path):
+ """Merged [workflow] table. Falls back to the skill's base customize.toml."""
+ script = project_root / "_bmad" / "scripts" / "resolve_customization.py"
+ data = _run_json([sys.executable, str(script), "--skill", str(skill_root), "--key", "workflow"])
+ if data is not None and "workflow" in data:
+ return data["workflow"]
+ # Fallback: read the skill's base customize.toml directly (no override merge).
+ toml_path = skill_root / "customize.toml"
+ if toml_path.exists():
+ try:
+ with toml_path.open("rb") as f:
+ return tomllib.load(f).get("workflow", {})
+ except (OSError, tomllib.TOMLDecodeError):
+ pass
+ return {}
+
+
+def _alias(code: str) -> str:
+ """Short alias for an installed agent code: bmad-agent-analyst -> analyst."""
+ for prefix in ("bmad-agent-", "bmad-"):
+ if code.startswith(prefix):
+ return code[len(prefix):]
+ return code
+
+
+def build_collective(agents: dict, party_members: list):
+ """One pool keyed by code. Custom members override matching installed agents.
+
+ Returns (collective, index, installed_codes):
+ * collective — every member (installed + custom), the pool groups draw
+ from and the orchestrator can summon by name.
+ * index — maps every resolvable token (code, prefix-stripped alias,
+ lower-cased name) to a canonical code.
+ * installed_codes — the codes occupying an installed-agent slot, in
+ order. This is the DEFAULT room: installed agents (with any custom
+ override applied in place), and NOT the pure-custom additions. So
+ shipping or defining custom members grows the pool without crowding
+ the default party.
+ """
+ collective = {}
+ index = {}
+ installed_codes = []
+
+ def register(code, entry):
+ collective[code] = entry
+ index[code] = code
+ index[code.lower()] = code
+ index[_alias(code).lower()] = code
+ name = entry.get("name")
+ if name:
+ index[name.lower()] = code
+
+ for code, info in agents.items():
+ register(code, {
+ "code": code,
+ "name": info.get("name", code),
+ "icon": info.get("icon", ""),
+ "title": info.get("title", ""),
+ "description": info.get("description", ""),
+ "module": info.get("module", ""),
+ "team": info.get("team", ""),
+ "source": "installed",
+ })
+ installed_codes.append(code)
+
+ for m in party_members or []:
+ code = m.get("code")
+ if not code:
+ continue
+ # A custom member overrides an installed agent it matches by code/alias/name.
+ canonical = index.get(code) or index.get(code.lower()) or code
+ entry = {"code": canonical, "source": "custom"}
+ for field in ("name", "icon", "title", "persona", "capabilities", "model"):
+ if m.get(field) is not None:
+ entry[field] = m[field]
+ entry.setdefault("name", canonical)
+ register(canonical, entry)
+ # An override keeps the installed slot; a brand-new custom does not join it.
+
+ return collective, index, installed_codes
+
+
+def resolve_members(member_tokens, collective, index):
+ """(resolved entries in listed order, unresolved tokens)."""
+ resolved, unresolved = [], []
+ for token in member_tokens or []:
+ code = index.get(token) or index.get(str(token).lower())
+ if code and code in collective:
+ resolved.append(collective[code])
+ else:
+ unresolved.append(token)
+ return resolved, unresolved
+
+
+def group_menu(groups):
+ """Names only — the cheap menu. Open-cast groups (no roster) are flagged."""
+ out = []
+ for g in groups or []:
+ if not isinstance(g, dict) or not g.get("id"):
+ continue
+ members = g.get("members", []) or []
+ entry = {"id": g["id"], "name": g.get("name", g["id"]),
+ "member_count": len(members)}
+ if not members:
+ entry["open_cast"] = True
+ out.append(entry)
+ return out
+
+
+def find_group(groups, group_id):
+ for g in groups or []:
+ if isinstance(g, dict) and g.get("id") == group_id:
+ return g
+ return None
+
+
+def group_detail(g, collective, index):
+ """Full detail for one group: resolved members + the optional scene.
+
+ `scene` is a freeform line the orchestrator plays — setting, what's
+ happening, room dynamics, in-the-moment character notes. Surfaced only
+ here (when a group is the active/chosen roster), never in the menu.
+
+ `members` is optional. With none, the group is open-cast: `open_cast`
+ is flagged and the scene describes the pool the orchestrator casts from
+ on the fly (e.g. "figures from the Star Wars Rebels universe"). A few
+ listed members anchor the room; the scene can still invite more.
+ """
+ raw_members = g.get("members", []) or []
+ members, unresolved = resolve_members(raw_members, collective, index)
+ detail = {"active": g["id"], "name": g.get("name", g["id"]),
+ "members": members, "unresolved": unresolved,
+ "memory_enabled": bool(g.get("memory", False))}
+ if g.get("scene"):
+ detail["scene"] = g["scene"]
+ if not raw_members:
+ detail["open_cast"] = True
+ return detail
+
+
+def main():
+ ap = argparse.ArgumentParser(description="Resolve the party-mode roster, lazily.")
+ ap.add_argument("--project-root", required=True)
+ ap.add_argument("--skill", required=True, help="Path to the bmad-party-mode skill dir")
+ ap.add_argument("--party", help="Resolve full detail for this group id")
+ ap.add_argument("--list-groups", action="store_true", help="Group names only")
+ args = ap.parse_args()
+
+ project_root = Path(args.project_root).resolve()
+ skill_root = Path(args.skill).resolve()
+
+ workflow = load_workflow(project_root, skill_root)
+ groups = workflow.get("party_groups", []) or []
+ default_party = workflow.get("default_party", "") or ""
+ party_mode = workflow.get("party_mode", "session") or "session"
+ # The global party_memory flag governs only the DEFAULT installed-agent room;
+ # a named group carries its own `memory` flag (resolved in group_detail).
+ party_memory = bool(workflow.get("party_memory", True))
+
+ # Group menu never needs the (more expensive) installed-agent resolve.
+ if args.list_groups:
+ _emit({
+ "party_mode": party_mode,
+ "default_party": default_party,
+ "groups": group_menu(groups),
+ })
+ return
+
+ agents, agents_ok = load_agents(project_root)
+ collective, index, installed_codes = build_collective(agents, workflow.get("party_members", []))
+
+ if args.party:
+ g = find_group(groups, args.party)
+ if g is None:
+ _emit({"error": "unknown_group", "requested": args.party,
+ "available": group_menu(groups)})
+ return
+ _emit({**group_detail(g, collective, index), "party_mode": party_mode})
+ return
+
+ # Default: the active roster to load on entry.
+ result = {"party_mode": party_mode, "groups": group_menu(groups),
+ "installed_agents_resolved": agents_ok}
+ g = find_group(groups, default_party) if default_party else None
+ if g is not None:
+ result.update(group_detail(g, collective, index))
+ else:
+ # No default group: the installed agents (custom additions stay in the
+ # pool but don't crowd the default room), exactly like a plain install.
+ result.update({"active": "installed",
+ "members": [collective[c] for c in installed_codes],
+ "memory_enabled": party_memory})
+ _emit(result)
+
+
+def _emit(obj):
+ reconfigure = getattr(sys.stdout, "reconfigure", None)
+ if reconfigure is not None:
+ reconfigure(encoding="utf-8")
+ sys.stdout.write(json.dumps(obj, indent=2, ensure_ascii=False) + "\n")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/80_bmad/base/.agents/skills/bmad-party-mode/scripts/tests/test-resolve_party.py b/80_bmad/base/.agents/skills/bmad-party-mode/scripts/tests/test-resolve_party.py
new file mode 100644
index 0000000..43aaa90
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-party-mode/scripts/tests/test-resolve_party.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+# /// script
+# requires-python = ">=3.11"
+# ///
+"""Unit tests for resolve_party.py — merge, alias, override, group resolution."""
+
+import sys
+import unittest
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
+import resolve_party as rp # noqa: E402
+
+AGENTS = {
+ "bmad-agent-analyst": {"name": "Mary", "icon": "📊", "title": "Analyst"},
+ "bmad-agent-pm": {"name": "John", "icon": "📋", "title": "PM"},
+}
+
+
+class TestAlias(unittest.TestCase):
+ def test_strips_known_prefixes(self):
+ self.assertEqual(rp._alias("bmad-agent-analyst"), "analyst")
+ self.assertEqual(rp._alias("bmad-foo"), "foo")
+
+ def test_passes_through_unprefixed(self):
+ self.assertEqual(rp._alias("morpheus"), "morpheus")
+
+
+class TestBuildCollective(unittest.TestCase):
+ def test_installed_agents_indexed_by_code_alias_and_name(self):
+ col, idx, _ = rp.build_collective(AGENTS, [])
+ self.assertEqual(set(col), {"bmad-agent-analyst", "bmad-agent-pm"})
+ self.assertEqual(idx["analyst"], "bmad-agent-analyst") # alias
+ self.assertEqual(idx["mary"], "bmad-agent-analyst") # name (ci)
+ self.assertEqual(idx["bmad-agent-pm"], "bmad-agent-pm") # full code
+ self.assertEqual(col["bmad-agent-analyst"]["source"], "installed")
+
+ def test_custom_member_appends(self):
+ col, _, _ = rp.build_collective(AGENTS, [{"code": "morpheus", "name": "Morpheus", "persona": "riddles"}])
+ self.assertIn("morpheus", col)
+ self.assertEqual(col["morpheus"]["source"], "custom")
+ self.assertEqual(col["morpheus"]["persona"], "riddles")
+
+ def test_custom_overrides_installed_by_alias(self):
+ col, _, _ = rp.build_collective(AGENTS, [{"code": "analyst", "name": "Mary-Custom", "persona": "p"}])
+ # Override lands on the canonical installed code, not a new "analyst" entry.
+ self.assertNotIn("analyst", col)
+ self.assertEqual(col["bmad-agent-analyst"]["source"], "custom")
+ self.assertEqual(col["bmad-agent-analyst"]["name"], "Mary-Custom")
+
+ def test_member_without_code_skipped(self):
+ col, _, _ = rp.build_collective(AGENTS, [{"name": "Nameless"}])
+ self.assertEqual(set(col), {"bmad-agent-analyst", "bmad-agent-pm"})
+
+
+class TestResolveMembers(unittest.TestCase):
+ def setUp(self):
+ self.col, self.idx, _ = rp.build_collective(AGENTS, [{"code": "morpheus", "name": "Morpheus"}])
+
+ def test_resolves_in_listed_order_and_flags_unknowns(self):
+ resolved, unresolved = rp.resolve_members(["morpheus", "analyst", "ghost"], self.col, self.idx)
+ self.assertEqual([m["code"] for m in resolved], ["morpheus", "bmad-agent-analyst"])
+ self.assertEqual(unresolved, ["ghost"])
+
+ def test_empty(self):
+ self.assertEqual(rp.resolve_members([], self.col, self.idx), ([], []))
+
+
+class TestGroups(unittest.TestCase):
+ GROUPS = [
+ {"id": "wr", "name": "Writers", "members": ["analyst", "morpheus"]},
+ {"id": "bad"}, # no name -> falls back to id; no members -> count 0
+ {"name": "no-id"}, # dropped from menu
+ ]
+
+ def test_menu_is_names_only_with_counts_and_open_cast_flag(self):
+ menu = rp.group_menu(self.GROUPS)
+ self.assertEqual(menu, [
+ {"id": "wr", "name": "Writers", "member_count": 2},
+ {"id": "bad", "name": "bad", "member_count": 0, "open_cast": True},
+ ])
+
+ def test_find_group(self):
+ self.assertEqual(rp.find_group(self.GROUPS, "wr")["name"], "Writers")
+ self.assertIsNone(rp.find_group(self.GROUPS, "missing"))
+
+
+class TestGroupDetail(unittest.TestCase):
+ def setUp(self):
+ self.col, self.idx, _ = rp.build_collective(AGENTS, [{"code": "morpheus", "name": "Morpheus"}])
+
+ def test_scene_passes_through_when_present(self):
+ g = {"id": "tos-10-forward", "name": "Ten Forward", "members": ["morpheus"],
+ "scene": "Late evening, a few rounds in."}
+ d = rp.group_detail(g, self.col, self.idx)
+ self.assertEqual(d["scene"], "Late evening, a few rounds in.")
+ self.assertEqual([m["code"] for m in d["members"]], ["morpheus"])
+
+ def test_scene_omitted_when_absent_or_empty(self):
+ for g in ({"id": "g", "members": ["morpheus"]},
+ {"id": "g", "members": ["morpheus"], "scene": ""}):
+ self.assertNotIn("scene", rp.group_detail(g, self.col, self.idx))
+
+ def test_anchored_group_is_not_open_cast(self):
+ g = {"id": "g", "members": ["morpheus"]}
+ self.assertNotIn("open_cast", rp.group_detail(g, self.col, self.idx))
+
+ def test_open_cast_group_flagged_with_empty_members(self):
+ g = {"id": "rebels", "name": "Star Wars Rebels",
+ "scene": "Figures from the Rebels universe drop in as the topic calls for them."}
+ d = rp.group_detail(g, self.col, self.idx)
+ self.assertTrue(d["open_cast"])
+ self.assertEqual(d["members"], [])
+ self.assertEqual(d["scene"][:7], "Figures")
+
+ def test_memory_enabled_follows_group_flag_and_defaults_off(self):
+ on = rp.group_detail({"id": "g", "members": ["morpheus"], "memory": True}, self.col, self.idx)
+ self.assertTrue(on["memory_enabled"])
+ off = rp.group_detail({"id": "g", "members": ["morpheus"], "memory": False}, self.col, self.idx)
+ self.assertFalse(off["memory_enabled"])
+ absent = rp.group_detail({"id": "g", "members": ["morpheus"]}, self.col, self.idx)
+ self.assertFalse(absent["memory_enabled"]) # opt-in per named group
+
+
+class TestInstalledCodesIsDefaultRoom(unittest.TestCase):
+ """The default room is installed agents only; pure customs stay in the pool."""
+
+ def test_pure_custom_excluded_override_kept_in_default_room(self):
+ col, _, installed = rp.build_collective(AGENTS, [
+ {"code": "morpheus", "name": "Morpheus"}, # pure custom
+ {"code": "analyst", "name": "Mary-Custom", "persona": "p"}, # override
+ {"code": "sec-hawk", "name": "Vex"}, # shipped crew member
+ ])
+ # Pure customs are in the pool...
+ self.assertIn("morpheus", col)
+ self.assertIn("sec-hawk", col)
+ # ...but NOT in the default room.
+ self.assertEqual(installed, ["bmad-agent-analyst", "bmad-agent-pm"])
+ default_room = [col[c]["code"] for c in installed]
+ self.assertEqual(default_room, ["bmad-agent-analyst", "bmad-agent-pm"])
+ # An override keeps its installed slot (and its custom content).
+ self.assertEqual(col["bmad-agent-analyst"]["name"], "Mary-Custom")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/80_bmad/base/.agents/skills/bmad-prd/SKILL.md b/80_bmad/base/.agents/skills/bmad-prd/SKILL.md
new file mode 100644
index 0000000..6ebfeab
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-prd/SKILL.md
@@ -0,0 +1,92 @@
+---
+name: bmad-prd
+description: Create, update, or validate a PRD. Use when the user wants help producing, editing, or validating a PRD.
+---
+# BMad PRD
+
+You are a master facilitator and coach helping the user create, edit, or validate a high quality PRD scoped to the level and rigor appropriate to their stated needs. Fight the urge to do the thinking for them unless they put you into Fast path.
+
+## Conventions
+
+- Bare paths resolve from skill root; `{skill-root}` is this skill's install dir; `{project-root}` is the project working dir.
+- `{workflow.}` resolves to fields in `customize.toml`'s `[workflow]` table (overrides win per BMad merge rules).
+- `{doc_workspace}` is the bound run folder.
+- **File roles.** `.memlog.md` is the run's canonical memory and audit trail — every decision, change, and override (including headless overrides) lands as one append-only line as the conversation unfolds. All writes go through the shared script, never by hand: `uv run {project-root}/_bmad/scripts/memlog.py append --workspace {doc_workspace} --type --text ""` (atomic; read it back only to resume or audit). The PRD is distilled toward it; whatever isn't logged is lost on resume. `addendum.md` preserves user-contributed depth that belongs in a downstream document (architecture, solution design, UX spec) or earned a place but does not fit the PRD itself — rejected-alternative rationale, options-considered matrices, mechanism/transport decisions, technical-how, in-depth personas, sizing data. Capture to the addendum *during* the conversation when the user volunteers such content — do not wait for finalize. Audit and override information never goes in the addendum.
+
+## On Activation
+
+1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults.
+2. Run `{workflow.activation_steps_prepend}`. Treat `{workflow.persistent_facts}` as foundational context (entries prefixed `file:` are loaded). `{workflow.external_sources}` is an org-configured registry of internal tools (knowledge bases, MCP tools); consult them alongside generic web research on the same triggers, org tools preferred when their directive matches. Research itself fires during Discovery — see **Research subagents**.
+3. Load `{project-root}/_bmad/bmm/config.yaml` (+ `config.user.yaml` if present). Resolve `{user_name}`, `{communication_language}`, `{document_output_language}`, `{planning_artifacts}`, `{project_name}`, `{date}`. Missing keys → neutral defaults; never block.
+4. If headless, follow `references/headless.md` for the whole run. Otherwise greet the user **by name** using `{user_name}` and **in their language** using `{communication_language}` — and stay in `{communication_language}` for every turn for the entire run, not just the greeting. In the greeting, let the user know that at any point they can invoke `bmad-party-mode` for multi-agent perspectives or `bmad-advanced-elicitation` for deeper exploration on a specific section. Then scan for misroute on the first message: if the signal points elsewhere (game → BMad GDS; express build → `bmad-quick-dev`; one-pager → `bmad-product-brief`; vet product idea → `bmad-prfaq`; agent skill or custom agent → `bmad-workflow-builder`), suggest they might want the other options before continuing.
+5. Detect intent: **Create** (no PRD), **Update** (existing PRD), **Validate** (critique only). If ambiguous, ask. For Create intent, before binding a fresh workspace, scan `{workflow.prd_output_path}` for prior in-progress runs (folders matching `{workflow.run_folder_pattern}` whose `prd.md` frontmatter `status` is not `final`); if any exist, offer to resume rather than starting over.
+
+Run `{workflow.activation_steps_append}`.
+
+Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
+
+## Intent Modes
+
+**Create.** Bind `{doc_workspace}` to `{workflow.prd_output_path}/{workflow.run_folder_pattern}/`. Write `prd.md` with YAML frontmatter (title, status, created, updated — initial `status: draft`), and seed the memlog with `uv run {project-root}/_bmad/scripts/memlog.py init --workspace {doc_workspace} --field topic=""` so subsequent decisions land in a known file. Tell the user the path. Run `## Discovery`, then `## Finalize`.
+
+**Update.** Reconcile the PRD with a change signal. Source-extract against PRD, addendum, `.memlog.md`, and original inputs (extract, don't ingest). If `.memlog.md` is missing, init it with `uv run {project-root}/_bmad/scripts/memlog.py init --workspace {doc_workspace}`, then spawn a one-time bootstrap subagent to reverse-engineer a thin log from the PRD (one `uv run {project-root}/_bmad/scripts/memlog.py append --workspace {doc_workspace} --type decision --text ""` per recovered decision) before continuing. Surface conflicts with prior decisions before applying. Then `## Finalize`.
+
+**Validate** (or *analyze*). Critique without changing. Load `references/validate.md`.
+
+## Discovery
+
+Order: **Brain dump → Stakes calibration → Working mode → mode-scoped work.** Get to working mode fast — two or three turns, not ten. Users in a hurry must not be held hostage by upstream probing.
+
+**Brain dump.** Always the first move, even when the user opens with paragraphs of context (that is intake, not the dump). Ask for verbal context *and* any existing inputs they want you to read — product brief, research, customer transcripts, competitive analysis, prior PRD draft, design docs. Paths or paste; big docs are fine, you will subagent-extract. A simple "anything else?" surfaces what they almost forgot.
+
+**Research subagents (default).** During Discovery, spawn web-research subagents to ground the picture: what exists in the space, how comparables position themselves, current landscape. Subagent does the search; parent receives a digest.
+
+**Elicitation, not direction.** Discovery pulls the user's vision out; it does not insert yours. Open-ended "tell me about X" beats multiple choice. When you find yourself naming wedges, picking MVP cuts, or proposing phases, stop — you have crossed from elicitation into authoring. Hand the pen back. Infer-and-confirm ("I'm assuming X works like Y — right?") is fine; quizzing the user through a tree of LLM-shaped choices is not.
+
+**Stakes calibration.** One short probe before working mode: hobby / internal / launch — enough to calibrate rigor and section depth. Audience, Existing inputs, and Downstream depth fill in inside the chosen mode, not upstream of the choice.
+
+**Working mode.** Offer the choice in the user's language:
+
+- **Fast path** — I batch remaining gaps into one or two consolidated questions, then draft the full PRD with `[ASSUMPTION]` tags where I inferred. You review and we iterate. The initial quality depends on how much you gave me upfront.
+- **Coaching path** — we walk PM-thinking sections together. Once chosen, I ask which entry point fits: **Vision + Features** (capability-first — for enterprise, dev products, internal tools, anyone who thinks in features), **Journey-led** (user-first — for consumer, UX-heavy, multi-stakeholder products; journeys with named protagonists carry persona context inline, no standalone persona section), or *let me suggest* based on what I heard. The chosen entry sets the section order.
+
+The workspace persists; stop and resume freely.
+
+**Concern scan.** As you read what the user gave you, name the concerns this product actually carries — compliance, integration density, operational SLAs, hardware constraints, public-API contracts, monetization, data governance, whatever applies. The list is open; recognize what's there, do not classify into a fixed shape. These concerns drive which template sections to pull in from the Adapt-In Menu and which to invent when no cluster names them.
+
+**Form-factor.** If not stated in sources, probe — mobile / web / desktop / multi-surface / hardware / API.
+
+**User Journeys are captured, not authored.** When UJs are warranted (consumer / multi-stakeholder B2B / meaningful UX — drop or downscale for internal tooling with a single operator role, regulatory-only updates, hobby/solo, pure technical PRDs), prompt the user to narrate a real session with a named protagonist (Mary, mom of three — not "the user") — what the person does, in what order, where it lands — then structure the answer into UJ-N form and confirm. Persona context lives inline at the moments that matter; no standalone persona section.
+
+## PRD Discipline
+
+**Shape.** Features grouped; FRs nested with globally numbered stable IDs. Cross-cutting NFRs in their own section; skip traceability matrices. Capabilities, not implementation — tech choices live in `addendum.md`. Treat `{workflow.prd_template}` as expert prior knowledge, not a checklist. The **Essential Spine** is the expected default — present it unless the product genuinely doesn't need a section, and when you drop one, do so for a reason a reviewer would agree with. The **Adapt-In Menu** is conditional: pull in the clusters the product's concerns need to best define the requirements. When the product carries a concern the menu doesn't name, invent the section — name it well, decide what belongs in it, place it where it serves the reader or the PRD. Reorder and combine for readability. Never include a section because it appears; never skip a concern because no template section covered it. Counter-metrics named when Success Metrics exist.
+
+**Extract, don't ingest.** Source documents go to subagents for extraction; the parent assembles from extracts. Only load source documents into the parent context wholesale when no subagents are available.
+
+**Length scales with stakes.** Hobby / solo PRDs aim for about two pages. Internal tools land around five to eight. Launch and chain-top PRDs run as long as their FRs and concerns require. Whatever the length, detail that doesn't earn its place in the PRD's main narrative belongs in `addendum.md` — moving overflow there is correct; padding the PRD to look thorough is not.
+
+## Reviewer Gate
+
+Used by the Validate intent and at Finalize step 3.
+
+Assemble the menu: rubric walker against `{workflow.validation_checklist_template}` (the PRD quality rubric) + each entry in `{workflow.finalize_reviewers}` + any ad-hoc reviewers the artifact warrants. Stakes-calibrated — hobby/solo may run quietly or skip; higher stakes get the explicit all/subset/skip menu.
+
+Dispatch entries as parallel subagents against `prd.md` (and `addendum.md` if present) using the standard prefix convention (`skill:` / `file:` / plain text). Each writes its full review to `{doc_workspace}/review-{slug}.md` and returns ONLY a compact summary (verdict, top 2-5 findings, file path) — the parent never holds full review text. The rubric walker uses the prompt and output format in `references/validate.md`. If subagents are unavailable, run sequentially: write the file *before* anything else, then flush the review from working context.
+
+Surface findings tiered, never dumped. Lead with a one-sentence gate verdict, then walk critical + high findings; medium/low roll into a single tail ("plus N more in {file}"). Read the full `review-{slug}.md` only when the user drills into a specific finding. Per finding: autofix, discuss, defer to open items, or ignore.
+
+Under Validate intent, the parent additionally runs the synthesis pipeline in `references/validate.md` — folding every selected reviewer's output into a single HTML + markdown report and opening the HTML.
+
+## Finalize
+
+Tell the user the sequence in one sentence, then walk it. Polish goes last so it does not redo work after reviewer fixes.
+
+1. **Memlog audit.** Walk `.memlog.md` with the user; each entry captured in PRD, in addendum, or set aside.
+2. **Input reconciliation.** Subagent per user-supplied input against `prd.md` + `addendum.md`. Each writes its extract to `{doc_workspace}/reconcile-{slug}.md` and returns ONLY a compact summary (input name, gaps 2-5, file path). Surface gaps — especially qualitative ideas (tone, voice, feel) the FR structure silently drops. Must happen before polish.
+3. **Reviewer pass.** Run `## Reviewer Gate`. Resolve before polish.
+4. **Triage open items.** All Open Questions, `[ASSUMPTION]` tags, `[NOTE FOR PM]` callouts. Phase-blockers (would make the PRD unsafe for UX/architecture/epics) surfaced one at a time and resolved; non-blockers deferred with owner + revisit condition logged via `memlog.py append`. If phase-blocker count is high, flag it.
+5. **Polish.** Apply `{workflow.doc_standards}` to `prd.md` and `addendum.md` in declared order (structural passes before prose — prose should not polish soon-to-be-cut text). Parallelize across documents, sequential within.
+6. **External handoffs.** Execute `{workflow.external_handoffs}`; surface returned URLs/IDs. Skip and flag unavailable tools.
+7. **Close.** Set `prd.md` frontmatter `status: final` and `updated` to `{date}` so future invocations distinguish this PRD from in-progress drafts. Record finalization via `uv run {project-root}/_bmad/scripts/memlog.py append --workspace {doc_workspace} --type event --text "PRD finalized"`. Share artifact paths. Common next: `bmad-ux`, `bmad-architecture`, `bmad-create-epics-and-stories`; invoke `bmad-help` for authoritative routing.
+8. Run `{workflow.on_complete}` if non-empty.
diff --git a/80_bmad/base/.agents/skills/bmad-prd/assets/headless-schemas.md b/80_bmad/base/.agents/skills/bmad-prd/assets/headless-schemas.md
new file mode 100644
index 0000000..89d5b6c
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-prd/assets/headless-schemas.md
@@ -0,0 +1,76 @@
+# Headless Mode JSON Schemas
+
+Every headless run ends with one of these payloads. Omit keys for artifacts not produced.
+
+## Common fields
+
+- `status` — `"complete"`, `"blocked"`, or `"partial"`
+- `intent` — `"create"`, `"update"`, or `"validate"` (matches the detected intent)
+- `reason` — required when `status` is `"blocked"`; one-sentence explanation
+- `assumptions` — array of inferred values that were not directly confirmed by inputs
+- `open_questions` — array of items that need a human decision before the artifact can be considered final
+
+## Create
+
+```json
+{
+ "status": "complete",
+ "intent": "create",
+ "prd": "{doc_workspace}/prd.md",
+ "addendum": "{doc_workspace}/addendum.md",
+ "memlog": "{doc_workspace}/.memlog.md",
+ "open_questions": [],
+ "assumptions": [],
+ "external_handoffs": [
+ {"directive": "Confluence upload", "tool": "corp:confluence_upload", "url": "https://confluence.corp/PROD/123", "status": "ok"}
+ ]
+}
+```
+
+## Update
+
+```json
+{
+ "status": "complete",
+ "intent": "update",
+ "prd": "{doc_workspace}/prd.md",
+ "memlog": "{doc_workspace}/.memlog.md",
+ "changes_summary": "1-3 sentences describing what changed and why",
+ "conflicts_with_prior_decisions": [],
+ "open_questions": [],
+ "external_handoffs": [
+ {"directive": "Confluence upload", "tool": "corp:confluence_upload", "url": "https://confluence.corp/PROD/123", "status": "ok"}
+ ]
+}
+```
+
+## Validate
+
+```json
+{
+ "status": "complete",
+ "intent": "validate",
+ "validation_report": "{doc_workspace}/validation-report.md",
+ "findings_summary": {
+ "critical": 0,
+ "high": 0,
+ "medium": 0,
+ "low": 0
+ },
+ "offer_to_update": true
+}
+```
+
+`validation_report` is always written for Validate intent — the path here is required, not optional.
+
+## Blocked
+
+```json
+{
+ "status": "blocked",
+ "intent": "update",
+ "reason": "Change signal ambiguous — could be a scope expansion or a clarification; no inferred direction"
+}
+```
+
+Always include the intent (best-guess if not certain) and a one-sentence `reason`.
diff --git a/80_bmad/base/.agents/skills/bmad-prd/assets/prd-template.md b/80_bmad/base/.agents/skills/bmad-prd/assets/prd-template.md
new file mode 100644
index 0000000..a7a4ad7
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-prd/assets/prd-template.md
@@ -0,0 +1,165 @@
+# PRD Template
+
+## Essential Spine *(almost always present)*
+
+```markdown
+---
+title: {Product Name}
+created: {YYYY-MM-DD}
+updated: {YYYY-MM-DD}
+---
+
+# PRD: {Product Name}
+*Working title — confirm.*
+
+## 0. Document Purpose
+[1 paragraph: who this PRD is for (PM, stakeholders, downstream workflow owners), how it's structured (Glossary-anchored vocabulary, features grouped with FRs nested, assumptions tagged inline and indexed). If UX work or other inputs already exist, name them here and reference where they live — this PRD builds on them, it does not duplicate.]
+
+## 1. Vision
+[2-3 paragraphs: what this is, what it does for the user, why it matters. Compelling enough to stand alone.]
+
+## 2. Target User
+
+### 2.1 Jobs To Be Done
+[Bulleted. Emotional, social, functional, contextual — whichever apply. Even "this is for me as the builder" is a valid framing for a hobby project.]
+
+### 2.2 Non-Users (v1) *(add when the audience boundary is non-obvious)*
+[Who this is explicitly not for in v1.]
+
+### 2.3 Key User Journeys
+*Named-persona narratives the product enables. Numbered globally as UJ-1 through UJ-N. FRs reference journeys by ID inline ("realizes UJ-3"); SMs may also cross-reference. If a UX doc already exists, mirror its UJ IDs here and point to the source.*
+
+**Default shape:** a named scene with entry state, path, climax, and resolution. Each beat forces specificity the team would otherwise leave implicit — auth assumptions, screen order, what tells the user value landed. Read together as a short narrative; the example below shows the form.
+
+- **UJ-1. {One-line title — persona doing the thing.}**
+ - **Persona + context:** one line, grounded enough to explain the *why*.
+ - **Entry state:** authenticated? which surface? coming from where?
+ - **Path:** 3-5 concrete beats — taps, screens, decisions.
+ - **Climax:** the moment value is delivered and how the user knows.
+ - **Resolution:** state they're left in, what's next.
+ - **Edge case** *(optional)*: one real failure mode and what the user does next.
+
+ *Written out, that becomes:*
+ > **UJ-3. Priya checks the trip damage before she's even home.**
+ > Priya, budgeting on a single income with a new baby, finishes a grocery run and gets in the car. Already authenticated via biometric on a previous session. She opens the app, taps the FAB camera, and scans the receipt. The app OCRs the total and shows a single-screen overlay: this trip $84.20, weekly cap $250, $172.10 remaining, three days left in the week. She closes the app and drives home. **Edge case:** if she scanned a receipt earlier today, the app asks whether this replaces or adds to that trip before counting it against the cap.
+
+- **UJ-2. ...**
+
+**Scope dial:**
+- **Lighter** — hobby/solo, library/CLI, or when the UJ is essentially a JTBD restated: a single sentence works (`{Persona}, {context}, {what they do and why}.`).
+- **Heavier** — auth, multi-device handoff, complex navigation, or anything feeding downstream UX/architecture: add a numbered Flow, an Edge cases list, and a capability → FR mapping (`The system must {capability}. → FR-N`).
+
+## 3. Glossary
+*Downstream workflows and readers must use these terms exactly. FRs, UJs, and SMs use Glossary terms verbatim; introducing a synonym anywhere in the PRD is a discipline violation. If §4 introduces a new domain noun, add it to the Glossary in the same pass.*
+
+- **Term** — Definition. Relationships to other Glossary terms. Cardinality where relevant.
+- **Term** — ...
+
+[Every domain noun the rest of the document uses. Defined once. No synonyms anywhere else in the PRD.]
+
+## 4. Features
+*Each subsection is a coherent feature: behavioral description first, FRs nested under it, optional feature-specific NFRs and notes. FRs are numbered globally (FR-1 through FR-N) so downstream artifacts have stable references even if features get reorganized. Reference user journeys by ID inline ("realizes UJ-2") where the chain matters.*
+
+### 4.1 {Feature Name}
+**Description:** [Behavioral narrative — how this feature works, who uses it, the user experience, edge cases. Realizes UJ-X, UJ-Y. Use Glossary terms exactly. Embed inline `[ASSUMPTION: ...]` tags where you inferred without confirmation.]
+
+**Functional Requirements:**
+
+#### FR-1: {Short capability name}
+
+[Actor] can [capability] [under conditions]. Realizes UJ-X.
+
+**Consequences (testable):**
+- {Specific testable condition, e.g. "System returns HTTP 429 when request rate exceeds 100/sec per merchant."}
+- {Another testable condition.}
+
+**Out of Scope:** *(optional — what this FR explicitly does NOT cover)*
+- {bound}
+
+#### FR-2: ...
+
+**Feature-specific NFRs:** *(only if any apply uniquely to this feature)*
+- Performance / security / accessibility / etc. specific to this feature.
+
+**Notes:** *(optional — open questions specific to this feature, `[NOTE FOR PM]` callouts)*
+
+### 4.2 {Feature Name}
+...
+
+## 5. Non-Goals (Explicit)
+[Bulleted. What this product is *not* and what it will *not* do in v1. Does outsized work for downstream readers and workflows — prevents the "let me also add this nearby thing" failure mode at every level (epic, ticket, code). Inline `[NON-GOAL for MVP]` callouts within §4 Features cover deferred items within features; this section captures the broader "we are not building X / we are not becoming Y" statements.]
+
+## 6. MVP Scope
+
+### 6.1 In Scope
+[Bulleted, crisp.]
+
+### 6.2 Out of Scope for MVP
+[Bulleted. Each item with a one-line reason if the reason matters. Mark items deferred to v2/v3 explicitly. Add `[NOTE FOR PM]` callouts where a deferred item is emotionally load-bearing — flags it for revisit if timeline permits.]
+
+## 7. Success Metrics
+
+*Each SM cross-references the FR(s) it validates. Counter-metrics counterbalance specific primary or secondary metrics.*
+
+**Primary**
+- **SM-1**: Metric — definition, target. Validates FR-X, FR-Y.
+
+**Secondary**
+- **SM-2**: Metric — definition, target. Validates FR-Z.
+
+**Counter-metrics (do not optimize)**
+- **SM-C1**: Metric — why this should *not* be optimized. Counterbalances SM-1.
+
+[Length scales with stakes. Hobby/utility PRD: a single sentence may be enough ("Success: I use this weekly and don't abandon it after a month"). Public launch / enterprise: full quantitative breakdown with measurement methods. Counter-metrics are as load-bearing as primary metrics — they prevent the architect from optimizing the wrong thing and the dev from gaming the wrong target.]
+
+## 8. Open Questions
+[Numbered. Things still unknown — they become future tickets or follow-up research, not silent gaps.]
+
+## 9. Assumptions Index
+*Every `[ASSUMPTION]` from the document, surfaced for explicit confirmation:*
+- Inline assumption from §X.Y — short description.
+- ...
+```
+
+---
+
+## Adapt-In Menu *(add the clusters the product calls for)*
+
+### Cross-cutting quality and shape *(most non-trivial PRDs)*
+- **Cross-Cutting NFRs** — system-wide non-functional requirements not tied to a single feature (performance, security, reliability, observability). Add when system-wide quality attributes are meaningful.
+- **Constraints and Guardrails** — Safety, Privacy, Cost. Subsection per cluster. Add when any of these are real concerns.
+- **Why Now** — add when timing is load-bearing (a market shift, a technology enabler, a regulatory deadline). Drop when timing is incidental.
+
+### Consumer / branded products
+- **Aesthetic and Tone** — visual references, anti-references, voice/tone for any product-generated text.
+- **Information Architecture** — top-level surfaces, navigation, screens.
+- **Monetization** — free vs. paid, pricing assumptions, ads policy.
+- **Platform** — web, mobile, PWA, native, v1 vs. v2+.
+
+### Enterprise initiatives
+- **Stakeholders and Approvals** — who must sign off, at what stage.
+- **Risk and Mitigations** — operational, security, business, reputational risk register.
+- **ROI / Business Case** — quantified benefit, cost, payback period.
+- **Operational Requirements** — SLAs, RTO/RPO, support tier, on-call expectations.
+- **Integration and Dependencies** — SSO, existing enterprise systems, data sources, downstream consumers.
+- **Rollout and Change Management** — phased rollout plan, training, internal communication.
+- **Data Governance** — residency, sovereignty, classification, retention.
+- **Audit Trail / Decision Provenance** — formal documentation requirements for regulated environments.
+
+### Regulated domains
+- **Compliance and Regulatory** — HIPAA, PCI-DSS, GDPR, SOX, SOC 2, Section 508 / WCAG 2.1 AA, FedRAMP, etc. — whichever apply. If any item needs depth, add a `[NOTE FOR PM]` callout to revisit or move to an addendum.
+
+### Developer products (libraries, APIs, CLIs, SDKs)
+- **API Contracts / Public Surface** — endpoint shapes, breaking change policy.
+- **Versioning and Deprecation Policy**.
+- **Performance Budgets** — latency, throughput, resource use.
+- **Language / Runtime Targets and Dependency Policy**.
+
+### Embedded / hardware
+- **Hardware Constraints** — memory, power, form factor.
+- **Deployment and Update Mechanism** — OTA, manual, image-based.
+- **Environmental and Reliability Requirements**.
+
+### Small-scope all-inclusive *(use when scope is 1-2 stories' worth and the user wants a single captured artifact — chosen during the Right-skill check in Discovery)*
+- **Stories** — story-level specs listed inline at the end of the doc. Each story: *"As a [persona], I can [action] [under conditions]. Acceptance: [testable criteria]."* Numbered Story-1, Story-2, ... for reference. Pair with very lean §1 Vision, §2 Target User (often just JTBD + one UJ), §3 Glossary (handful of terms), §4 Features (often a single feature), §6 MVP Scope (in/out very tight). The whole doc fits on a page or two and captures intent + implementable stories in one place. If the user doesn't want the captured artifact at all, `bmad-quick-dev` is the better path — this cluster is only for "I want a doc *and* the stories."
+
diff --git a/80_bmad/base/.agents/skills/bmad-prd/assets/prd-validation-checklist.md b/80_bmad/base/.agents/skills/bmad-prd/assets/prd-validation-checklist.md
new file mode 100644
index 0000000..f52c43b
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-prd/assets/prd-validation-checklist.md
@@ -0,0 +1,135 @@
+# PRD Quality Rubric
+
+A judgment rubric for the validator subagent. Walk the PRD with these dimensions in mind and write substantive findings — not box-ticking. The goal is a review that tells the user whether this PRD is *good*, not whether it has the right section headers.
+
+Most PRDs do not need every dimension scrutinized equally. Calibrate to the agreed stakes, the PRD's shape (consumer product, internal tool, regulatory update, technical capability spec), and what the PRD itself is trying to do. Be specific — cite locations, quote phrases, name what's missing. Abstract criticism is failure of nerve.
+
+## How to use this rubric
+
+1. Read the full PRD (and addendum.md if present) before writing anything.
+2. For each of the seven dimensions below, form a judgment — *strong / adequate / thin / broken* — backed by specifics from the PRD.
+3. Write findings only where they add information. A `strong` dimension may need no findings; a `broken` one needs concrete, fixable ones.
+4. Severity ranks impact on the PRD's usefulness, not how easy the fix is. A vague Vision statement is *critical* even though it's a one-paragraph fix; a glossary drift might be *low* even though it appears in many places.
+5. The overall verdict is your synthesis — 2–3 sentences that name what holds up and what's at risk. Earn it with the dimension judgments.
+
+## Output format
+
+Write findings to `{doc_workspace}/review-rubric.md`:
+
+```markdown
+# PRD Quality Review — {prd_name}
+
+## Overall verdict
+[2–3 sentences. What holds up, what's at risk. Earned by the dimension judgments below.]
+
+## Decision-readiness — [strong | adequate | thin | broken]
+[1–3 paragraphs of judgment with specific PRD locations.]
+
+### Findings
+- **[critical|high|medium|low]** [Title] (§ location) — [Note]. *Fix:* [suggested fix].
+
+## Substance over theater — [verdict]
+...
+
+(repeat for each dimension)
+
+## Mechanical notes
+[Glossary drift, ID continuity, broken cross-refs, Assumptions Index roundtrip. Lighter weight — these matter for downstream but don't drive the overall verdict.]
+```
+
+## The seven dimensions
+
+### 1. Decision-readiness
+
+Can a decision-maker act on this PRD? Are the trade-offs surfaced honestly, or has the PRD smoothed everything to neutral? Would someone pushing back find their objection acknowledged or dodged?
+
+Look for:
+- Decisions that are stated as decisions, not buried as "considerations."
+- Trade-offs named with what was given up, not just what was chosen.
+- Open Questions that are actually open — not rhetorical questions with an answer in the next sentence.
+- `[NOTE FOR PM]` callouts at real tensions, not at safe checkpoints.
+
+Red flag: a PRD where every choice "balances" everything, every NFR is "important," every persona "values" the product.
+
+### 2. Substance over theater
+
+Is the content earned, or is it furniture? Distinguish:
+
+- **Persona theater** — Personas that don't drive a single decision in the PRD. More than four personas. Personas whose only function is to make the PRD look thorough.
+- **Innovation theater** — claimed novelty that isn't novel. Differentiation sections written because the template had one, not because Discovery surfaced something.
+- **NFR theater** — copied boilerplate ("system must be scalable / secure / reliable") without product-specific thresholds.
+- **Vision theater** — a Vision statement that could swap into any PRD in this category without change.
+
+Flag what reads like furniture, even if it's well-written furniture.
+
+### 3. Strategic coherence
+
+Does the PRD have a thesis? Do the features serve a unified arc, or is it a list of capabilities someone wanted?
+
+Look for:
+- A stated thesis the PRD bets on (problem framing, user insight, market move).
+- Feature prioritization that follows from the thesis — not from "what's easy first."
+- Success Metrics that validate the thesis, not metrics that just measure activity (DAU/MAU when the thesis is about engagement quality is a tell).
+- Counter-metrics named when SMs exist.
+- Coherent MVP scope kind — problem-solving, experience, platform, or revenue — with scope logic that matches.
+
+Red flag: a PRD that reads as a backlog with section headings.
+
+### 4. Done-ness clarity
+
+Would an engineer reading this PRD know what "done" looks like for each FR?
+
+Look for:
+- FRs with at least one testable consequence per FR — verifiable condition, measurable outcome.
+- "System handles X gracefully," "reasonable performance," "user-friendly" — flag every one.
+- Acceptance criteria implied or explicit. Sometimes the FR's consequences carry this; sometimes the PRD genuinely needs an Acceptance section.
+- For non-functional sections (UX, performance, security): bounds, not adjectives.
+
+This is the dimension downstream story creation will lean on hardest. Be unforgiving here.
+
+### 5. Scope honesty
+
+Are omissions explicit, or is the reader meant to infer them?
+
+Look for:
+- A Non-Goals section where it would do real work — and `[NON-GOAL for MVP]` callouts where omissions could be silently assumed.
+- `[ASSUMPTION: …]` tags on inferences the user didn't directly confirm, indexed at the end.
+- `[NOTE FOR PM]` callouts at deferred decisions and unresolved tensions.
+- De-scoping proposed honestly, not done silently.
+
+Open-items density: count Open Questions + `[ASSUMPTION]` + `[NOTE FOR PM]` callouts relative to stakes. High counts on a low-stakes PRD is fine; high counts on a green-light-to-build PRD is a blocker.
+
+### 6. Downstream usability
+
+If this PRD feeds UX, architecture, or story creation, can those workflows source-extract from it cleanly?
+
+Look for:
+- Glossary present; every domain noun used identically across FRs, UJs, SM definitions.
+- FR / UJ / SM IDs contiguous, unique, and cross-references that resolve.
+- Each section makes sense pulled out alone — cross-references via Glossary terms, not "see above."
+- UJs each have a named protagonist; no floating UJs.
+
+For standalone PRDs (no downstream), this dimension matters less — say so.
+
+### 7. Shape fit
+
+Has the PRD been forced into a shape that doesn't match the product?
+
+- Consumer product / multi-stakeholder B2B / meaningful UX → UJs with named protagonists are load-bearing.
+- Internal tool, single-operator role → capability spec shape; UJs may be overhead; SMs may be operational rather than user-facing.
+- Regulatory or compliance update → constraint traceability is non-negotiable; UJs may be irrelevant.
+- Hobby / solo → rigor light, substance bar still applies.
+- Brownfield → existing-code references must be accurate; new UJs and existing UJs must be distinguished.
+- Chain-top (feeds UX → architecture → stories) → downstream usability matters more; standalone PRDs can be lighter on traceability.
+
+Flag PRDs that are over-formalized (UJ density for a single-operator tool) or under-formalized (consumer product with no UJs).
+
+## Mechanical notes
+
+Cover these as a tail section, not a primary dimension. They matter for downstream but don't drive the verdict on whether the PRD is good.
+
+- Glossary drift (case, plural, synonyms across the PRD).
+- ID continuity (gaps, duplicates, unresolved cross-references).
+- Assumptions Index roundtrip (every inline `[ASSUMPTION]` indexed; index entries all appear inline).
+- UJ protagonist naming (each UJ has a named protagonist carrying context inline).
+- Required sections present for the agreed stakes and product type.
diff --git a/80_bmad/base/.agents/skills/bmad-prd/assets/validation-report-template.html b/80_bmad/base/.agents/skills/bmad-prd/assets/validation-report-template.html
new file mode 100644
index 0000000..72e7271
--- /dev/null
+++ b/80_bmad/base/.agents/skills/bmad-prd/assets/validation-report-template.html
@@ -0,0 +1,325 @@
+
+
+
+
+
+PRD Validation: TEMPLATE_PRD_NAME
+
+
+
+
+
+
+
+
+
+
+
TEMPLATE_SYNTHESIS_PARAGRAPH
+
+
+
+
+
+
Decision-readiness
+
TEMPLATE_VERDICT_TEXT
+
+
+
+
+
+
+
+
+ Decision-readiness
+ TEMPLATE_VERDICT_TEXT
+
+
+
+
TEMPLATE_DIMENSION_JUDGMENT
+
+
+