Triage the 10 full-run kimera survivors: delete dead code, ignore one equivalent - #7
Merged
Merged
Conversation
Five analyzers memoized with a guard (`return @_x if @_x`, or a `@_done = true` flag) because their builders filled instance variables as a side effect. kimera mutated each guard away, and all 7 mutants survived, including in isolation: recomputing from the same trees yields an equal result, so only the repeated work differed. The builders now return what they build (Branches#chart, Refs#holder, Ownership#chart, Roster#registered and #counted), and each view is an `@_x ||=` memo like the other 93 in lib. kimera treats `||=` as memoization and judges what it computes instead. `hashira --json --top 100000` output is byte-identical before and after on kimera, hashira, rubocop-kata and a 2,600-file Rails app. kimera on the five files: 115 mutants, 115 killed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
Deleting `walked` from CognitiveScore#nesting survived, including in isolation: nesting is read only by IfChain and RescueScan mid-walk, when the walk has already begun, so the call never did anything. With it gone, the `return if @_walked` guard showed the same memo survivors as the analyzers in the previous commit. Its mutants had been killed only because re-entering the walk from nesting recursed until the stack overflowed. The walk now returns its increments and calls, memoized with ||=. Nothing reads them mid-walk, so nothing re-enters. kimera on the file: 20 mutants, 20 killed. `hashira --json` output is unchanged on the four codebases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
`fragment.mass >= PREFILTER` -> `>` survived, including in isolation: nothing observable separates a 12-token fragment from a 13-token one. A fragment under BASE_MASS (16) never fits a uniform cluster, and a thin one needs a canonical of about 42+ tokens, which a near-miss (at most 1.5x apart) reaches from a 12-token fragment only through a chain of several near-misses. Clusters now prefilters at BASE_MASS, and the existing "exact clone whose mass sits exactly on the floor" spec pins the boundary. Clusters are identical with the prefilter at 12 or 16 on kimera, hashira, rubocop-kata and a 2,600-file Rails app (221 clusters), and the duplication pass takes 6.9s instead of 8.9s on the latter. kimera on the file: 27 mutants, 27 killed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
`[...] unless words.empty?` -> `unless false` survives in isolation and is equivalent: RollCall keeps only word sets that at least 3 files share, so a file with no words never joins a roll. The filter is a real optimization, not dead code. Without it the coupling pass takes 2.7-3.3s instead of 2.1s on a 2,600-file app, with identical output. Any form of the filter keeps a "keep every file" mutant, so it gets an ignore entry naming the mechanism, and max_ignored rises to 1 with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
hashira's own ratchet flagged the new Roster#counted as feature_envy (two references to `definition`, one to self). Filtering and de-duplicating are now one step each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
These changed production code only so kimera would stop reporting survivors, and none of them fixed a bug: - The ||= rewrites of seven guard-style memos (and CognitiveScore's walk) are behavior-identical; kimera just doesn't mutate `@x ||=`. Their mutants are equivalent (recomputing yields an equal result), and the gap is kimera not recognizing guard-style memoization, to be fixed there instead. - Prefiltering at BASE_MASS instead of 12 is a design decision about duplication, not a test gap, so it's left for its own change. This reverts 3ea6da1, 21bf246, 4abf47f and 4c0ec7d. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
…esting Deleting it survived, including in isolation: nesting is read only by IfChain and RescueScan mid-walk, after the walk has begun, so the call never did anything. It was also the only reason the `return if @_walked` guard's mutants were killed: without the guard, nesting re-entered the walk and recursed until the stack overflowed. Those two mutants now survive like the other guard-style memos, which is kimera's gap to close, not hashira's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h
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.
A full
kimera runonmainfailsmax_survivors: 0with 10 survivors. They're the same 10 under kimera 0.1.1 and 0.1.2, and all 10 also survive--isolated. None of them is a bug: in each case no test can observe the mutation. This PR takes only the verdicts that belong in hashira.Net diff against
main: one dead call deleted and one ignore entry. An earlier version of this PR rewrote production code so kimera would stop generating some of these mutants. The branch keeps those commits, and a revert commit backs them out (history rewrites are blocked in this session).Changes
CognitiveScore#nestingcalledwalked, but its only callers (IfChain,RescueScan) read it mid-walk, after the walk has begun, so the call never did anything. It's deleted.Echo,[...] unless words.empty?→unless false.RollCallkeeps only word sets that at least 3 files share, so a file with no words never joins a roll. The filter is a real optimization: without it, the coupling pass takes 2.7–3.3s instead of 2.1s on a 2,600-file Rails app, with identical output. Every form of the filter keeps a "keep every file" mutant. So it gets an ignore entry with the mechanism as itsreason:, andmax_ignoredgoes from 0 to 1 in the same diff, followingkimera skill's rules.Left for other changes
boundaries.rb,smells/branches.rb,smells/refs.rb,coupling/roster.rbandsmells/ownership.rb, and 2 onCognitiveScore'sreturn if @_walked. That guard had been killed only becausenestingre-entered the walk; with the dead call gone, it survives like the rest.return @_x if @_x, orreturn if @_done; @_done = true, with the guard's condition forced false or the flag set to false. Removing a memo only recomputes an equal result.@x ||=memos but does mutate this equivalent form. That's being fixed in kimera. Once hashira picks up that release, these nine drop out with no hashira change.Clustersprefilter boundary:fragment.mass >= PREFILTER→>(12). A fragment under 16 tokens can reach a report only through a chain of several near-misses. That's a design question about the prefilter, not a test gap, so it stays visible until decided separately.Verification
bin/cipasses both withLANG=C.UTF-8and withLANGunset: rubocop, rubocop-kata doctor, 502 examples, the gate, andRatchet OK: 16 edges, 0 findings, unchanged.kimera ci --since origin/mainexits 0.echo.rbwith the entry: 0 survivors, 1 ignored.🤖 Generated with Claude Code
https://claude.ai/code/session_01PcDfzLuRgjoSnfPLrTaA4h