Compare commits

...

9 Commits

Author SHA1 Message Date
gabadi d207f3a958
Merge b161491ca8 into d401afd3f3 2026-04-13 01:07:26 -04: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
Alex Verkhovsky b161491ca8
Merge branch 'main' into fix/quick-dev-review-data-loss-classification 2026-03-30 20:40:56 -07:00
gabadi 98f8786060 fix: reframe data-loss clause to align with 'caused/exposed by change' language 2026-03-27 01:03:34 -03:00
gabadi 229c1c57f9 fix: extend bad_spec classification to cover data-loss findings within story domain 2026-03-27 00:58:09 -03:00
5 changed files with 52 additions and 20 deletions

View File

@ -34,7 +34,7 @@ Launch three subagents without conversation context. If no sub-agents are availa
1. Deduplicate all review findings. 1. Deduplicate all review findings.
2. Classify each finding. The first three categories are **this story's problem** — caused or exposed by the current change. The last two are **not this story's problem**. 2. Classify each finding. The first three categories are **this story's problem** — caused or exposed by the current change. The last two are **not this story's problem**.
- **intent_gap** — caused by the change; cannot be resolved from the spec because the captured intent is incomplete. Do not infer intent unless there is exactly one possible reading. - **intent_gap** — caused by the change; cannot be resolved from the spec because the captured intent is incomplete. Do not infer intent unless there is exactly one possible reading.
- **bad_spec** — caused by the change, including direct deviations from spec. The spec should have been clear enough to prevent it. When in doubt between bad_spec and patch, prefer bad_spec — a spec-level fix is more likely to produce coherent code. - **bad_spec** — caused by the change, including direct deviations from spec. The spec should have been clear enough to prevent it. When in doubt between bad_spec and patch, prefer bad_spec — a spec-level fix is more likely to produce coherent code. Also applies when the story's domain includes data silently dropped or never reaching its destination — the change exposed it.
- **patch** — caused by the change; trivially fixable without human input. Just part of the diff. - **patch** — caused by the change; trivially fixable without human input. Just part of the diff.
- **defer** — pre-existing issue not caused by this story, surfaced incidentally by the review. Collect for later focused attention. - **defer** — pre-existing issue not caused by this story, surfaced incidentally by the review. Collect for later focused attention.
- **reject** — noise. Drop silently. When unsure between defer and reject, prefer reject — only defer findings you are confident are real. - **reject** — noise. Drop silently. When unsure between defer and reject, prefer reject — only defer findings you are confident are real.

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>