Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ The skills CLI decides. With one agent it copies the skills into that agent's fo
| `-h, --help` | Show the help |
| `-v, --version` | Show the version |

`--modules` takes module codes. `method` (alias `bmm`) has the bundles `planning`, `build`, `agents` and `extras`; `cis` has none. A module named without `:` takes its default bundles. The core tools module installs on every run.
`--modules` takes module codes. `method` (alias `bmm`) has the bundles `planning`, `build` and `agents`; `cis` has none. A module named without `:` takes its default bundles. The core tools module installs on every run.

A 6.12 flag this installer dropped prints one line about it, then exits without installing.

Expand Down
13 changes: 4 additions & 9 deletions modules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,19 @@ modules:
bundles:
- code: planning
name: Planning
description: Brief, PRD, UX, architecture, spec
description: Brief, PRD, UX, architecture, spec, ticketing, walkthrough
default: true
skills: [bmad-product-brief, bmad-prfaq, bmad-prd, bmad-ux, bmad-architecture, bmad-spec, bmad-project-context]
skills: [bmad-product-brief, bmad-prfaq, bmad-prd, bmad-ux, bmad-architecture, bmad-spec, bmad-project-context, bmad-ticket, bmad-walkthrough]
- code: build
name: Build
description: Epics and stories, sprint planning, build, review, course correction, retrospective
description: Ticketing, spec, build, review, course correction, retrospective, walkthrough
default: true
skills: [bmad-create-epics-and-stories, bmad-sprint-planning, bmad-build, bmad-build-auto, bmad-code-review, bmad-correct-course, bmad-retrospective, bmad-qa-generate-e2e-tests]
skills: [bmad-ticket, bmad-spec, bmad-build, bmad-build-auto, bmad-code-review, bmad-correct-course, bmad-retrospective, bmad-qa-generate-e2e-tests, bmad-walkthrough]
- code: agents
name: Agent personas
description: Analyst, architect, developer, PM and UX designer agents
default: true
skills: [bmad-agent-analyst, bmad-agent-architect, bmad-agent-dev, bmad-agent-pm, bmad-agent-ux-designer]
- code: extras
name: Extras
description: Preview ticketing and the walkthrough
default: false
skills: [bmad-preview-ticketing, bmad-walkthrough]

- code: cis
name: BMad Creative Intelligence Suite
Expand Down
6 changes: 4 additions & 2 deletions test/commands/install-plan.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,15 @@ test('memberCalls merges modules that share a source and skips empty ones', () =
const report = statusOf()
report.modules[0].absent_skills = []
const { calls } = memberCalls(
[{ code: 'core-tools', bundles: null }, { code: 'method', bundles: ['extras'] }],
[{ code: 'core-tools', bundles: null }, { code: 'method', bundles: ['agents'] }],
modules,
report,
)

assert.equal(calls.length, 1)
assert.deepEqual(calls[0].skills, ['bmad-preview-ticketing', 'bmad-walkthrough'])
assert.deepEqual(calls[0].skills, [
'bmad-agent-analyst', 'bmad-agent-architect', 'bmad-agent-dev', 'bmad-agent-pm', 'bmad-agent-ux-designer',
])
assert.equal(calls[0].label, 'BMad Method')
})

