The hint pointed at npx bmad-method --version and package.json, which
exist only for the 6.12 npm install. It now covers both: bmad update
for skills installs, npx bmad-method --version for 6.12.
The root package.json, lockfile, .nvmrc, prettier ignore file and
.npmignore are gone. docs-site has its own package.json and lockfile
with the Astro, ESLint and Prettier dependencies, and its scripts run
relative to that directory. tools/quality.py, both workflows and the
docs all call npm inside docs-site.
stamp_release.py stamps only the 29 skill manifests now; the version
lives nowhere else on this branch. The tests for package stamping go
with it.
* build: replace the npm lint stack with pre-commit
markdownlint-cli2, prettier and eslint for YAML/JSON, husky and
lint-staged are gone. pre-commit runs ruff, rumdl (the same five
markdown rules), yamllint, yamlfix, the JSON checks, both validators
and pytest, at commit time and over the whole tree from
tools/quality.py, which is now what `npm run quality` calls. ESLint and
prettier stay only for the docs-site scripts and tests. quality.yaml
collapses to a Python job and a docs-site job.
yamlfix keeps one blank line and no document-start marker: its defaults
strip blank lines inside block scalars and add `---`, which the sprint
status scripts do not write back. The JSON hook keeps key order and
non-ASCII text.
* style: apply yamlfix and JSON formatting to the tree
Mechanical output of the new hooks; every file parses to the same data.
* docs: state what the commit hook covers
* refactor(docs-site): move the doc tooling out of tools/
The five doc scripts and their test exist because of Starlight: sidebar
order frontmatter, the rehype link convention, the built site, and the
Astro build itself. They now live under docs-site/scripts and
docs-site/test, next to the rehype plugins and the site tests, which
leaves tools/ Python-only. ESLint stops ignoring those two directories
and its script rules now target them; the Astro sources stay excluded.
* ci(docs): deploy the site from dev
main moves only by release fast-forward, so a docs deploy tied to it
would lag every doc change until the next release. Deploy on push to
dev instead; main receives the same tree later and needs no deploy.
* build: declare the Python toolchain in pyproject.toml
Pin the dev environment (pytest, pytest-xdist, pyyaml, ruamel.yaml, ruff)
with uv instead of a one-line --with list in package.json. The project is
marked non-packaged: the tree itself is what gets installed, and shipped
scripts keep their inline metadata. The validate CI job now runs on uv
alone, without Node, and gains a ruff check.
* style: apply ruff to tools and skill scripts
Mechanical output of ruff check --fix and ruff format under the new
config, plus four hand edits: explicit zip strictness in setup.py and
test_sprint_status.py, an f-string for the hex colour in brain.py, and a
noqa on the sys.path-dependent import in render_skill.py. No behaviour
change; 500 tests pass.
* build: declare Python 3.11 as the floor of every shipped script
Eighteen scripts declared 3.8 or 3.10 inline while ruff targeted 3.11,
so an autofix could introduce syntax those scripts did not advertise.
The lower floors were never reachable: every skill that carried one
also runs a 3.11 hub script, and uv fetches whatever interpreter a
script asks for. All inline metadata now says 3.11, and a test keeps
the inline floors equal to requires-python and the ruff target.
Checks that ran when a PR was opened against main are stale once the
retarget workflow moves it to dev. Trigger on the edited event and skip
title and body edits, so a retargeted PR gets fresh checks without the
contributor closing and reopening it.
Walk core+bmm skill sources into a skills/<canonical-id>/ tree and
fatten only dest bmad-help with the shared Python, module.yaml defaults,
and a baked core+bmm help catalog.
* refactor(bmm): move sprint-planning and sprint-status to plan/
They sit at the plan/ship boundary and their outputs are planning
artifacts of the dev cycle; next commit makes sprint-planning the
readiness gate, which is plan-side work.
* refactor(bmm): fold readiness gate into sprint-planning, retire check-implementation-readiness
The old skill was 1,154 lines of legacy numbered-step ceremony whose
document discovery hardcoded filename globs (*prd*, *ux*, *epic*) that
miss what current skills produce (SPEC.md, DESIGN.md) and still treated
retired sharded docs as first-class. Sprint-planning now opens with a
lean readiness gate: generic artifact discovery by content, forward/back
traceability, PASS/CONCERNS/FAIL, stop on FAIL with findings. The IR
trigger on John's and Winston's menus dispatches sprint-planning, so
'check implementation readiness' still works everywhere it used to.
* refactor(bmm): modernize sprint-planning with deterministic script core
SKILL.md drops the legacy XML step dialect for the product-brief style
(~100 lines, uv run, headless contract). New scripts/sprint_plan.py owns
the mechanical work — epic parsing, key derivation, ordering, preserve-
never-downgrade merge, story-file detection, action_items carry-over,
atomic writes, drift checks — with 11 tests wired in as
test:sprint-planning. Judgment stays with the LLM: epic discovery, the
readiness gate, and reconciling script-reported orphans and unparsed
headings. checklist.md retired (the script performs that checklist);
sprint-status-template.yaml is the single source for the status
vocabulary. Output stays byte-compatible with build's sprint sync and
retrospective's tooling.
* refactor(bmm): fold sprint-status into sprint-planning's status view
sprint_plan.py gains a status subcommand: counts (legacy values mapped),
risk flags, open action items, and a priority-ordered next-action
recommendation — the old skill's inference-driven summary, computed
deterministically and covered by 9 new tests. bmad-sprint-status becomes
a v6-shims husk that forwards with status-view intent and a deprecation
notice; its dead data/validate modes had zero callers and are gone. If
a hand-edited status file defeats the script, the skill falls back to
reading it directly and summarizing by best judgment. New explanation
page docs/explanation/sprint-planning.md covers the consolidated skill;
workflow maps and references updated across all languages.
* docs: changelog entries for skill reorg and sprint consolidation
* fix(bmm): harden sprint_plan.py per review; add validate/fix intents with full progressive disclosure
Review fixes (PR #2659 findings, bot + internal review):
- Normalize legacy v6 statuses (drafted/contexted) on every read — merged by
meaning and reported, never treated as illegal or reset
- dropped_orphans carry their old status; transplant renames via --set
- project_key/tracking_system/story_location preserved from the existing file
unless overridden; refresh round-trips custom keys and user comments
- Hardened write path: dump-to-bytes, fsync, permission-preserving atomic
write inside the guarded block, explicit checks (no asserts), atomic restore
- JSON-only argparse (errors and -h emit JSON); unicode-aware slugs with hash
fallback; fenced code blocks ignored when parsing epics
- Odd retro keys, date-typed stamps, and non-mapping YAML report cleanly
instead of crashing; unparseable timestamps warn instead of silently
disabling the staleness check; malformed action items flagged, not dropped
- Dead check subcommand removed; generate --dry-run reports drift/in_sync
- test:sprint-planning wired into quality and CI (was test-only)
- Retro tests use a vendored template fixture (PATH-05); repo-level
test-template-sync.js keeps it byte-identical to the source; template
example timestamps and story_location fixed; header block pinned to the
template by test
New capability:
- validate subcommand + reference: structural validation, never writes
- fix flow: evidence-gathering subagents -> user-confirmed state table ->
generate --fresh --set writes a pristine file (the one path allowed to
downgrade); universal script-failure fallback to inference for every intent
- SKILL.md is now a lean router: gate, tracking, status, fix, and validate
each load as progressive-disclosure references
Docs: explanation page gains Repair section; workflow-map and getting-started
across all five languages mention the status view; headless payload nests
under 'report' to avoid the status key collision; changelog updated.
Test suite grows 20 -> 37; retro suite 91/91; docs build and validators green.
* docs: mention repair in sprint-planning explanation description
* feat(bmm): rework bmad-retrospective as an evidence-based epic review
Replace the persona-meeting simulation with an evidence engine that mines
what a completed epic actually left behind — spec, full diff, per-story
commits, sprint status, and session logs — instead of simulating a team
that "remembers." Every finding carries a source reference.
- Five-phase flow: Gather -> Analyze -> Decide -> Close. Analyze derives
aggregate views (architecture delta, duplication, god-class growth,
pattern divergence, spec reconciliation) and reuses bmad-review for the
diff-scope code lenses rather than reimplementing them.
- Acceptance verdict (accepted / accepted-with-open-items / rejected); a
failing epic can never close as silently accepted.
- Team discussion is now opt-in and off by default, delegating to
bmad-party-mode seeded with the real findings.
- Add deterministic scripts: sprint_status.py (epic detection plus a
comment-preserving, force-quoting, validate-and-restore sprint-status.yaml
update) and git_evidence.py (range / commit / size-trajectory
measurement), with a pytest suite.
- The retrospective document is the working artifact: built early, filled
per phase, and resumable. Adds a headless mode (-H) with assumption
capture.
- SKILL.md drops from ~1527 lines to a lean spine plus five references.
* fix(bmm): harden retrospective scripts for orchestrator use
Address review feedback on the evidence-based retrospective (PR #2612) from
CodeRabbit and the bmad-loop maintainer. All changes are additive — no existing
JSON field or CLI argument that a consumer reads is renamed or removed.
- detect-epic: STORY_RE now matches split-story keys (2-6a-...), aligning with
bmad-loop's sprint-status detection; previously such an epic was invisible and
a headless run could retro the wrong epic.
- sprint_status/git_evidence: argparse failures now emit JSON on the documented
stdout contract instead of plain usage text.
- sprint_status: guard non-list action_items (clean JSON error, no traceback);
_restore reports success/failure so a failed rollback is surfaced, not hidden.
- action_items entries carry a stable id and a ref to the retro document, so an
orchestrator can dedupe across re-runs and dispatch each sourced finding.
- update echoes the acceptance verdict in its JSON; the retro key value stays
"done" for existing lifecycle consumers. Retro doc gains machine-readable
frontmatter, and -H <epic> is documented as the stable automation interface.
- evidence-gathering: derived range now includes the first story commit
(<first>^..<last>); aggregate-views drops the size/acceleration overclaim.
- Tests: split-story detection, non-list guard, restore reporting, argparse
JSON, and id/ref/verdict coverage (13 pass).
* docs(bmm): refine retrospective party-mode phrasing
* docs(bmm): document the reworked retrospective
- Add docs/explanation/retrospective.md — a short feature page: what the
skill does, why to run it after an epic, and what to do with its output
(retro document, action items, acceptance verdict).
- Update the workflow-map retrospective row to reflect the evidence-based
review and its actual outputs instead of "Lessons learned."
* fix(bmm): validate git_evidence --range as a strict revision range
An unvalidated --range reached the git argv unchanged: a value starting
with "-" was consumed by git as an option, a single rev logged all
history up to it, an existing path was consumed as a pathspec, and a
file named like a range (a..b) was silently logged as one — each
returning a confident, wrong evidence set with exit 0. Reject anything
that is not an explicit REV..REV form — including empty endpoints
("..", "a..", "..b"), which git silently defaults to HEAD, and
unstripped values — and terminate the git argv with "--" so a
range-shaped name is always parsed as revisions, never as a pathspec.
Drop the root-commit special case from evidence-gathering.md: its
wording steered into a bare-rev invocation now rejected, the scenario
(an epic starting at the repository's first commit) is vanishingly
rare, and an agent that ever meets it can still construct a shape-valid
range itself. Document the exit-code split (2 invalid args, 1 git
failure). Every rejected mode is covered by regression tests; git
error-string assertions are pinned to LC_ALL=C.
* fix(bmm): harden sprint_status.py input validation and atomic writes
Nine findings from the PR #2612 review of the reworked retrospective, all
reproduced against the previous behavior:
- Pin the emitter indentation so a round-trip stops de-indenting
pre-existing, untouched action_items; the sprint-status template now
survives an update byte-identical apart from last_updated.
- Keep malformed input on the documented JSON-to-stdout contract instead
of a traceback: shape-check the root document and development_status on
both subcommands, widen the file open from FileNotFoundError to
OSError, and report invalid UTF-8 as a JSON error. A non-mapping
development_status previously reported ok:true while doing nothing.
- Validate comment preservation against the whole file's comment lines
rather than only the leading block matched by substring, so a lost
mid-file comment fails the write and restores.
- Write atomically through a temp file, fsync and os.replace, resolving
symlinks and carrying the target's mode across. The rollback goes
through the same path: a truncating rewrite that died halfway used to
destroy the bytes it was restoring.
- Stop inserting an empty development_status mapping, and report
retro_key_found: null when --set-retro-done was not passed, reserving
true/false for "flag passed, key present/absent".
- Include restored:true on every update failure that precedes the write.
- Make _slugify Unicode-aware with a content-hash fallback, so non-Latin
action text no longer collapses to the literal "item".
- Reject an --add-action item whose action is empty or not a string.
- Validate --date against MM-DD-YYYY HH:MM and normalize it, since
strptime otherwise admits unpadded spellings.
Each fix is pinned by a subprocess-level regression test; the suite goes
from 18 to 49 tests.
* feat(bmm): add action-item status updates to sprint_status.py
The update subcommand could only append, and retro-document.md forbids
hand-editing sprint-status.yaml, so nothing anywhere could move an action
item off open. bmad-sprint-status renders every open and in-progress item
on every call, so retrospectives accumulated permanently-open noise.
Add --set-action-status, taking a JSON array of transitions for items
already in the file. Each entry selects one item by id, or by epic plus
exact action text for legacy entries written before ids existed, and gives
it one of open, in-progress, done. Selectors resolve against action_items
as loaded and strictly before the --add-action append, so an item added in
the same run is not addressable in that run. Validation is all-or-nothing
and entirely pre-write: a selector matching nothing, matching more than
one item, colliding with another entry, or carrying a status outside the
vocabulary aborts the whole invocation with restored: true and the file
byte-identical. After the write the file is re-parsed and every targeted
item is confirmed to carry its new status. Success reports the new
action_items_updated count.
Rewrite the contradicting paragraph in retro-document.md so the flag is
the one sanctioned path to change a status: offer the transitions when
the Phase 4 follow-through has evidence an item landed, apply only what
the user confirmed, and never touch prior statuses in a headless run.
* fix(bmm): measure renames, merges, and binary churn in git_evidence
Five ways the measurement was quietly wrong:
- Renames emitted an unopenable "src/{a => b}" pseudo-path and split one
file's churn across up to three keys; non-ASCII paths arrived octal
escaped. Both passes now run with core.quotePath=false and
--no-renames, so a rename is an honest delete + add and a path is a
real string that opens.
- Merge commits emit no numstat rows, so cross-story conflict-resolution
churn vanished with nothing saying it had been skipped. The listing
pass keeps full topology (per-story attribution is unchanged); a
second pass measures merges alone under -m --first-parent
--min-parents=2 and reports merge_files, merge_count and
merges_measured. Merge churn is never folded into files: a merge's
first-parent diff restates the churn of the commits it merged in.
- A commit naming two stories attributed to whichever id was passed
first. Every matching id is now collected, so a seam commit counts for
both stories. commits[].story becomes commits[].stories.
- A git failure with empty stderr reported "error": "". It now falls
back to the exit code.
- One binary revision of a path nulled its added/deleted/net, dropping
real measured text churn from the ranking. The text sums survive and
binary_revisions reports the exposure beside them.
log.diffMerges is pinned to separate on the command line, because a user
config of off makes the merge pass emit no rows at all. Git output is
decoded with surrogateescape rather than replace, so two distinct
non-UTF-8 paths cannot collapse into one key.
evidence-gathering.md documents the changed output. 19 subprocess-level
tests over real git fixture repos cover every case above; the suite goes
81 -> 100.
* feat(bmm): add a pending-stories gate and align the retrospective docs
`detect-epic` now also reports `pending_stories` — the selected epic's
story keys that are not `done`, scoped to that epic alone — and SKILL.md
branches on it before Phase 1: interactively the user is shown the list
and may decline, headless the run proceeds and records the list as an
assumption. An epic supplied on the invocation skips detection, so the
instructions say plainly that the check did not run rather than implying
it did.
Both scripts are built with `add_help=False`. `-h`/`--help` previously
printed argparse's usage text on stdout and exited 0, breaking the
JSON-only stdout contract the scripts sell to their machine consumer;
help is now an ordinary unrecognized argument routed through the
existing JSON error path. SKILL.md also gained the branch for a
`detect-epic` that exits non-zero, which is the normal path for a
stories-mode project with no sprint-status.yaml.
The references are brought back into agreement with what the scripts do
after the last three batches: the close-out invocation quotes its values
and pins the `--date` format that now hard-fails a non-conforming value;
the result JSON documents `retro_key_found: null` and which failures
carry `restored`; the retro key is stated to read `done` even for a
rejected epic, so a verdict-aware gate must read the document
frontmatter; Phase 3 gains an inline fallback when bmad-party-mode is
absent; Phase 4 specifies the previous-retro follow-through record the
close-out consumes; and the god-class view is rewritten for the current
git_evidence keys.
Suite goes from 100 to 111 tests.
* chore(bmm): align retrospective script conventions and test harness
Adopt the invocation convention the quick-dev and dev-auto skills settled
on, and make the git_evidence test fixtures independent of the machine
they run on.
All five documented invocations become `uv run --no-cache`: the shared
cache may be unwritable in a sandbox and may serve a stale build. Both
scripts drop their shebangs entirely — they are only ever launched via
`uv run`, so a shebang and executable bit are a false affordance; the
PEP 723 blocks stay, since that is what uv reads. The encoding audit
that change implies found one implicit site left: `_load_yaml` now pins
the ruamel emitter's encoding, which is what encodes the bytes
`_dump_bytes` writes to the user's file.
`_git` and `_git_unchecked` passed an env of only the four GIT_* identity
vars, so PATH and HOME were wiped and git resolved through os.defpath —
the fixtures ran a different binary than the script under test, and
failed outright wherever git lives only in /opt/homebrew, /usr/local or
a nix store. Both now share a `_git_env` that inherits the environment,
strips ambient GIT_* vars that would redirect or reconfigure the fixture,
and pins identity, both gitconfig sources, gitattributes and the locale.
`_run` parsed stdout bare, so a crash surfaced as JSONDecodeError with
the real traceback hidden in the discarded stderr; it now routes through
the `_json` guard the rest of the file already used. Both test files gain
the repo's established runner footer and the PEP 723 header that makes it
self-bootstrap under `uv run <file>`.
No test's assertions change; the suite holds at 111 passing, and passes
under a gitconfig setting commit.gpgsign, core.autocrlf, core.hooksPath
and init.defaultBranch against it.
* feat(bmm): aim detect-epic at a supplied epic and reject unfinished ones
Unattended retros need the unfinished-story gate on the orchestrator path
and a hard machine verdict when delivery is incomplete.
detect-epic gains optional --epic N so -H <epic> can request the same
pending_stories list auto-detect already returns for its picked epic.
Non-positive values fail as JSON (exit 1). The skill now always runs
detect-epic for a supplied epic with that flag, and the acceptance
rubric forces rejected when pending_stories is non-empty — headless
included; interactive humans may still override.
Suite 111 → 115.
* fix(bmm): harden retrospective script contracts after re-review
- reject three-dot --range values in git_evidence.py: A...B passed the
guard and silently measured a symmetric difference
- move the directory fsync in _atomic_write past the failure path so a
post-rename fsync error can no longer report "restored": true about a
write that landed
- validate --verdict against the frontmatter vocabulary and spell
accepted-with-open-items one way across every machine-read surface
- emit story_count from detect-epic so a typo'd epic number is
distinguishable from a finished epic, and teach the SKILL gate to
treat 0 as suspect
- align the dev agent's ER menu description with the reworked skill
* fix(bmm): reject typed retrospective statuses
* docs: fix retrospective sidebar order
* ci(bmm): run retrospective Python tests
* fix(bmm): harden retrospective script execution
Reject non-positive epic numbers before update processing.
Keep explicit repositories authoritative when invoked from Git hooks.
* docs(bmm): rewrite retrospective skill prose in plain language
Remove invented metaphor and jargon from the skill's prompt surface
(SKILL.md and references): witnesses/interrogates, testimony, seams,
close-out, mining, and similar phrasing are replaced with plain
equivalents. Rename Phase 5 "Close" to "Finalize" and the "Honest
degradation" section to "Missing evidence", syncing cross-references.
Industry-standard terms (god-class, churn) and BMAD vocabulary
(declared/profiled, party mode) are kept. No operational rule,
script contract, or verdict vocabulary changes.
* docs(bmm): refine retrospective prose
---------
Co-authored-by: Alex Verkhovsky <alexey.verkhovsky@gmail.com>
Render complete dev-auto workflows into root-scoped immutable snapshots
using shared declarative rendering and strict TOML configuration layers.
Keep generated render state out of installer module discovery and custom
file preservation, preserve quick-dev behavior, and provide deterministic
Python version failures for standalone resolver use.
* fix(publish): advance @next dist-tag after stable release
When a stable release publishes via workflow_dispatch, @latest can leapfrog
the existing @next prerelease (e.g. latest=6.5.0 while next=6.4.1-next.0),
turning `npx bmad-method@next install` into a silent downgrade until the
next qualifying push to main republishes a fresh -next.0.
- publish.yaml: after stable publish, repoint @next at the just-published
stable version. The existing derive-prerelease step picks max(latest, next)
as its base, so subsequent push-driven prereleases bump from there.
- bmad-cli.js: checkForUpdate was querying the @beta dist-tag (which this
package does not use). Replace string-matching with semver.prerelease()
and query @next for prerelease users.
* fix(publish): harden next-tag advance step and broaden path filter
- continue-on-error on the dist-tag advance: failure leaves @next stale
until the next push-driven prerelease, which is recoverable; failing the
job after a successful publish + git tag + GH release is not.
- Status echo so release-log triage can confirm the advance ran.
- Add removals.txt to the push-trigger path filter. Installer-affecting
changes outside src/** (like the post-6.5.0 removals.txt fix) should
still trigger a fresh -next.0 publish.
* refactor(installer): restructure installer with clean separation of concerns
Move tools/cli/ to tools/installer/ with major structural cleanup:
- InstallPaths async factory for path resolution and directory creation
- Config value object (frozen) replaces mutable config bag
- ExistingInstall value object replaces stateful Detector class
- OfficialModules + CustomModules + ExternalModuleManager replace monolithic ModuleManager
- install() is prompt-free; all user interaction in ui.js
- Update state returned explicitly instead of mutating customConfig
- Delete dead code: dependency-resolver, _base-ide, IdeConfigManager,
platform-codes helpers, npx wrapper, xml-utils
- Flatten directory structure: custom/handler → custom-handler,
tools/cli/ → tools/installer/, lib/ directories removed
- Update all path references in package.json, tests, CI, and docs
* fix(installer): guard ExistingInstall.version and surface module.yaml errors
Guard ExistingInstall.version access with .installed check in
uninstall.js, ui.js, and installer.js to prevent throwing on
empty/partial _bmad dirs. Surface invalid module.yaml parse errors
as warnings instead of silently returning empty results.
The deterministic skill validator was in the npm quality chain but
missing from the GitHub Actions workflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The *.agent.yaml format was replaced by SKILL.md-based agents.
Zero agent YAML files remain in src/, so remove the Zod schema,
validator CLI, fixture-based test suite (52 fixtures), unit tests,
CLI integration tests, and the CI steps that invoked them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously the quality workflow only triggered on pull_request events,
so direct pushes to main (including merged PRs) skipped all CI checks.
Add a push trigger for the main branch so broken builds are caught.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: add continuous delivery workflows for npm publishing
Add publish-next (auto-prerelease on push to main) and publish-latest
(manual stable release with Discord notification). Update CONTRIBUTING.md
to describe the trunk-based CD model.
* fix(ci): guard publish-latest against non-main dispatch
Reject workflow_dispatch runs from non-main refs to prevent
publishing unintended code or fast-forwarding main unexpectedly.
* chore: unify npm publish workflow
Add publish-next (auto-prerelease on push to main) and publish-latest
(manual stable release with Discord notification). Update CONTRIBUTING.md
to describe the trunk-based CD model.
* fix(docs): comprehensive documentation site review fixes
Rehype plugins:
- Rewrite rehype-markdown-links for correct relative .md resolution
- Handle raw HTML base paths and bare .md links in rehype-base-paths
- Guard protocol-relative URLs (//...) in all link processors
- Use file.path instead of file.history[0] for vfile compatibility
- Fail build when content directory cannot be detected
- Export helpers for testability; add 107 unit tests
Build & CI:
- Revert cancel-in-progress to false to avoid mid-deploy cancellation
- Remove redundant link-validation CI step (build validates internally)
- Remove unnecessary fetch-depth:0 from docs deploy workflow
- Refuse docs build on Windows (platform guard)
- Remove dead build scripts and stale references
Tooling:
- Add DOCS_ROOT boundary check in validate-doc-links.js
- Handle directory paths and prefix stripping in link validator
- Remove dead regex and add // guard in fix-doc-links.js
Accessibility & CSS:
- Darken caution/danger aside title colors for WCAG AA 4.5:1 contrast
- Fix 100vw scrollbar overflow (banner width:100%, html overflow-x:clip)
- Add :focus-visible ring to banner link for keyboard navigation
- Remove dead CSS declaration and add missing code block lang
Documentation content:
- Convert /docs/ absolute links to relative paths and fix llms.txt URLs
- Correct command file paths and naming in commands reference
- Update stale shard-doc command to current /bmad-shard-doc format
- Fix incomplete sentence in install-bmad.md
- Add Quick Flow next steps and fix 404 link path
- Expand thin content pages with substantive detail
- Add sidebar ordering frontmatter to all content pages
- Remove BMGD docs (moved to dedicated repo)
- Remove unused assets and misleading diagram caption
- Add non-iframe fallback link to workflow map diagram
- Remove dead noscript block from workflow-map
- Standardize BMAD to BMad, fix spelling/grammar, normalize headings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): add non-interactive installation to sidebar, rewrite and reorder how-to guides
- Move non-interactive-installation.md into how-to/ directory so it appears
in the sidebar navigation (was orphaned at docs root)
- Rewrite the page based on editorial review: consolidate redundant sections,
add missing how-to structure (prerequisites, "What You Get"), condense
installation modes from 5 subsections to a table, cut speculative examples
- Reorder how-to sidebar: Install (1), Non-Interactive (2), Upgrade to v6 (3),
then the rest following user journey order
- Fix README link to point to docs site instead of repo-internal markdown path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): address documentation review findings
Fix broken directory tree, grammar errors, inconsistent naming,
missing admonition/headings, enable lastUpdated timestamps in CI,
and remove footer CSS that misapplied to the content footer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): move bleeding-edge install command out of Verify Installation
The alternative npx command for installing from main was misplaced
inside the "Verify Installation" section. Move it to a tip admonition
under Step 1 where users look for install options.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The workflow was failing with 403 "Resource not accessible by integration"
on fork PRs because pull_request events get read-only GITHUB_TOKEN
permissions for cross-repository PRs. Switching to pull_request_target
runs the workflow in the base repo context, granting write permissions
needed to post the @coderabbitai review comment.
This is safe because the workflow only posts a comment and does not
check out or execute any code from the PR branch.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The manual-release.yaml workflow has been broken since the v6 alpha
rewrite — it calls `npm run validate` which no longer exists. Releases
are now handled via the /draft-changelog and release skills instead.
- Delete .github/workflows/manual-release.yaml
- Delete tools/docs/BUNDLE_DISTRIBUTION_SETUP.md (references deleted workflow)
- Remove release:major/minor/patch/watch npm scripts (triggered deleted workflow)
Can be restored from git history if a CI-based release workflow is needed again.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
CodeRabbit doesn't reliably handle the ready_for_review webhook
event, so draft PRs that are marked ready never get auto-reviewed.
This workflow posts @coderabbitai review when a PR transitions
from draft to ready, working around the limitation.
* docs: add pull request template
Adds PR template matching the format documented in CONTRIBUTING.md.
Completes one of two remaining GitHub Community Standards items.
Fixes#1553
* Update .github/PULL_REQUEST_TEMPLATE.md
* docs: add official external modules reference page
* chore: remove obsolete docs and basement files
* fix: update robots.txt URLs to docs.bmad-method.org
* fix: generate robots.txt dynamically from site base URL
Replace static robots.txt with an Astro endpoint that uses the
configured site URL, so sitemap references are correct on both
fork deployments and production.
* fix: unify site URL resolution in build-docs.js
build-docs.js had its own hardcoded fallback URL
(bmad-code-org.github.io) instead of using the shared
getSiteUrl() function, causing URL mismatches between
robots.txt, llms.txt, and sitemaps. Now all components
resolve the site URL through the same function. Renamed
site-url.js to .mjs to avoid Node ESM detection warnings.
* fix: correct module names and relocate prompt file
- CIS: "Creative Innovation Suite" → "Creative Intelligence Suite"
- GDS: "Game Dev Suite" → "Game Dev Studio"
- Move _prompt-external-modules-page.md from docs/ to tools/docs/
* refactor: convert build-docs to ESM, eliminate mutable globals
- Convert build-docs.js to build-docs.mjs (CJS → ESM)
- Import getSiteUrl directly, remove async import workaround
- Kill mutable SITE_URL global, call getSiteUrl() where needed
- Clean up Banner.astro variable naming
- Update package.json and CI workflow for .mjs extension
* 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>
- Transition BMad Method from Alpha to Beta
- Beta versions now publish to npm 'latest' tag (default for npx)
- Updated manual release workflow to prioritize beta releases
- Updated CHANGELOG with Beta.0 release notes
* fix: web bundler entry point
* removed the web-bundles folder
* added web-bundles to gitignore
* disabled web bundles
---------
Co-authored-by: Brian <bmadcode@gmail.com>