rigortype 0.4.5 → 0.4.7

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 (452) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/data/gem_overlay/activesupport/core_ext.rbs +16 -13
  4. data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
  5. data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
  6. data/docs/handbook/01-getting-started.md +5 -2
  7. data/docs/handbook/11-sig-gen.md +61 -5
  8. data/docs/handbook/appendix-phpstan.md +4 -4
  9. data/docs/manual/02-cli-reference.md +192 -27
  10. data/docs/manual/03-configuration.md +38 -4
  11. data/docs/manual/04-diagnostics.md +1 -1
  12. data/docs/manual/06-baseline.md +6 -4
  13. data/docs/manual/09-editor-integration.md +13 -2
  14. data/docs/manual/10-mcp-server.md +47 -3
  15. data/docs/manual/12-caching.md +9 -1
  16. data/docs/manual/plugins/rigor-actionmailer.md +30 -0
  17. data/docs/manual/plugins/rigor-actionpack.md +49 -11
  18. data/docs/manual/plugins/rigor-activesupport-core-ext.md +20 -1
  19. data/docs/manual/plugins/rigor-devise.md +15 -0
  20. data/docs/manual/plugins/rigor-rspec.md +2 -1
  21. data/lib/rigor/analysis/baseline.rb +24 -27
  22. data/lib/rigor/analysis/buffer_binding.rb +14 -0
  23. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
  24. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
  25. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +4 -4
  26. data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
  27. data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +105 -12
  28. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +143 -15
  29. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +4 -1
  30. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
  31. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +1 -1
  32. data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +66 -3
  33. data/lib/rigor/analysis/check_rules/rebinding_block_callees/dispatch.rb +112 -0
  34. data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +394 -0
  35. data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
  36. data/lib/rigor/analysis/check_rules/ruby_deprecations.rb +7 -0
  37. data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
  38. data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
  39. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
  40. data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
  41. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +53 -2
  42. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
  43. data/lib/rigor/analysis/check_rules.rb +217 -52
  44. data/lib/rigor/analysis/crash_signature.rb +2 -2
  45. data/lib/rigor/analysis/dependency_recorder.rb +15 -4
  46. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
  47. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
  48. data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
  49. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  50. data/lib/rigor/analysis/edit_replay.rb +154 -0
  51. data/lib/rigor/analysis/fact_store.rb +3 -3
  52. data/lib/rigor/analysis/incremental.rb +37 -0
  53. data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -2
  54. data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
  55. data/lib/rigor/analysis/incremental_session.rb +202 -43
  56. data/lib/rigor/analysis/path_expansion.rb +41 -0
  57. data/lib/rigor/analysis/require_relative_closure.rb +100 -0
  58. data/lib/rigor/analysis/rule_catalog.rb +7 -3
  59. data/lib/rigor/analysis/run_disclosure_credit.rb +80 -0
  60. data/lib/rigor/analysis/run_disclosure_ledger.rb +155 -0
  61. data/lib/rigor/analysis/run_stats.rb +2 -2
  62. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +8 -4
  63. data/lib/rigor/analysis/runner/declaration_position.rb +1 -1
  64. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +204 -96
  65. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +1 -1
  66. data/lib/rigor/analysis/runner/pool_coordinator.rb +157 -320
  67. data/lib/rigor/analysis/runner/project_pre_passes.rb +48 -6
  68. data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
  69. data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
  70. data/lib/rigor/analysis/runner/scan_environment.rb +51 -0
  71. data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
  72. data/lib/rigor/analysis/runner.rb +233 -120
  73. data/lib/rigor/analysis/self_call_resolution_recorder.rb +1 -1
  74. data/lib/rigor/analysis/template_unit_positions.rb +2 -3
  75. data/lib/rigor/analysis/template_units.rb +9 -1
  76. data/lib/rigor/analysis/worker_session.rb +38 -33
  77. data/lib/rigor/bleeding_edge.rb +3 -6
  78. data/lib/rigor/builtins/imported_refinements.rb +6 -8
  79. data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
  80. data/lib/rigor/builtins/regex_refinement.rb +4 -6
  81. data/lib/rigor/cache/descriptor.rb +6 -5
  82. data/lib/rigor/cache/incremental_snapshot.rb +60 -18
  83. data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
  84. data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
  85. data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
  86. data/lib/rigor/cache/rbs_constant_table.rb +1 -1
  87. data/lib/rigor/cache/rbs_descriptor.rb +54 -3
  88. data/lib/rigor/cache/rbs_environment.rb +4 -1
  89. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
  90. data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
  91. data/lib/rigor/cache/store.rb +11 -10
  92. data/lib/rigor/ci_detector.rb +1 -1
  93. data/lib/rigor/cli/annotate_command.rb +24 -19
  94. data/lib/rigor/cli/baseline_command.rb +145 -55
  95. data/lib/rigor/cli/catalogue.rb +256 -0
  96. data/lib/rigor/cli/check_command.rb +188 -93
  97. data/lib/rigor/cli/check_runner_factory.rb +2 -2
  98. data/lib/rigor/cli/command.rb +15 -1
  99. data/lib/rigor/cli/coverage_command.rb +21 -8
  100. data/lib/rigor/cli/coverage_mutation.rb +5 -7
  101. data/lib/rigor/cli/coverage_renderer.rb +2 -1
  102. data/lib/rigor/cli/coverage_scan.rb +3 -5
  103. data/lib/rigor/cli/diff_command.rb +27 -21
  104. data/lib/rigor/cli/docs_command.rb +1 -2
  105. data/lib/rigor/cli/doctor_command.rb +12 -12
  106. data/lib/rigor/cli/effects_command.rb +50 -40
  107. data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
  108. data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
  109. data/lib/rigor/cli/effects_renderer.rb +2 -1
  110. data/lib/rigor/cli/effects_snapshot_command.rb +18 -17
  111. data/lib/rigor/cli/explain_command.rb +18 -8
  112. data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
  113. data/lib/rigor/cli/json_document.rb +41 -0
  114. data/lib/rigor/cli/lens_command.rb +17 -13
  115. data/lib/rigor/cli/lsp_command.rb +250 -23
  116. data/lib/rigor/cli/mcp_command.rb +14 -8
  117. data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
  118. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
  119. data/lib/rigor/cli/options.rb +60 -4
  120. data/lib/rigor/cli/plugin_command.rb +93 -46
  121. data/lib/rigor/cli/plugins_command.rb +22 -18
  122. data/lib/rigor/cli/plugins_renderer.rb +34 -8
  123. data/lib/rigor/cli/protection_fork_scan.rb +2 -2
  124. data/lib/rigor/cli/protection_renderer.rb +2 -1
  125. data/lib/rigor/cli/show_bleedingedge_command.rb +23 -16
  126. data/lib/rigor/cli/sig_gen_command.rb +130 -34
  127. data/lib/rigor/cli/skill_command.rb +32 -3
  128. data/lib/rigor/cli/skill_deep_probe.rb +1 -1
  129. data/lib/rigor/cli/skill_describe.rb +1 -1
  130. data/lib/rigor/cli/trace_command.rb +14 -9
  131. data/lib/rigor/cli/triage_command.rb +10 -11
  132. data/lib/rigor/cli/triage_renderer.rb +2 -1
  133. data/lib/rigor/cli/type_of_command.rb +18 -12
  134. data/lib/rigor/cli/type_of_project_scope.rb +24 -0
  135. data/lib/rigor/cli/type_of_renderer.rb +4 -1
  136. data/lib/rigor/cli/type_scan_command.rb +14 -9
  137. data/lib/rigor/cli/type_scan_renderer.rb +2 -1
  138. data/lib/rigor/cli/unused_command.rb +27 -17
  139. data/lib/rigor/cli/upgrade_command.rb +5 -0
  140. data/lib/rigor/cli.rb +209 -54
  141. data/lib/rigor/config_audit.rb +17 -6
  142. data/lib/rigor/configuration/severity_profile.rb +5 -5
  143. data/lib/rigor/configuration.rb +86 -34
  144. data/lib/rigor/effects/definition_context.rb +0 -2
  145. data/lib/rigor/effects/envelope.rb +1 -1
  146. data/lib/rigor/effects/framework_units.rb +1 -1
  147. data/lib/rigor/effects/mutation_classifier.rb +4 -7
  148. data/lib/rigor/effects/propagator.rb +1 -1
  149. data/lib/rigor/effects/registry.rb +2 -2
  150. data/lib/rigor/effects/snapshot.rb +1 -1
  151. data/lib/rigor/effects/taint_cause.rb +0 -2
  152. data/lib/rigor/effects/unit_scan.rb +9 -13
  153. data/lib/rigor/environment/bundle_sig_discovery.rb +5 -9
  154. data/lib/rigor/environment/class_registry.rb +3 -3
  155. data/lib/rigor/environment/core_root.rb +77 -0
  156. data/lib/rigor/environment/default_libraries.rb +1 -1
  157. data/lib/rigor/environment/deferred_signature_plan.rb +283 -0
  158. data/lib/rigor/environment/gated_signature_guard.rb +1 -1
  159. data/lib/rigor/environment/gated_signature_plan.rb +5 -2
  160. data/lib/rigor/environment/lockfile_resolver.rb +28 -12
  161. data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
  162. data/lib/rigor/environment/member_consistency.rb +56 -7
  163. data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
  164. data/lib/rigor/environment/project_path_gems.rb +124 -0
  165. data/lib/rigor/environment/rbs_hierarchy.rb +6 -15
  166. data/lib/rigor/environment/rbs_loader.rb +592 -70
  167. data/lib/rigor/environment/reflection.rb +7 -7
  168. data/lib/rigor/environment/required_features.rb +136 -32
  169. data/lib/rigor/environment/ruby_library_roots.rb +122 -0
  170. data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
  171. data/lib/rigor/environment.rb +44 -11
  172. data/lib/rigor/flow_contribution/merger.rb +4 -4
  173. data/lib/rigor/inference/acceptance.rb +93 -32
  174. data/lib/rigor/inference/block_parameter_binder.rb +2 -3
  175. data/lib/rigor/inference/block_run_count.rb +178 -0
  176. data/lib/rigor/inference/budget_trace.rb +8 -2
  177. data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
  178. data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
  179. data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
  180. data/lib/rigor/inference/callee_mutation_chain.rb +126 -0
  181. data/lib/rigor/inference/callee_write_census.rb +815 -0
  182. data/lib/rigor/inference/construction_escape.rb +217 -0
  183. data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
  184. data/lib/rigor/inference/deep_erasure.rb +170 -0
  185. data/lib/rigor/inference/def_handle.rb +1 -1
  186. data/lib/rigor/inference/def_node_resolver.rb +1 -1
  187. data/lib/rigor/inference/def_return_typer.rb +204 -12
  188. data/lib/rigor/inference/definer_resolution.rb +21 -5
  189. data/lib/rigor/inference/definers_index.rb +106 -0
  190. data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
  191. data/lib/rigor/inference/element_read_widening.rb +49 -3
  192. data/lib/rigor/inference/error_info.rb +17 -3
  193. data/lib/rigor/inference/expression_typer.rb +173 -57
  194. data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
  195. data/lib/rigor/inference/global_write_census.rb +110 -1
  196. data/lib/rigor/inference/global_writer_reach.rb +260 -0
  197. data/lib/rigor/inference/hkt_body.rb +1 -2
  198. data/lib/rigor/inference/hkt_body_parser.rb +3 -5
  199. data/lib/rigor/inference/hkt_reducer.rb +2 -2
  200. data/lib/rigor/inference/hkt_registry.rb +3 -5
  201. data/lib/rigor/inference/indexed_narrowing.rb +4 -7
  202. data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
  203. data/lib/rigor/inference/ivar_writer_census.rb +246 -0
  204. data/lib/rigor/inference/key_presence_guard.rb +2 -1
  205. data/lib/rigor/inference/loop_value_record.rb +57 -0
  206. data/lib/rigor/inference/match_rebinding/frame.rb +65 -0
  207. data/lib/rigor/inference/match_rebinding/yielding_match.rb +45 -0
  208. data/lib/rigor/inference/match_rebinding.rb +11 -1
  209. data/lib/rigor/inference/memo_audit.rb +55 -0
  210. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
  211. data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
  212. data/lib/rigor/inference/method_dispatcher/block_folding.rb +1 -1
  213. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +113 -12
  214. data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
  215. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
  216. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -3
  217. data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
  218. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +39 -27
  219. data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
  220. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +203 -17
  221. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
  222. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
  223. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +2 -2
  224. data/lib/rigor/inference/method_dispatcher/set_folding.rb +59 -24
  225. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +83 -20
  226. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
  227. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
  228. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
  229. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
  230. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  231. data/lib/rigor/inference/method_dispatcher.rb +109 -29
  232. data/lib/rigor/inference/module_function_state/spellings.rb +64 -0
  233. data/lib/rigor/inference/module_function_state.rb +23 -1
  234. data/lib/rigor/inference/multi_target_binder.rb +1 -1
  235. data/lib/rigor/inference/mutation_rejoin.rb +240 -4
  236. data/lib/rigor/inference/mutation_widening.rb +162 -29
  237. data/lib/rigor/inference/narrowing.rb +113 -38
  238. data/lib/rigor/inference/object_mixins.rb +13 -1
  239. data/lib/rigor/inference/optimistic_origin.rb +1 -1
  240. data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
  241. data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
  242. data/lib/rigor/inference/pre_eval_constants.rb +1 -1
  243. data/lib/rigor/inference/project_method_ownership.rb +6 -3
  244. data/lib/rigor/inference/project_seed_tables.rb +2 -1
  245. data/lib/rigor/inference/project_yielder.rb +122 -0
  246. data/lib/rigor/inference/receiver_alias.rb +20 -0
  247. data/lib/rigor/inference/refined_dispatch/constructed_class.rb +3 -1
  248. data/lib/rigor/inference/refined_dispatch/own_method.rb +2 -1
  249. data/lib/rigor/inference/remover_holder_scan.rb +233 -0
  250. data/lib/rigor/inference/remover_narrowing.rb +224 -0
  251. data/lib/rigor/inference/rewrite_mutation.rb +53 -2
  252. data/lib/rigor/inference/scope_indexer/certainty.rb +9 -1
  253. data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
  254. data/lib/rigor/inference/scope_indexer/declared_ivar_types.rb +64 -0
  255. data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +205 -0
  256. data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
  257. data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
  258. data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +135 -0
  259. data/lib/rigor/inference/scope_indexer/unseen_ivar_writers.rb +133 -0
  260. data/lib/rigor/inference/scope_indexer.rb +614 -146
  261. data/lib/rigor/inference/self_call_ivar_writes.rb +101 -17
  262. data/lib/rigor/inference/set_mutation.rb +189 -0
  263. data/lib/rigor/inference/singleton_hook_decline.rb +1 -2
  264. data/lib/rigor/inference/statement_evaluator.rb +3036 -278
  265. data/lib/rigor/inference/struct_fold_safety.rb +4 -6
  266. data/lib/rigor/inference/synthetic_method_index.rb +23 -0
  267. data/lib/rigor/inference/synthetic_method_scanner/project_members.rb +130 -0
  268. data/lib/rigor/inference/synthetic_method_scanner.rb +73 -14
  269. data/lib/rigor/inference/toplevel_def_census.rb +59 -0
  270. data/lib/rigor/inference/unknown_store_widening.rb +103 -4
  271. data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
  272. data/lib/rigor/inference/void_tail_summary.rb +2 -1
  273. data/lib/rigor/language_server/buffer_table.rb +9 -3
  274. data/lib/rigor/language_server/completion_provider.rb +26 -20
  275. data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
  276. data/lib/rigor/language_server/diagnostic_publisher.rb +28 -9
  277. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  278. data/lib/rigor/language_server/folding_range_provider.rb +1 -2
  279. data/lib/rigor/language_server/hover_provider.rb +1 -7
  280. data/lib/rigor/language_server/hover_renderer.rb +6 -8
  281. data/lib/rigor/language_server/project_context.rb +98 -4
  282. data/lib/rigor/language_server/publish_batcher.rb +3 -4
  283. data/lib/rigor/language_server/selection_range_provider.rb +2 -4
  284. data/lib/rigor/language_server/server.rb +12 -6
  285. data/lib/rigor/language_server/signature_help_provider.rb +4 -4
  286. data/lib/rigor/lens/plugins.rb +1 -1
  287. data/lib/rigor/mcp/server.rb +82 -3
  288. data/lib/rigor/mcp.rb +1 -1
  289. data/lib/rigor/plugin/access_denied_error.rb +1 -2
  290. data/lib/rigor/plugin/base.rb +26 -11
  291. data/lib/rigor/plugin/bundled_catalog.rb +1 -12
  292. data/lib/rigor/plugin/io_boundary.rb +1 -1
  293. data/lib/rigor/plugin/loader.rb +25 -8
  294. data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
  295. data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
  296. data/lib/rigor/plugin/manifest.rb +38 -16
  297. data/lib/rigor/plugin/registry.rb +41 -3
  298. data/lib/rigor/plugin/services.rb +2 -3
  299. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
  300. data/lib/rigor/plugin/trust_policy.rb +2 -2
  301. data/lib/rigor/plugin/type_node_resolver.rb +2 -4
  302. data/lib/rigor/plugin.rb +6 -8
  303. data/lib/rigor/plugin_gap_advisory.rb +5 -1
  304. data/lib/rigor/project_environment.rb +16 -2
  305. data/lib/rigor/protection/analysis_guard.rb +1 -1
  306. data/lib/rigor/protection/discovery_seed.rb +96 -2
  307. data/lib/rigor/protection/mutator.rb +1 -1
  308. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  309. data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
  310. data/lib/rigor/rbs_extended/reporter.rb +27 -3
  311. data/lib/rigor/rbs_extended.rb +2 -3
  312. data/lib/rigor/reflection/constant_ancestors.rb +5 -3
  313. data/lib/rigor/rooted_glob.rb +25 -2
  314. data/lib/rigor/run_scoped_slots.rb +38 -0
  315. data/lib/rigor/runtime/jit.rb +1 -1
  316. data/lib/rigor/scope/discovery_index.rb +19 -6
  317. data/lib/rigor/scope/resolution_chain.rb +3 -1
  318. data/lib/rigor/scope.rb +379 -36
  319. data/lib/rigor/sig_gen/classification.rb +4 -0
  320. data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
  321. data/lib/rigor/sig_gen/generator.rb +668 -84
  322. data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
  323. data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
  324. data/lib/rigor/sig_gen/layout_index.rb +3 -3
  325. data/lib/rigor/sig_gen/method_candidate.rb +23 -4
  326. data/lib/rigor/sig_gen/observation_collector.rb +7 -6
  327. data/lib/rigor/sig_gen/observed_call.rb +1 -1
  328. data/lib/rigor/sig_gen/path_mapper.rb +6 -0
  329. data/lib/rigor/sig_gen/rbs_validity.rb +1 -1
  330. data/lib/rigor/sig_gen/renderer.rb +21 -12
  331. data/lib/rigor/sig_gen/skip_reason_catalog.rb +15 -2
  332. data/lib/rigor/sig_gen/type_elaborator.rb +21 -5
  333. data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
  334. data/lib/rigor/sig_gen/write_reporter.rb +63 -14
  335. data/lib/rigor/sig_gen/write_result.rb +23 -12
  336. data/lib/rigor/sig_gen/writer.rb +217 -37
  337. data/lib/rigor/type/acceptance_router.rb +2 -2
  338. data/lib/rigor/type/accepts_result.rb +1 -1
  339. data/lib/rigor/type/app.rb +4 -6
  340. data/lib/rigor/type/combinator.rb +13 -16
  341. data/lib/rigor/type/constant.rb +48 -7
  342. data/lib/rigor/type/hash_shape.rb +26 -40
  343. data/lib/rigor/type/struct_instance.rb +3 -2
  344. data/lib/rigor/type/union.rb +1 -1
  345. data/lib/rigor/type_node/identifier.rb +1 -2
  346. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  347. data/lib/rigor/type_node/string_literal.rb +1 -2
  348. data/lib/rigor/type_node/symbol_literal.rb +1 -2
  349. data/lib/rigor/type_node/union.rb +3 -6
  350. data/lib/rigor/value_semantics.rb +1 -10
  351. data/lib/rigor/version.rb +1 -1
  352. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
  353. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
  354. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
  355. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +89 -70
  356. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
  357. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +25 -4
  358. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
  359. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
  360. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
  361. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
  362. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +1 -1
  363. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +79 -19
  364. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
  365. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +6 -3
  366. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
  367. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
  368. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
  369. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
  370. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +2 -3
  371. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +0 -1
  372. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +5 -4
  373. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
  374. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
  375. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +7 -12
  376. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
  377. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
  378. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
  379. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +19 -6
  380. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +26 -13
  381. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
  382. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +5 -3
  383. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
  384. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
  385. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
  386. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +7 -6
  387. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
  388. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
  389. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
  390. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
  391. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
  392. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
  393. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
  394. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -5
  395. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
  396. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
  397. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
  398. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
  399. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -2
  400. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
  401. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
  402. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
  403. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
  404. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
  405. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +1 -3
  406. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
  407. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
  408. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
  409. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +1 -1
  410. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
  411. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +102 -11
  412. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
  413. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
  414. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
  415. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +5 -2
  416. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
  417. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
  418. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +1 -1
  419. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
  420. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +17 -21
  421. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
  422. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +3 -2
  423. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
  424. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer.rb +1 -1
  425. data/sig/rigor/analysis/baseline.rbs +0 -2
  426. data/sig/rigor/analysis/fact_store.rbs +1 -0
  427. data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
  428. data/sig/rigor/cli/diff_command.rbs +1 -1
  429. data/sig/rigor/cli/explain_command.rbs +1 -1
  430. data/sig/rigor/effects/file_collection.rbs +5 -6
  431. data/sig/rigor/effects/registry.rbs +8 -6
  432. data/sig/rigor/effects/summary.rbs +6 -5
  433. data/sig/rigor/environment.rbs +5 -3
  434. data/sig/rigor/inference/optimistic_origin.rbs +11 -0
  435. data/sig/rigor/inference.rbs +10 -1
  436. data/sig/rigor/plugin/additional_initializer.rbs +0 -5
  437. data/sig/rigor/plugin/base.rbs +1 -0
  438. data/sig/rigor/plugin/effect_ancestry.rbs +6 -4
  439. data/sig/rigor/plugin/effect_attribution.rbs +25 -10
  440. data/sig/rigor/plugin/effect_edge.rbs +12 -5
  441. data/sig/rigor/plugin/effect_entry_points.rbs +8 -3
  442. data/sig/rigor/plugin/io_boundary.rbs +6 -5
  443. data/sig/rigor/plugin/manifest.rbs +16 -18
  444. data/sig/rigor/plugin/protocol_contract.rbs +6 -9
  445. data/sig/rigor/plugin/registry.rbs +1 -1
  446. data/sig/rigor/scope.rbs +51 -50
  447. data/sig/rigor/type.rbs +0 -6
  448. data/skills/rigor-plugin-author/SKILL.md +4 -4
  449. data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
  450. data/skills/rigor-plugin-review/SKILL.md +3 -3
  451. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +12 -1
  452. metadata +55 -3
data/sig/rigor/scope.rbs CHANGED
@@ -14,39 +14,33 @@ module Rigor
14
14
  attr_reader void_origins: Hash[untyped, Inference::VoidOrigin]
15
15
  attr_reader plugin_typed_calls: Hash[untyped, bool]
16
16
  attr_reader optimistic_origins: Hash[untyped, Symbol]
17
- # A marked binding whose miss answer is known stores an `Inference::OptimisticOrigin::BoundMark` (a `Data`)
18
- # in place of its bare cause (issue #1302).
19
- attr_reader optimistic_locals: Hash[Symbol, Symbol | Data]
20
- attr_reader optimistic_ivars: Hash[Symbol, Symbol | Data]
21
- # sig-gen gap: #1154 — an `attr_reader` over an ivar assigned in `initialize` from a parameter reaches `untyped`.
17
+ # A marked binding whose miss answer is known stores an `Inference::OptimisticOrigin::BoundMark` in place of
18
+ # its bare cause (issue #1302).
19
+ attr_reader optimistic_locals: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark]
20
+ attr_reader optimistic_ivars: Hash[Symbol, Symbol | Inference::OptimisticOrigin::BoundMark]
21
+ attr_reader construction_facts: Hash[Symbol, Set[untyped]]
22
22
  attr_reader repeated_or_writes: Hash[untyped, bool]
23
- # sig-gen gap: #1154 — the same reader shape; `Inference::MatchRebinding::Frame` carries no signature.
23
+ # sig-gen gap: #2323 — the same reader shape; `Inference::MatchRebinding::Frame` carries no signature.
24
24
  attr_reader match_frame: untyped
25
25
  attr_reader indexed_narrowings: Hash[IndexedKey, Type::t]
26
26
  attr_reader method_chain_narrowings: Hash[ChainKey, Type::t]
27
27
  attr_reader source_path: String?
28
+ # authored: the element is a `Symbol` by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
29
+ # would never propose it.
28
30
  attr_reader struct_fold_safe_locals: Set[Symbol]
29
31
  attr_reader opaque_block_self: bool
30
- # sig-gen gap: #1154 — sig-gen skips the reader (sig.skipped.untyped-return): an `attr_reader`
31
- # over an ivar assigned in `initialize` from a parameter, so inference reaches `untyped`.
32
32
  # Issue #1759 — `:refinement` (REFINEMENT_BLOCK_SELF) directly in a `refine X do … end` block body.
33
33
  attr_reader block_self_unknown: bool | :refinement
34
- # sig-gen gap: #1154 — sig-gen skips the reader (sig.skipped.untyped-return): an `attr_reader`
35
- # over an ivar assigned in `initialize` from a parameter, so inference reaches `untyped`.
36
34
  attr_reader singleton_class_body: bool
37
35
  attr_reader lexical_nesting: Array[String]?
38
36
  # Issue #1429 — a guard's narrowing of a constant reference, keyed by its spelling.
39
- # sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
40
37
  attr_reader constant_narrowings: Hash[String, Type::t]
41
38
  # Issue #1429 — the pre-guard type of each global or constant a guard narrowed.
42
- # sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
43
39
  attr_reader guard_records: Hash[[Symbol, Symbol | String], Type::t]
44
40
  # Issue #1446 — the classes a class guard narrowed a `bot` receiver to.
45
- # sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
46
41
  attr_reader bot_guard_classes: Hash[[Symbol, Symbol | String], Array[String]]
47
42
  # Issue #1667 — the modules a plugin-declared refined block runs under, in declaration order.
48
- # sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
49
- attr_reader declared_refinements: Array[String]
43
+ attr_reader declared_refinements: Array[String | Symbol]
50
44
 
51
45
  # ADR-53 Track A — the seed-time discovery tables live on the
52
46
  # DiscoveryIndex; Scope keeps per-table readers as delegates.
@@ -62,37 +56,40 @@ module Rigor
62
56
  def discovered_def_sources: () -> Hash[String, Hash[Symbol, String]]
63
57
  def discovered_singleton_def_sources: () -> Hash[String, Hash[Symbol, String]]
64
58
  def discovered_method_visibilities: () -> Hash[String, Hash[Symbol | [:singleton, Symbol], Symbol]]
65
- # sig-gen gap: #1148 — sig-gen skips an endless-def reader (untyped return); the row is hand-written.
66
59
  def discovered_parameter_envelopes: () -> Hash[String, Hash[untyped, untyped]]
67
- # sig-gen gap: #1149 — sig-gen skips the `||` fallback reader (untyped return); the row is hand-written.
68
60
  def parameter_envelopes_of: (String class_name) -> Hash[untyped, untyped]
69
61
  def discovered_superclasses: () -> Hash[String, String]
70
- # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the per-file
71
- # deferred-range table's row shape is hand-written.
72
62
  def discovered_deferred_ranges: () -> Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]]
73
- # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the refinement table's
74
- # shape is hand-written. A method key is a Symbol or the `"*"` wildcard (ADR-121 WD7).
63
+ # A method key is a Symbol or the `"*"` wildcard (ADR-121 WD7).
75
64
  def discovered_refinements: () -> Hash[String, Hash[Symbol | String, Array[String]]]
76
65
  # authored: the list holds module names and the `InEffectRefinements::UNKNOWN` Symbol; sig-gen reads the delegated
77
66
  # return through an unsigned class as untyped.
78
67
  def in_effect_refinements: (untyped node, ?Array[String] declared) -> Array[String | Symbol]
79
- # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the census shape is
80
- # hand-written.
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.
81
70
  def discovered_global_write_census: () -> Set[Array[untyped]]
82
71
  def discovered_includes: () -> Hash[String, Array[String]]
83
72
  # Issue #1123 — the instance-ancestor-ORDER table beside the include one.
84
73
  def discovered_prepends: () -> Hash[String, Array[String]]
85
- # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the table shape is hand-written.
86
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.
87
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.
88
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.
89
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.
90
86
  def local_constant_names: () -> Set[String]
91
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.
92
88
  def bound_constant_names: (String name) -> Array[String]
93
89
  # sig-gen gap: #1150 — the `Data.define` table it reads carries no type, so sig-gen skips the return; the shape is hand-written.
94
90
  def shadowing_constant_names: (String name) -> Array[String]
95
- # sig-gen gap: #1149 — sig-gen types the `||` fallback `untyped`, so the element type is hand-written.
91
+ # sig-gen gap: #2309 — the `|| Set.new.freeze` fallback arm types `Set[untyped]` beside the table's `Set[Symbol]`, so the
92
+ # element type is hand-written.
96
93
  def published_constant_ivars_for: (String class_name) -> Set[Symbol]
97
94
  def published_constant?: (String name) -> bool
98
95
  def record_constant_dependency: (String name) -> void
@@ -110,10 +107,14 @@ module Rigor
110
107
  def plugin_typed_call?: (untyped node) -> bool
111
108
 
112
109
  def with_repeated_or_writes: (untyped nodes) -> Rigor::Scope
113
- # sig-gen gap: #1154 — `Hash#key?` over that reader reaches `untyped`, so the `bool` is hand-written.
114
110
  def repeated_or_write?: (untyped node) -> bool
115
111
 
116
112
  class DiscoveryIndex
113
+ # #1557 — the def-nesting table is a Hash, or an `Inference::ScopeIndexer::LayeredDefNestings` that answers only
114
+ # `[]` and `empty?`, so that `each` or `key?` over one layer raises instead of reading half the table. A union
115
+ # rather than an interface: the engine reads an RBS interface as `untyped`, which would check nothing.
116
+ type def_nestings = Hash[untyped, Array[String]] | Inference::ScopeIndexer::LayeredDefNestings
117
+
117
118
  attr_reader declared_types: Hash[untyped, Type::t]
118
119
  attr_reader class_ivars: Hash[String, Hash[Symbol, Type::t]]
119
120
  attr_reader class_cvars: Hash[String, Hash[Symbol, Type::t]]
@@ -124,7 +125,7 @@ module Rigor
124
125
  attr_reader in_source_constants: Hash[String, Type::t]
125
126
  attr_reader discovered_methods: Hash[String, Hash[Symbol, Symbol]]
126
127
  attr_reader discovered_def_nodes: Hash[String, Hash[Symbol, untyped]]
127
- attr_reader discovered_def_nestings: Hash[untyped, Array[String]]
128
+ attr_reader discovered_def_nestings: def_nestings
128
129
  attr_reader discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]]
129
130
  attr_reader discovered_def_sources: Hash[String, Hash[Symbol, String]]
130
131
  attr_reader discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]]
@@ -201,7 +202,7 @@ module Rigor
201
202
  # authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
202
203
  def sibling_tables: () -> Hash[Symbol, untyped]
203
204
 
204
- def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?program_global_seeds: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol | [:singleton, Symbol], Symbol]], ?discovered_parameter_envelopes: Hash[String, Hash[untyped, untyped]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_prepends: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?constant_writers: Hash[String, Array[String]], ?constant_shadowers: Hash[String, Array[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?discovered_refinements: Hash[String, Hash[Symbol | String, Array[String]]], ?discovered_global_write_census: Set[Array[untyped]], ?run_generation: Object?, ?patched_line_readers: Set[Symbol], ?clears_last_status: bool, ?defines_case_equality: bool, ?implicit_self_evidence: untyped, ?in_effect_refinements: untyped, ?possible_discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?possible_discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?contested_discovered_def_nodes: Set[Array[untyped]], ?contested_discovered_singleton_def_nodes: Set[Array[untyped]], ?contested_discovered_method_visibilities: Set[Array[untyped]], ?contested_discovered_parameter_envelopes: Set[Array[untyped]]) -> DiscoveryIndex
205
+ def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?program_global_seeds: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: def_nestings, ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol | [:singleton, Symbol], Symbol]], ?discovered_parameter_envelopes: Hash[String, Hash[untyped, untyped]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_prepends: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?constant_writers: Hash[String, Array[String]], ?constant_shadowers: Hash[String, Array[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?discovered_refinements: Hash[String, Hash[Symbol | String, Array[String]]], ?discovered_global_write_census: Set[Array[untyped]], ?run_generation: Object?, ?patched_line_readers: Set[Symbol], ?clears_last_status: bool, ?defines_case_equality: bool, ?implicit_self_evidence: untyped, ?in_effect_refinements: untyped, ?possible_discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?possible_discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?contested_discovered_def_nodes: Set[Array[untyped]], ?contested_discovered_singleton_def_nodes: Set[Array[untyped]], ?contested_discovered_method_visibilities: Set[Array[untyped]], ?contested_discovered_parameter_envelopes: Set[Array[untyped]]) -> DiscoveryIndex
205
206
  end
206
207
 
207
208
  class IndexedKey
@@ -218,22 +219,19 @@ module Rigor
218
219
 
219
220
  def self.empty: (?environment: Environment, ?source_path: String?) -> Scope
220
221
 
221
- 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?, ?dynamic_origins: Hash[untyped, Symbol]) -> void
222
+ 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], ?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
222
223
  def with_source_path: (String? path) -> Scope
223
224
  def with_struct_fold_safe: (Set[Symbol] locals) -> Scope
224
225
  def with_lexical_nesting: (Array[String]? chain) -> Scope
225
226
  def struct_fold_safe?: (String | Symbol name) -> bool
226
227
  def entering_opaque_block: () -> Scope
227
- # sig-gen gap: #1148 — sig-gen skips the endless-def reader (sig.skipped.untyped-return); the row is hand-written.
228
228
  def block_self_unknown?: () -> bool
229
229
  REFINEMENT_BLOCK_SELF: :refinement
230
- # sig-gen gap: #1148 — sig-gen skips the endless-def predicate (sig.skipped.untyped-return); the row is hand-written.
231
230
  def refinement_block_self?: () -> bool
232
231
  def with_block_self_unknown: (bool flag) -> Scope
233
232
  def opaque_block_self?: () -> bool
234
233
  def with_singleton_class_body: (bool) -> Scope
235
234
  def with_declared_refinements: (Array[String] names) -> Scope
236
- # sig-gen gap: #1148 — sig-gen skips the endless-def reader (sig.skipped.untyped-return); the row is hand-written.
237
235
  def singleton_class_body?: () -> bool
238
236
  def with_discovery: (DiscoveryIndex index) -> Scope
239
237
  def local: (String | Symbol name) -> Type::t?
@@ -242,10 +240,15 @@ module Rigor
242
240
  def global: (String | Symbol name) -> Type::t?
243
241
  def local_origin: (String | Symbol name) -> Symbol?
244
242
  def ivar_origin: (String | Symbol name) -> Symbol?
