Commit Graph

16 Commits

Author SHA1 Message Date
Brian Madison 7ad054f0e9 fix(installer): address fourth-round PR #2353 review comments
(1) Use process.exitCode instead of process.exit() after --list-options
write (CodeRabbit major). process.exit() forces immediate termination
even with pending I/O, which can truncate buffered writes when stdout
is piped or captured by CI. Await the write callback, set exitCode,
and return so the event loop drains naturally.

(2) Thread setOverrides through Config → OfficialModules.build for
headless callers (CodeRabbit major). Non-UI entry points (direct
installer.install({...}) without going through ui.collectModuleConfigs)
previously got an empty override map. Config now carries setOverrides
and the headless branch of OfficialModules.build also runs
loadExistingConfig + applyOverridesAfterSeeding('core') to mirror the
UI path's semantics. The UI path is unaffected because it takes the
moduleConfigs early-return.

(3) Evaluate function defaults under skipPrompts and accept-defaults
paths (CodeRabbit major). Both branches were dropping function defaults
silently, so any same-module dynamic default (`{other_key}` placeholder
in default:) disappeared under --yes. Two-pass: write non-function
defaults first so the answer bag is populated, then call function
defaults with that bag. Try/catch around the call surfaces resolution
failures as warnings instead of crashing the install.

(4) Track result-only schema keys as declared (Augment medium). A
schema entry with `result:` and no `prompt:` was being classified as
"unknown" when targeted by --set, producing a wrong warning and
overwriting the computed template output with the raw value. Added
declaredResultKeys parallel to declaredPromptKeys; an override on
either is now seeded as the answer so the result template still
renders ({value} substitution preserved). Carry-forward block
refactored to consume the same set.

(5) Diagnose non-object module.yaml under --list-options (Augment low).
The non-object branch silently flipped moduleScopedFailure with no
output. Now emits "module.yaml is not a valid object (got <type>)"
mirroring the catch branch, and the type guard also catches arrays
which typeof reports as 'object'.

(6) Reword --list-options doc cache scope (CodeRabbit minor).
"Installed at least once on this machine" → "currently cached official
modules" with a note that cache can be cleared or absent on ephemeral
CI workers — accurately reflects what the command can discover.

Tests: +4 cases — Config.build setOverrides threading and default,
formatOptionsList non-object yaml diagnostic and ok:false. Total 347
passing.
2026-04-28 18:59:17 -05:00
Brian Madison f1c9e12618 fix(installer): address PR #2353 review comments
Carry forward unknown --set keys across upgrades (CodeRabbit major).
Without this, an unknown key like --set bmm.future_thing=hello landed in
config.toml on run #1 but was silently dropped on the next install
because collectModuleConfig rebuilds collectedConfig from prompt answers
only. collectModuleConfig now copies any non-declared keys from
_existingConfig into collectedConfig and tracks them in setOverrideKeys
so the manifest writer's schema-strict partition keeps them.

Guard single-select rendering with Array.isArray (CodeRabbit major):
a malformed truthy non-array would have aborted --list-options.

Unify core override handling: move the inline post-collection block
from ui.js into OfficialModules.applyOverridesAfterSeeding so core and
non-core take a single validated path. Removes duplicated schema-load
logic and inline requires from ui.js.

Remove dead code: findOfficialModuleYaml and readDeclaredKeys in
set-overrides.js were exported but never imported. Drop them and
their path/fs/yaml/project-root imports — the module is now pure
string-parsing with zero deps.

Doc fix: change "silently ignored" to "ignored with a warning" for
the --action quick-update note (Augment + CodeRabbit).

Polish: clearer flag placeholder (--set <module.key=value> instead of
the misleading <key=value>), trim-asymmetry rationale comment in
parseSetEntry, dedupe rationale in list-options.

