diff --git a/README.md b/README.md index 49a83e74..7f73e30d 100644 --- a/README.md +++ b/README.md @@ -1,237 +1,75 @@ -# BMad Method & BMad Core +# BMAD Method -[![Stable Version](https://img.shields.io/npm/v/bmad-method?color=blue&label=stable)](https://www.npmjs.com/package/bmad-method) -[![Alpha Version](https://img.shields.io/npm/v/bmad-method/alpha?color=orange&label=alpha)](https://www.npmjs.com/package/bmad-method) +[![Version](https://img.shields.io/npm/v/bmad-method?color=blue&label=version)](https://www.npmjs.com/package/bmad-method) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org) [![Discord](https://img.shields.io/badge/Discord-Join%20Community-7289da?logo=discord&logoColor=white)](https://discord.gg/gk8jAdXWmj) ---- +**Build More, Architect Dreams** β€” An AI-driven agile development framework with 21 specialized agents, 50+ guided workflows, and scale-adaptive intelligence that adjusts from bug fixes to enterprise systems. -
+## Why BMAD? -## πŸŽ‰ NEW: BMAD V6 Installer - Create & Share Custom Content! +Traditional AI tools do the thinking for you, producing average results. BMAD agents act as expert collaborators who guide you through structured workflows to bring out your best thinking. -The completely revamped **BMAD V6 installer** now includes built-in support for creating, installing, and sharing custom modules, agents, workflows, templates, and tools! Build your own AI solutions or share them with your team - and real soon, with the whole BMad Community througha verified community sharing portal! +- **Scale-Adaptive**: Automatically adjusts planning depth based on project complexity (Level 0-4) +- **Structured Workflows**: Grounded in agile best practices across analysis, planning, architecture, and implementation +- **Specialized Agents**: 12+ domain experts (PM, Architect, Developer, UX, Scrum Master, and more) +- **Complete Lifecycle**: From brainstorming to deployment, with just-in-time documentation -**✨ What's New:** +## Quick Start -- πŸ“¦ **Streamlined Custom Module Installation** - Package your custom content as installable modules -- πŸ€– **Agent & Workflow Sharing** - Distribute standalone agents and workflows -- πŸ”„ **Unitary Module Support** - Install individual components without full modules -- βš™οΈ **Dependency Management** - Automatic handling of module dependencies -- πŸ›‘οΈ **Update-Safe Customization** - Your custom content persists through updates - -**πŸ“š Learn More:** - -- [**Custom Content Overview**](http://docs.bmad-method.org/explanation/bmad-builder/custom-content-types/) - Discover all supported content types -- [**Installation Guide**](http://docs.bmad-method.org/how-to/installation/install-custom-modules/) - Learn to create and install custom content -- [**2 Very simple Custom Modules of questionable quality**](./samples/sample-custom-modules/README.md) - if you want to download and try to install a custom shared module, get an idea of how to bundle and share your own, or create your own personal agents, workflows and modules. - -
- ---- - -## AI-Driven Agile Development That Scales From Bug Fixes to Enterprise - -**Build More, Architect Dreams** (BMAD) with **21 specialized AI agents** across 4 official modules, and **50+ guided workflows** that adapt to your project's complexityβ€”from quick bug fixes to enterprise platforms, and new step file workflows that allow for incredibly long workflows to stay on the rails longer than ever before! - -Additionally - when we say 'Build More, Architect Dreams' - we mean it! The BMad Builder has landed, and now as of Alpha.15 is fully supported in the installation flow via NPX - custom stand along agents, workflows and the modules of your dreams! The community forge will soon open, endless possibility awaits! - -> **πŸš€ v6 is a MASSIVE upgrade from v4!** Complete architectural overhaul, scale-adaptive intelligence, visual workflows, and the powerful BMad Core framework. v4 users: this changes everything. [See what's new β†’](#whats-new-in-v6) - -> **πŸ“Œ v6 Alpha Status:** Near-beta quality with vastly improved stability. Documentation is being finalized. New videos coming soon to [BMadCode YouTube](https://www.youtube.com/@BMadCode). - -## 🎯 Why BMad Method? - -Unlike generic AI coding assistants, BMad Method provides **structured, battle-tested workflows** powered by specialized agents who understand agile development. Each agent has deep domain expertiseβ€”from product management to architecture to testingβ€”working together seamlessly. - -**✨ Key Benefits:** - -- **Scale-Adaptive Intelligence** - Automatically adjusts planning depth from bug fixes to enterprise systems -- **Complete Development Lifecycle** - Analysis β†’ Planning β†’ Architecture β†’ Implementation -- **Specialized Expertise** - 19 agents with specific roles (PM, Architect, Developer, UX Designer, etc.) -- **Proven Methodologies** - Built on agile best practices with AI amplification -- **IDE Integration** - Works with Claude Code, Cursor, Windsurf, VS Code - -## πŸ—οΈ The Power of BMad Core - -**BMad Method** is actually a sophisticated module built on top of **BMad Core** (**C**ollaboration **O**ptimized **R**eflection **E**ngine). This revolutionary architecture means: - -- **BMad Core** provides the universal framework for human-AI collaboration -- **BMad Method** leverages Core to deliver agile development workflows -- **BMad Builder** lets YOU create custom modules as powerful as BMad Method itself - -With **BMad Builder**, you can architect both simple agents and vastly complex domain-specific modules (legal, medical, finance, education, creative) that will soon be sharable in an **official community marketplace**. Imagine building and sharing your own specialized AI team! - -## πŸ“Š See It In Action - -

- BMad Method Workflow -

- -

- Complete BMad Method workflow showing all phases, agents, and decision points -

- -## πŸš€ Get Started in 3 Steps - -### 1. Install BMad Method +**Prerequisites**: [Node.js](https://nodejs.org) v20+ ```bash -# Install v6 RECOMMENDED npx bmad-method@alpha install ``` +Follow the installer prompts to configure your project. Then run: + ```bash -# Install v4 Legacy (not recommended if starting fresh) -npx bmad-method install -# OR -npx bmad-method@latest install -``` - - -### 2. Initialize Your Project - -Load any agent in your IDE and run: - -``` *workflow-init ``` -This analyzes your project and recommends the right workflow track. +This analyzes your project and recommends a track: -### 3. Choose Your Track +| Track | Best For | Time to First Story | +| --------------- | ------------------------- | ------------------- | +| **Quick Flow** | Bug fixes, small features | ~5 minutes | +| **BMad Method** | Products and platforms | ~15 minutes | +| **Enterprise** | Compliance-heavy systems | ~30 minutes | -BMad Method adapts to your needs with three intelligent tracks: +## Modules -| Track | Use For | Planning | Time to Start | -| ----------------- | ------------------------- | ----------------------- | ------------- | -| **⚑ Quick Flow** | Bug fixes, small features | Tech spec only | < 5 minutes | -| **πŸ“‹ BMad Method** | Products, platforms | PRD + Architecture + UX | < 15 minutes | -| **🏒 Enterprise** | Compliance, scale | Full governance suite | < 30 minutes | +| Module | Purpose | +| ------------------------------------- | -------------------------------------------------------- | +| **BMad Method (BMM)** | Core agile development with 34 workflows across 4 phases | +| **BMad Builder (BMB)** | Create custom agents and domain-specific modules | +| **Creative Intelligence Suite (CIS)** | Innovation, brainstorming, and problem-solving | -> **Not sure?** Run `*workflow-init` and let BMad analyze your project goal. +## Documentation -## πŸ”„ How It Works: 4-Phase Methodology +**[Full Documentation](http://docs.bmad-method.org)** β€” Tutorials, how-to guides, concepts, and reference -BMad Method guides you through a proven development lifecycle: +- [Getting Started Tutorial](http://docs.bmad-method.org/tutorials/getting-started/getting-started-bmadv6/) +- [Upgrading from Previous Versions](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/) -1. **πŸ“Š Analysis** (Optional) - Brainstorm, research, and explore solutions -2. **πŸ“ Planning** - Create PRDs, tech specs, or game design documents -3. **πŸ—οΈ Solutioning** - Design architecture, UX, and technical approach -4. **⚑ Implementation** - Story-driven development with continuous validation +## Community -Each phase has specialized workflows and agents working together to deliver exceptional results. +- [Discord](https://discord.gg/gk8jAdXWmj) β€” Get help, share ideas, collaborate +- [YouTube](https://www.youtube.com/@BMadCode) β€” Video tutorials and updates +- [GitHub Issues](https://github.com/bmad-code-org/BMAD-METHOD/issues) β€” Bug reports and feature requests +- [Discussions](https://github.com/bmad-code-org/BMAD-METHOD/discussions) β€” Community conversations -## πŸ€– Meet Your Team +## Contributing -**12 Specialized Agents** working in concert: +We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. -| Development | Architecture | Product | Leadership | -| ----------- | -------------- | ----------- | ------------ | -| Developer | Architect | PM | Scrum Master | -| UX Designer | Test Architect | Analyst | BMad Master | -| | | Tech Writer | | +## License -**Test Architect** integrates with `@seontechnologies/playwright-utils` for production-ready web app fixture-based utilities. - -Each agent brings deep expertise and can be customized to match your team's style. - -## πŸ“¦ What's Included - -### Official Modules - -- **BMad Method (BMM)** - Complete agile development framework - - 12 specialized agents - - 34 workflows across 4 phases - - Stand Along Quick Spec Flow for a streamlined simple implementation process - - [β†’ Documentation Hub](http://docs.bmad-method.org/explanation/bmm/) - -- **BMad Builder (BMB)** - Create custom agents and workflows - - Build anything from simple agents to complex modules - - Create domain-specific solutions (legal, medical, finance, education) - - [β†’ Builder Guide](http://docs.bmad-method.org/explanation/bmad-builder/) - -- **Creative Intelligence Suite (CIS)** - Innovation & problem-solving - - Brainstorming, design thinking, storytelling - - 5 creative facilitation workflows - - [β†’ Creative Workflows](http://docs.bmad-method.org/explanation/creative-intelligence/) - -### Key Features - -- **🎨 Customizable Agents** - Modify personalities, expertise, and communication styles -- **🌐 Multi-Language Support** - Separate settings for communication and code output -- **πŸ“„ Document Sharding** - 90% token savings for large projects -- **πŸ”„ Update-Safe** - Your customizations persist through updates -- **πŸš€ Web Bundles** - Use in ChatGPT, Claude Projects, or Gemini Gems - -## πŸ“š Documentation - -### Quick Links - -- **[Quick Start Guide](http://docs.bmad-method.org/tutorials/getting-started/getting-started-bmadv6/)** - 15-minute introduction -- **[Complete BMM Documentation](http://docs.bmad-method.org/explanation/bmm/)** - All guides and references -- **[Agent Customization](http://docs.bmad-method.org/how-to/customization/customize-agents/)** - Personalize your agents -- **[All Documentation](http://docs.bmad-method.org/)** - Complete documentation index - -### For v4 Users - -- **[v4 Documentation](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4/docs)** -- **[v4 to v6 Upgrade Guide](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)** - -## πŸ’¬ Community & Support - -- **[Discord Community](https://discord.gg/gk8jAdXWmj)** - Get help, share projects -- **[GitHub Issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)** - Report bugs, request features -- **[YouTube Channel](https://www.youtube.com/@BMadCode)** - Video tutorials and demos -- **[Web Bundles](https://bmad-code-org.github.io/bmad-bundles/)** - Pre-built agent bundles (Currently not functioning, reworking soon) -- **[Code of Conduct](.github/CODE_OF_CONDUCT.md)** - Community guidelines - -## πŸ› οΈ Development - -If you would like to contribute, first check the [CONTRIBUTING.md](CONTRIBUTING.md) for full development guidelines. - -## What's New in v6 - -**v6 represents a complete architectural revolution from v4:** - -### πŸš€ Major Upgrades - -- **BMad Core Framework** - Modular architecture enabling custom domain solutions -- **Scale-Adaptive Intelligence** - Automatic adjustment from bug fixes to enterprise -- **Visual Workflows** - Beautiful SVG diagrams showing complete methodology -- **BMad Builder Module** - Create and share your own AI agent teams -- **50+ Workflows** - Up from 20 in v4, covering every development scenario -- **19 Specialized Agents** - Enhanced with customizable personalities and expertise -- **Update-Safe Customization** - Your configs persist through all updates -- **Web Bundles** - Use agents in ChatGPT, Claude, and Gemini -- **Multi-Language Support** - Separate settings for communication and code -- **Document Sharding** - 90% token savings for large projects - -### πŸ”„ For v4 Users - -- **[Comprehensive Upgrade Guide](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)** - Step-by-step migration -- **[v4 Documentation Archive](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4)** - Legacy reference -- Backwards compatibility where possible -- Smooth migration path with installer detection - -## πŸ“„ License - -MIT License - See [LICENSE](LICENSE) for details. - -**Trademarks:** BMadβ„’ and BMAD-METHODβ„’ are trademarks of BMad Code, LLC. - -Supported by:  DigitalOcean +MIT License β€” see [LICENSE](LICENSE) for details. --- -