243
+ # sig-gen gap: #2403 — the `Hash#[]` miss in `bound_cause` is lost across the call; sig-gen says `Symbol`.
245
244
  def optimistic_local: (String | Symbol name) -> Symbol?
245
+ # sig-gen gap: #2403 — the `Hash#[]` miss in `bound_cause` is lost across the call; sig-gen says `Symbol`.
246
246
  def optimistic_ivar: (String | Symbol name) -> Symbol?
247
247
  def optimistic_local_miss: (String | Symbol name) -> Object?
248
248
  def optimistic_ivar_miss: (String | Symbol name) -> Object?
249
+ def construction_fact?: (String | Symbol name, ?Symbol fact) -> bool
250
+ def project_method_name?: (untyped) -> (false | true)
251
+ def with_construction_fact: (untyped, untyped) -> Rigor::Scope
249
252
  def with_local: (String | Symbol name, Type::t type) -> Scope
250
253
  def with_rejoined_locals: (untyped) -> Rigor::Scope
251
254
  def with_ivar: (String | Symbol name, Type::t type) -> Scope
@@ -261,33 +264,29 @@ module Rigor
261
264
  # Issue #1446 — `rigor sig-gen` output.
262
265
  def with_guarded_ivar: (untyped name, untyped type, untyped pre_guard) -> Scope
263
266
  def without_ivar_guard: (untyped name) -> Scope
264
- # sig-gen gap: #1154 — the table reader over an ivar `initialize` assigns from a parameter reaches `untyped`.
265
267
  def guard_narrowed_ivar?: (untyped name) -> bool
266
268
  # Issue #1446 — `rigor sig-gen` output.
267
269
  def with_bot_guard_classes: (untyped kind, untyped name, untyped class_names) -> Scope
268
- # sig-gen gap: #1154 — the table reader over an ivar `initialize` assigns from a parameter reaches `untyped`.
269
270
  def bot_guard_classes_for: (untyped kind, untyped name) -> Array[String]?
270
271
  def without_constant_narrowing: (untyped key) -> Scope
271
272
  def guard_narrowed?: () -> bool
272
273
  def forget_guard_narrowings: () -> Scope
273
274
  def forget_guard_narrowing_of: (untyped kind, untyped name) -> Scope
274
275
  def without_constant_narrowings_named: (untyped name) -> Scope
275
- # sig-gen gap: #1154 — the table reader over an ivar `initialize` assigns from a parameter reaches `untyped`.
276
276
  def constant_narrowing: (String key) -> Type::t?
277
- # sig-gen gap: #1151 — an `attr_reader` over a frozen Set literal types `untyped`, as the sibling
278
- # `declaration_sourced` row does.
277
+ # authored: the element is `[Symbol, Symbol]` by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
278
+ # would never propose it.
279
279
  def published_constant_sourced: () -> Set[[Symbol, Symbol]]
280
- # sig-gen gap: #1152 — `Set#include?` over a tuple key types `untyped`, so the `bool` is hand-written.
281
280
  def published_constant_sourced?: (Symbol kind, String | Symbol name) -> bool
282
281
  def with_published_constant_mark: (Symbol kind, String | Symbol name) -> Scope
283
282
  # Issue #1362 — a `[:global_copy, local, global]` record rides beside the `(kind, name)` refs.
283
+ # authored: the element is a `[Symbol, Symbol]` or `[Symbol, Symbol, Symbol]` tuple by contract; a Set's element type stays `untyped` in sig-gen (#2177, #2317), so the generator
284
+ # would never propose it.
284
285
  def declaration_sourced: () -> Set[[Symbol, Symbol] | [Symbol, Symbol, Symbol]]
285
286
  def seed_declaration_sourced_ivar: (String | Symbol name, Type::t type) -> Scope
286
287
  def seed_declaration_sourced_global: (String | Symbol name, Type::t type) -> Scope
287
288
  def with_global_copy_marks: (String | Symbol name, Array[String | Symbol] globals) -> Scope
288
289
  def without_local_declaration_marks: (String | Symbol name) -> Scope
289
- # sig-gen gap: #1154 — the records come out of `@declaration_sourced`, an ivar assigned in `initialize` from a
290
- # parameter, which reaches `untyped`.
291
290
  def declaration_sourced_global_copies: (String | Symbol name) -> Array[Symbol]
292
291
  def with_declaration_sourced_local: (String | Symbol name, Type::t type) -> Scope
293
292
  def with_local_declaration_mark: (String | Symbol name) -> Scope
@@ -300,19 +299,15 @@ module Rigor
300
299
  def inferred_param?: (String | Symbol name) -> bool
301
300
  def forget_match_globals: () -> Scope
302
301
  def untyped_match_globals: () -> Scope
303
- # sig-gen gap: #1154 — the reader over the `@globals` ivar `initialize` assigns from a parameter reaches
304
- # `untyped`, so the `bool` is hand-written.
305
302
  def match_globals_bound?: () -> bool
306
303
  def with_match_frame: (untyped body, ?untyped parameters) -> Scope
307
- # sig-gen gap: #1154 — the frame reader over an ivar assigned in `initialize` from a parameter reaches
304
+ # sig-gen gap: #2323 — the frame reader over an ivar assigned in `initialize` from a parameter reaches
308
305
  # `untyped`, so the `bool` is hand-written.
309
306
  def match_rebinding_closure?: () -> bool
310
307
  def forget_last_line: () -> Scope
311
308
  def untyped_last_line: () -> Scope
312
- # sig-gen gap: #1154 — the reader over the `@globals` ivar `initialize` assigns from a parameter reaches
313
- # `untyped`, so the `bool` is hand-written.
314
309
  def last_line_bound?: () -> bool
315
- # sig-gen gap: #1154 — the frame reader over the `@match_frame` ivar `initialize` assigns from a parameter
310
+ # sig-gen gap: #2323 — the frame reader over the `@match_frame` ivar `initialize` assigns from a parameter
316
311
  # reaches `untyped`, so the `bool` is hand-written.
317
312
  def last_line_closure?: () -> bool
318
313
  def forget_error_info: () -> Scope
@@ -326,19 +321,22 @@ module Rigor
326
321
  def def_node_slot: (untyped class_name, untyped method_name, ?Symbol kind) -> untyped
