Skip to content

feat: cross-file reference validator for BMAD source files #1493

@arcaven

Description

@arcaven

Describe your idea

A CI validator (tools/validate-file-refs.js) that checks cross-file references in src/ content files — agents, workflows, tasks, and steps — and reports broken paths. It follows the same scan/extract/resolve/report pattern as validate-doc-links.js and plugs into the existing validate CI job.

The tool validates {project-root}/_bmad/ references, relative paths (./, ../), exec attributes, <invoke-task> tags, step metadata (thisStepFile/nextStepFile), and Load directives. It also detects absolute path leaks (/Users/, /home/, C:\) in source files.

It runs in warning mode by default (exit 0) so it provides visibility without blocking CI. A --strict flag is available for enforcement when the team is ready.

Why is this needed?

Looking at the project's closed issue history, broken file references and path handling problems account for 59 bugs — 25% of all 236 closed bugs — and over 129 maintainer/user comments. These two categories have no automated prevention today. When files are renamed, moved, or have extensions changed (e.g., the .yaml to .md migration), stale references are left behind and only surface through user reports after release.

The existing docs:validate-links covers documentation links in docs/, and validate:schemas covers YAML structure, but neither checks whether the file paths referenced inside workflow, agent, and task content actually point to real files.

On a test run against the current main, the validator immediately finds 5 broken references matching known open issues #1455/#1324 (missing validate-workflow.xml) and #1212 (wrong .yaml extension, actual file is .md), along with 2 previously unreported broken relative paths in the create-prd workflow steps.

What the data shows

To quantify the value, we replayed the validator against all 26 v6 release tags (alpha.0 through Beta.2):

Metric Value
Tags analyzed 26
Unique broken refs tracked across history 289
Fixed manually over time without automation 285
Peak breakage in a single release (alpha.23) 208 broken refs
Still broken on current HEAD 5
False positives on current HEAD 0

Key moments where the validator would have made a difference:

The pattern is consistent: file reorganizations introduce broken references in bulk, which are then fixed reactively over multiple releases through user reports. Automated detection at the PR level would collapse that feedback loop from weeks/months to the moment the breaking change is proposed.

Non-blocking adoption

The validator is designed for gradual adoption. It adds a step to the existing validate CI job but exits 0 regardless of findings — build results are unaffected. Broken references appear in the build log for visibility without blocking merges.

When the team is ready to enforce, it's a single-line change:

- "validate:refs": "node tools/validate-file-refs.js"
+ "validate:refs": "node tools/validate-file-refs.js --strict"

No existing CI checks, pre-commit hooks, or npm scripts are modified in behavior. The validator is purely additive.

How should it work?

  • Scans src/ for .yaml, .md, and .xml files (212 files, 479 references today)
  • Maps {project-root}/_bmad/ references to source tree paths (_bmad/core/src/core/, _bmad/bmm/src/bmm/)
  • Checks relative path references resolve from the containing file's directory
  • Skips runtime variables ({output_folder}, {timestamp}, {{mustache}}) and install-generated files (_config/, config.yaml)
  • Reports broken references with file path, line context, and expected target
  • Self-contained: uses only node:fs, node:path, and yaml (already a project dependency)
  • Adds validate:refs npm script and a step in the validate job in quality.yaml

PR

Working implementation: #1494

Additional context

The validator's structure follows validate-doc-links.js (371 lines) as a template and ports regex patterns from dependency-resolver.js's parseFileReferences() rather than importing the class directly, keeping it self-contained. The implementation is 430 lines, within the CONTRIBUTING.md guidelines.

Reference patterns validated were cataloged by auditing all 212 source files. The full inventory covers 13 distinct reference patterns including YAML path values, step sequencing metadata, XML invoke-task tags, and markdown Load directives.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions