rigortype 0.3.8 → 0.4.0

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.
Files changed (634) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/data/capability_roles/capability_roles.rbs +36 -0
  4. data/data/core_overlay/enumerable.rbs +51 -0
  5. data/data/core_overlay/enumerator.rbs +84 -0
  6. data/data/core_overlay/hash_rbs3.rbs +41 -0
  7. data/data/core_overlay/process.rbs +40 -0
  8. data/data/core_overlay/string_io.rbs +33 -0
  9. data/data/effects/core.yml +3 -3
  10. data/data/gem_overlay/activesupport/core_ext.rbs +236 -17
  11. data/docs/handbook/02-everyday-types.md +17 -14
  12. data/docs/handbook/03-narrowing.md +132 -14
  13. data/docs/handbook/04-tuples-and-shapes.md +8 -6
  14. data/docs/handbook/05-methods-and-blocks.md +1 -1
  15. data/docs/handbook/06-classes.md +2 -2
  16. data/docs/handbook/07-rbs-and-extended.md +19 -1
  17. data/docs/handbook/10-sorbet.md +9 -10
  18. data/docs/handbook/11-sig-gen.md +525 -13
  19. data/docs/handbook/README.md +1 -1
  20. data/docs/handbook/appendix-elixir.md +2 -2
  21. data/docs/handbook/appendix-go.md +2 -2
  22. data/docs/handbook/appendix-java-csharp.md +2 -2
  23. data/docs/handbook/appendix-mypy.md +2 -2
  24. data/docs/handbook/appendix-phpstan.md +1 -1
  25. data/docs/handbook/appendix-rust.md +1 -1
  26. data/docs/handbook/appendix-type-theory.md +4 -4
  27. data/docs/handbook/appendix-typescript.md +1 -1
  28. data/docs/llms.txt +2 -0
  29. data/docs/manual/02-cli-reference.md +95 -6
  30. data/docs/manual/03-configuration.md +18 -0
  31. data/docs/manual/04-diagnostics.md +15 -0
  32. data/docs/manual/07-plugins.md +15 -5
  33. data/docs/manual/08-skills.md +23 -2
  34. data/docs/manual/10-mcp-server.md +3 -2
  35. data/docs/manual/11-ci.md +9 -0
  36. data/docs/manual/15-type-protection-coverage.md +8 -0
  37. data/docs/manual/16-rbs-extended-annotations.md +46 -8
  38. data/docs/manual/18-removing-dead-code.md +10 -8
  39. data/docs/manual/19-effect-labels.md +10 -0
  40. data/docs/manual/plugins/README.md +7 -0
  41. data/docs/manual/plugins/rigor-actioncable.md +8 -1
  42. data/docs/manual/plugins/rigor-actionmailer.md +7 -0
  43. data/docs/manual/plugins/rigor-actionpack.md +261 -0
  44. data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
  45. data/docs/manual/plugins/rigor-activejob.md +7 -0
  46. data/docs/manual/plugins/rigor-activerecord.md +138 -4
  47. data/docs/manual/plugins/rigor-activestorage.md +8 -1
  48. data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
  49. data/docs/manual/plugins/rigor-grape.md +106 -0
  50. data/docs/manual/plugins/rigor-graphql.md +23 -2
  51. data/docs/manual/plugins/rigor-pundit.md +8 -1
  52. data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
  53. data/docs/manual/plugins/rigor-rails-routes.md +7 -0
  54. data/docs/manual/plugins/rigor-rbs-inline.md +229 -1
  55. data/docs/manual/plugins/rigor-sidekiq.md +8 -1
  56. data/docs/manual/plugins/rigor-sorbet.md +21 -5
  57. data/exe/rigor +19 -4
  58. data/lib/rigor/analysis/baseline.rb +3 -3
  59. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
  60. data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
  61. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
  62. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
  63. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
  64. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
  65. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
  66. data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
  67. data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
  68. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
  69. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -1
  70. data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
  71. data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
  72. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +38 -4
  73. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
  74. data/lib/rigor/analysis/check_rules.rb +718 -79
  75. data/lib/rigor/analysis/crash_signature.rb +8 -24
  76. data/lib/rigor/analysis/dependency_recorder.rb +23 -0
  77. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
  78. data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
  79. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
  80. data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
  81. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
  82. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  83. data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
  84. data/lib/rigor/analysis/erb_template_detector.rb +1 -2
  85. data/lib/rigor/analysis/fact_store.rb +15 -1
  86. data/lib/rigor/analysis/incremental.rb +42 -0
  87. data/lib/rigor/analysis/incremental_session.rb +117 -26
  88. data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
  89. data/lib/rigor/analysis/project_scan.rb +11 -1
  90. data/lib/rigor/analysis/reachability/graph.rb +3 -5
  91. data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
  92. data/lib/rigor/analysis/reachability/project_files.rb +2 -2
  93. data/lib/rigor/analysis/reachability/scan.rb +5 -5
  94. data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
  95. data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
  96. data/lib/rigor/analysis/result.rb +1 -3
  97. data/lib/rigor/analysis/rule_catalog.rb +131 -1
  98. data/lib/rigor/analysis/run_cache_key.rb +21 -12
  99. data/lib/rigor/analysis/run_cache_probe.rb +3 -5
  100. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
  101. data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
  102. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
  103. data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
  104. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
  105. data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
  106. data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
  107. data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
  108. data/lib/rigor/analysis/runner.rb +407 -51
  109. data/lib/rigor/analysis/template_unit_collector.rb +303 -0
  110. data/lib/rigor/analysis/template_unit_paths.rb +91 -0
  111. data/lib/rigor/analysis/template_unit_positions.rb +293 -0
  112. data/lib/rigor/analysis/template_units.rb +399 -0
  113. data/lib/rigor/analysis/worker_session.rb +62 -20
  114. data/lib/rigor/bleeding_edge.rb +10 -24
  115. data/lib/rigor/builtins/hkt_builtins.rb +3 -2
  116. data/lib/rigor/builtins/imported_refinements.rb +159 -21
  117. data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
  118. data/lib/rigor/builtins/regex_refinement.rb +21 -13
  119. data/lib/rigor/builtins/static_return_refinements.rb +7 -6
  120. data/lib/rigor/cache/annotation_location.rb +2 -4
  121. data/lib/rigor/cache/descriptor.rb +63 -20
  122. data/lib/rigor/cache/engine_source.rb +33 -5
  123. data/lib/rigor/cache/file_digest.rb +9 -1
  124. data/lib/rigor/cache/incremental_snapshot.rb +72 -6
  125. data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
  126. data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
  127. data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
  128. data/lib/rigor/cache/rbs_constant_table.rb +0 -3
  129. data/lib/rigor/cache/rbs_descriptor.rb +112 -14
  130. data/lib/rigor/cache/rbs_environment.rb +8 -4
  131. data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
  132. data/lib/rigor/cache/store.rb +76 -32
  133. data/lib/rigor/ci_detector.rb +1 -0
  134. data/lib/rigor/cli/annotate_command.rb +5 -6
  135. data/lib/rigor/cli/check_command.rb +57 -10
  136. data/lib/rigor/cli/check_invocation.rb +6 -11
  137. data/lib/rigor/cli/check_runner_factory.rb +1 -5
  138. data/lib/rigor/cli/coverage_command.rb +1 -1
  139. data/lib/rigor/cli/coverage_mutation.rb +12 -3
  140. data/lib/rigor/cli/coverage_scan.rb +1 -5
  141. data/lib/rigor/cli/diff_command.rb +1 -1
  142. data/lib/rigor/cli/doc_links.rb +4 -4
  143. data/lib/rigor/cli/docs_command.rb +6 -6
  144. data/lib/rigor/cli/doctor_command.rb +85 -38
  145. data/lib/rigor/cli/effects_command.rb +2 -2
  146. data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
  147. data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
  148. data/lib/rigor/cli/explain_command.rb +34 -1
  149. data/lib/rigor/cli/fused_protection_report.rb +7 -1
  150. data/lib/rigor/cli/lsp_command.rb +1 -1
  151. data/lib/rigor/cli/mcp_command.rb +1 -1
  152. data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
  153. data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
  154. data/lib/rigor/cli/mutation_protection_report.rb +7 -1
  155. data/lib/rigor/cli/plugin_command.rb +4 -4
  156. data/lib/rigor/cli/plugins_command.rb +2 -1
  157. data/lib/rigor/cli/prism_colorizer.rb +1 -2
  158. data/lib/rigor/cli/protection_fork_scan.rb +6 -6
  159. data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
  160. data/lib/rigor/cli/sig_gen_command.rb +212 -31
  161. data/lib/rigor/cli/skill_command.rb +2 -2
  162. data/lib/rigor/cli/skill_deep_probe.rb +4 -4
  163. data/lib/rigor/cli/skill_describe.rb +35 -35
  164. data/lib/rigor/cli/trace_command.rb +4 -4
  165. data/lib/rigor/cli/trace_renderer.rb +5 -6
  166. data/lib/rigor/cli/triage_command.rb +1 -1
  167. data/lib/rigor/cli/type_of_command.rb +29 -11
  168. data/lib/rigor/cli/type_of_renderer.rb +20 -9
  169. data/lib/rigor/cli/type_of_template_probe.rb +189 -0
  170. data/lib/rigor/cli/type_scan_command.rb +4 -4
  171. data/lib/rigor/cli/unused_command.rb +11 -3
  172. data/lib/rigor/cli/upgrade_command.rb +1 -1
  173. data/lib/rigor/cli.rb +89 -9
  174. data/lib/rigor/config_audit.rb +30 -5
  175. data/lib/rigor/configuration/severity_profile.rb +25 -9
  176. data/lib/rigor/configuration.rb +109 -7
  177. data/lib/rigor/effects/ancestry_recorder.rb +191 -0
  178. data/lib/rigor/effects/attribution.rb +12 -5
  179. data/lib/rigor/effects/callee_rule.rb +368 -0
  180. data/lib/rigor/effects/catalog.rb +7 -4
  181. data/lib/rigor/effects/collector.rb +11 -5
  182. data/lib/rigor/effects/config_envelopes.rb +15 -10
  183. data/lib/rigor/effects/definition_context.rb +179 -0
  184. data/lib/rigor/effects/definition_lines.rb +25 -6
  185. data/lib/rigor/effects/effect_table.rb +11 -4
  186. data/lib/rigor/effects/entry_points.rb +0 -2
  187. data/lib/rigor/effects/envelope_check.rb +9 -9
  188. data/lib/rigor/effects/envelope_index.rb +20 -8
  189. data/lib/rigor/effects/file_collection.rb +59 -5
  190. data/lib/rigor/effects/framework_units.rb +5 -7
  191. data/lib/rigor/effects/identity.rb +20 -6
  192. data/lib/rigor/effects/inline_anchor.rb +7 -7
  193. data/lib/rigor/effects/label_intent.rb +3 -4
  194. data/lib/rigor/effects/liskov_check.rb +8 -8
  195. data/lib/rigor/effects/local_ownership.rb +38 -12
  196. data/lib/rigor/effects/method_key.rb +22 -1
  197. data/lib/rigor/effects/mutation_classifier.rb +23 -12
  198. data/lib/rigor/effects/plugin_facts.rb +47 -37
  199. data/lib/rigor/effects/propagator.rb +297 -19
  200. data/lib/rigor/effects/registry.rb +1 -1
  201. data/lib/rigor/effects/scanner.rb +122 -73
  202. data/lib/rigor/effects/signature_sources.rb +4 -6
  203. data/lib/rigor/effects/snapshot.rb +12 -11
  204. data/lib/rigor/effects/snapshot_diff.rb +1 -1
  205. data/lib/rigor/effects/summary.rb +27 -4
  206. data/lib/rigor/effects/unit_scan.rb +393 -38
  207. data/lib/rigor/effects/unknown_label_check.rb +3 -8
  208. data/lib/rigor/effects/unknown_label_report.rb +3 -4
  209. data/lib/rigor/effects/visibility.rb +101 -0
  210. data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
  211. data/lib/rigor/environment/class_registry.rb +3 -1
  212. data/lib/rigor/environment/failure_slot.rb +2 -2
  213. data/lib/rigor/environment/installed_gem_set.rb +85 -0
  214. data/lib/rigor/environment/lockfile_resolver.rb +68 -4
  215. data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
  216. data/lib/rigor/environment/member_consistency.rb +298 -0
  217. data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
  218. data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
  219. data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
  220. data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
  221. data/lib/rigor/environment/rbs_loader.rb +674 -79
  222. data/lib/rigor/environment.rb +174 -24
  223. data/lib/rigor/flow_contribution/merger.rb +0 -2
  224. data/lib/rigor/flow_contribution.rb +11 -13
  225. data/lib/rigor/hashing/xxh3.rb +264 -0
  226. data/lib/rigor/inference/acceptance.rb +292 -17
  227. data/lib/rigor/inference/block_auto_splat.rb +216 -0
  228. data/lib/rigor/inference/block_call_timing.rb +338 -0
  229. data/lib/rigor/inference/block_parameter_binder.rb +75 -30
  230. data/lib/rigor/inference/block_repetition.rb +71 -0
  231. data/lib/rigor/inference/body_fixpoint.rb +7 -6
  232. data/lib/rigor/inference/budget_trace.rb +3 -6
  233. data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
  234. data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
  235. data/lib/rigor/inference/captured_locals.rb +389 -18
  236. data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
  237. data/lib/rigor/inference/content_join.rb +200 -27
  238. data/lib/rigor/inference/coverage_scanner.rb +4 -6
  239. data/lib/rigor/inference/def_return_typer.rb +11 -7
  240. data/lib/rigor/inference/define_method_block_self.rb +64 -0
  241. data/lib/rigor/inference/dynamic_origin.rb +1 -1
  242. data/lib/rigor/inference/element_read_widening.rb +180 -0
  243. data/lib/rigor/inference/error_info.rb +196 -0
  244. data/lib/rigor/inference/expression_typer.rb +2124 -468
  245. data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
  246. data/lib/rigor/inference/fork_map.rb +5 -7
  247. data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
  248. data/lib/rigor/inference/global_write_census.rb +239 -0
  249. data/lib/rigor/inference/guard_rebinding.rb +447 -0
  250. data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
  251. data/lib/rigor/inference/hkt_reducer.rb +2 -3
  252. data/lib/rigor/inference/hkt_registry.rb +4 -7
  253. data/lib/rigor/inference/index_write_widening.rb +16 -7
  254. data/lib/rigor/inference/indexed_narrowing.rb +61 -9
  255. data/lib/rigor/inference/jump_targets.rb +82 -0
  256. data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
  257. data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
  258. data/lib/rigor/inference/last_line.rb +340 -0
  259. data/lib/rigor/inference/last_status.rb +144 -0
  260. data/lib/rigor/inference/macro_block_self_type.rb +168 -21
  261. data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
  262. data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
  263. data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
  264. data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
  265. data/lib/rigor/inference/match_rebinding.rb +392 -0
  266. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
  267. data/lib/rigor/inference/method_dispatcher/block_folding.rb +87 -33
  268. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
  269. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
  270. data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
  271. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
  272. data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
  273. data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
  274. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
  275. data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
  276. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
  277. data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
  278. data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
  279. data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
  280. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
  281. data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
  282. data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
  283. data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
  284. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
  285. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
  286. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
  287. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
  288. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
  289. data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
  290. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
  291. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
  292. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
  293. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
  294. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
  295. data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
  296. data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
  297. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  298. data/lib/rigor/inference/method_dispatcher.rb +225 -25
  299. data/lib/rigor/inference/method_parameter_binder.rb +12 -9
  300. data/lib/rigor/inference/multi_target_binder.rb +341 -55
  301. data/lib/rigor/inference/mutation_rejoin.rb +171 -0
  302. data/lib/rigor/inference/mutation_widening.rb +156 -85
  303. data/lib/rigor/inference/narrowing.rb +835 -162
  304. data/lib/rigor/inference/operand_effects.rb +167 -0
  305. data/lib/rigor/inference/operand_walk.rb +88 -0
  306. data/lib/rigor/inference/optimistic_origin.rb +153 -16
  307. data/lib/rigor/inference/origin_lookup.rb +2 -3
  308. data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
  309. data/lib/rigor/inference/pre_eval_constants.rb +6 -5
  310. data/lib/rigor/inference/precision_scanner.rb +3 -4
  311. data/lib/rigor/inference/project_method_ownership.rb +136 -0
  312. data/lib/rigor/inference/project_patched_methods.rb +9 -4
  313. data/lib/rigor/inference/project_patched_scanner.rb +10 -6
  314. data/lib/rigor/inference/protection_scanner.rb +1 -2
  315. data/lib/rigor/inference/range_constant.rb +57 -0
  316. data/lib/rigor/inference/rbs_type_translator.rb +49 -11
  317. data/lib/rigor/inference/receiver_alias.rb +93 -4
  318. data/lib/rigor/inference/receiver_blind_block.rb +219 -0
  319. data/lib/rigor/inference/refinement_mutation.rb +76 -0
  320. data/lib/rigor/inference/repeated_or_writes.rb +463 -0
  321. data/lib/rigor/inference/return_barrier.rb +54 -0
  322. data/lib/rigor/inference/rewrite_mutation.rb +120 -0
  323. data/lib/rigor/inference/scope_indexer.rb +5228 -627
  324. data/lib/rigor/inference/statement_evaluator.rb +3452 -595
  325. data/lib/rigor/inference/stored_block_call.rb +54 -0
  326. data/lib/rigor/inference/string_mutation.rb +97 -0
  327. data/lib/rigor/inference/struct_fold_safety.rb +6 -7
  328. data/lib/rigor/inference/synthetic_method_index.rb +1 -2
  329. data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
  330. data/lib/rigor/inference/unknown_store_widening.rb +200 -0
  331. data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
  332. data/lib/rigor/inference/version_guard.rb +28 -21
  333. data/lib/rigor/inference/void_origin.rb +3 -3
  334. data/lib/rigor/inference/void_tail_summary.rb +2 -4
  335. data/lib/rigor/language_server/buffer_table.rb +4 -4
  336. data/lib/rigor/language_server/completion_provider.rb +1 -1
  337. data/lib/rigor/language_server/debouncer.rb +0 -1
  338. data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
  339. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  340. data/lib/rigor/language_server/folding_range_provider.rb +1 -1
  341. data/lib/rigor/language_server/hover_provider.rb +1 -1
  342. data/lib/rigor/language_server/hover_renderer.rb +4 -4
  343. data/lib/rigor/language_server/incremental_sync.rb +6 -6
  344. data/lib/rigor/language_server/project_context.rb +7 -8
  345. data/lib/rigor/language_server/publish_batcher.rb +2 -2
  346. data/lib/rigor/language_server/selection_range_provider.rb +2 -2
  347. data/lib/rigor/language_server/server.rb +9 -9
  348. data/lib/rigor/language_server/signature_help_provider.rb +1 -1
  349. data/lib/rigor/language_server/uri.rb +1 -1
  350. data/lib/rigor/mcp/server.rb +2 -1
  351. data/lib/rigor/plugin/base.rb +258 -26
  352. data/lib/rigor/plugin/box_probe.rb +91 -0
  353. data/lib/rigor/plugin/bundled_catalog.rb +167 -0
  354. data/lib/rigor/plugin/effect_attribution.rb +65 -11
  355. data/lib/rigor/plugin/effect_entry_points.rb +3 -3
  356. data/lib/rigor/plugin/fact_store.rb +6 -6
  357. data/lib/rigor/plugin/io_boundary.rb +93 -8
  358. data/lib/rigor/plugin/isolation.rb +29 -6
  359. data/lib/rigor/plugin/loader.rb +33 -13
  360. data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
  361. data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
  362. data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
  363. data/lib/rigor/plugin/manifest.rb +94 -11
  364. data/lib/rigor/plugin/registry.rb +76 -12
  365. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
  366. data/lib/rigor/plugin/template_unit.rb +196 -0
  367. data/lib/rigor/plugin/trust_policy.rb +2 -4
  368. data/lib/rigor/plugin/type_node_resolver.rb +3 -3
  369. data/lib/rigor/plugin.rb +1 -0
  370. data/lib/rigor/plugin_gap_advisory.rb +96 -0
  371. data/lib/rigor/project_environment.rb +138 -0
  372. data/lib/rigor/protection/analysis_guard.rb +93 -14
  373. data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
  374. data/lib/rigor/protection/dependency_closure.rb +5 -8
  375. data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
  376. data/lib/rigor/protection/discovery_seed.rb +14 -12
  377. data/lib/rigor/protection/kill_signature.rb +1 -4
  378. data/lib/rigor/protection/measurement_integrity.rb +1 -3
  379. data/lib/rigor/protection/mutation_cache.rb +7 -11
  380. data/lib/rigor/protection/mutation_scanner.rb +12 -15
  381. data/lib/rigor/protection/mutator.rb +2 -1
  382. data/lib/rigor/protection/test_suite_oracle.rb +5 -5
  383. data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
  384. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  385. data/lib/rigor/rbs_extended/reporter.rb +36 -10
  386. data/lib/rigor/rbs_extended.rb +88 -21
  387. data/lib/rigor/reflection/constant_ancestors.rb +97 -0
  388. data/lib/rigor/reflection/constant_path.rb +139 -0
  389. data/lib/rigor/reflection.rb +93 -110
  390. data/lib/rigor/runtime/jit.rb +6 -8
  391. data/lib/rigor/scope/discovery_index.rb +165 -2
  392. data/lib/rigor/scope.rb +1041 -32
  393. data/lib/rigor/sig_gen/alias_index.rb +289 -0
  394. data/lib/rigor/sig_gen/classification.rb +22 -5
  395. data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
  396. data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
  397. data/lib/rigor/sig_gen/generator.rb +673 -53
  398. data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
  399. data/lib/rigor/sig_gen/layout_index.rb +3 -4
  400. data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
  401. data/lib/rigor/sig_gen/method_candidate.rb +47 -3
  402. data/lib/rigor/sig_gen/observation_collector.rb +18 -16
  403. data/lib/rigor/sig_gen/path_mapper.rb +4 -6
  404. data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
  405. data/lib/rigor/sig_gen/renderer.rb +128 -14
  406. data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
  407. data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
  408. data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
  409. data/lib/rigor/sig_gen/write_result.rb +19 -3
  410. data/lib/rigor/sig_gen/writer.rb +189 -41
  411. data/lib/rigor/sig_gen.rb +3 -0
  412. data/lib/rigor/signature_path_audit.rb +153 -6
  413. data/lib/rigor/source/literals.rb +0 -23
  414. data/lib/rigor/source/node_children.rb +0 -2
  415. data/lib/rigor/source/node_locator.rb +5 -11
  416. data/lib/rigor/source/node_walker.rb +0 -6
  417. data/lib/rigor/source/parameter_envelope.rb +72 -0
  418. data/lib/rigor/source.rb +1 -0
  419. data/lib/rigor/triage/catalogue.rb +1 -3
  420. data/lib/rigor/triage.rb +3 -5
  421. data/lib/rigor/type/accepts_result.rb +24 -6
  422. data/lib/rigor/type/combinator.rb +144 -5
  423. data/lib/rigor/type/data_class.rb +2 -2
  424. data/lib/rigor/type/data_instance.rb +4 -4
  425. data/lib/rigor/type/difference.rb +1 -0
  426. data/lib/rigor/type/float_range.rb +128 -0
  427. data/lib/rigor/type/hash_shape.rb +6 -6
  428. data/lib/rigor/type/integer_range.rb +13 -8
  429. data/lib/rigor/type/nominal.rb +8 -2
  430. data/lib/rigor/type/refined.rb +4 -3
  431. data/lib/rigor/type/struct_class.rb +3 -3
  432. data/lib/rigor/type/struct_instance.rb +4 -4
  433. data/lib/rigor/type.rb +1 -0
  434. data/lib/rigor/type_node/generic.rb +1 -1
  435. data/lib/rigor/type_node/range_literal.rb +25 -0
  436. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  437. data/lib/rigor/type_node.rb +1 -0
  438. data/lib/rigor/version.rb +1 -1
  439. data/lib/rigor.rb +1 -0
  440. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
  441. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
  442. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
  443. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
  444. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
  445. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
  446. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
  447. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
  448. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
  449. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
  450. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
  451. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
  452. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
  453. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
  454. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
  455. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
  456. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
  457. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
  458. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +264 -3
  459. data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
  460. data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
  461. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
  462. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
  463. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
  464. data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
  465. data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
  466. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
  467. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
  468. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
  469. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
  470. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
  471. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -5
  472. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
  473. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
  474. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +383 -7
  475. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
  476. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
  477. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
  478. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
  479. data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
  480. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
  481. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
  482. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
  483. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
  484. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
  485. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
  486. data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
  487. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
  488. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
  489. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
  490. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
  491. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
  492. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
  493. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
  494. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
  495. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
  496. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
  497. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
  498. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
  499. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
  500. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
  501. data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
  502. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
  503. data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
  504. data/plugins/rigor-grape/sig/grape.rbs +263 -0
  505. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
  506. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
  507. data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
  508. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
  509. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
  510. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
  511. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
  512. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
  513. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
  514. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
  515. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
  516. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
  517. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
  518. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
  519. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
  520. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
  521. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
  522. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
  523. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
  524. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
  525. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
  526. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
  527. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
  528. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
  529. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
  530. data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
  531. data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
  532. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
  533. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +324 -18
  534. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
  535. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
  536. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
  537. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
  538. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
  539. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
  540. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
  541. data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
  542. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
  543. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
  544. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
  545. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
  546. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
  547. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
  548. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
  549. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
  550. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
  551. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
  552. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
  553. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
  554. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
  555. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
  556. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
  557. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
  558. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
  559. data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
  560. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
  561. data/sig/rigor/analysis/baseline.rbs +69 -7
  562. data/sig/rigor/analysis/fact_store.rbs +1 -1
  563. data/sig/rigor/analysis/project_scan.rbs +74 -0
  564. data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
  565. data/sig/rigor/cache.rbs +2 -3
  566. data/sig/rigor/effects/config_envelopes.rbs +100 -0
  567. data/sig/rigor/effects/effect_table.rbs +60 -0
  568. data/sig/rigor/effects/envelope.rbs +97 -0
  569. data/sig/rigor/effects/envelope_index.rbs +33 -0
  570. data/sig/rigor/effects/file_collection.rbs +81 -0
  571. data/sig/rigor/effects/label.rbs +26 -0
  572. data/sig/rigor/effects/label_set.rbs +46 -0
  573. data/sig/rigor/effects/method_key.rbs +24 -0
  574. data/sig/rigor/effects/origin.rbs +50 -0
  575. data/sig/rigor/effects/plugin_facts.rbs +141 -0
  576. data/sig/rigor/effects/registry.rbs +68 -0
  577. data/sig/rigor/effects/summary.rbs +50 -0
  578. data/sig/rigor/effects/taint_cause.rbs +12 -0
  579. data/sig/rigor/environment.rbs +17 -10
  580. data/sig/rigor/inference/optimistic_origin.rbs +10 -0
  581. data/sig/rigor/inference.rbs +9 -14
  582. data/sig/rigor/plugin/additional_initializer.rbs +36 -0
  583. data/sig/rigor/plugin/base.rbs +30 -7
  584. data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
  585. data/sig/rigor/plugin/effect_attribution.rbs +66 -0
  586. data/sig/rigor/plugin/effect_edge.rbs +33 -0
  587. data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
  588. data/sig/rigor/plugin/io_boundary.rbs +4 -0
  589. data/sig/rigor/plugin/loader.rbs +3 -3
  590. data/sig/rigor/plugin/manifest.rbs +51 -11
  591. data/sig/rigor/plugin/protocol_contract.rbs +68 -0
  592. data/sig/rigor/plugin/registry.rbs +62 -1
  593. data/sig/rigor/plugin.rbs +1 -1
  594. data/sig/rigor/rbs_extended.rbs +1 -1
  595. data/sig/rigor/reflection.rbs +9 -6
  596. data/sig/rigor/scope.rbs +148 -12
  597. data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
  598. data/sig/rigor/source.rbs +4 -4
  599. data/sig/rigor/testing.rbs +10 -4
  600. data/sig/rigor/type.rbs +33 -1
  601. data/sig/rigor.rbs +39 -20
  602. data/skills/rigor-ask/SKILL.md +16 -11
  603. data/skills/rigor-baseline-reduce/SKILL.md +4 -6
  604. data/skills/rigor-ci-setup/SKILL.md +17 -21
  605. data/skills/rigor-doctor/SKILL.md +24 -22
  606. data/skills/rigor-doctor/references/01-checks.md +97 -33
  607. data/skills/rigor-editor-setup/SKILL.md +6 -4
  608. data/skills/rigor-mcp-setup/SKILL.md +5 -4
  609. data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
  610. data/skills/rigor-next-steps/SKILL.md +4 -2
  611. data/skills/rigor-plugin-author/SKILL.md +19 -23
  612. data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
  613. data/skills/rigor-plugin-author/references/02-walker-and-types.md +25 -27
  614. data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
  615. data/skills/rigor-plugin-review/SKILL.md +6 -4
  616. data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
  617. data/skills/rigor-plugin-tune/SKILL.md +4 -2
  618. data/skills/rigor-project-init/SKILL.md +15 -10
  619. data/skills/rigor-project-init/references/01-detect.md +13 -9
  620. data/skills/rigor-project-init/references/02-configure.md +43 -14
  621. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
  622. data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
  623. data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
  624. data/skills/rigor-protection-uplift/SKILL.md +4 -6
  625. data/skills/rigor-rbs-setup/SKILL.md +4 -2
  626. data/skills/rigor-type-oracle/SKILL.md +226 -0
  627. data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
  628. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
  629. data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
  630. data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
  631. data/skills/rigor-upgrade/SKILL.md +13 -8
  632. metadata +133 -3
  633. data/lib/rigor/cli/probe_environment.rb +0 -85
  634. data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
