fix(installer): strip core-key pollution from [modules.*]; soften config headers
- writeCentralConfig now always strips core-module keys from every [modules.<code>] bucket, even when the module's schema is not available in src/ (external / marketplace modules like cis, bmb). Core values belong in [core] only; workflows read them directly. - When the module's own schema IS available (built-in modules), also drop any key it does not declare as a prompt — same spread-pollution filter as before, now layered on top. - Section-aware headers on both _bmad/config.toml and _bmad/config.user.toml: [core] / [modules.*] values are editable (installer reads them as defaults on next install); [agents.*] is regenerated from module.yaml and will be wiped — overrides for agents go in _bmad/custom/config*.toml instead.
This commit is contained in:
parent
6b91aa249d
commit
ffcdaf7529
|
|
@ -423,11 +423,26 @@ class ManifestGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const partition = (moduleName, cfg) => {
|
// Core keys are always known (core module.yaml is built-in). These are
|
||||||
|
// the only keys allowed in [core]; they must be stripped from every
|
||||||
|
// non-core module bucket because legacy _bmad/{mod}/config.yaml files
|
||||||
|
// spread core values into each module. Core belongs in [core] only —
|
||||||
|
// workflows that need user_name/language/etc. read [core] directly.
|
||||||
|
const coreKeys = new Set(Object.keys(scopeByModuleKey.core || {}));
|
||||||
|
|
||||||
|
// Partition a module's answered config into team vs user buckets.
|
||||||
|
// For non-core modules: strip core keys always; when we know the module's
|
||||||
|
// own schema, also drop keys it doesn't declare. Unknown-schema modules
|
||||||
|
// (external / marketplace) fall through with their remaining answers as
|
||||||
|
// team so they don't vanish from the config.
|
||||||
|
const partition = (moduleName, cfg, onlyDeclaredKeys = false) => {
|
||||||
const team = {};
|
const team = {};
|
||||||
const user = {};
|
const user = {};
|
||||||
const scopes = scopeByModuleKey[moduleName] || {};
|
const scopes = scopeByModuleKey[moduleName] || {};
|
||||||
|
const isCore = moduleName === 'core';
|
||||||
for (const [key, value] of Object.entries(cfg || {})) {
|
for (const [key, value] of Object.entries(cfg || {})) {
|
||||||
|
if (!isCore && coreKeys.has(key)) continue;
|
||||||
|
if (onlyDeclaredKeys && !(key in scopes)) continue;
|
||||||
if (scopes[key] === 'user') {
|
if (scopes[key] === 'user') {
|
||||||
user[key] = value;
|
user[key] = value;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -439,22 +454,33 @@ class ManifestGenerator {
|
||||||
|
|
||||||
const teamHeader = [
|
const teamHeader = [
|
||||||
'# ─────────────────────────────────────────────────────────────────',
|
'# ─────────────────────────────────────────────────────────────────',
|
||||||
'# DO NOT EDIT — regenerated on every install.',
|
'# Installer-managed. Regenerated on every install.',
|
||||||
'#',
|
'#',
|
||||||
'# To override any value, add it to one of:',
|
'# [core] and [modules.<code>] values: you CAN edit these directly.',
|
||||||
'# _bmad/custom/config.toml (team, committed to version control)',
|
'# The installer reads current values as defaults on next install,',
|
||||||
'# _bmad/custom/config.user.toml (personal, gitignored)',
|
'# so your edits persist.',
|
||||||
|
'#',
|
||||||
|
'# [agents.<code>] values: regenerated from each module.yaml on every',
|
||||||
|
'# install. DO NOT edit here — your changes will be wiped. To override',
|
||||||
|
'# an agent descriptor or add custom agents, use:',
|
||||||
|
'# _bmad/custom/config.toml (team, committed)',
|
||||||
|
'# _bmad/custom/config.user.toml (personal, gitignored)',
|
||||||
|
'# Those files are never touched by the installer.',
|
||||||
'# ─────────────────────────────────────────────────────────────────',
|
'# ─────────────────────────────────────────────────────────────────',
|
||||||
'',
|
'',
|
||||||
];
|
];
|
||||||
|
|
||||||
const userHeader = [
|
const userHeader = [
|
||||||
'# ─────────────────────────────────────────────────────────────────',
|
'# ─────────────────────────────────────────────────────────────────',
|
||||||
'# DO NOT EDIT — regenerated on every install.',
|
'# Installer-managed. Regenerated on every install.',
|
||||||
'# This file holds install answers scoped to YOU personally.',
|
'# Holds install answers scoped to YOU personally.',
|
||||||
'#',
|
'#',
|
||||||
'# To override any value, add it to:',
|
'# You CAN edit values here directly. The installer reads current',
|
||||||
'# _bmad/custom/config.user.toml (personal, gitignored)',
|
'# values as defaults on next install, so your edits persist.',
|
||||||
|
'#',
|
||||||
|
'# For custom agents or sections the installer does not know about,',
|
||||||
|
'# use _bmad/custom/config.user.toml — it is never touched by the',
|
||||||
|
'# installer.',
|
||||||
'# ─────────────────────────────────────────────────────────────────',
|
'# ─────────────────────────────────────────────────────────────────',
|
||||||
'',
|
'',
|
||||||
];
|
];
|
||||||
|
|
@ -485,7 +511,12 @@ class ManifestGenerator {
|
||||||
if (moduleName === 'core') continue;
|
if (moduleName === 'core') continue;
|
||||||
const cfg = moduleConfigs[moduleName];
|
const cfg = moduleConfigs[moduleName];
|
||||||
if (!cfg || Object.keys(cfg).length === 0) continue;
|
if (!cfg || Object.keys(cfg).length === 0) continue;
|
||||||
const { team: modTeam, user: modUser } = partition(moduleName, cfg);
|
// Only filter out spread-from-core pollution when we actually know
|
||||||
|
// this module's prompt schema. For external/marketplace modules whose
|
||||||
|
// module.yaml isn't in the src tree, fall through as all-team so we
|
||||||
|
// don't drop their real answers.
|
||||||
|
const haveSchema = Object.keys(scopeByModuleKey[moduleName] || {}).length > 0;
|
||||||
|
const { team: modTeam, user: modUser } = partition(moduleName, cfg, haveSchema);
|
||||||
if (Object.keys(modTeam).length > 0) {
|
if (Object.keys(modTeam).length > 0) {
|
||||||
teamLines.push(`[modules.${moduleName}]`);
|
teamLines.push(`[modules.${moduleName}]`);
|
||||||
for (const [key, value] of Object.entries(modTeam)) {
|
for (const [key, value] of Object.entries(modTeam)) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue