evilution 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f47321127e4fb0090ec208b430b7c14da3ca3b9b16e883f076b9707c787744a
4
- data.tar.gz: 78951f4619c9f8911e94272734b74606df0633131741201c7056c3a3dd1977dd
3
+ metadata.gz: cf5cad66d4d6bece9286a19581f84e7733f98672fc1cc4d7637549841b26c846
4
+ data.tar.gz: 870b94aaf76c4ef8185d7cd134e9b4eb460c2150f0106d8536026161eac6dee7
5
5
  SHA512:
6
- metadata.gz: 57ec220fad323e96e3bb3a4cb75b58dac381018d1b22334b4eb27b58c43db6219f732df58387eb41328332c90fb82d023829ac7df5632748223ada9aac048e26
7
- data.tar.gz: 5960714fac3df7b1beb118043e899961a4069dad090887e36727cda63d0b81eda52661ec9cb8745df7def51481e39aad9340673c9ec255fa59c1d32f506be3a9
6
+ metadata.gz: bfd5f6fc137910fd2c2f6db848c848c3b4418743377e351d6147c9d9588dc9b9d4896bc4112cba1f953e48b267dc5d3836d2935be8132f8d8d9c53e4ac3c9fe4
7
+ data.tar.gz: 8d31a8e8be3971ff23039605ea06ee69f32aca37f2b279dad6606059de4d29b513c52966212398a3af63c5b875f6e42aebb166de119a909a22ab61c87acce760
@@ -659,3 +659,4 @@
659
659
  {"id":"int-e24299f1","kind":"field_change","created_at":"2026-10-13T17:20:30.564416401Z","actor":"Denis Kiselev","issue_id":"EV-x38e","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}}
660
660
  {"id":"int-2efcd224","kind":"field_change","created_at":"2026-10-14T01:56:27.118884805Z","actor":"Denis Kiselev","issue_id":"EV-9zfe","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}}
661
661
  {"id":"int-5a397b18","kind":"field_change","created_at":"2026-10-14T06:28:38.598622816Z","actor":"Denis Kiselev","issue_id":"EV-23dn","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"README update merged in PR #1867 (GH #1864)"}}
662
+ {"id":"int-891f7a12","kind":"field_change","created_at":"2026-10-14T06:49:36.086216634Z","actor":"Denis Kiselev","issue_id":"EV-bbrc","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Shipped in 1.5.0 (PR #1851, GH #1846)"}}
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  Versioning policy: see [docs/versioning.md](docs/versioning.md).
4
4
 
5
+ ## [1.5.1] - 2026-10-22
6
+
7
+ ### Fixed
8
+
9
+ - **`--incremental` no longer lets a killed mutant answer for its siblings** — a cache entry was keyed by operator, line and column, but operators such as `nil_replacement` and `conditional_negation` emit several mutants at one location. The first one killed answered for the rest, so a survivor was reported `killed` even on an empty cache. Entries are now keyed by the mutated source as well; entries written by earlier versions are misses, never wrong verdicts, so the first run after the upgrade re-runs them (PR #1891, GH #1873; fix by [@gipcompany](https://github.com/gipcompany))
10
+
11
+ ### Changed
12
+
13
+ - **Dependency bumps** — `mcp` 1.7.0 -> 1.8.0 (PR #1893), `ruby/setup-ruby` 1.328.0 -> 1.329.0 (PR #1894)
14
+
5
15
  ## [1.5.0] - 2026-10-14
6
16
 
7
17
  The `default` profile grows from 136 to 155 operators, `strict` gains one more, and several existing operators emit more mutants than before: literals, collections, constants, indexes, variable reads and compound writes are all probed more closely. Constant assignments outside a method are subjects now, as class-body code was in 1.4.0. Mutation scores will move: every new mutant is one your suite has never been measured against. Pin the gem version and the operator profile if you need a stable score across runs.
@@ -12,7 +12,7 @@ class Evilution::Cache
12
12
  end
13
13
 
14
14
  def fetch(mutation)
15
- return nil if mutation.original_source.nil?
15
+ return nil if stripped?(mutation)
16
16
 
17
17
  file_key = file_key(mutation)
18
18
  entry_key = entry_key(mutation)
@@ -27,7 +27,7 @@ class Evilution::Cache
27
27
  end
28
28
 
29
29
  def store(mutation, result_data)
30
- return if mutation.original_source.nil?
30
+ return if stripped?(mutation)
31
31
 
32
32
  file_key = file_key(mutation)
33
33
  entry_key = entry_key(mutation)
@@ -49,13 +49,23 @@ class Evilution::Cache
49
49
 
50
50
  private
51
51
 
52
+ # Both keys digest a source, so a mutation missing either one cannot be keyed.
53
+ def stripped?(mutation)
54
+ mutation.original_source.nil? || mutation.mutated_source.nil?
55
+ end
56
+
52
57
  def file_key(mutation)
53
58
  content_hash = Digest::SHA256.hexdigest(mutation.original_source)
54
59
  "#{safe_filename(mutation.file_path)}_#{content_hash[0, 16]}"
55
60
  end
56
61
 
62
+ # Several operators emit more than one mutation at the same location (e.g.
63
+ # nil_replacement -> true / false / 0), so the location alone would let a
64
+ # killed sibling answer for a survivor. The original source is fixed per
65
+ # cache file, so a digest of the mutated source identifies the mutation.
57
66
  def entry_key(mutation)
58
- "#{mutation.operator_name}:#{mutation.line}:#{mutation.column}"
67
+ mutated_digest = Digest::SHA256.hexdigest(mutation.mutated_source)
68
+ "#{mutation.operator_name}:#{mutation.line}:#{mutation.column}:#{mutated_digest[0, 16]}"
59
69
  end
60
70
 
61
71
  def safe_filename(path)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Evilution
4
- VERSION = "1.5.0"
4
+ VERSION = "1.5.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evilution
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Kiselev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-14 00:00:00.000000000 Z
11
+ date: 2026-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs