Skip to content

mutation: scripts/refresh_mcp_toplist_badge.py has 116 pre-existing survivors outside the Ranking dataclass fix #281

Description

@cdeust

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

  • Every one of the 116 currently-surviving mutants across
    _provenance_comment, fetch, main, parse_leaderboard,
    parse_server_page, render_badge, resolve_ranking, validate,
    _today is either killed by a new/strengthened test, or documented at
    the use site as a provably equivalent mutant with a verified rationale
    (the maxsplit-style equivalence class already established in
    generate_repo_badges.py may recur here).
  • scripts/mutation_check.sh (or an equivalent direct-venv mutmut run)
    on this file + its test reports 0 unexplained survivors.
  • No change to RepoBadge/Ranking's already-fixed dataclass extraction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions