Compare commits

...

7 Commits

Author SHA1 Message Date
Hisyam ff89b8063c
Merge 84a3aa57de into d401afd3f3 2026-04-12 23:18:46 -05:00
Brian d401afd3f3
Merge pull request #2252 from bmad-code-org/fix-workflow-diagram-bob
docs: remove Bob from workflow map diagrams
2026-04-12 23:13:57 -05:00
Brian b4d6a92e65
Merge branch 'main' into fix-workflow-diagram-bob 2026-04-12 23:13:47 -05:00
Brian Madison 246270bef2 docs: remove Bob from workflow map diagrams
Bob (Scrum Master) was consolidated into Amelia (Developer) in v6.3.0
(#2186) but still appeared in the workflow map diagrams for
sprint-planning, create-story, and retrospective. Updated both English
and French versions to show Amelia and removed the unused Bob CSS class.

Closes #2249
2026-04-12 23:12:32 -05:00
Brian 79a6876a65
Merge pull request #2251 from bmad-code-org/fix-installer-builtin-modules
fix(installer): source built-in modules locally instead of from registry
2026-04-12 23:01:42 -05:00
Brian Madison 83f374c254 fix(installer): source built-in modules locally instead of from registry
Core and BMM modules live in this repo (src/core-skills, src/bmm-skills)
but the installer UI sourced them from the remote registry. When the
registry was unreachable (VPN, proxy, firewall), the fallback YAML only
had the 4 external modules, so core and bmm disappeared from the install
list entirely.

Now _selectOfficialModules and getDefaultModules always read built-in
modules from the local source via OfficialModules.listAvailable(), then
append external modules from the registry. Network failures only affect
external modules.

Closes #2239
2026-04-12 22:41:40 -05:00
Hisyam 84a3aa57de
docs: add pencil usage guidelines to core-tools #2162
Addresses issue #2162 by adding recommendations for introducing Pencil early in the BMad workflow.
2026-03-30 12:14:20 +07:00
5 changed files with 62 additions and 19 deletions

View File

@ -291,3 +291,14 @@ Run both `bmad-review-adversarial-general` and `bmad-review-edge-case-hunter` to
**Input:** Target folder path **Input:** Target folder path
**Output:** `index.md` with organized file listings, relative links, and brief descriptions **Output:** `index.md` with organized file listings, relative links, and brief descriptions
## 3rd Party Tools Integration: Pencil
If you are using **Pencil** within BMAD workflows for creating mockups or UI designs, it is critical that the LLM is fully aware of its existence early in the process rather than treating it merely as a nice-to-have MCP (Model Context Protocol).
**Important Guidelines for Pencil:**
- **Introduce Early:** The sooner you bring Pencil into your planning process, the better. You must specify Pencil in your tooling **before** generating the `_bmad-output/planning-artifacts/architecture.md` document.
- **Enforce Context:** Explicitly enforce the inclusion of your `.pen` (Pencil) files in the `_bmad-output/project-context.md` file.
- **Why this matters:** If you bring Pencil in after the PRD, UX, and Architecture docs are already drafted without establishing these guardrails, the AI will not integrate it smoothly and will cause avoidable course corrections during sprints.

View File

@ -1,5 +1,6 @@
code: core code: core
name: "BMad Core Module" name: "BMad Core Module"
description: "Core configuration and shared resources"
header: "BMad Core Configuration" header: "BMad Core Configuration"
subheader: "Configure the core settings for your BMad installation.\nThese settings will be used across all installed bmad skills, workflows, and agents." subheader: "Configure the core settings for your BMad installation.\nThese settings will be used across all installed bmad skills, workflows, and agents."

View File

@ -598,7 +598,7 @@ class UI {
const officialCodes = new Set(officialSelected); const officialCodes = new Set(officialSelected);
const externalManager = new ExternalModuleManager(); const externalManager = new ExternalModuleManager();
const registryModules = await externalManager.listAvailable(); const registryModules = await externalManager.listAvailable();
const officialRegistryCodes = new Set(registryModules.map((m) => m.code)); const officialRegistryCodes = new Set(['core', 'bmm', ...registryModules.map((m) => m.code)]);
const installedNonOfficial = [...installedModuleIds].filter((id) => !officialRegistryCodes.has(id)); const installedNonOfficial = [...installedModuleIds].filter((id) => !officialRegistryCodes.has(id));
// Phase 2: Community modules (category drill-down) // Phase 2: Community modules (category drill-down)
@ -630,6 +630,11 @@ class UI {
* @returns {Array} Selected official module codes * @returns {Array} Selected official module codes
*/ */
async _selectOfficialModules(installedModuleIds = new Set()) { async _selectOfficialModules(installedModuleIds = new Set()) {
// Built-in modules (core, bmm) come from local source, not the registry
const { OfficialModules } = require('./modules/official-modules');
const builtInModules = (await new OfficialModules().listAvailable()).modules || [];
// External modules come from the registry (with fallback)
const externalManager = new ExternalModuleManager(); const externalManager = new ExternalModuleManager();
const registryModules = await externalManager.listAvailable(); const registryModules = await externalManager.listAvailable();
@ -637,20 +642,34 @@ class UI {
const initialValues = []; const initialValues = [];
const lockedValues = ['core']; const lockedValues = ['core'];
const buildModuleEntry = async (mod) => { const buildModuleEntry = async (code, name, description, isDefault) => {
const isInstalled = installedModuleIds.has(mod.code); const isInstalled = installedModuleIds.has(code);
const version = await getMarketplaceVersion(mod.code); const version = await getMarketplaceVersion(code);
const label = version ? `${mod.name} (v${version})` : mod.name; const label = version ? `${name} (v${version})` : name;
return { return {
label, label,
value: mod.code, value: code,
hint: mod.description, hint: description,
selected: isInstalled, selected: isInstalled || isDefault,
}; };
}; };
// Add built-in modules first (always available regardless of network)
const builtInCodes = new Set();
for (const mod of builtInModules) {
const code = mod.id;
builtInCodes.add(code);
const entry = await buildModuleEntry(code, mod.name, mod.description, mod.defaultSelected);
allOptions.push({ label: entry.label, value: entry.value, hint: entry.hint });
if (entry.selected) {
initialValues.push(code);
}
}
// Add external registry modules (skip built-in duplicates)
for (const mod of registryModules) { for (const mod of registryModules) {
const entry = await buildModuleEntry(mod); if (mod.builtIn || builtInCodes.has(mod.code)) continue;
const entry = await buildModuleEntry(mod.code, mod.name, mod.description, mod.defaultSelected);
allOptions.push({ label: entry.label, value: entry.value, hint: entry.hint }); allOptions.push({ label: entry.label, value: entry.value, hint: entry.hint });
if (entry.selected) { if (entry.selected) {
initialValues.push(mod.code); initialValues.push(mod.code);
@ -1122,12 +1141,26 @@ class UI {
* @returns {Array} Default module codes * @returns {Array} Default module codes
*/ */
async getDefaultModules(installedModuleIds = new Set()) { async getDefaultModules(installedModuleIds = new Set()) {
// Built-in modules with default_selected come from local source
const { OfficialModules } = require('./modules/official-modules');
const builtInModules = (await new OfficialModules().listAvailable()).modules || [];
const defaultModules = [];
const seen = new Set();
for (const mod of builtInModules) {
if (mod.defaultSelected || installedModuleIds.has(mod.id)) {
defaultModules.push(mod.id);
seen.add(mod.id);
}
}
// Add external registry defaults
const externalManager = new ExternalModuleManager(); const externalManager = new ExternalModuleManager();
const registryModules = await externalManager.listAvailable(); const registryModules = await externalManager.listAvailable();
const defaultModules = [];
for (const mod of registryModules) { for (const mod of registryModules) {
if (mod.builtIn || seen.has(mod.code)) continue;
if (mod.defaultSelected || installedModuleIds.has(mod.code)) { if (mod.defaultSelected || installedModuleIds.has(mod.code)) {
defaultModules.push(mod.code); defaultModules.push(mod.code);
} }

View File

@ -93,7 +93,6 @@
.agent-icon.john { background: linear-gradient(135deg, #60a5fa, #3b82f6); } .agent-icon.john { background: linear-gradient(135deg, #60a5fa, #3b82f6); }
.agent-icon.sally { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #000; } .agent-icon.sally { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #000; }
.agent-icon.winston { background: linear-gradient(135deg, #a78bfa, #8b5cf6); } .agent-icon.winston { background: linear-gradient(135deg, #a78bfa, #8b5cf6); }
.agent-icon.bob { background: linear-gradient(135deg, #34d399, #10b981); color: #000; }
.agent-icon.amelia { background: linear-gradient(135deg, #fb7185, #ef4444); } .agent-icon.amelia { background: linear-gradient(135deg, #fb7185, #ef4444); }
.agent-name { font-size: 0.65rem; } .agent-name { font-size: 0.65rem; }
@ -261,7 +260,7 @@
<span class="workflow-name">sprint-planning</span> <span class="workflow-name">sprint-planning</span>
</div> </div>
<div class="workflow-meta"> <div class="workflow-meta">
<div class="agent"><div class="agent-icon bob">B</div><span class="agent-name">Bob</span></div> <div class="agent"><div class="agent-icon amelia">A</div><span class="agent-name">Amelia</span></div>
<span class="output">sprint-status.yaml →</span> <span class="output">sprint-status.yaml →</span>
</div> </div>
</div> </div>
@ -270,7 +269,7 @@
<span class="workflow-name">create-story</span> <span class="workflow-name">create-story</span>
</div> </div>
<div class="workflow-meta"> <div class="workflow-meta">
<div class="agent"><div class="agent-icon bob">B</div><span class="agent-name">Bob</span></div> <div class="agent"><div class="agent-icon amelia">A</div><span class="agent-name">Amelia</span></div>
<span class="output">story-[slug].md →</span> <span class="output">story-[slug].md →</span>
</div> </div>
</div> </div>
@ -308,7 +307,7 @@
<span class="badge adhoc">par Epic</span> <span class="badge adhoc">par Epic</span>
</div> </div>
<div class="workflow-meta"> <div class="workflow-meta">
<div class="agent"><div class="agent-icon bob">B</div><span class="agent-name">Bob</span></div> <div class="agent"><div class="agent-icon amelia">A</div><span class="agent-name">Amelia</span></div>
<span class="output">leçons</span> <span class="output">leçons</span>
</div> </div>
</div> </div>

View File

@ -93,7 +93,6 @@
.agent-icon.john { background: linear-gradient(135deg, #60a5fa, #3b82f6); } .agent-icon.john { background: linear-gradient(135deg, #60a5fa, #3b82f6); }
.agent-icon.sally { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #000; } .agent-icon.sally { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #000; }
.agent-icon.winston { background: linear-gradient(135deg, #a78bfa, #8b5cf6); } .agent-icon.winston { background: linear-gradient(135deg, #a78bfa, #8b5cf6); }
.agent-icon.bob { background: linear-gradient(135deg, #34d399, #10b981); color: #000; }
.agent-icon.amelia { background: linear-gradient(135deg, #fb7185, #ef4444); } .agent-icon.amelia { background: linear-gradient(135deg, #fb7185, #ef4444); }
.agent-name { font-size: 0.65rem; } .agent-name { font-size: 0.65rem; }
@ -272,7 +271,7 @@
<span class="workflow-name">sprint-planning</span> <span class="workflow-name">sprint-planning</span>
</div> </div>
<div class="workflow-meta"> <div class="workflow-meta">
<div class="agent"><div class="agent-icon bob">B</div><span class="agent-name">Bob</span></div> <div class="agent"><div class="agent-icon amelia">A</div><span class="agent-name">Amelia</span></div>
<span class="output">sprint-status.yaml →</span> <span class="output">sprint-status.yaml →</span>
</div> </div>
</div> </div>
@ -281,7 +280,7 @@
<span class="workflow-name">create-story</span> <span class="workflow-name">create-story</span>
</div> </div>
<div class="workflow-meta"> <div class="workflow-meta">
<div class="agent"><div class="agent-icon bob">B</div><span class="agent-name">Bob</span></div> <div class="agent"><div class="agent-icon amelia">A</div><span class="agent-name">Amelia</span></div>
<span class="output">story-[slug].md →</span> <span class="output">story-[slug].md →</span>
</div> </div>
</div> </div>
@ -319,7 +318,7 @@
<span class="badge adhoc">per epic</span> <span class="badge adhoc">per epic</span>
</div> </div>
<div class="workflow-meta"> <div class="workflow-meta">
<div class="agent"><div class="agent-icon bob">B</div><span class="agent-name">Bob</span></div> <div class="agent"><div class="agent-icon amelia">A</div><span class="agent-name">Amelia</span></div>
<span class="output">lessons</span> <span class="output">lessons</span>
</div> </div>
</div> </div>