mirror of
https://github.com/bmad-code-org/BMAD-METHOD.git
synced 2026-09-19 08:11:52 +08:00
docs/getting-started-activation
88 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1a8fea5bd0 | fix(docs): resolve deployed validation findings (#2644) | ||
|
|
43b54b8067 |
fix(review): dispatch reviewers by prompt file (#2642)
* fix(review): dispatch reviewers by prompt file
* fix(review): load review content from parent message only
Align phase-four reviewer prompt files with file-dispatch: drop the
{review_content} fill-in slot and take the review target exclusively
from the calling prompt.
* fix(review): keep no-subagent fallback prompts self-contained
When subagents are unavailable, write full instruction body plus
REVIEW TARGET under implementation_artifacts, not a path-only pointer.
* fix(review): keep layer recipes plain multi-line prompts
Drop blockquote wrapping so diffs stay intact, leave parent policy in
the review step, and keep customize instructions as the layer recipe
(default subagent prompt or a custom bash/LLM override).
|
||
|
|
cfee292715 |
fix(dev-auto): move deferred findings into the spec (#2640)
Record deferred review findings only in spec frontmatter and remove the deferred-work output. Make updates safe for legacy specs and YAML-special content, strengthen contract coverage, and synchronize the reference docs. |
||
|
|
c2530ea53f |
feat: add inspectable workflow snapshots (#2601)
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. |
||
|
|
ca0f3b11fb |
fix(review): restore direct phase-four reviewer prompts (#2638)
* fix(review): restore direct phase-four reviewer prompts * test(review): remove prompt content assertions * fix(review): restore one-shot worktree discovery |
||
|
|
c23f23400d |
feat: streamline core to an 8-skill set with merged review and editorial skills (#2603)
* feat: streamline core to a 5-skill kernel with standalone skill modules
Core installs 14 -> 5 catalog-visible skills; atoms exit to standalone
modules; installer gains real dependency resolution; zero npm deps.
- Merge bmad-editorial-review-prose/-structure into bmad-editorial-review
(structure models JIT-loaded, new customize.toml)
- Merge bmad-review-adversarial-general/-edge-case-hunter/-verification-gap
into bmad-review as selectable lenses; hidden husk-forwarders remain at
the old IDs (no catalog rows) so gds/loop/os-utils keep working
- Move bmad-brainstorming, bmad-party-mode, bmad-forge-idea out of core to
src/standalone-skills/ as single-skill modules; add bmad-analysis bundle
module (curated dependency list over the atoms)
- Move bmad-spec into bmm (2-plan-workflows)
- Modernize bmad-advanced-elicitation: uv run, customize.toml, methods
pick offloaded to scripts/pick_methods.py (with tests)
- Delete bmad-index-docs, bmad-shard-doc (removes the tree's only external
npm dependency), and the four deprecation shims (bmad-create-prd,
bmad-edit-prd, bmad-validate-prd, bmad-create-architecture); all added
to removals.txt
- Installer: activate the dependencies field (recursive union into
selectedModules, cycle-guarded, warn on unknown), config-driven picker
visibility; core stays force-installed
- bmm module.yaml declares deps on the three atoms
- Docs updated across all locales; new reference/standalone-skills.md;
shard-doc how-tos removed
* Restore original critical wording lost in the review/editorial merges
The merges into bmad-review and bmad-editorial-review were meant to keep
the source skills' critical wording behind progressive disclosure, not
paraphrase it away. Restore what was lost:
- lens-adversarial: clueless-weasel framing, extreme-skepticism wording,
the at-least-ten-issues quota, and zero-findings-is-suspicious (the
merge had inverted this to zero-is-valid)
- bmad-review SKILL: zero-findings stance is now per-lens
- lens-edge-case: mandatory exact-order step enforcement
- lens-verification-gap: exact 'No verification gaps found.' clean line
- editorial-review: full Human/LLM reader principles restored to new
references/reader-principles.md; structure-pass HIGH-VALUE DENSITY
role, front-load-value, anti-patterns, pacing check, and length_target
assessment; prose-pass role sentence, analyze-style-first step, and
merge-overlapping-fixes rule; output summary block and min-3-words HALT
* feat(installer): promote bmad-analysis bundle to src/bmad-analysis-skills
Move the bmad-analysis bundle module out of src/standalone-skills/ into its
own src/bmad-analysis-skills root, teach the installer to resolve it there
(getModulePath, official-modules listing, isBuiltInModule helper), and
update the marketplace manifest and standalone-skills docs to match.
* refactor(bmad-review): rename edge-case lens to edge-case-hunter
Rename the lens code and reference file (lens-edge-case.md ->
lens-edge-case-hunter.md), add explicit when = "always" to the shipped
lenses, and tighten the lens-selection wording in SKILL.md.
* feat(bmad-editorial-review): configurable style guide + analysis-driven rework
Apply the workflow-builder analysis recommendations:
- Make the baseline style guide configurable: style_guide in customize.toml
now IS the baseline (default "Microsoft Writing Style Guide") instead of
an empty override slot; SKILL.md no longer hardcodes the guide.
- Inline reader-principles.md into SKILL.md and delete the reference (it
loaded on every run and was half-duplicated inline).
- Complete the customization surface: activation_steps_prepend/append,
persistent_facts (project-context glob), on_complete, and a
review_output_path scalar split out of output_preferences; add a
file:-load fallback convention.
- Ground word metrics: new scripts/word_metrics.py (stdlib, PEP 723, tests)
emits total/per-section word counts so impact estimates and the reduction
summary use exact numbers.
- Cross-pass dedup: prose pass skips CUT-tagged passages and re-attaches
fixes in MERGE'd ones; output ranks by impact with a long-tail rollup.
- Polish: HALT threshold replaced with plain outcome, duplicate LLM-reader
bullets merged, all-caps lowered, literal Overview heading added.
* fix(installer): stop cache-refresh git commands from escaping to the parent repo
Two compounding bugs let a pre-commit test run shallow-fetch and hard-reset
the developer's own repository:
1. Git spawns in custom-module-manager and external-manager inherited the
hook environment. Git exports GIT_DIR (absolute, in worktree checkouts)
into pre-commit hooks; a child git then targets the hook's repo regardless
of cwd, and treats its cwd — the module cache dir — as the work tree. The
cache refresh's 'git fetch --depth 1' + 'git reset --hard origin/main'
therefore shallowed the shared .bare and moved the checked-out branch.
New git-env.js strips repo-targeting GIT_* vars from every git spawn in
both managers, including calls that previously inherited process.env
implicitly.
2. Test suite 51 (quickUpdate dependency expansion) ran the real
CustomModuleManager lookup, which scans ~/.bmad/cache/custom-modules and
network-refreshes every cached clone — real user state. The suite now
stubs findModuleSourceByCode.
Verified by rerunning the suite with GIT_DIR pointed at the repo and a PATH
shim blocking fetch/reset/clone: 432 passing, zero blocked calls.
* De-scope standalone-skills mechanism: atoms return to core, shims reinstated
Shrink the PR to its heart — the skill merges — and defer the module
mechanics to a follow-up where all skills become module-driven:
- bmad-brainstorming, bmad-party-mode, bmad-forge-idea move back to
src/core-skills/ as ordinary core skills with their catalog rows
restored; src/standalone-skills/ and the bmad-analysis bundle module
are removed
- Installer reverted to main: standalone discovery, hidden-module
filtering, dependency resolution, manifest changes (test suites 49-51
removed with the code); the cache-refresh git fix is retained
- The four bmm deprecation shims (create/edit/validate-prd,
create-architecture) are reinstated so enterprise installs that
invoke the old IDs or carry _bmad/custom overrides keep working;
descriptions trimmed to the short husk style; their removals.txt
entries dropped (removal rides the v7 cut as their frontmatter
promises)
- marketplace.json keeps the five plugin entries with atom paths
pointing at src/core-skills/
- Docs (en/cs/fr/vi/zh) reframe the three skills as core thinking
skills; standalone-skills.md reference page removed
* Fix all findings from the max-effort adversarial review
Correctness:
- Finish the edge-case -> edge-case-hunter lens rename at every caller:
the forwarder husk, the code-review/dev-auto/quick-dev review layers,
the renderer test assertion, and the stale example path in
bmad-review/SKILL.md
- marketplace.json: ship the five core kernel skills with
bmad-method-lifecycle so its skills' bmad-review/bmad-editorial-review/
bmad-help/bmad-advanced-elicitation invocations resolve in a
marketplace install
- pick_methods.py / word_metrics.py: force UTF-8 stdout (Windows locale
code pages crashed on the catalog's arrows and CJK headings)
- word_metrics.py: pair fences CommonMark-style so 4-backtick fences can
embed 3-backtick examples without corrupting sections; count CJK
characters as words
- pick_methods.py: validate --extra entries are JSON objects (was an
uncaught AttributeError); read catalogs with utf-8-sig (BOM'd CSVs
silently blanked every num)
- bmad-spec: activation now resolves {output_folder} (which the
Workspace uses) instead of the unused {planning_artifacts}; drop the
stale core-only-installs comment
- Editorial husks: pin the legacy output contracts (three-column table /
Document Summary report and exact empty-state lines) like the review
husks do
- PRD shims: advertise the real bmad-prd customize keys
(validation_checklist_template, prd_output_path, run_folder_pattern,
finalize_reviewers) instead of three that don't exist
- bmad-prd: add the forwarded-activation clause its shims rely on
(ported from bmad-architecture)
- Locale workflow-maps (fr/cs/vi/zh): add the bmad-spec Phase-2 row the
English map gained, which every locale's core-tools note points at
- git-env.js: also strip GIT_CONFIG_PARAMETERS and the
GIT_CONFIG_COUNT/KEY_n/VALUE_n family; pass gitEnv() to the three npm
install spawns whose transitive git calls inherited hook vars
Consistency:
- brain.py --extra overlay now replaces-by-name like pick_methods.py
(same customize.toml additional_* semantics across sibling skills),
with a regression test
* Fix prettier formatting in marketplace.json
* Apply valid CodeRabbit findings
- brain.py: catch malformed --extra overlays (bad JSON, non-array root,
non-object entries) into the clean error path instead of a raw
traceback, with a regression test; read catalogs and overlays with
utf-8-sig; normalize ALL CSV fields (required ones were unstripped and
could arrive as None from short rows)
- brain-selector: clamp the random-technique count to what the pool can
supply so the Total badge matches the actual draw (template +
regenerated assets/brain-selector.html)
- bmad-editorial-review: word_metrics command now uses the explicit
{skill-root}/ prefix
- resolve_party.py / resolve_personas.py: custom member overrides now
start from the installed entry, so omitted fields (icon, title,
description, module, team) survive; non-string member tokens land in
unresolved instead of raising TypeError; party's member loop gains the
isinstance guards its personas twin already had
- bmad-brainstorming: fix the SKILL.md claim that headless is the only
context for self-generated ideas (autonomous mode is interactive);
autonomous mode honors user-supplied techniques before self-selecting
- Docs: drop duplicate 'only' in the spec template; align zh-cn
forge-idea's bmad-review description with the English wording
* Create only the output folder at install time
bmm no longer pre-creates planning_artifacts, implementation_artifacts,
and project_knowledge — the last of which put an empty docs/ at every
project root. Skills create those lazily on first write. core now
declares {output_folder} in its directories block, which was previously
created only as a side effect of the artifact folders nesting under it.
|
||
|
|
717479bc3f |
fix(dev-auto): temporarily revert skill-entry renderer (#2598)
Back out the dev-auto render.py workflow entry change from #2587, including the follow-up renderer-only fix on top of it, so the skill returns to the pre-renderer SKILL.md flow while the longer fixes are worked separately. |
||
|
|
1cd4a7f5c0 |
fix(skills): HALT renderers on missing config keys and bad overrides (#2588)
Two silent-corruption paths in the bmad-quick-dev/bmad-dev-auto
template renderers now HALT instead:
- A {{.var}} referenced by the skill's .md sources but absent from the
merged central config previously rendered as an empty string with
exit 0 (missingkey=zero), baking a corrupted workflow (e.g. missing
planning_artifacts yields "List files in ``") with no failure signal.
render.py now collects the referenced names before rendering and
HALTs naming the missing key(s) and the referencing file(s). The
dedicated implementation_artifacts guard stays: it runs before the
derive step and also catches present-but-empty values.
- An optional customization layer (_bmad/custom/<skill>.toml, its
.user.toml, or the optional central-config layers) that exists but
fails to parse or read previously warned on stderr and continued
with {} — silently discarding the user's overrides; unattended
dev-auto runs never see stderr. Missing stays fine (layers are
optional); unparseable or unreadable now HALTs.
Both render.py copies change in lockstep (parity test); regression
tests added to both renderer suites.
|
||
|
|
64157d394c |
feat(dev-auto): render templates via stdlib Python at skill entry (#2587)
Propagate bmad-quick-dev's render.py pattern (#2281) to bmad-dev-auto. SKILL.md becomes the two-line stdout-dispatch shim that runs render.py via uv and follows the instruction it prints; the old SKILL.md body moves to workflow.md, rendered to _bmad/render/bmad-dev-auto/ with all compile-time values baked in. - render.py is a copy of quick-dev's, differing only in skill-name references; a test guards against the two copies drifting apart. - Compile-time config refs ({communication_language}, {planning_artifacts}, {implementation_artifacts}, {deferred_work_file}, {document_output_language}) become {{.var}} substitutions resolved from the central four-layer TOML config. Runtime refs ({spec_file}, {diff_output}, ...) pass through. - [workflow] customization resolves at render time: on_complete inlines into the HALT On Complete section, implementation_handoff into step-03, and review_layers materialize as invocation blocks in step-04 — the runtime resolve_customization.py calls and the activation-time workflow-block resolution step are gone, along with the Load Config activation step (values are baked at point of use; the language rule moves into each step's RULES). - Step files now reference workflow.md instead of SKILL.md; step-02 resolves the spec template's date field; step-04 defines {date} for the triage-log header. - tools/validate-file-refs.js whitelists render/bmad-dev-auto/; test:renderer now also runs the new test/test-dev-auto-renderer.js. - docs: the dev-auto reference's Context Inputs now names the central _bmad/config.toml surface instead of _bmad/bmm/config.yaml. |
||
|
|
49069b8b52 |
feat(quick-dev): render templates via stdlib Python at skill entry (#2281)
* feat(quick-dev): render templates via stdlib Python at skill entry Move compile-time variable substitution out of the LLM and into a deterministic Python step. SKILL.md becomes a two-line stdout-dispatch shim that runs render.py and follows the instruction it prints. The renderer reads BMad configuration from the central four-layer TOML surface introduced in #2285 (_bmad/config.toml plus config.user.toml and the two _bmad/custom/ overrides), with a fallback to the legacy per-module _bmad/bmm/config.yaml for pre-#2285 installs. Compile-time refs ({{.var}}) get substituted at render time. LLM-runtime refs ({var}) pass through untouched. Renderer (render.py) - Python 3 stdlib only (tomllib, already bundled since 3.11). UTF-8 I/O. Every invocation rebuilds from scratch — no hash, no cache. - find_project_root walks up from cwd; HALT to stdout if no _bmad/ is found anywhere on the path. - load_central_config deep-merges the four TOML layers in priority order (base-team → base-user → custom-team → custom-user) so user overrides in _bmad/custom/config.user.toml win over installer- regenerated base values. flatten_central_config lifts scalar keys from [core] and [modules.bmm] into the renderer's flat namespace; module keys beat core on collision (matches the installer's own core-key-stripping behavior). - When _bmad/config.toml is absent, falls through to the legacy flat-YAML parser for _bmad/bmm/config.yaml — the renderer keeps working across the #2285 transition. - {{.var}} substitution; unresolved refs emit empty string (Go missingkey=zero semantics). - Smart defaults for planning_artifacts / implementation_artifacts / communication_language applied after config load. Derives sprint_status / deferred_work_file from implementation_artifacts. {{.main_config}} points at whichever surface was actually read. - Renders every .md in the skill dir except SKILL.md to {project-root}/_bmad/render/bmad-quick-dev/. - On success, stderr summary plus a single stdout line: "read and follow {workflow_md}". On failure, stdout HALT directive — per the Anthropic skills spec, script stdout is the defined agent- communication channel. Skill entry (SKILL.md) - Two-line shim: run python render.py, follow stdout. No template tokens in SKILL.md itself. Template conversions - workflow.md, step-01..05, step-oneshot, sync-sprint-status: convert every compile-time {var} reference to {{.var}}. Runtime refs preserved. - spec-template.md untouched (single-curly comment hint stays as documentation). Skill-prose cleanups bundled in - Remove dead step-file frontmatter: empty-string variable declarations (spec_file, story_key, diff_output, review_mode) in quick-dev step-01 and code-review step-01; empty --- --- blocks in step-03 and step-05; the specLoopIteration counter init moved from step-04 frontmatter into the step body where first-entry vs loopback semantics are explicit. - Unify the language rule across all six quick-dev step files plus workflow.md. Tooling - tools/validate-skills.js: add TPL-01 rule. Files whose name contains "template" must not contain compile-time {{.var}} substitutions. Template files seed durable, version-controlled artifacts that execute on other machines; baking a value at render time would freeze a machine-local path into every downstream artifact. - tools/validate-file-refs.js: add render/ to INSTALL_ONLY_PATHS so the validator recognizes the runtime-generated buffer. - tools/skill-validator.md: document TPL-01; deterministic rule count bumped from 14 to 15. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(quick-dev): drop render.py YAML fallback and smart defaults Single happy path: central _bmad/config.toml with four-layer merge, Python 3.11+ required (no ImportError guard), HALT if config missing. Deletes load_flat_yaml, the YAML fallback branch, the setdefault block for planning_artifacts/implementation_artifacts/communication_language, and the tomllib ImportError fallback. Part of plan-quick-dev-python-config-hardening.md (F0). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): normalize render.py paths to forward slashes On Windows, os.path.join returns backslash-separated paths that can misrender as escape sequences when later concatenated into POSIX shell strings or regexes. Normalize the project root to forward slashes after find_project_root, and use posixpath.join for every path that gets baked into rendered .md files or joined into config values. os.makedirs and os.listdir accept forward-slash paths on Windows, so their call sites stay as-is. Part of plan-quick-dev-python-config-hardening.md (F3). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): preserve source line endings in render.py Python text-mode open() with the platform default performs universal- newline translation: on Windows, LF source files get written as CRLF, producing spurious diffs when rendered output is compared against source. Pass newline="" on both the source read and the rendered write so line endings pass through verbatim. Part of plan-quick-dev-python-config-hardening.md (F4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): delete stale .md renders before rebuilding render.py rebuilds from scratch per the docstring, but makedirs(exist_ok=True) only overwrites files that still exist in the source — stale outputs from renamed/deleted source files linger in _bmad/render/bmad-quick-dev/ forever. Remove every .md in the render dir before the render loop; keep the dir itself and any non-.md files. Part of plan-quick-dev-python-config-hardening.md (F5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): scope render/ whitelist to bmad-quick-dev The previous INSTALL_ONLY_PATHS entry 'render/' was a blanket prefix that let every {project-root}/_bmad/render/... reference in any skill slip past validation. Narrow to 'render/bmad-quick-dev/' so only this skill's render buffer is whitelisted. Future skills adopting the stdout-dispatch renderer pattern add their own entries explicitly. Part of plan-quick-dev-python-config-hardening.md (F6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(quick-dev): add renderer smoke test with TOML override New test/test-quick-dev-renderer.js spins up a temp project with base _bmad/config.toml and a _bmad/custom/config.user.toml override, runs render.py, and asserts the override wins in rendered workflow.md and that sprint_status is rooted at an absolute path in the temp project. Registered as test:renderer in package.json and chained into the npm test script. Part of plan-quick-dev-python-config-hardening.md (F7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): HALT cleanly when base config.toml is unparseable Load the four config layers through a load_toml helper that marks the base _bmad/config.toml as required. A missing, unparseable, or unreadable base now prints a HALT directive to stdout and exits, instead of being silently skipped and then crashing downstream with a KeyError when a derived value (e.g. implementation_artifacts) is absent. Optional layers still warn on stderr and fall back to empty. Merge semantics are unchanged (dict-aware deep merge, override wins for lists and scalars). * fix(quick-dev): resolve render.py via {skill-root} in skill entry shim The bare `python render.py` shim assumes the agent's working directory is the skill directory, but agents run from the project root, so the script is not found. Reference it as `{skill-root}/render.py` — BMAD's standard token for a skill's installed directory, already used by every other skill's resolve_customization.py invocation — and add the one-line `{skill-root}` explainer so the model resolves it from an instruction rather than guessing. Interpreter stays `python`; the python vs python3 choice is a separate cross-platform concern. * refactor(quick-dev): resolve [workflow] customization in render.py render.py now merges the three customize layers (customize.toml -> custom/bmad-quick-dev.toml -> .user.toml) with the same structural rules as resolve_customization.py and inlines the resolved [workflow] values, so no {workflow.*} placeholder survives. workflow.md drops its Step 1 runtime resolver + manual-merge fallback; step-05 and step-oneshot drop their runtime workflow.on_complete calls. The shared resolve_customization.py and every other skill are untouched. Smoke test extended with a [workflow] override fixture covering inlining, array append, and no-leak assertions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): harden render.py invocation in the SKILL.md shim The shim called bare `python`, which can resolve to Python 2 or be absent; render.py needs 3.11+ for tomllib. Spell out python3 and the version requirement. Also make the exit code authoritative: on a non-zero exit (including an uncaught crash that writes only to stderr), do not proceed -- report what was printed and stop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(quick-dev): drop the render.py success stderr line The "rendered N files" progress line was pure diagnostic noise. The shim already tells the LLM to ignore stderr and follow the stdout instruction, so on success render.py now prints only the "read and follow ..." line. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(quick-dev): drop the activation gate sentence from the rendered workflow The gate ported from #2398 defended against runtime customization indirection: agents guessed resolver outputs instead of executing them, silently skipping append steps. render.py inlines the prepend/append entries into the rendered workflow.md, so there is nothing left to short-circuit, and each inlined list already carries its own execute- in-order imperative. In the default install both lists render as _None._ and the gate is pure noise. * feat(quick-dev): materialize review layers into invocation blocks Reconcile #2550 with render-time [workflow] resolution. Main made review layers configurable as [[workflow.review_layers]] arrays of tables and had the LLM resolve them during activation; this branch resolves the [workflow] block in render.py instead, so activation-time resolution no longer exists and the layer refs must be materialized at render time. Rather than inlining the layer tables as data plus interpretation rules, render.py now knows this skill's customization schema outright and renders review_layers/oneshot_review_layers as direct invocation blocks: disabled layers (empty instruction) drop out, each active layer becomes a #### section holding its instruction verbatim, zero active layers renders the HALT instruction, and runtime placeholders like {diff_output} pass through. The only judgment left to the LLM is the optional `when` condition, which renders as a run-time guard line. The step-04/step-oneshot review intros collapse to a single execute-in- parallel imperative. Smoke test covers default rendering, replace-by-id, disable-by-empty-instruction, when-guards, and the all-disabled HALT. * fix(quick-dev): invoke render.py via uv run per house standard The SKILL.md shim launched render.py with bare `python3`, which the rest of BMAD is migrating away from: the customize-bmad docs and the installer's uv-check standardize on `uv run` (uv provisions a suitable 3.11+ interpreter on demand). Bare `python3` is also fragile on Windows, where python.org installs expose `python`/`py` rather than `python3`. Make `uv run` the primary invocation and demote `python3` to the documented fallback, spelling out `python`/`py -3` for Windows and the 3.11+ tomllib requirement. render.py itself is unchanged; the renderer test drives it directly and is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(quick-dev): HALT cleanly on missing or malformed config render.py derived sprint_status/deferred_work_file from an unconditional vars_["implementation_artifacts"] subscript, so a config lacking that key raised a raw KeyError instead of the stdout HALT the rest of the script uses on bad input. flatten_central_config likewise called .get("bmm") on merged["modules"] without checking it was a table, so a non-table [modules] crashed with an AttributeError. Guard both: HALT with a clear stdout directive when implementation_artifacts is missing or blank, and coerce a non-dict modules to {} before indexing. Add renderer regression tests asserting each path exits without a Python traceback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(quick-dev): resolve config at compile time, drop the runtime re-read The activation "Load Config" step told the LLM to open {{.main_config}} and re-resolve project_name, communication_language, sprint_status, etc. at run time -- but render.py already bakes those from the full four-layer config merge. main_config pointed at only the base _bmad/config.toml, so on installs with override layers (config.user.toml / custom/*) the runtime re-read saw stale values that could contradict the baked {{.var}} in the same rendered file. It also handed resolution back to the LLM: the drift this skill's renderer exists to remove. Delete the ceremony and wire each value where it is actually used: - Every value the step resolved is already inlined at its point of use (planning/implementation_artifacts, sprint_status, communication_language) or loaded via persistent_facts (project-context.md), so the central block was pure redundancy. - Fold document_output_language into the per-step language rule, adopting the house-canonical form ("Speak in X. Write any file output in Y.") already used by bmad-checkpoint-preview. - Move the {date} = current-datetime definition to step-02, where the spec template's {date} field is filled. - Drop the user greeting (user_name) and user_skill_level tailoring: quick-dev is not a conversational skill and neither was load-bearing. - Remove main_config from render.py; it had no remaining consumer. Renderer tests repointed at the files that now carry these values, plus coverage for document_output_language baking and main_config removal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(quick-dev): reference variables by bare name, not placeholder curlies Curlies mean "expand this to the value"; a bare backticked name means "this is the variable/field I'm talking about". Several step files wrapped a variable in curlies where they were only naming, assigning, passing, or testing it -- so the notation implied an expansion that never happens: - step-01: identify `epic_num`/`story_num`, set/leave `story_key` unset - step-02: test `preserved_intent`; and resolve the template's `date` field (was `{date}`, which read as "expand date here" rather than naming it) - step-03/step-05/step-oneshot: pass `target_status` to sync-sprint-status, set `title` - sync-sprint-status: the `target_status` parameter, `story_key` precondition, and both `target_status` conditionals Value tokens that are genuinely materialized in place -- `{spec_file}` paths, `development_status[{story_key}]`, "set ... to `{target_status}`" -- stay curly. Also reword step-02's frozen-block instruction from the ambiguous "substitute it for the `<frozen-after-approval>` block" to "replace the `<frozen-after-approval>` block in the spec you just filled out with `preserved_intent`" so it's clear the replacement happens in the artifact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(quick-dev): require uv, drop the python3 interpreter fallback The SKILL.md shim tried `uv run render.py` and, if uv was missing, retried with a bare `python3`/`py -3` interpreter. Nothing else in the codebase does that interpreter fallback: the uv-based skills (bmad-prd, bmad-ux, bmad-architecture, bmad-product-brief) fall back to reading customize.toml and using defaults -- graceful feature degradation, never a different runner -- and the legacy skills just call python3 outright. uv is the established house runner (memlog.py, resolve_customization.py, lint_spine.py all invoke it). That graceful-degrade path does not exist here: render.py is the entry dispatch that produces the workflow.md the LLM then follows, so there is nothing to fall back to. The only honest outcomes are "uv runs it" or "HALT". Make uv the floor and drop the fallback. Pin the interpreter the house way -- a PEP 723 `requires-python = ">=3.11"` block, matching memlog.py/lint_spine.py -- so `uv run` provisions a 3.11+ interpreter and the tomllib requirement is guaranteed rather than hoped for. This replaces the prose "needs 3.11+" hedge the shim used to carry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5f3ebc91ed |
feat: add Antigravity CLI (AGY) as supported installer platform (#2551)
* feat: add Antigravity CLI (AGY) as supported installer platform Distinct from the Antigravity IDE entry: the CLI reads workspace skills from the shared .agents/skills standard and its own global dir. Closes #2440. * test: assert Antigravity CLI global_target_dir differs from the IDE |
||
|
|
c0fa3231a2 |
v6.10.0: bmad-loop replaces bmad-automator, changelog draft (#2545)
* docs: draft v6.10.0 changelog; rebrand bmad-auto to bmad-loop; simplify uv check message Drafts the v6.10.0 changelog entry, headlined by bmad-loop landing as an installable module and bmad-automator's deprecation in its favor. Renames the installer's bmad-auto module registry entry (code, name, url, module-definition path, post-install message) to bmad-loop ahead of the upstream repo rename. Also simplifies the uv-detected install message to a plain pass/fail line with a checkmark, since the prior "ready to run BMAD's Python-powered scripts via uv run" phrasing read as more actionable than it was. * feat(installer): support module-code aliases, migrate bauto to bmad-loop Adds a bauto -> bmad-loop registry alias so existing installs migrate forward on quick-update (and the interactive Modify flow) instead of being orphaned as "no source available" the way the prior baut -> automator rename was (CHANGELOG v6.7.1). ExternalModuleManager resolves aliases in getModuleByCode/resolveCanonicalCode; quickUpdate translates installed ids up front and removes the stale _bmad/<alias>/ directory after a successful migration. removals.txt gains bmad-auto-setup, the renamed skill id, so stale IDE-side skill dirs get pruned too. Also corrects bmad-modules.yaml's bmad-loop entry to match the real upstream repo content (src/bmad_loop/..., bmad-loop-setup skill) now that the bmad-auto -> bmad-loop rename has actually landed there, and moves bmad-loop to the top of the installer picker with a shorter, less wrap-prone description. |
||
|
|
35b19db2e3 |
fix(installer): accept windows custom module paths (#2511)
* fix(installer): accept windows custom module paths * fix(installer): reject versioned windows local paths * style: format custom module manager --------- Co-authored-by: Brian <bmadcode@gmail.com> |
||
|
|
4b1cb84b97 | style(test): format validate-skills regression test (#2503) | ||
|
|
c9813c6862 |
fix(validate-skills): exempt deprecated skills from SKILL-06 trigger (#2486)
* fix(validate-skills): exempt deprecated skills from SKILL-06 trigger SKILL-06 flagged deprecated compatibility shims for missing a "Use when" trigger phrase. Deprecated skills omit it on purpose so users are steered to their replacement, so exempt them from that specific check. - detect deprecation via description starting with "DEPRECATED" - keep the other SKILL-06 check (length) and all other rules applying - add test/test-validate-skills.js + fixtures, wired into npm test * test(validate-skills): document test helpers with JSDoc Added JSDoc to the test/assert/hasTriggerFinding helpers so the new test file documents its own helpers. No behaviour change — the suite still passes 3/3. |
||
|
|
02739932bc |
feat(installer): check for uv and standardize messaging on uv run (#2495)
Replace the standalone python3 environment check with a uv check, since uv is becoming the de facto standard for running BMad's Python scripts (`uv run <script>`) and uv provisions the interpreter itself. Installer: - Remove tools/installer/core/python-check.js and its wiring in ui.js - Add tools/installer/core/uv-check.js: warn-don't-block, no ack prompt (the migration is in progress, so a missing uv never blocks install). Missing uv warns and points the user at setup, preferring "ask your agent to set up uv" - Add a uv heads-up to the install intro (install-messages.yaml) and a uv tip line to the final "BMAD is ready" summary box - Swap test Suite 46 from python-check to uv-check coverage Docs and script comments (no functional skill invocations changed): - resolve_config.py / resolve_customization.py docstrings: drop the "No uv ... plain python3 is sufficient" claims; frame uv run as the standard, python3 as the transition fallback; examples use uv run - customize-bmad.md (en/fr/vi-vn): same reframing; example commands use uv run - Update uv run hints in brain.py / list_customizable test comments |
||
|
|
5bcc235cdb | fix(installer): guard WSL installs from Windows Node (#2470) | ||
|
|
560a2e3a6f |
feat: installer detects Python version and warns when 3.11+ (tomllib) is missing (#2466)
* feat: installer detects Python version and warns when 3.11+ (tomllib) is missing Several BMAD features need Python at runtime: memlog (3.8+) and the TOML config resolution scripts (3.11+ for stdlib tomllib). Users install into varied environments (Linux, Windows, WSL, Docker) where Python may be missing or too old, and previously only found out via runtime errors. The installer now probes PATH at startup (py -3 / python3 / python) and classifies the result: 3.11+ passes silently with a success line; 3.8-3.10 or missing/too-old Python gets a warning naming exactly which features degrade, plus per-platform install hints. The warning requires an explicit ack — continue (fix later, no reinstall needed) or quit and re-run after installing Python. Warn-don't-block: most of BMAD works without Python, so the install is never refused. In --yes mode the warning logs and continues without prompting. * fix: align Python check with runtime truth (python3) and harden edge cases Review fixes for the installer Python check: - Probe python3 first on all platforms: every runtime call site invokes a literal python3, so only that command vouches for BMAD features. Python found via py/python now gets an explicit mismatch warning instead of a false "all BMAD features supported". - Treat closed/piped stdin as non-interactive (in addition to --yes) so scripted installs no longer silently exit 0 via clack's cancel path. - Retry probes with shell:true on win32 EINVAL (CVE-2024-27980 hardening rejects .bat/.cmd shims like pyenv-win's without a shell). - Add Suite 46 branch tests for checkPythonEnvironment with stubbed detection, prompts, and process.exit. |
||
|
|
fbb48ed711 |
fix: remove empty skill-group dirs left in _bmad after install (#2461)
* fix: remove empty skill-group dirs left in _bmad after install Skill cleanup removed each skill's own directory but never pruned the now-empty grouping folders above it (e.g. _bmad/bmm/1-analysis), leaving empty dirs behind after every install. Walk up from each removed skill dir and drop empty parents, stopping at the bmad root. * fix: harden empty-parent pruning boundary and cleanup Use a path-boundary check instead of a string prefix so sibling dirs (e.g. _bmad2) can't match the bmad root, and make the walk best-effort so a dir that vanishes or fills in mid-walk never aborts the install. Move the test fixture cleanup into finally so failures don't leak temp dirs. --------- Co-authored-by: Brian <bmadcode@gmail.com> |
||
|
|
397b2a5c87 |
feat: add CodeWhale as supported installer platform (#2459)
CodeWhale uses .codewhale/skills/ (project) and ~/.codewhale/skills/ (global) for skill directories, matching the existing config-driven installer pattern. - platform-codes.yaml: codewhale entry after codex - test: Test 12b validates install target and setup |
||
|
|
74cf467d57 |
v6.7.0: bundle module registry, retire marketplace, refresh display names (#2388)
* feat(installer): bundle module registry, retire marketplace, refresh display names Prepares v6.7.0 for release: - Moves bundled module list from tools/installer/modules/registry-fallback.yaml to bmad-modules.yaml at repo root; renames to reflect single-source-of-truth role. - Retires the remote marketplace registry fetch in ExternalModuleManager; the installer now reads the bundled YAML only. - Adds WDS (Whiteport Design Studio) entry alongside BMM, BMB, BMA, CIS, GDS, TEA. - Refreshes display names and descriptions on every bundled module; TEA repositioned after BMM in the picker. - Adds plugin_name override field on registry entries so modules whose marketplace.json declares a plugin under a different name than the installer code (e.g. WDS uses bmad-wds) match without falling back to the single-plugin heuristic. - Removes the community modules picker from the interactive installer; previously installed community modules are preserved on update and can still be installed via --custom-source. - Renames the custom-source confirm prompt for clarity. CHANGELOG.md updated with the full v6.7.0 entry. * feat(installer): fully retire community catalog plumbing Removes the last marketplace network connections from the installer. The v6.7.0 first pass retired the official-registry fetch but left CommunityModuleManager + RegistryClient in place, which still fetched community-index.yaml and categories.yaml on every install to support the channel-gate and update flows. This commit: - Deletes tools/installer/modules/community-manager.js and registry-client.js entirely. - Strips CommunityModuleManager calls from ui.js (channel gate + update channels), core/manifest.js (getModuleVersionInfo), core/installer.js (resolution + installed-modules listing), and modules/official-modules.js (findModuleSource fallback + pre-install plugin resolution + post-install manifest entry). - Simplifies installFromResolution: community branch removed; all non-external installs are now treated as custom-source. - Removes corresponding test suites (CommunityModuleManager unit tests and the entire RegistryClient suite). - Updates CHANGELOG with the migration note. After this commit, grep confirms zero references to the bmad-plugins- marketplace registry from the installer. The only remaining 'marketplace' references are about per-repo .claude-plugin/marketplace.json files, which the installer reads from cloned custom-source repos. |
||
|
|
9debc165aa |
fix(installer): remove bmad-help from Copilot Custom Agents picker (#2359)
* fix(installer): remove bmad-help from Copilot Custom Agents picker Per @BMadCode's feedback after #2324 merged: every persona agent's activation message already advertises bmad-help, so its picker entry is redundant AND confusing (looks like a peer agent when it's actually the meta-help). Removes the ALWAYS_AGENT_IDS allowlist exception that put it there. The toml-driven filter (the mechanism BMadCode endorsed in his PR review) remains the sole signal: a skill is a persona iff its source customize.toml has an [agent] section. bmad-help has no customize.toml, so under the cleaned-up filter it's correctly excluded. Tests: replaces the inclusion assertion in Suite 17 with an exclusion assertion. Suite still covers persona / non-conventional persona / workflow / meta-skill-with-`-agent-`-in-name cases. Refs #2324 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test: clarify Suite 17 fixture comment per PR review The fixture creates no customize.toml at all for bmad-help, so the exclusion path being exercised is the missing-file branch — not the file-without-[agent]-section branch. Reword the comment accordingly. Per @augmentcode review on #2359. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
65b810a11f |
fix(installer): generate slash-command and Agent pointer files (OpenCode + GitHub Copilot) (#2324)
* fix(installer): generate OpenCode /<skill> slash commands Adds .opencode/commands/<canonicalId>.md pointer files for each installed skill so users can invoke skills directly (e.g. /bmad-quick-dev) instead of going through the /skills menu. - platform-codes.yaml: add commands_target_dir field for opencode - _config-driven.js: installCommandPointers() with skip-if-exists default, reserved-name collision guard, YAML-safe description quoting - _config-driven.js: cleanupCommandPointers() for symmetric uninstall - test-installation-components.js: extend OpenCode suite with assertions covering pointer creation, content, and idempotency OpenCode-only and opt-in via the new yaml field; other adapters unchanged. Refs #2267 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(installer): address PR #2324 review feedback Six fixes from CodeRabbit + Augment review on the OpenCode command pointer generation: - skipTarget no longer suppresses installCommandPointers in multi-IDE shared-target_dir batches. Pointers live in a per-IDE directory and are not deduped across peers, so OpenCode must still generate them even when a peer (e.g. openhands) won the .agents/skills write race. - skipTarget no longer suppresses cleanupCommandPointers either, so partial uninstalls leave no stale pointers when a peer remains. - canonicalId is validated as a safe basename before being interpolated into a file path (defense in depth against a malformed manifest entry writing outside commands_target_dir). - yamlSafeSingleLine now quotes descriptions starting with `[` or `{` so YAML doesn't parse them as a sequence/map. - Per-record fs.writeFile failures are caught and counted (writeFailures) rather than aborting the whole IDE install — pointer files are a non-essential adjunct to the skill copy. - Generator-shaped pointer files are refreshed when the manifest description changes; hand-modified files (body diverges from the generator pattern) are still preserved unless forceCommands is set. Tests: extends Suite 8 with description-update propagation; adds new Suite 40c covering OpenCode + openhands batches in both orderings plus partial-IDE uninstall pointer cleanup. 308 tests pass (was 296). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(installer): address PR #2324 follow-up nitpicks Four nitpicks from CodeRabbit's original review that were missed in the first triage pass: - Hand-edited pointers now survive the production install flow. cleanupCommandPointers spares pointers for canonicalIds that are still in the new manifest when called from the install/update flow (signal: options.previousSkillIds is set). Uninstall and partial-IDE removal flows still wipe pointers as before. The previous behavior wiped every pointer in removalSet before installCommandPointers could run, so its skip-if-exists guard never fired and hand edits were lost on every reinstall — contradicting the docstring's preservation claim. - RESERVED_OPENCODE_COMMANDS is now gated on this.name === 'opencode' so future adapters opting into commands_target_dir don't silently inherit OpenCode's reserved-name set. - printSummary now surfaces results.commands so users see how many pointers were created/refreshed/skipped per install, plus a warning for any per-file write failures. - Dropped a dead `typeof entry !== 'string'` check; fs.readdir without withFileTypes always yields strings. Tests: extends Suite 8 with a hand-edit-preservation regression that calls setup with previousSkillIds (the production shape) and asserts a sentinel byte sequence in the pointer body survives. 310 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(installer): extend command-pointer generation to Copilot Custom Agents Re-scopes #2324 to cover the second user-facing pain: GitHub Copilot's Custom Agents picker, where installed BMAD skills currently don't show up even though slash commands work natively. Generalizes the per-platform pointer-file mechanism so the same installCommandPointers / cleanupCommandPointers code path serves both OpenCode (slash commands palette) and Copilot (Custom Agents picker), with all platform-specific shape pushed into platform-codes.yaml as data: - commands_target_dir — where pointer files live (existing) - commands_extension — file extension (default '.md'; Copilot uses '.agent.md' per VS Code Custom Agents docs) - commands_body_template — pointer body, supports {canonicalId} and {target_dir} placeholders. Default matches OpenCode's `@skills/<id>` resolver. Copilot has no such resolver, so its template uses the {project-root}/<target_dir>/<id>/SKILL.md LOAD pattern (consistent with PR #1769). OpenCode behavior is unchanged. Copilot users now get a per-skill .github/agents/<canonicalId>.agent.md file that surfaces the skill in the Custom Agents picker — addressing the "agents being gone" complaint flagged by enterprise users. Tests: extends Suite 17 with assertions for Copilot agent pointer creation, body content (LOAD pattern with {project-root}-rooted path), and idempotency. 318 tests pass (was 310). Refs #2267 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(installer): filter Copilot Custom Agents picker to persona agents only Earlier commit naively wrote a `.github/agents/<id>.agent.md` for every installed skill, which would clutter the Custom Agents picker with 90+ workflow/tool entries that don't belong there. Adds an `agents-only` filter that gates the per-skill emission on whether the canonical id signals a persona agent: - Primary rule: id contains `-agent-` (e.g. `bmad-agent-pm`, `gds-agent-game-dev`, `wds-agent-freya-ux`, `bmad-cis-agent-storyteller`). - Allowlist: `bmad-tea` — TEA's Murat persona uses the bare module code rather than the `-agent-` convention. Listed explicitly so the rule still surfaces it. Verified against the full installed manifest (114 skills): catches all 20 description-confirmed personas across BMM, CIS, GDS, WDS, TEA; excludes all 94 workflows/tools. Wired through a new yaml field on github-copilot: commands_filter: agents-only OpenCode is unaffected — it has no `commands_filter` set, so the loop behaves as before (every skill becomes a slash command). Tests: extends Suite 17 with a multi-skill manifest fixture covering persona/agent + bmad-tea + workflow cases; asserts persona agents and bmad-tea get .agent.md files while workflows do not. 322 tests pass. Refs #2267 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(installer): detect personas via customize.toml [agent] section Per maintainer review on PR #2324: the `-agent-` naming convention isn't a load-bearing contract anywhere else in the codebase, and the bmad-tea allowlist already shows it starting to break. A future persona that doesn't follow the convention would silently disappear from the Copilot Custom Agents picker. Replaces the name-based filter with a behavior-based signal: read each skill's source `customize.toml` and check for an `[agent]` section. This is the actual configuration source of truth — every BMAD persona is configured under `[agent]`, every workflow under `[workflow]`, every standalone skill has no customize.toml. Verified on disk against the full installed manifest (114 skills): - 20 personas detected — exactly the description-confirmed count across BMM, CIS, GDS, WDS, TEA. bmad-tea is caught natively (no allowlist). - 94 workflows/tools correctly excluded. - `bmad-agent-builder` (meta-skill that builds agent skills) is now CORRECTLY excluded — its canonical id contains `-agent-` but its customize.toml has [workflow], not [agent], because it isn't a persona itself. The previous naming-based filter was including it in the agents picker, which would have been a silent UX bug. `NON_CONVENTIONAL_AGENT_IDS` constant is removed entirely — the toml signal subsumes it. Tests: extends Suite 17 with a 4-skill fixture that covers persona + non-conventional persona + workflow + meta-skill cases. 388 tests pass. Refs #2267 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(installer): always include bmad-help in Copilot agents picker Adds a single, deliberate exception to the toml-based agents-only filter: `bmad-help` is the structural meta-skill across BMAD — the orientation helper that points users at every other skill. Users invoke it persona-style ("ask the helper") even though it has no `[agent]` customize.toml of its own (it isn't a configurable persona). Implemented as a one-element ALWAYS_AGENT_IDS set rather than a hardcode in the function body so the exception is named, documented, and discoverable. The skill is structurally unique — there is no second meta-help skill — so this is not the start of a growing allowlist; it's a one-off for the one orientation surface BMAD ships. Verified on disk: agents picker now shows 21 entries (20 personas via [agent] in customize.toml + bmad-help). bmad-agent-builder stays correctly excluded (its customize.toml has [workflow], not [agent]). Tests: extends Suite 17 with a `bmad-help` fixture (no customize.toml, must still appear in agents picker). 389 tests pass. Refs #2267 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Brian <bmadcode@gmail.com> |
||
|
|
fcf20f1c7b |
Fix/azure devops url parsing (#2269)
* fix(installer): handle deep-path URLs in custom module source parser Rewrite parseSource() from host-specific regex to generic URL-based parser so Azure DevOps _git paths and other multi-segment repo URLs are preserved in cloneUrl and cacheKey. Closes #2268 * test(installer): add Azure DevOps URL tests and wire into CI - Add 18 assertions for dev.azure.com and visualstudio.com URLs - Cover modern ADO, legacy ADO, .git suffix, ?path= subdir variants - Add test:urls script to test and quality npm chains --------- Co-authored-by: Brian <bmadcode@gmail.com> |
||
|
|
91a57499e9 |
feat(installer): add --set and --list-options for non-interactive config (#2354)
Closes #1663. Adds two installer flags so module config options can be set without interactive prompts. Designed for CI scripts, Dockerfiles, and enterprise rollouts where the user wants to bake answers into the install command rather than answer prompts. `--set <module>.<key>=<value>` (repeatable) sets any module config option. `--list-options [module]` lists every key the installer can discover locally — built-in modules (`core`, `bmm`) plus any cached official modules. One flag scales to every module without growing the CLI surface per option. ```bash npx bmad-method install --yes \ --modules bmm --tools claude-code \ --set bmm.project_knowledge=research \ --set bmm.user_skill_level=expert \ --set core.user_name=Brian ``` ## How it works `--set` is a post-install patch. The installer runs its normal flow untouched, then `applySetOverrides` upserts each value into the relevant config files: - `_bmad/config.toml` (team scope, default) - `_bmad/config.user.toml` (user scope, when the key already lives there — so user-scope keys like `core.user_name` and `bmm.user_skill_level` keep their proper file) - `_bmad/<module>/config.yaml` (so declared schema keys carry forward via the existingValue path on the next install) A module without `_bmad/<module>/config.yaml` is skipped silently — no orphan sections in `config.toml` for uninstalled modules. ## Tradeoffs documented in install-bmad.md - **Verbatim values.** `--set bmm.project_knowledge=research` writes `"research"`, not `"{project-root}/research"`. The `result:` template is not applied. Pass it explicitly if you want the rendered form: `--set bmm.project_knowledge='{project-root}/research'`. - **Carry-forward, declared keys.** Free — values land in the per-module `config.yaml`, so the next install reads them as `existingValue` and they become the prompt default (accepted under `--yes`). - **Carry-forward, undeclared keys.** Best-effort. The value lives in `config.toml` for the current install but won't be re-emitted on the next install (the manifest writer's schema-strict partition drops unknown keys). Re-pass `--set` if needed. - **No "key not in schema" validation.** Whatever you assert is written. ## Security Prototype-pollution defense: `--set __proto__.x=1` would otherwise reach `overrides.__proto__[x] = 1` and pollute `Object.prototype`, cascading into every plain-object lookup in the process. Defense-in- depth via parser-level reserved-name rejection (`__proto__`, `prototype`, `constructor`) AND `Object.create(null)` for the override maps. Verified the attack reproduces without the guard and is blocked with it. ## What's intentionally NOT integrated `--set` deliberately does not touch the prompt / template / schema collection flow. No pre-seeding answers, no question filtering, no function-default evaluation, no schema-strict partition exemption. That earlier integration approach was tried and scrapped: it spread state across `Config`, `OfficialModules`, `manifest-generator`, both collection helpers, and required parallel plumbing for quick-update — every bug fix touched a different layer. The post-install patch model covers the actual user need (set a config value from CI) in ~330 lines of `set-overrides.js` without the schema gymnastics. ## Files - `tools/installer/set-overrides.js` (new): parser, prototype-pollution guard, `applySetOverrides` post-install patch, `upsertTomlKey` / `tomlString` / `tomlHasKey` line-based TOML helpers - `tools/installer/list-options.js` (new): module.yaml discovery + formatter for `--list-options` - `tools/installer/commands/install.js`: register `--set` / `--list-options` flags, early validation, `--list-options` exit-code handling (await `stream.write` callback then `process.exitCode` to avoid truncating piped output), thread `setOverrides` through to quick-update - `tools/installer/core/config.js`: carry `setOverrides` field for the post-install patch step - `tools/installer/core/installer.js`: invoke `applySetOverrides` after `writeCentralConfig` (covers regular install + quick-update via the shared install path) - `tools/installer/ui.js`: parse `--set` for early validation, warn about overrides targeting modules not in `--modules`, drop those entries before threading - `docs/how-to/install-bmad.md`, `README.md`: usage, routing rules, carry-forward semantics, tradeoffs ## Test plan Suite 44 (24 cases): parser, prototype-pollution guard, `tomlString` escaping, `upsertTomlKey` across insert/replace/missing-section/ empty-file/preserved-newline cases, `applySetOverrides` happy path + uninstalled-module skip + missing-user-toml-creation + empty-input no-op, `discoverOfficialModuleYamls` / `formatOptionsList` sanity (hermetic via `BMAD_EXTERNAL_MODULES_CACHE` temp dir). 355 total passing. Lint + prettier + markdownlint clean. E2E smoke verified across: - [x] `--set` writes correct files (team toml / user toml / per-module yaml) for declared and undeclared keys - [x] Quick-update without `--set` carries forward declared keys via `existingValue` path - [x] Quick-update WITH `--set` applies cleanly (uniform behavior across action types) - [x] `--set` for unselected module: warned, no orphan section - [x] Prototype pollution: rejected with non-zero exit - [x] `--list-options bmm` exit 0 with full output through pipe; `--list-options nope` exit 1 - [x] Translated docs (`docs/{cs,fr,vi-vn,zh-cn}/`) intentionally not touched — they'll lag behind English until the translation pipeline runs |
||
|
|
3da984a491 |
fix(config): promote project_name to core (closes #2279) (#2348)
* fix(config): promote project_name to core, fixes #2279 project_name was a bmm-specific prompt despite being a universal project-level concept used by every module — including core skills like bmad-brainstorming, which loads from _bmad/core/config.yaml and was silently broken because project_name lived under bmm. Users without bmm installed could not run brainstorming at all. Move: - src/core-skills/module.yaml: declare project_name with prompt "What is your project called?" and default {directory_name}, matching what bmm previously had. - src/bmm-skills/module.yaml: remove the bmm definition; add project_name to the "Variables from Core Config inserted" header comment so contributors can see what's inherited. Migration for existing installs: - tools/installer/modules/official-modules.js: after loadExistingConfig reads each per-module config.yaml, hoist any keys that are now declared in core but appear under non-core modules. Without this, the partition logic in writeCentralConfig (which strips core keys from non-core buckets) would silently drop the user's prior project_name on the next quick-update. Generic — handles project_name today and any future module→core promotions. - The hoist preserves precedence: an existing core value beats a stale module-side copy. --yes seed: - tools/installer/ui.js: add project_name to the hardcoded core seed (using path.basename(directory) to match the {directory_name} default) so non-interactive fresh installs populate it. Without this the seed silently omits project_name and core skills fall back to literals. Tests: - test/test-installation-components.js Suite 43 (9 assertions) covers the schema move, the loadExistingConfig hoist, and the precedence rule. - Suite 35 fixture updated: project_name moved from bmm bucket to core, with a stale bmm copy left in place to verify it gets stripped. Verified manually: - Fresh install -y: project_name lands in [core] of config.toml. - Existing install with project_name in bmm/config.yaml: quick-update hoists it to [core] and strips it from [modules.bmm]. * fix(installer): harden config-load against malformed config.yaml Per augment review on #2348: loadExistingConfig stored any truthy yaml.parse result (including scalars like '42'), which would later crash _hoistCoreKeysFromLegacyModuleConfigs at \`key in cfg\` with "Cannot use 'in' operator to search for ... in 42". - loadExistingConfig: only keep parses that are plain objects (not scalars or arrays). A corrupt config.yaml is now treated the same as a parse error — skipped, not crashed-on. - _hoistCoreKeysFromLegacyModuleConfigs: belt-and-suspenders type guards on _existingConfig.core (in case it's populated by some other path) and on each module cfg in the loop. - Test Suite 43 adds 2 assertions covering a scalar core/config.yaml: loadExistingConfig must not crash, and bmm.project_name must still hoist into a clean core bucket. |
||
|
|
7ee5fa313b |
fix(installer): require --tools for fresh --yes installs; remove --tools none (#2346)
* fix(installer): require --tools for fresh --yes installs; remove --tools none (closes #2326) Fresh non-interactive installs without --tools previously produced a config-only install (~35 files vs ~1400 in the manifest) with no warning and a "BMAD is ready to use" success card, leaving slash commands unreachable. --tools none was an explicit opt-in for the same broken state. Now: fresh install + -y without --tools throws a helpful error pointing at --list-tools. --tools none is rejected as an unknown ID. Empty and typo'd tool IDs are also rejected. Existing-install paths (--action update, quick-update, modify) are unchanged - they continue to reuse previously-configured tools when --tools is omitted. Adds --list-tools flag that prints all 42 supported tool IDs (id, name, target_dir, preferred star) sourced from platform-codes.yaml. English docs updated; localized docs (vi-vn, fr, cs, etc.) will sync via the normal translation pass. * fix(installer): address review for #2326 — single source of truth, drop dead code, add tests - Refactor formatPlatformList to use IdeManager so --list-tools and --tools validation see the same set of platforms. Eliminates the drift where suspended platforms appeared in --list-tools but were rejected at validation. - Drop unused getValidPlatformIds export. - Flatten redundant block scope around the throw in the --yes-without-tools branch (refactor leftover). - Drop dead String() defensive cast (Commander always passes a string). - Add Test Suite 42: 8 unit tests covering _parseToolsFlag empty/whitespace/ unknown/typo cases plus an integration check that --list-tools output and --tools validation agree on the ID set. * fix(installer): close --tools "" bypass and drop hardcoded tool count - Replace truthy `if (options.tools)` guard with `!== undefined` in both upgrade and fresh-install branches. Empty string now reaches _parseToolsFlag and produces the specific "passed empty" error instead of falling through to a generic message (fresh-install) or being silently ignored (existing-install). - Drop the hardcoded "42 supported tools" count from the prereqs in install-bmad.md so the doc doesn't drift as platform-codes.yaml changes. Addresses augment / coderabbit review on #2346. |
||
|
|
01cc32540b |
feat(installer): expand to 42 platforms with shared target_dir coordination (#2313)
* refactor(installer): replace legacy_targets auto-cleanup with upgrade warnings Removes the legacy_targets YAML field and its install-time auto-migration of pre-v6.1.0 directories (.claude/commands, .opencode/agents, etc.). On install, surface a warning instead: read manifest version and scan 24 known legacy paths, then print rm -rf commands the user can run themselves. Also deletes orphan tools/platform-codes.yaml (never loaded by any code) and fixes a stale URL in the cs translation. * feat(installer): consolidate to .agents/skills and add global_target_dir for all platforms Updates platform-codes.yaml against verified primary docs for all 24 supported platforms. 14 platforms (auggie, codex, crush, cursor, gemini, github-copilot, kilo, kimi-code, opencode, pi, roo, rovo-dev, windsurf) move their project target_dir to the cross-tool .agents/skills/ standard. Junie moves from the broken .agents/skills/ to its own .junie/skills/ per JetBrains docs. Adds global_target_dir to every platform: 11 share ~/.agents/skills/, Crush uses XDG ~/.config/agents/skills/, Codex global stays ~/.codex/skills/, the rest are tool-specific. Ona and Trae omit global (no documented home path). Note: installer logic does not yet dedupe writes for platforms sharing a target_dir — users installing multiple .agents/skills/ tools together will overwrite the same files (harmless on install, but uninstalling one clears the dir for the others). Coordination logic is the next step. * feat(installer): add 18 new platforms, dedup shared target_dir, ownership-aware cleanup Adds 18 platforms from the verified Vercel list (adal, amp, bob, command-code, cortex, droid, firebender, goose, kode, mistral-vibe, mux, neovate, openclaw, openhands, pochi, replit, warp, zencoder). Marks codex and github-copilot as preferred alongside claude-code and cursor. Coordination for platforms sharing a target_dir: - IdeManager.setupBatch dedups skill writes when multiple selected platforms point at the same target_dir (e.g. .agents/skills/). The first platform writes, peers skip the redundant wipe-and-rewrite. Result reports the same count and target dir for every member so the install summary is consistent. - IdeManager.cleanupByList accepts remainingIdes; when removing one platform from a shared dir while another co-installed platform still owns it, the target_dir wipe is skipped. Platform-specific hooks (copilot markers, kilo modes, rovodev prompts) still run. - _setupIdes uses setupBatch; _removeDeselectedIdes passes remainingIdes so partial reconfigure preserves shared skills. Skill ownership now uses skill-manifest.csv canonicalIds, not the bmad- prefix. This unblocks custom modules that ship skills with non-bmad names (e.g. fred-cool-skill). Affected sites: - _config-driven.detect: reads canonicalIds from the project's bmadDir - _config-driven.findAncestorConflict: reads canonicalIds from the ancestor's own bmadDir, falling back to the prefix only when no manifest exists - legacy-warnings.findStaleLegacyDirs: same canonicalId-based detection Migration warnings: LEGACY_SKILL_PATHS adds 12 skill dirs that moved to the .agents/skills/ standard (cursor, gemini, github-copilot, kimi, opencode, pi, roo, rovodev, windsurf, plus their globals). Users with stale skills in those locations get a one-line warning with the rm command per dir. New shared helper tools/installer/ide/shared/installed-skills.js exposes getInstalledCanonicalIds(bmadDir) and isBmadOwnedEntry(entry, canonicalIds). Tests: 9 new assertions across two suites covering dedup, partial uninstall preservation, and custom-module skill detection. All 286 tests pass. * fix(installer): setupBatch must not claim a shared target_dir on failure If the first platform's setup throws or returns success: false, the dedup map previously still recorded the claim with skillCount: 0, causing every peer sharing the target_dir to skip its install — leaving the dir empty/broken behind a cascade of misleading "shares with X" rows. Now the claim is only recorded when the install succeeded and wrote skills. On failure, the next peer becomes the new first writer and recovers. Adds Suite 40b regression test that monkey-patches cursor.setup to throw and verifies gemini still populates the shared dir. * fix(installer): address PR #2313 review findings Three issues raised by augmentcode and coderabbit bot reviewers: 1. _removeDeselectedIdes silently swallowed cleanup failures after the refactor to cleanupByList. The old per-IDE try/catch logged a warning; the new path discarded the result array. Now logs a warning per failed ide so failures stay visible. 2. The legacy-dir cleanup hint printed `rm -rf "<path>"/bmad*` which both matched bmad-os-* utility skills the user should keep AND missed the custom-module skills (e.g. fred-cool-skill) that the new canonical-id detection now finds. Findings now carry the exact entry names from the scan, and the warning prints one precise rm line per entry. 3. warnPreNativeSkillsLegacy did unguarded fs reads at install start. A permission/IO error would have aborted the whole install. Wrapped the call site in try/catch so legacy-scan failures only emit a warning. |
||
|
|
0533976753 |
fix: installer live version for external modules (#2307)
* resolved merge conflict * fix: addressed PR comments * fix: use git tags for installer module versions |
||
|
|
3d824d4c0f |
feat(installer): channel-based version resolution + interactive channel management (#2305)
* feat(installer): channel-based version resolution for external modules Adds stable/next/pinned channel resolution so external/community modules install at released git tags by default instead of tracking main HEAD. Manifest now records channel, resolved version, and SHA per module for reproducible installs. CLI flags: --channel, --all-stable, --all-next, --next=CODE (repeatable), --pin CODE=TAG (repeatable). Precedence: pin > next > channel > registry default > stable. --yes accepts patch/minor upgrades but refuses majors. Interactive "Ready to install (all stable)?" gate with a per-module picker (stable/next/pin) when declined. Re-install prompts classify tag diffs as patch/minor/major with semver-class-dependent defaults. Legacy version:null manifests get a one-time migration prompt. Custom modules gain an optional @<ref> URL suffix for pinning (https, ssh, /tree/<ref>/subdir forms supported; local paths rejected). Community modules honor --next/--pin overrides with a curator-bypass warning; default path still enforces the approved SHA. Quick-update now reads the manifest's recorded channel per module so pinned installs don't silently roll forward. * feat(installer): interactive channel switch, upgrade refusal, unified docs Builds on the channel-resolution foundation. The installer now lets users flip a module between stable, next, and pinned after install — either interactively via a "Review channel assignments?" gate, or by flag. Quick and modify re-installs classify stable upgrades; under non-interactive flows, patches and minors apply automatically but majors are refused with a pointer to --pin. Fallback behavior for GitHub rate-limit / network failures is now cache- aware: re-installs reuse the recorded ref silently; fresh installs abort with actionable guidance (set GITHUB_TOKEN or use --next/--pin). Bundled modules (core, bmm) warn when targeted by --pin or --next so users aren't left wondering why the flag had no effect. Install summary labels no longer mangle "main" into "vmain"; next-channel entries render as "main @ <short-sha>" instead. Bundled modules are now correctly skipped from all channel prompts and tag-API lookups. Docs consolidated into a single how-to. install-bmad.md now covers the interactive flow, the channel model (stable/next/pinned plus the npm dist-tag axis for core/bmm), the re-install upgrade prompts, the full flag reference, copy-paste recipes, and troubleshooting. The old non-interactive-installation.md is reduced to a redirect stub. * fix(installer): review fixes + unit tests for channel resolution - ui.js: import parseGitHubRepo; fixes ReferenceError in the interactive channel picker's stable-tag pre-resolve path. - community-manager: pinned modules now fetch+checkout the pin tag on cache refresh instead of resetting to origin/HEAD (was silently drifting to main on re-install). - channel-plan: parseChannelOptions returns acceptBypass so --yes auto-confirms the curator-bypass prompt; headless --next/--pin installs of community modules no longer hang. - community-manager: simplify recordedVersion (dead ternary branch). - custom-module-manager: drop "or sha" from the @<ref> comment (git clone --branch rejects raw SHAs); update-path fetches origin <ref> so /tree/<branch>/ URLs work too. - install-bmad.md: rename "Headless / CI installs" to "Headless CI installs" so the stub's #headless-ci-installs anchor resolves. - test/test-installer-channels.js: 83 unit tests for channel-plan and channel-resolver pure modules; wired into npm test as test:channels. * fix(installer): address CodeRabbit review findings - ui.js: skip stable-channel upgrade classification when the user has already declared intent via --pin/--next=/--channel or the review gate. Prevents the decline / major-refused / fetch-error branches from silently overwriting an explicit pin with prev.version. - external-manager.js: short-circuit cloneExternalModule when the requested plan matches an existing in-process resolution and the cache is valid. Avoids redundant resolveChannel() + git fetch on every same-plan lookup in a single install. - installer.js: fall back to CommunityModuleManager.getResolution() when no external resolution exists, so community module result rows carry newChannel/newSha instead of null under --next/--pin. - installer.js: don't label a module as "no change" when its version string is 'main'/'HEAD' — the SHA may have moved and preVersions doesn't track the prior SHA. Show "(refreshed)" instead. - official-modules.js: match versionInfo.version to the manifest's cloneRef || (hasGitClone ? 'main' : version) expression so summary lines report the cloned ref for git-backed custom installs. - install-bmad.md: clarify that sha is only written for git-backed modules and that rerunning the same --modules on another machine does not reproduce stable-channel installs — convert recorded tags into explicit --pin flags for cross-machine reproducibility. |
||
|
|
2395b0e2ed |
fix: bmad tea instal version (#2298)
* fix: bmad tea instal version * fix: addressed review comments |
||
|
|
914c4edd6b |
fix(installer): resolve external-module agents from cache during manifest write (#2295)
External official modules (bmb, cis, gds, tea, wds) are cloned to ~/.bmad/cache/external-modules/<name>/ and never copied into src/modules/, so collectAgentsFromModuleYaml silently skipped them and their agents never reached config.toml. Swap the hardcoded src/modules lookup for a resolveInstalledModuleYaml() helper that also searches the external cache (handling src/, skills/, nested, and root layouts) and warns instead of silently skipping when a module.yaml can't be found. |
||
|
|
1251458173 |
feat(agents): set team to software-development on BMM agents (#2286)
* feat(agents): set team to software-development on BMM agents All six BMM agents (analyst, tech-writer, PM, UX designer, architect, dev) now explicitly declare `team: software-development` in the module.yaml roster instead of falling back to the module-code default of `bmm`. This matches the BMad-wide team convention where agents across modules that collaborate on software delivery share one named team. Tea's Murat joins the same team via a parallel PR in bmad-method-test-architecture- enterprise so party-mode, help catalog, and retrospective skills can route the full software-delivery roster as a single unit. * test: update team assertions for explicit software-development |
||
|
|
4405b817a9 |
refactor(skills): remove bmad-skill-manifest yaml; introduce central config.toml (#2285)
* refactor: remove bmad-skill-manifest yaml; introduce four-layer central config.toml
- Agent essence moves from per-skill bmad-skill-manifest.yaml files
into each module.yaml's `agents:` block (code, name, title, icon,
description). Per-agent customize.toml remains the deep-behavior
source of truth.
- Installer emits four TOML files:
_bmad/config.toml team install answers + agent roster
_bmad/config.user.toml user install answers
_bmad/custom/config.toml team overrides stub
_bmad/custom/config.user.toml personal overrides stub
Prompts declare scope: user to route answers to config.user.toml.
- resolve_config.py merges four layers: base-team -> base-user ->
custom-team -> custom-user.
- Three consumer skills (party-mode, advanced-elicitation,
retrospective) switched from agent-manifest.csv to the resolver.
- installer.js mergeModuleHelpCatalogs now takes the in-memory
agent list from ManifestGenerator -- no CSV roundtrip.
- Deleted: 6 bmad-skill-manifest.yaml files, agent-manifest.csv
emission, collectAgents/getAgentsFromDirRecursive,
paths.agentManifest().
* fix(installer): strip core-key pollution from [modules.*]; soften config headers
- writeCentralConfig now always strips core-module keys from every
[modules.<code>] bucket, even when the module's schema is not
available in src/ (external / marketplace modules like cis, bmb).
Core values belong in [core] only; workflows read them directly.
- When the module's own schema IS available (built-in modules),
also drop any key it does not declare as a prompt — same
spread-pollution filter as before, now layered on top.
- Section-aware headers on both _bmad/config.toml and
_bmad/config.user.toml: [core] / [modules.*] values are
editable (installer reads them as defaults on next install);
[agents.*] is regenerated from module.yaml and will be wiped —
overrides for agents go in _bmad/custom/config*.toml instead.
* docs: cover central config.toml + Diataxis prose pass across three files
Document the new four-file central configuration surface (_bmad/config.toml,
config.user.toml, and custom/ overrides) alongside the existing per-skill
customize.toml. Make editing rules, scope partitioning, and when-to-use-which
guidance explicit.
- customize-bmad.md: new "Central Configuration" section with editing rules,
three worked examples (rebrand, fictional agent, module settings override),
and a "when to use which surface" table. Converted five h4 headers to
bold paragraph intros per style guide.
- expand-bmad-for-your-org.md: two-layer mental model extended to three;
new Recipe 5 with three variants (rebrand, custom crew, pinned team
settings); reinforcement table extended.
- named-agents.md: noted the dual customization surface — per-skill shapes
behavior, central config shapes roster identity.
Diataxis prose pass applied across all three files: banned vocabulary
check, em-dash cap, hypophora / metanoia / amplificatio / stakes-inflation
cleanup, rhythm and burstiness fixes. Structural conformance verified;
markdownlint and prettier clean.
* test+docs: add central config unit tests; fix stale recipe count
- test: two new suites (35 + 36) covering writeCentralConfig and
ensureCustomConfigStubs. Verifies scope partitioning (user_name
lands only in config.user.toml), core-key pollution stripping
from [modules.*], unknown-schema fallthrough (external modules
survive without schema), agent roster baked into config.toml
[agents.*] only, stub-preservation on re-install. 44 new
assertions.
- docs: fixed four stale "four recipes" references to say "five"
after Recipe 5 (Customize the Agent Roster) was added. Touches
frontmatter, opening paragraph, Combining Recipes paragraph,
and the named-agents cross-link blurb.
* fix: address PR review feedback on central config
- resolve_config.py argparse: three-layer → four-layer description
- SKILL/workflow/explanation docs: document all four layers including
_bmad/config.user.toml (was missing from merge-stack descriptions)
- customize-bmad.md + installer headers: drop the false "direct edits to
config.toml persist" claim; installer reads from per-module config.yaml,
not central TOML, so direct edits get clobbered. Route users to
_bmad/custom/config.toml for durable overrides
- writeCentralConfig: warn loudly when a module.yaml can't be parsed
(previously silent — user-scoped keys could mis-file into team config)
- writeCentralConfig: preserve [agents.*] blocks for modules that didn't
contribute fresh agents this run (e.g. quickUpdate skipping modules
whose source is unavailable) so the roster doesn't silently shrink
- add extractAgentBlocks helper + Test Suite 37 covering preservation
Addresses comments from augmentcode and coderabbitai on PR #2285.
|
||
|
|
d09363b1b2 |
feat(installer): use GitHub API as primary fetch with raw CDN fallback (#2248)
* feat(installer): use GitHub API as primary fetch with raw CDN fallback Corporate proxies commonly block raw.githubusercontent.com while allowing api.github.com. Add fetchGitHubFile() to RegistryClient that tries the GitHub Contents API first, falling back to the raw CDN transparently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(installer): cap redirect depth and preserve dual-fallback errors Add maxRedirects parameter to fetch() and _fetchWithHeaders() to prevent unbounded redirect recursion. Wrap CDN fallback in try/catch and throw AggregateError with both API and CDN errors for better diagnostics. Extract marketplace repo coordinates into named constants in external-manager. * chore(installer): drop unused fetchJson and fetchGitHubJson Neither method has any callers. Also drop the corresponding test. * refactor(test): fold registry tests into test-installation-components No reason for RegistryClient tests to be a separate runner — the same file already tests the registry consumers in Suite 33. Drop test:registry from package.json scripts and quality gate. * fix(installer): include URL, API message, and rate-limit info in HTTP errors Non-2xx responses previously yielded bare `HTTP 403`. Now surface the request URL, GitHub's JSON error message (or body snippet), X-RateLimit-Reset when quota is exhausted, and Retry-After. Turns a mystery 403 into 'rate limit exhausted; resets at 2026-04-15T18:00:00Z' — the difference between 'try GITHUB_TOKEN' and a wild goose chase. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
a6d075bd0b |
fix(installer): replace fs-extra with native node:fs to prevent file loss
fs-extra routes all operations through graceful-fs, which globally monkey-patches node:fs with a deferred retry queue. During multi-module installs (~500+ file ops), retried unlink operations from one module's remove phase can fire after the next module's copy phase has written files, silently deleting them non-deterministically. Replace fs-extra with a thin fs-native.js wrapper over node:fs/promises and node:fs. All 21 consumers now use native APIs with no global monkey-patching, eliminating the retry-queue race condition entirely. Closes #1779 |
||
|
|
ea99b7ece5 |
chore(installer): remove 1,683 lines of dead code (#2247)
* chore(installer): remove dead code across installer modules
Delete 3 entirely dead files (agent-command-generator, bmad-artifacts,
module-injections) and remove ~50 unused exports from manifest.js,
cli-utils.js, prompts.js, path-utils.js, official-modules.js,
external-manager.js, custom-module-manager.js, and registry-client.js.
Removes corresponding dead tests.
* fix(installer): restore currentProjectDir writes for placeholder expansion
The previous commit removed the three assignments to
OfficialModules.currentProjectDir as dead code, but buildQuestion()
still reads the property to resolve {directory_name} placeholders in
module config defaults during interactive collection. Without the
writes, any module default containing {directory_name} would surface
the literal placeholder to users.
|
||
|
|
b744408783 |
feat(installer): community module browser and custom URL support (#2229)
* feat(installer): add community module browser and custom URL support Three-tier module selection: official, community (category drill-down with featured/search), and custom GitHub URL. - Add RegistryClient shared fetch utility - Add CommunityModuleManager with SHA-pinned cloning (refuses install if approved SHA cannot be reached; uses HEAD when no SHA set) - Add CustomModuleManager for arbitrary GitHub repo installation - Extend findModuleSource chain with community and custom fallthrough - Extend manifest to detect community and custom source types - Add Config.customModulesMeta for custom module metadata * fix: resolve review findings for community/custom module support - Remove redundant CommunityModuleManager instantiation in UI display - Remove dead customModulesMeta field from Config (never populated) - Add 35 unit tests for CustomModuleManager and CommunityModuleManager pure functions: URL validation, normalization, search, featured, categories * fix: preserve installed community/custom modules in modify flow When a user does "Modify Installation" and declines to browse community modules, previously installed community/custom modules are now auto-kept. If the user does browse, their selections are trusted (they can deselect). Also fix stale docs: class doc for SHA pinning, JSDoc return type. * fix: include community and custom modules in quick update Quick update now checks community registry and custom cache so installed community/custom modules are updated instead of skipped. * fix: use defaults for new config fields during quick update When quick update encounters new config fields (e.g., from a newly supported community module), use schema defaults silently instead of prompting the user. Quick update should be non-interactive. * test: add unit tests for SHA pinning, category filtering, and URL edge cases Cover SHA normalization (set vs null/trusted), listByCategory, getModuleByCode, and URL validation edge cases (HTTP, trailing slash, SSH without .git). Total: 243 tests. |
||
|
|
5dbfb588ee |
refactor(installer): remove custom content installation feature (#2227)
* refactor(installer): remove custom content installation feature Remove the entire local filesystem custom content feature from the installer to make way for marketplace-based plugin installation. Deleted: custom-handler.js, custom-module-cache.js, custom-modules.js Removed: --custom-content CLI flag, interactive custom content prompts, custom module caching, manifest tracking, missing-source resolution, and related test suites. Updated docs across all translations. * fix: address review findings from Augment Fix admonition syntax (remove accidental space in :::note) across 4 translated docs files, and update stale JSDoc on listAvailable(). |
||
|
|
6cecab2626 |
chore(install): stop copying skill prompts to _bmad by default (#2182)
* chore(install): stop copying skill prompts to _bmad by default Flip install_to_bmad default from true to false so skill directories are cleaned from _bmad/ after IDE install. Skills are self-contained in their IDE directories (.claude/skills/, etc.) and no longer need duplicate copies in _bmad/. Two skills (bmad-create-prd, bmad-validate-prd) opt back in via explicit manifests because bmad-edit-prd cross-references their data files. Also fixes broken bmm-skills/ path references and corrects the file-ref validator module-to-source mapping. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(install): make edit-prd self-contained and remove install_to_bmad Give bmad-edit-prd its own copy of prd-purpose.md and replace the cross-skill validation workflow reference with a skill invocation, so all three PRD skills are fully self-contained. With no remaining consumers, remove the install_to_bmad flag from manifests, CSV output, the post-install cleanup loop, and the dedicated test file. * feat(install): clean up skill directories from _bmad after IDE install Skills are self-contained in IDE directories, so _bmad/ only needs module-level files (config.yaml, _config/). After all IDE setups complete, remove skill directories from _bmad/ via skill-manifest.csv. Also cleans up skill dirs left by older installer versions. * test(install): drop stale install_to_bmad column from suite 27 CSV row --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
c46502f640 |
feat(installer): overhaul branding, versioning, and skill cleanup (#2223)
* feat(installer): overhaul branding, versioning, and skill cleanup Logo and branding: - Responsive logo: full "BMAD METHOD" at >=95 cols, "BMAD" for narrower terminals - Color scheme updated from yellow to blue (matching bmadcode.com brand) - Added copyright notice and tagline in white for contrast - Removed version number from logo (individual module versions shown in summary) - Added ™ to both wide and narrow logo variants Installer start message: - Replaced outdated V6 launch announcement with clean welcome - Consolidated redundant module/platform messaging into single intro - Tightened open source manifesto (same spirit, fewer words) - Merged speaking/media into support section with contact email - Added full social links: Website, Discord, YouTube, X, Facebook - Replaced docs.bmad-method.org and changelog links with bmadcode.com hub Install summary improvements: - Module names now show full display names from module.yaml (not abbreviations) - All module versions sourced from .claude-plugin/marketplace.json exclusively - Summary shows version transitions: "v6.2.2 -> v6.3.0", "v6.3.0, no change", or "v6.3.0, installed" for fresh installs - Switched summary from clack note() to box() for full-brightness text - Removed dim/gray styling that was hard to read on dark terminals - Links styled with color.blue instead of color.dim - Get started section leads with actionable steps (launch agent, run bmad-help) - Removed redundant social links (already shown in start message) Version source unification: - All module versions now come from .claude-plugin/marketplace.json only - Removed package.json as version source for core/bmm modules - Updated manifest.js getModuleVersionInfo() to use marketplace.json - Updated installer.js _getMarketplaceVersion() helper - Updated ui.js getMarketplaceVersion() for module selection display - Quick Update menu no longer shows misleading version (was using package.json) - Module selection list now shows versions next to each module name Skill cleanup overhaul: - Replaced blunt-force bmad-* prefix deletion with surgical removal system - Added removals.txt support: optional per-project file listing skills to remove - Created initial removals.txt with all skills removed since v6.2.0 - Install/update: captures previously installed skill IDs from skill-manifest.csv before manifest regeneration, then removes those + removals.txt entries - Uninstall: removes all installed skills via skill-manifest.csv + removals.txt - Deselecting modules now correctly removes their skills from IDE directories - User-created bmad-* skills in IDE directories are no longer destroyed - Legacy directory cleanup retains prefix matching (those dirs are abandoned) Bug fixes: - Fixed duplicate "CORE module already up to date" during quick update - Fixed version display showing package.json version instead of actual module version - Updated test fixture for bmad-os-* preservation test to use skill-manifest.csv * fix(installer): address Augment review findings - Fix plugins[0] fragility: extract highest version across all plugins in marketplace.json instead of assuming first entry (ui.js, installer.js, manifest.js) - Fix _readMarketplaceVersion ignoring moduleSourcePath: custom modules can now source their own marketplace.json by walking up from source path - Hard-exclude bmad-os-* utility skills in both surgical and legacy cleanup modes, preventing accidental deletion if tracked in manifests - Distinguish missing file vs parse error in skill-manifest.csv reading: warn on corrupt CSV instead of silently skipping cleanup * fix(installer): resolve module source before reading marketplace version Move _readMarketplaceVersion call after source type resolution so custom modules use their own source path instead of falling back to the external module cache, which could match a different module with the same code. |
||
|
|
1f99eb0496 |
fix: preserve local custom module sources during quick update (#2172)
* fix: preserve local custom module sources during quick update Keep customModules in the generated main manifest so local custom module source paths survive update runs. Load those preserved source paths during stock quick update before falling back to the custom cache directory. This fixes the case where BMAD would drop customModules, lose the original source path for a local module, and then skip the module or try to re-cache from _bmad/_config/custom/<module>, which could fail with ENOENT after the cache directory was removed. Also adds an installation component regression test to verify customModules and sourcePath are preserved in manifest generation. Fixes #1582 * fix: ensure consistent formatting * refactor: extract quick update custom source assembly Move quick-update custom module source collection out of Installer and into CustomModules as assembleQuickUpdateSources(). This keeps discoverPaths() focused on consuming prepared install inputs while making the quick-update source assembly step explicit and easier to evolve. Also: - preserve customModules metadata in manifest regeneration for installed modules - drop stale customModules entries when modules are no longer installed - cover manifest preservation and manifest-backed quick-update sources in tests |
||
|
|
04513e5953 |
feat(installer): restore KiloCoder support and installer (#2151)
Kilo Code now supports Agent Skills. Remove the suspended flag, restore it in the IDE picker, and replace the suspended test suite with a full native-skills installation test. - Remove suspended message from platform-codes.yaml - Rewrite test suite 22: config, IDE picker, install, skill output, legacy cleanup, and reinstall assertions - Update migration checklist to reflect active status Co-authored-by: Junie <junie@jetbrains.com> Co-authored-by: Brian <bmadcode@gmail.com> |
||
|
|
aae6ddb8c9 |
fix: remove ancestor_conflict_check from all platforms (#2158)
The ancestor directory walk was based on the false premise that IDEs like Claude Code inherit skills from parent directories — they do not. The check blocked legitimate installations when unrelated BMAD skills existed anywhere up the directory tree. |
||
|
|
513f440a23 |
refactor(installer): restructure installer with clean separation of concerns (#2129)
* 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. |
||
|
|
a04635efe0 |
fix: agent-manifest.csv empty after install — type mismatch + scan path bug (#2115)
Two bugs combined to produce an empty agent-manifest.csv:
1. collectAgents() only scanned {module}/agents/ directories, but agents
live at various paths (bmm/1-analysis/bmad-agent-analyst/,
cis/skills/bmad-cis-agent-*, etc.). Now walks the full module tree.
2. All 9 BMM agent manifests declared type: skill instead of type: agent.
The manifest generator requires type: agent to include a directory in
agent-manifest.csv. CIS, GDS, TEA, and WDS already had the correct type.
Changes:
- Fix 9 BMM bmad-skill-manifest.yaml files: type: skill → type: agent
- Replace collectAgents/getAgentsFromDir with full-tree recursive scan
- Module field from manifest file always takes precedence over directory
- Remove dead skillManifest load (legacy .md agent support removed)
- Add TODO in bmad-artifacts.js documenting legacy agent pipeline as dead code
- Add 10 regression tests covering BMM, CIS, and GDS directory layouts
|
||
|
|
303e7ae290 |
fix: issue 55 config paths (#2113)
* fix: issue 55 config paths * Fix: ci test failure |
||
|
|
93a1e1dc46 |
refactor(installer): remove dead task/tool/workflow manifest code (#2083)
* refactor(installer): discover skills by SKILL.md instead of manifest YAML Switch skill discovery gate from requiring bmad-skill-manifest.yaml with type: skill to detecting any directory with a valid SKILL.md (frontmatter name + description, name matches directory name). Delete 34 stub manifests that carried no data beyond type: skill. Agent manifests (9) are retained for persona metadata consumed by agent-manifest.csv. * refactor(installer): remove dead task/tool/workflow manifest code The remove-skill-manifest-yaml branch deleted the scanners that discover tasks, tools, and workflows but left behind the code that writes their manifest CSVs. Remove collectTasks/Tools/Workflows, writeTaskManifest/ToolManifest/WorkflowManifest, their helpers, and the now-unreachable getPreservedCsvRows/upgradeRowToSchema methods. Update installer pre-registration and test assertions accordingly. |
||
|
|
31ae226bb4 |
refactor(installer): discover skills by SKILL.md instead of manifest YAML (#2082)
Switch skill discovery gate from requiring bmad-skill-manifest.yaml with type: skill to detecting any directory with a valid SKILL.md (frontmatter name + description, name matches directory name). Delete 34 stub manifests that carried no data beyond type: skill. Agent manifests (9) are retained for persona metadata consumed by agent-manifest.csv. |
||
|
|
c28206dca4 |
refactor(installer): remove dead agent compilation pipeline (#2080)
* refactor(installer): remove dead agent compilation pipeline Delete 9 files (~2,600 lines) that compiled .agent.yaml to .md. No .agent.yaml files exist in the source tree — agents now ship as pre-built SKILL.md. Clean up all references in installer, module manager, custom handler, base IDE, UI, and tests. * refactor(custom-handler): remove dead install/copy/find methods CustomHandler.install(), copyDirectory(), and findFilesRecursively() are never called — custom modules are installed via moduleManager.install() since Dec 2025. Also removes unused FileOps import and constructor. Verified with before/after clean-installer comparison (codex + custom modules with custom.yaml): output is identical. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(installer): remove dead compilation refs from docs and module manager Address review findings from PR #2080 triage: - Remove compile-agents from CLI action docs (en, fr, zh-cn) - Remove dead vendorCrossModuleWorkflows() and .agent.yaml skip logic - Clean stale compilation-era comments in manifest-generator --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |