Class: Rigor::Analysis::RunCacheProbe
- Inherits:
-
Object
- Object
- Rigor::Analysis::RunCacheProbe
- Defined in:
- lib/rigor/analysis/run_cache_probe.rb
Overview
ADR-87 WD4 — the boot-slimming run-cache hit probe. Serves an ordinary rigor check's diagnostics
straight from the ADR-45 analysis.run-diagnostics cache WITHOUT loading the inference engine, its
plugin gems, or building the RBS environment: a warm HIT boots only CLI + config + cache + digest code
(the recon's $LOADED_FEATURES never gains a rigor/inference entry). The full plugin/prepass +
env-build tax (~0.8s on a gitlab null) is paid ONLY on a miss.
Soundness is inherited wholesale from ADR-45: the stored dependency descriptor records every file the
prior run read — analyzed sources, the RBS signature tree, AND every file each plugin read mid-analysis
(the Pundit-policy case) — and Cache::Store#peek_validated re-checks all of it against the live tree
(ADR-87 :stat-validated). A hit therefore means every input the prior run observed is unchanged, so
its cached diagnostics are exactly what a fresh full run would produce; skipping the plugin prepasses is
sound because their inputs are in that same validated set. The key is built through the shared
RunCacheKey — a project whose plugins synthesise virtual RBS produces a probe key that omits that
entry, so it simply misses and the full path takes over (never a wrong hit).
What the slot does NOT contain (#428)
ADR-103 puts the two effect diagnostics OUTSIDE the cached run assembly on purpose: the effects:
block is deliberately absent from the diagnostics cache identity, so a finding written into that
entry would outlive the configuration that produced it. Runner#run_analysis therefore appends them
after #compute_run_diagnostics — which is exactly the code a served hit skips. Serving the slot
verbatim silently dropped both of them on every warm run, and a check that only ever fires on a cold
cache is worse than one that never fires at all.
A probe that serves a slot has to answer for what the slot omits, so this one does, per pass:
effect.annotations-uncheckedis reproduced here. It was built to be free (a glob and a regex over the project's own signature tree — Effects::SignatureSources), so the probe simply runs it, with no virtual RBS: the inline stratum is the documented fail-quiet direction of that pass, and it is the stratum a run without an environment never had. #441 — that omission is unreachable rather than merely tolerated, because a project whose plugins synthesise virtual RBS is exactly the one whose probe key omits therbs.virtual_rbsentry (§ above), so it misses here and the full path — which carries the stratum in every run mode — answers instead.effect.envelope-exceeded/effect.liskov-widened/effect.unknown-labelcannot be: they read the propagated effect graph and the cross-file discovery tables, i.e. the engine this path exists to skip. So the probe declines for a project that could earn one (#envelope_lane_live?) and the full path — which caches both halves in its own two slots, and re-judges them every run — serves it instead. The decline is measured against the declarations alone, never against what they would judge to, so it costs one glob and never a wrong answer.
Instance Method Summary collapse
-
#initialize(configuration:, cache_root:, explain:) ⇒ RunCacheProbe
constructor
A new instance of RunCacheProbe.
-
#serve(paths) ⇒ Analysis::Result?
The cached run result with the severity profile applied and no stats (matching a cache-served
Runner#run), or nil to DECLINE — a miss / stale / unavailable cache — so the caller loads the engine and runs the full path.
Constructor Details
#initialize(configuration:, cache_root:, explain:) ⇒ RunCacheProbe
Returns a new instance of RunCacheProbe.
57 58 59 60 61 |
# File 'lib/rigor/analysis/run_cache_probe.rb', line 57 def initialize(configuration:, cache_root:, explain:) @configuration = configuration @cache_root = cache_root @explain = explain end |
Instance Method Details
#serve(paths) ⇒ Analysis::Result?
Returns the cached run result with the severity profile applied and no stats
(matching a cache-served Runner#run), or nil to DECLINE — a miss / stale / unavailable cache — so
the caller loads the engine and runs the full path. Any failure declines rather than raising: the
probe must never turn a servable run into a crash.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/rigor/analysis/run_cache_probe.rb', line 68 def serve(paths) files = PathExpansion.ruby_files(paths, @configuration.exclude_patterns) key = RunCacheKey.descriptor( configuration: @configuration, files: files, explain: @explain, rbs_config_entries: RunCacheKey.libraries_config_entries(@configuration) ) return nil if key.nil? diagnostics = validated_diagnostics(key) return nil if diagnostics.nil? # #428 — asked only after the peek, so a run that was going to miss anyway never pays the walk. return nil if envelope_lane_live? Result.new( diagnostics: SeverityStamp.apply(diagnostics + residual_diagnostics, @configuration), stats: nil ) rescue StandardError nil end |