Module: Rigor::BleedingEdge
- Defined in:
- lib/rigor/bleeding_edge.rb
Overview
ADR-50 § WD2 — the bleeding-edge overlay.
A Rigor-maintained set of the next major's queued changes — severity-map promotions and
new-discipline rule enablements — that a user can adopt early, before they become
default-on at a major (ADR-50 § WD7). It is orthogonal to severity_profile: (how loud
today's rules are) and is versioned with the gem, NOT a user-supplied file: the
inspectable counterpart to PHPStan's bleedingEdge include.
The WD2 foundation slice wired the surface end-to-end (bleeding_edge: config, the
rigor show-bleedingedge command, the severity-composition hook in
Configuration::SeverityProfile.resolve), so a discipline lands as a single FEATURES
entry with no engine plumbing — as the first one, reject-unparseable-signatures, does.
Each feature carries a stable feature id — part of the ADR-50 WD1 contract
vocabulary: the config, the show command, and the eventual CHANGELOG migration note all
name the same id, and a feature graduates to default-on at a major by being removed from
FEATURES.
Defined Under Namespace
Classes: Feature
Constant Summary collapse
- FEATURES =
The overlay.
Feature ids are kebab-case, and name the discipline rather than the rule it happens to promote (
reject-unparseable-signatures, notrbs-quarantine-error): a discipline may grow to cover more rules without its id going stale, and the id is contract vocabulary that outlives the rule set it started with. [ Feature.new( id: "reject-unparseable-signatures", summary: "A broken `signature_paths:` RBS set fails the run instead of degrading it silently. An " \ "unparseable `.rbs` is otherwise skipped with a warning, and a duplicate-declaration " \ "conflict (a file that parses fine but collides on resolve — typically against Rigor's " \ "own bundled RBS) collapses the whole env with a warning; either way the run gets quieter " \ "rather than cleaner. This treats both as a build error, the way a broken source file " \ "already is.", severity_overrides: { "rbs.coverage.quarantined-signature" => :error, "rbs.coverage.environment-build-failed" => :error }.freeze ), Feature.new( id: "use-of-void-value", summary: "Using a value recovered from an author-declared `-> void` return in value context (an " \ "assignment right-hand side, a call receiver, or an argument) becomes a `:warning`. An " \ "explicit `-> void` is the strongest possible \"do not rely on this return\" signal, so " \ "the direct-dispatch case is FP-narrow; a bare-statement `void` result and a legitimate " \ "`top` value both stay silent. Off by default because a new required diagnostic is an " \ "ADR-50 WD1 compatibility change (ADR-100 WD2).", severity_overrides: { "static.value-use.void" => :warning }.freeze ) ].freeze
Class Method Summary collapse
-
.active_features(selector) ⇒ Array<Feature>
Resolves a normalized
bleeding_edge:selector (see Configuration#bleeding_edge) to the active Feature list. - .feature(id) ⇒ Feature?
-
.feature_ids ⇒ Array<String>
Every feature id in the overlay.
-
.features ⇒ Array<Feature>
The whole overlay.
-
.severity_overrides_for(selector) ⇒ Hash{String => Symbol}
The merged severity-override map the active features impose for a selector.
-
.unknown_selected_ids(selector) ⇒ Array<String>
Feature ids named by a selector that are NOT in the overlay (typo / graduated / from a newer gem).
Class Method Details
.active_features(selector) ⇒ Array<Feature>
Resolves a normalized bleeding_edge: selector (see Configuration#bleeding_edge) to
the active Feature list. Unknown ids in a list / except selector are simply
absent from the overlay and contribute nothing — symmetric with how
severity_overrides: keeps an unknown rule id inert until it lands (robust across gem
versions).
104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/rigor/bleeding_edge.rb', line 104 def active_features(selector) case selector["mode"] when "all" except = selector["except"] || [] FEATURES.reject { |f| except.include?(f.id) } when "list" ids = selector["ids"] || [] FEATURES.select { |f| ids.include?(f.id) } else [] end end |
.feature(id) ⇒ Feature?
90 91 92 |
# File 'lib/rigor/bleeding_edge.rb', line 90 def feature(id) FEATURES.find { |f| f.id == id } end |
.feature_ids ⇒ Array<String>
Returns every feature id in the overlay.
84 85 86 |
# File 'lib/rigor/bleeding_edge.rb', line 84 def feature_ids FEATURES.map(&:id) end |
.features ⇒ Array<Feature>
Returns the whole overlay.
79 80 81 |
# File 'lib/rigor/bleeding_edge.rb', line 79 def features FEATURES end |
.severity_overrides_for(selector) ⇒ Hash{String => Symbol}
The merged severity-override map the active features impose for a selector. Frozen so
the result is Ractor.shareable?.
122 123 124 125 126 |
# File 'lib/rigor/bleeding_edge.rb', line 122 def severity_overrides_for(selector) active_features(selector).each_with_object({}) do |feature, acc| acc.merge!(feature.severity_overrides) end.freeze end |
.unknown_selected_ids(selector) ⇒ Array<String>
Feature ids named by a selector that are NOT in the overlay (typo / graduated / from a
newer gem). Surfaced by rigor show-bleedingedge as a hint; never an error.
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rigor/bleeding_edge.rb', line 133 def unknown_selected_ids(selector) named = case selector["mode"] when "list" then selector["ids"] || [] when "all" then selector["except"] || [] else [] end known = feature_ids named.reject { |id| known.include?(id) } end |