Skip to content

toml_artifact_parity: resurrect #155's check with a corrected renderer model #408

Description

@pbean

Context

Follow-up from #405 / PR #406. Relates to #154.

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.

What is wrong with #155's version

  1. 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 —

    if len(matches) > 1:
        paths = ", ".join(path for path, _ in matches)
        raise RenderError(f"ambiguous config value `{key}` found at: {paths}")

    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.

  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:configBMAD config resolution and the setup skillenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions