Carry which kind of dormancy, not a sentence about it - #374
Merged
Conversation
dormant_rules computed one of three distinct diagnoses and then rendered it away into prose, so the only way to ask which one it was was to match a substring. Four tests did exactly that. That fails open. Reword a diagnosis for clarity, keep the matched substring by luck, and the test still passes while checking something weaker than it was written to check -- the failure mode is invisible because a passing test looks the same either way. _Dormant now carries `kind` (a Literal, so mypy rejects a typo) and `detail` (the shadower's issue, when there is one). main() renders the sentence from _DORMANT_WHY. The computation no longer knows any wording, so rephrasing a diagnosis is a change to output alone. No behavior change. The two _run_main tests still assert on the rendered EXPLAINED NOTHING lines and still pass, which is what pins the output format across this refactor. Both mutation proofs still fail as they should: swapping the reverted/excluded kinds fails 4 tests, removing the internal _sorted_rules call fails 1. Gates unmoved at 108/0, 90/0 and 1/0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #374 +/- ##
=======================================
Coverage 98.51% 98.51%
=======================================
Files 44 44
Lines 2895 2895
=======================================
Hits 2852 2852
Misses 43 43 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #373, from its review.
dormant_rulescomputed one of three distinct diagnoses — reverted / shadowed / excluded — then rendered it away into prose, so the only way to ask which one it was was to match a substring. Four tests did exactly that:That fails open. Reword a diagnosis for clarity, keep the matched substring by luck, and the test still passes while checking something weaker than it was written to check. A passing test looks identical either way.
The change
_Dormantnow carries the distinction the function already computed:main()renders the sentence from a_DORMANT_WHYtable. The computation no longer knows any wording, so rephrasing a diagnosis is a change to output alone.kindis aLiteral, so mypy rejects a typo'd kind rather than letting it reach a test.No behavior change, and here is what pins that
The two
_run_maintests assert on the renderedEXPLAINED NOTHINGlines and are untouched by this PR. They still pass, which is precisely what proves the output format survived a refactor that moved where the prose is built.Both of #373's mutation proofs still fail as they should — and the first one got stronger:
dormant_rules' internal_sorted_rulescallThe swap catching more is the payoff. Under substring matching it was caught only where the two kinds happened to produce visibly different sentences; under
kind ==every test naming a kind catches it, because the assertion is about identity rather than about text that happens to differ.Measured
Gates unmoved:
108/0at 1.4.0,90/0at 2.0.0,1/0at 2.1.0, all exit 0. Suite 3217, ruff and mypy clean.🤖 Generated with Claude Code