rigortype 0.4.6 → 0.4.8

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 (550) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/data/core_overlay/bigdecimal.rbs +33 -0
  4. data/data/core_overlay/resolv.rbs +30 -0
  5. data/data/gem_overlay/activesupport/core_ext.rbs +45 -13
  6. data/data/gem_overlay/addressable/addressable.rbs +40 -0
  7. data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
  8. data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
  9. data/docs/handbook/01-getting-started.md +6 -3
  10. data/docs/handbook/11-sig-gen.md +85 -3
  11. data/docs/handbook/appendix-phpstan.md +4 -4
  12. data/docs/install.md +20 -0
  13. data/docs/manual/01-installation.md +67 -26
  14. data/docs/manual/02-cli-reference.md +455 -113
  15. data/docs/manual/03-configuration.md +76 -5
  16. data/docs/manual/04-diagnostics.md +5 -4
  17. data/docs/manual/06-baseline.md +6 -4
  18. data/docs/manual/08-skills.md +11 -0
  19. data/docs/manual/09-editor-integration.md +21 -2
  20. data/docs/manual/10-mcp-server.md +38 -2
  21. data/docs/manual/12-caching.md +4 -3
  22. data/docs/manual/14-rails-quickstart.md +1 -1
  23. data/docs/manual/19-effect-labels.md +3 -4
  24. data/docs/manual/plugins/rigor-actionpack.md +32 -15
  25. data/docs/manual/plugins/rigor-activesupport-core-ext.md +23 -1
  26. data/docs/manual/plugins/rigor-sorbet.md +17 -3
  27. data/lib/rigor/analysis/baseline.rb +24 -27
  28. data/lib/rigor/analysis/check_rules/always_raises_shield.rb +147 -0
  29. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
  30. data/lib/rigor/analysis/check_rules/call_facts.rb +58 -0
  31. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
  32. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +12 -4
  33. data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
  34. data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +85 -13
  35. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +16 -4
  36. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +6 -1
  37. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
  38. data/lib/rigor/analysis/check_rules/plugin_api_surface.rb +195 -0
  39. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +41 -12
  40. data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +27 -1
  41. data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +3 -3
  42. data/lib/rigor/analysis/check_rules/replaced_singleton_defs.rb +96 -0
  43. data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
  44. data/lib/rigor/analysis/check_rules/rule_ids.rb +9 -2
  45. data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
  46. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
  47. data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
  48. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +2 -2
  49. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +2 -2
  50. data/lib/rigor/analysis/check_rules.rb +720 -141
  51. data/lib/rigor/analysis/crash_signature.rb +45 -3
  52. data/lib/rigor/analysis/dependency_recorder.rb +237 -80
  53. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
  54. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
  55. data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
  56. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  57. data/lib/rigor/analysis/edit_replay.rb +93 -6
  58. data/lib/rigor/analysis/fact_store.rb +3 -3
  59. data/lib/rigor/analysis/incremental.rb +11 -1
  60. data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +4 -3
  61. data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
  62. data/lib/rigor/analysis/incremental_session.rb +306 -53
  63. data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -3
  64. data/lib/rigor/analysis/rule_catalog.rb +39 -3
  65. data/lib/rigor/analysis/run_cache_key.rb +27 -3
  66. data/lib/rigor/analysis/run_disclosure_credit.rb +26 -6
  67. data/lib/rigor/analysis/run_stats.rb +2 -2
  68. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -2
  69. data/lib/rigor/analysis/runner/declaration_position.rb +8 -8
  70. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +264 -112
  71. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +4 -9
  72. data/lib/rigor/analysis/runner/pool_coordinator.rb +173 -328
  73. data/lib/rigor/analysis/runner/project_pre_passes.rb +4 -37
  74. data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
  75. data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
  76. data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
  77. data/lib/rigor/analysis/runner.rb +298 -109
  78. data/lib/rigor/analysis/self_call_resolution_recorder.rb +62 -23
  79. data/lib/rigor/analysis/template_unit_positions.rb +2 -3
  80. data/lib/rigor/analysis/template_units.rb +9 -1
  81. data/lib/rigor/analysis/worker_session.rb +65 -71
  82. data/lib/rigor/bleeding_edge.rb +22 -10
  83. data/lib/rigor/builtins/imported_refinements.rb +6 -8
  84. data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
  85. data/lib/rigor/builtins/regex_refinement.rb +4 -6
  86. data/lib/rigor/cache/descriptor.rb +6 -5
  87. data/lib/rigor/cache/file_digest.rb +39 -31
  88. data/lib/rigor/cache/incremental_snapshot.rb +95 -17
  89. data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
  90. data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
  91. data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
  92. data/lib/rigor/cache/rbs_constant_table.rb +1 -1
  93. data/lib/rigor/cache/rbs_descriptor.rb +90 -4
  94. data/lib/rigor/cache/rbs_environment.rb +8 -1
  95. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
  96. data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
  97. data/lib/rigor/cache/store.rb +11 -10
  98. data/lib/rigor/ci_detector.rb +1 -1
  99. data/lib/rigor/cli/annotate_command.rb +24 -19
  100. data/lib/rigor/cli/baseline_command.rb +160 -57
  101. data/lib/rigor/cli/catalogue.rb +256 -0
  102. data/lib/rigor/cli/check_command.rb +112 -104
  103. data/lib/rigor/cli/check_runner_factory.rb +2 -2
  104. data/lib/rigor/cli/command.rb +15 -1
  105. data/lib/rigor/cli/coverage_command.rb +21 -8
  106. data/lib/rigor/cli/coverage_mutation.rb +5 -7
  107. data/lib/rigor/cli/coverage_renderer.rb +2 -1
  108. data/lib/rigor/cli/coverage_scan.rb +3 -5
  109. data/lib/rigor/cli/diff_command.rb +25 -20
  110. data/lib/rigor/cli/docs_command.rb +1 -2
  111. data/lib/rigor/cli/doctor_command.rb +12 -12
  112. data/lib/rigor/cli/effects_command.rb +50 -40
  113. data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
  114. data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
  115. data/lib/rigor/cli/effects_renderer.rb +2 -1
  116. data/lib/rigor/cli/effects_snapshot_command.rb +26 -18
  117. data/lib/rigor/cli/explain_command.rb +18 -8
  118. data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
  119. data/lib/rigor/cli/json_document.rb +41 -0
  120. data/lib/rigor/cli/lens_command.rb +29 -10
  121. data/lib/rigor/cli/lsp_command.rb +250 -23
  122. data/lib/rigor/cli/mcp_command.rb +12 -7
  123. data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
  124. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
  125. data/lib/rigor/cli/options.rb +40 -1
  126. data/lib/rigor/cli/plugin_command.rb +93 -46
  127. data/lib/rigor/cli/plugins_command.rb +17 -18
  128. data/lib/rigor/cli/plugins_renderer.rb +10 -6
  129. data/lib/rigor/cli/protection_fork_scan.rb +2 -2
  130. data/lib/rigor/cli/protection_renderer.rb +2 -1
  131. data/lib/rigor/cli/show_bleedingedge_command.rb +21 -15
  132. data/lib/rigor/cli/sig_gen_command.rb +92 -27
  133. data/lib/rigor/cli/skill_command.rb +32 -3
  134. data/lib/rigor/cli/skill_deep_probe.rb +1 -1
  135. data/lib/rigor/cli/skill_describe.rb +2 -1
  136. data/lib/rigor/cli/trace_command.rb +14 -9
  137. data/lib/rigor/cli/triage_command.rb +10 -11
  138. data/lib/rigor/cli/triage_renderer.rb +2 -1
  139. data/lib/rigor/cli/type_of_command.rb +16 -11
  140. data/lib/rigor/cli/type_of_project_scope.rb +1 -4
  141. data/lib/rigor/cli/type_of_renderer.rb +4 -1
  142. data/lib/rigor/cli/type_scan_command.rb +14 -9
  143. data/lib/rigor/cli/type_scan_renderer.rb +2 -1
  144. data/lib/rigor/cli/unused_command.rb +27 -17
  145. data/lib/rigor/cli/upgrade_command.rb +5 -0
  146. data/lib/rigor/cli.rb +214 -56
  147. data/lib/rigor/config_audit.rb +33 -19
  148. data/lib/rigor/configuration/severity_profile.rb +14 -5
  149. data/lib/rigor/configuration.rb +104 -35
  150. data/lib/rigor/effects/collector.rb +53 -21
  151. data/lib/rigor/effects/definition_context.rb +0 -2
  152. data/lib/rigor/effects/envelope.rb +1 -1
  153. data/lib/rigor/effects/framework_units.rb +1 -1
  154. data/lib/rigor/effects/mutation_classifier.rb +4 -7
  155. data/lib/rigor/effects/propagator.rb +1 -1
  156. data/lib/rigor/effects/registry.rb +2 -2
  157. data/lib/rigor/effects/snapshot.rb +1 -1
  158. data/lib/rigor/effects/taint_cause.rb +0 -2
  159. data/lib/rigor/effects/unit_scan.rb +9 -13
  160. data/lib/rigor/environment/bundle_sig_discovery.rb +64 -33
  161. data/lib/rigor/environment/class_registry.rb +3 -3
  162. data/lib/rigor/environment/constant_type_cache_holder.rb +5 -0
  163. data/lib/rigor/environment/core_root.rb +77 -0
  164. data/lib/rigor/environment/default_libraries.rb +18 -1
  165. data/lib/rigor/environment/deferred_signature_plan.rb +381 -0
  166. data/lib/rigor/environment/gated_signature_guard.rb +1 -1
  167. data/lib/rigor/environment/gated_signature_plan.rb +5 -2
  168. data/lib/rigor/environment/hkt_registry_holder.rb +6 -0
  169. data/lib/rigor/environment/lockfile_resolver.rb +28 -12
  170. data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
  171. data/lib/rigor/environment/member_consistency.rb +56 -7
  172. data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
  173. data/lib/rigor/environment/project_path_gems.rb +124 -0
  174. data/lib/rigor/environment/rbs_collection_discovery.rb +123 -8
  175. data/lib/rigor/environment/rbs_coverage_report.rb +12 -11
  176. data/lib/rigor/environment/rbs_hierarchy.rb +12 -15
  177. data/lib/rigor/environment/rbs_loader.rb +772 -110
  178. data/lib/rigor/environment/reflection.rb +7 -7
  179. data/lib/rigor/environment/required_features.rb +0 -3
  180. data/lib/rigor/environment/ruby_library_roots.rb +1 -1
  181. data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
  182. data/lib/rigor/environment.rb +169 -42
  183. data/lib/rigor/flow_contribution/merger.rb +4 -4
  184. data/lib/rigor/inference/acceptance.rb +136 -40
  185. data/lib/rigor/inference/alias_mutation_floor/foreign_locals.rb +117 -0
  186. data/lib/rigor/inference/alias_mutation_floor/memos.rb +85 -0
  187. data/lib/rigor/inference/alias_mutation_floor/reach.rb +119 -0
  188. data/lib/rigor/inference/alias_mutation_floor/site_collector.rb +252 -0
  189. data/lib/rigor/inference/alias_mutation_floor.rb +339 -0
  190. data/lib/rigor/inference/anonymous_meta_class.rb +18 -0
  191. data/lib/rigor/inference/block_auto_splat.rb +1 -1
  192. data/lib/rigor/inference/block_parameter_binder.rb +2 -3
  193. data/lib/rigor/inference/block_run_count.rb +185 -0
  194. data/lib/rigor/inference/budget_trace.rb +8 -2
  195. data/lib/rigor/inference/builtins/array_catalog.rb +2 -2
  196. data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
  197. data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
  198. data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
  199. data/lib/rigor/inference/callee_mutation_chain.rb +88 -77
  200. data/lib/rigor/inference/callee_write_census.rb +815 -0
  201. data/lib/rigor/inference/captured_locals.rb +2 -0
  202. data/lib/rigor/inference/census_foreign_block.rb +354 -0
  203. data/lib/rigor/inference/clause_widening.rb +1 -1
  204. data/lib/rigor/inference/closure_escape_analyzer.rb +11 -4
  205. data/lib/rigor/inference/construction_escape.rb +258 -0
  206. data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
  207. data/lib/rigor/inference/declaration_walk.rb +4 -0
  208. data/lib/rigor/inference/deep_erasure.rb +39 -7
  209. data/lib/rigor/inference/def_handle.rb +1 -1
  210. data/lib/rigor/inference/def_node_resolver.rb +33 -15
  211. data/lib/rigor/inference/def_return_typer.rb +47 -5
  212. data/lib/rigor/inference/definer_resolution.rb +19 -9
  213. data/lib/rigor/inference/definers_index.rb +162 -0
  214. data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
  215. data/lib/rigor/inference/element_read_widening.rb +49 -3
  216. data/lib/rigor/inference/error_info.rb +16 -0
  217. data/lib/rigor/inference/expression_typer.rb +1559 -320
  218. data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
  219. data/lib/rigor/inference/flow_tracer.rb +31 -14
  220. data/lib/rigor/inference/fork_map.rb +3 -0
  221. data/lib/rigor/inference/fresh_frame_blocks.rb +52 -1
  222. data/lib/rigor/inference/global_write_census.rb +81 -5
  223. data/lib/rigor/inference/global_writer_reach.rb +260 -0
  224. data/lib/rigor/inference/hkt_body.rb +1 -2
  225. data/lib/rigor/inference/hkt_body_parser.rb +3 -5
  226. data/lib/rigor/inference/hkt_reducer.rb +2 -2
  227. data/lib/rigor/inference/hkt_registry.rb +3 -5
  228. data/lib/rigor/inference/in_effect_refinements.rb +7 -0
  229. data/lib/rigor/inference/indexed_narrowing.rb +61 -15
  230. data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
  231. data/lib/rigor/inference/ivar_writer_census.rb +154 -8
  232. data/lib/rigor/inference/key_presence_guard.rb +51 -24
  233. data/lib/rigor/inference/last_line/self_evidence.rb +30 -0
  234. data/lib/rigor/inference/last_line.rb +5 -2
  235. data/lib/rigor/inference/loop_value_record.rb +66 -14
  236. data/lib/rigor/inference/match_rebinding/frame.rb +57 -0
  237. data/lib/rigor/inference/match_rebinding/yielding_match.rb +101 -0
  238. data/lib/rigor/inference/match_rebinding.rb +28 -5
  239. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
  240. data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
  241. data/lib/rigor/inference/method_dispatcher/block_folding.rb +44 -30
  242. data/lib/rigor/inference/method_dispatcher/class_keyed_block_params.rb +65 -0
  243. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +3 -3
  244. data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
  245. data/lib/rigor/inference/method_dispatcher/core_enumerable_receiver.rb +44 -0
  246. data/lib/rigor/inference/method_dispatcher/declared_constructor.rb +151 -0
  247. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +1 -1
  248. data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +2 -2
  249. data/lib/rigor/inference/method_dispatcher/interface_shape.rb +181 -0
  250. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
  251. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +1 -1
  252. data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
  253. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +51 -27
  254. data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
  255. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +606 -78
  256. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
  257. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
  258. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +3 -3
  259. data/lib/rigor/inference/method_dispatcher/set_folding.rb +9 -7
  260. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +467 -84
  261. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
  262. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
  263. data/lib/rigor/inference/method_dispatcher/singleton_type_params.rb +104 -0
  264. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
  265. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
  266. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  267. data/lib/rigor/inference/method_dispatcher.rb +123 -25
  268. data/lib/rigor/inference/method_parameter_binder.rb +136 -56
  269. data/lib/rigor/inference/module_function_state/spellings.rb +2 -2
  270. data/lib/rigor/inference/module_function_state.rb +24 -3
  271. data/lib/rigor/inference/multi_target_binder.rb +2 -2
  272. data/lib/rigor/inference/mutation_rejoin.rb +240 -4
  273. data/lib/rigor/inference/mutation_widening.rb +199 -29
  274. data/lib/rigor/inference/narrowing.rb +238 -50
  275. data/lib/rigor/inference/operand_effects.rb +43 -2
  276. data/lib/rigor/inference/optimistic_origin.rb +134 -9
  277. data/lib/rigor/inference/origin_lookup.rb +1 -1
  278. data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
  279. data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
  280. data/lib/rigor/inference/pre_eval_constants.rb +1 -1
  281. data/lib/rigor/inference/precision_scanner.rb +1 -1
  282. data/lib/rigor/inference/project_method_ownership.rb +30 -9
  283. data/lib/rigor/inference/project_patched_methods.rb +65 -13
  284. data/lib/rigor/inference/project_patched_scanner.rb +120 -25
  285. data/lib/rigor/inference/project_patched_visibility.rb +39 -3
  286. data/lib/rigor/inference/project_yielder.rb +11 -17
  287. data/lib/rigor/inference/rbs_type_translator.rb +68 -15
  288. data/lib/rigor/inference/receiver_alias.rb +20 -0
  289. data/lib/rigor/inference/receiver_writer_call.rb +67 -0
  290. data/lib/rigor/inference/recursion_rebinding.rb +157 -0
  291. data/lib/rigor/inference/refined_dispatch/constructed_class.rb +57 -17
  292. data/lib/rigor/inference/refined_dispatch/own_method.rb +51 -16
  293. data/lib/rigor/inference/refined_dispatch.rb +13 -0
  294. data/lib/rigor/inference/reflective_ivar_write.rb +19 -11
  295. data/lib/rigor/inference/remover_holder_scan.rb +287 -0
  296. data/lib/rigor/inference/remover_narrowing.rb +224 -0
  297. data/lib/rigor/inference/rewrite_mutation.rb +53 -2
  298. data/lib/rigor/inference/scope_indexer/certainty.rb +0 -1
  299. data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +13 -6
  300. data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
  301. data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +70 -26
  302. data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
  303. data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
  304. data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +295 -0
  305. data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +136 -9
  306. data/lib/rigor/inference/scope_indexer.rb +2213 -226
  307. data/lib/rigor/inference/self_call_ivar_writes.rb +103 -12
  308. data/lib/rigor/inference/self_preserving_block.rb +87 -0
  309. data/lib/rigor/inference/set_mutation.rb +189 -0
  310. data/lib/rigor/inference/singleton_hook_decline.rb +42 -8
  311. data/lib/rigor/inference/singleton_object_constant.rb +32 -2
  312. data/lib/rigor/inference/statement_evaluator.rb +3268 -358
  313. data/lib/rigor/inference/string_mutation.rb +14 -0
  314. data/lib/rigor/inference/struct_fold_safety.rb +4 -6
  315. data/lib/rigor/inference/synthetic_method_scanner.rb +40 -17
  316. data/lib/rigor/inference/toplevel_def_census.rb +67 -0
  317. data/lib/rigor/inference/unknown_store_widening.rb +103 -4
  318. data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
  319. data/lib/rigor/inference/untyped_rejoin.rb +1 -1
  320. data/lib/rigor/inference/void_tail_summary.rb +29 -9
  321. data/lib/rigor/language_server/buffer_table.rb +3 -3
  322. data/lib/rigor/language_server/completion_provider.rb +26 -20
  323. data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
  324. data/lib/rigor/language_server/diagnostic_publisher.rb +8 -3
  325. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  326. data/lib/rigor/language_server/folding_range_provider.rb +1 -2
  327. data/lib/rigor/language_server/hover_provider.rb +1 -7
  328. data/lib/rigor/language_server/hover_renderer.rb +6 -8
  329. data/lib/rigor/language_server/project_context.rb +39 -1
  330. data/lib/rigor/language_server/publish_batcher.rb +3 -4
  331. data/lib/rigor/language_server/selection_range_provider.rb +2 -4
  332. data/lib/rigor/language_server/server.rb +7 -3
  333. data/lib/rigor/language_server/signature_help_provider.rb +4 -4
  334. data/lib/rigor/lens/claims/comparison.rb +78 -0
  335. data/lib/rigor/lens/claims/request.rb +131 -0
  336. data/lib/rigor/lens/claims/type_reader.rb +216 -0
  337. data/lib/rigor/lens/claims.rb +208 -0
  338. data/lib/rigor/lens/contract_reader.rb +5 -0
  339. data/lib/rigor/lens/document.rb +1 -1
  340. data/lib/rigor/lens/file_reader.rb +21 -8
  341. data/lib/rigor/lens/plugins.rb +1 -1
  342. data/lib/rigor/lens/run.rb +8 -0
  343. data/lib/rigor/lens.rb +1 -1
  344. data/lib/rigor/library_probe.rb +68 -0
  345. data/lib/rigor/mcp/server.rb +73 -2
  346. data/lib/rigor/mcp.rb +1 -1
  347. data/lib/rigor/memo_audit.rb +282 -0
  348. data/lib/rigor/plugin/access_denied_error.rb +1 -2
  349. data/lib/rigor/plugin/base.rb +15 -2
  350. data/lib/rigor/plugin/bundled_catalog.rb +1 -12
  351. data/lib/rigor/plugin/io_boundary.rb +26 -4
  352. data/lib/rigor/plugin/loader.rb +25 -8
  353. data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
  354. data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
  355. data/lib/rigor/plugin/manifest.rb +16 -16
  356. data/lib/rigor/plugin/registry.rb +16 -5
  357. data/lib/rigor/plugin/services.rb +2 -3
  358. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
  359. data/lib/rigor/plugin/trust_policy.rb +48 -2
  360. data/lib/rigor/plugin/type_node_resolver.rb +2 -4
  361. data/lib/rigor/plugin.rb +6 -8
  362. data/lib/rigor/plugin_gap_advisory.rb +5 -1
  363. data/lib/rigor/project_environment.rb +16 -2
  364. data/lib/rigor/protection/analysis_guard.rb +1 -1
  365. data/lib/rigor/protection/discovery_seed.rb +44 -5
  366. data/lib/rigor/protection/mutation_cache.rb +4 -1
  367. data/lib/rigor/protection/mutator.rb +1 -1
  368. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  369. data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
  370. data/lib/rigor/rbs_extended/reporter.rb +27 -3
  371. data/lib/rigor/rbs_extended.rb +2 -3
  372. data/lib/rigor/reflection/constant_ancestors.rb +81 -22
  373. data/lib/rigor/reflection/declaration_collectors.rb +55 -0
  374. data/lib/rigor/reflection/declarations.rb +58 -0
  375. data/lib/rigor/reflection/project_method.rb +177 -0
  376. data/lib/rigor/reflection.rb +2 -0
  377. data/lib/rigor/rooted_glob.rb +32 -1
  378. data/lib/rigor/run_scoped_slots.rb +38 -0
  379. data/lib/rigor/runtime/jit.rb +1 -1
  380. data/lib/rigor/scope/discovery_index.rb +168 -8
  381. data/lib/rigor/scope/resolution_chain/relevance.rb +14 -1
  382. data/lib/rigor/scope/resolution_chain.rb +901 -54
  383. data/lib/rigor/scope.rb +644 -37
  384. data/lib/rigor/sig_gen/bot_proposal_guard.rb +306 -0
  385. data/lib/rigor/sig_gen/classification.rb +18 -1
  386. data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
  387. data/lib/rigor/sig_gen/generator.rb +588 -66
  388. data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
  389. data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
  390. data/lib/rigor/sig_gen/layout_index.rb +3 -3
  391. data/lib/rigor/sig_gen/method_candidate.rb +37 -4
  392. data/lib/rigor/sig_gen/observation_collector.rb +14 -7
  393. data/lib/rigor/sig_gen/observed_call.rb +1 -1
  394. data/lib/rigor/sig_gen/path_mapper.rb +6 -0
  395. data/lib/rigor/sig_gen/platform_guarded_files.rb +184 -0
  396. data/lib/rigor/sig_gen/renderer.rb +15 -9
  397. data/lib/rigor/sig_gen/skip_reason_catalog.rb +62 -2
  398. data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
  399. data/lib/rigor/sig_gen/write_reporter.rb +63 -14
  400. data/lib/rigor/sig_gen/write_result.rb +23 -12
  401. data/lib/rigor/sig_gen/writer.rb +238 -37
  402. data/lib/rigor/sig_gen.rb +1 -0
  403. data/lib/rigor/source/forwardable_delegators.rb +122 -0
  404. data/lib/rigor/source/node_children.rb +13 -0
  405. data/lib/rigor/type/acceptance_router.rb +2 -2
  406. data/lib/rigor/type/accepts_result.rb +1 -1
  407. data/lib/rigor/type/app.rb +4 -6
  408. data/lib/rigor/type/combinator.rb +173 -21
  409. data/lib/rigor/type/constant.rb +4 -5
  410. data/lib/rigor/type/hash_shape.rb +21 -40
  411. data/lib/rigor/type/interface.rb +60 -0
  412. data/lib/rigor/type/union.rb +1 -1
  413. data/lib/rigor/type.rb +1 -0
  414. data/lib/rigor/type_node/identifier.rb +1 -2
  415. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  416. data/lib/rigor/type_node/string_literal.rb +1 -2
  417. data/lib/rigor/type_node/symbol_literal.rb +1 -2
  418. data/lib/rigor/type_node/union.rb +3 -6
  419. data/lib/rigor/type_of_memo/serving.rb +99 -0
  420. data/lib/rigor/type_of_memo/stats.rb +43 -0
  421. data/lib/rigor/type_of_memo.rb +337 -0
  422. data/lib/rigor/typing_state.rb +1094 -0
  423. data/lib/rigor/value_semantics.rb +1 -10
  424. data/lib/rigor/version.rb +1 -1
  425. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
  426. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
  427. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
  428. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +38 -36
  429. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
  430. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -4
  431. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
  432. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
  433. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
  434. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
  435. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +3 -3
  436. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +115 -36
  437. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +3 -6
  438. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +25 -1
  439. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
  440. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +16 -6
  441. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +4 -2
  442. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -3
  443. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -1
  444. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
  445. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
  446. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
  447. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
  448. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +132 -33
  449. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +20 -6
  450. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +7 -4
  451. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +54 -17
  452. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +19 -5
  453. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
  454. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
  455. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +11 -14
  456. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
  457. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
  458. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
  459. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +30 -9
  460. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +55 -13
  461. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +15 -21
  462. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +1 -6
  463. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
  464. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
  465. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
  466. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
  467. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +1 -1
  468. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
  469. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
  470. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
  471. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
  472. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
  473. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
  474. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
  475. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +8 -7
  476. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
  477. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
  478. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +12 -2
  479. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
  480. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
  481. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +8 -2
  482. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
  483. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
  484. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
  485. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
  486. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
  487. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +200 -4
  488. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
  489. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
  490. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
  491. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +4 -3
  492. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
  493. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +5 -5
  494. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
  495. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
  496. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
  497. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +3 -2
  498. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
  499. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
  500. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +210 -3
  501. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +146 -7
  502. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
  503. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +52 -34
  504. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +97 -24
  505. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
  506. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +16 -16
  507. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +4 -8
  508. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
  509. data/sig/rigor/analysis/baseline.rbs +0 -3
  510. data/sig/rigor/analysis/check_rules/rule_walk.rbs +6 -0
  511. data/sig/rigor/analysis/fact_store.rbs +2 -2
  512. data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
  513. data/sig/rigor/cache/descriptor.rbs +14 -0
  514. data/sig/rigor/cli/diff_command.rbs +1 -1
  515. data/sig/rigor/cli/explain_command.rbs +1 -1
  516. data/sig/rigor/effects/registry.rbs +2 -2
  517. data/sig/rigor/environment.rbs +4 -1
  518. data/sig/rigor/inference.rbs +4 -1
  519. data/sig/rigor/plugin/additional_initializer.rbs +0 -5
  520. data/sig/rigor/plugin/base.rbs +53 -18
  521. data/sig/rigor/plugin/effect_attribution.rbs +3 -3
  522. data/sig/rigor/plugin/effect_edge.rbs +1 -1
  523. data/sig/rigor/plugin/effect_entry_points.rbs +3 -3
  524. data/sig/rigor/plugin/interfaces.rbs +51 -0
  525. data/sig/rigor/plugin/io_boundary.rbs +3 -3
  526. data/sig/rigor/plugin/manifest.rbs +9 -9
  527. data/sig/rigor/plugin/node_context.rbs +21 -0
  528. data/sig/rigor/plugin/protocol_contract.rbs +3 -7
  529. data/sig/rigor/reflection.rbs +37 -0
  530. data/sig/rigor/scope.rbs +43 -4
  531. data/sig/rigor/trinary.rbs +1 -0
  532. data/sig/rigor/type.rbs +9 -3
  533. data/sig/rigor.rbs +3 -2
  534. data/skills/rigor-ask/SKILL.md +1 -0
  535. data/skills/rigor-plugin-author/SKILL.md +4 -4
  536. data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
  537. data/skills/rigor-plugin-review/SKILL.md +3 -3
  538. data/skills/rigor-project-init/references/01-detect.md +1 -0
  539. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +17 -2
  540. data/skills/rigor-project-init/references/06-agent-contract.md +4 -4
  541. data/skills/rigor-rbs-contract/SKILL.md +147 -0
  542. data/skills/rigor-rbs-contract/references/01-finding-candidates.md +212 -0
  543. data/skills/rigor-rbs-contract/references/02-contract-rules.md +157 -0
  544. data/skills/rigor-rbs-contract/references/03-target-own-code.md +90 -0
  545. data/skills/rigor-rbs-contract/references/04-target-gem-rbs-collection.md +210 -0
  546. data/skills/rigor-rbs-contract/references/05-declaration-mutants.md +182 -0
  547. data/skills/rigor-rbs-setup/SKILL.md +3 -1
  548. data/skills/rigor-type-oracle/SKILL.md +26 -1
  549. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +4 -3
  550. metadata +82 -3