@@ -29,13 +29,11 @@ module Rigor
29
29
  # bucket on trust.
30
30
  Undecidable = Data.define(:fqn, :path, :line, :reason)
31
31
 
32
- # @param declarations [Array<Scan::Declaration>]
33
- # @param references [Array<Scan::Reference>]
34
- # @param root_fqns [Enumerable<String>] declarations that are entry points regardless of who references
32
+ # @param root_fqns — declarations that are entry points regardless of who references
35
33
  # them (config-declared globs in this slice; plugin-supplied roots are #349).
36
- # @param foreign [#call] predicate answering "is this FQN owned by something outside the project?" —
34
+ # @param foreign — predicate answering "is this FQN owned by something outside the project?" —
37
35
  # a reopened gem or stdlib class must never be a candidate (WD6). Defaults to "nothing is foreign".
38
- # @param dynamic_uses [Array<Scan::DynamicUse>] sites where a constant is reached by name at runtime.
36
+ # @param dynamic_uses — sites where a constant is reached by name at runtime.
39
37
  # A literal-argument site contributes a real reference; a dynamic one taints a namespace (WD4).
40
38
  def initialize(declarations:, references:, root_fqns: [], dynamic_uses: [], foreign: ->(_fqn) { false })
41
39
  @declarations = declarations
