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
Found by the PR #86 final review (adversarially verified). Pre-existing on main; masked by test fixtures.
The gap
_verify_shared_gates reads fm.get("baseline_commit", "") from the spec frontmatter and skips the whole baseline-match check when the key is absent (verify.py ~1055-1061). The generic bmad-dev-auto skill never writes baseline_commit — its step-03 stamps baseline_revision ('Capture baseline_revision (current HEAD…) into {spec_file} frontmatter'). The only baseline_revision → baseline_commit translation lives in devcontract's result-synthesis, which the gate does not consult (it re-reads frontmatter directly).
Net: in production the baseline-match gate never fires for generic-skill sessions — a spec claiming a stale/foreign baseline sails through.
Why the tests didn't catch it
tests/conftest.py's write_spec (and the engine-test session fakes) emit baseline_commit: directly, fabricating exactly the key the real skill never writes — so the gate looks alive and matching under test.
Fix shape
Gate reads both keys (baseline_commit, falling back to baseline_revision) or a single normalizing reader.
Make the fixtures honest: write_spec should stamp baseline_revision like the real skill, so a regression here fails a test.
Context
Found by the PR #86 final review (adversarially verified). Pre-existing on
main; masked by test fixtures.The gap
_verify_shared_gatesreadsfm.get("baseline_commit", "")from the spec frontmatter and skips the whole baseline-match check when the key is absent (verify.py ~1055-1061). The genericbmad-dev-autoskill never writesbaseline_commit— its step-03 stampsbaseline_revision('Capturebaseline_revision(current HEAD…) into{spec_file}frontmatter'). The onlybaseline_revision → baseline_committranslation lives indevcontract's result-synthesis, which the gate does not consult (it re-reads frontmatter directly).Net: in production the baseline-match gate never fires for generic-skill sessions — a spec claiming a stale/foreign baseline sails through.
Why the tests didn't catch it
tests/conftest.py'swrite_spec(and the engine-test session fakes) emitbaseline_commit:directly, fabricating exactly the key the real skill never writes — so the gate looks alive and matching under test.Fix shape
baseline_commit, falling back tobaseline_revision) or a single normalizing reader.write_specshould stampbaseline_revisionlike the real skill, so a regression here fails a test.baseline_revision(review F2), so once the gate reads it, restore re-drives stay consistent by construction.