Commit Graph

3 Commits

Author SHA1 Message Date
Brian Madison c563cef0c2 refactor: replace module installer scripts with declarative directories config
Removes the security-risky _module-installer pattern (code execution at
install time) in favor of a declarative `directories` key in module.yaml.
The main installer now handles directory creation centrally based on this
config, eliminating per-module installer.js scripts and their CJS/ESM issues.

Changes:
- Delete src/bmm/_module-installer/installer.js
- Delete src/core/_module-installer/installer.js
- Add `directories` key to src/bmm/module.yaml
- Rename runModuleInstaller() -> createModuleDirectories()
- Remove _module-installer from ESLint overrides
- Remove _module-installer from file-ref validator skip dirs
2026-02-08 19:21:48 -06:00
Michael Pursifull 24cf444366
feat: extend Layer 1 file-ref validator to scan CSV workflow-file references (#1573)
* feat: extend validate-file-refs.js to scan CSV workflow-file references

Add CSV file reference extraction to the Layer 1 validation pipeline,
preventing broken _bmad/ workflow-file paths in module-help.csv files.
Closes the gap identified after PR #1529 where CSV references were
unvalidated despite being a source of repeat community issues.

Refs: #1519

* fix: include test:refs in aggregate test script

Add CSV file-ref extraction tests to the aggregate `npm test` pipeline,
matching the existing pattern for test:schemas and test:install.

Thanks to CodeRabbit for catching the omission.

* fix: address review feedback on CSV validator extension

- Surface CSV parse errors visibly instead of silently swallowing
  (no Layer 2c schema validator exists yet to catch these)
- Add explanatory comments for the !VERBOSE logging pattern
  (non-verbose prints file headers only when issues found)
- Add verbose-mode diagnostics for extensionless path handling
  ([SKIP] when nothing exists, [OK-DIR] for valid directories)

* refactor: collect-then-print to eliminate confusing !VERBOSE pattern

Replace the split header-printing logic (print early in verbose mode,
print late in non-verbose mode with a !VERBOSE guard) with a simpler
collect-then-print approach. Refs are now classified into ok[] and
broken[] arrays first, then printed in a single location with one
straightforward if/else if decision.

Addresses alexeyv's review feedback about the counterintuitive
"if not verbose, log" pattern.

* feat: promote extensionless unresolved paths from silent skip to [UNRESOLVED]

Paths without file extensions that don't exist as files or directories
are now flagged as [UNRESOLVED] — a distinct tag from [BROKEN] (which
means a file with a known extension wasn't found). Both count toward
the broken reference total and appear in CI annotations.

This catches real bugs like wrong directory names in installed_path
metadata and dead invoke-workflow references to removed workflows.
Extensionless paths that DO exist as directories are still [OK-DIR].

---------

Co-authored-by: Alex Verkhovsky <alexey.verkhovsky@gmail.com>
Co-authored-by: Brian <bmadcode@gmail.com>
2026-02-08 09:19:53 -06:00
Michael Pursifull ba890779a2
feat: cross-file reference validator for BMAD source files (#1494)
* 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

* 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.

* 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

* 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.

* 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

---------

Co-authored-by: Alex Verkhovsky <alexey.verkhovsky@gmail.com>
Co-authored-by: Brian <bmadcode@gmail.com>
2026-02-03 13:13:38 -06:00