evilution 0.30.1 → 0.30.3
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 +4 -4
- data/.beads/interactions.jsonl +15 -0
- data/.rubocop_todo.yml +1 -0
- data/CHANGELOG.md +14 -0
- data/lib/evilution/integration/loading/mutation_applier.rb +15 -0
- data/lib/evilution/integration/minitest.rb +29 -7
- data/lib/evilution/mutator/operator/method_body_replacement.rb +19 -3
- data/lib/evilution/runner/isolation_resolver.rb +14 -0
- data/lib/evilution/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 43c577be5df2b96507216aaeb8825fe47a86b52d4a7e43684db715763538d9b5
|
|
4
|
+
data.tar.gz: 1a17f1e3e393cb527be15d518fc4f193f04a2932fe44dfa17cf2e406f6ac662a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dfc0f9ebbcdb8548b582cd74a803119a42b177316c524b31b4d383c64aada5fadd2d65111fc20817f52b38efa4fa57184ead3679cd085df116a8178a8ed00a6
|
|
7
|
+
data.tar.gz: aa58a74d4bd33407126dc3c15c0716c06e260ee17475430b5b6405af4cc3c98191607823490bf4f9b72abe87238d1ec7219cec6dbd17e2915011b04d8abfc14e
|
data/.beads/interactions.jsonl
CHANGED
|
@@ -370,3 +370,18 @@
|
|
|
370
370
|
{"id":"int-5c439789","kind":"field_change","created_at":"2026-05-15T04:10:04.253005681Z","actor":"Denis Kiselev","issue_id":"EV-m47s","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}}
|
|
371
371
|
{"id":"int-9c968bc0","kind":"field_change","created_at":"2026-05-15T04:10:02.826901138Z","actor":"Denis Kiselev","issue_id":"EV-74e3","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}}
|
|
372
372
|
{"id":"int-4677d561","kind":"field_change","created_at":"2026-05-15T05:18:42.843114482Z","actor":"Denis Kiselev","issue_id":"EV-ju3o","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}}
|
|
373
|
+
{"id":"int-f977cb7c","kind":"field_change","created_at":"2026-05-15T06:37:09.06468763Z","actor":"Denis Kiselev","issue_id":"EV-mn3p","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary PASS 0.30.1. client.rb 882 mutations 100% score, 3 equivalent. capsule.rb 6.85% — upstream test debt, not evilution bug. No evilution bugs surfaced. Artifact .artifacts/sidekiq_sidekiq.yml."}}
|
|
374
|
+
{"id":"int-1b07bd8c","kind":"field_change","created_at":"2026-05-15T06:50:28.638714936Z","actor":"Denis Kiselev","issue_id":"EV-7764","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary infra mismatch — pagy uses thor-driven multi-file test orchestration that single-spec evilution invocation can't replicate. No evilution bug surfaced. Documented in artifact."}}
|
|
375
|
+
{"id":"int-47573a1f","kind":"field_change","created_at":"2026-05-15T06:51:44.810876255Z","actor":"Denis Kiselev","issue_id":"EV-ff13","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary PASS 0.30.1+EV-5nxs. Baseline 509/0/0. object_utils.rb 57 mutations 100%, candidates.rb 100% (21 muts/s). No evilution bugs. Artifact .artifacts/norman_friendly_id.yml."}}
|
|
376
|
+
{"id":"int-296f712f","kind":"field_change","created_at":"2026-05-15T06:57:54.666163064Z","actor":"Denis Kiselev","issue_id":"EV-9cd2","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Canary smoke_fail 2026-05-15. Baseline 431/0/0. All targeted mutations 0% kill. Same pattern as pagy. Suspected ActiveSupport::TestCase + reset_state + class-reopen gap in evilution Minitest integration but no minimal repro yet. Not filed as separate bug — needs smaller reproducer. Artifact .artifacts/kaminari_kaminari.yml."}}
|
|
377
|
+
{"id":"int-90ffe424","kind":"field_change","created_at":"2026-05-15T06:58:55.664447898Z","actor":"Denis Kiselev","issue_id":"EV-225l","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary SKIPPED 2026-05-15. test_helper.rb spawns its own redis-server (no env override); host has no redis-server binary. Sidekiq EV-mn3p already covers concurrency tier signal (100% PASS on client.rb). Resque revisit only justified if a resque-specific bug surfaces later. Artifact .artifacts/resque_resque.yml."}}
|
|
378
|
+
{"id":"int-0648236b","kind":"field_change","created_at":"2026-05-15T07:00:59.017162278Z","actor":"Denis Kiselev","issue_id":"EV-ks6i","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary PASS 0.30.1+EV-5nxs. configuration.rb 40.69% upstream gap. body.rb 66.78% upstream gap. 0 errored mutations across both targets. No evilution bugs. Artifact .artifacts/mikel_mail.yml."}}
|
|
379
|
+
{"id":"int-8a14f28f","kind":"field_change","created_at":"2026-05-15T08:24:58.326924498Z","actor":"Denis Kiselev","issue_id":"EV-5nxs","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}}
|
|
380
|
+
{"id":"int-e084d525","kind":"field_change","created_at":"2026-05-15T09:44:03.368189125Z","actor":"Denis Kiselev","issue_id":"EV-9a6c","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Fixed PR #1251, shipped 0.30.2. method_body_replacement targets body.statements (not whole BeginNode) for method-level rescue/ensure; super-detection still scans full body. Copilot review addressed. Verified on redis-rb client.rb — 5 super-errors eliminated."}}
|
|
381
|
+
{"id":"int-be59f27d","kind":"field_change","created_at":"2026-05-15T09:44:04.508238014Z","actor":"Denis Kiselev","issue_id":"EV-5rtm","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Canary PASS 0.30.2. pipeline.rb 100% (240/240), client.rb 76.67% (138k/42s/0err — 5 prior EV-9a6c errors eliminated), errors.rb 0% upstream gap. 3 evilution bugs surfaced + all fixed: EV-ju3o #1240 + EV-7u9c #1241 (0.30.1), EV-9a6c #1247 (0.30.2). Remaining survivors = redis-rb test debt. Artifact .artifacts/redis_redis-rb.yml."}}
|
|
382
|
+
{"id":"int-3960db7a","kind":"field_change","created_at":"2026-05-15T10:18:04.635769183Z","actor":"Denis Kiselev","issue_id":"EV-xqv3","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary done 0.30.2. Baseline 1311/0/0. lexer.rb 1299 mutations 26.79% — real upstream coverage gap (abstract base class, subclass tests don't exercise base). 1 evilution bug surfaced EV-5nxs #1248 (autorun stub timing) — fixed PR #1249, shipped 0.30.2. Artifact .artifacts/rouge-ruby_rouge.yml."}}
|
|
383
|
+
{"id":"int-b24804d2","kind":"field_change","created_at":"2026-05-15T10:19:29.488481997Z","actor":"Denis Kiselev","issue_id":"EV-rxob","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"20-repo stability matrix complete. All 20 sub-canaries closed. Results: 10 pass, 2 smoke_fail (pagy/kaminari — 0% score, follow-up EV-laxo investigates suspected reset_state vs class-reopen), 1 skipped (resque — host redis-server infra). 4 evilution bugs surfaced + all fixed/shipped: EV-ju3o #1240 + EV-7u9c #1241 (0.30.1), EV-9a6c #1247 + EV-5nxs #1248 (0.30.2). Aggregate .artifacts/SUMMARY.md. Open follow-up: EV-laxo (pagy/kaminari 0% root cause)."}}
|
|
384
|
+
{"id":"int-8a9bcade","kind":"field_change","created_at":"2026-05-15T12:15:27.827753441Z","actor":"Denis Kiselev","issue_id":"EV-225l","extra":{"field":"status","new_value":"open","old_value":"closed"}}
|
|
385
|
+
{"id":"int-434f659f","kind":"field_change","created_at":"2026-05-15T12:15:28.901913417Z","actor":"Denis Kiselev","issue_id":"EV-225l","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Canary PASS 0.30.2 (re-run, earlier skip was wrong). Baseline 285/286 (1 error = port-9736-hardcoded test, infra collateral). stat.rb 95.92%, job.rb 100% (451 muts, 1 equivalent). No evilution bugs. Ran against shared docker redis on 6381 with 3-line test_helper.rb patch (which-guard, backtick self-spawn, port). Artifact .artifacts/resque_resque.yml."}}
|
|
386
|
+
{"id":"int-d1684261","kind":"field_change","created_at":"2026-05-15T13:01:27.370142624Z","actor":"Denis Kiselev","issue_id":"EV-laxo","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Investigation complete. Root causes found, both confirmed via instrumented iseq probing. pagy 0%: fork isolation clobbers eval'd mutation — spec require()s lazily-loaded target file not in $LOADED_FEATURES, reloads original from disk (EV-vxgl #1253 P1). kaminari 0%: kaminari runs on test-unit gem not Minitest (ActiveSupport::TestCase < Test::Unit::TestCase), test classes never Minitest::Runnable, 0 tests dispatch — plus evilution silently scores 0% instead of erroring (EV-5dxk #1254 P2). Original hypothesis (reset_state runnables clear) was wrong — disproven."}}
|
|
387
|
+
{"id":"int-011584d4","kind":"field_change","created_at":"2026-05-15T15:55:27.437673072Z","actor":"Denis Kiselev","issue_id":"EV-vxgl","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Fixed PR (merged). MutationApplier#mark_feature_loaded registers realpath in $LOADED_FEATURES post-eval — spec require() no longer reloads original. pagy jobs=4: 0% -> 82.81%. Residual gap vs jobs=1 is separate (EV-wu8w in_process inflation)."}}
|
data/.rubocop_todo.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Versioning policy: see [docs/versioning.md](docs/versioning.md).
|
|
4
4
|
|
|
5
|
+
## [0.30.3] - 2026-05-16
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Fork isolation no longer clobbers the eval'd mutation when the spec `require`s a lazily-loaded target file** — `MutationApplier` evals the mutated source straight into the VM, which does not register a `$LOADED_FEATURES` entry. When the project lazy-loads the target file (only the spec references it) and the spec then `require`s it, `require` found nothing loaded and re-read the **original** file from disk, clobbering the mutation before any test ran. Every mutation then silently survived. In-process runs masked it — the first mutation's spec-load populated `$LOADED_FEATURES` for the rest of the process — but under fork isolation each worker restarts from the same pre-`require` snapshot, so the whole file scored 0%. `MutationApplier` now registers the mutated file's canonical (`File.realpath`) path in `$LOADED_FEATURES` after applying the mutation, so a later `require`/`require_relative` is a no-op. Surfaced by the EV-7764 pagy stability canary: `gem/lib/pagy/classes/request.rb` went from 0% to 82.8% under `--jobs 4` (EV-vxgl, PR #1256, GH #1253)
|
|
10
|
+
- **Minitest integration reports `:error` instead of a misleading 0% when zero test methods run** — if the dispatched Minitest run executed no test methods (the resolved spec registered no `Minitest::Runnable` suite — commonly because the project's tests use a different framework such as the `test-unit` gem, or `--spec` points at the wrong file), `reporter.passed?` returned `true` for the empty run and every mutation was scored *survived*, producing a meaningless 0%. `run_minitest` now reports the dispatched test-method count; a zero-count run yields an error-shaped result so `classify_status` maps it to `:error` and the high-error-rate warning fires, instead of silently inflating the denominator. The Minitest analogue of the EV-720r RSpec fix. Surfaced by the EV-9cd2 kaminari stability canary (kaminari runs on `test-unit`, not Minitest) (EV-5dxk, PR #1257, GH #1254)
|
|
11
|
+
|
|
12
|
+
## [0.30.2] - 2026-05-15
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **`method_body_replacement` no longer corrupts methods with a method-level `rescue`/`ensure`** — for the shorthand form `def foo; stmts; rescue => e; ...; end` (no explicit `begin`), Prism makes `DefNode#body` a `BeginNode` whose `location` spans the *entire* `def...end` block — the `def` keyword and matching `end` included. The operator replaced that whole range with `nil` / `self` / `super`, obliterating the method framing and leaving the replacement dangling at the enclosing class/module scope; `super` replacements then raised `NoMethodError: super called outside of method` at load time, and the run miscounted every such mutation as an error. The operator now targets only the leading statements (`body.statements`) when the body is a `BeginNode`, preserving the `rescue`/`else`/`ensure` clauses and the `def` framing; methods with a rescue/ensure-only body (no leading statements) emit no mutation. Super *detection* still scans the full body, so a `super` call in any clause keeps the bare-super replacement candidate. Surfaced by the EV-5rtm redis-rb stability canary — 5 methods in `lib/redis/client.rb` (`ensure_connected`, `call_v`, `blocking_call_v`, `pipelined`, `multi`) all-errored before this fix (EV-9a6c, PR #1251, GH #1247)
|
|
17
|
+
- **`Minitest.autorun` stub now runs before the user `--preload` file** — the EV-7u9c fix (0.30.1) stubbed `Minitest.autorun` from `Integration::Minitest#ensure_framework_loaded` and `run_baseline_test_file`, both of which execute *after* `Runner#perform_preload`. When the user passed `--preload <file>` and that file required `minitest/autorun` (typical for `spec_helper.rb` / `test_helper.rb`), the `at_exit` handler was installed during preload — before the stub took effect — and the misleading "invalid option: --integration" banner returned at process exit. `Evilution::Runner::IsolationResolver#perform_preload` now invokes `Evilution::Integration::Minitest.stub_autorun!` immediately before requiring the preload file when `config.integration == :minitest`; it is a no-op for the RSpec integration. Surfaced by the EV-xqv3 rouge stability canary, whose `spec/spec_helper.rb` requires `minitest/autorun` (EV-5nxs, PR #1249, GH #1248)
|
|
18
|
+
|
|
5
19
|
## [0.30.1] - 2026-05-15
|
|
6
20
|
|
|
7
21
|
### Fixed
|
|
@@ -59,6 +59,21 @@ class Evilution::Integration::Loading::MutationApplier
|
|
|
59
59
|
@redefinition_recovery.call(mutation.original_source) do
|
|
60
60
|
@source_evaluator.call(eval_target, mutation.file_path)
|
|
61
61
|
end
|
|
62
|
+
mark_feature_loaded(mutation.file_path)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The mutated source is eval'd straight into the VM — `eval` does not register
|
|
66
|
+
# a `$LOADED_FEATURES` entry. If the spec then `require`s the same file (common
|
|
67
|
+
# when the project lazy-loads it and only the test references it), `require`
|
|
68
|
+
# reloads the ORIGINAL from disk and clobbers the mutation, so every mutation
|
|
69
|
+
# silently survives. Under fork isolation each worker starts from the same
|
|
70
|
+
# pre-`require` snapshot, so the whole file scores 0%. Registering the
|
|
71
|
+
# canonical path makes a later `require`/`require_relative` a no-op.
|
|
72
|
+
def mark_feature_loaded(file_path)
|
|
73
|
+
absolute = File.realpath(File.expand_path(file_path))
|
|
74
|
+
$LOADED_FEATURES << absolute unless $LOADED_FEATURES.include?(absolute)
|
|
75
|
+
rescue Errno::ENOENT
|
|
76
|
+
nil
|
|
62
77
|
end
|
|
63
78
|
|
|
64
79
|
def failure_result(error, message)
|
|
@@ -122,16 +122,37 @@ class Evilution::Integration::Minitest < Evilution::Integration::Base
|
|
|
122
122
|
return unresolved_result(mutation) if files.nil?
|
|
123
123
|
|
|
124
124
|
command = "ruby -Itest #{files.join(" ")}"
|
|
125
|
+
execute_minitest(mutation, files, command)
|
|
126
|
+
rescue StandardError => e
|
|
127
|
+
{ passed: false, error: e.message, test_command: command }
|
|
128
|
+
end
|
|
125
129
|
|
|
130
|
+
def execute_minitest(mutation, files, command)
|
|
126
131
|
files.each { |f| load(File.expand_path(f)) }
|
|
127
132
|
|
|
128
|
-
args = build_args(mutation)
|
|
129
133
|
detector = reset_crash_detector
|
|
130
|
-
|
|
134
|
+
run = run_minitest(build_args(mutation), detector)
|
|
131
135
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
return no_tests_ran_result(command) if run[:count].zero?
|
|
137
|
+
|
|
138
|
+
build_minitest_result(run[:passed], command, detector)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Zero dispatched test methods means the run carries no signal — the result
|
|
142
|
+
# is neither survived nor killed. Most common cause: the project's tests use
|
|
143
|
+
# a framework other than Minitest (e.g. the test-unit gem, whose
|
|
144
|
+
# Test::Unit::TestCase classes are not Minitest::Runnable), or --spec points
|
|
145
|
+
# at a file that registers no Minitest suite. Report :error so the score is
|
|
146
|
+
# not silently inflated to 0% with every mutation marked survived.
|
|
147
|
+
def no_tests_ran_result(command)
|
|
148
|
+
{
|
|
149
|
+
passed: false,
|
|
150
|
+
error: "no Minitest tests executed (0 test methods ran) — the resolved " \
|
|
151
|
+
"spec registered no Minitest suite. Check --integration/--spec; " \
|
|
152
|
+
"the project may use a non-Minitest framework (e.g. test-unit).",
|
|
153
|
+
error_class: "Evilution::Error",
|
|
154
|
+
test_command: command
|
|
155
|
+
}
|
|
135
156
|
end
|
|
136
157
|
|
|
137
158
|
def unresolved_result(mutation)
|
|
@@ -157,7 +178,8 @@ class Evilution::Integration::Minitest < Evilution::Integration::Base
|
|
|
157
178
|
options[:io] = out
|
|
158
179
|
|
|
159
180
|
reporter = ::Minitest::CompositeReporter.new
|
|
160
|
-
|
|
181
|
+
summary = ::Minitest::SummaryReporter.new(out, options)
|
|
182
|
+
reporter << summary
|
|
161
183
|
reporter << detector
|
|
162
184
|
|
|
163
185
|
self.class.initialize_minitest_state(reporter, options)
|
|
@@ -165,7 +187,7 @@ class Evilution::Integration::Minitest < Evilution::Integration::Base
|
|
|
165
187
|
dispatch_minitest_suites(reporter, options)
|
|
166
188
|
reporter.report
|
|
167
189
|
|
|
168
|
-
reporter.passed
|
|
190
|
+
{ passed: reporter.passed?, count: summary.count }
|
|
169
191
|
end
|
|
170
192
|
|
|
171
193
|
def dispatch_minitest_suites(reporter, options)
|
|
@@ -7,14 +7,18 @@ class Evilution::Mutator::Operator::MethodBodyReplacement < Evilution::Mutator::
|
|
|
7
7
|
SUPER_REPLACEMENT = "super"
|
|
8
8
|
|
|
9
9
|
def visit_def_node(node)
|
|
10
|
-
|
|
10
|
+
target = mutation_target(node.body)
|
|
11
|
+
if target
|
|
11
12
|
replacements = ALWAYS_SAFE_REPLACEMENTS.dup
|
|
13
|
+
# Super detection scans the whole body (rescue/else/ensure clauses
|
|
14
|
+
# included) — a super call in any clause means a parent target exists,
|
|
15
|
+
# so a bare-super replacement of the statements is meaningful.
|
|
12
16
|
replacements << SUPER_REPLACEMENT if body_calls_super?(node.body)
|
|
13
17
|
|
|
14
18
|
replacements.each do |replacement|
|
|
15
19
|
add_mutation(
|
|
16
|
-
offset:
|
|
17
|
-
length:
|
|
20
|
+
offset: target.location.start_offset,
|
|
21
|
+
length: target.location.length,
|
|
18
22
|
replacement: replacement,
|
|
19
23
|
node: node
|
|
20
24
|
)
|
|
@@ -26,6 +30,18 @@ class Evilution::Mutator::Operator::MethodBodyReplacement < Evilution::Mutator::
|
|
|
26
30
|
|
|
27
31
|
private
|
|
28
32
|
|
|
33
|
+
# A method-level rescue/ensure (`def foo; stmts; rescue; ...; end`) makes
|
|
34
|
+
# node.body a BeginNode whose location spans the entire `def...end` — the
|
|
35
|
+
# `def` keyword and matching `end` included. Replacing that range obliterates
|
|
36
|
+
# the method framing, leaving the replacement (`nil`/`self`/`super`) dangling
|
|
37
|
+
# at the enclosing scope. The replaceable region is only the leading
|
|
38
|
+
# statements; returns nil when there are none (rescue/ensure-only body).
|
|
39
|
+
def mutation_target(body)
|
|
40
|
+
return body unless body.is_a?(Prism::BeginNode)
|
|
41
|
+
|
|
42
|
+
body.statements
|
|
43
|
+
end
|
|
44
|
+
|
|
29
45
|
# The bare-super replacement raises NoMethodError at runtime when the enclosing
|
|
30
46
|
# class has no parent implementation of the method. We emit it only when the
|
|
31
47
|
# original body already calls super, using that as a heuristic that a super
|
|
@@ -37,6 +37,7 @@ class Evilution::Runner::IsolationResolver
|
|
|
37
37
|
return unless path
|
|
38
38
|
|
|
39
39
|
prepare_load_path_for_preload
|
|
40
|
+
prepare_integration_for_preload
|
|
40
41
|
require File.expand_path(path)
|
|
41
42
|
rescue Evilution::ConfigError
|
|
42
43
|
raise
|
|
@@ -186,6 +187,19 @@ class Evilution::Runner::IsolationResolver
|
|
|
186
187
|
raise Evilution::ConfigError.new("preload file not found: #{path.inspect}", file: path)
|
|
187
188
|
end
|
|
188
189
|
|
|
190
|
+
# User preload files (spec_helper.rb, test_helper.rb) typically require
|
|
191
|
+
# 'minitest/autorun', which installs an at_exit handler that re-parses ARGV
|
|
192
|
+
# at process exit. The stub from Integration::Minitest#ensure_framework_loaded
|
|
193
|
+
# only fires during baseline — too late to prevent the handler from being
|
|
194
|
+
# registered. Stub before user code runs.
|
|
195
|
+
def prepare_integration_for_preload
|
|
196
|
+
return unless config.integration.to_s == "minitest"
|
|
197
|
+
|
|
198
|
+
require "minitest"
|
|
199
|
+
require_relative "../integration/minitest"
|
|
200
|
+
Evilution::Integration::Minitest.stub_autorun!
|
|
201
|
+
end
|
|
202
|
+
|
|
189
203
|
def warn_missing_explicit_preload(path)
|
|
190
204
|
return if config.quiet
|
|
191
205
|
|
data/lib/evilution/version.rb
CHANGED
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: 0.30.
|
|
4
|
+
version: 0.30.3
|
|
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-05-
|
|
11
|
+
date: 2026-05-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|