Class: Moult::Gate::Policy
- Inherits:
-
Object
- Object
- Moult::Gate::Policy
- Defined in:
- lib/moult/gate/policy.rb
Overview
The explicit, recorded set of thresholds the gate enforces — the realisation of "Clean as You Code" for Moult. A Policy is a plain value object; the thresholds it carries are serialized into every gate report so the verdict is auditable (never a hidden heuristic) and reproducible.
The DEFAULTS are judgement-based heuristics in the spirit of the health
knees — calibrated against a real corpus (Moult's own codebase: a default
must let a clean, well-tested gem pass). They are pinned in
test/test_gate_policy.rb; drift is a bug. Teams override them via the gate:
section of .moult.yml.
Constant Summary collapse
- DEFAULTS =
{ # A dead-code candidate on changed lines at or above this confidence fails # the gate. Public symbols base well below this; the rule bites freshly # added unused private methods — the canonical "new dead code" smell. dead_code_max_confidence: 0.8, # The highest boundary severity allowed to appear in a changed file. With # "medium", a new HIGH-severity packwerk violation (dependency/layer) fails. boundary_max_severity: "medium", # A changed method whose ABC complexity exceeds this ceiling fails the gate. complexity_ceiling: 30.0, # A clone group touching the diff whose flay mass exceeds this fails. Set to # roughly a fully duplicated ~10-line method: below it lies idiomatic # parallelism (sibling guard clauses, similar small methods) that a clean # codebase legitimately has, so a lower bar produces noise, not signal. duplication_max_mass: 100, # Path prefixes excluded from gating. Test/spec code is legitimately # repetitive (parallel cases, shared setup), so — like SonarQube and # CodeScene — the gate judges production code. Findings under these prefixes # are dropped from every rule. Override to [] to gate everything. exclude_paths: ["test", "spec"] }.freeze
- KEYS =
DEFAULTS.keys.freeze
Instance Attribute Summary collapse
-
#boundary_max_severity ⇒ Object
readonly
Returns the value of attribute boundary_max_severity.
-
#complexity_ceiling ⇒ Object
readonly
Returns the value of attribute complexity_ceiling.
-
#dead_code_max_confidence ⇒ Object
readonly
Returns the value of attribute dead_code_max_confidence.
-
#duplication_max_mass ⇒ Object
readonly
Returns the value of attribute duplication_max_mass.
-
#exclude_paths ⇒ Object
readonly
Returns the value of attribute exclude_paths.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
Class Method Summary collapse
-
.default ⇒ Policy
The pinned defaults, recorded with source "default".
-
.load(overrides, source:) ⇒ Policy
Merge a (string- or symbol-keyed) overrides hash onto DEFAULTS.
Instance Method Summary collapse
-
#excluded?(path) ⇒ Boolean
Is
path(root-relative) outside the gate's scope — i.e. -
#initialize(dead_code_max_confidence:, boundary_max_severity:, complexity_ceiling:, duplication_max_mass:, exclude_paths:, source:) ⇒ Policy
constructor
A new instance of Policy.
-
#to_h ⇒ Object
The auditable record of every applied threshold.
Constructor Details
#initialize(dead_code_max_confidence:, boundary_max_severity:, complexity_ceiling:, duplication_max_mass:, exclude_paths:, source:) ⇒ Policy
Returns a new instance of Policy.
47 48 49 50 51 52 53 54 55 |
# File 'lib/moult/gate/policy.rb', line 47 def initialize(dead_code_max_confidence:, boundary_max_severity:, complexity_ceiling:, duplication_max_mass:, exclude_paths:, source:) @dead_code_max_confidence = dead_code_max_confidence @boundary_max_severity = boundary_max_severity @complexity_ceiling = complexity_ceiling @duplication_max_mass = duplication_max_mass @exclude_paths = exclude_paths @source = source end |
Instance Attribute Details
#boundary_max_severity ⇒ Object (readonly)
Returns the value of attribute boundary_max_severity.
44 45 46 |
# File 'lib/moult/gate/policy.rb', line 44 def boundary_max_severity @boundary_max_severity end |
#complexity_ceiling ⇒ Object (readonly)
Returns the value of attribute complexity_ceiling.
44 45 46 |
# File 'lib/moult/gate/policy.rb', line 44 def complexity_ceiling @complexity_ceiling end |
#dead_code_max_confidence ⇒ Object (readonly)
Returns the value of attribute dead_code_max_confidence.
44 45 46 |
# File 'lib/moult/gate/policy.rb', line 44 def dead_code_max_confidence @dead_code_max_confidence end |
#duplication_max_mass ⇒ Object (readonly)
Returns the value of attribute duplication_max_mass.
44 45 46 |
# File 'lib/moult/gate/policy.rb', line 44 def duplication_max_mass @duplication_max_mass end |
#exclude_paths ⇒ Object (readonly)
Returns the value of attribute exclude_paths.
44 45 46 |
# File 'lib/moult/gate/policy.rb', line 44 def exclude_paths @exclude_paths end |
#source ⇒ Object (readonly)
Returns the value of attribute source.
44 45 46 |
# File 'lib/moult/gate/policy.rb', line 44 def source @source end |
Class Method Details
.default ⇒ Policy
The pinned defaults, recorded with source "default".
60 61 62 |
# File 'lib/moult/gate/policy.rb', line 60 def default load({}, source: "default") end |
.load(overrides, source:) ⇒ Policy
Merge a (string- or symbol-keyed) overrides hash onto DEFAULTS. Unknown keys are ignored so a stray .moult.yml entry can't silently weaken the gate.
69 70 71 |
# File 'lib/moult/gate/policy.rb', line 69 def load(overrides, source:) new(**DEFAULTS.merge(sanitize(overrides)), source: source) end |
Instance Method Details
#excluded?(path) ⇒ Boolean
Is path (root-relative) outside the gate's scope — i.e. under an excluded
prefix like test/ or spec/?
85 86 87 88 |
# File 'lib/moult/gate/policy.rb', line 85 def excluded?(path) segment = path.to_s.split("/").first exclude_paths.include?(segment) end |
#to_h ⇒ Object
The auditable record of every applied threshold.
91 92 93 94 95 96 97 98 99 100 |
# File 'lib/moult/gate/policy.rb', line 91 def to_h { source: source, dead_code_max_confidence: dead_code_max_confidence, boundary_max_severity: boundary_max_severity, complexity_ceiling: complexity_ceiling, duplication_max_mass: duplication_max_mass, exclude_paths: exclude_paths } end |