327
322
  def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
328
323
  def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
324
+ def subclassing_opacity: () -> [false | true, Array[untyped]]
325
+ def user_instance_def_owners: (untyped) -> Array[untyped]
329
326
  def discovered_method_through_ancestors?: (String | Symbol? class_name, String | Symbol method_name, Symbol kind, ?name_memo: Hash[untyped, untyped]) -> bool
330
327
  def external_ancestor_name_candidates: (String | Symbol class_name, ?name_memo: Hash[untyped, untyped]) -> Array[Array[String]]
331
328
  def enqueue_ancestors: (String current, Array[String] queue, Hash[untyped, untyped] name_memo, ?mixins: bool) -> void
332
329
  def ancestor_name_candidates: (String | Symbol subclass_qualified, String | Symbol raw_ancestor) -> Array[String]
333
330
 
334
- # sig-gen gap: #1148 — sig-gen skips the method (sig.skipped.untyped-return: every decline returns the
335
- # frozen EMPTY_HEADER_NESTING constant); the row is hand-written.
331
+ # sig-gen gap: #2312 — sig-gen skips the method (sig.skipped.untyped-return): its non-decline arm is the result of
332
+ # the private helper `ambiguous_ancestor_resolutions_of`, whose parameters are untyped, so the arm is `untyped`.
336
333
  def ambiguous_ancestor_resolutions: (String | Symbol subclass_qualified, String | Symbol raw_ancestor) -> Array[String]
337
334
 
338
335
  # Issue #530 — public so the external-gem ancestry probe asks the same question the walk does.
339
336
  def known_user_class?: (String | Symbol name) -> bool
340
337
  def singleton_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
341
338
  def module_function_def?: (untyped, untyped) -> (false | true)
339
+ def module_function_row_def?: (untyped, untyped) -> (false | true)
342
340
  def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
343
341
  def user_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
344
342
  def user_singleton_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
@@ -349,6 +347,9 @@ module Rigor
349
347
  # sig-gen gap: #1167 — the instance-side twin: the same untyped `call_node`, the same untyped-return skip.
350
348
  def instance_def_shadows_call?: (String | Symbol class_name, String | Symbol method_name, untyped call_node) -> bool
351
349
  def top_level_def_for: (String | Symbol method_name) -> ::Prism::DefNode?
350
+ def ownerless_definition?: (untyped, ?top_level: untyped) -> (false | true)
351
+ def toplevel_def_ambiguity: (String | Symbol method_name) -> (:contested | :several | :main_singleton | :aliased | :anonymous | :object)?
352
+ def declared_class?: (String | Symbol class_name) -> bool
352
353
  def bindable_top_level_def_for: (String | Symbol method_name) -> ::Prism::DefNode?
353
354
  def toplevel?: () -> bool
354
355
  def discovered_method_visibility: (String | Symbol class_name, String | Symbol method_name) -> Symbol?
@@ -356,8 +357,8 @@ module Rigor
356
357
  def data_member_layout: (String | Symbol class_name) -> Array[Symbol]?
357
358
  def struct_member_layout: (String | Symbol class_name) -> { members: Array[Symbol], keyword_init: bool }?
358
359
  def includes_of: (String | Symbol class_name) -> Array[String]
359
- # sig-gen gap: #1153 — sig-gen proposes `Array[untyped] | []` off the empty-table early return, so the
360
- # element type is hand-written, matching {#includes_of}.
360
+ # sig-gen gap: #2302 — `names = []` grown by `concat` reads `Array[untyped]`, so the element type is
361
+ # hand-written, matching {#includes_of}.
361
362
  def singleton_extends_of: (String | Symbol class_name) -> Array[String]
362
363
  def indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Type::t?
363
364
  def with_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key, Type::t type) -> Scope
data/sig/rigor/type.rbs CHANGED
@@ -429,14 +429,8 @@ module Rigor
429
429
  attr_reader trinary: Trinary
430
430
  attr_reader mode: accepts_mode
431
431
  attr_reader reasons: Array[String]
432
- # sig-gen gap: #1155 — the memoized `||=` return is an honest union with an
433
- # untyped arm (the slot read cannot prove the memoized value), so sig-gen
434
- # skips it (sig.skipped.untyped-return); the runtime result is always
435
- # AcceptsResult and the row is hand-written.
436
432
  def self.yes: (?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> AcceptsResult
437
- # sig-gen gap: #1155 — same memoized `||=` untyped-return gap as `self.yes`.
438
433
  def self.no: (?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> AcceptsResult
439
- # sig-gen gap: #1155 — same memoized `||=` untyped-return gap as `self.yes`.
440
434
  def self.maybe: (?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> AcceptsResult
441
435
  def initialize: (Trinary trinary, ?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> void
442
436
  def yes?: () -> bool
@@ -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
@@ -218,8 +218,19 @@ baseline is a ceiling, not a blanket. Reducing it later is the
218
218
  Recommend committing `.rigor-baseline.yml` — it documents project
219
219
  state; list it in the Final step's file inventory.
220
220
 
221
+ **Rule-less diagnostics cannot be baselined.** A file Prism cannot
222
+ parse (a parse error), a missing `paths:` entry or an internal error
223
+ yields a diagnostic with no rule, so it has no `(file, rule)` bucket.
224
+ The summary then prints a second line ("N diagnostic(s) have no rule
225
+ (parse, path or internal errors) in M file(s) and cannot be
226
+ baselined") and lists the files; the command still exits 0. Acknowledge
227
+ mode reaches a green `rigor check` only after those files are fixed or
228
+ added to `exclude:`, or the bad `paths:` entry is removed. Do that
229
+ before wiring `baseline:`, then re-run `rigor baseline regenerate`.
230
+
221
231
  Print the suppression summary for the user: "N diagnostics recorded
222
- as baseline; M will surface on subsequent runs."
232
+ as baseline; M will surface on subsequent runs." Take N from the
233
+ `covering N diagnostic(s)` count, and count the unbaselineable ones in M.
223
234
 
224
235
  ## Phase 8 — Surface real bugs & offer escalation
225
236