Compare commits

...

21 Commits

Author SHA1 Message Date
Michael Pursifull d9813534bf
Merge 23f1a6fbeb into 323cd75efd 2026-02-01 17:38:27 -06:00
Michael Pursifull 23f1a6fbeb
Merge branch 'main' into feat/validate-file-refs 2026-02-01 17:38:26 -06:00
Brian Madison 323cd75efd x post premium example udpate for social post tool - do not add to changelog 2026-02-01 17:32:46 -06:00
Michael Pursifull 02385edf06
Merge branch 'main' into feat/validate-file-refs 2026-02-01 17:16:14 -06:00
Brian Madison b0c35d595f social post skill helper 2026-02-01 16:59:43 -06:00
Michael Pursifull 88a2ad7ed9
Merge branch 'main' into feat/validate-file-refs 2026-02-01 16:37:36 -06:00
Michael Pursifull 96595244e7
fix: address review feedback, add CI annotations and step summary
Address alexeyv's review findings on PR #1494:
- Fix exec-attr prefix handling for {_bmad}/ and bare _bmad/ paths
- Fix mapInstalledToSource fallback (remove phantom src/modules/ mapping)
- Switch extractYamlRefs to parseDocument() for YAML line numbers

Add CI integration (stories 2-1, 2-2):
- Emit ::warning annotations for broken refs and abs-path leaks
- Write markdown table to $GITHUB_STEP_SUMMARY
- Guard both behind environment variable checks

Harden CI output:
- escapeAnnotation() encodes %, \r, \n per GitHub Actions spec
- escapeTableCell() escapes pipe chars in step summary table
2026-02-01 16:27:38 -06:00
Brian Madison 0c46ef0be2 6.0.0-Beta.5 2026-02-01 16:13:27 -06:00
Brian Madison 79067a9427 changelog: v6.0.0-Beta.5
### 🎁 Features
* Add generate-project-context workflow
* Shard market research customer analysis