@@ -11,7 +11,7 @@ module Rigor
11
11
  # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`), and `initialize`
12
12
  # stores the result of the private `validate_receiver!` helper (#2312).
13
13
  attr_reader receiver: String
14
- # sig-gen gap: #2321 — `method:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
14
+ # sig-gen gap: #2325 — `method:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
15
15
  # intent tracked by #2325, and only then does this row generate; coercion-facing: `String | Symbol | nil`),
16
16
  # stored as `method&.to_sym`.
17
17
  attr_reader method: Symbol?
@@ -4,15 +4,15 @@ module Rigor
4
4
  # framework entry points (ADR-103 WD6). Frozen value object; {#globs} are deduplicated and
5
5
  # sorted in `initialize`.
6
6
  class EffectEntryPoints
7
- # sig-gen gap: #2321 — `initialize` declares `name:` `untyped` (input `untyped`, looks deliberate; a declared
7
+ # sig-gen gap: #2325 — `initialize` declares `name:` `untyped` (input `untyped`, looks deliberate; a declared
8
8
  # type is authoring intent tracked by #2325, and only then does this row generate; coercion-facing: it takes
9
9
  # anything that answers `to_s`), so no input type reaches the reader.
10
10
  attr_reader name: String
11
- # sig-gen gap: #2321 — `globs:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
11
+ # sig-gen gap: #2325 — `globs:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
12
12
  # intent tracked by #2325, and only then does this row generate; coercion-facing: `Array(globs)`, each `to_s`),
13
13
  # deduplicated and sorted in `initialize`.
14
14
  attr_reader globs: Array[String]
15
- # sig-gen gap: #2321 — `why:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
15
+ # sig-gen gap: #2325 — `why:` is `untyped` (input `untyped`, looks deliberate; a declared type is authoring
16
16
  # intent tracked by #2325, and only then does this row generate; coercion-facing: `to_s`).
17
17
  attr_reader why: String
18
18
 
@@ -0,0 +1,51 @@
1
+ # ADR-128 — the plugin-facing structural interfaces: what a hook may call on the engine objects it receives.
2
+ #
3
+ # The criterion (ADR-128): a method is public plugin API only if it is declared on `Plugin::Base`, on one of the
4
+ # interfaces below, or in a namespace `docs/internal-spec/public-api.md` lists as public. Being reachable at
5
+ # runtime does not make a method public. `spec/rigor/plugin_boundary_spec.rb` gates the bundled plugins against
6
+ # these member lists, so adding a member here is an API promise, and `public_api_drift_spec.rb` pins the sets.
7
+ #
8
+ # Each interface is backed by a concrete engine class (the `BACKING` table in `spec/support/plugin_boundary.rb`).
9
+ # Engine signatures keep those concrete classes (ADR-128 WD5); an interface appears only at a plugin-facing
10
+ # position, in `base.rbs`.
11
+ module Rigor
12
+ module Plugin
13
+ # The scope a hook receives. Backed by `Rigor::Scope`, which has far more members (about 200); only these are
14
+ # promised. `environment` is non-nil, matching `Scope#environment`.
15
+ interface _Scope
16
+ def type_of: (::Prism::Node node) -> Rigor::Type::t
17
+ def self_type: () -> Rigor::Type::t?
18
+ def local: (String | Symbol name) -> Rigor::Type::t?
19
+ def source_path: () -> String?
20
+ def with_local: (String | Symbol name, Rigor::Type::t type) -> Rigor::Plugin::_Scope
21
+ def environment: () -> Rigor::Plugin::_Environment
22
+ end
23
+
24
+ # The project's RBS and class-registry handle, backed by `Rigor::Environment`.
25
+ interface _Environment
26
+ def nominal_for_name: (String | Symbol name) -> Rigor::Type::Nominal?
27
+ def rbs_module?: (String | Symbol name) -> bool
28
+ end
29
+
30
+ # The services container `Plugin::Base#init` / `#prepare` receive, backed by `Rigor::Plugin::Services`.
31
+ # `reflection` and `type` are public namespaces (`Rigor::Reflection`, `Rigor::Type::Combinator`) that a plugin
32
+ # also reaches by constant, so they are typed as those modules rather than narrowed to an interface.
33
+ interface _Services
34
+ def fact_store: () -> Rigor::Plugin::_FactStore
35
+ def configuration: () -> Rigor::Plugin::_Configuration
36
+ def reflection: () -> singleton(Rigor::Reflection)
37
+ def type: () -> singleton(Rigor::Type::Combinator)
38
+ end
39
+
40
+ # The per-run cross-plugin fact store, backed by `Rigor::Plugin::FactStore`.
41
+ interface _FactStore
42
+ def publish: (plugin_id: String | Symbol, name: Symbol, value: untyped) -> nil
43
+ def read: (plugin_id: String | Symbol, name: Symbol) -> untyped
44
+ end
45
+
46
+ # The project configuration, backed by `Rigor::Configuration`.
47
+ interface _Configuration
48
+ def paths: () -> Array[String]
49
+ end
50
+ end
51
+ end
@@ -4,7 +4,7 @@ class Rigor::Plugin::IoBoundary
4
4
  def file?: (untyped) -> bool
5
5
  def directory?: (untyped) -> bool
6
6
  def list_directory: (untyped) -> Array[String]
7
- def list_directory_kinds: (untyped) -> Hash[String, untyped]
7
+ def list_directory_kinds: (untyped) -> Hash[String, Symbol]
8
8
  # Records a `:names` glob row (membership only); a caller needing a match's content `read_file`s it. A `..`
9
9
  # segment, a brace or a backslash in `pattern` raises `AccessDeniedError`.
10
10
  def glob: (untyped root, untyped pattern) -> Array[String]
@@ -14,7 +14,7 @@ class Rigor::Plugin::IoBoundary
14
14
  # whose parameter is undeclared.
15
15
  def refusal_summary: () -> { count: Integer, first_path: String?, nearest_root: String? }?
16
16
  def open_url: (untyped url) -> String
17
- # Returns a frozen `Rigor::Cache::Descriptor` (no RBS yet -> untyped).
18
- def cache_descriptor: () -> untyped
17
+ # The returned descriptor is frozen.
18
+ def cache_descriptor: () -> Rigor::Cache::Descriptor
19
19
  def replay: (untyped descriptor) -> nil
20
20
  end
@@ -18,7 +18,7 @@ class Rigor::Plugin::Manifest
18
18
  def config_schema: () -> untyped
19
19
  def config_defaults: () -> Hash[String, untyped]
20
20
  def target_gems: () -> Array[String]
21
- # sig-gen gap: #2321 — written by a private `assign_*` helper whose parameters are undeclared (`initialize` hands
21
+ # sig-gen gap: #2418 — written by a private `assign_*` helper whose parameters are undeclared (`initialize` hands
22
22
  # its fields to such helpers); each write is a derived expression (`dup.freeze`, `map`), so the helper's parameter
23
23
  # types alone would not generate it.
24
24
  def template_globs: () -> Array[String]
@@ -35,31 +35,31 @@ class Rigor::Plugin::Manifest
35
35
  def hkt_registrations: () -> untyped
36
36
  def hkt_definitions: () -> untyped
37
37
  def signature_paths: () -> Array[String]
38
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_protocol_contracts!` requires every element
38
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_protocol_contracts!` requires every element
39
39
  # `is_a?(ProtocolContract)`.
40
40
  def protocol_contracts: () -> Array[Rigor::Plugin::ProtocolContract]
41
41
  # ADR-32 WD6/WD12 — any object responding to `call`, and its result is a documented multi-shape
42
42
  # outcome (`String` / nil / `[:error, msg]` / `[:ok, src, msgs]`), not `String?` — `untyped` is the
43
43
  # honest claim until the outcome has a sig'd shape.
44
44
  def source_rbs_synthesizer: () -> untyped
45
- # sig-gen gap: #2321 — same shape as `template_globs`: the validator (`validate_additional_initializers!`) requires
45
+ # sig-gen gap: #2418 — same shape as `template_globs`: the validator (`validate_additional_initializers!`) requires
46
46
  # every element `is_a?(AdditionalInitializer)`, so the element type is hand-written.
47
47
  def additional_initializers: () -> Array[Rigor::Plugin::AdditionalInitializer]
48
48
 
49
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_root!` bounds the spelling.
49
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_effect_root!` bounds the spelling.
50
50
  def effect_root: () -> String?
51
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_labels!` requires non-empty `String`
51
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_effect_labels!` requires non-empty `String`
52
52
  # elements.
53
53
  def effect_labels: () -> Array[String]
54
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_attributions!` requires every element
54
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_effect_attributions!` requires every element
55
55
  # `is_a?(EffectAttribution)`.
56
56
  def effect_attributions: () -> Array[Rigor::Plugin::EffectAttribution]
57
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_edges!` requires `is_a?(EffectEdge)`.
57
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_effect_edges!` requires `is_a?(EffectEdge)`.
58
58
  def effect_edges: () -> Array[Rigor::Plugin::EffectEdge]
59
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_entry_points!` requires
59
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_effect_entry_points!` requires
60
60
  # `is_a?(EffectEntryPoints)`.
61
61
  def effect_entry_points: () -> Array[Rigor::Plugin::EffectEntryPoints]
62
- # sig-gen gap: #2321 — same shape as `template_globs`: `validate_effect_ancestry!` requires `is_a?(EffectAncestry)`.
62
+ # sig-gen gap: #2418 — same shape as `template_globs`: `validate_effect_ancestry!` requires `is_a?(EffectAncestry)`.
63
63
  def effect_ancestry: () -> Array[Rigor::Plugin::EffectAncestry]
64
64
 
65
65
  # The identity opening a root when this plugin's labels join the run's vocabulary: the
@@ -0,0 +1,21 @@
1
+ module Rigor
2
+ module Plugin
3
+ # ADR-37 slice 1d — the lexical context of a node, the fifth argument of a `node_rule` block.
4
+ class NodeContext
5
+ EMPTY: nil
6
+
7
+ attr_reader ancestors: Array[::Prism::Node]
8
+
9
+ def initialize: (Array[::Prism::Node] ancestors) -> void
10
+ # The three finders return the innermost ancestor of a given kind: a `DefNode`, a `ClassNode` or
11
+ # `ModuleNode`, and a `CallNode` respectively. `enclosing_def` is sig-gen's proposal (#2719, #2914); the other
12
+ # two blocks (`||`, `&&`) are not a single class test, so their bodies still infer `Prism::Node?`. A narrower
13
+ # declaration would be an unmarked sig-gen divergence (ADR-107).
14
+ # Known Steep 2.0.0 limitation (surfaced by `library "prism"`, #2718): it does not narrow `rfind` through an
15
+ # `is_a?` block, so it warns that the body is `Prism::Node?`; the declaration keeps the precise shape.
16
+ def enclosing_def: () -> (Prism::DefNode | nil)
17
+ def enclosing_module: () -> ::Prism::Node?
18
+ def enclosing_block: (Symbol method_name) -> ::Prism::Node?
19
+ end
20
+ end
21
+ end
@@ -23,11 +23,8 @@ module Rigor
23
23
  def self.[]: (index: Integer, type_name: String) -> instance | (Integer index, String type_name) -> instance
24
24
  end
25
25
 
26
- # sig-gen gap: #2321 — `attr_reader` rows over ivars `initialize` assigns from expressions derived
27
- # from its parameters (`dup.freeze`/`to_sym`), so the stored types are hand-written.
28
26
  attr_reader path_glob: String
29
27
 
30
- # sig-gen gap: #2321 — as above (`to_sym` normalizes the accepted Symbol|String).
31
28
  attr_reader method_name: Symbol
32
29
 
33
30
  # `singleton ? true : false` collapses any truthy input to bool — sig-gen already infers
@@ -38,12 +35,11 @@ module Rigor
38
35
  # parameters are undeclared (it guarantees `Array[ParamType]`).
39
36
  attr_reader param_types: Array[ParamType]
40
37
 
41
- # sig-gen gap: #2321 — as above (nil or a non-empty `dup.freeze`d String).
42
38
  attr_reader return_type_name: String?
43
39
 
44
- # sig-gen gap: #2321 — as above (`VALID_SEVERITIES.include?(to_sym)` bounds the stored value
45
- # to the three declared literals; a derived-write credit would generate `Symbol`, not the literal union, so
46
- # this row needs the declared literals kept as intent).
40
+ # authored: the declared literal union is intent. `initialize` stores `severity.to_sym` after
41
+ # `validate_severity!` bounds it to `VALID_SEVERITIES`, so the value is one of the three literals, but sig-gen
42
+ # generates `Symbol` for it, not the union.
47
43
  attr_reader severity: :error | :warning | :info
48
44
 
49
45
  # `method_name`/`severity` accept String too (both are `to_sym`'d); `param_types` entries are
@@ -19,5 +19,42 @@ module Rigor
19
19
  def self?.class_type_param_names: (String | Symbol class_name, ?scope: Scope) -> Array[Symbol]
20
20
  def self?.discovered_class?: (String | Symbol class_name, ?scope: Scope) -> bool
21
21
  def self?.discovered_method?: (String | Symbol class_name, String | Symbol method_name, ?kind: Symbol, ?scope: Scope) -> bool
22
+ def self?.project_method_defined: (String | Symbol? class_name, String | Symbol method_name, kind: :instance | :singleton, source: :def | :discovered | :either, scope: Scope) -> Trinary
23
+ def self?.rbs_method_defined: (String | Symbol? class_name, String | Symbol method_name, kind: :instance | :singleton, scope: Scope) -> Trinary
24
+ def self?.ancestry_reaches: (String | Symbol? class_name, Array[String | Symbol] ancestor_names, kind: :instance | :singleton, scope: Scope) -> Trinary
25
+ # sig-gen gap: #2302 — the collector's `@classes = []` is grown by `<<`, so sig-gen reads the array as `Array[untyped]`.
26
+ def self?.class_declarations_in: (Prism::Node root) ?{ (DeclaredCall call) -> void } -> Array[ClassDeclaration]
27
+
28
+ # One `class` header of a parsed file, as `class_declarations_in` reports it.
29
+ class ClassDeclaration < Data
30
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so sig-gen proposes `untyped`; the shape is hand-written.
31
+ attr_reader name: String
32
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so sig-gen proposes `untyped`; the shape is hand-written.
33
+ attr_reader nesting: Array[String]
34
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so sig-gen proposes `untyped`; the shape is hand-written.
35
+ attr_reader node: Prism::ClassNode
36
+
37
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so the constructor's keywords are `untyped` in sig-gen.
38
+ def self.new: (name: String, nesting: Array[String], node: Prism::ClassNode) -> instance
39
+ | (String name, Array[String] nesting, Prism::ClassNode node) -> instance
40
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so the constructor's keywords are `untyped` in sig-gen.
41
+ def self.[]: (name: String, nesting: Array[String], node: Prism::ClassNode) -> instance
42
+ | (String name, Array[String] nesting, Prism::ClassNode node) -> instance
43
+ end
44
+
45
+ # One call `class_declarations_in` yields: the `Prism::CallNode` and the class or module it lexically sits in.
46
+ class DeclaredCall < Data
47
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so sig-gen proposes `untyped`; the shape is hand-written.
48
+ attr_reader node: Prism::CallNode
49
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so sig-gen proposes `untyped`; the shape is hand-written.
50
+ attr_reader owner: String?
51
+
52
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so the constructor's keywords are `untyped` in sig-gen.
53
+ def self.new: (node: Prism::CallNode, owner: String?) -> instance
54
+ | (Prism::CallNode node, String? owner) -> instance
55
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so the constructor's keywords are `untyped` in sig-gen.
56
+ def self.[]: (node: Prism::CallNode, owner: String?) -> instance
57
+ | (Prism::CallNode node, String? owner) -> instance
58
+ end
22
59
  end
23
60
  end
data/sig/rigor/scope.rbs CHANGED
@@ -18,6 +18,7 @@ module Rigor
18
18
  # its bare cause (issue #1302).
19
19
  attr_reader optimistic_locals: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark]
20
20
  attr_reader optimistic_ivars: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark]
21
+ attr_reader construction_facts: Hash[Symbol, Set[untyped]]
21
22
  attr_reader repeated_or_writes: Hash[untyped, bool]
22
23
  # sig-gen gap: #2323 — the same reader shape; `Inference::MatchRebinding::Frame` carries no signature.
23
24
  attr_reader match_frame: untyped
@@ -29,7 +30,7 @@ module Rigor
29
30
  attr_reader struct_fold_safe_locals: Set[Symbol]
30
31
  attr_reader opaque_block_self: bool
31
32
  # Issue #1759 — `:refinement` (REFINEMENT_BLOCK_SELF) directly in a `refine X do … end` block body.
32
- attr_reader block_self_unknown: bool | :refinement
33
+ attr_reader block_self_unknown: bool | :refinement | :preserved
33
34
  attr_reader singleton_class_body: bool
34
35
  attr_reader lexical_nesting: Array[String]?
35
36
  # Issue #1429 — a guard's narrowing of a constant reference, keyed by its spelling.
@@ -64,14 +65,24 @@ module Rigor
64
65
  # authored: the list holds module names and the `InEffectRefinements::UNKNOWN` Symbol; sig-gen reads the delegated
65
66
  # return through an unsigned class as untyped.
66
67
  def in_effect_refinements: (untyped node, ?Array[String] declared) -> Array[String | Symbol]
68
+ # authored: the element is an `Array` led by its Symbol kind by contract (`[:defines, name]`, `[:ivar_set, name]`); a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
69
+ # would never propose it.
67
70
  def discovered_global_write_census: () -> Set[Array[untyped]]
68
71
  def discovered_includes: () -> Hash[String, Array[String]]
69
72
  # Issue #1123 — the instance-ancestor-ORDER table beside the include one.
70
73
  def discovered_prepends: () -> Hash[String, Array[String]]
71
74
  def discovered_extends: () -> Hash[String, Array[String]]
75
+ # authored: the element is `String` (a source path) by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
76
+ # would never propose it.
72
77
  def discovered_class_sources: () -> Hash[String, Set[String]]
78
+ # authored: the element is `String` (a source path) by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
79
+ # would never propose it.
73
80
  def constant_sources: () -> Hash[String, Set[String]]
81
+ # authored: the element is `String` (a constant's last segment) by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
82
+ # would never propose it.
74
83
  def published_constant_names: () -> Set[String]
84
+ # authored: the element is `String` (a constant name) by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
85
+ # would never propose it.
75
86
  def local_constant_names: () -> Set[String]
76
87
  # sig-gen gap: #1150 — the `Data.define` table it reads carries no type, so sig-gen skips the return; the shape is hand-written.
77
88
  def bound_constant_names: (String name) -> Array[String]
@@ -89,6 +100,12 @@ module Rigor
89
100
  def run_generation: () -> Object?
90
101
  def record_dynamic_origin: (untyped node, Symbol cause) -> Scope
91
102
  def record_optimistic_origin: (untyped node, Symbol cause) -> Scope
103
+ # sig-gen gap: #2840 — the reader returns through a sentinel `equal?` guard over `Hash#fetch`; sig-gen emits nothing.
104
+ def dynamic_origin: (untyped node) -> Symbol?
105
+ # sig-gen gap: #2840 — the reader returns through a sentinel `equal?` guard over `Hash#fetch`; sig-gen emits nothing.
106
+ def optimistic_origin: (untyped node) -> Symbol?
107
+ # sig-gen gap: #2840 — the reader returns through a sentinel `equal?` guard over `Hash#fetch`; sig-gen emits nothing.
108
+ def void_origin: (untyped node) -> Inference::VoidOrigin?
92
109
 
93
110
  def record_void_origin: (untyped node, Inference::VoidOrigin origin) -> Scope
94
111
 
@@ -208,12 +225,16 @@ module Rigor
208
225
 
209
226
  def self.empty: (?environment: Environment, ?source_path: String?) -> Scope
210
227
 
211
- def initialize: (environment: Environment, locals: Hash[Symbol, Type::t], ?fact_store: Analysis::FactStore, ?self_type: Type::t?, ?ivars: Hash[Symbol, Type::t], ?cvars: Hash[Symbol, Type::t], ?globals: Hash[Symbol, Type::t], ?discovery: DiscoveryIndex, ?source_path: String?, ?opaque_block_self: bool, ?block_self_unknown: bool | :refinement, ?singleton_class_body: bool, ?dynamic_origins: Hash[untyped, Symbol], ?indexed_narrowings: Hash[IndexedKey, Type::t], ?method_chain_narrowings: Hash[ChainKey, Type::t], ?declaration_sourced: Set[[Symbol, Symbol] | [Symbol, Symbol, Symbol]], ?published_constant_sourced: Set[[Symbol, Symbol]], ?struct_fold_safe_locals: Set[Symbol], ?lexical_nesting: Array[String]?, ?local_origins: Hash[Symbol, Symbol], ?ivar_origins: Hash[Symbol, Symbol], ?void_origins: Hash[untyped, Inference::VoidOrigin], ?plugin_typed_calls: Hash[untyped, bool], ?optimistic_origins: Hash[untyped, Symbol], ?optimistic_locals: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark], ?optimistic_ivars: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark], ?repeated_or_writes: Hash[untyped, bool], ?match_frame: untyped, ?constant_narrowings: Hash[String, Type::t], ?guard_records: Hash[[Symbol, Symbol | String], Type::t], ?bot_guard_classes: Hash[[Symbol, Symbol | String], Array[String]], ?declared_refinements: Array[String | Symbol]) -> void
228
+ def initialize: (environment: Environment, locals: Hash[Symbol, Type::t], ?fact_store: Analysis::FactStore, ?self_type: Type::t?, ?ivars: Hash[Symbol, Type::t], ?cvars: Hash[Symbol, Type::t], ?globals: Hash[Symbol, Type::t], ?discovery: DiscoveryIndex, ?source_path: String?, ?opaque_block_self: bool, ?block_self_unknown: bool | :refinement | :preserved, ?singleton_class_body: bool, ?dynamic_origins: Hash[untyped, Symbol], ?indexed_narrowings: Hash[IndexedKey, Type::t], ?method_chain_narrowings: Hash[ChainKey, Type::t], ?declaration_sourced: Set[[Symbol, Symbol] | [Symbol, Symbol, Symbol]], ?published_constant_sourced: Set[[Symbol, Symbol]], ?struct_fold_safe_locals: Set[Symbol], ?lexical_nesting: Array[String]?, ?local_origins: Hash[Symbol, Symbol], ?ivar_origins: Hash[Symbol, Symbol], ?void_origins: Hash[untyped, Inference::VoidOrigin], ?plugin_typed_calls: Hash[untyped, bool], ?optimistic_origins: Hash[untyped, Symbol], ?optimistic_locals: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark], ?optimistic_ivars: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark], ?construction_facts: Hash[Symbol, Set[Symbol]], ?repeated_or_writes: Hash[untyped, bool], ?match_frame: untyped, ?constant_narrowings: Hash[String, Type::t], ?guard_records: Hash[[Symbol, Symbol | String], Type::t], ?bot_guard_classes: Hash[[Symbol, Symbol | String], Array[String]], ?declared_refinements: Array[String | Symbol]) -> void
212
229
  def with_source_path: (String? path) -> Scope
213
230
  def with_struct_fold_safe: (Set[Symbol] locals) -> Scope
214
231
  def with_lexical_nesting: (Array[String]? chain) -> Scope
215
232
  def struct_fold_safe?: (String | Symbol name) -> bool
233
+ def entering_block_without_gradual_marks: (Prism::Node block_node) -> Scope
216
234
  def entering_opaque_block: () -> Scope
235
+ PRESERVED_BLOCK_SELF: :preserved
236
+ def entering_self_preserving_block: () -> Scope
237
+ def walked_block_self_unknown?: () -> bool
217
238
  def block_self_unknown?: () -> bool
218
239
  REFINEMENT_BLOCK_SELF: :refinement
219
240
  def refinement_block_self?: () -> bool
@@ -229,10 +250,15 @@ module Rigor
229
250
  def global: (String | Symbol name) -> Type::t?
230
251
  def local_origin: (String | Symbol name) -> Symbol?
231
252
  def ivar_origin: (String | Symbol name) -> Symbol?
253
+ # sig-gen gap: #2403 — the `Hash#[]` miss in `bound_cause` is lost across the call; sig-gen says `Symbol`.
232
254
  def optimistic_local: (String | Symbol name) -> Symbol?
255
+ # sig-gen gap: #2403 — the `Hash#[]` miss in `bound_cause` is lost across the call; sig-gen says `Symbol`.
233
256
  def optimistic_ivar: (String | Symbol name) -> Symbol?
234
257
  def optimistic_local_miss: (String | Symbol name) -> Object?
235
258
  def optimistic_ivar_miss: (String | Symbol name) -> Object?
259
+ def construction_fact?: (String | Symbol name, ?Symbol fact) -> bool
260
+ def project_method_name?: (untyped) -> (false | true)
261
+ def with_construction_fact: (untyped, untyped) -> Rigor::Scope
236
262
  def with_local: (String | Symbol name, Type::t type) -> Scope
237
263
  def with_rejoined_locals: (untyped) -> Rigor::Scope
238
264
  def with_ivar: (String | Symbol name, Type::t type) -> Scope
@@ -271,8 +297,6 @@ module Rigor
271
297
  def seed_declaration_sourced_global: (String | Symbol name, Type::t type) -> Scope
272
298
  def with_global_copy_marks: (String | Symbol name, Array[String | Symbol] globals) -> Scope
273
299
  def without_local_declaration_marks: (String | Symbol name) -> Scope
274
- # sig-gen gap: #2322 — the records come out of `@declaration_sourced`, whose set now types; `ref[2]` reads as
275
- # `Symbol?`, but the `filter_map` over it answers `Array[untyped]`.
276
300
  def declaration_sourced_global_copies: (String | Symbol name) -> Array[Symbol]
277
301
  def with_declaration_sourced_local: (String | Symbol name, Type::t type) -> Scope
278
302
  def with_local_declaration_mark: (String | Symbol name) -> Scope
@@ -283,6 +307,9 @@ module Rigor
283
307
  def with_inferred_param_mark: (String | Symbol name) -> Scope
284
308
  def without_inferred_param_mark: (String | Symbol name) -> Scope
285
309
  def inferred_param?: (String | Symbol name) -> bool
310
+ def with_gradual_narrowing_mark: (String | Symbol name) -> Scope
311
+ def gradual_narrowing?: (String | Symbol name) -> bool
312
+ def gradual_narrowing_names: () -> Array[Symbol]
286
313
  def forget_match_globals: () -> Scope
287
314
  def untyped_match_globals: () -> Scope
288
315
  def match_globals_bound?: () -> bool
@@ -307,6 +334,13 @@ module Rigor
307
334
  def def_node_slot: (untyped class_name, untyped method_name, ?Symbol kind) -> untyped
308
335
  def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
309
336
  def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
337
+ # Returns `[opaque_flag, recorder_keys]`. Steep 2.0.0 cannot verify a tuple through the
338
+ # `Array#freeze` on the returned literal and reports a MethodBodyTypeMismatch warning; the
339
+ # declaration keeps the precise shape because `rigor sig-gen` proves it.
340
+ def subclassing_opacity: () -> [false | true, Array[untyped]]
341
+ # authored: each owner is a frozen `[class_name, open_to_override]` pair. sig-gen types the lazily built
342
+ # `(owners ||= []) <<` array as `Array[untyped]`; the body keeps it to avoid `Hash#filter_map`'s per-entry pair.
343
+ def user_instance_def_owners: (untyped) -> Array[Array[untyped]]
310
344
  def discovered_method_through_ancestors?: (String | Symbol? class_name, String | Symbol method_name, Symbol kind, ?name_memo: Hash[untyped, untyped]) -> bool
311
345
  def external_ancestor_name_candidates: (String | Symbol class_name, ?name_memo: Hash[untyped, untyped]) -> Array[Array[String]]
312
346
  def enqueue_ancestors: (String current, Array[String] queue, Hash[untyped, untyped] name_memo, ?mixins: bool) -> void
@@ -320,6 +354,7 @@ module Rigor
320
354
  def known_user_class?: (String | Symbol name) -> bool
321
355
  def singleton_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
322
356
  def module_function_def?: (untyped, untyped) -> (false | true)
357
+ def module_function_row_def?: (untyped, untyped) -> (false | true)
323
358
  def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
324
359
  def user_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
325
360
  def user_singleton_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
@@ -330,6 +365,9 @@ module Rigor
330
365
  # sig-gen gap: #1167 — the instance-side twin: the same untyped `call_node`, the same untyped-return skip.
331
366
  def instance_def_shadows_call?: (String | Symbol class_name, String | Symbol method_name, untyped call_node) -> bool
332
367
  def top_level_def_for: (String | Symbol method_name) -> ::Prism::DefNode?
368
+ def ownerless_definition?: (untyped, ?top_level: untyped) -> (false | true)
369
+ def toplevel_def_ambiguity: (String | Symbol method_name) -> (:contested | :several | :main_singleton | :aliased | :anonymous | :object)?
370
+ def declared_class?: (String | Symbol class_name) -> bool
333
371
  def bindable_top_level_def_for: (String | Symbol method_name) -> ::Prism::DefNode?
334
372
  def toplevel?: () -> bool
335
373
  def discovered_method_visibility: (String | Symbol class_name, String | Symbol method_name) -> Symbol?
@@ -337,6 +375,7 @@ module Rigor
337
375
  def data_member_layout: (String | Symbol class_name) -> Array[Symbol]?
338
376
  def struct_member_layout: (String | Symbol class_name) -> { members: Array[Symbol], keyword_init: bool }?
339
377
  def includes_of: (String | Symbol class_name) -> Array[String]
378
+ def prepends_of: (String | Symbol class_name) -> Array[String]
340
379
  # sig-gen gap: #2302 — `names = []` grown by `concat` reads `Array[untyped]`, so the element type is
341
380
  # hand-written, matching {#includes_of}.
342
381
  def singleton_extends_of: (String | Symbol class_name) -> Array[String]
@@ -22,6 +22,7 @@ module Rigor
22
22
  def and: (Trinary other) -> Trinary
23
23
  def or: (Trinary other) -> Trinary
24
24
  def ==: (untyped other) -> bool
25
+ alias eql? ==
25
26
  def hash: () -> Integer
26
27
  def to_s: () -> String
27
28
  def inspect: () -> String
data/sig/rigor/type.rbs CHANGED
@@ -56,8 +56,8 @@ module Rigor
56
56
  end
57
57
 
58
58
  class Dynamic
59
- attr_reader static_facet: Type::t
60
- def initialize: (Type::t static_facet) -> void
59
+ attr_reader static_facet: Type::t | Interface
60
+ def initialize: (Type::t | Interface static_facet) -> void
61
61
  def describe: (?Symbol verbosity) -> String
62
62
  def erase_to_rbs: () -> "untyped"
63
63
  def top: () -> Trinary
@@ -169,6 +169,11 @@ module Rigor
169
169
  def inspect: () -> String
170
170
  end
171
171
 
172
+ # ADR-130 — a `Rigor::Plugin` interface, carried only as a `Dynamic`'s facet (`Dynamic[Rigor::Plugin::_Scope]`), so
173
+ # it is not a member of `Type::t`. Declared for that name only; its members are read from the source.
174
+ class Interface
175
+ end
176
+
172
177
  class Union
173
178
  attr_reader members: Array[Type::t]
174
179
  def initialize: (Array[Type::t] members) -> void
@@ -446,7 +451,8 @@ module Rigor
446
451
  def self?.top: () -> Top
447
452
  def self?.bot: () -> Bot
448
453
  def self?.untyped: () -> Dynamic
449
- def self?.dynamic: (Type::t static_facet) -> Dynamic
454
+ def self?.untyped?: (Type::t? type) -> bool
455
+ def self?.dynamic: (Type::t | Interface static_facet) -> Dynamic
450
456
  def self?.nominal_of: (Module | String class_name_or_object, ?type_args: Array[Type::t]) -> Nominal
451
457
  def self?.singleton_of: (Module | String class_name_or_object) -> Singleton
452
458
  def self?.constant_of: (untyped value) -> Constant
data/sig/rigor.rbs CHANGED
@@ -165,8 +165,9 @@ module Rigor
165
165
  # sig-gen gap: #1008 — `result` is populated by `collect_return_summaries` mutating it by
166
166
  # reference from a sibling method; sig-gen folds only the `{}` seed and the empty-memo early
167
167
  # return, so it proposes the seed shape instead of the honest, usually-non-empty contract.
168
- # Keys are `[path, "Class#method"]` pairs; values are `{ keys:, returns:, effects: }` bundles.
169
- def return_summaries: () -> Hash[[String, String], Hash[Symbol, untyped]]
168
+ # Keys are `[path, "Class#method"]` pairs; values are `{ keys:, returns:, effects: }` bundles, or
169
+ # nil for a def whose keys the run cannot list. nil for a pool run, which harvests none (#3160).
170
+ def return_summaries: () -> Hash[[String, String], Hash[Symbol, untyped]?]?
170
171
  # ADR-67 — `[class_name, method_name, kind] => { param_name => Type }`.
