You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #155 carried a toml_artifact_parity validate check: read the four-layer central TOML the
renderer reads (_bmad/config.toml, config.user.toml, custom/config.toml, custom/config.user.toml), read the legacy _bmad/bmm/config.yaml that bmadconfig.load_paths
reads, and warn when the two disagree on implementation_artifacts / planning_artifacts —
the desync in which the skill writes specs and the deferred-work ledger where the orchestrator
is not looking.
The check was cut from PR #406's review round, not because it is expensive but because its
model of the renderer is now provably wrong. Resurrecting it requires fixing the model first.
Collision resolution. It resolves [modules.bmm] over [core] when both define the key,
and its own test pins that. The current renderer does no such thing: _resolve_short_config collects every match by key name anywhere in the merged tree and
raises on more than one —
iflen(matches) >1:
paths=", ".join(pathforpath, _inmatches)
raiseRenderError(f"ambiguous config value `{key}` found at: {paths}")
Merge semantics._toml_merge is a plain recursive dict merge. config_utils.structural_merge
merges table arrays by identity key and appends other arrays. The layered result differs
whenever any layer carries an array.
Note that #154's own Context paragraph states the "[modules.bmm] beating [core] on collision"
model too — it was written in the same era and inherits the same error.
Scope
Reuse the renderer's own semantics rather than reimplementing them: mirror structural_merge
and _find_config_values, or state explicitly why a local copy is required and pin it with a
test that fails when the vendored renderer changes shape.
Three outcomes, not two: agree (silent), disagree (parity warning, the original
finding), and ambiguous (the key resolves in more than one table — the renderer would
HALT, which is a different and more urgent finding than a parity mismatch).
New check ids must land in checks.VALIDATE_CHECKS, or the existing subset tests fail.
Context
Follow-up from #405 / PR #406. Relates to #154.
PR #155 carried a
toml_artifact_parityvalidate check: read the four-layer central TOML therenderer reads (
_bmad/config.toml,config.user.toml,custom/config.toml,custom/config.user.toml), read the legacy_bmad/bmm/config.yamlthatbmadconfig.load_pathsreads, and warn when the two disagree on
implementation_artifacts/planning_artifacts—the desync in which the skill writes specs and the deferred-work ledger where the orchestrator
is not looking.
The check was cut from PR #406's review round, not because it is expensive but because its
model of the renderer is now provably wrong. Resurrecting it requires fixing the model first.
What is wrong with #155's version
Collision resolution. It resolves
[modules.bmm]over[core]when both define the key,and its own test pins that. The current renderer does no such thing:
_resolve_short_configcollects every match by key name anywhere in the merged tree andraises on more than one —
So the exact case fix(worktree): survive the renderer-era bmad-dev-auto (BMAD-METHOD #2587/#2588) #155 models as "bmm wins" is a hard HALT today. The check would print a
confident parity verdict for a config that cannot render at all — worse than no check.
Merge semantics.
_toml_mergeis a plain recursive dict merge.config_utils.structural_mergemerges table arrays by identity key and appends other arrays. The layered result differs
whenever any layer carries an array.
Note that #154's own Context paragraph states the "
[modules.bmm]beating[core]on collision"model too — it was written in the same era and inherits the same error.
Scope
structural_mergeand
_find_config_values, or state explicitly why a local copy is required and pin it with atest that fails when the vendored renderer changes shape.
finding), and ambiguous (the key resolves in more than one table — the renderer would
HALT, which is a different and more urgent finding than a parity mismatch).
checks.VALIDATE_CHECKS, or the existing subset tests fail.