### 🐛 Bug Fixes
* Fix npm install peer dependency issues (PR #1476)
* Fix leaked source paths in PRD validation report (#1481)
* Fix orphaned market research customer analysis (#1486)
* Fix duplicate 2-letter brainstorming code (BS → BSP)
* Fix tech writer sidecar functionality (#1487)
* Fix relative paths in workflow steps (#1497, #1498)
* Fix party-mode workflow file extension (#1499)
* Fix generated slash commands (#1501)
* Fix agent scan and help CSV files
* Fix HELP_STEP placeholder replacement (#1437)

### 📚 Documentation
* Add exact slash commands to Getting Started guide (#1505)
* Remove .claude/commands from version control (#1506)

### 🔧 Maintenance
* Update Starlight to 0.37.5
* Add GitHub issue templates
2026-02-01 16:13:15 -06:00
Brian Madison fa01b4929b add helper skills 2026-02-01 16:01:29 -06:00
Michael Pursifull b7cfbefb6f
Merge remote-tracking branch 'upstream/main' into feat/validate-file-refs 2026-02-01 15:14:40 -06:00
Brian Madison 0bbb544521 remove skills that are now part of a plugin installer 2026-02-01 12:19:36 -06:00
Brian Madison c3d1bf3fe8 Fix duplicate 2-letter code - brainstorming now uses BSP
- BS -> BSP (Brainstorming in core module)

Resolves conflict with cis Brainstorming (BS).
Core is for project brainstorming, cis is general brainstorming.
2026-02-01 11:16:32 -06:00
Brian ba2f2df29a
Merge branch 'main' into feat/validate-file-refs 2026-02-01 08:06:58 -08:00
Alex Verkhovsky 1e8b17d367
Merge branch 'main' into feat/validate-file-refs 2026-02-01 00:19:49 -07:00
Michael Pursifull f4a473aea0
Merge branch 'main' into feat/validate-file-refs 2026-01-31 17:01:26 -06:00
Michael Pursifull 57aef6bea8
Merge branch 'main' into feat/validate-file-refs 2026-01-31 15:06:18 -06:00
Michael Pursifull 773da2820a
fix: correct verbose [OK]/[BROKEN] overlap and line number drift
Broken refs no longer print [OK] before [BROKEN] in --verbose mode.
Code block stripping now preserves newlines so offsetToLine() reports
accurate line numbers when code blocks precede broken references.
2026-01-31 15:03:50 -06:00
Michael Pursifull 961a892578
feat: add line numbers, fix utility/ path mapping, improve verbose output
- Add utility/ to direct path mapping (was incorrectly falling through
  to src/modules/utility/)
- Show line numbers for broken references in markdown files
- Show YAML key path for broken references in YAML files
- Print file headers in verbose mode for all files with refs
2026-01-31 15:03:06 -06:00
Michael Pursifull 1b863ee9c7
feat: strip JSON example blocks to reduce false-positive broken refs
Add stripJsonExampleBlocks() to the markdown reference extractor so
bare JSON example/template blocks (braces on their own lines) are
removed before pattern matching. This prevents paths inside example
data from being flagged as broken references.
2026-01-31 15:02:52 -06:00
Michael Pursifull 8a91b32315
feat: add cross-file reference validator for CI
Add tools/validate-file-refs.js that validates cross-file references
in BMAD source files (agents, workflows, tasks, steps). Catches broken
file paths, missing referenced files, wrong extensions, and absolute
path leaks before they reach users.

Addresses broken-file-ref and path-handling bug classes which account
for 25% of all historical bugs (59 closed issues, 129+ comments).

- Scans src/ for YAML, markdown, and XML files
- Validates {project-root}/_bmad/ references against source tree
- Checks relative path references, exec attributes, invoke-task tags
- Detects absolute path leaks (/Users/, /home/, C:\)
- Adds validate:refs npm script and CI step in quality.yaml
2026-01-31 15:02:42 -06:00
20 changed files with 1165 additions and 152 deletions

Binary file not shown.

View File

@ -0,0 +1,169 @@
---
name: changelog-social
description: Generate social media announcements for Discord, Twitter, and LinkedIn from the latest changelog entry. Use when user asks to create release announcements, social posts, or share changelog updates. Reads CHANGELOG.md in current working directory. Reference examples/ for tone and format.
disable-model-invocation: true
---
# Changelog Social
Generate engaging social media announcements from changelog entries.
## Workflow
### Step 1: Extract Changelog Entry
Read `./CHANGELOG.md` and extract the latest version entry. The changelog follows this format:
```markdown
## [VERSION]
### 🎁 Features
* **Title** — Description
### 🐛 Bug Fixes
* **Title** — Description
### 📚 Documentation
* **Title** — Description
### 🔧 Maintenance
* **Title** — Description
```
Parse:
- **Version number** (e.g., `6.0.0-Beta.5`)
- **Features** - New functionality, enhancements
- **Bug Fixes** - Fixes users will care about
- **Documentation** - New or improved docs
- **Maintenance** - Dependency updates, tooling improvements
### Step 2: Get Git Contributors
Use git log to find contributors since the previous version. Get commits between the current version tag and the previous one:
```bash
# Find the previous version tag first
git tag --sort=-version:refname | head -5
# Get commits between versions with PR numbers and authors
git log <previous-tag>..<current-tag> --pretty=format:"%h|%s|%an" --grep="#"
```
Extract PR numbers from commit messages that contain `#` followed by digits. Compile unique contributors.
### Step 3: Generate Discord Announcement
**Limit: 2,000 characters per message.** Split into multiple messages if needed.
Use this template style:
```markdown
🚀 **BMad vVERSION RELEASED!**
🎉 [Brief hype sentence]
🪥 **KEY HIGHLIGHT** - [One-line summary]
🎯 **CATEGORY NAME**
• Feature one - brief description
• Feature two - brief description
• Coming soon: Future teaser
🔧 **ANOTHER CATEGORY**
• Fix or feature
• Another item
📚 **DOCS OR OTHER**
• Item
• Item with link
🌟 **COMMUNITY PHILOSOPHY** (optional - include for major releases)
• Everything is FREE - No paywalls
• Knowledge shared, not sold
📊 **STATS**
X commits | Y PRs merged | Z files changed
🙏 **CONTRIBUTORS**
@username1 (X PRs!), @username2 (Y PRs!)
@username3, @username4, username5 + dependabot 🛡️
Community-driven FTW! 🌟
📦 **INSTALL:**
`npx bmad-method@VERSION install`
⭐ **SUPPORT US:**
🌟 GitHub: github.com/bmad-code-org/BMAD-METHOD/
📺 YouTube: youtube.com/@BMadCode
☕ Donate: buymeacoffee.com/bmad
🔥 **Next version tease!**
```
**Content Strategy:**
- Focus on **user impact** - what's better for them?
- Highlight **annoying bugs fixed** that frustrated users
- Show **new capabilities** that enable workflows
- Keep it **punchy** - use emojis and short bullets
- Add **personality** - excitement, humor, gratitude
### Step 4: Generate Twitter Post
**Limit: 25,000 characters per tweet (Premium).** With Premium, use a single comprehensive post matching the Discord style (minus Discord-specific formatting). Aim for 1,500-3,000 characters for better engagement.
**Threads are optional** — only use for truly massive releases where you want multiple engagement points.
See `examples/twitter-example.md` for the single-post Premium format.
## Content Selection Guidelines
**Include:**
- New features that change workflows
- Bug fixes for annoying/blocking issues
- Documentation that helps users
- Performance improvements
- New agents or workflows
- Breaking changes (call out clearly)
**Skip/Minimize:**
- Internal refactoring
- Dependency updates (unless user-facing)
- Test improvements
- Minor style fixes
**Emphasize:**
- "Finally fixed" issues
- "Faster" operations
- "Easier" workflows
- "Now supports" capabilities
## Examples
Reference example posts in `examples/` for tone and formatting guidance:
- **discord-example.md** — Full Discord announcement with emojis, sections, contributor shout-outs
- **twitter-example.md** — Twitter thread format (5 tweets max for major releases)
- **linkedin-example.md** — Professional post for major/minor releases with significant features
**When to use LinkedIn:**
- Major version releases (e.g., v6.0.0 Beta, v7.0.0)
- Minor releases with exceptional new features
- Community milestone announcements
Read the appropriate example file before generating to match the established style and voice.
## Output Format
Present both announcements in clearly labeled sections:
```markdown
## Discord Announcement
[paste Discord content here]
## Twitter Post
[paste Twitter content here]
```
Offer to make adjustments if the user wants different emphasis, tone, or content.

View File

@ -0,0 +1,53 @@
🚀 **BMad v6.0.0-alpha.23 RELEASED!**
🎉 Huge update - almost beta!
🪟 **WINDOWS INSTALLER FIXED** - Menu arrows issue should be fixed! CRLF & ESM problems resolved.
🎯 **PRD WORKFLOWS IMPROVED**
• Validation & Edit workflows added!
• PRD Cohesion check ensures document flows beautifully
• Coming soon: Use of subprocess optimization (context saved!)
• Coming soon: Final format polish step in all workflows - Human consumption OR hyper-optimized LLM condensed initially!
🔧 **WORKFLOW CREATOR & VALIDATOR**
• Subprocess support for advanced optimization
• Path violation checks ensure integrity
• Beyond error checking - offers optimization & flow suggestions!
📚 **NEW DOCS SITE** - docs.bmad-method.org
• Diataxis framework: Tutorials, How-To, Explanations, References
• Current docs still being revised
• Tutorials, blogs & explainers coming soon!
💡 **BRAINSTORMING REVOLUTION**
• 100+ idea goal (quantity-first!)
• Anti-bias protocol (pivot every 10 ideas)
• Chain-of-thought + simulated temperature prompts
• Coming soon: SubProcessing (on-the-fly sub agents)
🌟 **COMMUNITY PHILOSOPHY**
• Everything is FREE - No paywalls, no gated content
• Knowledge shared, not sold
• No premium tiers - full access to our ideas
📊 **27 commits | 217 links converted | 42+ docs created**
🙏 **17 Community PR Authors in this release!**
@lum (6 PRs!), @q00 (3 PRs!), @phil (2 PRs!)
@mike, @alex, @ramiz, @sjennings + dependabot 🛡️
Community-driven FTW! 🌟
📦 **INSTALL ALPHA:**
`npx bmad-method install`
⭐ **SUPPORT US:**
🌟 GitHub: github.com/bmad-code-org/BMAD-METHOD/
📺 YouTube: youtube.com/@BMadCode
🎤 **SPEAKING & MEDIA**
Available for conferences, podcasts, media appearances!
Topics: AI-Native Organizations (Any Industry), BMad Method
DM on Discord for inquiries!
🔥 **V6 Beta is DAYS away!** January 22nd ETA - new features such as xyz and abc bug fixes!

View File

@ -0,0 +1,49 @@
🚀 **Announcing BMad Method v6.0.0 Beta - AI-Native Agile Development Framework**
I'm excited to share that BMad Method, the open-source AI-driven agile development framework, is entering Beta! After 27 alpha releases and countless community contributions, we're approaching a major milestone.
**What's New in v6.0.0-alpha.23**
🪟 **Windows Compatibility Fixed**
We've resolved the installer issues that affected Windows users. The menu arrows problem, CRLF handling, and ESM compatibility are all resolved.
🎯 **Enhanced PRD Workflows**
Our Product Requirements Document workflows now include validation and editing capabilities, with a new cohesion check that ensures your documents flow beautifully. Subprocess optimization is coming soon to save even more context.
🔧 **Workflow Creator & Validator**
New tools for creating and validating workflows with subprocess support, path violation checks, and optimization suggestions that go beyond simple error checking.
📚 **New Documentation Platform**
We've launched docs.bmad-method.org using the Diataxis framework - providing clear separation between tutorials, how-to guides, explanations, and references. Our documentation is being continuously revised and expanded.
💡 **Brainstorming Revolution**
Our brainstorming workflows now use research-backed techniques: 100+ idea goals, anti-bias protocols, chain-of-thought reasoning, and simulated temperature prompts for higher divergence.
**Our Philosophy**
Everything in BMad Method is FREE. No paywalls, no gated content, no premium tiers. We believe knowledge should be shared, not sold. This is community-driven development at its finest.
**The Stats**
- 27 commits in this release
- 217 documentation links converted
- 42+ new documents created
- 17 community PR authors contributed
**Get Started**
```
npx bmad-method@alpha install
```
**Learn More**
- GitHub: github.com/bmad-code-org/BMAD-METHOD
- YouTube: youtube.com/@BMadCode
- Docs: docs.bmad-method.org
**What's Next?**
Beta is just days away with an ETA of January 22nd. We're also available for conferences, podcasts, and media appearances to discuss AI-Native Organizations and the BMad Method.
Have you tried BMad Method yet? I'd love to hear about your experience in the comments!
#AI #SoftwareDevelopment #Agile #OpenSource #DevTools #LLM #AgentEngineering

View File

@ -0,0 +1,55 @@
🚀 **BMad v6.0.0-alpha.23 RELEASED!**
Huge update - we're almost at Beta! 🎉
🪟 **WINDOWS INSTALLER FIXED** - Menu arrows issue should be fixed! CRLF & ESM problems resolved.
🎯 **PRD WORKFLOWS IMPROVED**
• Validation & Edit workflows added!
• PRD Cohesion check ensures document flows beautifully
• Coming soon: Subprocess optimization (context saved!)
• Coming soon: Final format polish step in all workflows
🔧 **WORKFLOW CREATOR & VALIDATOR**
• Subprocess support for advanced optimization
• Path violation checks ensure integrity
• Beyond error checking - offers optimization & flow suggestions!
📚 **NEW DOCS SITE** - docs.bmad-method.org
• Diataxis framework: Tutorials, How-To, Explanations, References
• Current docs still being revised
• Tutorials, blogs & explainers coming soon!
💡 **BRAINSTORMING REVOLUTION**
• 100+ idea goal (quantity-first!)
• Anti-bias protocol (pivot every 10 ideas)
• Chain-of-thought + simulated temperature prompts
• Coming soon: SubProcessing (on-the-fly sub agents)
🌟 **COMMUNITY PHILOSOPHY**
• Everything is FREE - No paywalls, no gated content
• Knowledge shared, not sold
• No premium tiers - full access to our ideas
📊 **27 commits | 217 links converted | 42+ docs created**
🙏 **17 Community PR Authors in this release!**
@lum (6 PRs!), @q00 (3 PRs!), @phil (2 PRs!)
@mike, @alex, @ramiz, @sjennings + dependabot 🛡️
Community-driven FTW! 🌟
📦 **INSTALL ALPHA:**
`npx bmad-method install`
⭐ **SUPPORT US:**
🌟 GitHub: github.com/bmad-code-org/BMAD-METHOD/
📺 YouTube: youtube.com/@BMadCode
🎤 **SPEAKING & MEDIA**
Available for conferences, podcasts, media appearances!
Topics: AI-Native Organizations (Any Industry), BMad Method
DM on Discord for inquiries!
🔥 **V6 Beta is DAYS away!** January 22nd ETA!
#AI #DevTools #Agile #OpenSource #LLM #AgentEngineering

View File

@ -0,0 +1,7 @@
---
name: draft-changelog
description: Analyzes changes since the last release and generates a draft changelog entry
disable-model-invocation: true
---
Read `prompts/instructions.md` and execute.

View File

@ -0,0 +1,58 @@
# Draft Changelog Execution
## Input
Project path (or run from project root)
## Step 1: Identify Current State
- Get the latest released tag
- Get current version
- Verify there are commits since the last release
## Step 2: Launch Explore Agent
Use `thoroughness: "very thorough"` to analyze all changes since the last release tag.
**Key: For each merge commit, look up the merged PR/issue that was closed.**
- Use `gh pr view` or git commit body to find the PR number
- Read the PR description and comments to understand full context
- Don't rely solely on commit merge messages - they lack context
**Analyze:**
1. **All merges/commits** since the last tag
2. **For each merge, read the original PR/issue** that was closed
3. **Files changed** with statistics
4. **Categorize changes:**
- 🎁 **Features** - New functionality, new agents, new workflows
- 🐛 **Bug Fixes** - Fixed bugs, corrected issues
- ♻️ **Refactoring** - Code improvements, reorganization
- 📚 **Documentation** - Docs updates, README changes
- 🔧 **Maintenance** - Dependency updates, tooling, infrastructure
- 💥 **Breaking Changes** - Changes that may affect users
**Provide:**
- Comprehensive summary of ALL changes with PR context
- Categorization of each change
- Identification of breaking changes
- Significance assessment (major/minor/trivial)
## Step 3: Generate Draft Changelog
Format:
```markdown
## v0.X.X - [Date]
* [Change 1 - categorized by type]
* [Change 2]
```
Guidelines:
- Present tense ("Fix bug" not "Fixed bug")
- Most significant changes first
- Group related changes
- Clear, concise language
- For breaking changes, clearly indicate impact
## Step 4: Present Draft
Show the draft with current version, last tag, commit count, and options to edit/retry.

View File

@ -0,0 +1,14 @@
# gh-triage
Fetches all GitHub issues via gh CLI and uses AI agents to deeply analyze, cluster, and prioritize issues.
## Usage
Run from within any BMad Method repository to triage issues.
## What It Does
1. Fetches all open issues via `gh issue list`
2. Splits issues into batches
3. Launches parallel agents to analyze each batch
4. Generates comprehensive triage report to `_bmad-output/triage-reports/`

View File

@ -1,158 +1,12 @@
---
name: gh-triage
description: Fetch all GitHub issues via gh CLI and use AI agents to deeply analyze, cluster, and prioritize issues with actual understanding. Use for issue triage, backlog cleanup, or when user mentions "issues", "triage", or "backlog".
description: Fetch all GitHub issues via gh CLI and use AI agents to deeply analyze, cluster, and prioritize issues
license: MIT
disable-model-invocation: true
metadata:
author: bmad-code-org
version: "3.0.0"
anthropic-internal: Core team issue triage tool for BMad Method repositories
min-github-cli-version: "2.0"
compatibility: Requires gh CLI, git repository, and BMad Method with Task tool support
---
# GitHub Issue Triage with AI Analysis
**CRITICAL RULES:**
- NEVER include time or effort estimates in output or recommendations
- Focus on WHAT needs to be done, not HOW LONG it takes
- Use Bash tool with gh CLI for all GitHub operations
## Execution Plan
You will perform GitHub issue triage using AI agents for deep analysis:
### Step 1: Fetch Issues
Use `gh issue list` to fetch all open issues from the current repository in JSON format.
### Step 2: Batch Creation
Split issues into batches of ~10 issues each for parallel analysis.
### Step 3: Parallel Agent Analysis
For EACH batch, use the Task tool with `subagent_type=general-purpose` to launch an agent with this prompt:
```
You are analyzing a batch of GitHub issues for deep understanding and triage.
**YOUR TASK:**
Read the issues in your batch and provide DEEP analysis:
1. **For EACH issue, analyze:**
- What is this ACTUALLY about? (beyond keywords)
- What component/system does it affect?
- What's the impact and severity?
- Is it a bug, feature request, or something else?
- What specific theme does it belong to?
2. **PRIORITY ASSESSMENT:**
- CRITICAL: Blocks users, security issues, data loss, broken installers
- HIGH: Major functionality broken, important features missing
- MEDIUM: Workarounds available, minor bugs, nice-to-have features
- LOW: Edge cases, cosmetic issues, questions
3. **RELATIONSHIPS:**
- Duplicates: Near-identical issues about the same problem
- Related: Issues connected by theme or root cause
- Dependencies: One issue blocks or requires another
**YOUR BATCH:**
[Paste the batch of issues here - each with number, title, body, labels]
**OUTPUT FORMAT (JSON only, no markdown):**
{
"issues": [
{
"number": 123,
"title": "issue title",
"deep_understanding": "2-3 sentences explaining what this is really about",
"affected_components": ["installer", "workflows", "docs"],
"issue_type": "bug/feature/question/tech-debt",
"priority": "CRITICAL/HIGH/MEDIUM/LOW",
"priority_rationale": "Why this priority level",
"theme": "installation/workflow/integration/docs/ide-support/etc",
"relationships": {
"duplicates_of": [456],
"related_to": [789, 101],
"blocks": [111]
}
}
],
"cross_repo_issues": [
{"number": 123, "target_repo": "bmad-builder", "reason": "about agent builder"}
],
"cleanup_candidates": [
{"number": 456, "reason": "v4-related/outdated/duplicate"}
],
"themes_found": {
"Installation Blockers": {
"count": 5,
"root_cause": "Common pattern if identifiable"
}
}
}
Return ONLY valid JSON. No explanations outside the JSON structure.
```
### Step 4: Consolidate & Generate Report
After all agents complete, create a comprehensive markdown report saved to `_bmad-output/triage-reports/triage-YYYY-MM-DD.md` with:
## Report Structure
### Executive Summary
- Total issues analyzed
- Issue count by priority (CRITICAL, HIGH, MEDIUM, LOW)
- Major themes discovered
- Top 5 critical issues requiring immediate attention
### Critical Issues (CRITICAL Priority)
For each CRITICAL issue:
- **#123 - [Issue Title](url)**
- **What it's about:** [Deep understanding]
- **Affected:** [Components]
- **Why Critical:** [Rationale]
- **Suggested Action:** [Specific action]
### High Priority Issues (HIGH Priority)
Same format as Critical, grouped by theme.
### Theme Clusters
For each major theme:
- **Theme Name** (N issues)
- **What connects these:** [Pattern]
- **Root cause:** [If identifiable]
- **Consolidated actions:** [Bulk actions if applicable]
- **Issues:** #123, #456, #789
### Relationships & Dependencies
- **Duplicates:** List pairs with `gh issue close` commands
- **Related Issues:** Groups of related issues
- **Dependencies:** Blocking relationships
### Cross-Repo Issues
Issues that should be migrated to other repositories (bmad-builder, bmad-module-creative-intelligence-suite, bmad-module-game-dev-studio, bmad-method-test-architecture-enterprise).
For each, provide:
```
gh issue close XXX --repo CURRENT_REPO --comment "This issue belongs in REPO. Please report at https://github.com/TARGET_REPO/issues/new"
```
### Cleanup Candidates
- **v4-related:** Deprecated version issues with close commands
- **Stale:** No activity >30 days
- **Low priority + old:** Low priority issues >60 days old
### Actionable Next Steps
Specific, prioritized actions:
1. [CRITICAL] Fix broken installer - affects all new users
2. [HIGH] Resolve Windows path escaping issues
3. [HIGH] Address workflow integration bugs
etc.
Include `gh` commands where applicable for bulk actions.
---
## Execute Now
Begin by fetching issues from the current repository and follow the plan above.
Read `prompts/instructions.md` and execute.

View File

@ -0,0 +1,60 @@
You are analyzing a batch of GitHub issues for deep understanding and triage.
**YOUR TASK:**
Read the issues in your batch and provide DEEP analysis:
1. **For EACH issue, analyze:**
- What is this ACTUALLY about? (beyond keywords)
- What component/system does it affect?
- What's the impact and severity?
- Is it a bug, feature request, or something else?
- What specific theme does it belong to?
2. **PRIORITY ASSESSMENT:**
- CRITICAL: Blocks users, security issues, data loss, broken installers
- HIGH: Major functionality broken, important features missing
- MEDIUM: Workarounds available, minor bugs, nice-to-have features
- LOW: Edge cases, cosmetic issues, questions
3. **RELATIONSHIPS:**
- Duplicates: Near-identical issues about the same problem
- Related: Issues connected by theme or root cause
- Dependencies: One issue blocks or requires another
**YOUR BATCH:**
[Paste the batch of issues here - each with number, title, body, labels]
**OUTPUT FORMAT (JSON only, no markdown):**
{
"issues": [
{
"number": 123,
"title": "issue title",
"deep_understanding": "2-3 sentences explaining what this is really about",
"affected_components": ["installer", "workflows", "docs"],
"issue_type": "bug/feature/question/tech-debt",
"priority": "CRITICAL/HIGH/MEDIUM/LOW",
"priority_rationale": "Why this priority level",
"theme": "installation/workflow/integration/docs/ide-support/etc",
"relationships": {
"duplicates_of": [456],
"related_to": [789, 101],
"blocks": [111]
}
}
],
"cross_repo_issues": [
{"number": 123, "target_repo": "bmad-builder", "reason": "about agent builder"}
],
"cleanup_candidates": [
{"number": 456, "reason": "v4-related/outdated/duplicate"}
],
"themes_found": {
"Installation Blockers": {
"count": 5,
"root_cause": "Common pattern if identifiable"
}
}
}
Return ONLY valid JSON. No explanations outside the JSON structure.

View File

@ -0,0 +1,74 @@
# GitHub Issue Triage with AI Analysis
**CRITICAL RULES:**
- NEVER include time or effort estimates in output or recommendations
- Focus on WHAT needs to be done, not HOW LONG it takes
- Use Bash tool with gh CLI for all GitHub operations
## Execution
### Step 1: Fetch Issues
Use `gh issue list --json number,title,body,labels` to fetch all open issues.
### Step 2: Batch Creation
Split issues into batches of ~10 issues each for parallel analysis.
### Step 3: Parallel Agent Analysis
For EACH batch, use the Task tool with `subagent_type=general-purpose` to launch an agent with prompt from `prompts/agent-prompt.md`
### Step 4: Consolidate & Generate Report
After all agents complete, create a comprehensive markdown report saved to `_bmad-output/triage-reports/triage-YYYY-MM-DD.md`
## Report Format
### Executive Summary
- Total issues analyzed
- Issue count by priority (CRITICAL, HIGH, MEDIUM, LOW)
- Major themes discovered
- Top 5 critical issues requiring immediate attention
### Critical Issues (CRITICAL Priority)
For each CRITICAL issue:
- **#123 - [Issue Title](url)**
- **What it's about:** [Deep understanding]
- **Affected:** [Components]
- **Why Critical:** [Rationale]
- **Suggested Action:** [Specific action]
### High Priority Issues (HIGH Priority)
Same format as Critical, grouped by theme.
### Theme Clusters
For each major theme:
- **Theme Name** (N issues)
- **What connects these:** [Pattern]
- **Root cause:** [If identifiable]
- **Consolidated actions:** [Bulk actions if applicable]
- **Issues:** #123, #456, #789
### Relationships & Dependencies
- **Duplicates:** List pairs with `gh issue close` commands
- **Related Issues:** Groups of related issues
- **Dependencies:** Blocking relationships
### Cross-Repo Issues
Issues that should be migrated to other repositories.
For each, provide:
```
gh issue close XXX --repo CURRENT_REPO --comment "This issue belongs in REPO. Please report at https://github.com/TARGET_REPO/issues/new"
```
### Cleanup Candidates
- **v4-related:** Deprecated version issues with close commands
- **Stale:** No activity >30 days
- **Low priority + old:** Low priority issues >60 days old
### Actionable Next Steps
Specific, prioritized actions:
1. [CRITICAL] Fix broken installer - affects all new users
2. [HIGH] Resolve Windows path escaping issues
3. [HIGH] Address workflow integration bugs
etc.
Include `gh` commands where applicable for bulk actions.

View File

@ -0,0 +1,24 @@
# release-module
Automates the complete release process for npm modules.
## Usage
Run from project root or pass project path:
```
bmad-utility-skills:release-module
```
## Prerequisite
First run `draft-changelog` to analyze changes and create a draft changelog.
## What It Does
1. Gets and confirms changelog entry
2. Confirms version bump type (patch/minor/major)
3. Updates CHANGELOG.md
4. Bumps version with `npm version`
5. Pushes git tag
6. Publishes to npm
7. Creates GitHub release

View File

@ -0,0 +1,7 @@
---
name: release-module
description: Automates the complete release process for npm modules - version bump, changelog, git tag, npm publish, GitHub release
disable-model-invocation: true
---
Read `prompts/instructions.md` and execute.

View File

@ -0,0 +1,73 @@
# Release BMad Module Execution
## Input
Project path (or run from project root)
## Execution Steps
### Step 1: Get Current State
- Verify git working tree is clean
- Get latest tag and current version
- Check for unpushed commits
### Step 2: Get Changelog Entry
Ask the user for the changelog entry (from draft-changelog skill or manual).
### Step 3: Confirm Changelog
Show project name, current version, proposed next version, and changelog. Get confirmation.
### Step 4: Confirm Version Bump Type
Ask what type of bump: patch, minor, major, prerelease, or custom.
### Step 5: Update CHANGELOG.md
Insert new entry at top, commit, and push.
### Step 6: Bump Version
Run `npm version` to update package.json, create commit, and create tag.
### Step 7: Push Tag
Push the new version tag to GitHub.
### Step 8: Publish to npm
Publish the package.
### Step 9: Create GitHub Release
Create release with changelog notes using `gh release create`.
### Step 10: Create Social Announcement
Create a social media announcement file at `_bmad-output/social/{repo-name}-release.md`.
Format:
```markdown
# {name} v{version} Released
## Highlights
{2-3 bullet points of key features/changes}
## Links
- GitHub: {release-url}
- npm: {npm-url}
```
### Step 11: Confirm Completion
Show npm, GitHub, and social announcement file paths.
## Error Handling
Stop immediately on any step failure. Inform user and suggest fix.
## Important Notes
- Wait for user confirmation before destructive operations
- Push changelog commit before version bump
- Use explicit directory paths in commands

View File

@ -113,3 +113,6 @@ jobs:
- name: Test agent compilation components
run: npm run test:install
- name: Validate file references
run: npm run validate:refs

View File

@ -1,5 +1,37 @@
# Changelog
## [6.0.0-Beta.5]
### 🎁 Features
* **Add generate-project-context workflow** — New 3-step workflow for project context generation, integrated with quick-flow-solo-dev agent
* **Shard market research customer analysis** — Refactor monolithic customer insights into 4-step detailed customer behavior analysis workflow
### 🐛 Bug Fixes
* **Fix npm install peer dependency issues** — Add `.npmrc` with `legacy-peer-deps=true`, update Starlight to 0.37.5, and add `--legacy-peer-deps` flag to module installer (PR #1476)
* **Fix leaked source paths in PRD validation report** — Replace absolute `/src/core/` paths with `{project-root}/_bmad/core/` (#1481)
* **Fix orphaned market research customer analysis** — Connect step-01-init to step-02-customer-behavior to complete workflow sharding (#1486)
* **Fix duplicate 2-letter brainstorming code** — Change BS to BSP to resolve conflict with cis Brainstorming module
* **Fix tech writer sidecar functionality** — Enable proper sidecar operation (#1487)
* **Fix relative paths in workflow steps** — Correct paths in step-11-polish (#1497) and step-e-04-complete (#1498)
* **Fix party-mode workflow file extension** — Correct extension in workflow.xml (#1499)
* **Fix generated slash commands** — Add `disable-model-invocation` to all generated commands (#1501)
* **Fix agent scan and help CSV files** — Correct module-help.csv entries
* **Fix HELP_STEP placeholder replacement** — Fix placeholder not replaced in compiled agents, fix hardcoded path, fix single quote (#1437)
### 📚 Documentation
* **Add exact slash commands to Getting Started guide** — Provide precise command examples for users (#1505)
* **Remove .claude/commands from version control** — Commands are generated, not tracked (#1506)
### 🔧 Maintenance
* **Update Starlight to 0.37.5** — Latest version with peer dependency compatibility
* **Add GitHub issue templates** — New bug-report.yaml and documentation.yaml templates
---
## [6.0.0-Beta.4]
### 🐛 Bug Fixes

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "bmad-method",
"version": "6.0.0-Beta.4",
"version": "6.0.0-Beta.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bmad-method",
"version": "6.0.0-Beta.4",
"version": "6.0.0-Beta.5",
"license": "MIT",
"dependencies": {
"@clack/prompts": "^0.11.0",

View File

@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "bmad-method",
"version": "6.0.0-Beta.4",
"version": "6.0.0-Beta.5",
"description": "Breakthrough Method of Agile AI-driven Development",
"keywords": [
"agile",
@ -49,6 +49,7 @@
"test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas",
"test:install": "node test/test-installation-components.js",
"test:schemas": "node test/test-agent-schema.js",
"validate:refs": "node tools/validate-file-refs.js",
"validate:schemas": "node tools/validate-agent-schema.js"
},
"lint-staged": {

View File

@ -1,5 +1,5 @@
module,phase,name,code,sequence,workflow-file,command,required,agent,options,description,output-location,outputs
core,anytime,Brainstorming,BS,,_bmad/core/workflows/brainstorming/workflow.md,bmad-brainstorming,false,analyst,,"Generate diverse ideas through interactive techniques. Use early in ideation phase or when stuck generating ideas.",{output_folder}/brainstorming/brainstorming-session-{{date}}.md,,
core,anytime,Brainstorming,BSP,,_bmad/core/workflows/brainstorming/workflow.md,bmad-brainstorming,false,analyst,,"Generate diverse ideas through interactive techniques. Use early in ideation phase or when stuck generating ideas.",{output_folder}/brainstorming/brainstorming-session-{{date}}.md,,
core,anytime,Party Mode,PM,,_bmad/core/workflows/party-mode/workflow.md,bmad-party-mode,false,party-mode facilitator,,"Orchestrate multi-agent discussions. Use when you need multiple agent perspectives or want agents to collaborate.",,
core,anytime,bmad-help,BH,,_bmad/core/tasks/help.md,bmad-help,false,,,"Get unstuck by showing what workflow steps come next or answering BMad Method questions.",,
core,anytime,Index Docs,ID,,_bmad/core/tasks/index-docs.xml,bmad-index-docs,false,,,"Create lightweight index for quick LLM scanning. Use when LLM needs to understand available docs without loading everything.",,

Can't render this file because it has a wrong number of fields in line 2.

480
tools/validate-file-refs.js Normal file
View File

@ -0,0 +1,480 @@
/**
* File Reference Validator
*
* Validates cross-file references in BMAD source files (agents, workflows, tasks, steps).
* Catches broken file paths, missing referenced files, and absolute path leaks.
*
* What it checks:
* - {project-root}/_bmad/ references in YAML and markdown resolve to real src/ files
* - Relative path references (./file.md, ../data/file.csv) point to existing files
* - exec="..." and <invoke-task> targets exist
* - Step metadata (thisStepFile, nextStepFile) references are valid
* - Load directives (Load: `./file.md`) target existing files
* - No absolute paths (/Users/, /home/, C:\) leak into source files
*
* What it does NOT check (deferred):
* - {installed_path} variable interpolation (self-referential, low risk)
* - {{mustache}} template variables (runtime substitution)
* - {config_source}:key dynamic YAML dereferences
*
* Usage:
* node tools/validate-file-refs.js # Warn on broken references (exit 0)
* node tools/validate-file-refs.js --strict # Fail on broken references (exit 1)
* node tools/validate-file-refs.js --verbose # Show all checked references
*
* Default mode is warning-only (exit 0) so adoption is non-disruptive.
* Use --strict when you want CI or pre-commit to enforce valid references.
*/
const fs = require('node:fs');
const path = require('node:path');
const yaml = require('yaml');
const PROJECT_ROOT = path.resolve(__dirname, '..');
const SRC_DIR = path.join(PROJECT_ROOT, 'src');
const VERBOSE = process.argv.includes('--verbose');
const STRICT = process.argv.includes('--strict');
// --- Constants ---
// File extensions to scan
const SCAN_EXTENSIONS = new Set(['.yaml', '.yml', '.md', '.xml']);
// Skip directories
const SKIP_DIRS = new Set(['node_modules', '_module-installer', '.git']);
// Pattern: {project-root}/_bmad/ references
const PROJECT_ROOT_REF = /\{project-root\}\/_bmad\/([^\s'"<>})\]`]+)/g;
// Pattern: {_bmad}/ shorthand references
const BMAD_SHORTHAND_REF = /\{_bmad\}\/([^\s'"<>})\]`]+)/g;
// Pattern: exec="..." attributes
const EXEC_ATTR = /exec="([^"]+)"/g;
// Pattern: <invoke-task> content
const INVOKE_TASK = /<invoke-task>([^<]+)<\/invoke-task>/g;
// Pattern: relative paths in quotes
const RELATIVE_PATH_QUOTED = /['"](\.\.\/?[^'"]+\.(?:md|yaml|yml|xml|json|csv|txt))['"]/g;
const RELATIVE_PATH_DOT = /['"](\.\/[^'"]+\.(?:md|yaml|yml|xml|json|csv|txt))['"]/g;
// Pattern: step metadata
const STEP_META = /(?:thisStepFile|nextStepFile|continueStepFile|skipToStepFile|altStepFile|workflowFile):\s*['"](\.[^'"]+)['"]/g;
// Pattern: Load directives
const LOAD_DIRECTIVE = /Load[:\s]+`(\.[^`]+)`/g;
// Pattern: absolute path leaks
const ABS_PATH_LEAK = /(?:\/Users\/|\/home\/|[A-Z]:\\\\)/;
// --- Output Escaping ---
function escapeAnnotation(str) {
return str.replaceAll('%', '%25').replaceAll('\r', '%0D').replaceAll('\n', '%0A');
}
function escapeTableCell(str) {
return String(str).replaceAll('|', String.raw`\|`);
}
// Path prefixes/patterns that only exist in installed structure, not in source
const INSTALL_ONLY_PATHS = ['_config/'];
// Files that are generated at install time and don't exist in the source tree
const INSTALL_GENERATED_FILES = ['config.yaml'];
// Variables that indicate a path is not statically resolvable
const UNRESOLVABLE_VARS = [
'{output_folder}',
'{value}',
'{timestamp}',
'{config_source}:',
'{installed_path}',
'{shared_path}',
'{planning_artifacts}',
'{research_topic}',
'{user_name}',
'{communication_language}',
'{epic_number}',
'{next_epic_num}',
'{epic_num}',
'{part_id}',
'{count}',
'{date}',
'{outputFile}',
'{nextStepFile}',
];
// --- File Discovery ---
function getSourceFiles(dir) {
const files = [];
function walk(currentDir) {
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
for (const entry of entries) {
if (SKIP_DIRS.has(entry.name)) continue;
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
walk(fullPath);
} else if (entry.isFile() && SCAN_EXTENSIONS.has(path.extname(entry.name))) {
files.push(fullPath);
}
}
}
walk(dir);
return files;
}
// --- Code Block Stripping ---
function stripCodeBlocks(content) {
return content.replaceAll(/```[\s\S]*?```/g, (m) => m.replaceAll(/[^\n]/g, ''));
}
function stripJsonExampleBlocks(content) {
// Strip bare JSON example blocks: { and } each on their own line.
// These are example/template data (not real file references).
return content.replaceAll(/^\{\s*\n(?:.*\n)*?^\}\s*$/gm, (m) => m.replaceAll(/[^\n]/g, ''));
}
// --- Path Mapping ---
function mapInstalledToSource(refPath) {
// Strip {project-root}/_bmad/ or {_bmad}/ prefix
let cleaned = refPath.replace(/^\{project-root\}\/_bmad\//, '').replace(/^\{_bmad\}\//, '');
// Also handle bare _bmad/ prefix (seen in some invoke-task)
cleaned = cleaned.replace(/^_bmad\//, '');
// Skip install-only paths (generated at install time, not in source)
if (isInstallOnly(cleaned)) return null;
// core/, bmm/, and utility/ are directly under src/
if (cleaned.startsWith('core/') || cleaned.startsWith('bmm/') || cleaned.startsWith('utility/')) {
return path.join(SRC_DIR, cleaned);
}
// Fallback: map directly under src/
return path.join(SRC_DIR, cleaned);
}
// --- Reference Extraction ---
function isResolvable(refStr) {
// Skip refs containing unresolvable runtime variables
if (refStr.includes('{{')) return false;
for (const v of UNRESOLVABLE_VARS) {
if (refStr.includes(v)) return false;
}
return true;
}
function isInstallOnly(cleanedPath) {
// Skip paths that only exist in the installed _bmad/ structure, not in src/
for (const prefix of INSTALL_ONLY_PATHS) {
if (cleanedPath.startsWith(prefix)) return true;
}
// Skip files that are generated during installation
const basename = path.basename(cleanedPath);
for (const generated of INSTALL_GENERATED_FILES) {
if (basename === generated) return true;
}
return false;
}
function extractYamlRefs(filePath, content) {
const refs = [];
let doc;
try {
doc = yaml.parseDocument(content);
} catch {
return refs; // Skip unparseable YAML (schema validator handles this)
}
function checkValue(value, range, keyPath) {
if (typeof value !== 'string') return;
if (!isResolvable(value)) return;
const line = range ? offsetToLine(content, range[0]) : undefined;
// Check for {project-root}/_bmad/ refs
const prMatch = value.match(/\{project-root\}\/_bmad\/[^\s'"<>})\]`]+/);
if (prMatch) {
refs.push({ file: filePath, raw: prMatch[0], type: 'project-root', line, key: keyPath });
}
// Check for {_bmad}/ refs
const bmMatch = value.match(/\{_bmad\}\/[^\s'"<>})\]`]+/);
if (bmMatch) {
refs.push({ file: filePath, raw: bmMatch[0], type: 'project-root', line, key: keyPath });
}
// Check for relative paths
const relMatch = value.match(/^\.\.?\/[^\s'"<>})\]`]+\.(?:md|yaml|yml|xml|json|csv|txt)$/);
if (relMatch) {
refs.push({ file: filePath, raw: relMatch[0], type: 'relative', line, key: keyPath });
}
}
function walkNode(node, keyPath) {
if (!node) return;
if (yaml.isMap(node)) {
for (const item of node.items) {
const key = item.key && item.key.value !== undefined ? item.key.value : '?';
const childPath = keyPath ? `${keyPath}.${key}` : String(key);
walkNode(item.value, childPath);
}
} else if (yaml.isSeq(node)) {
for (const [i, item] of node.items.entries()) {
walkNode(item, `${keyPath}[${i}]`);
}
} else if (yaml.isScalar(node)) {
checkValue(node.value, node.range, keyPath);
}
}
walkNode(doc.contents, '');
return refs;
}
function offsetToLine(content, offset) {
let line = 1;
for (let i = 0; i < offset && i < content.length; i++) {
if (content[i] === '\n') line++;
}
return line;
}
function extractMarkdownRefs(filePath, content) {
const refs = [];
const stripped = stripJsonExampleBlocks(stripCodeBlocks(content));
function runPattern(regex, type) {
regex.lastIndex = 0;
let match;
while ((match = regex.exec(stripped)) !== null) {
const raw = match[1];
if (!isResolvable(raw)) continue;
refs.push({ file: filePath, raw, type, line: offsetToLine(stripped, match.index) });
}
}
// {project-root}/_bmad/ refs
runPattern(PROJECT_ROOT_REF, 'project-root');
// {_bmad}/ shorthand
runPattern(BMAD_SHORTHAND_REF, 'project-root');
// exec="..." attributes
runPattern(EXEC_ATTR, 'exec-attr');
// <invoke-task> tags
runPattern(INVOKE_TASK, 'invoke-task');
// Step metadata
runPattern(STEP_META, 'relative');
// Load directives
runPattern(LOAD_DIRECTIVE, 'relative');
// Relative paths in quotes
runPattern(RELATIVE_PATH_QUOTED, 'relative');
runPattern(RELATIVE_PATH_DOT, 'relative');
return refs;
}
// --- Reference Resolution ---
function resolveRef(ref) {
if (ref.type === 'project-root') {
return mapInstalledToSource(ref.raw);
}
if (ref.type === 'relative') {
return path.resolve(path.dirname(ref.file), ref.raw);
}
if (ref.type === 'exec-attr') {
let execPath = ref.raw;
if (execPath.includes('{project-root}')) {
return mapInstalledToSource(execPath);
}
if (execPath.includes('{_bmad}')) {
return mapInstalledToSource(execPath);
}
if (execPath.startsWith('_bmad/')) {
return mapInstalledToSource(execPath);
}
// Relative exec path
return path.resolve(path.dirname(ref.file), execPath);
}
if (ref.type === 'invoke-task') {
// Extract file path from invoke-task content
const prMatch = ref.raw.match(/\{project-root\}\/_bmad\/([^\s'"<>})\]`]+)/);
if (prMatch) return mapInstalledToSource(prMatch[0]);
const bmMatch = ref.raw.match(/\{_bmad\}\/([^\s'"<>})\]`]+)/);
if (bmMatch) return mapInstalledToSource(bmMatch[0]);
const bareMatch = ref.raw.match(/_bmad\/([^\s'"<>})\]`]+)/);
if (bareMatch) return mapInstalledToSource(bareMatch[0]);
return null; // Can't resolve — skip
}
return null;
}
// --- Absolute Path Leak Detection ---
function checkAbsolutePathLeaks(filePath, content) {
const leaks = [];
const stripped = stripCodeBlocks(content);
const lines = stripped.split('\n');
for (const [i, line] of lines.entries()) {
if (ABS_PATH_LEAK.test(line)) {
leaks.push({ file: filePath, line: i + 1, content: line.trim() });
}
}
return leaks;
}
// --- Main ---
console.log(`\nValidating file references in: ${SRC_DIR}`);
console.log(`Mode: ${STRICT ? 'STRICT (exit 1 on issues)' : 'WARNING (exit 0)'}${VERBOSE ? ' + VERBOSE' : ''}\n`);
const files = getSourceFiles(SRC_DIR);
console.log(`Found ${files.length} source files\n`);
let totalRefs = 0;
let brokenRefs = 0;
let totalLeaks = 0;
let filesWithIssues = 0;
const allIssues = []; // Collect for $GITHUB_STEP_SUMMARY
for (const filePath of files) {
const relativePath = path.relative(PROJECT_ROOT, filePath);
const content = fs.readFileSync(filePath, 'utf-8');
const ext = path.extname(filePath);
// Extract references
let refs;
if (ext === '.yaml' || ext === '.yml') {
refs = extractYamlRefs(filePath, content);
} else {
refs = extractMarkdownRefs(filePath, content);
}
// Resolve and check
const broken = [];
if (VERBOSE && refs.length > 0) {
console.log(`\n${relativePath}`);
}
for (const ref of refs) {
totalRefs++;
const resolved = resolveRef(ref);
if (resolved && !fs.existsSync(resolved)) {
// For paths without extensions, also check if it's a directory
const hasExt = path.extname(resolved) !== '';
if (!hasExt) {
// Could be a directory reference — skip if not clearly a file
continue;
}
broken.push({ ref, resolved: path.relative(PROJECT_ROOT, resolved) });
brokenRefs++;
continue;
}
if (VERBOSE && resolved) {
console.log(` [OK] ${ref.raw}`);
}
}
// Check absolute path leaks
const leaks = checkAbsolutePathLeaks(filePath, content);
totalLeaks += leaks.length;
// Report issues for this file
if (broken.length > 0 || leaks.length > 0) {
filesWithIssues++;
if (!VERBOSE) {
console.log(`\n${relativePath}`);
}
for (const { ref, resolved } of broken) {
const location = ref.line ? `line ${ref.line}` : ref.key ? `key: ${ref.key}` : '';
console.log(` [BROKEN] ${ref.raw}${location ? ` (${location})` : ''}`);
console.log(` Target not found: ${resolved}`);
allIssues.push({ file: relativePath, line: ref.line || 1, ref: ref.raw, issue: 'broken ref' });
if (process.env.GITHUB_ACTIONS) {
const line = ref.line || 1;
console.log(`::warning file=${relativePath},line=${line}::${escapeAnnotation(`Broken reference: ${ref.raw}${resolved}`)}`);
}
}
for (const leak of leaks) {
console.log(` [ABS-PATH] Line ${leak.line}: ${leak.content}`);
allIssues.push({ file: relativePath, line: leak.line, ref: leak.content, issue: 'abs-path' });
if (process.env.GITHUB_ACTIONS) {
console.log(`::warning file=${relativePath},line=${leak.line}::${escapeAnnotation(`Absolute path leak: ${leak.content}`)}`);
}
}
}
}
// Summary
console.log(`\n${'─'.repeat(60)}`);
console.log(`\nSummary:`);
console.log(` Files scanned: ${files.length}`);
console.log(` References checked: ${totalRefs}`);
console.log(` Broken references: ${brokenRefs}`);
console.log(` Absolute path leaks: ${totalLeaks}`);
const hasIssues = brokenRefs > 0 || totalLeaks > 0;
if (hasIssues) {
console.log(`\n ${filesWithIssues} file(s) with issues`);
if (STRICT) {
console.log(`\n [STRICT MODE] Exiting with failure.`);
} else {
console.log(`\n Run with --strict to treat warnings as errors.`);
}
} else {
console.log(`\n All file references valid!`);
}
console.log('');
// Write GitHub Actions step summary
if (process.env.GITHUB_STEP_SUMMARY) {
let summary = '## File Reference Validation\n\n';
if (allIssues.length > 0) {
summary += '| File | Line | Reference | Issue |\n';
summary += '|------|------|-----------|-------|\n';
for (const issue of allIssues) {
summary += `| ${escapeTableCell(issue.file)} | ${issue.line} | ${escapeTableCell(issue.ref)} | ${issue.issue} |\n`;
}
summary += '\n';
}
summary += `**${files.length} files scanned, ${totalRefs} references checked, ${brokenRefs + totalLeaks} issues found**\n`;
fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, summary);
}
process.exit(hasIssues && STRICT ? 1 : 0);