What
While fixing the RepoBadge/ConstraintSet-class mutation-attribution gap
(dataclass method bodies invisible to mutmut) for scripts/generate_repo_badges.py,
the task's own boy-scout sweep instruction found the identical dataclass-exclusion
defect in scripts/refresh_mcp_toplist_badge.py's Ranking class
(percentile()/tier_text() methods, 298 mutants generated for the file, 0
attributed to either method). That specific defect is fixed in this PR's branch
(fix-repobadge-mutation-attribution): the methods are extracted to
ranking_percentile()/ranking_tier_text() free functions, the existing
27-test suite in tests_py/scripts/test_refresh_mcp_toplist_badge.py passes
unchanged, and a scoped mutation run confirms 0 survivors in either
extracted function (they are now fully killed).
The separate, larger gap found in the same run
Running the SAME scoped mutation pass on the whole file surfaced a much larger,
unrelated number: 314 total mutants, 198 killed, 116 survived, all in
functions that never had the dataclass-exclusion problem at all —
_provenance_comment (16), fetch (15), main (22), parse_leaderboard (21),
parse_server_page (6), render_badge (20), resolve_ranking (7),
validate (8), _today (1). This file's test suite is comprehensive on
paper (27 tests covering fetch/parse/validate/render/main), but a real
mutation run had apparently never been carried through to completion and
triaged before — there is a substantial gap between "every code path is
exercised" and "every mutation of that code is caught."
Why this is filed rather than fixed here (§15.1)
Fixing 116 survivors across 8 unrelated functions is a second, independent
root-cause investigation of comparable-or-greater size than the dataclass
extraction itself — mixing it into the dataclass-attribution PR would
roughly quadruple that PR's blast radius beyond its named subject
(RepoBadge's mutation-attribution gap in generate_repo_badges.py, plus
the same defect class found in Ranking). This mirrors PR #280's own
precedent: #280 found this exact RepoBadge/dataclass defect and reported
it with evidence rather than fixing it in the same PR, for the identical
reason.
Reproduction
scripts/mutation_check.sh tests_py/scripts/test_refresh_mcp_toplist_badge.py \
scripts/refresh_mcp_toplist_badge.py
(or invoke mutmut directly against the shared venv if uv run cannot resolve
a fresh environment — see the fix-repobadge-mutation-attribution branch notes).
Acceptance criteria
What
While fixing the
RepoBadge/ConstraintSet-class mutation-attribution gap(dataclass method bodies invisible to mutmut) for
scripts/generate_repo_badges.py,the task's own boy-scout sweep instruction found the identical dataclass-exclusion
defect in
scripts/refresh_mcp_toplist_badge.py'sRankingclass(
percentile()/tier_text()methods, 298 mutants generated for the file, 0attributed to either method). That specific defect is fixed in this PR's branch
(
fix-repobadge-mutation-attribution): the methods are extracted toranking_percentile()/ranking_tier_text()free functions, the existing27-test suite in
tests_py/scripts/test_refresh_mcp_toplist_badge.pypassesunchanged, and a scoped mutation run confirms 0 survivors in either
extracted function (they are now fully killed).
The separate, larger gap found in the same run
Running the SAME scoped mutation pass on the whole file surfaced a much larger,
unrelated number: 314 total mutants, 198 killed, 116 survived, all in
functions that never had the dataclass-exclusion problem at all —
_provenance_comment(16),fetch(15),main(22),parse_leaderboard(21),parse_server_page(6),render_badge(20),resolve_ranking(7),validate(8),_today(1). This file's test suite is comprehensive onpaper (27 tests covering fetch/parse/validate/render/main), but a real
mutation run had apparently never been carried through to completion and
triaged before — there is a substantial gap between "every code path is
exercised" and "every mutation of that code is caught."
Why this is filed rather than fixed here (§15.1)
Fixing 116 survivors across 8 unrelated functions is a second, independent
root-cause investigation of comparable-or-greater size than the dataclass
extraction itself — mixing it into the dataclass-attribution PR would
roughly quadruple that PR's blast radius beyond its named subject
(
RepoBadge's mutation-attribution gap ingenerate_repo_badges.py, plusthe same defect class found in
Ranking). This mirrors PR #280's ownprecedent: #280 found this exact
RepoBadge/dataclass defect and reportedit with evidence rather than fixing it in the same PR, for the identical
reason.
Reproduction
(or invoke mutmut directly against the shared venv if
uv runcannot resolvea fresh environment — see the fix-repobadge-mutation-attribution branch notes).
Acceptance criteria
_provenance_comment,fetch,main,parse_leaderboard,parse_server_page,render_badge,resolve_ranking,validate,_todayis either killed by a new/strengthened test, or documented atthe use site as a provably equivalent mutant with a verified rationale
(the maxsplit-style equivalence class already established in
generate_repo_badges.pymay recur here).scripts/mutation_check.sh(or an equivalent direct-venv mutmut run)on this file + its test reports 0 unexplained survivors.
RepoBadge/Ranking's already-fixed dataclass extraction.