Compare commits

...

8 Commits

Author SHA1 Message Date
Markus Ende 6e4cea4ff9
Merge 147144a1ec into 3ad6985643 2026-02-23 08:47:27 +01:00
Brian Madison 3ad6985643 6.0.2 2026-02-22 19:48:27 -06:00
Brian Madison 44eeaa8a71 feat(docs): add public roadmap and improve site navigation
- Add comprehensive public roadmap with In Progress, Getting Started, and Community sections
- Add roadmap callout to README.md and docs welcome page
- Add roadmap-specific card grid styles with equal-height cards
- Fix rehype-markdown-links plugin to detect docs directory in various project structures
- Rename roadmap.md to roadmap.mdx for proper Astro/Starlight rendering
- Update doc link validator to support .mdx files
2026-02-22 19:41:57 -06:00
Brian Madison 1d49fe1802 feat(templates): remove disable-model-invocation to enable workflow skill calls
This change removes the disable-model-invocation flag from all IDE installer
templates. By allowing model invocation, bmad help can now properly invoke
suggested workflows as direct skill calls, improving the user experience by
enabling automatic workflow execution when desired.
2026-02-22 16:38:05 -06:00
Brian Madison 476082fda7 refactor(workflows): standardize workflow descriptions for skill generation
- Standardize all workflow descriptions to follow format: [short description]. Use when the user says 'explicit action phrase' or 'another phrase'
- Remove verbose descriptions in favor of concise summaries with explicit trigger phrases
- Use max 2 phrases per workflow to minimize context and false positives
- Phrases are explicit actions (e.g., "lets create", "run X") not questions
- No slash commands in descriptions - users invoke via /name directly
- Rename qa/automate to qa-generate-e2e-tests for clarity
- Update various core tasks and workflows
2026-02-22 12:21:00 -06:00
Brian 147144a1ec
Merge branch 'main' into fix/copilot-hardcoded-bmm-config-path 2026-02-20 20:36:33 -06:00
Markus Ende 7a016d5efa fix: address CodeRabbit review comments for github-copilot installer
- Deduplicate selectedModules to prevent duplicate paths in markdown output
- Remove unused primaryModule variable (dead code)
- Refactor loadModuleConfig to accept installedModules param instead of hardcoded 'bmm'
- Make tech-writer BMM-only check explicit (entry.module !== 'bmm' returns null)
- Add test/test-github-copilot-installer.js with comprehensive unit tests
- Add test:copilot script to package.json and include in main test command
2026-02-19 20:37:52 +01:00
Markus Ende c017a5fdba fix: use module-specific config.yaml paths in GitHub Copilot installer
Replace hardcoded bmm/config.yaml references with dynamic module-based paths
so custom modules load their own config.yaml instead of the non-existent bmm config.

- createWorkflowPromptContent(): use entry.module from bmad-help.csv
- createAgentActivatorPromptContent(): use artifact.module
- createTechWriterPromptContent(): use entry.module for config and agent paths
- generateCopilotInstructions(): dynamically list installed module paths

Fixes #1708
2026-02-19 19:58:06 +01:00
54 changed files with 850 additions and 78 deletions

View File