- - Contributors - -

+**BMAD** and **BMAD-METHOD** are trademarks of BMad Code, LLC. -

- Built with ❀️ for the human-AI collaboration community -

+[![Contributors](https://contrib.rocks/image?repo=bmad-code-org/BMAD-METHOD)](https://github.com/bmad-code-org/BMAD-METHOD/graphs/contributors) diff --git a/docs/explanation/features/web-bundles.md b/docs/explanation/features/web-bundles.md index aeef17e1..3cf6212c 100644 --- a/docs/explanation/features/web-bundles.md +++ b/docs/explanation/features/web-bundles.md @@ -33,5 +33,3 @@ Web bundles package BMad agents as self-contained files that work in Gemini Gems - Some quality reduction vs local usage - Less convenient than full local installation - Limited to agent capabilities (no workflow file access) - -[← Back to Core Concepts](../index.md) diff --git a/docs/how-to/customization/index.md b/docs/how-to/customization/index.md index 12c3eca1..c66f4f34 100644 --- a/docs/how-to/customization/index.md +++ b/docs/how-to/customization/index.md @@ -25,5 +25,3 @@ Replace or extend workflow steps to create tailored processes. (Coming soon) --- **Next:** Read the [Agent Customization Guide](./customize-agents.md) to start personalizing your agents. - -[← Back to Core Concepts](../index.md) diff --git a/docs/index.md b/docs/index.md index a43bddda..484852d4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ --- -title: Welcome to BMad +title: Welcome to the BMad Method --- -BMad (**B**uild **M**ore, **A**rchitect **D**reams) is an AI-driven development framework that helps you build software faster and smarter. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexityβ€”whether you're fixing a bug or building an enterprise platform. +The BMad Method (**B**reakthrough **M**ethod of **A**gile AI **D**riven Development) is an AI-driven development framework that helps you build software faster and smarter. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexityβ€”whether you're fixing a bug or building an enterprise platform. If you're comfortable working with AI coding assistants like Claude, Cursor, or GitHub Copilot, you're ready to get started. @@ -12,8 +12,7 @@ If you're comfortable working with AI coding assistants like Claude, Cursor, or The fastest way to understand BMad is to try it. Choose a tutorial to walk through your first project in about 10 minutes. -- **[Get Started with v4 (Stable)](./tutorials/getting-started/getting-started-bmadv4.md)** β€” Production-ready version with battle-tested workflows -- **[Try v6 (Alpha)](./tutorials/getting-started/getting-started-bmadv6.md)** β€” Latest features, still in active development +- **[Get Started with BMad](./tutorials/getting-started/getting-started-bmadv6.md)** β€” Latest features, still in active development :::tip[Already familiar with AI-assisted development?] Feel free to skip around. Use the sidebar to jump to any topic, or check out [What Are Agents?](./explanation/core-concepts/what-are-agents.md) to understand how BMad organizes its AI personas. @@ -25,12 +24,12 @@ Feel free to skip around. Use the sidebar to jump to any topic, or check out [Wh These docs are organized into four sections based on what you're trying to do: -| Section | Purpose | -|---------|---------| -| **[Tutorials](./tutorials/index.md)** | Learning-oriented. Step-by-step guides that walk you through building something. Start here if you're new. | -| **[How-To Guides](./how-to/index.md)** | Task-oriented. Practical guides for solving specific problems. "How do I customize an agent?" lives here. | -| **[Explanation](./explanation/index.md)** | Understanding-oriented. Deep dives into concepts and architecture. Read when you want to know *why*. | -| **[Reference](./reference/index.md)** | Information-oriented. Technical specifications for agents, workflows, and configuration. | +| Section | Purpose | +| ----------------- | ---------------------------------------------------------------------------------------------------------- | +| **Tutorials** | Learning-oriented. Step-by-step guides that walk you through building something. Start here if you're new. | +| **How-To Guides** | Task-oriented. Practical guides for solving specific problems. "How do I customize an agent?" lives here. | +| **Explanation** | Understanding-oriented. Deep dives into concepts and architecture. Read when you want to know *why*. | +| **Reference** | Information-oriented. Technical specifications for agents, workflows, and configuration. | --- @@ -61,5 +60,4 @@ Get help, share what you're building, or contribute to BMad: Ready to dive in? Pick a tutorial and start building. -- **[Get Started with v4 (Stable)](./tutorials/getting-started/getting-started-bmadv4.md)** β€” Recommended for production projects -- **[Try v6 (Alpha)](./tutorials/getting-started/getting-started-bmadv6.md)** β€” Explore the latest features +- **[Get Started with BMadv6](./tutorials/getting-started/getting-started-bmadv6.md)** β€” Explore the latest features diff --git a/docs/tutorials/getting-started/getting-started-bmadv6.md b/docs/tutorials/getting-started/getting-started-bmadv6.md index 644e822d..6b8b6e11 100644 --- a/docs/tutorials/getting-started/getting-started-bmadv6.md +++ b/docs/tutorials/getting-started/getting-started-bmadv6.md @@ -1,15 +1,14 @@ --- -title: "Getting Started with BMad v6 Alpha" -description: Install BMad v6 Alpha and build your first project +title: "Getting Started with the BMad Method" +description: Install BMad and build your first project --- +**Upgrading from previous versions?** See the [Upgrade Guide](../../how-to/installation/upgrade-to-v6.md) instead. + +--- Build software faster using AI-powered workflows with specialized agents that guide you through planning, architecture, and implementation. -:::caution[Alpha Software] -BMad v6 is currently in **alpha**. Expect breaking changes, incomplete features, and evolving documentation. For a stable experience, use the [BMad v4 tutorial](./getting-started-bmadv4.md) instead. -::: - ## What You'll Learn - Install and initialize BMad Method for a new project @@ -36,12 +35,12 @@ BMad v6 is currently in **alpha**. Expect breaking changes, incomplete features, BMad helps you build software through guided workflows with specialized AI agents. The process follows four phases: -| Phase | Name | What Happens | -|-------|------|--------------| -| 1 | Analysis | Brainstorming, research, product brief *(optional)* | -| 2 | Planning | Create requirements (PRD or tech-spec) | -| 3 | Solutioning | Design architecture *(BMad Method/Enterprise only)* | -| 4 | Implementation | Build epic by epic, story by story | +| Phase | Name | What Happens | +| ----- | -------------- | --------------------------------------------------- | +| 1 | Analysis | Brainstorming, research, product brief *(optional)* | +| 2 | Planning | Create requirements (PRD or tech-spec) | +| 3 | Solutioning | Design architecture *(BMad Method/Enterprise only)* | +| 4 | Implementation | Build epic by epic, story by story | ![BMad Method Workflow - Standard Greenfield](./images/workflow-method-greenfield.svg) @@ -49,11 +48,11 @@ BMad helps you build software through guided workflows with specialized AI agent Based on your project's complexity, BMad offers three planning tracks: -| Track | Best For | Documents Created | -|-------|----------|-------------------| -| **Quick Flow** | Bug fixes, simple features, clear scope (1-15 stories) | Tech-spec only | -| **BMad Method** | Products, platforms, complex features (10-50+ stories) | PRD + Architecture + UX | -| **Enterprise** | Compliance, multi-tenant systems (30+ stories) | PRD + Architecture + Security + DevOps | +| Track | Best For | Documents Created | +| --------------- | ------------------------------------------------------ | -------------------------------------- | +| **Quick Flow** | Bug fixes, simple features, clear scope (1-15 stories) | Tech-spec only | +| **BMad Method** | Products, platforms, complex features (10-50+ stories) | PRD + Architecture + UX | +| **Enterprise** | Compliance, multi-tenant systems (30+ stories) | PRD + Architecture + Security + DevOps | :::note Story counts are guidance, not definitions. Choose your track based on planning needs, not story math. @@ -166,12 +165,12 @@ Load the **SM agent** and run `sprint-planning`. This creates `sprint-status.yam For each story, repeat this cycle with fresh chats: -| Step | Agent | Workflow | Purpose | -|------|-------|----------|---------| -| 1 | SM | `create-story` | Create story file from epic | -| 2 | DEV | `dev-story` | Implement the story | -| 3 | TEA | `automate` | Generate guardrail tests *(optional)* | -| 4 | DEV | `code-review` | Quality validation *(recommended)* | +| Step | Agent | Workflow | Purpose | +| ---- | ----- | -------------- | ------------------------------------- | +| 1 | SM | `create-story` | Create story file from epic | +| 2 | DEV | `dev-story` | Implement the story | +| 3 | TEA | `automate` | Generate guardrail tests *(optional)* | +| 4 | DEV | `code-review` | Quality validation *(recommended)* | After completing all stories in an epic, load the **SM agent** and run `retrospective`. @@ -200,18 +199,18 @@ your-project/ ## Quick Reference -| Command | Agent | Purpose | -|---------|-------|---------| -| `*workflow-init` | Analyst | Initialize a new project | -| `*workflow-status` | Any | Check progress and next steps | -| `*prd` | PM | Create Product Requirements Document | -| `*create-architecture` | Architect | Create architecture document | -| `*create-epics-and-stories` | PM | Break down PRD into epics | -| `*implementation-readiness` | Architect | Validate planning cohesion | -| `*sprint-planning` | SM | Initialize sprint tracking | -| `*create-story` | SM | Create a story file | -| `*dev-story` | DEV | Implement a story | -| `*code-review` | DEV | Review implemented code | +| Command | Agent | Purpose | +| --------------------------- | --------- | ------------------------------------ | +| `*workflow-init` | Analyst | Initialize a new project | +| `*workflow-status` | Any | Check progress and next steps | +| `*prd` | PM | Create Product Requirements Document | +| `*create-architecture` | Architect | Create architecture document | +| `*create-epics-and-stories` | PM | Break down PRD into epics | +| `*implementation-readiness` | Architect | Validate planning cohesion | +| `*sprint-planning` | SM | Initialize sprint tracking | +| `*create-story` | SM | Create a story file | +| `*dev-story` | DEV | Implement a story | +| `*code-review` | DEV | Review implemented code | ## Common Questions diff --git a/tools/audit-doc-links.js b/tools/audit-doc-links.js new file mode 100644 index 00000000..c028e90e --- /dev/null +++ b/tools/audit-doc-links.js @@ -0,0 +1,341 @@ +/** + * Documentation Link Auditor + * + * Scans markdown files in docs/ and: + * - Identifies broken relative links + * - Attempts to find where files may have moved + * - Generates a report with auto-fix suggestions + * - Outputs JSON for the fixer script to consume + * + * Usage: node tools/audit-doc-links.js + */ + +const { readFileSync, writeFileSync, existsSync } = require('node:fs'); +const { resolve, dirname, join, normalize, relative, basename } = require('node:path'); +const { glob } = require('glob'); + +const DOCS_DIR = resolve(process.cwd(), 'docs'); +const REPORT_PATH = resolve(__dirname, '.link-audit-report.json'); + +// Regex to match markdown links: [text](path) +const LINK_PATTERN = /\[([^\]]*)\]\(([^)]+)\)/g; + +// Colors for console output +const colors = { + reset: '\u001B[0m', + red: '\u001B[31m', + green: '\u001B[32m', + yellow: '\u001B[33m', + cyan: '\u001B[36m', + dim: '\u001B[2m', +}; + +/** + * Determines whether a link should be ignored during validation. + */ +function shouldIgnoreLink(link) { + return ( + link.startsWith('http://') || + link.startsWith('https://') || + link.startsWith('mailto:') || + link.startsWith('tel:') || + link.startsWith('/') || // Absolute paths handled by Astro routing + link.startsWith('#') // Same-file anchors + ); +} + +/** + * Remove fenced and inline code segments from Markdown content. + */ +function stripCodeBlocks(content) { + return content + .replaceAll(/```[\s\S]*?```/g, '') + .replaceAll(/~~~[\s\S]*?~~~/g, '') + .replaceAll(/`[^`\n]+`/g, ''); +} + +/** + * Parse link to extract path and anchor. + */ +function parseLink(link) { + const hashIndex = link.indexOf('#'); + if (hashIndex === -1) { + return { path: link, anchor: null }; + } + return { + path: link.slice(0, hashIndex) || null, + anchor: link.slice(hashIndex + 1), + }; +} + +/** + * Get line number for a character position in content. + */ +function getLineNumber(content, charIndex) { + const lines = content.slice(0, charIndex).split('\n'); + return lines.length; +} + +/** + * Extract links with their line numbers from markdown content. + */ +function extractLinksWithPositions(content, filePath) { + const strippedContent = stripCodeBlocks(content); + const links = []; + + let match; + LINK_PATTERN.lastIndex = 0; + + while ((match = LINK_PATTERN.exec(strippedContent)) !== null) { + const rawLink = match[2]; + if (!shouldIgnoreLink(rawLink)) { + const lineNumber = getLineNumber(strippedContent, match.index); + links.push({ + raw: rawLink, + text: match[1], + line: lineNumber, + fullMatch: match[0], + }); + } + } + + return links; +} + +/** + * Resolve a relative link path to an absolute file path. + */ +function resolveLink(fromFile, linkPath) { + if (!linkPath) return fromFile; + + const fromDir = dirname(fromFile); + let resolved = normalize(resolve(fromDir, linkPath)); + + // If link doesn't have extension, try .md + if (!resolved.endsWith('.md') && !resolved.endsWith('.mdx') && !existsSync(resolved)) { + const withMd = resolved + '.md'; + if (existsSync(withMd)) { + return withMd; + } + // Try as directory with index.md + const asIndex = join(resolved, 'index.md'); + if (existsSync(asIndex)) { + return asIndex; + } + } + + return resolved; +} + +/** + * Search for a file that may have moved. + * Uses multiple strategies to find the best match. + * + * @param {string} brokenPath - The original broken link path (e.g., "../tutorials/getting-started/foo.md") + * @returns {string[]} Array of matching absolute paths + */ +async function findMovedFile(brokenPath) { + const fileName = basename(brokenPath); + const searchName = fileName.endsWith('.md') ? fileName : `${fileName}.md`; + + // Strategy 1: Try to match with directory context + // e.g., for "tutorials/getting-started/foo.md", look for "*/getting-started/foo.md" + const pathParts = brokenPath.replace(/^\.\.?\/?/, '').split('/'); + if (pathParts.length >= 2) { + const parentDir = pathParts.at(-2); + const contextPattern = `**/${parentDir}/${searchName}`; + const contextMatches = await glob(contextPattern, { + cwd: DOCS_DIR, + absolute: true, + ignore: ['**/_*/**'], + }); + if (contextMatches.length > 0) { + return contextMatches; + } + } + + // Strategy 2: For non-index files, try filename-only match + // Skip this for index.md since it's too generic (exists in every directory) + if (searchName !== 'index.md') { + const matches = await glob(`**/${searchName}`, { + cwd: DOCS_DIR, + absolute: true, + ignore: ['**/_*/**'], + }); + return matches; + } + + // For index.md with no context match, return empty (truly missing) + return []; +} + +/** + * Calculate the relative path from source file to target file. + */ +function calculateRelativePath(fromFile, toFile) { + const fromDir = dirname(fromFile); + let relativePath = relative(fromDir, toFile); + + // Ensure path starts with ./ or ../ + if (!relativePath.startsWith('.')) { + relativePath = './' + relativePath; + } + + return relativePath; +} + +/** + * Main audit function. + */ +async function main() { + console.log('\n Documentation Link Auditor'); + console.log(' ==========================\n'); + console.log(' Scanning for broken links and attempting auto-resolution...\n'); + + // Find all markdown files, excluding underscore directories + const files = await glob('**/*.{md,mdx}', { + cwd: DOCS_DIR, + absolute: true, + ignore: ['**/_*/**'], + }); + + console.log(` Found ${files.length} markdown files to scan.\n`); + + const brokenLinks = []; + const autoFixable = []; + const needsReview = []; + const missing = []; + + // Track all files for fast lookup + const allFiles = new Set(files); + + for (const file of files) { + const content = readFileSync(file, 'utf-8'); + const links = extractLinksWithPositions(content, file); + const relativePath = relative(DOCS_DIR, file); + + for (const linkInfo of links) { + const { path: linkPath } = parseLink(linkInfo.raw); + + if (!linkPath) continue; // Same-file anchor only + + const targetFile = resolveLink(file, linkPath); + + // Check if target exists + if (!existsSync(targetFile)) { + const fileName = basename(linkPath); + + // Try to find the file elsewhere + const candidates = await findMovedFile(linkPath); + + const brokenInfo = { + sourceFile: relativePath, + sourceFileAbsolute: file, + line: linkInfo.line, + linkText: linkInfo.text, + originalLink: linkInfo.raw, + expectedTarget: linkPath, + fullMatch: linkInfo.fullMatch, + }; + + if (candidates.length === 1) { + // Found exactly one match - auto-fixable + const newPath = calculateRelativePath(file, candidates[0]); + brokenInfo.suggestedFix = newPath; + brokenInfo.foundAt = relative(DOCS_DIR, candidates[0]); + brokenInfo.status = 'auto-fixable'; + autoFixable.push(brokenInfo); + } else if (candidates.length > 1) { + // Multiple matches - needs manual review + brokenInfo.candidates = candidates.map((c) => relative(DOCS_DIR, c)); + brokenInfo.status = 'needs-review'; + needsReview.push(brokenInfo); + } else { + // No matches found + brokenInfo.status = 'missing'; + missing.push(brokenInfo); + } + + brokenLinks.push(brokenInfo); + } + } + } + + // Generate report + const report = { + timestamp: new Date().toISOString(), + summary: { + totalFiles: files.length, + totalBroken: brokenLinks.length, + autoFixable: autoFixable.length, + needsReview: needsReview.length, + missing: missing.length, + }, + autoFixable, + needsReview, + missing, + }; + + // Write JSON report + writeFileSync(REPORT_PATH, JSON.stringify(report, null, 2)); + + // Console output + console.log(' ' + '─'.repeat(50)); + console.log('\n SUMMARY\n'); + + if (brokenLinks.length === 0) { + console.log(` ${colors.green}βœ“${colors.reset} No broken links found!\n`); + process.exit(0); + } + + console.log(` Total broken links: ${colors.red}${brokenLinks.length}${colors.reset}`); + console.log(` β”œβ”€ Auto-fixable: ${colors.green}${autoFixable.length}${colors.reset}`); + console.log(` β”œβ”€ Needs review: ${colors.yellow}${needsReview.length}${colors.reset}`); + console.log(` └─ Missing: ${colors.red}${missing.length}${colors.reset}\n`); + + // Show auto-fixable + if (autoFixable.length > 0) { + console.log(` ${colors.green}AUTO-FIXABLE${colors.reset} (file found elsewhere)\n`); + for (const item of autoFixable) { + console.log(` ${colors.cyan}${item.sourceFile}${colors.reset}:${item.line}`); + console.log(` ${colors.dim}Link:${colors.reset} ${item.originalLink}`); + console.log(` ${colors.dim}Fix:${colors.reset} ${item.suggestedFix}`); + console.log(` ${colors.dim}Found at:${colors.reset} ${item.foundAt}\n`); + } + } + + // Show needs review + if (needsReview.length > 0) { + console.log(` ${colors.yellow}NEEDS REVIEW${colors.reset} (multiple matches found)\n`); + for (const item of needsReview) { + console.log(` ${colors.cyan}${item.sourceFile}${colors.reset}:${item.line}`); + console.log(` ${colors.dim}Link:${colors.reset} ${item.originalLink}`); + console.log(` ${colors.dim}Candidates:${colors.reset}`); + for (const candidate of item.candidates) { + console.log(` - ${candidate}`); + } + console.log(); + } + } + + // Show missing + if (missing.length > 0) { + console.log(` ${colors.red}MISSING${colors.reset} (file not found anywhere)\n`); + for (const item of missing) { + console.log(` ${colors.cyan}${item.sourceFile}${colors.reset}:${item.line}`); + console.log(` ${colors.dim}Link:${colors.reset} ${item.originalLink}\n`); + } + } + + console.log(' ' + '─'.repeat(50)); + console.log(`\n Report saved to: ${colors.dim}${relative(process.cwd(), REPORT_PATH)}${colors.reset}`); + console.log(`\n To fix auto-fixable links, run:`); + console.log(` node tools/fix-doc-links.js --apply\n`); + + process.exit(1); +} + +main().catch((error) => { + console.error('Error:', error.message); + process.exit(1); +}); diff --git a/tools/fix-doc-links.js b/tools/fix-doc-links.js new file mode 100644 index 00000000..2d700615 --- /dev/null +++ b/tools/fix-doc-links.js @@ -0,0 +1,172 @@ +/** + * Documentation Link Fixer + * + * Reads the audit report generated by audit-doc-links.js and applies fixes + * to broken links where a single match was found. + * + * Usage: + * node tools/fix-doc-links.js # Dry-run (preview changes) + * node tools/fix-doc-links.js --apply # Apply changes + */ + +const { readFileSync, writeFileSync, existsSync } = require('node:fs'); +const { resolve, relative } = require('node:path'); + +const REPORT_PATH = resolve(__dirname, '.link-audit-report.json'); + +// Colors for console output +const colors = { + reset: '\u001B[0m', + red: '\u001B[31m', + green: '\u001B[32m', + yellow: '\u001B[33m', + cyan: '\u001B[36m', + dim: '\u001B[2m', +}; + +/** + * Load the audit report. + */ +function loadReport() { + if (!existsSync(REPORT_PATH)) { + console.error(`\n ${colors.red}Error:${colors.reset} No audit report found.`); + console.error(` Run 'node tools/audit-doc-links.js' first.\n`); + process.exit(1); + } + + try { + const content = readFileSync(REPORT_PATH, 'utf-8'); + return JSON.parse(content); + } catch (error) { + console.error(`\n ${colors.red}Error:${colors.reset} Failed to parse audit report.`); + console.error(` ${error.message}\n`); + process.exit(1); + } +} + +/** + * Apply a fix to a file by replacing the original link with the suggested fix. + */ +function applyFix(filePath, originalLink, suggestedFix) { + const content = readFileSync(filePath, 'utf-8'); + + // Create the replacement pattern - we need to match the exact link in markdown syntax + // Original might have anchor, so we need to handle that + const originalWithoutAnchor = originalLink.split('#')[0]; + const suggestedWithoutAnchor = suggestedFix.split('#')[0]; + + // Also preserve any anchor from the original if the fix doesn't include one + let finalFix = suggestedFix; + if (originalLink.includes('#') && !suggestedFix.includes('#')) { + const anchor = originalLink.slice(originalLink.indexOf('#')); + finalFix = suggestedFix + anchor; + } + + // Replace the link - be careful to only replace inside markdown link syntax + const linkPattern = new RegExp(`\\]\\(${escapeRegex(originalLink)}\\)`, 'g'); + + const newContent = content.replace(linkPattern, `](${finalFix})`); + + if (newContent === content) { + return false; // No change made + } + + writeFileSync(filePath, newContent); + return true; +} + +/** + * Escape special regex characters in a string. + */ +function escapeRegex(string) { + return string.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); +} + +/** + * Main function. + */ +async function main() { + const args = process.argv.slice(2); + const applyChanges = args.includes('--apply'); + + console.log('\n Documentation Link Fixer'); + console.log(' ========================\n'); + + if (applyChanges) { + console.log(` ${colors.green}APPLYING CHANGES${colors.reset}\n`); + } else { + console.log(` ${colors.yellow}DRY RUN${colors.reset} - No files will be modified.`); + console.log(` Use --apply to apply changes.\n`); + } + + const report = loadReport(); + + if (report.autoFixable.length === 0) { + console.log(` ${colors.green}βœ“${colors.reset} No auto-fixable links found.\n`); + process.exit(0); + } + + console.log(` Found ${report.autoFixable.length} auto-fixable link(s).\n`); + + const fixed = []; + const failed = []; + + // Group fixes by file for efficiency + const byFile = {}; + for (const item of report.autoFixable) { + if (!byFile[item.sourceFileAbsolute]) { + byFile[item.sourceFileAbsolute] = []; + } + byFile[item.sourceFileAbsolute].push(item); + } + + for (const [filePath, items] of Object.entries(byFile)) { + const displayPath = relative(process.cwd(), filePath); + console.log(` ${colors.cyan}${displayPath}${colors.reset}`); + + for (const item of items) { + console.log(` Line ${item.line}:`); + console.log(` ${colors.dim}Old:${colors.reset} ${item.originalLink}`); + console.log(` ${colors.dim}New:${colors.reset} ${item.suggestedFix}`); + + if (applyChanges) { + try { + const success = applyFix(filePath, item.originalLink, item.suggestedFix); + if (success) { + console.log(` ${colors.green}βœ“ Fixed${colors.reset}`); + fixed.push(item); + } else { + console.log(` ${colors.yellow}⚠ No match found (may have been fixed already)${colors.reset}`); + } + } catch (error) { + console.log(` ${colors.red}βœ— Error: ${error.message}${colors.reset}`); + failed.push({ ...item, error: error.message }); + } + } + console.log(); + } + } + + // Summary + console.log(' ' + '─'.repeat(50)); + console.log('\n SUMMARY\n'); + + if (applyChanges) { + console.log(` Fixed: ${colors.green}${fixed.length}${colors.reset}`); + if (failed.length > 0) { + console.log(` Failed: ${colors.red}${failed.length}${colors.reset}`); + } + console.log(`\n Run 'node tools/audit-doc-links.js' to verify remaining issues.\n`); + } else { + console.log(` Would fix: ${colors.yellow}${report.autoFixable.length}${colors.reset} link(s)`); + console.log(`\n To apply these fixes, run:`); + console.log(` node tools/fix-doc-links.js --apply\n`); + } + + process.exit(failed.length > 0 ? 1 : 0); +} + +main().catch((error) => { + console.error('Error:', error.message); + process.exit(1); +});