Expand Down
3 changes: 1 addition & 2 deletions test/commands/install.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ test('--yes takes the default modules and asks nothing', async (t) => {
assert.deepEqual(asked, ['intro'])
const members = only(requests)[1]
assert.equal(members.agents, null)
for (const skill of ['bmad-prd', 'bmad-build', 'bmad-agent-dev', 'bmad-brainstorming']) {
for (const skill of ['bmad-prd', 'bmad-build', 'bmad-ticket', 'bmad-walkthrough', 'bmad-agent-dev', 'bmad-brainstorming']) {
assert.ok(members.skills.includes(skill), `missing ${skill}`)
}
assert.equal(members.skills.includes('bmad-walkthrough'), false)
})

test('a skipped skill is reported and turns the run into an exit 1', async (t) => {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/status-after-prd.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"bmad-code-review",
"bmad-correct-course",
"bmad-create-epics-and-stories",
"bmad-preview-ticketing",
"bmad-ticket",
"bmad-prfaq",
"bmad-product-brief",
"bmad-project-context",
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/status-fresh.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"bmad-correct-course",
"bmad-create-epics-and-stories",
"bmad-prd",
"bmad-preview-ticketing",
"bmad-ticket",
"bmad-prfaq",
"bmad-product-brief",
"bmad-project-context",
Expand Down
23 changes: 11 additions & 12 deletions test/modules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ import {
const METHOD_RECORD_SKILLS = [
'bmad-agent-analyst', 'bmad-agent-architect', 'bmad-agent-dev', 'bmad-agent-pm',
'bmad-agent-ux-designer', 'bmad-architecture', 'bmad-build', 'bmad-build-auto',
'bmad-code-review', 'bmad-correct-course', 'bmad-create-epics-and-stories', 'bmad-prd',
'bmad-preview-ticketing', 'bmad-prfaq', 'bmad-product-brief', 'bmad-project-context',
'bmad-qa-generate-e2e-tests', 'bmad-retrospective', 'bmad-spec', 'bmad-sprint-planning',
'bmad-ux', 'bmad-walkthrough',
'bmad-code-review', 'bmad-correct-course', 'bmad-prd', 'bmad-prfaq', 'bmad-product-brief',
'bmad-project-context', 'bmad-qa-generate-e2e-tests', 'bmad-retrospective', 'bmad-spec',
'bmad-ticket', 'bmad-ux', 'bmad-walkthrough',
]

/** @type {string[]} */
Expand Down Expand Up @@ -63,7 +62,7 @@ test('loads and validates the real modules.yaml', async () => {
assert.equal(method.record, 'bmod-method')
assert.equal(method.source, 'bmad-code-org/BMAD-METHOD')
assert.ok(method.message && method.message.length > 0)
assert.deepEqual(bundleCodes(method, () => true), ['planning', 'build', 'agents', 'extras'])
assert.deepEqual(bundleCodes(method, () => true), ['planning', 'build', 'agents'])
assert.equal(must(modules, 'cis').bundles, undefined)
})

Expand All @@ -82,8 +81,8 @@ test('parseModulesFlag reads the code:bundle+bundle,code grammar', async () => {
{ code: 'method', bundles: ['planning', 'build'] },
{ code: 'cis', bundles: null },
])
assert.deepEqual(parseModulesFlag(' method : planning + extras , cis ', modules), [
{ code: 'method', bundles: ['planning', 'extras'] },
assert.deepEqual(parseModulesFlag(' method : planning + agents , cis ', modules), [
{ code: 'method', bundles: ['planning', 'agents'] },
{ code: 'cis', bundles: null },
])
assert.deepEqual(parseModulesFlag('bmm', modules), [
Expand Down Expand Up @@ -143,7 +142,7 @@ test('defaultChoices takes default modules with their default bundles', async ()
test('bundleCodes filters', async () => {
const method = must(await loadModules(), 'method')
assert.deepEqual(bundleCodes(method, (bundle) => bundle.default === true), ['planning', 'build', 'agents'])
assert.deepEqual(bundleCodes(method, (bundle) => bundle.default !== true), ['extras'])
assert.deepEqual(bundleCodes(method, (bundle) => bundle.default !== true), [])
})

test('skillsToInstall without bundles takes the whole record list', async () => {
Expand All @@ -161,12 +160,12 @@ test('skillsToInstall keeps module order and reports unknown skills', async () =
'bmad-product-brief', 'bmad-prfaq', 'bmad-prd', 'bmad-ux',
'bmad-architecture', 'bmad-spec', 'bmad-project-context',
])
assert.equal(install[7], 'bmad-create-epics-and-stories')
assert.equal(install[7], 'bmad-ticket')
assert.deepEqual(unknown, [])

const partial = skillsToInstall(method, ['extras'], ['bmad-walkthrough'])
assert.deepEqual(partial.install, ['bmad-walkthrough'])
assert.deepEqual(partial.unknown, ['bmad-preview-ticketing'])
const partial = skillsToInstall(method, ['agents'], ['bmad-agent-dev'])
assert.deepEqual(partial.install, ['bmad-agent-dev'])
assert.deepEqual(partial.unknown, ['bmad-agent-analyst', 'bmad-agent-architect', 'bmad-agent-pm', 'bmad-agent-ux-designer'])
})

test('groupBySource keeps modules.yaml order', async () => {
Expand Down
14 changes: 7 additions & 7 deletions test/prompts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@ test('an installed module with no known version gets the plain suffix', () => {

test('the bundle picker offers every bundle and ticks the default ones', () => {
const picker = bundlePicker(method, { installedSkills: [] })
assert.deepEqual(picker.options.map((option) => option.value), ['planning', 'build', 'agents', 'extras'])
assert.deepEqual(picker.options.map((option) => option.value), ['planning', 'build', 'agents'])
assert.deepEqual(picker.initialValues, ['planning', 'build', 'agents'])
})

test('a bundle whose skills are all installed is ticked even when it is not a default', () => {
const extras = method.bundles?.find((bundle) => bundle.code === 'extras')
assert.ok(extras)
const picker = bundlePicker(method, { installedSkills: extras.skills })
assert.deepEqual(picker.initialValues, ['planning', 'build', 'agents', 'extras'])
const extra = { code: 'extra', name: 'Extra', description: 'Not a default', skills: ['bmad-walkthrough'] }
const withExtra = { ...method, bundles: [...(method.bundles ?? []), extra] }
const picker = bundlePicker(withExtra, { installedSkills: extra.skills })
assert.deepEqual(picker.initialValues, ['planning', 'build', 'agents', 'extra'])

const partial = bundlePicker(method, { installedSkills: extras.skills.slice(0, 1) })
assert.equal(partial.initialValues.includes('extras'), false)
const none = bundlePicker(withExtra, { installedSkills: [] })
assert.equal(none.initialValues.includes('extra'), false)
})

test('a module without bundles offers nothing', () => {
Expand Down
Loading