171
172
  def param_inferred_types: () -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
172
173
  def collect_param_inference_table: (untyped files) -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
@@ -130,6 +130,7 @@ A good hand-off is two or three sentences of orientation plus the pointer:
130
130
  - baseline reduction → **`rigor-baseline-reduce`** · coverage holes → **`rigor-protection-uplift`**
131
131
  - a missing gem/DSL → **`rigor-plugin-author`** · monkey-patch clusters → **`rigor-monkeypatch-resolve`**
132
132
  - about to *write* a type (RBS, `#:`, a Sorbet `sig`, a YARD tag, a doc sentence) → **`rigor-type-oracle`**
133
+ - auditing, fixing, or contributing RBS declarations (a gem's `sig/`, a gem_rbs_collection entry) → **`rigor-rbs-contract`**
133
134
 
134
135
  When in doubt, give less and point — it respects the user's "three skills
135
136
  to remember" promise and keeps each answer to the part only `rigor-ask`
@@ -68,10 +68,10 @@ install`), every plugin bundled in the toolchain is readable source.
68
68
  Use it as a worked-example library throughout this skill:
69
69
 
70
70
  ```sh
71
- rigor plugin list # all bundled + example plugins, with paths
72
- rigor plugin print rigor-activesupport-core-ext # a plugin's main source, inline
73
- rigor plugin path rigor-units # the dir, to browse with your file tool
74
- rigor plugin root # gem root + public API (lib/rigor/plugin.rb)
71
+ rigor plugin # all bundled + example plugins, with paths
72
+ rigor plugin rigor-activesupport-core-ext # a plugin's main source, inline
73
+ rigor plugin --path rigor-units # the dir, to browse with your file tool
74
+ rigor plugin --root # gem root + public API (lib/rigor/plugin.rb)
75
75
  ```
76
76
 
77
77
  `rigor plugin` (singular) browses the toolchain's plugins; `rigor
@@ -254,8 +254,8 @@ Two ways to wire the RBS, depending on how the plugin is packaged:
254
254
  read one as a worked example:
255
255
 
256
256
  ```sh
257
- rigor plugin print rigor-activesupport-core-ext # see manifest + sig/ layout
258
- rigor plugin path rigor-activesupport-core-ext # then browse its sig/ dir
257
+ rigor plugin rigor-activesupport-core-ext # see manifest + sig/ layout
258
+ rigor plugin --path rigor-activesupport-core-ext # then browse its sig/ dir
259
259
  ```
260
260
 
261
261
  2. **A project-private plugin** — the manifest field still works, but
@@ -280,9 +280,9 @@ They compose — many plugins ship both.
280
280
 
281
281
  > **Browse a real plugin instead of guessing the API.** Because Rigor
282
282
  > is installed on disk (`mise` / `gem install`), every bundled plugin's
283
- > source is readable as a worked example. `rigor plugin list` shows
284
- > them all with absolute paths; `rigor plugin print <name>` inlines a
285
- > plugin's main source; `rigor plugin root` points at the engine source
283
+ > source is readable as a worked example. `rigor plugin` shows
284
+ > them all with absolute paths; `rigor plugin <name>` inlines a
285
+ > plugin's main source; `rigor plugin --root` points at the engine source
286
286
  > and the public `Rigor::Plugin::Base` API. When the prose here is
287
287
  > thinner than you need, read a shipped plugin that does the same thing.
288
288
 
@@ -74,9 +74,9 @@ Rigor is installed on disk, so both the plugin under review and the
74
74
  worked-example plugins are readable source:
75
75
 
76
76
  ```sh
77
- rigor plugin list # every bundled + example plugin, with paths
78
- rigor plugin print rigor-<id> # a plugin's main source, inline
79
- rigor plugin path rigor-<id> # its directory, to browse
77
+ rigor plugin # every bundled + example plugin, with paths
78
+ rigor plugin rigor-<id> # a plugin's main source, inline
79
+ rigor plugin --path rigor-<id> # its directory, to browse
80
80
  ```
81
81
 
82
82
  The **authoritative** authoring surface — the one this review scores
@@ -56,6 +56,7 @@ bundle exec rbs collection install
56
56
  Use `bundle exec` when `rbs` appears in `Gemfile` or `Gemfile.lock`
57
57
  (the common case — Steep / rbs_rails workflows put it there). If `rbs`
58
58
  is not in the Gemfile, use the bare `rbs collection install` instead.
59
+ If `bundle exec rbs` runs an `rbs` that `gem:rigortype` put on `PATH` instead of the project's, see the [install guide's note on `rbs` shadowing](https://github.com/rigortype/rigor/blob/master/docs/install.md#case-a--mise-is-available-recommended).
59
60
 
60
61
  Ask the user for permission before running, since this installs files
61
62
  into `.gem_rbs_collection/` (a generated directory that belongs in
@@ -170,6 +170,8 @@ bundle exec rbs collection install # if rbs is in Gemfile
170
170
  # or: rbs collection install
171
171
  ```
172
172
 
173
+ If `bundle exec rbs` runs an `rbs` that `gem:rigortype` put on `PATH` instead of the project's, see the [install guide's note on `rbs` shadowing](https://github.com/rigortype/rigor/blob/master/docs/install.md#case-a--mise-is-available-recommended).
174
+
173
175
  Re-run `rigor triage`. If the `gem-without-rbs` count drops, carry
174
176
  the new, smaller count into Phase 7.
175
177
 
@@ -218,8 +220,19 @@ baseline is a ceiling, not a blanket. Reducing it later is the
218
220
  Recommend committing `.rigor-baseline.yml` — it documents project
219
221
  state; list it in the Final step's file inventory.
220
222
 
223
+ **Rule-less diagnostics cannot be baselined.** A file Prism cannot
224
+ parse (a parse error), a missing `paths:` entry or an internal error
225
+ yields a diagnostic with no rule, so it has no `(file, rule)` bucket.
226
+ The summary then prints a second line ("N diagnostic(s) have no rule
227
+ (parse, path or internal errors) in M file(s) and cannot be
228
+ baselined") and lists the files; the command still exits 0. Acknowledge
229
+ mode reaches a green `rigor check` only after those files are fixed or
230
+ added to `exclude:`, or the bad `paths:` entry is removed. Do that
231
+ before wiring `baseline:`, then re-run `rigor baseline regenerate`.
232
+
221
233
  Print the suppression summary for the user: "N diagnostics recorded
222
- as baseline; M will surface on subsequent runs."
234
+ as baseline; M will surface on subsequent runs." Take N from the
235
+ `covering N diagnostic(s)` count, and count the unbaselineable ones in M.
223
236
 
224
237
  ## Phase 8 — Surface real bugs & offer escalation
225
238
 
@@ -386,7 +399,9 @@ information and Rigor has no built-in coverage. In order:
386
399
 
387
400
  1. `bundle exec rbs collection install` (bare `rbs collection install`
388
401
  if `rbs` is not in the project's Gemfile) — pulls community RBS for
389
- the gem if it exists. Re-run triage afterwards.
402
+ the gem if it exists. Re-run triage afterwards. If `bundle exec rbs`
403
+ runs a `gem:rigortype` `rbs` instead of the project's, see the
404
+ [install guide's note on `rbs` shadowing](https://github.com/rigortype/rigor/blob/master/docs/install.md#case-a--mise-is-available-recommended).
390
405
  2. `dependencies.source_inference:` in `.rigor.dist.yml` — opt the
391
406
  gem into Rigor inferring `Dynamic`-typed returns from its source.
392
407
  3. If the gem is widely used and genuinely warrants first-class
@@ -28,13 +28,13 @@ rigor skill --full rigor-type-oracle
28
28
  ```
29
29
 
30
30
  Its `references/02-agents-md-fragment.md` section carries the paragraph
31
- and the five bullets. Copy that block **verbatim** — including its
31
+ and the six bullets. Copy that block **verbatim** — including its
32
32
  single-long-line shape, which is deliberate (some renderers turn a
33
33
  newline inside a paragraph into a line break).
34
34
 
35
- Do not paraphrase it from memory, and do not shorten it: the five bullets
35
+ Do not paraphrase it from memory, and do not shorten it: the six bullets
36
36
  are the load-bearing part — expression, method signature, parameter,
37
- the gap rule, and provenance.
37
+ the gap rule, provenance, and the declared-`void` contract.
38
38
 
39
39
  ## Where it goes
40
40
 
@@ -44,7 +44,7 @@ the gap rule, and provenance.
44
44
  | Only `CLAUDE.md` exists | Append it there. |
45
45
  | Both exist | Put it in `AGENTS.md`. Add `@AGENTS.md` to `CLAUDE.md` only if it is not already pulled in. |
46
46
  | Neither exists | **Create `AGENTS.md`** with this as its first section. |
47
- | A types / type-checking section already exists | Merge into it; keep the five bullets intact. Never write a second, competing rule. |
47
+ | A types / type-checking section already exists | Merge into it; keep the six bullets intact. Never write a second, competing rule. |
48
48
 
49
49
  Never overwrite unrelated content. If the project already states a rule
50
50
  about type authorship that contradicts this one, stop and show the user