@@ -83,14 +83,14 @@ module Rigor
83
83
  # Loads the project's configured plugins, runs every `#prepare`, and returns the union of every
84
84
  # published `:reachability_roots` and `:reachability_references` fact.
85
85
  #
86
- # @param configuration [Rigor::Configuration] the loaded project configuration.
87
- # @param plugin_requirer [#call] how a plugin gem is brought into the process. The same seam
88
- # `Analysis::Runner` exposes, so a spec can register a plugin class without publishing a gem.
89
- # @param cache_store [Rigor::Cache::Store, nil] when given, each plugin's `#prepare` producers read
86
+ # @param plugin_requirer — how a plugin gem is brought into the process, called with the gem name. The
87
+ # same seam `Analysis::Runner` exposes, so a spec can register a plugin class without publishing a
88
+ # gem.
89
+ # @param cache_store — when given, each plugin's `#prepare` producers read
90
90
  # and write the same ADR-60 record-and-validate slots they use under `rigor check`, instead of
91
91
  # recomputing from scratch — a routes parse or a factory discovery is a validated cache read on
92
92
  # every invocation after the first. Nil keeps the historical recompute-always behaviour.
93
- # @return [Contribution] sorted and de-duplicated. Empty whenever the project declares no plugins, no
93
+ # @return sorted and de-duplicated. Empty whenever the project declares no plugins, no
94
94
  # plugin contributes anything, or anything at all goes wrong.