@ -1,5 +1,42 @@
# Changelog
## [6.0.2]
### 🎁 Features
* Add CodeBuddy platform support with installer configuration (#1483)
* Add LLM audit prompt for file reference conventions - new audit tool using parallel subagents (#1720)
* Migrate Codex installer from `.codex/prompts` to `.agents/skills` format to align with Codex CLI changes (#1729)
* Convert review-pr and audit-file-refs tools to proper bmad-os skills with slash commands `/bmad-os-review-pr` and `/bmad-os-audit-file-refs` (#1732)
### 🐛 Bug Fixes
* Fix 24 broken step references in create-architecture workflow after directory rename (#1734)
* Fix step file path references in check-implementation-readiness workflow (#1709, #1716)
* Fix 3 broken file references and enable strict file reference validation in CI (#1717)
* Fix Rovo Dev integration with custom installer that generates prompts.yml manifest (#1701)
* Fix 104 relative step file references to use standardized `{project-root}/_bmad/` paths across 68 files (#1722)
* Fix code fence imbalance in step-03-starter.md that caused rendering issues (#1724)
* Remove Windsurf from recommended/preferred IDEs list (#1727)
* Fix default Codex install location from global to project for better defaults (#1698)
* Add npx cache workaround to Quick Start for stale beta versions (#1685)
* Add language instructions to replace placeholder text in Research overview (#1703)
* Ignore `.junie/` IDE integration folder in git and prettier configs (#1719)
### ♻️ Refactoring
* Update open source tool skills structure for future plugin migration
* Standardize all workflow descriptions for skill generation with concise format and explicit trigger phrases
* Remove `disable-model-invocation` flag from all IDE installer templates to enable workflow skill calls
### 📚 Documentation
* Elevate `bmad-help` as primary on-ramp across all documentation
* Update workflow names with `bmad-bmm-` prefix and standardize table formatting
* Clarify phase routing and catalog path in help task
---
## [6.0.0]
V6 Stable Release! The End of Beta!

View File

@ -22,6 +22,16 @@ Traditional AI tools do the thinking for you, producing average results. BMad ag
[Learn more at **docs.bmad-method.org**](http://docs.bmad-method.org)
---
## 🚀 What's Next for BMad?
**V6 is here and we're just getting started!** The BMad Method is evolving rapidly with optimizations including Cross Platform Agent Team and Sub Agent inclusion, Skills Architecture, BMad Builder v1, Dev Loop Automation, and so much more in the works.
**[📍 Check out the complete Roadmap →](http://docs.bmad-method.org/roadmap/)**
---
## Quick Start
**Prerequisites**: [Node.js](https://nodejs.org) v20+

View File

@ -7,6 +7,10 @@ The BMad Method (**B**reakthrough **M**ethod of **A**gile AI **D**riven Developm
If you're comfortable working with AI coding assistants like Claude, Cursor, or GitHub Copilot, you're ready to get started.
:::note[🚀 V6 is Here and We're Just Getting Started!]
Skills Architecture, BMad Builder v1, Dev Loop Automation, and so much more in the works. **[Check out the Roadmap →](/roadmap/)**
:::
## New Here? Start with a Tutorial
The fastest way to understand BMad is to try it.

136
docs/roadmap.mdx Normal file
View File

@ -0,0 +1,136 @@
---
title: Roadmap
description: What's next for BMad - Features, improvements, and community contributions
---
# The BMad Method: Public Roadmap
The BMad Method, BMad Method Module (BMM), and BMad Builder (BMB) are evolving. Here's what we're working on and what's coming next.
<div class="roadmap-container">
<h2 class="roadmap-section-title">In Progress</h2>
<div class="roadmap-future">
<div class="roadmap-future-card">
<span class="roadmap-emoji">🧩</span>
<h4>Universal Skills Architecture</h4>
<p>One skill, any platform. Write once, run everywhere.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🏗️</span>
<h4>BMad Builder v1</h4>
<p>Craft production-ready AI agents and workflows with evals, teams, and graceful degradation built in.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🧠</span>
<h4>Project Context System</h4>
<p>Your AI actually understands your project. Framework-aware context that evolves with your codebase.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">📦</span>
<h4>Centralized Skills</h4>
<p>Install once, use everywhere. Share skills across projects without the file clutter.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🔄</span>
<h4>Adaptive Skills</h4>
<p>Skills that know your tool. Optimized variants for Claude, Codex, Kimi, and OpenCode, plus many more.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">📝</span>
<h4>BMad Team Pros Blog</h4>
<p>Guides, articles and insights from the team. Launching soon.</p>
</div>
</div>
<h2 class="roadmap-section-title">Getting Started</h2>
<div class="roadmap-future">
<div class="roadmap-future-card">
<span class="roadmap-emoji">🏪</span>
<h4>Skill Marketplace</h4>
<p>Discover, install, and update community-built skills. One curl command away from superpowers.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🎨</span>
<h4>Workflow Customization</h4>
<p>Make it yours. Integrate Jira, Linear, custom outputs your workflow, your rules.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🚀</span>
<h4>Phase 1-3 Optimization</h4>
<p>Lightning-fast planning with sub-agent context gathering. YOLO mode meets guided excellence.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🌐</span>
<h4>Enterprise Ready</h4>
<p>SSO, audit logs, team workspaces. All the boring stuff that makes companies say yes.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">💎</span>
<h4>Community Modules Explosion</h4>
<p>Entertainment, security, therapy, roleplay and much more. Expand the BMad Method platform.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">⚡</span>
<h4>Dev Loop Automation</h4>
<p>Optional autopilot for development. Let AI handle the flow while keeping quality sky-high.</p>
</div>
</div>
<h2 class="roadmap-section-title">Community and Team</h2>
<div class="roadmap-future">
<div class="roadmap-future-card">
<span class="roadmap-emoji">🎙️</span>
<h4>The BMad Method Podcast</h4>
<p>Conversations about AI-native development. Launching March 1, 2026!</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🎓</span>
<h4>The BMad Method Master Class</h4>
<p>Go from user to expert. Deep dives into every phase, every workflow, every secret.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🏗️</span>
<h4>The BMad Builder Master Class</h4>
<p>Build your own agents. Advanced techniques for when you are ready to create, not just use.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">⚡</span>
<h4>BMad Prototype First</h4>
<p>Idea to working prototype in one session. Craft your dream app like a work of art.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🌴</span>
<h4>BMad BALM!</h4>
<p>Life management for the AI-native. Tasks, habits, goals your AI copilot for everything.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🖥️</span>
<h4>Official UI</h4>
<p>A beautiful interface for the entire BMad ecosystem. CLI power, GUI polish.</p>
</div>
<div class="roadmap-future-card">
<span class="roadmap-emoji">🔒</span>
<h4>BMad in a Box</h4>
<p>Self-hosted, air-gapped, enterprise-grade. Your AI assistant, your infrastructure, your control.</p>
</div>
</div>
<div style="text-align: center; margin-top: 3rem; padding: 2rem; background: var(--color-bg-card); border-radius: 12px; border: 1px solid var(--color-border);">
<h3 style="margin: 0 0 1rem;">Want to Contribute?</h3>
<p style="color: var(--slate-color-400); margin: 0;">
This is only a partial list of what's planned. The BMad Open Source team welcomes contributors!{" "}<br />
<a href="https://github.com/bmad-code-org/BMAD-METHOD" style="color: var(--color-in-progress);">Join us on GitHub</a> to help shape the future of AI-driven development.
</p>
<p style="color: var(--slate-color-400); margin: 1.5rem 0 0;">
Love what we're building? We appreciate both one-time and monthly{" "}<a href="https://buymeacoffee.com/bmad" style="color: var(--color-in-progress);">support</a>.
</p>
<p style="color: var(--slate-color-400); margin: 1rem 0 0;">
For corporate sponsorship, partnership inquiries, speaking engagements, training, or media enquiries:{" "}
<a href="mailto:contact@bmadcode.com" style="color: var(--color-in-progress);">contact@bmadcode.com</a>
</p>
</div>
</div>

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "bmad-method",
"version": "6.0.1",
"version": "6.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bmad-method",
"version": "6.0.1",
"version": "6.0.2",
"license": "MIT",
"dependencies": {
"@clack/core": "^1.0.0",

View File

@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "bmad-method",
"version": "6.0.1",
"version": "6.0.2",
"description": "Breakthrough Method of Agile AI-driven Development",
"keywords": [
"agile",
@ -40,7 +40,8 @@
"lint:md": "markdownlint-cli2 \"**/*.md\"",
"prepare": "command -v husky >/dev/null 2>&1 && husky || exit 0",
"rebundle": "node tools/cli/bundlers/bundle-web.js rebundle",
"test": "npm run test:schemas && npm run test:refs && npm run test:install && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check",
"test": "npm run test:schemas && npm run test:refs && npm run test:install && npm run test:copilot && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check",
"test:copilot": "node test/test-github-copilot-installer.js",
"test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas",
"test:install": "node test/test-installation-components.js",
"test:refs": "node test/test-file-refs-csv.js",

View File

@ -1,6 +1,6 @@
---
name: create-product-brief
description: Create comprehensive product briefs through collaborative step-by-step discovery as creative Business Analyst working with the user as peers.
description: Create product brief through collaborative discovery. Use when the user says 'lets create a product brief' or 'help me create a project brief'
---
# Product Brief Workflow

View File

@ -1,6 +1,6 @@
---
name: domain-research
description: Conduct domain research covering industry analysis, regulations, technology trends, and ecosystem dynamics using current web data and verified sources.
description: Conduct domain and industry research. Use when the user says 'lets create a research report on [domain or industry]
---
# Domain Research Workflow

View File

@ -1,6 +1,6 @@
---
name: market-research
description: Conduct market research covering market size, growth, competition, and customer insights using current web data and verified sources.
description: Conduct market research on competition and customers. Use when the user says 'create a market research report about [business idea]'.
---
# Market Research Workflow

View File

@ -1,6 +1,6 @@
---
name: technical-research
description: Conduct technical research covering technology evaluation, architecture decisions, and implementation approaches using current web data and verified sources.
description: Conduct technical research on technologies and architecture. Use when the user says 'create a technical research report on [topic]'.
---
# Technical Research Workflow

View File

@ -1,6 +1,6 @@
---
name: create-prd
description: Create a comprehensive PRD (Product Requirements Document) through structured workflow facilitation
description: Create a PRD from scratch. Use when the user says 'lets create a product requirements document' or 'I want to create a new PRD'
main_config: '{project-root}/_bmad/bmm/config.yaml'
nextStep: './steps-c/step-01-init.md'
---

View File

@ -1,6 +1,6 @@
---
name: edit-prd
description: Edit and improve an existing PRD - enhance clarity, completeness, and quality
description: Edit an existing PRD. Use when the user says 'edit this PRD'.
main_config: '{project-root}/_bmad/bmm/config.yaml'
editWorkflow: './steps-e/step-e-01-discovery.md'
---

View File

@ -1,6 +1,6 @@
---
name: validate-prd
description: Validate an existing PRD against BMAD standards - comprehensive review for completeness, clarity, and quality
description: Validate a PRD against standards. Use when the user says 'validate this PRD' or 'run PRD validation'
main_config: '{project-root}/_bmad/bmm/config.yaml'
validateWorkflow: './steps-v/step-v-01-discovery.md'
---

View File

@ -1,6 +1,6 @@
---
name: create-ux-design
description: Work with a peer UX Design expert to plan your applications UX patterns, look and feel.
description: Plan UX patterns and design specifications. Use when the user says 'lets create UX design' or 'create UX specifications' or 'help me plan the UX'
---
# Create UX Design Workflow

View File

@ -1,6 +1,6 @@
---
name: check-implementation-readiness
description: 'Critical validation workflow that assesses PRD, Architecture, and Epics & Stories for completeness and alignment before implementation. Uses adversarial review approach to find gaps and issues.'
description: Validate PRD, UX, Architecture and Epics specs are complete. Use when the user says 'check implementation readiness'.
---
# Implementation Readiness

View File

@ -1,6 +1,6 @@
---
name: create-architecture
description: Collaborative architectural decision facilitation for AI-agent consistency. Replaces template-driven architecture with intelligent, adaptive conversation that produces a decision-focused architecture document optimized for preventing agent conflicts.
description: Create architecture solution design decisions for AI agent consistency. Use when the user says 'lets create architecture' or 'create technical architecture' or 'create a solution design'
---
# Architecture Workflow

View File

@ -1,6 +1,6 @@
---
name: create-epics-and-stories
description: 'Transform PRD requirements and Architecture decisions into comprehensive stories organized by user value. This workflow requires completed PRD + Architecture documents (UX recommended if UI exists) and breaks down requirements into implementation-ready epics and user stories that incorporate all available technical and design context. Creates detailed, actionable stories with complete acceptance criteria for development teams.'
description: Break requirements into epics and user stories. Use when the user says 'create the epics and stories list'
---
# Create Epics and Stories

View File

@ -1,7 +1,6 @@
# Review Story Workflow
name: code-review
description: "Perform an ADVERSARIAL Senior Developer code review that finds 3-10 specific problems in every story. Challenges everything: code quality, test coverage, architecture compliance, security, performance. NEVER accepts `looks good` - must find minimum issues and can auto-fix with user approval."
author: "BMad"
description: "Perform adversarial code review finding specific issues. Use when the user says 'run code review' or 'review this code'"
# Critical variables from config
config_source: "{project-root}/_bmad/bmm/config.yaml"

View File

@ -1,7 +1,6 @@
# Correct Course - Sprint Change Management Workflow
name: "correct-course"
description: "Navigate significant changes during sprint execution by analyzing impact, proposing solutions, and routing for implementation"
author: "BMad Method"
description: "Manage significant changes during sprint execution. Use when the user says 'correct course' or 'propose sprint change'"
config_source: "{project-root}/_bmad/bmm/config.yaml"
user_name: "{config_source}:user_name"

View File

@ -1,6 +1,5 @@
name: create-story
description: "Create the next user story from epics+stories with enhanced context analysis and direct ready-for-dev marking"
author: "BMad"
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]'"
# Critical variables from config
config_source: "{project-root}/_bmad/bmm/config.yaml"

View File

@ -1,6 +1,5 @@
name: dev-story
description: "Execute a story by implementing tasks/subtasks, writing tests, validating, and updating the story file per acceptance criteria"
author: "BMad"
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'"
# Critical variables from config
config_source: "{project-root}/_bmad/bmm/config.yaml"

View File

@ -1,7 +1,6 @@
# Retrospective - Epic Completion Review Workflow
name: "retrospective"
description: "Run after epic completion to review overall success, extract lessons learned, and explore if new information emerged that might impact the next epic"
author: "BMad"
description: "Post-epic review to extract lessons and assess success. Use when the user says 'run a retrospective' or 'lets retro the epic [epic]'"
config_source: "{project-root}/_bmad/bmm/config.yaml"
user_name: "{config_source}:user_name"

View File

@ -1,5 +1,5 @@
name: sprint-planning
description: "Generate and manage the sprint status tracking file for Phase 4 implementation, extracting all epics and stories from epic files and tracking their status through the development lifecycle"
description: "Generate sprint status tracking from epics. Use when the user says 'run sprint planning' or 'generate sprint plan'"
author: "BMad"
# Critical variables from config

View File

@ -1,6 +1,6 @@
# Sprint Status - Implementation Tracker
name: sprint-status
description: "Summarize sprint-status.yaml, surface risks, and route to the right implementation workflow."
description: "Summarize sprint status and surface risks. Use when the user says 'check sprint status' or 'show sprint status'"
author: "BMad"
# Critical variables from config

View File

@ -1,6 +1,6 @@
---
name: quick-dev
description: 'Flexible development - execute tech-specs OR direct instructions with optional planning.'
description: "Implement a Quick Tech Spec for small changes or features. Use when the user provides a quick tech spec and says 'implement this quick spec' or 'proceed with implementation of [quick tech spec]'"
---
# Quick Dev Workflow

View File

@ -1,6 +1,6 @@
---
name: quick-spec
description: Conversational spec engineering - ask questions, investigate code, produce implementation-ready tech-spec.
description: Very quick process to create implementation-ready quick specs for small changes or features. Use when the user says 'create a quick spec' or 'generate a quick tech spec'
main_config: '{project-root}/_bmad/bmm/config.yaml'
# Checkpoint handler paths

View File

@ -1,7 +1,7 @@
# Document Project Workflow Configuration
name: "document-project"
version: "1.2.0"
description: "Analyzes and documents brownfield projects by scanning codebase, architecture, and patterns to create comprehensive reference documentation for AI-assisted development"
description: "Document brownfield projects for AI context. Use when the user says 'document this project' or 'generate project docs'"
author: "BMad"
# Critical variables

View File

@ -1,6 +1,6 @@
---
name: generate-project-context
description: Creates a concise project-context.md file with critical rules and patterns that AI agents must follow when implementing code. Optimized for LLM context efficiency.
description: Create project-context.md with AI rules. Use when the user says 'generate project context' or 'create project context'
---
# Generate Project Context Workflow

View File

@ -1,7 +1,5 @@
# Quinn QA workflow: Automate
name: qa-automate
description: "Generate tests quickly for existing features using standard test patterns"
author: "BMad"
name: qa-generate-e2e-tests
description: "Generate end to end automated tests for existing features. Use when the user says 'create qa automated tests for [feature]'"
# Critical variables from config
config_source: "{project-root}/_bmad/bmm/config.yaml"

View File

@ -1,6 +1,6 @@
<task id="_bmad/core/tasks/editorial-review-prose.xml"
name="Editorial Review - Prose"
description="Clinical copy-editor that reviews text for communication issues">
description="Clinical copy-editor that reviews text for communication issues. Use when user says 'review for prose' or 'improve the prose'">
<objective>Review text for communication issues that impede comprehension and output suggested fixes in a three-column table</objective>

View File

@ -3,8 +3,7 @@
but no context except the content to review -->
<task id="_bmad/core/tasks/editorial-review-structure.xml"
name="Editorial Review - Structure"
description="Structural editor that proposes cuts, reorganization,
and simplification while preserving comprehension">
description="Structural editor that proposes cuts, reorganization, and simplification while preserving comprehension. Use when user requests 'structural review' or 'cohesive reivew' or 'editorial review of structure'.">
<objective>Review document structure and propose substantive changes
to improve clarity and flow-run this BEFORE copy editing</objective>
<inputs>

View File

@ -1,6 +1,6 @@
---
name: help
description: Get unstuck by showing what workflow steps come next or answering questions about what to do
description: "Analyzes what is done and the users query and offers advice on what to do next. Use if user says 'bmad-help what should I do next' or 'bmad-help what do I do now'"
---
# Task: BMAD Help

View File

@ -1,5 +1,5 @@
<task id="_bmad/core/tasks/index-docs" name="Index Docs"
description="Generates or updates an index.md of all documents in the specified directory">
description="Generates or updates an index.md to reference all docs in the folder. Use if user requests to 'create an index of all files [here]' or 'reindex the folder [here].">
<llm critical="true">
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i>
<i>DO NOT skip steps or change the sequence</i>

View File

@ -1,7 +1,8 @@
<!-- if possible, run this in a separate subagent or process with read access to the project,
but no context except the content to review -->
<task id="_bmad/core/tasks/review-adversarial-general.xml" name="Adversarial Review (General)">
<task id="_bmad/core/tasks/review-adversarial-general.xml" name="Adversarial Review (General)"
description="Perform a Cynical Review and produce a findings report. Use when the user requests a 'critical review of' or 'cynical review of' something.">
<objective>Cynically review content and produce findings</objective>
<inputs>

View File

@ -1,5 +1,5 @@
<task id="_bmad/core/tasks/shard-doc" name="Shard Document"
description="Splits large markdown documents into smaller, organized files based on level 2 (default) sections">
description="Splits large markdown documents into smaller, organized files based on level 2 (default) sections. Use if the user says 'Shard Document [document]'">
<objective>Split large markdown documents into smaller, organized files based on level 2 sections using @kayvan/markdown-tree-parser tool</objective>
<llm critical="true">

View File

@ -1,4 +1,5 @@
<task id="_bmad/core/workflows/advanced-elicitation/workflow.xml" name="Advanced Elicitation"
description="Push the LLM to reconsider refine and improve its recent output. Use when the user asks for 'advanced elicitation'"
methods="{project-root}/_bmad/core/workflows/advanced-elicitation/methods.csv"
agent-party="{project-root}/_bmad/_config/agent-manifest.csv">
<llm critical="true">

View File

@ -1,6 +1,6 @@
---
name: brainstorming
description: Facilitate interactive brainstorming sessions using diverse creative techniques and ideation methods
description: "Facilitate interactive brainstorming sessions using diverse creative techniques and ideation methods. Use when the user says 'help me brainstorm' or 'help me ideate'."
context_file: '' # Optional context file path for project-specific guidance
---

View File

@ -1,6 +1,6 @@
---
name: party-mode
description: Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations
description: "Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations. Use when user requests 'party mode' only."
---
# Party Mode Workflow

View File

@ -0,0 +1,238 @@
/**
* GitHub Copilot Installer Tests
*
* Tests for the GitHubCopilotSetup class methods:
* - loadModuleConfig: module-aware config loading
* - createTechWriterPromptContent: BMM-only tech-writer handling
* - generateCopilotInstructions: selectedModules deduplication
*
* Usage: node test/test-github-copilot-installer.js
*/
const path = require('node:path');
const fs = require('fs-extra');
const { GitHubCopilotSetup } = require('../tools/cli/installers/lib/ide/github-copilot');
// ANSI colors
const colors = {
reset: '\u001B[0m',
green: '\u001B[32m',
red: '\u001B[31m',
yellow: '\u001B[33m',
cyan: '\u001B[36m',
dim: '\u001B[2m',
};
let passed = 0;
let failed = 0;
/**
* Test helper: Assert condition
*/
function assert(condition, testName, errorMessage = '') {
if (condition) {
console.log(`${colors.green}${colors.reset} ${testName}`);
passed++;
} else {
console.log(`${colors.red}${colors.reset} ${testName}`);
if (errorMessage) {
console.log(` ${colors.dim}${errorMessage}${colors.reset}`);
}
failed++;
}
}
/**
* Test Suite
*/
async function runTests() {
console.log(`${colors.cyan}========================================`);
console.log('GitHub Copilot Installer Tests');
console.log(`========================================${colors.reset}\n`);
const tempDir = path.join(__dirname, 'temp-copilot-test');
try {
// Clean up any leftover temp directory
await fs.remove(tempDir);
await fs.ensureDir(tempDir);
const installer = new GitHubCopilotSetup();
// ============================================================
// Test Suite 1: loadModuleConfig
// ============================================================
console.log(`${colors.yellow}Test Suite 1: loadModuleConfig${colors.reset}\n`);
// Create mock bmad directory structure with multiple modules
const bmadDir = path.join(tempDir, '_bmad');
await fs.ensureDir(path.join(bmadDir, 'core'));
await fs.ensureDir(path.join(bmadDir, 'bmm'));
await fs.ensureDir(path.join(bmadDir, 'custom-module'));
// Create config files for each module
await fs.writeFile(path.join(bmadDir, 'core', 'config.yaml'), 'project_name: Core Project\nuser_name: CoreUser\n');
await fs.writeFile(path.join(bmadDir, 'bmm', 'config.yaml'), 'project_name: BMM Project\nuser_name: BmmUser\n');
await fs.writeFile(path.join(bmadDir, 'custom-module', 'config.yaml'), 'project_name: Custom Project\nuser_name: CustomUser\n');
// Test 1a: Load config with only core module (default)
const coreConfig = await installer.loadModuleConfig(bmadDir, ['core']);
assert(
coreConfig.project_name === 'Core Project',
'loadModuleConfig loads core config when only core installed',
`Got: ${coreConfig.project_name}`,
);
// Test 1b: Load config with bmm module (should prefer bmm over core)
const bmmConfig = await installer.loadModuleConfig(bmadDir, ['bmm', 'core']);
assert(bmmConfig.project_name === 'BMM Project', 'loadModuleConfig prefers bmm config over core', `Got: ${bmmConfig.project_name}`);
// Test 1c: Load config with custom module (should prefer custom over core)
const customConfig = await installer.loadModuleConfig(bmadDir, ['custom-module', 'core']);
assert(
customConfig.project_name === 'Custom Project',
'loadModuleConfig prefers custom module config over core',
`Got: ${customConfig.project_name}`,
);
// Test 1d: Load config with multiple non-core modules (first wins)
const multiConfig = await installer.loadModuleConfig(bmadDir, ['bmm', 'custom-module', 'core']);
assert(
multiConfig.project_name === 'BMM Project',
'loadModuleConfig uses first non-core module config',
`Got: ${multiConfig.project_name}`,
);
// Test 1e: Empty modules list uses default (core)
const defaultConfig = await installer.loadModuleConfig(bmadDir);
assert(
defaultConfig.project_name === 'Core Project',
'loadModuleConfig defaults to core when no modules specified',
`Got: ${defaultConfig.project_name}`,
);
// Test 1f: Non-existent module falls back to core
const fallbackConfig = await installer.loadModuleConfig(bmadDir, ['nonexistent', 'core']);
assert(
fallbackConfig.project_name === 'Core Project',
'loadModuleConfig falls back to core for non-existent modules',
`Got: ${fallbackConfig.project_name}`,
);
console.log('');
// ============================================================
// Test Suite 2: createTechWriterPromptContent (BMM-only)
// ============================================================
console.log(`${colors.yellow}Test Suite 2: createTechWriterPromptContent (BMM-only)${colors.reset}\n`);
// Test 2a: BMM tech-writer entry should generate content
const bmmTechWriterEntry = {
'agent-name': 'tech-writer',
module: 'bmm',
name: 'Write Document',
};
const bmmResult = installer.createTechWriterPromptContent(bmmTechWriterEntry);
assert(
bmmResult !== null && bmmResult.fileName === 'bmad-bmm-write-document',
'createTechWriterPromptContent generates content for BMM tech-writer',
`Got: ${bmmResult ? bmmResult.fileName : 'null'}`,
);
// Test 2b: Non-BMM tech-writer entry should return null
const customTechWriterEntry = {
'agent-name': 'tech-writer',
module: 'custom-module',
name: 'Write Document',
};
const customResult = installer.createTechWriterPromptContent(customTechWriterEntry);
assert(customResult === null, 'createTechWriterPromptContent returns null for non-BMM tech-writer', `Got: ${customResult}`);
// Test 2c: Core tech-writer entry should return null
const coreTechWriterEntry = {
'agent-name': 'tech-writer',
module: 'core',
name: 'Write Document',
};
const coreResult = installer.createTechWriterPromptContent(coreTechWriterEntry);
assert(coreResult === null, 'createTechWriterPromptContent returns null for core tech-writer', `Got: ${coreResult}`);
// Test 2d: Non-tech-writer BMM entry should return null
const nonTechWriterEntry = {
'agent-name': 'pm',
module: 'bmm',
name: 'Write Document',
};
const nonTechResult = installer.createTechWriterPromptContent(nonTechWriterEntry);
assert(nonTechResult === null, 'createTechWriterPromptContent returns null for non-tech-writer agents', `Got: ${nonTechResult}`);
// Test 2e: Unknown tech-writer command should return null
const unknownCmdEntry = {
'agent-name': 'tech-writer',
module: 'bmm',
name: 'Unknown Command',
};
const unknownResult = installer.createTechWriterPromptContent(unknownCmdEntry);
assert(unknownResult === null, 'createTechWriterPromptContent returns null for unknown commands', `Got: ${unknownResult}`);
console.log('');
// ============================================================
// Test Suite 3: selectedModules deduplication
// ============================================================
console.log(`${colors.yellow}Test Suite 3: selectedModules deduplication${colors.reset}\n`);
// We can't easily test generateCopilotInstructions directly without mocking,
// but we can verify the deduplication logic pattern
const testDedupe = (modules) => {
const installedModules = modules.length > 0 ? [...new Set(modules)] : ['core'];
return installedModules;
};
// Test 3a: Duplicate modules should be deduplicated
const dupeResult = testDedupe(['bmm', 'core', 'bmm', 'custom', 'core', 'custom']);
assert(
dupeResult.length === 3 && dupeResult.includes('bmm') && dupeResult.includes('core') && dupeResult.includes('custom'),
'Deduplication removes duplicate modules',
`Got: ${JSON.stringify(dupeResult)}`,
);
// Test 3b: Empty array defaults to core
const emptyResult = testDedupe([]);
assert(
emptyResult.length === 1 && emptyResult[0] === 'core',
'Empty modules array defaults to core',
`Got: ${JSON.stringify(emptyResult)}`,
);
// Test 3c: Order is preserved after deduplication (first occurrence wins)
const orderResult = testDedupe(['custom', 'bmm', 'custom', 'bmm']);
assert(
orderResult[0] === 'custom' && orderResult[1] === 'bmm',
'Deduplication preserves order (first occurrence)',
`Got: ${JSON.stringify(orderResult)}`,
);
} finally {
// Cleanup
await fs.remove(tempDir);
}
// Print summary
console.log(`${colors.cyan}========================================`);
console.log('Test Results:');
console.log(` Passed: ${passed}`);
console.log(` Failed: ${failed}`);
console.log(`========================================${colors.reset}\n`);
if (failed > 0) {
console.log(`${colors.red}Some tests failed!${colors.reset}`);
process.exit(1);
} else {
console.log(`${colors.green}✨ All GitHub Copilot installer tests passed!${colors.reset}`);
}
}
runTests().catch((error) => {
console.error(`${colors.red}Test runner error:${colors.reset}`, error);
process.exit(1);
});

View File

@ -353,7 +353,6 @@ You must fully embody this agent's persona and follow all activation instruction
return `---
name: '{{name}}'
description: '{{description}}'
disable-model-invocation: true
---
# {{name}}

View File

@ -166,7 +166,6 @@ class GitHubCopilotSetup extends BaseIdeSetup {
return `---
description: '${description.replaceAll("'", "''")}'
tools: ${toolsStr}
disable-model-invocation: true
---
You must fully embody this agent's persona and follow all activation instructions exactly as specified.
@ -248,9 +247,9 @@ You must fully embody this agent's persona and follow all activation instruction
*/
createWorkflowPromptContent(entry, workflowFile, toolsStr) {
const description = this.escapeYamlSingleQuote(this.createPromptDescription(entry.name));
// bmm/config.yaml is safe to hardcode here: these prompts are only generated when
// bmad-help.csv exists (bmm module data), so bmm is guaranteed to be installed.
const configLine = `1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables`;
// Use the module from the bmad-help.csv entry to reference the correct config.yaml
const configModule = entry.module || 'core';
const configLine = `1. Load {project-root}/${this.bmadFolderName}/${configModule}/config.yaml and store ALL fields as session variables`;
let body;
if (workflowFile.endsWith('.yaml')) {
@ -325,11 +324,13 @@ ${body}
/**
* Create prompt content for tech-writer agent-only commands (Pattern C)
* Tech-writer is BMM-specific - these commands only work with the BMM module.
* @param {Object} entry - bmad-help.csv row
* @returns {Object|null} { fileName, content } or null if not a tech-writer command
*/
createTechWriterPromptContent(entry) {
if (entry['agent-name'] !== 'tech-writer') return null;
// Tech-writer is BMM-specific - only process entries from the bmm module
if (entry['agent-name'] !== 'tech-writer' || entry.module !== 'bmm') return null;
const techWriterCommands = {
'Write Document': { code: 'WD', file: 'bmad-bmm-write-document', description: 'Write document' },
@ -345,14 +346,16 @@ ${body}
const safeDescription = this.escapeYamlSingleQuote(cmd.description);
const toolsStr = this.getToolsForFile(`${cmd.file}.prompt.md`);
// Use the module from the bmad-help.csv entry to reference the correct paths
const configModule = entry.module || 'core';
const content = `---
description: '${safeDescription}'
agent: 'agent'
tools: ${toolsStr}
---
1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables
2. Load the full agent file from {project-root}/${this.bmadFolderName}/bmm/agents/tech-writer/tech-writer.md and activate the Paige (Technical Writer) persona
1. Load {project-root}/${this.bmadFolderName}/${configModule}/config.yaml and store ALL fields as session variables
2. Load the full agent file from {project-root}/${this.bmadFolderName}/${configModule}/agents/tech-writer/tech-writer.md and activate the Paige (Technical Writer) persona
3. Execute the ${entry.name} menu command (${cmd.code})
`;
@ -377,15 +380,15 @@ tools: ${toolsStr}
const agentPath = artifact.agentPath || artifact.relativePath;
const agentFilePath = `{project-root}/${this.bmadFolderName}/${agentPath}`;
// bmm/config.yaml is safe to hardcode: agent activators are only generated from
// bmm agent artifacts, so bmm is guaranteed to be installed.
// Use the agent's module to reference the correct config.yaml
const configModule = artifact.module || 'core';
return `---
description: '${safeDescription}'
agent: 'agent'
tools: ${toolsStr}
---
1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables
1. Load {project-root}/${this.bmadFolderName}/${configModule}/config.yaml and store ALL fields as session variables
2. Load the full agent file from ${agentFilePath}
3. Follow ALL activation instructions in the agent file
4. Display the welcome/greeting as instructed
@ -401,7 +404,13 @@ tools: ${toolsStr}
* @param {Map} agentManifest - Agent manifest data
*/
async generateCopilotInstructions(projectDir, bmadDir, agentManifest, options = {}) {
const configVars = await this.loadModuleConfig(bmadDir);
// Determine installed modules (excluding internal directories)
const selectedModules = options.selectedModules || [];
// Deduplicate selectedModules to prevent duplicate paths in generated markdown
const installedModules = selectedModules.length > 0 ? [...new Set(selectedModules)] : ['core'];
const configVars = await this.loadModuleConfig(bmadDir, installedModules);
// Filter to only non-core modules for display (core is always listed separately)
const nonCoreModules = installedModules.filter((m) => m !== 'core');
// Build the agents table from the manifest
let agentsTable = '| Agent | Persona | Title | Capabilities |\n|---|---|---|---|\n';
@ -428,6 +437,36 @@ tools: ${toolsStr}
}
const bmad = this.bmadFolderName;
// Build dynamic module paths based on installed modules
const moduleAgentPaths = nonCoreModules.map((m) => `\`${bmad}/${m}/agents/\``).join(', ');
const moduleWorkflowPaths = nonCoreModules.map((m) => `\`${bmad}/${m}/workflows/\``).join(', ');
const moduleConfigPaths = nonCoreModules.map((m) => `\`${bmad}/${m}/config.yaml\``).join(', ');
// Build agent definitions line
let agentDefsLine;
if (nonCoreModules.length > 0) {
agentDefsLine = `- **Agent definitions**: ${moduleAgentPaths} and \`${bmad}/core/agents/\` (core)`;
} else {
agentDefsLine = `- **Agent definitions**: \`${bmad}/core/agents/\``;
}
// Build workflow definitions line
let workflowDefsLine;
if (nonCoreModules.length > 0) {
workflowDefsLine = `- **Workflow definitions**: ${moduleWorkflowPaths} (organized by phase)`;
} else {
workflowDefsLine = `- **Workflow definitions**: \`${bmad}/core/workflows/\``;
}
// Build module configuration line
let moduleConfigLine;
if (nonCoreModules.length > 0) {
moduleConfigLine = `- **Module configuration**: ${moduleConfigPaths}`;
} else {
moduleConfigLine = `- **Module configuration**: (no non-core modules installed)`;
}
const bmadSection = `# BMAD Method — Project Instructions
## Project Configuration
@ -444,12 +483,12 @@ tools: ${toolsStr}
## BMAD Runtime Structure
- **Agent definitions**: \`${bmad}/bmm/agents/\` (BMM module) and \`${bmad}/core/agents/\` (core)
- **Workflow definitions**: \`${bmad}/bmm/workflows/\` (organized by phase)
${agentDefsLine}
${workflowDefsLine}
- **Core tasks**: \`${bmad}/core/tasks/\` (help, editorial review, indexing, sharding, adversarial review)
- **Core workflows**: \`${bmad}/core/workflows/\` (brainstorming, party-mode, advanced-elicitation)
- **Workflow engine**: \`${bmad}/core/tasks/workflow.xml\` (executes YAML-based workflows)
- **Module configuration**: \`${bmad}/bmm/config.yaml\`
${moduleConfigLine}
- **Core configuration**: \`${bmad}/core/config.yaml\`
- **Agent manifest**: \`${bmad}/_config/agent-manifest.csv\`
- **Workflow manifest**: \`${bmad}/_config/workflow-manifest.csv\`
@ -458,7 +497,7 @@ tools: ${toolsStr}
## Key Conventions
- Always load \`${bmad}/bmm/config.yaml\` before any agent activation or workflow execution
- Always load the agent/workflow's module \`config.yaml\` before activation or execution (each prompt file specifies which config to load)
- Store all config fields as session variables: \`{user_name}\`, \`{communication_language}\`, \`{output_folder}\`, \`{planning_artifacts}\`, \`{implementation_artifacts}\`, \`{project_knowledge}\`
- MD-based workflows execute directly load and follow the \`.md\` file
- YAML-based workflows require the workflow engine load \`workflow.xml\` first, then pass the \`.yaml\` config
@ -505,13 +544,15 @@ Type \`/bmad-\` in Copilot Chat to see all available BMAD workflows and agent ac
/**
* Load module config.yaml for template variables
* @param {string} bmadDir - BMAD installation directory
* @param {string[]} installedModules - List of installed modules to check for config
* @returns {Object} Config variables
*/
async loadModuleConfig(bmadDir) {
const bmmConfigPath = path.join(bmadDir, 'bmm', 'config.yaml');
const coreConfigPath = path.join(bmadDir, 'core', 'config.yaml');
async loadModuleConfig(bmadDir, installedModules = ['core']) {
// Build config paths from installed modules (non-core first, then core as fallback)
const nonCoreModules = installedModules.filter((m) => m !== 'core');
const configPaths = [...nonCoreModules.map((m) => path.join(bmadDir, m, 'config.yaml')), path.join(bmadDir, 'core', 'config.yaml')];
for (const configPath of [bmmConfigPath, coreConfigPath]) {
for (const configPath of configPaths) {
if (await fs.pathExists(configPath)) {
try {
const content = await fs.readFile(configPath, 'utf8');

View File

@ -176,7 +176,6 @@ class TaskToolCommandGenerator {
return `---
description: '${description.replaceAll("'", "''")}'
disable-model-invocation: true
---
# ${item.displayName || item.name}

View File

@ -1,7 +1,6 @@
---
name: '{{name}}'
description: '{{description}}'
disable-model-invocation: true
---
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.

View File

@ -1,7 +1,6 @@
---
name: '{{name}}'
description: '{{description}}'
disable-model-invocation: true
---
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.

View File

@ -1,7 +1,6 @@
---
name: '{{name}}'
description: '{{description}}'
disable-model-invocation: true
---
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:

View File

@ -1,7 +1,6 @@
---
name: '{{name}}'
description: '{{description}}'
disable-model-invocation: true
---
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!

View File

@ -1,6 +1,5 @@
---
description: '{{description}}'
disable-model-invocation: true
---
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:

View File

@ -1,6 +1,5 @@
---
description: '{{description}}'
disable-model-invocation: true
---
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{{workflow_path}}, READ its entire contents and follow its directions exactly!

View File

@ -51,7 +51,7 @@ function getMarkdownFiles(dir) {
if (entry.isDirectory()) {
walk(fullPath);
} else if (entry.isFile() && entry.name.endsWith('.md')) {
} else if (entry.isFile() && (entry.name.endsWith('.md') || entry.name.endsWith('.mdx'))) {
files.push(fullPath);
}
}
@ -120,10 +120,13 @@ function resolveLink(siteRelativePath, sourceFile) {
if (!resolved.startsWith(DOCS_ROOT + path.sep) && resolved !== DOCS_ROOT) return null;
if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) return resolved;
if (fs.existsSync(resolved + '.md')) return resolved + '.md';
// Directory: check for index.md
if (fs.existsSync(resolved + '.mdx')) return resolved + '.mdx';
// Directory: check for index.md or index.mdx
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
const indexFile = path.join(resolved, 'index.md');
const indexMdxFile = path.join(resolved, 'index.mdx');
if (fs.existsSync(indexFile)) return indexFile;
if (fs.existsSync(indexMdxFile)) return indexMdxFile;
}
return null;
}
@ -134,12 +137,17 @@ function resolveLink(siteRelativePath, sourceFile) {
}
if (checkPath.endsWith('/')) {
// Could be file.md or directory/index.md
const asFile = path.join(DOCS_ROOT, checkPath.slice(0, -1) + '.md');
// Could be file.md, file.mdx, or directory/index.md/mdx
const baseName = checkPath.slice(0, -1);
const asMd = path.join(DOCS_ROOT, baseName + '.md');
const asMdx = path.join(DOCS_ROOT, baseName + '.mdx');
const asIndex = path.join(DOCS_ROOT, checkPath, 'index.md');
const asIndexMdx = path.join(DOCS_ROOT, checkPath, 'index.mdx');
if (fs.existsSync(asFile)) return asFile;
if (fs.existsSync(asMd)) return asMd;
if (fs.existsSync(asMdx)) return asMdx;
if (fs.existsSync(asIndex)) return asIndex;
if (fs.existsSync(asIndexMdx)) return asIndexMdx;
return null;
}
@ -151,10 +159,16 @@ function resolveLink(siteRelativePath, sourceFile) {
const withMd = direct + '.md';
if (fs.existsSync(withMd)) return withMd;
// Directory without trailing slash: check for index.md
// Try with .mdx extension
const withMdx = direct + '.mdx';
if (fs.existsSync(withMdx)) return withMdx;
// Directory without trailing slash: check for index.md or index.mdx
if (fs.existsSync(direct) && fs.statSync(direct).isDirectory()) {
const indexFile = path.join(direct, 'index.md');
const indexMdxFile = path.join(direct, 'index.mdx');
if (fs.existsSync(indexFile)) return indexFile;
if (fs.existsSync(indexMdxFile)) return indexMdxFile;
}
return null;

View File

@ -90,6 +90,7 @@ export default defineConfig({
// Sidebar configuration (Diataxis structure)
sidebar: [
{ label: 'Welcome', slug: 'index' },
{ label: 'Roadmap', slug: 'roadmap' },
{
label: 'Tutorials',
collapsed: false,

View File

@ -101,11 +101,19 @@ export function findFirstDelimiter(str) {
/** Walk up from a file path to find the content docs directory. */
export function detectContentDir(filePath) {
const segments = filePath.split(path.sep);
// Look for src/content/docs in the path
// Look for src/content/docs in the path (standard Astro)
for (let i = segments.length - 1; i >= 2; i--) {
if (segments[i - 2] === 'src' && segments[i - 1] === 'content' && segments[i] === 'docs') {
return segments.slice(0, i + 1).join(path.sep);
}
}
// Also check for a standalone 'docs' directory (BMAD project structure)
// Path format: .../bmm/docs/file.mdx or .../bmm/website/...
for (let i = segments.length - 1; i >= 0; i--) {
if (segments[i] === 'docs') {
// Found docs directory - use its parent as the content root
return segments.slice(0, i + 1).join(path.sep);
}
}
return null;
}

View File

@ -507,3 +507,299 @@ blockquote {
padding-right: 3rem;
}
}
/* ============================================
ROADMAP STYLES
============================================ */
.roadmap-container {
--color-planned: #6366f1;
--color-in-progress: #10b981;
--color-exploring: #f59e0b;
--color-bg-card: rgba(255, 255, 255, 0.03);
--color-border: rgba(255, 255, 255, 0.1);
}
.dark .roadmap-container {
--color-bg-card: rgba(255, 255, 255, 0.03);
--color-border: rgba(255, 255, 255, 0.1);
}
.light .roadmap-container {
--color-bg-card: rgba(0, 0, 0, 0.02);
--color-border: rgba(0, 0, 0, 0.1);
}
.roadmap-legend {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
justify-content: center;
margin: 2rem 0;
padding: 1rem 1.5rem;
background: var(--color-bg-card);
border: 1px solid var(--color-border);
border-radius: 12px;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
}
.legend-dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.legend-dot.planned { background: var(--color-planned); }
.legend-dot.in-progress { background: var(--color-in-progress); }
.legend-dot.exploring { background: var(--color-exploring); }
.roadmap-timeline {
position: relative;
max-width: 1000px;
margin: 3rem auto;
padding: 0 1rem;
}
.roadmap-timeline::before {
content: '';
position: absolute;
left: 50%;
top: 0;
bottom: 0;
width: 3px;
background: linear-gradient(to bottom, var(--color-in-progress), var(--color-planned), var(--color-exploring));
transform: translateX(-50%);
border-radius: 3px;
}
.roadmap-item {
position: relative;
margin-bottom: 3rem;
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 2rem;
align-items: start;
}
.roadmap-item:nth-child(odd) .roadmap-card {
grid-column: 1;
}
.roadmap-item:nth-child(even) .roadmap-card {
grid-column: 3;
}
.roadmap-marker {
grid-column: 2;
width: 20px;
height: 20px;
border-radius: 50%;
border: 4px solid var(--starlight-canvas-bg);
background: var(--color-in-progress);
position: relative;
z-index: 1;
box-shadow: 0 0 0 4px var(--color-border);
}
.roadmap-item.in-progress .roadmap-marker { background: var(--color-in-progress); }
.roadmap-item.planned .roadmap-marker { background: var(--color-planned); }
.roadmap-item.exploring .roadmap-marker { background: var(--color-exploring); }
.roadmap-item:nth-child(odd) .roadmap-content {
grid-column: 1;
text-align: right;
}
.roadmap-item:nth-child(even) .roadmap-content {
grid-column: 3;
text-align: left;
}
.roadmap-card {
background: var(--color-bg-card);
border: 1px solid var(--color-border);
border-radius: 16px;
padding: 1.5rem;
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.roadmap-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
border-color: var(--color-in-progress);
}
.roadmap-card.planned:hover { border-color: var(--color-planned); }
.roadmap-card.exploring:hover { border-color: var(--color-exploring); }
.roadmap-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1rem;
}
.roadmap-item:nth-child(odd) .roadmap-header {
flex-direction: row-reverse;
}
.roadmap-badge {
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.roadmap-badge.in-progress {
background: rgba(16, 185, 129, 0.15);
color: #10b981;
}
.roadmap-badge.planned {
background: rgba(99, 102, 241, 0.15);
color: #6366f1;
}
.roadmap-badge.exploring {
background: rgba(245, 158, 11, 0.15);
color: #f59e0b;
}
.roadmap-title {
font-size: 1.25rem;
font-weight: 700;
margin: 0;
}
.roadmap-description {
color: var(--slate-color-500);
margin-bottom: 1rem;
line-height: 1.6;
}
.roadmap-features {
list-style: none;
padding: 0;
margin: 0;
}
.roadmap-features li {
padding: 0.5rem 0;
padding-left: 1.5rem;
position: relative;
font-size: 0.9rem;
color: var(--slate-color-400);
}
.roadmap-features li::before {
content: '→';
position: absolute;
left: 0;
color: var(--color-in-progress);
}
.roadmap-item.planned .roadmap-features li::before { color: var(--color-planned); }
.roadmap-item.exploring .roadmap-features li::before { color: var(--color-exploring); }
.roadmap-section-title {
text-align: center;
font-size: 1.5rem;
font-weight: 700;
margin: 3rem 0 2rem;
padding: 1rem;
background: linear-gradient(135deg, var(--color-in-progress), var(--color-planned));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.roadmap-future {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
align-items: stretch;
gap: 1.5rem;
margin-top: 3rem;
padding: 2rem;
background: var(--color-bg-card);
border: 1px solid var(--color-border);
border-radius: 16px;
}
.roadmap-future-card {
padding: 1.5rem;
border-radius: 12px;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(245, 158, 11, 0.05));
border: 1px solid var(--color-border);
transition: transform 0.2s ease;
display: flex;
flex-direction: column;
min-height: 140px;
}
.roadmap-future-card h4 {
margin: 0 0 0.5rem 0;
}
.roadmap-future-card p {
margin: 0;
}
.roadmap-future-card:hover {
transform: scale(1.02);
}
.roadmap-future-card h4 {
margin: 0 0 0.5rem;
font-size: 1.1rem;
color: var(--color-planned);
}
.roadmap-future-card p {
margin: 0;
font-size: 0.9rem;
color: var(--slate-color-400);
}
.roadmap-emoji {
font-size: 1.5rem;
margin-bottom: 0.5rem;
display: block;
}
@media (max-width: 768px) {
.roadmap-timeline::before {
left: 20px;
}
.roadmap-item {
grid-template-columns: auto 1fr;
gap: 1rem;
}
.roadmap-item:nth-child(odd) .roadmap-card,
.roadmap-item:nth-child(even) .roadmap-card {
grid-column: 2;
}
.roadmap-item:nth-child(odd) .roadmap-content,
.roadmap-item:nth-child(even) .roadmap-content {
grid-column: 2;
text-align: left;
}
.roadmap-marker {
grid-column: 1;
grid-row: 1;
}
.roadmap-item:nth-child(odd) .roadmap-header {
flex-direction: row;
}
}