From 3de445395618508d5f22b0e86742d15db82b798f Mon Sep 17 00:00:00 2001 From: glenn schrooyen Date: Wed, 9 Sep 2026 00:58:03 +0200 Subject: [PATCH] INSTR-01: match the finding KIND, because M12 was not holding this file to its own rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review APPROVED f6f3f22 plainly. Three LOW notes, all applied - the first is a real gap and the other two are one line each. ⚠️ M12's ASSERTION WAS KIND-BLIND. It matched on the key and ignored the finding kind, so renaming `diff()`'s `"VANISHED STORE KEY"` to `"GONE STORE KEY"` left M12 GREEN - review measured it. A vanished latch quietly downgraded to a softer heading is exactly what part 3 of this same file requires every mutation to be graded against ("the SPECIFIC finding it should produce"), so the file was not holding itself to its own doctrine. Inherited from SAFETY-44's original M12, not introduced here, and fixed now: ("VANISHED STORE KEY", "unit/shed/sign_tripped") in _m12_new Driven: the kind rename is exit 1 and M12 is among the reds where it was green before, and C5's removal still turns M12 red, so the strengthening did not cost the discrimination it exists for. C4 IS NAMED IN THE CLAUSE MAP. It has no 5e row deliberately - part 3's M9 reaches `vanished_unit is not None` end-to-end and a synthetic row would duplicate that rather than add separability - but C5 lives in the same `if`, and listing one guard while omitting the other reads as an oversight rather than a boundary. Review's own recommendation was not to add the row. AND THE PRINTED SET SAYS WHAT IT LOSES. The finding regex captures the first TOKEN of each text, so two findings of one kind collapse into one tuple; the line now says "first token only" so nobody reads it as an inventory. Harmless for M12 - the difference is one-directional and the pair it asserts on is exact - but the display was lossier than it looked. Unused `_m12_out` dropped. 28/28 files pass. `rehearse_roster.py` is untouched by this round; review confirmed its AST is identical between 91b0d5e and f6f3f22, so every measurement made against the shipped rule still stands. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU --- goodwe_controller/test_rehearse.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/goodwe_controller/test_rehearse.py b/goodwe_controller/test_rehearse.py index bf98399..fa924e1 100644 --- a/goodwe_controller/test_rehearse.py +++ b/goodwe_controller/test_rehearse.py @@ -471,21 +471,31 @@ def m12_findings(tree): _m12 = mutant_tree([("app/inverter.py", _M12_OLD, _M12_NEW)]) _m12_clean_code, _m12_clean, _ = m12_findings(HERE) -_m12_code, _m12_mut, _m12_out = m12_findings(Path(_m12)) +_m12_code, _m12_mut, _ = m12_findings(Path(_m12)) _m12_new = _m12_mut - _m12_clean print(f" staged leg, legacy+shed: shipped exit {_m12_clean_code}, " f"one roster unit's latch popped -> exit {_m12_code}") -print(f" findings the mutation ADDS: {sorted(_m12_new)}") +# ⚠️ THE PRINTED SET IS LOSSIER THAN IT LOOKS: the regex captures the first +# TOKEN of each finding's text, so two findings of one kind collapse into one +# tuple. Harmless here - the difference is one-directional and the pair M12 +# asserts on is exact - but do not read this line as an inventory. +print(f" findings the mutation ADDS (first token only): {sorted(_m12_new)}") check("⚠️ PRECONDITION: the baseline is STABLE and does not already carry the " "finding this mutation exists to produce. It is NOT clean - a legacy " "fixture never is - and the SET DIFFERENCE is what makes that fine, " "which is the sentence the deletion should have read before acting on it", not any(k == "unit/shed/sign_tripped" for _, k in _m12_clean)) -check("⭐ M12 RESTORED: a ROSTER unit's latch key that vanishes is a finding " - "even though a sibling holds True - and this is the STAGED leg, where " - "`snapshot_over()` supplies a transition-made destination, so the " - "provenance clause does not foreclose the narrowing", - any(k == "unit/shed/sign_tripped" for _, k in _m12_new)) +# ⚠️ AND IT MATCHES THE **KIND** AS WELL AS THE KEY, which SAFETY-44's original +# did not. Review measured it: renaming the finding kind in `diff()` from +# "VANISHED STORE KEY" to "GONE STORE KEY" left M12 GREEN. A vanished latch +# quietly downgraded to a softer heading is exactly the shape part 3 requires +# every mutation to be graded against - "the SPECIFIC finding it should produce" +# - and this file was not holding itself to its own rule. +check("⭐ M12 RESTORED: a ROSTER unit's latch key that vanishes is a " + "VANISHED STORE KEY finding even though a sibling holds True - and this " + "is the STAGED leg, where `snapshot_over()` supplies a transition-made " + "destination, so the provenance clause does not foreclose the narrowing", + ("VANISHED STORE KEY", "unit/shed/sign_tripped") in _m12_new) shutil.rmtree(Path(_m12).parent, ignore_errors=True) @@ -742,6 +752,11 @@ check("...and no leg's text has swallowed the CLOSING SUMMARY, which repeats " # and the whole 28-file suite stayed green # MACHINE-READ (C1) R6 # OFF-ROSTER (C5) R2, and M12 end-to-end on the staged leg +# PREFIX GATE (C4) NO 5e ROW, deliberately - `vanished_unit is not None` +# is reached end-to-end by part 3's M9, and a synthetic +# row would duplicate that rather than add separability. +# Listed because C5 lives in the same `if` and omitting +# one guard while naming the other reads as an oversight. # # ⚠️ ONE HOLE IS STILL OPEN AND IS **UNMEASURED**, stated so nobody reads # `sorted()` as guarded: ATTRIBUTION. Which vanished key gets a destination is