95
95
  def collect(configuration:, plugin_requirer: ->(name) { require name }, cache_store: nil)
96
96
  return Contribution.empty if configuration.plugins.empty?
@@ -46,8 +46,8 @@ module Rigor
46
46
  File.fnmatch?(pattern, path, File::FNM_PATHNAME)
47
47
  end
48
48
 
49
- # @param relative_paths [Array<String>] paths relative to `root`.
50
- # @return [Array<String>] those that belong to the project itself.
49
+ # @param relative_paths — paths relative to `root`.
50
+ # @return those that belong to the project itself.
51
51
  def own(relative_paths, root)
52
52
  prefixes = submodule_prefixes(root)
53
53
  relative_paths.grep_v(VENDOR_DIRS).reject { |rel| prefixes.any? { |prefix| rel.start_with?(prefix) } }
@@ -70,11 +70,6 @@ module Rigor
70
70
  end
71
71
  end
72
72
 
73
- # @param path [String] the file's path, as the report should render it.
74
- # @param source [String] the file's bytes.
75
- # @param target_ruby [String, nil] Prism version string, threaded from the project configuration.
76
- # @return [Result, nil] nil when the file does not parse (a parse error is the analyzer's business, not
77
- # this scan's — it simply contributes nothing rather than half a file).
78
73
  # A constant name is ASCII by construction, so a byte sequence that is not valid UTF-8 cannot be one.