Tests: +6 cases — collectModuleConfig --set application end-to-end
(prompt-skip with template rendering), and carry-forward of unknown
keys from _existingConfig. Total 333 passing.
2026-04-28 10:27:37 -05:00
Brian Madison f33d251790 feat(installer): add --set and --list-options for non-interactive config (#1663)
`--set <module>.<key>=<value>` (repeatable) sets any module config option
non-interactively. Scales to every module without growing the CLI surface
per option, and persists into _bmad/config.toml so values survive upgrades.

`--list-options [module]` prints every available --set key for built-in
and locally-cached official modules (community/custom users read their own
module.yaml). Pass a module code to scope the listing.

Validation rules, all non-fatal:
- Module not in --modules → warn and drop the value.
- Key not declared in module.yaml → warn but persist (forward-compat).
  The manifest writer's schema-strict partition exempts these so they
  survive into config.toml even though the schema doesn't know them.
- Malformed --set syntax → exit non-zero up front.

The legacy core shortcuts (--user-name, --output-folder, etc.) remain
supported as aliases for `--set core.<key>=<value>`. --set with
--action quick-update is ignored with a warning since quick-update
preserves the existing answers by design.

Files:
- tools/installer/set-overrides.js (new): parser
- tools/installer/list-options.js (new): discovery + formatter
- tools/installer/commands/install.js: flags + early validation
- tools/installer/ui.js: parse, warn-on-unselected, thread to OfficialModules
- tools/installer/modules/official-modules.js: pre-fill answers, persist unknowns
- tools/installer/core/config.js + installer.js: carry setOverrideKeys through
- tools/installer/core/manifest-generator.js: partition exempts override keys
- test/test-installation-components.js: +15 cases (Suite 44)
- docs/how-to/install-bmad.md, README.md: --set as preferred non-interactive path

Closes #1663
2026-04-28 09:54:34 -05:00
Brian 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.
2026-04-27 23:01:23 -05:00
Brian 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.
2026-04-24 08:20:30 -05:00
Brian 97d32405d0
feat(installer): universal source support for custom module installs (#2233)
* feat(installer): add plugin resolution strategies for custom URL installs

When installing from a custom GitHub URL, the installer now analyzes
marketplace.json plugin structures to determine how to locate module
registration files (module.yaml, module-help.csv). Five strategies
are tried in cascade:

1. Root module files at the common parent of listed skills
2. A -setup skill with registration files in its assets/
3. Single standalone skill with registration files in assets/
4. Multiple standalone skills, each with their own registration files
5. Fallback: synthesize registration from marketplace.json metadata
   and SKILL.md frontmatter

Also changes the custom URL flow from confirm-all to multiselect,
letting users pick which plugins to install. Already-installed modules
are pre-checked for update; new modules are unchecked for opt-in.

New file: tools/installer/modules/plugin-resolver.js
Modified: custom-module-manager.js, official-modules.js, ui.js

* fix(installer): address PR review findings for plugin resolver

- Guard against path traversal in plugin-resolver.js: skill paths from
  unverified marketplace.json are now constrained to the repo root using
  path.resolve() + startsWith check
- Skip npm install during browsing phase: cloneRepo() accepts
  skipInstall option, used in ui.js before user confirms selection,
  preventing arbitrary lifecycle script execution from untrusted repos
- Add createModuleDirectories() call to installFromResolution() so
  modules with declarative directory config are fully set up
- Fix ESLint: use replaceAll instead of replace with global regex

* fix(installer): pass version and repoUrl to manifest for custom plugins

installFromResolution was passing empty strings for version and repoUrl,
which the manifest stores as null. Now threads the repo URL from ui.js
through resolvePlugin into each ResolvedModule, and passes the plugin
version and URL to the manifest correctly.

* fix(installer): manifest-generator overwrites custom module version/repoUrl

ManifestGenerator rebuilds the entire manifest via getModuleVersionInfo
for every module. For custom modules, this returned null for version and
repoUrl because it only checked _readMarketplaceVersion (which searches
for marketplace.json on disk) and hardcoded repoUrl to null. Now checks
the resolution cache first to get the correct version and repo URL.

* fix(installer): resolve custom modules from disk cache on quick update

When the resolution cache is empty (fresh CLI process, e.g. quick
update), findModuleSourceByCode only matched plugin.name against the
module code. This failed for modules like "sam" and "dw" where the
code comes from module.yaml inside a setup/standalone skill, not from
the plugin name in marketplace.json.

Now runs the PluginResolver on cached repos when the direct name match
fails, finding the correct module source and re-populating the cache
for the install pipeline.

* feat(installer): universal source support for custom modules

Replace GitHub-only custom module installation with support for any Git
host (GitHub, GitLab, Bitbucket, self-hosted) and local file paths.

- Add parseSource() universal input parser (local paths, SSH, HTTPS with
  deep path/subdir extraction for GitHub, GitLab, Gitea)
- Add resolveSource() coordinator: parse -> clone if URL -> detect
  discovery vs direct mode (marketplace.json present or not)
- Clone-first approach eliminates host-specific raw URL fetching
- 3-level cache structure (host/owner/repo) with .bmad-source.json
  metadata for URL reconstruction
- Local paths install directly without caching; localPath persisted in
  manifest for quick-update source lookup
- Direct mode scans target directory for SKILL.md when no marketplace.json
- Fix version display bug where walk-up found parent repo marketplace.json
  and reported wrong version for custom modules

* fix(installer): harden readMarketplaceJsonFromDisk and hoist require

- Add try/catch to readMarketplaceJsonFromDisk so malformed JSON returns
  null instead of throwing an unhandled parse error
- Hoist CustomModuleManager require outside the per-module loop in
  _installOfficialModules

* fix(installer): restore validateGitHubUrl strictness and fix prettier

- Restore original GitHub-only regex in deprecated validateGitHubUrl
  wrapper so existing tests pass (rejects non-GitHub URLs, trailing
  slashes)
- Run prettier to fix formatting in custom-module-manager.js

* feat(installer): add --custom-source CLI flag for non-interactive installs

Allows installing custom modules from Git URLs or local paths directly
from the command line without interactive prompts:

  npx bmad-method install --custom-source /path/to/module
  npx bmad-method install --custom-source https://gitlab.com/org/repo
  npx bmad-method install --custom-source /path/one,https://host/org/repo

Works alongside --modules and --yes flags. All discovered modules from
each source are auto-selected.

* docs: add custom and community module installation guide

New how-to page covering community module browsing, custom sources (any
Git host, local paths), discovery vs direct mode, local development
workflow, and the --custom-source CLI flag. Clarifies that
.claude-plugin/ is a cross-tool convention, not Claude-specific.

Also updates non-interactive installation docs with the new flag and
examples, bumps sidebar ordering, and fixes --custom-source to install
only core + custom modules when --modules is not specified.
2026-04-09 18:44:40 -05:00
Brian 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().
2026-04-07 21:41:03 -05:00
Alex Verkhovsky bb046f5062
docs: mention next install channel (#1887) 2026-03-11 02:34:26 -06:00
Alex Verkhovsky db8f856fce
docs: update terminology from commands to skills across all documentation (#1850)
Align documentation with the skills-based architecture migration by
replacing references to "commands", "slash commands", and legacy command
names with the new "skills" terminology and skill names.
2026-03-07 16:14:25 -07:00
Alex Verkhovsky 811d03262d
fix(config): remove Windsurf from recommended/preferred IDEs (#1727)
Windsurf is no longer a preferred IDE. Only Claude Code and Cursor
are now recommended. Windsurf remains a supported platform (installer
still works, templates stay, reference tables stay).

- Set preferred: false in both platform-codes.yaml files
- Move windsurf entry to "Other IDEs" section in tools/platform-codes.yaml
- Fix codex.js hardcoding preferred: true in constructor
- Remove stale "3 preferred tools" count from ui.js JSDoc
- Update docs to list only Claude Code and Cursor as recommended
- Update docs/index.md popular tools to Claude Code, Cursor, Codex CLI
2026-02-20 20:16:43 -06:00
Brian Madison 1782e97731 docs: elevate bmad-help as primary on-ramp across all documentation
BMad-Help is one of V6's flagship features but was undersold in docs.
This update positions it properly as the intelligent guide that:

- Inspects project state and detects what's completed
- Understands natural language queries
- Varies options based on installed modules
- Auto-invokes after every workflow
- Recommends first required tasks

Changes:
- Add dedicated "Meet BMad-Help" section to getting-started
- Expand commands.md with full BMad-Help subsection and examples
- Reposition get-answers-about-bmad.md to start with BMad-Help
- Enhance install-bmad.md and established-projects.md with query examples
- Add index.md tip box promoting /bmad-help as quickest way to dive in
2026-02-18 00:22:12 -06:00
Alex Verkhovsky a1101534b2
fix(docs): comprehensive documentation site review fixes (#1578)
* fix(docs): comprehensive documentation site review fixes

Rehype plugins:
- Rewrite rehype-markdown-links for correct relative .md resolution
- Handle raw HTML base paths and bare .md links in rehype-base-paths
- Guard protocol-relative URLs (//...) in all link processors
- Use file.path instead of file.history[0] for vfile compatibility
- Fail build when content directory cannot be detected
- Export helpers for testability; add 107 unit tests

Build & CI:
- Revert cancel-in-progress to false to avoid mid-deploy cancellation
- Remove redundant link-validation CI step (build validates internally)
- Remove unnecessary fetch-depth:0 from docs deploy workflow
- Refuse docs build on Windows (platform guard)
- Remove dead build scripts and stale references

Tooling:
- Add DOCS_ROOT boundary check in validate-doc-links.js
- Handle directory paths and prefix stripping in link validator
- Remove dead regex and add // guard in fix-doc-links.js

Accessibility & CSS:
- Darken caution/danger aside title colors for WCAG AA 4.5:1 contrast
- Fix 100vw scrollbar overflow (banner width:100%, html overflow-x:clip)
- Add :focus-visible ring to banner link for keyboard navigation
- Remove dead CSS declaration and add missing code block lang

Documentation content:
- Convert /docs/ absolute links to relative paths and fix llms.txt URLs
- Correct command file paths and naming in commands reference
- Update stale shard-doc command to current /bmad-shard-doc format
- Fix incomplete sentence in install-bmad.md
- Add Quick Flow next steps and fix 404 link path
- Expand thin content pages with substantive detail
- Add sidebar ordering frontmatter to all content pages
- Remove BMGD docs (moved to dedicated repo)
- Remove unused assets and misleading diagram caption
- Add non-iframe fallback link to workflow map diagram
- Remove dead noscript block from workflow-map
- Standardize BMAD to BMad, fix spelling/grammar, normalize headings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(docs): add non-interactive installation to sidebar, rewrite and reorder how-to guides

- Move non-interactive-installation.md into how-to/ directory so it appears
  in the sidebar navigation (was orphaned at docs root)
- Rewrite the page based on editorial review: consolidate redundant sections,
  add missing how-to structure (prerequisites, "What You Get"), condense
  installation modes from 5 subsections to a table, cut speculative examples
- Reorder how-to sidebar: Install (1), Non-Interactive (2), Upgrade to v6 (3),
  then the rest following user journey order
- Fix README link to point to docs site instead of repo-internal markdown path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(docs): address documentation review findings

Fix broken directory tree, grammar errors, inconsistent naming,
missing admonition/headings, enable lastUpdated timestamps in CI,
and remove footer CSS that misapplied to the content footer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(docs): move bleeding-edge install command out of Verify Installation

The alternative npx command for installing from main was misplaced
inside the "Verify Installation" section. Move it to a tip admonition
under Step 1 where users look for install options.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 11:58:22 -06:00
Alex Verkhovsky fc5ef57a5a
feat: add Kiro IDE support via config-driven installer (#1589)
Replace broken kiro-cli.js custom installer with config-driven approach
using platform-codes.yaml. Creates Kiro-specific templates with
inclusion: manual frontmatter and #[[file:...]] reference syntax.
2026-02-08 09:18:28 -06:00
Brian Madison 6c2d0195d3 minor doc updates 2026-02-06 22:54:47 -06:00
Brian Madison c352e03d18 add interactive diagram to test final doc build and layout 2026-01-25 22:12:23 -06:00
Alex Verkhovsky 91f6c41be1
docs: radical reduction of documentation scope for v6 beta (#1406)
* docs: radical reduction of documentation scope for v6 beta

Archive and basement unreviewed content to ship a focused, minimal doc set.

Changes:
- Archive stale how-to workflow guides (will rewrite for v6)
- Archive outdated explanation and reference content
- Move unreviewed content to basement for later review
- Reorganize TEA docs into dedicated /tea/ section
- Add workflow-map visual reference page
- Simplify getting-started tutorial and sidebar navigation
- Add explanation pages: brainstorming, adversarial-review, party-mode,
  quick-flow, advanced-elicitation
- Fix base URL handling for subdirectory deployments (GitHub Pages forks)

The goal is a minimal, accurate doc set for beta rather than
comprehensive but potentially misleading content.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: restructure BMM and agents documentation by consolidating and flattening index files.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 14:00:26 -06:00