Conversation
added 3 commits
July 28, 2026 01:14
.necro/summary.json and NECRO_MODERNIZATION_REPORT.md are NecroRuby's internal notes, not part of the gem. They were committed by mistake -- the modernization agent writes them into the checkout root and `git add -A` staged them. They have no business in this diff. Sorry for the noise.
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.
NecroRuby has revived
ice_nineModernized and tested on Ruby 4.0.6, the latest Ruby release.
At a glance
Full modernization report
ice_nine modernization report
Target: Ruby 4.0.6 (floor: Ruby >= 3.3). All changes below were verified against
Ruby 4.0.6, which is first on
PATHin this environment.Original pass: 2026-07-28. Last refreshed: 2026-09-10 (see "Refreshed" section at
the end for what changed in this pass).
TL;DR
bundle installwas completely broken on any current Ruby/Bundler beforethese changes: the
Gemfilepinned abundlerversion incompatible withBundler 4.x and pulled
mutant/mutant-rspec/mutant-licensefrom aprivate, credentialed git/gem source that no longer resolves.
bundle installresolves cleanly, the full spec suitepasses (233 examples, 0 failures) with 100% line and 100% branch
coverage, RuboCop reports zero offenses, and
bundler-auditreports noknown vulnerabilities.
1. Dependency changes
Removed (dead/abandoned)
mutant/mutant-rspec/mutant-license(Gemfile) — pulled viagithub: 'mbj/mutant'plus a private, credentialed gem source(
https://oss:<redacted-license-key>@gem.mutant.dev/). This hardcoded alive license credential directly in version control (see Security below)
and, independently, no longer resolves against modern Bundler
(
bundler >= 2.2.33, < 3in the gemspec conflicts with Bundler 4.x, and thegit source itself fails to check out in a clean clone). Mutation testing is
a nice-to-have for this codebase, not a hard requirement, so it was dropped
rather than pinned to a broken private toolchain.
bundlerpin inice_nine.gemspec(~> 2.2, >= 2.2.33) — Bundlermanages its own version resolution; pinning it as a
development_dependencyis both unnecessary and actively broke installation under Bundler 4.16.
rbench(used only bybenchmarks/speed.rb, previously pulled in viathe now-deleted
Gemfile.devtools) — last released in 2011 and unmaintained.Replaced with Ruby's own maintained
benchmarkstdlib; the benchmark scriptnow has zero external gem dependencies.
Gemfile.devtools,Guardfile,.pelusa.yml,config/{devtools,flay,flog,mutant,reek,roodi,rubocop,yardstick}.yml.None of this was actually wired up —
Gemfile.devtoolswas nevereval'd/required by the checked-inGemfile, and theRakefilecalledRake.application.load_importswith no priorimportcalls, so it definedzero rake tasks in the original repo (
rake -Tprinted nothing). Thesefiles referenced gems (
guard-*,flay,flog,reek,roodi,yardstick, oldrubocop ~> 0.27) that are either unmaintained, userubocop cop names that no longer exist, or were simply unreachable dead
weight. Removed rather than resurrected.
spec/support/config_alias.rb— defined a legacy top-levelConfig = RbConfigalias for pre-1.9-era Ruby/Rubinius compatibility. It was neverrequired by
spec_helper.rbor anywhere else, so it never actually loaded;confirmed dead and removed.
Upgraded / added (current, maintained)
rspec~> 3.8~> 3.13rake~> 13.2(moved toGemfile, perGemspec/DevelopmentDependencies)rubocopGemfile(dead~> 0.27.1in deletedGemfile.devtools)~> 1.75rubocop-performance~> 1.24(new)rubocop-rspec~> 3.6(new)simplecov~> 0.9.1in deletedGemfile.devtools~> 0.22yard~> 0.8.7.6in deletedGemfile.devtools~> 0.9bundler-audit~> 0.9(new — security scanning)bigdecimal~> 3.1, explicit (see Compatibility below)ice_nine.gemspecitself now declares zero development dependencies —all dev/test tooling lives in
Gemfile, andgem.filesis scoped tolib/,LICENSE,README.md,TODOinstead of shipping the entire repo(specs, CI config, dotfiles) inside the built gem.
2. Security
Gemfileembedded a live-looking Basic Auth credential in a gem source URL
(
https://oss:<redacted>@gem.mutant.dev/). This is a real secret-leakpattern (anyone with read access to the repo/history had the credential).
Removing the
mutanttoolchain removes this entirely; the exposedcredential's history remains in prior commits (out of scope for this PR —
the org/author should treat that credential as compromised regardless).
bundler-audit check --updateagainst the currentruby-advisory-db:no vulnerabilities found in the resulting dependency set.
eval/system/Marshal/YAML.loador other injection-prone patternsin
lib/.gem.metadata['rubygems_mfa_required'] = 'true'andsource_code_uri/bug_tracker_uri/changelog_urimetadata to thegemspec — RubyGems.org best practice for supply-chain hardening on a
popular gem.
bundler-auditon every push/PR as a dedicated job.3. Ruby 4.0.6 compatibility fixes
bigdecimalis no longer a default gem as of Ruby 3.4+. The numericfreezer spec (
spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb)does
require 'bigdecimal'and failed to load at all under 4.0.6. Added anexplicit
bigdecimaldependency toGemfile.default; running the original suite under Ruby 4.0.6 already emitted
warning: literal string will be frozen in the future. Rather than ignorethis, the whole codebase (
lib/andspec/) now carries an explicit# frozen_string_literal: truemagic comment (replacing the now-redundant# encoding: utf-8comments, which have done nothing since Ruby 2.0defaulted to UTF-8 source encoding).
a handful of specs relied on bare string literals (
'','1',%w[a b], two separately-written-but-textually-identical'...'literals used to prove distinct object identity) being distinct, mutable
objects at runtime — an assumption frozen/deduplicated string literals
silently break. Fixed by using
String.new(...)(or+'...', applied byRuboCop's
Performance/UnfreezeString) wherever a test specificallyneeds a fresh, unfrozen, non-interned string object. No library code
(
lib/) needed changes for this —IceNine's own freezing logic wasalways frozen-string-safe.
.freezeonIceNine::VERSION(the literal isalready frozen by the magic comment).
(
File.expand_path(..., __FILE__)→__dir__, noFixnum/Bignum, no$SAFE, noRandom::DEFAULT, etc.)..ruby-versionadded, pinned to4.0.6.ice_nine.gemspec:required_ruby_versionraised from>= 2.7.3(2.7 hasbeen EOL for years) to
>= 3.3, the oldest currently-maintained Ruby lineat the time of this change.
.github/workflows/ci.yml: matrix updated from['2.7', '3.0', '3.1', '3.2'](all EOL) to['3.3', '3.4', '4.0']; split into separatetest,rubocop, andauditjobs; the old CI also invokedbundle exec mutant run, which depended on the now-removed private credentialed source andwould never have run successfully in a fork/clean clone.
4. Test coverage
bundle installfailed outright on anycurrent Bundler (see above), so the suite could not run at all in this
environment prior to the dependency fixes.
SimpleCov(now with branch coverageenabled, not just line coverage) reports 100% line coverage (126/126)
and 100% branch coverage (10/10), enforced via
minimum_coverage line: 100, branch: 100inspec/spec_helper.rb(runwith
COVERAGE=true).developed against
mutantmutation testing), so no coverage gaps needednew specs — the only spec changes were the frozen-string-literal fixes
above and Rubocop-driven style/naming cleanups (renamed
object_arg1/2to
first_object_arg/second_object_arg,stub_const-adjacent copsscoped-excluded where the test intentionally manipulates real global
constants — see
.rubocop.ymlfor rationale comments).5. Documentation
2 constants) both before and after — the original author was already
thorough. Added one missing doc comment
(
IceNine::Freezer::Object::BasicObject, previously an undocumentedconstant alias) and verified every other public class/method's docs are
still accurate after the code changes.
README.md: added a "Requirements" section (Ruby >= 3.3, tested on 3.3/3.4/4.0)and a "Development" section with concrete setup/test/lint commands. Removed
three dead badges/links (Code Climate, Inch CI, and unused Travis/Gemnasium
reference definitions) — Inch CI and Gemnasium have both been shut down for
years, Travis's free OSS tier no longer applies, and none of these were
backed by any in-repo config to verify their claims.
CONTRIBUTING.md: updated the stalerake ciinstruction (that task neverexisted even in the original Rakefile) to
bundle exec rake, which nowactually runs the spec suite + RuboCop.
6. Lint
.rubocop.yml/config/rubocop.ymlcopconfiguration (referencing cop names that don't exist in modern RuboCop)
with a current config using the
rubocop-performanceandrubocop-rspecplugins.
bundle exec rubocop(49 files): zero offenses.comments in
.rubocop.yml, rather than disabled blindly:RSpec/NamedSubject— the suite consistently and intentionally namessubjectand references it explicitly.RSpec/VerifiedDoubles— the doubles involved are opaqueidentity-compared placeholders with no interface to verify against.
RSpec/RemoveConst,RSpec/LeakyConstantDeclaration,RSpec/BeforeAfterAll,Lint/ConstantDefinitionInBlock,Lint/EmptyClass— scoped to exactly one file(
spec/unit/ice_nine/freezer/class_methods/element_reader_spec.rb),which intentionally defines/removes real global constants to exercise
IceNine::Freezer's name-based constant lookup across namespaces; thatis the behavior under test, not accidental leaky state.
7. Notable design decisions
unchanged — this is a dependency/tooling/compatibility modernization pass,
not a rewrite. Every
lib/change is either a magic-comment update or aone-line
supercall / doc comment addition.mutant(dead private license server),guard(unmaintained file-watcher stack),
flay/flog/reek/roodi(unmaintained code-metrics gems using ancient rubocop-era config formats),
or
yardstick. RuboCop + SimpleCov + bundler-audit cover the same ground(style, coverage, security) with actively maintained tooling.
Rakefilerewritten from a no-op (Rake.application.load_importswith noimports registered) into a real, minimal task file:
rspec,rubocop,and a
defaulttask that runs both.Refreshed (2026-09-10)
The PR had been open for a while, so this pass re-verified everything against
the current Ruby/gem ecosystem rather than re-scoping any of the above. No
design decisions from the original pass changed.
bundle install/bundle outdatedagainst the live rubygems.org index. Every existing
Gemfileconstraint(
rspec ~> 3.13,rake ~> 13.2,rubocop ~> 1.75,rubocop-performance ~> 1.24,rubocop-rspec ~> 3.6,simplecov ~> 0.22,yard ~> 0.9,bundler-audit ~> 0.9,bigdecimal ~> 3.1) still resolves cleanly to acurrent, maintained patch/minor release inside its existing range (e.g.
rubocopresolved to1.91.0,bigdecimalto3.3.1).bigdecimalandsimplecovdo have newer major lines available (4.xand1.xrespectively), but since the pinned ranges still resolve to actively
maintained releases and a reviewer has already read the current pins, they
were left as-is rather than bumped across a major version on a PR under
review — see
.necro/summary.jsonfor the explicit blocked note on this.No gemspec/Gemfile/lockfile edits were needed. (The gem intentionally does
not commit
Gemfile.lock— unchanged.).ruby-version(4.0.6),required_ruby_version(
>= 3.3), and the CI matrix (3.3/3.4/4.0) were already current as ofthis refresh; nothing to change there.
spec/spec_helper.rbcalledSimpleCov::Formatter::MultiFormatter[...], which the installedsimplecov(0.22.0) now warns is deprecated in favor of.new(...)(
[DEPRECATION] ::[] is deprecated. Use ::new instead.printed on everycoverage run). Switched to
SimpleCov::Formatter::MultiFormatter.new([...]);behavior is identical, warning is gone.
rubocop(1.91.0, still within the~> 1.75pin) ships a new cop,Style/DirectiveScope, which flagged therubocop:disable/rubocop:enablepair inspec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb(adisable/enable pair around a single statement should be a single
rubocop:disable-nextcomment instead). Applied RuboCop's ownautocorrect for this one offense.
bundler-audit check --updateagainst thecurrent
ruby-advisory-db(updated 2026-09-08) — no vulnerabilities found.(126/126) and 100% branch (10/10) coverage,
bundle exec rubocopzerooffenses (49 files), all under Ruby 4.0.6.
About this PR — what NecroRuby is, CI, and smaller pieces
NecroRuby is a bot that brings quality open-source Ruby libraries
up-to-date with the modern Ruby ecosystem — upgrading dependencies,
restoring test coverage, tightening security, and improving documentation
for gems whose last release is over a year old.
NecroRuby is a fully autonomous process and is capable of mistakes. If you
disagree with any of these changes, just say so on this PR (or close it) and
NecroRuby will move on — it won't argue, and it won't keep nudging you. If
you have questions, ask here and it will answer.
Checks may not have run yet. GitHub holds workflow runs from first-time
contributors until a maintainer approves one. Approving a run here would
let NecroRuby see its work against your CI rather than only its own — and
fix it if it fails.
This arrives as one pull request because a single PR is easier to track and
keeps one review thread and one CI signal. It is already one commit per
concern, so it can be reviewed a commit at a time. If you'd rather have
genuinely separate pull requests, comment "please split this up" and
NecroRuby will:
itself is left completely alone — same branch, same diff, same threads.
docs, lint — each targeting that feature branch, so you can review and
approve them independently. Every file appears in exactly one part.
proposes has been reviewed in a small, single-concern PR.
Nothing merges into
mainwithout you merging it.🤖 Opened automatically by NecroRuby, an UpWoof.ai service.