79
74
  # Dropping it is both correct and the only safe answer: carrying it forward crashed the whole run on
80
75
  # the first `String#sub` downstream, which is how this surfaced — `rigor unused` on Rigor's own
@@ -86,6 +81,11 @@ module Rigor
86
81
  name.valid_encoding? ? name : nil
87
82
  end
88
83
 
84
+ # @param path — the file's path, as the report should render it.
85
+ # @param source — the file's bytes.
86
+ # @param target_ruby — Prism version string, threaded from the project configuration.
87
+ # @return nil when the file does not parse (a parse error is the analyzer's business, not
88
+ # this scan's — it simply contributes nothing rather than half a file).
89
89
  def self.call(path:, source:, target_ruby: nil)
90
90
  parsed = if target_ruby
91
91
  Prism.parse(source, filepath: path,
@@ -36,6 +36,7 @@ module Rigor
36
36
  File.expand_path("scan.rb", __dir__),
37
37
  File.expand_path(__FILE__)
38
38
  ].freeze
39
+ Ractor.make_shareable(SOURCE_FILES)
39
40
 
40
41
  # A file modified within this window of the recording instant is computed but never
41
42
  # recorded — the FileDigest racy-write guard, one tier simpler because a refused signature
@@ -43,9 +44,9 @@ module Rigor
43
44
  RACY_WINDOW_NS = 2_000_000_000
44
45
  private_constant :RACY_WINDOW_NS
45
46
 
46
- # @param cache_path [String, nil] the configuration's cache root; nil or empty is an inert
47
+ # @param cache_path — the configuration's cache root; nil or empty is an inert
47
48
  # cache (every fetch computes, nothing persists).
48
- # @param target_ruby [String, nil] parse-affecting configuration, part of the identity.
49
+ # @param target_ruby — parse-affecting configuration, part of the identity.
49
50
  def self.open(cache_path, target_ruby: nil)
