- frontmatter: accept a block that ends at EOF (optional trailing newline).
- legacy-resolver: accept CRLF frontmatter delimiters.
- integration.test.sh: unique mktemp stderr capture, explicit if/then/else
assertions (drop the SC2015 && ok || ko chains), plus unknown-flag and
invalid-channel usage-error cases.
- test-installation-components: clear the resolution cache in a finally.
- acme-devlog fixtures: correct the uninstall note to the flat TOML layout,
replace `ls -t | head` with a glob/-nt lookup, drop the always-on devlog
config file: fact, "run" -> "invoke" wording, and reconcile the devlog-write
template contract with the bundled template.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The acme-devlog fixture's .mcp.json was swallowed by the global
.gitignore '.mcp.json' rule, so it was never committed. The skill's
install test asserts _bmad/devlog/.mcp.json exists, which passed
locally (file on disk) but failed on CI's clean checkout. Add a
negation for the test-fixtures path and commit the fixture.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The standalone bmad-module skill only understood the new plugin.json#bmad
spec, so installing a legacy repo (marketplace.json + module.yaml, e.g.
bmad-code-org/bmad-module-game-dev-studio) failed with exit 20. Legacy
support existed only in the full installer's PluginResolver, which the
skill can't import (it ships self-contained under .claude/skills/).
Port that resolver into lib/legacy-resolver.mjs (strategies 1-5): when a
repo has no plugin.json#bmad but has a marketplace.json, resolve it into a
synthetic manifest of the same shape readAndValidateManifest produces, then
run it through the existing buildCopyPlan -> rewrite -> stage -> swap
pipeline unchanged. buildCopyPlan already copies marketplace.json verbatim,
flattens arbitrary skill paths to skills/<basename>, and flattens
moduleDefinition/moduleHelpCsv, so almost no downstream change is needed.
- plugin-json.mjs: extract validateManifestObject(m, {allowReserved}) and
add hasBmadPluginJson(dir). Legacy installs pass allowReserved:true so
first-party codes (gds, bmm, ...) install; new-spec authors still get
exit 21.
- install.mjs: detect new-spec -> legacy -> neither in §3; write
synthesized module.yaml/module-help.csv into the temp clone for the
strategy-5 fallback.
- cli.mjs: add --module <code> to disambiguate a multi-module marketplace
(otherwise exit 20 lists the available codes).
- help-catalog.mjs: export MODULE_HELP_CSV_HEADER for the synthesizer.
- tests: legacy fixtures (strategy-1, reserved code, synthesize fallback)
+ integration assertions. SKILL.md/README updated.
Verified: full install of the real game-dev-studio repo resolves gds and
lands 250 files under _bmad/gds/. Integration suite 97/0, installer
component tests 374/0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This work was developed in a separate bmad-marketplace repo and is now
landing directly in BMAD-METHOD, so the migration framing is obsolete:
- remove links to docs/spec.md (only existed in the temp repo) and the
bmad-marketplace / 'upstream patch' / 'sibling checkout' references in
README, the integration test, and the acme-md-lint fixture
- drop dead 'spec §N' pointers in install.mjs, install-plan.mjs, and
plugin-json.mjs (including a user-facing reserved-code error message)
- reword the manifest-generator 'patch' note as in-repo behavior
- correct the documented install path from _bmad/ to the IDE skills
directories the installer now distributes skills to (.claude/skills/, etc.)
No behavior change. Integration suite: 73 pass / 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bmad-module skill copied a module's files and distributed skills to IDEs,
but skipped four post-copy steps the full `bmad install --custom-source` path
performs, leaving modules incompletely installed:
- Merge each module's module-help.csv into _bmad/_config/bmad-help.csv (the
catalog bmad-help reads) — new lib/help-catalog.mjs
- Generate [modules.<code>] / [agents.<code>] blocks in config.toml /
config.user.toml from module.yaml (defaults + --set overrides), via a
targeted merge that preserves [core] and sibling modules — new lib/config-gen.mjs
- Create the working directories a module declares under `directories:`
(with move-on-path-change and wds_folders) — new lib/module-dirs.mjs
- Run `npm install --omit=dev` in place when a module ships package.json
(opt out via bmad.install.skipNpm) — new lib/npm-deps.mjs
All four run as a shared finishModuleInstall step wired into install, update,
and remove; every step is non-fatal so a module already committed to _bmad/
isn't lost to a post-copy hiccup. Adds a repeatable --set <code>.<key>=<value>
flag mirroring the installer.
Also fixes two latent issues in the manifest-driven copy that the new steps
depend on:
- moduleDefinition / moduleHelpCsv are now flattened to the module root even
when they live inside a declared skill dir (the setup-skill assets pattern);
previously claimedSrc dedup skipped them and the rewritten plugin.json
pointed at a non-existent ./module.yaml.
- package.json / package-lock.json are now copied so npm deps can install.
Tests: extends the integration suite with config/agent-roster, --set,
directory-creation, help-catalog, removal-cleanup, and npm assertions
(73/73 pass); adds a minimal-npm fixture and rewrites the comprehensive
fixture's module-help.csv to the canonical schema.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bmad-module skill staged community modules under _bmad/<code>/ but never
pushed their skills out to the coding assistants the user selected at
`bmad install` time, so a freshly installed module was invisible to Claude
Code / Cursor / Copilot / etc. until a full reinstall; remove left skills
orphaned in the IDE dirs.
install/update/remove now distribute (or prune) skills to every IDE listed in
_bmad/_config/manifest.yaml and clean the redundant skill dirs from _bmad/,
matching how official modules end up.
Single engine, three callers — no fork:
- New tools/installer/core/ide-sync.js (syncIdes) wraps the real
IdeManager.setupBatch + platform-codes engine. The full installer
(_setupIdes/_cleanupSkillDirs), the new `bmad ide-sync` command, and the
skill all route through it, so new IDEs and engine changes propagate
everywhere automatically.
Local, dependency-free delivery — no npx/network at runtime:
- build-ide-sync.mjs esbuild-bundles the engine into vendor/ide-sync.mjs
(+ platform-codes.yaml), aliasing ../prompts and ../project-root to small
shims so @clack and the installer graph are dropped. The bundle ships inside
the skill tree (like yaml.mjs); the skill execs it locally. It's
generated-from-source and gated by vendor:check, refreshed on every install.
update/remove pass --prune with the module's canonicalIds so skills dropped
between versions (or on uninstall) are removed from IDE dirs + command
pointers. Graceful degradation: if the bundle is unreachable, the verb still
succeeds and points the user at `bmad ide-sync`.
Tests: new test/test-ide-sync.js drift-guard (engine == bundle, incl. prune),
integration.test.sh IDE-distribution section (offline), bundle self-check in
the build. All gates green (vendor:check, lint, format, test:install 349/349).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The suite resolved its reference modules from `<repo>/examples`, which
existed only in the sibling bmad-marketplace checkout — so after the
skill moved into BMAD-METHOD core every install/list/remove assertion
failed with "local source not a directory".
Vendor the two reference modules (acme-md-lint, acme-devlog) under
tests/fixtures/examples/ and point EXAMPLES there; drop the now-unused
REPO_DIR. Also correct the comprehensive-install assertion: hooks are
flattened to the canonical root slot (hooks.json), matching .mcp.json
and rewriteManifestPaths — not a hooks/ subdir.
Suite now passes 41/41.
Note: these fixtures are copies of the bmad-marketplace examples and
must be re-synced if those reference modules change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>