From 827fd3299fd62106941468da8b62dd1ee92e690b Mon Sep 17 00:00:00 2001 From: Mark2Mac Date: Tue, 4 Aug 2026 12:45:12 +0200 Subject: [PATCH] test(mp2): lock the layout-span guard against regressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `_is_layout_only_span()` is what keeps MP2 from reporting alignment as context stuffing, and it has no test. The only layout case covered today is `"=" * 80`, which never reaches the helper — the older single-character guard skips it first. Measured on a corpus of 4406 files from 65 skill/plugin units, comparing the analyzer before the helper landed with `main` today: MP2 findings 279 -> 4 The four survivors come from MP2's prose patterns ("exceed context window"), not from the repetition pattern. So the helper is carrying 275 of 279 findings, with nothing pinning its behaviour. The three cases added here are each reported when the helper is stubbed out, which is what makes them regressions rather than restatements of the guard above them: a dash rule, a run of padded columns, and a box edge with padding. The fourth test locks the other side, `_MAX_LAYOUT_ONLY_SPAN`: past that width layout stops being a plausible explanation and the run is reported again. No source change. Signed-off-by: Mark2Mac --- tests/unit/test_patterns_new.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/unit/test_patterns_new.py b/tests/unit/test_patterns_new.py index e765c304..708b3670 100644 --- a/tests/unit/test_patterns_new.py +++ b/tests/unit/test_patterns_new.py @@ -551,6 +551,25 @@ def test_mp2_repeated_pattern(self) -> None: def test_mp2_separator_not_flagged(self) -> None: assert not any(f.rule_id == "MP2" for f in mp_mod.analyze("=" * 80, "test.md", "markdown")) + @pytest.mark.parametrize( + "content", + [ + pytest.param("- " * 40, id="dash_space_rule"), + pytest.param("| " * 40, id="pipe_space_columns"), + pytest.param("│ " * 30, id="box_drawing_and_padding"), + ], + ) + def test_mp2_layout_span_not_flagged(self, content: str) -> None: + # The single-character guard above exempts only a run of one repeated character with no + # whitespace, so alignment built from a repeated *unit* — a rule, a column, a box edge — + # falls through to _is_layout_only_span(). Each case here is reported when that helper + # is removed, which is what makes them regressions rather than restatements. + assert not any(f.rule_id == "MP2" for f in mp_mod.analyze(content, "test.md", "markdown")) + + def test_mp2_layout_glyphs_beyond_the_cosmetic_span_are_still_flagged(self) -> None: + # _MAX_LAYOUT_ONLY_SPAN is the point where layout stops being a plausible explanation. + assert any(f.rule_id == "MP2" for f in mp_mod.analyze("- " * 200, "test.md", "markdown")) + @pytest.mark.parametrize( "content", [