50
51
  return new(path: nil, header: nil) if cache_path.nil? || cache_path.to_s.empty?
51
52
 
@@ -26,8 +26,8 @@ module Rigor
26
26
  module SignatureScan
27
27
  module_function
28
28
 
29
- # @param file [String] path to a `.rbs` file.
30
- # @return [Array<Scan::Reference>] one file-level reference per distinct referenced name. Empty when the
29
+ # @param file — path to a `.rbs` file.
30
+ # @return one file-level reference per distinct referenced name. Empty when the
31
31
  # file cannot be read or parsed — a broken signature is the analyzer's business, not this scan's.
32
32
  def call(file)
33
33
  _, _, decls = ::RBS::Parser.parse_signature(::RBS::Buffer.new(name: file, content: File.read(file)))
@@ -7,7 +7,7 @@ module Rigor
7
7
  class Result
8
8
  attr_reader :diagnostics, :stats
9
9
 
10
- # @param stats [Rigor::Analysis::RunStats, nil] end-of-run telemetry (target file count, RBS class
10
+ # @param stats — end-of-run telemetry (target file count, RBS class
11
11
  # breakdown, wall + RSS) collected by the Runner. Nil when stats collection wasn't requested or wasn't
12
12
  # applicable (early-exit paths like `validate_target_ruby` failure).
13
13
  def initialize(diagnostics: [], stats: nil)
@@ -43,8 +43,6 @@ module Rigor
43
43
 
44
44
  # The diagnostics {#crashed?} answers true for, so a caller can name what it saw rather than only that
45
45
  # it saw something.
46
- #
47
- # @return [Array<Rigor::Analysis::Diagnostic>]
48
46
  def crash_diagnostics
49
47
  diagnostics.select { |diagnostic| CrashSignature.discards_file_analysis?(diagnostic) }
50
48
  end
@@ -642,7 +642,10 @@ module Rigor
642
642
  "Later write is `nil` — the `@cache = nil` clear-idiom is allowlisted.",
643
643
  "Either side is Union / Dynamic / IntegerRange / a shape-varied carrier.",
644
644
  "Writes live in different classes that happen to share an ivar name.",
645
- "Writes are in `def self.foo` (singleton) bodies — those track separately."
645
+ "Writes are in a singleton body — `def self.foo` or a `class << self` def — those track " \
646
+ "separately.",
647
+ "Writes are in a `def` inside an anonymous-class factory block (`Class.new do … end`, " \
648
+ "`Module.new`, `Struct.new`, `Data.define`): that body defines another class."
646
649
  ],
647
650
  suppression: "`# rigor:disable ivar-write-mismatch` on the offending write.",
648
651
  severity_authored: :error,
@@ -653,6 +656,90 @@ module Rigor
653
656
  since: "0.1.2"
654
657
  ),
655
658
 
659
+ CheckRules::RULE_GLOBAL_WRITE_TYPE_MISMATCH => Entry.new(
660
+ id: CheckRules::RULE_GLOBAL_WRITE_TYPE_MISMATCH,
661
+ summary: "A special global is assigned a literal its setter rejects (TypeError at runtime).",
662
+ fires_when: [
663
+ "The write is `$g = literal` to a special whose setter checks the value: `$/` / `$-0`, `$,` and " \
664
+ "`$\\` (a String or nil), `$;` / `$-F` (a String, a Regexp, nil, or an object with `to_str`), `$~` " \
665
+ "(a MatchData or nil), `$0` / `$PROGRAM_NAME` (a String or an object with `to_str`), `$.` (an " \
666
+ "Integer, a Float, or an object with `to_int`), `$-i` (a String, nil, false, or an object with " \
667
+ "`to_str`), and `$stdout` / `$>` / `$stderr` (an object that responds to `write`, ADR-117 WD2).",
668
+ "The value is a literal node — an Integer, Float, Rational or imaginary literal, a String, Symbol " \
669
+ "or Regexp literal (interpolated or not), an Array or Hash literal, or `nil` / `true` / `false`, " \
670
+ "parenthesised or not — whose class the setter does not take: `$/ = 1`, `$/ = /x/`, `$~ = \"x\"`, " \
671
+ "`$0 = nil`, `$. = \"3\"`, `$stdout = 1`.",
672
+ "Where the setter also converts (`to_str`, `to_int`) or asks for `write`, the literal's object " \
673
+ "cannot answer that method: RBS gives its class neither the method nor a `method_missing` / " \
674
+ "`respond_to_missing?` / `respond_to?` of its own, and the program defines none of them anywhere.",
675
+ "The envelope is the interpreter's setter, not the global's RBS declaration: `$/ = /x/` fires " \
676
+ "although `$;` takes a Regexp."
677
+ ],
678
+ does_not_fire_when: [
679
+ "The special's setter accepts every value: `$stdin` (never checked, ADR-117 WD2), `$_`, `$VERBOSE`, " \
680
+ "`$DEBUG`, `$=`; nor `$@`, whose setter depends on whether `$!` is set.",
681
+ "The value is not a literal — a variable, a method call, a constant, a conditional — whatever its " \
682
+ "inferred type: a class RBS declares without `write` or `to_str` does not prove the object lacks it.",
683
+ "RBS gives the literal's class the method or a hatch of its own (a `sig/` reopening or `include` " \
684
+ "counts).",
685
+ "The program — any project or `pre_eval:` file — defines the method or a `method_missing` / " \
686
+ "`respond_to_missing?` / `respond_to?` anywhere, in any spelling (`def`, `define_method`, " \
687
+ "`define_singleton_method`, `alias`, `alias_method`, `attr_*`, a delegation macro, a string `eval`, " \
688
+ "the same through `send`) and on any receiver, or defines a method whose name no literal spells (a " \
689
+ "computed `define_method` or `send` name, a string `eval` whose code is not a plain literal, a name " \
690
+ "whose bytes are not valid in its encoding). " \
691
+ "This is blanket: no census of where a definition lands can be complete, so the literal of every " \
692
+ "class declines, whatever the definition's owner.",
693
+ "An ancestor's surface is rewritten from outside (`Integer.include(M)`, `Object.include(M)`, a string " \
694
+ "`class_eval`), or a top-level `include` / `prepend` / `extend`, or an ancestor's `include`, names a " \
695
+ "module RBS does not rule out.",
696
+ "For `$stdout` / `$>` / `$stderr`, a refinement that may add `write`, to any class, and a `using` in " \
697
+ "effect at the write. Which class it refines is not followed. The `to_str` / `to_int` conversions, and a " \
698
+ "refined `respond_to_missing?` / `respond_to?`, ignore refinements, so those still fire.",
699
+ "Any project or `pre_eval:` file aliases the special (`alias $stdout $out`, on either side).",
700
+ "The write is `$g op= v`, `$g ||= v`, `$g &&= v`, a multiple-assignment target, a `for` index, or a " \
701
+ "`rescue => $g` reference: their value is not type-checked.",
702
+ "The write sits in the dead arm of a decidable version guard. Other code that never runs (`if " \
703
+ "false`, after `return`) is not recognised, and a write there still fires."
704
+ ],
705
+ suppression: "`# rigor:disable global.write-type-mismatch` on the write.",
706
+ severity_authored: :error,
707
+ severity_by_profile: { lenient: :warning, balanced: :error, strict: :error },
708
+ # A literal's class is exact, the setter's envelope is the running interpreter's, and every way a program can
709
+ # give the object the method the setter asks for declines; the write then raises every time it runs.
710
+ evidence_tier: :high,
711
+ since: "0.4.0"
712
+ ),
713
+
714
+ CheckRules::RULE_GLOBAL_READONLY_WRITE => Entry.new(
715
+ id: CheckRules::RULE_GLOBAL_READONLY_WRITE,
716
+ summary: "A read-only special global is written (NameError at runtime).",
717
+ fires_when: [
718
+ "The write is `$g = value`, `$g op= value`, or a target of a multiple assignment (`$g, x = ...`, " \
719
+ "`*$g`) — forms that always write — to a special Ruby defines read-only: `$!`, `$$`, `$?`, `$<`, " \
720
+ "`$FILENAME`, `$*`, `$:` / `$LOAD_PATH` / `$-I`, `$\"` / `$LOADED_FEATURES`, `$-W`, `$-p`, `$-l`, " \
721
+ "`$-a`.",
722
+ "Whatever the value: the setter raises `NameError` (`$! is a read-only variable`) before it " \
723
+ "looks at it."
724
+ ],
725
+ does_not_fire_when: [
726
+ "The write is `$g ||= v` or `$g &&= v`, which writes only when the current value is falsy " \
727
+ "(truthy): `$LOAD_PATH ||= []` never writes.",
728
+ "The write is a `for` index or a `rescue => $g` reference.",
729
+ "Any project or `pre_eval:` file aliases the special (`alias $! $err`, on either side), which can " \
730
+ "make the name another variable.",
731
+ "Mutating the value is not a write: `$LOAD_PATH << dir` and `$LOADED_FEATURES.delete(f)` stay silent.",
732
+ "The write sits in the dead arm of a decidable version guard. Other code that never runs is not " \
733
+ "recognised, and a write there still fires."
734
+ ],
735
+ suppression: "`# rigor:disable global.readonly-write` on the write.",
736
+ severity_authored: :error,
737
+ severity_by_profile: { lenient: :error, balanced: :error, strict: :error },
738
+ # Syntactic: the name alone decides it, and the write raises every time it runs.
739
+ evidence_tier: :high,
740
+ since: "0.4.0"
741
+ ),
742
+
656
743
  CheckRules::RULE_SUPPRESSION_UNKNOWN_RULE => Entry.new(
657
744
  id: CheckRules::RULE_SUPPRESSION_UNKNOWN_RULE,
658
745
  summary: "A `# rigor:disable[-file]` comment names a rule that does not exist.",
@@ -893,6 +980,48 @@ module Rigor
893
980
  since: "0.3.4"
894
981
  ),
895
982
 
983
+ CheckRules::RULE_CONTRADICTING_SIGNATURE => Entry.new(
984
+ id: CheckRules::RULE_CONTRADICTING_SIGNATURE,
985
+ summary: "Two declarations of one method provably contradict: no value or call satisfies both.",
986
+ fires_when: [
987
+ "A method is declared both in the project's `sig/` and by an inline `# @rbs` / `#:` " \
988
+ "annotation, and the return or a parameter every call must pass holds two proven-disjoint " \
989
+ "types — distinct literals, a literal outside such a class, or two classes written absolutely " \
990
+ "whose RBS comes from Ruby core or the stdlib, neither an RBS ancestor of the other " \
991
+ "(`::String` against `::Integer`) — or the two keyword-free declarations accept " \
992
+ "positional counts that cannot meet, or one requires a keyword the other cannot take in any " \
993
+ "form. Several overloads are paired by correspondence, never by order. Positioned at the " \
994
+ "`.rbs` member; Rigor reads that declaration.",
995
+ "A member-level `%a{rigor:v1:return: …}` or `%a{rigor:v1:param: …}` refinement is proven " \
996
+ "disjoint from the type its own member declares, in every overload it applies to " \
997
+ "(`rigor:v1:return: positive-int` on `-> String`)."
998
+ ],
999
+ does_not_fire_when: [
1000
+ "One declaration refines the other (`String` against `non-empty-string`, `Symbol` against " \
1001
+ "`:asc | :desc`, `bool` against `TrueClass`): the two merge to the more precise one, silently.",
1002
+ "Either side is `untyped`, `void` or `top` in that position — consistent with everything.",
1003
+ "Rigor cannot prove the two contradict: a module or interface on either side, a class the " \
1004
+ "project declares (in `sig/`, inline or only in Ruby), a gem's class, any relative class name, " \
1005
+ "two element types of one generic class, a type alias, `self`, a type variable, a proc, an " \
1006
+ "optional or rest position, any block position, overloads that do not pair one to one, or " \
1007
+ "differently shaped parameter lists that still overlap. The " \
1008
+ "inline signature is then dropped and reported as `source-rbs-annotation-not-honoured` (info).",
1009
+ "A refinement is written on one overload rather than on the member: call sites do not honour it.",
1010
+ "Two `.rbs` files declare the same method (that fails the class's definition build, " \
1011
+ "`rbs.coverage.definition-build-failed`), or a project `.rbs` collides with bundled RBS " \
1012
+ "(the file is quarantined, `rbs.coverage.quarantined-signature`)."
1013
+ ],
1014
+ suppression: "`disable: [\"rbs.contradicting-signature\"]` in `.rigor.yml`, or a baseline entry. A " \
1015
+ "`# rigor:disable` comment does not reach a row positioned in a `.rbs` file. The real " \
1016
+ "fix is to regenerate the stale signature or correct the annotation.",
1017
+ severity_authored: :error,
1018
+ severity_by_profile: { lenient: :error, balanced: :error, strict: :error },
1019
+ # Both sides are authored declarations, and a firing needs a proof that no value or call satisfies
1020
+ # both — the ADR-35 both-sides-authored construction, with every doubt routed to the `:info` row.
1021
+ evidence_tier: :high,
1022
+ since: "0.4.0"
1023
+ ),
1024
+
896
1025
  CheckRules::RULE_SUPPRESSION_UNKNOWN_MARKER => Entry.new(
897
1026
  id: CheckRules::RULE_SUPPRESSION_UNKNOWN_MARKER,
898
1027
  summary: "A comment uses a suppression marker Rigor does not recognise " \
@@ -922,6 +1051,7 @@ module Rigor
922
1051
  since: "0.3.0"
923
1052
  )
924
1053
  }.freeze
1054
+ Ractor.make_shareable(ENTRIES)
925
1055
 
926
1056
  module_function
927
1057
 
@@ -80,17 +80,25 @@ module Rigor
80
80
  # collecting project's path-set churn is the same churn, and over-evicting costs one recompute.
81
81
  EFFECTS_GENERATION_CAP = GENERATION_CAP
82
82
 
83
- # @param rbs_config_entries [Array<Cache::Descriptor::ConfigEntry>] the RBS-derived config slots
83
+ # @param rbs_config_entries — the RBS-derived config slots
84
84
  # (`rbs.libraries` [+ `rbs.virtual_rbs`]). nil on any failure so a malformed key disables the cache.
85
- def descriptor(configuration:, files:, explain:, rbs_config_entries:)
85
+ # @param template_units_digest — #392 — the run's template-unit identity
86
+ # ({Analysis::TemplateUnits#digest}: every unit's source bytes + transform id + synthesis version).
87
+ # nil for a project whose plugins declare no `template_globs:`, which is every project today, and a
88
+ # nil contributes NO slot — so no existing key moves. A project that DOES have units produces a key
89
+ # the ADR-87 boot-slim probe (which loads no plugin and so passes nil) cannot reconstruct: the probe
90
+ # simply misses and the full path takes over, the same forgone-fast-lane trade the `rbs.virtual_rbs`
91
+ # slot already makes, and never a wrong hit.
92
+ def descriptor(configuration:, files:, explain:, rbs_config_entries:, template_units_digest: nil)
86
93
  Cache::Descriptor.new(
87
94
  gems: [Cache::RbsDescriptor.rbs_gem_entry],
88
- configs: rbs_config_entries + engine_source_entries + lockfile_entries(configuration) + [
89
- config_entry("configuration", Marshal.dump(configuration.to_h)),
90
- config_entry("engine",
91
- "#{Rigor::VERSION}:#{Cache::Descriptor::SCHEMA_VERSION}:#{explain}"),
92
- config_entry("paths", files.sort.join("\n"))
93
- ]
95
+ configs: rbs_config_entries + engine_source_entries + lockfile_entries(configuration) +
96
+ template_unit_entries(template_units_digest) + [
97
+ config_entry("configuration", Marshal.dump(configuration.to_h)),
98
+ config_entry("engine",
99
+ "#{Rigor::VERSION}:#{Cache::Descriptor::SCHEMA_VERSION}:#{explain}"),
100
+ config_entry("paths", files.sort.join("\n"))
101
+ ]
94
102
  )
95
103
  rescue StandardError
96
104
  nil
@@ -104,11 +112,12 @@ module Rigor
104
112
  #
105
113
  # {Cache::EngineSource::Unavailable} is left to propagate into `descriptor`'s rescue, which disables
106
114
  # the cache for the run: an engine we cannot identify must not be keyed by its version alone.
107
- def engine_source_entries
108
- identity = Cache::EngineSource.process_identity
109
- return [] if identity.nil?
115
+ def template_unit_entries(digest)
116
+ digest.nil? ? [] : [config_entry("template-units", digest)]
117
+ end
110
118
 
111
- [config_entry("engine-source", identity)]
119
+ def engine_source_entries
120
+ Cache::EngineSource.key_config_entries
112
121
  end
113
122
 
114
123
  # Issue #564 — the two dependency lockfiles, BY CONTENT. Both are inputs to the run's diagnostics and
@@ -51,17 +51,15 @@ module Rigor
51
51
  # serves it instead. The decline is measured against the declarations alone, never against what they
52
52
  # would judge to, so it costs one glob and never a wrong answer.
53
53
  class RunCacheProbe
54
- # @param configuration [Rigor::Configuration]
55
- # @param cache_root [String]
56
- # @param explain [Boolean] the `--explain` flag (folded into the key, as the runner does).
54
+ # @param explain — the `--explain` flag (folded into the key, as the runner does).
57
55
  def initialize(configuration:, cache_root:, explain:)
58
56
  @configuration = configuration
59
57
  @cache_root = cache_root
60
58
  @explain = explain
61
59
  end
62
60
 
63
- # @param paths [Array<String>] the analysis roots (`@argv` or `configuration.paths`).
64
- # @return [Analysis::Result, nil] the cached run result with the severity profile applied and no stats
61
+ # @param paths — the analysis roots (`@argv` or `configuration.paths`).
62
+ # @return the cached run result with the severity profile applied and no stats
65
63
  # (matching a cache-served `Runner#run`), or nil to DECLINE — a miss / stale / unavailable cache — so
66
64
  # the caller loads the engine and runs the full path. Any failure declines rather than raising: the
67
65
  # probe must never turn a servable run into a crash.
@@ -66,7 +66,7 @@ module Rigor
66
66
  # via `RIGOR_LSP_POOL_MIN_BATCH` (mirrors `RIGOR_RACTOR_WORKERS`'s override shape).
67
67
  DEFAULT_MIN_BATCH_SIZE = 16
68
68
 
69
- # @return [Integer] `RIGOR_LSP_POOL_MIN_BATCH` when set to a non-empty value, else
69
+ # @return `RIGOR_LSP_POOL_MIN_BATCH` when set to a non-empty value, else
70
70
  # {DEFAULT_MIN_BATCH_SIZE}.
71
71
  def self.resolve_min_batch_size
72
72
  env_value = ENV.fetch("RIGOR_LSP_POOL_MIN_BATCH", nil)
@@ -75,19 +75,17 @@ module Rigor
75
75
  Integer(env_value)
76
76
  end
77
77
 
78
- # @param configuration [Rigor::Configuration]
79
- # @param cache_store [Rigor::Cache::Store, nil]
80
- # @param environment [Rigor::Environment] the warm, shared per-session Environment
78
+ # @param environment — the warm, shared per-session Environment
81
79
  # (`ProjectContext#environment`) every job's Runner reuses instead of rebuilding.
82
- # @param prebuilt [Rigor::Analysis::ProjectScan] the warm, shared pre-pass snapshot
80
+ # @param prebuilt — the warm, shared pre-pass snapshot
83
81
  # (`ProjectContext#project_scan`) every job's Runner adopts instead of re-scanning.
84
- # @param workers [Integer] pool size. `#analyze` degrades to sequential in-process execution — one
82
+ # @param workers — pool size. `#analyze` degrades to sequential in-process execution — one
85
83
  # job at a time, no `fork` — when fewer than 2 bindings are submitted, fewer than `min_batch_size`
86
84
  # bindings are submitted, `workers` is not positive, `fork` is unavailable on this platform, or
87
85
  # `cache_store` is nil. The middle two are the fork-pool-is-not-worth-it-yet gate documented on
88
86
  # {DEFAULT_MIN_BATCH_SIZE}; the last two mirror
89
87
  # {PoolCoordinator#analyze_files_in_pool}'s own fork-pool preconditions.
90
- # @param min_batch_size [Integer] see {DEFAULT_MIN_BATCH_SIZE}. Exposed as a constructor param
88
+ # @param min_batch_size — see {DEFAULT_MIN_BATCH_SIZE}. Exposed as a constructor param
91
89
  # (rather than read from the env internally) purely for spec control; production callers get the
92
90
  # resolved default.
93
91
  def initialize(configuration:, cache_store:, environment:, prebuilt:, workers:,
@@ -185,7 +183,7 @@ module Rigor
185
183
  degraded
186
184
  end
187
185
 
188
- # @return [Hash, nil] the child's `{index => diagnostics}` payload, or nil when the child exited
186
+ # @return the child's `{index => diagnostics}` payload, or nil when the child exited
189
187
  # abnormally or wrote no readable payload. `Marshal.load` is safe here: the blob was written by our
190
188
  # own forked child to a temp file we created.
191
189
  def fork_worker_payload(status, out_path)
@@ -20,8 +20,7 @@ module Rigor
20
20
 
21
21
  module_function
22
22
 
23
- # @param finding [#location]
24
- # @return [Array(String, Integer)] `[path, line]`
23
+ # @return `[path, line]`
25
24
  def of(finding)
26
25
  location = finding.location
27
26
  return [CONFIG_PATH, 1] if location.nil?