rigortype 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (634) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/data/capability_roles/capability_roles.rbs +36 -0
  4. data/data/core_overlay/enumerable.rbs +51 -0
  5. data/data/core_overlay/enumerator.rbs +84 -0
  6. data/data/core_overlay/hash_rbs3.rbs +41 -0
  7. data/data/core_overlay/process.rbs +40 -0
  8. data/data/core_overlay/string_io.rbs +33 -0
  9. data/data/effects/core.yml +3 -3
  10. data/data/gem_overlay/activesupport/core_ext.rbs +236 -17
  11. data/docs/handbook/02-everyday-types.md +17 -14
  12. data/docs/handbook/03-narrowing.md +132 -14
  13. data/docs/handbook/04-tuples-and-shapes.md +8 -6
  14. data/docs/handbook/05-methods-and-blocks.md +1 -1
  15. data/docs/handbook/06-classes.md +2 -2
  16. data/docs/handbook/07-rbs-and-extended.md +19 -1
  17. data/docs/handbook/10-sorbet.md +9 -10
  18. data/docs/handbook/11-sig-gen.md +525 -13
  19. data/docs/handbook/README.md +1 -1
  20. data/docs/handbook/appendix-elixir.md +2 -2
  21. data/docs/handbook/appendix-go.md +2 -2
  22. data/docs/handbook/appendix-java-csharp.md +2 -2
  23. data/docs/handbook/appendix-mypy.md +2 -2
  24. data/docs/handbook/appendix-phpstan.md +1 -1
  25. data/docs/handbook/appendix-rust.md +1 -1
  26. data/docs/handbook/appendix-type-theory.md +4 -4
  27. data/docs/handbook/appendix-typescript.md +1 -1
  28. data/docs/llms.txt +2 -0
  29. data/docs/manual/02-cli-reference.md +95 -6
  30. data/docs/manual/03-configuration.md +18 -0
  31. data/docs/manual/04-diagnostics.md +15 -0
  32. data/docs/manual/07-plugins.md +15 -5
  33. data/docs/manual/08-skills.md +23 -2
  34. data/docs/manual/10-mcp-server.md +3 -2
  35. data/docs/manual/11-ci.md +9 -0
  36. data/docs/manual/15-type-protection-coverage.md +8 -0
  37. data/docs/manual/16-rbs-extended-annotations.md +46 -8
  38. data/docs/manual/18-removing-dead-code.md +10 -8
  39. data/docs/manual/19-effect-labels.md +10 -0
  40. data/docs/manual/plugins/README.md +7 -0
  41. data/docs/manual/plugins/rigor-actioncable.md +8 -1
  42. data/docs/manual/plugins/rigor-actionmailer.md +7 -0
  43. data/docs/manual/plugins/rigor-actionpack.md +261 -0
  44. data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
  45. data/docs/manual/plugins/rigor-activejob.md +7 -0
  46. data/docs/manual/plugins/rigor-activerecord.md +138 -4
  47. data/docs/manual/plugins/rigor-activestorage.md +8 -1
  48. data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
  49. data/docs/manual/plugins/rigor-grape.md +106 -0
  50. data/docs/manual/plugins/rigor-graphql.md +23 -2
  51. data/docs/manual/plugins/rigor-pundit.md +8 -1
  52. data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
  53. data/docs/manual/plugins/rigor-rails-routes.md +7 -0
  54. data/docs/manual/plugins/rigor-rbs-inline.md +229 -1
  55. data/docs/manual/plugins/rigor-sidekiq.md +8 -1
  56. data/docs/manual/plugins/rigor-sorbet.md +21 -5
  57. data/exe/rigor +19 -4
  58. data/lib/rigor/analysis/baseline.rb +3 -3
  59. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
  60. data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
  61. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
  62. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
  63. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
  64. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
  65. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
  66. data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
  67. data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
  68. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
  69. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -1
  70. data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
  71. data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
  72. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +38 -4
  73. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
  74. data/lib/rigor/analysis/check_rules.rb +718 -79
  75. data/lib/rigor/analysis/crash_signature.rb +8 -24
  76. data/lib/rigor/analysis/dependency_recorder.rb +23 -0
  77. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
  78. data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
  79. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
  80. data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
  81. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
  82. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  83. data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
  84. data/lib/rigor/analysis/erb_template_detector.rb +1 -2
  85. data/lib/rigor/analysis/fact_store.rb +15 -1
  86. data/lib/rigor/analysis/incremental.rb +42 -0
  87. data/lib/rigor/analysis/incremental_session.rb +117 -26
  88. data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
  89. data/lib/rigor/analysis/project_scan.rb +11 -1
  90. data/lib/rigor/analysis/reachability/graph.rb +3 -5
  91. data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
  92. data/lib/rigor/analysis/reachability/project_files.rb +2 -2
  93. data/lib/rigor/analysis/reachability/scan.rb +5 -5
  94. data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
  95. data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
  96. data/lib/rigor/analysis/result.rb +1 -3
  97. data/lib/rigor/analysis/rule_catalog.rb +131 -1
  98. data/lib/rigor/analysis/run_cache_key.rb +21 -12
  99. data/lib/rigor/analysis/run_cache_probe.rb +3 -5
  100. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
  101. data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
  102. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
  103. data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
  104. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
  105. data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
  106. data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
  107. data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
  108. data/lib/rigor/analysis/runner.rb +407 -51
  109. data/lib/rigor/analysis/template_unit_collector.rb +303 -0
  110. data/lib/rigor/analysis/template_unit_paths.rb +91 -0
  111. data/lib/rigor/analysis/template_unit_positions.rb +293 -0
  112. data/lib/rigor/analysis/template_units.rb +399 -0
  113. data/lib/rigor/analysis/worker_session.rb +62 -20
  114. data/lib/rigor/bleeding_edge.rb +10 -24
  115. data/lib/rigor/builtins/hkt_builtins.rb +3 -2
  116. data/lib/rigor/builtins/imported_refinements.rb +159 -21
  117. data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
  118. data/lib/rigor/builtins/regex_refinement.rb +21 -13
  119. data/lib/rigor/builtins/static_return_refinements.rb +7 -6
  120. data/lib/rigor/cache/annotation_location.rb +2 -4
  121. data/lib/rigor/cache/descriptor.rb +63 -20
  122. data/lib/rigor/cache/engine_source.rb +33 -5
  123. data/lib/rigor/cache/file_digest.rb +9 -1
  124. data/lib/rigor/cache/incremental_snapshot.rb +72 -6
  125. data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
  126. data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
  127. data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
  128. data/lib/rigor/cache/rbs_constant_table.rb +0 -3
  129. data/lib/rigor/cache/rbs_descriptor.rb +112 -14
  130. data/lib/rigor/cache/rbs_environment.rb +8 -4
  131. data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
  132. data/lib/rigor/cache/store.rb +76 -32
  133. data/lib/rigor/ci_detector.rb +1 -0
  134. data/lib/rigor/cli/annotate_command.rb +5 -6
  135. data/lib/rigor/cli/check_command.rb +57 -10
  136. data/lib/rigor/cli/check_invocation.rb +6 -11
  137. data/lib/rigor/cli/check_runner_factory.rb +1 -5
  138. data/lib/rigor/cli/coverage_command.rb +1 -1
  139. data/lib/rigor/cli/coverage_mutation.rb +12 -3
  140. data/lib/rigor/cli/coverage_scan.rb +1 -5
  141. data/lib/rigor/cli/diff_command.rb +1 -1
  142. data/lib/rigor/cli/doc_links.rb +4 -4
  143. data/lib/rigor/cli/docs_command.rb +6 -6
  144. data/lib/rigor/cli/doctor_command.rb +85 -38
  145. data/lib/rigor/cli/effects_command.rb +2 -2
  146. data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
  147. data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
  148. data/lib/rigor/cli/explain_command.rb +34 -1
  149. data/lib/rigor/cli/fused_protection_report.rb +7 -1
  150. data/lib/rigor/cli/lsp_command.rb +1 -1
  151. data/lib/rigor/cli/mcp_command.rb +1 -1
  152. data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
  153. data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
  154. data/lib/rigor/cli/mutation_protection_report.rb +7 -1
  155. data/lib/rigor/cli/plugin_command.rb +4 -4
  156. data/lib/rigor/cli/plugins_command.rb +2 -1
  157. data/lib/rigor/cli/prism_colorizer.rb +1 -2
  158. data/lib/rigor/cli/protection_fork_scan.rb +6 -6
  159. data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
  160. data/lib/rigor/cli/sig_gen_command.rb +212 -31
  161. data/lib/rigor/cli/skill_command.rb +2 -2
  162. data/lib/rigor/cli/skill_deep_probe.rb +4 -4
  163. data/lib/rigor/cli/skill_describe.rb +35 -35
  164. data/lib/rigor/cli/trace_command.rb +4 -4
  165. data/lib/rigor/cli/trace_renderer.rb +5 -6
  166. data/lib/rigor/cli/triage_command.rb +1 -1
  167. data/lib/rigor/cli/type_of_command.rb +29 -11
  168. data/lib/rigor/cli/type_of_renderer.rb +20 -9
  169. data/lib/rigor/cli/type_of_template_probe.rb +189 -0
  170. data/lib/rigor/cli/type_scan_command.rb +4 -4
  171. data/lib/rigor/cli/unused_command.rb +11 -3
  172. data/lib/rigor/cli/upgrade_command.rb +1 -1
  173. data/lib/rigor/cli.rb +89 -9
  174. data/lib/rigor/config_audit.rb +30 -5
  175. data/lib/rigor/configuration/severity_profile.rb +25 -9
  176. data/lib/rigor/configuration.rb +109 -7
  177. data/lib/rigor/effects/ancestry_recorder.rb +191 -0
  178. data/lib/rigor/effects/attribution.rb +12 -5
  179. data/lib/rigor/effects/callee_rule.rb +368 -0
  180. data/lib/rigor/effects/catalog.rb +7 -4
  181. data/lib/rigor/effects/collector.rb +11 -5
  182. data/lib/rigor/effects/config_envelopes.rb +15 -10
  183. data/lib/rigor/effects/definition_context.rb +179 -0
  184. data/lib/rigor/effects/definition_lines.rb +25 -6
  185. data/lib/rigor/effects/effect_table.rb +11 -4
  186. data/lib/rigor/effects/entry_points.rb +0 -2
  187. data/lib/rigor/effects/envelope_check.rb +9 -9
  188. data/lib/rigor/effects/envelope_index.rb +20 -8
  189. data/lib/rigor/effects/file_collection.rb +59 -5
  190. data/lib/rigor/effects/framework_units.rb +5 -7
  191. data/lib/rigor/effects/identity.rb +20 -6
  192. data/lib/rigor/effects/inline_anchor.rb +7 -7
  193. data/lib/rigor/effects/label_intent.rb +3 -4
  194. data/lib/rigor/effects/liskov_check.rb +8 -8
  195. data/lib/rigor/effects/local_ownership.rb +38 -12
  196. data/lib/rigor/effects/method_key.rb +22 -1
  197. data/lib/rigor/effects/mutation_classifier.rb +23 -12
  198. data/lib/rigor/effects/plugin_facts.rb +47 -37
  199. data/lib/rigor/effects/propagator.rb +297 -19
  200. data/lib/rigor/effects/registry.rb +1 -1
  201. data/lib/rigor/effects/scanner.rb +122 -73
  202. data/lib/rigor/effects/signature_sources.rb +4 -6
  203. data/lib/rigor/effects/snapshot.rb +12 -11
  204. data/lib/rigor/effects/snapshot_diff.rb +1 -1
  205. data/lib/rigor/effects/summary.rb +27 -4
  206. data/lib/rigor/effects/unit_scan.rb +393 -38
  207. data/lib/rigor/effects/unknown_label_check.rb +3 -8
  208. data/lib/rigor/effects/unknown_label_report.rb +3 -4
  209. data/lib/rigor/effects/visibility.rb +101 -0
  210. data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
  211. data/lib/rigor/environment/class_registry.rb +3 -1
  212. data/lib/rigor/environment/failure_slot.rb +2 -2
  213. data/lib/rigor/environment/installed_gem_set.rb +85 -0
  214. data/lib/rigor/environment/lockfile_resolver.rb +68 -4
  215. data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
  216. data/lib/rigor/environment/member_consistency.rb +298 -0
  217. data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
  218. data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
  219. data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
  220. data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
  221. data/lib/rigor/environment/rbs_loader.rb +674 -79
  222. data/lib/rigor/environment.rb +174 -24
  223. data/lib/rigor/flow_contribution/merger.rb +0 -2
  224. data/lib/rigor/flow_contribution.rb +11 -13
  225. data/lib/rigor/hashing/xxh3.rb +264 -0
  226. data/lib/rigor/inference/acceptance.rb +292 -17
  227. data/lib/rigor/inference/block_auto_splat.rb +216 -0
  228. data/lib/rigor/inference/block_call_timing.rb +338 -0
  229. data/lib/rigor/inference/block_parameter_binder.rb +75 -30
  230. data/lib/rigor/inference/block_repetition.rb +71 -0
  231. data/lib/rigor/inference/body_fixpoint.rb +7 -6
  232. data/lib/rigor/inference/budget_trace.rb +3 -6
  233. data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
  234. data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
  235. data/lib/rigor/inference/captured_locals.rb +389 -18
  236. data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
  237. data/lib/rigor/inference/content_join.rb +200 -27
  238. data/lib/rigor/inference/coverage_scanner.rb +4 -6
  239. data/lib/rigor/inference/def_return_typer.rb +11 -7
  240. data/lib/rigor/inference/define_method_block_self.rb +64 -0
  241. data/lib/rigor/inference/dynamic_origin.rb +1 -1
  242. data/lib/rigor/inference/element_read_widening.rb +180 -0
  243. data/lib/rigor/inference/error_info.rb +196 -0
  244. data/lib/rigor/inference/expression_typer.rb +2124 -468
  245. data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
  246. data/lib/rigor/inference/fork_map.rb +5 -7
  247. data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
  248. data/lib/rigor/inference/global_write_census.rb +239 -0
  249. data/lib/rigor/inference/guard_rebinding.rb +447 -0
  250. data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
  251. data/lib/rigor/inference/hkt_reducer.rb +2 -3
  252. data/lib/rigor/inference/hkt_registry.rb +4 -7
  253. data/lib/rigor/inference/index_write_widening.rb +16 -7
  254. data/lib/rigor/inference/indexed_narrowing.rb +61 -9
  255. data/lib/rigor/inference/jump_targets.rb +82 -0
  256. data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
  257. data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
  258. data/lib/rigor/inference/last_line.rb +340 -0
  259. data/lib/rigor/inference/last_status.rb +144 -0
  260. data/lib/rigor/inference/macro_block_self_type.rb +168 -21
  261. data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
  262. data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
  263. data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
  264. data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
  265. data/lib/rigor/inference/match_rebinding.rb +392 -0
  266. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
  267. data/lib/rigor/inference/method_dispatcher/block_folding.rb +87 -33
  268. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
  269. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
  270. data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
  271. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
  272. data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
  273. data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
  274. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
  275. data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
  276. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
  277. data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
  278. data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
  279. data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
  280. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
  281. data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
  282. data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
  283. data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
  284. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
  285. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
  286. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
  287. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
  288. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
  289. data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
  290. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
  291. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
  292. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
  293. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
  294. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
  295. data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
  296. data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
  297. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  298. data/lib/rigor/inference/method_dispatcher.rb +225 -25
  299. data/lib/rigor/inference/method_parameter_binder.rb +12 -9
  300. data/lib/rigor/inference/multi_target_binder.rb +341 -55
  301. data/lib/rigor/inference/mutation_rejoin.rb +171 -0
  302. data/lib/rigor/inference/mutation_widening.rb +156 -85
  303. data/lib/rigor/inference/narrowing.rb +835 -162
  304. data/lib/rigor/inference/operand_effects.rb +167 -0
  305. data/lib/rigor/inference/operand_walk.rb +88 -0
  306. data/lib/rigor/inference/optimistic_origin.rb +153 -16
  307. data/lib/rigor/inference/origin_lookup.rb +2 -3
  308. data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
  309. data/lib/rigor/inference/pre_eval_constants.rb +6 -5
  310. data/lib/rigor/inference/precision_scanner.rb +3 -4
  311. data/lib/rigor/inference/project_method_ownership.rb +136 -0
  312. data/lib/rigor/inference/project_patched_methods.rb +9 -4
  313. data/lib/rigor/inference/project_patched_scanner.rb +10 -6
  314. data/lib/rigor/inference/protection_scanner.rb +1 -2
  315. data/lib/rigor/inference/range_constant.rb +57 -0
  316. data/lib/rigor/inference/rbs_type_translator.rb +49 -11
  317. data/lib/rigor/inference/receiver_alias.rb +93 -4
  318. data/lib/rigor/inference/receiver_blind_block.rb +219 -0
  319. data/lib/rigor/inference/refinement_mutation.rb +76 -0
  320. data/lib/rigor/inference/repeated_or_writes.rb +463 -0
  321. data/lib/rigor/inference/return_barrier.rb +54 -0
  322. data/lib/rigor/inference/rewrite_mutation.rb +120 -0
  323. data/lib/rigor/inference/scope_indexer.rb +5228 -627
  324. data/lib/rigor/inference/statement_evaluator.rb +3452 -595
  325. data/lib/rigor/inference/stored_block_call.rb +54 -0
  326. data/lib/rigor/inference/string_mutation.rb +97 -0
  327. data/lib/rigor/inference/struct_fold_safety.rb +6 -7
  328. data/lib/rigor/inference/synthetic_method_index.rb +1 -2
  329. data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
  330. data/lib/rigor/inference/unknown_store_widening.rb +200 -0
  331. data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
  332. data/lib/rigor/inference/version_guard.rb +28 -21
  333. data/lib/rigor/inference/void_origin.rb +3 -3
  334. data/lib/rigor/inference/void_tail_summary.rb +2 -4
  335. data/lib/rigor/language_server/buffer_table.rb +4 -4
  336. data/lib/rigor/language_server/completion_provider.rb +1 -1
  337. data/lib/rigor/language_server/debouncer.rb +0 -1
  338. data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
  339. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  340. data/lib/rigor/language_server/folding_range_provider.rb +1 -1
  341. data/lib/rigor/language_server/hover_provider.rb +1 -1
  342. data/lib/rigor/language_server/hover_renderer.rb +4 -4
  343. data/lib/rigor/language_server/incremental_sync.rb +6 -6
  344. data/lib/rigor/language_server/project_context.rb +7 -8
  345. data/lib/rigor/language_server/publish_batcher.rb +2 -2
  346. data/lib/rigor/language_server/selection_range_provider.rb +2 -2
  347. data/lib/rigor/language_server/server.rb +9 -9
  348. data/lib/rigor/language_server/signature_help_provider.rb +1 -1
  349. data/lib/rigor/language_server/uri.rb +1 -1
  350. data/lib/rigor/mcp/server.rb +2 -1
  351. data/lib/rigor/plugin/base.rb +258 -26
  352. data/lib/rigor/plugin/box_probe.rb +91 -0
  353. data/lib/rigor/plugin/bundled_catalog.rb +167 -0
  354. data/lib/rigor/plugin/effect_attribution.rb +65 -11
  355. data/lib/rigor/plugin/effect_entry_points.rb +3 -3
  356. data/lib/rigor/plugin/fact_store.rb +6 -6
  357. data/lib/rigor/plugin/io_boundary.rb +93 -8
  358. data/lib/rigor/plugin/isolation.rb +29 -6
  359. data/lib/rigor/plugin/loader.rb +33 -13
  360. data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
  361. data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
  362. data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
  363. data/lib/rigor/plugin/manifest.rb +94 -11
  364. data/lib/rigor/plugin/registry.rb +76 -12
  365. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
  366. data/lib/rigor/plugin/template_unit.rb +196 -0
  367. data/lib/rigor/plugin/trust_policy.rb +2 -4
  368. data/lib/rigor/plugin/type_node_resolver.rb +3 -3
  369. data/lib/rigor/plugin.rb +1 -0
  370. data/lib/rigor/plugin_gap_advisory.rb +96 -0
  371. data/lib/rigor/project_environment.rb +138 -0
  372. data/lib/rigor/protection/analysis_guard.rb +93 -14
  373. data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
  374. data/lib/rigor/protection/dependency_closure.rb +5 -8
  375. data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
  376. data/lib/rigor/protection/discovery_seed.rb +14 -12
  377. data/lib/rigor/protection/kill_signature.rb +1 -4
  378. data/lib/rigor/protection/measurement_integrity.rb +1 -3
  379. data/lib/rigor/protection/mutation_cache.rb +7 -11
  380. data/lib/rigor/protection/mutation_scanner.rb +12 -15
  381. data/lib/rigor/protection/mutator.rb +2 -1
  382. data/lib/rigor/protection/test_suite_oracle.rb +5 -5
  383. data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
  384. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  385. data/lib/rigor/rbs_extended/reporter.rb +36 -10
  386. data/lib/rigor/rbs_extended.rb +88 -21
  387. data/lib/rigor/reflection/constant_ancestors.rb +97 -0
  388. data/lib/rigor/reflection/constant_path.rb +139 -0
  389. data/lib/rigor/reflection.rb +93 -110
  390. data/lib/rigor/runtime/jit.rb +6 -8
  391. data/lib/rigor/scope/discovery_index.rb +165 -2
  392. data/lib/rigor/scope.rb +1041 -32
  393. data/lib/rigor/sig_gen/alias_index.rb +289 -0
  394. data/lib/rigor/sig_gen/classification.rb +22 -5
  395. data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
  396. data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
  397. data/lib/rigor/sig_gen/generator.rb +673 -53
  398. data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
  399. data/lib/rigor/sig_gen/layout_index.rb +3 -4
  400. data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
  401. data/lib/rigor/sig_gen/method_candidate.rb +47 -3
  402. data/lib/rigor/sig_gen/observation_collector.rb +18 -16
  403. data/lib/rigor/sig_gen/path_mapper.rb +4 -6
  404. data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
  405. data/lib/rigor/sig_gen/renderer.rb +128 -14
  406. data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
  407. data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
  408. data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
  409. data/lib/rigor/sig_gen/write_result.rb +19 -3
  410. data/lib/rigor/sig_gen/writer.rb +189 -41
  411. data/lib/rigor/sig_gen.rb +3 -0
  412. data/lib/rigor/signature_path_audit.rb +153 -6
  413. data/lib/rigor/source/literals.rb +0 -23
  414. data/lib/rigor/source/node_children.rb +0 -2
  415. data/lib/rigor/source/node_locator.rb +5 -11
  416. data/lib/rigor/source/node_walker.rb +0 -6
  417. data/lib/rigor/source/parameter_envelope.rb +72 -0
  418. data/lib/rigor/source.rb +1 -0
  419. data/lib/rigor/triage/catalogue.rb +1 -3
  420. data/lib/rigor/triage.rb +3 -5
  421. data/lib/rigor/type/accepts_result.rb +24 -6
  422. data/lib/rigor/type/combinator.rb +144 -5
  423. data/lib/rigor/type/data_class.rb +2 -2
  424. data/lib/rigor/type/data_instance.rb +4 -4
  425. data/lib/rigor/type/difference.rb +1 -0
  426. data/lib/rigor/type/float_range.rb +128 -0
  427. data/lib/rigor/type/hash_shape.rb +6 -6
  428. data/lib/rigor/type/integer_range.rb +13 -8
  429. data/lib/rigor/type/nominal.rb +8 -2
  430. data/lib/rigor/type/refined.rb +4 -3
  431. data/lib/rigor/type/struct_class.rb +3 -3
  432. data/lib/rigor/type/struct_instance.rb +4 -4
  433. data/lib/rigor/type.rb +1 -0
  434. data/lib/rigor/type_node/generic.rb +1 -1
  435. data/lib/rigor/type_node/range_literal.rb +25 -0
  436. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  437. data/lib/rigor/type_node.rb +1 -0
  438. data/lib/rigor/version.rb +1 -1
  439. data/lib/rigor.rb +1 -0
  440. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
  441. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
  442. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
  443. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
  444. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
  445. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
  446. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
  447. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
  448. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
  449. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
  450. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
  451. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
  452. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
  453. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
  454. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
  455. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
  456. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
  457. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
  458. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +264 -3
  459. data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
  460. data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
  461. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
  462. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
  463. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
  464. data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
  465. data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
  466. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
  467. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
  468. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
  469. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
  470. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
  471. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -5
  472. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
  473. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
  474. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +383 -7
  475. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
  476. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
  477. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
  478. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
  479. data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
  480. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
  481. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
  482. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
  483. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
  484. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
  485. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
  486. data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
  487. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
  488. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
  489. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
  490. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
  491. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
  492. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
  493. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
  494. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
  495. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
  496. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
  497. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
  498. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
  499. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
  500. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
  501. data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
  502. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
  503. data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
  504. data/plugins/rigor-grape/sig/grape.rbs +263 -0
  505. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
  506. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
  507. data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
  508. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
  509. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
  510. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
  511. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
  512. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
  513. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
  514. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
  515. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
  516. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
  517. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
  518. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
  519. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
  520. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
  521. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
  522. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
  523. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
  524. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
  525. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
  526. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
  527. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
  528. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
  529. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
  530. data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
  531. data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
  532. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
  533. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +324 -18
  534. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
  535. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
  536. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
  537. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
  538. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
  539. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
  540. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
  541. data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
  542. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
  543. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
  544. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
  545. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
  546. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
  547. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
  548. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
  549. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
  550. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
  551. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
  552. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
  553. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
  554. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
  555. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
  556. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
  557. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
  558. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
  559. data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
  560. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
  561. data/sig/rigor/analysis/baseline.rbs +69 -7
  562. data/sig/rigor/analysis/fact_store.rbs +1 -1
  563. data/sig/rigor/analysis/project_scan.rbs +74 -0
  564. data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
  565. data/sig/rigor/cache.rbs +2 -3
  566. data/sig/rigor/effects/config_envelopes.rbs +100 -0
  567. data/sig/rigor/effects/effect_table.rbs +60 -0
  568. data/sig/rigor/effects/envelope.rbs +97 -0
  569. data/sig/rigor/effects/envelope_index.rbs +33 -0
  570. data/sig/rigor/effects/file_collection.rbs +81 -0
  571. data/sig/rigor/effects/label.rbs +26 -0
  572. data/sig/rigor/effects/label_set.rbs +46 -0
  573. data/sig/rigor/effects/method_key.rbs +24 -0
  574. data/sig/rigor/effects/origin.rbs +50 -0
  575. data/sig/rigor/effects/plugin_facts.rbs +141 -0
  576. data/sig/rigor/effects/registry.rbs +68 -0
  577. data/sig/rigor/effects/summary.rbs +50 -0
  578. data/sig/rigor/effects/taint_cause.rbs +12 -0
  579. data/sig/rigor/environment.rbs +17 -10
  580. data/sig/rigor/inference/optimistic_origin.rbs +10 -0
  581. data/sig/rigor/inference.rbs +9 -14
  582. data/sig/rigor/plugin/additional_initializer.rbs +36 -0
  583. data/sig/rigor/plugin/base.rbs +30 -7
  584. data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
  585. data/sig/rigor/plugin/effect_attribution.rbs +66 -0
  586. data/sig/rigor/plugin/effect_edge.rbs +33 -0
  587. data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
  588. data/sig/rigor/plugin/io_boundary.rbs +4 -0
  589. data/sig/rigor/plugin/loader.rbs +3 -3
  590. data/sig/rigor/plugin/manifest.rbs +51 -11
  591. data/sig/rigor/plugin/protocol_contract.rbs +68 -0
  592. data/sig/rigor/plugin/registry.rbs +62 -1
  593. data/sig/rigor/plugin.rbs +1 -1
  594. data/sig/rigor/rbs_extended.rbs +1 -1
  595. data/sig/rigor/reflection.rbs +9 -6
  596. data/sig/rigor/scope.rbs +148 -12
  597. data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
  598. data/sig/rigor/source.rbs +4 -4
  599. data/sig/rigor/testing.rbs +10 -4
  600. data/sig/rigor/type.rbs +33 -1
  601. data/sig/rigor.rbs +39 -20
  602. data/skills/rigor-ask/SKILL.md +16 -11
  603. data/skills/rigor-baseline-reduce/SKILL.md +4 -6
  604. data/skills/rigor-ci-setup/SKILL.md +17 -21
  605. data/skills/rigor-doctor/SKILL.md +24 -22
  606. data/skills/rigor-doctor/references/01-checks.md +97 -33
  607. data/skills/rigor-editor-setup/SKILL.md +6 -4
  608. data/skills/rigor-mcp-setup/SKILL.md +5 -4
  609. data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
  610. data/skills/rigor-next-steps/SKILL.md +4 -2
  611. data/skills/rigor-plugin-author/SKILL.md +19 -23
  612. data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
  613. data/skills/rigor-plugin-author/references/02-walker-and-types.md +25 -27
  614. data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
  615. data/skills/rigor-plugin-review/SKILL.md +6 -4
  616. data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
  617. data/skills/rigor-plugin-tune/SKILL.md +4 -2
  618. data/skills/rigor-project-init/SKILL.md +15 -10
  619. data/skills/rigor-project-init/references/01-detect.md +13 -9
  620. data/skills/rigor-project-init/references/02-configure.md +43 -14
  621. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
  622. data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
  623. data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
  624. data/skills/rigor-protection-uplift/SKILL.md +4 -6
  625. data/skills/rigor-rbs-setup/SKILL.md +4 -2
  626. data/skills/rigor-type-oracle/SKILL.md +226 -0
  627. data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
  628. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
  629. data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
  630. data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
  631. data/skills/rigor-upgrade/SKILL.md +13 -8
  632. metadata +133 -3
  633. data/lib/rigor/cli/probe_environment.rb +0 -85
  634. data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
@@ -0,0 +1,141 @@
1
+ module Rigor
2
+ module Effects
3
+ # The loaded plugins' effect contributions, compiled once per process (ADR-103): attribution rows
4
+ # indexed by receiver spelling, framework-edge strategies, label vocabulary, entry-point presets,
5
+ # and plugin-claimed ancestry.
6
+ class PluginFacts
7
+ # How many ancestors the walk visits before giving up — bounds work, not correctness.
8
+ ANCESTRY_CAP: Integer
9
+
10
+ # One compiled attribution row. `discharge` is the RESOLVED grant — `.build` has already
11
+ # demoted a non-first-party plugin's `true` and recorded a warning.
12
+ class Row < ::Data
13
+ # sig-gen gap: #1150 — `Data.define` member reads carry no type.
14
+ def key: () -> String
15
+ # sig-gen gap: #1150
16
+ def labels: () -> LabelSet
17
+ # sig-gen gap: #1150 — a {Narrowing} handler name, when the call's own arguments settle the
18
+ # row's answer.
19
+ def narrow: () -> String?
20
+ # sig-gen gap: #1150
21
+ def discharge: () -> bool
22
+ # sig-gen gap: #1150 — the class a `self`-path row is scoped to.
23
+ def within: () -> String?
24
+ # sig-gen gap: #1150 — the taint cause the row seeds where its edge resolves to nothing.
25
+ def taint: () -> String?
26
+ # sig-gen gap: #1150
27
+ def plugin_id: () -> String
28
+ # sig-gen gap: #1150 — the receiver a UNIT rule has no call node to read off.
29
+ def receiver: () -> String?
30
+ # sig-gen gap: #1150 — the {CalleeRule} rule name (#1048), nil when the row records no edge.
31
+ def callee: () -> String?
32
+ # sig-gen gap: #1150 — the plugin's lookup-order table for the rule's answer (#1065).
33
+ def callee_fallbacks: () -> Hash[String, Array[String]]?
34
+ # sig-gen gap: #1150
35
+ def responds: () -> bool
36
+
37
+ # sig-gen gap: #1150 — member constructor. The custom `initialize` accepts kwargs only and
38
+ # defaults `receiver` / `callee` / `callee_fallbacks` / `responds`, so there is no
39
+ # positional arm.
40
+ def self.new: (key: String, labels: LabelSet, narrow: String?, discharge: bool,
41
+ within: String?, taint: String?, plugin_id: String, ?receiver: String?,
42
+ ?callee: String?, ?callee_fallbacks: Hash[String, Array[String]]?,
43
+ ?responds: bool) -> instance
44
+ # sig-gen gap: #1150 — as above.
45
+ def self.[]: (key: String, labels: LabelSet, narrow: String?, discharge: bool,
46
+ within: String?, taint: String?, plugin_id: String, ?receiver: String?,
47
+ ?callee: String?, ?callee_fallbacks: Hash[String, Array[String]]?,
48
+ ?responds: bool) -> instance
49
+
50
+ def discharge?: () -> bool
51
+ end
52
+
53
+ # One compiled framework-edge strategy: the base class a plugin pointed the engine at, and
54
+ # which plugin pointed.
55
+ class Edge < ::Data
56
+ # sig-gen gap: #1150 — `Data.define` member reads carry no type. `target` is the closed
57
+ # {Plugin::EffectEdge::TARGETS} set.
58
+ def target: () -> (:activerecord_callbacks | :perform_now | :mailer_body)
59
+ # sig-gen gap: #1150
60
+ def receiver: () -> String
61
+ # sig-gen gap: #1150 — nil for a whole-class edge (`method` omitted).
62
+ def selector: () -> Symbol?
63
+ # sig-gen gap: #1150
64
+ def plugin_id: () -> String
65
+
66
+ # sig-gen gap: #1150 — member constructor.
67
+ def self.new: (target: (:activerecord_callbacks | :perform_now | :mailer_body),
68
+ receiver: String, selector: Symbol?, plugin_id: String) -> instance
69
+ | ((:activerecord_callbacks | :perform_now | :mailer_body) target, String receiver,
70
+ Symbol? selector, String plugin_id) -> instance
71
+ # sig-gen gap: #1150 — as above.
72
+ def self.[]: (target: (:activerecord_callbacks | :perform_now | :mailer_body),
73
+ receiver: String, selector: Symbol?, plugin_id: String) -> instance
74
+ end
75
+
76
+ # The rows whose `callee:` names a {CalleeRule::UNIT_RULES} rule — applied once per unit.
77
+ # Unmarked residue: populated by `absorb_attribution`, not assigned from an `initialize`
78
+ # parameter, so no gap issue covers it (same shape as `Registry#additional_initializers`).
79
+ attr_reader unit_callee_rows: Array[Row]
80
+
81
+ # Human-readable notes about contributions accepted only in part. Surfaced by `rigor effects`;
82
+ # never a diagnostic. Unmarked residue — accumulated by `absorb`/`extend_registry`.
83
+ attr_reader warnings: Array[String]
84
+
85
+ # `{owner => [labels]}` — what {#extend_registry} folds into the run's vocabulary.
86
+ # Unmarked residue — built by `absorb`, not an `initialize` parameter.
87
+ attr_reader labels_by_owner: Hash[String, Array[String]]
88
+
89
+ # Every `effect_entry_points:` preset across the loaded set.
90
+ # Unmarked residue — concatenated by `absorb`, not an `initialize` parameter.
91
+ attr_reader entry_points: Array[Plugin::EffectEntryPoints]
92
+
93
+ # A content digest of every compiled plugin fact; {Identity} folds it in.
94
+ # Unmarked residue — computed by `compute_digest`, not an `initialize` parameter.
95
+ attr_reader digest: String
96
+
97
+ def self.empty: () -> PluginFacts
98
+
99
+ # `superclasses`/`includes` are the project's as-written ancestry tables
100
+ # (`Scope::DiscoveryIndex#discovered_superclasses` / `#discovered_includes`).
101
+ def self.build: (Plugin::Registry? plugin_registry, ?superclasses: Hash[String, String]?,
102
+ ?includes: Hash[String, Array[String]]?) -> PluginFacts
103
+
104
+ # `contributions:` elements are `Plugin::Registry::Contribution` rows.
105
+ def initialize: (contributions: Array[Plugin::Registry::Contribution],
106
+ superclasses: Hash[String, String]?,
107
+ ?includes: Hash[String, Array[String]]?) -> void
108
+
109
+ def empty?: () -> bool
110
+
111
+ # Whether any attribution row exists at all — the scan's fast path.
112
+ def attributions?: () -> bool
113
+ def edges?: () -> bool
114
+
115
+ # The row colouring `owner`'s `selector`, on `owner` itself or a project ancestor.
116
+ def class_row: (String? owner, bool singleton, String selector) -> Row?
117
+
118
+ # The row colouring receiver `path`'s `selector` (`"Rails.cache"`) — exact, no ancestry walk.
119
+ def path_row: (String? path, String selector) -> Row?
120
+
121
+ # The row colouring `path`'s `selector` for a self-rooted receiver (`"self.flash.now"`) inside
122
+ # a unit whose class is `owner_class`.
123
+ def self_path_row: (String? path, String selector, String? owner_class) -> Row?
124
+
125
+ # The row colouring `selector` on the RESULT of a call to `producer` (or an ancestor of it).
126
+ def result_row: (String? producer, String selector) -> Row?
127
+
128
+ # The framework-edge strategies of one kind, e.g. every `:activerecord_callbacks` base class
129
+ # the loaded plugins named.
130
+ def edges_for: (Symbol target) -> Array[Edge]
131
+
132
+ # Whether `class_name` is `ancestor`, or reaches it through the project's own `class … <`
133
+ # lines and included modules.
134
+ def descends_from?: (String? class_name, String? ancestor) -> bool
135
+
136
+ # `registry` extended with every plugin's `effect_labels:` under its own owner. Rejected
137
+ # extensions land in {#warnings} instead of raising.
138
+ def extend_registry: (Registry registry) -> Registry
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,68 @@
1
+ module Rigor
2
+ module Effects
3
+ # The effect-label vocabulary: which spellings are recognised, which have been retired, and who
4
+ # may open a new root (ADR-103 WD2; normative in `docs/type-specification/effect-labels.md`).
5
+ # A frozen value object; {#with} returns a new one rather than mutating.
6
+ class Registry
7
+ class Error < StandardError
8
+ end
9
+
10
+ # An added label whose root neither exists already nor belongs to the extender.
11
+ class OwnershipError < Error
12
+ end
13
+
14
+ # An added label that is not well-formed under {Label::PATTERN}.
15
+ class InvalidLabelError < Error
16
+ end
17
+
18
+ DATA_PATH: String
19
+
20
+ # How far a misspelling may be from a known label before {#suggest} declines to guess.
21
+ SUGGESTION_DISTANCE_CAP: Integer
22
+
23
+ # The shared registry as shipped, memoised per process.
24
+ def self.default: () -> Registry
25
+
26
+ # The vocabulary one run works in: the shipped registry plus `effects.labels:` and every
27
+ # loaded plugin's `effect_labels:` (ADR-103 WD2 / #385 / #387). Fail-soft: a rejected
28
+ # extension degrades to the shipped vocabulary.
29
+ def self.for_configuration: (Configuration configuration, ?plugin_facts: PluginFacts?) -> Registry
30
+
31
+ # Build a registry from a registry-shaped YAML file. Missing or unreadable data degrades to
32
+ # an empty vocabulary (fail-open).
33
+ def self.load_file: (untyped path) -> Registry
34
+
35
+ # sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from the
36
+ # parameter of the same name; sig-gen proposes `untyped` for it.
37
+ attr_reader vocabulary_version: Integer
38
+ # sig-gen gap: #1154 — every declared label, sorted; implied ancestors are recognised by
39
+ # {#known?} but not listed here.
40
+ attr_reader labels: Array[String]
41
+ # The roots of the vocabulary — the outermost segments {#with} treats as already owned.
42
+ # Unmarked residue: `@roots` is computed from `@known` in `initialize`, not assigned from a
43
+ # parameter, so #1154 does not cover it.
44
+ attr_reader roots: Array[String]
45
+ # sig-gen gap: #1154 — one line per root, from the data file's `descriptions:`.
46
+ attr_reader descriptions: Hash[String, String]
47
+
48
+ def initialize: (vocabulary_version: Integer, labels: Array[untyped],
49
+ ?retired: Hash[untyped, untyped],
50
+ ?descriptions: Hash[untyped, untyped]) -> void
51
+
52
+ # Whether the vocabulary recognises `label`: an exact row, or an ancestor of one.
53
+ def known?: (untyped label) -> bool
54
+
55
+ # The nearest recognised label to a misspelling within {SUGGESTION_DISTANCE_CAP} edits, or
56
+ # nil when nothing is close enough.
57
+ def suggest: (untyped label) -> String?
58
+
59
+ # The replacement labels for a retired spelling, or nil when it was never retired.
60
+ def retired: (untyped label) -> Array[String]?
61
+
62
+ # A new registry carrying `labels` on top of this one. `owner` is the identity opening a
63
+ # root — a plugin id, or a first-party plugin's framework root; nil is the project, which
64
+ # may open any root.
65
+ def with: (labels: Array[untyped], owner: String?) -> Registry
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ module Rigor
2
+ module Effects
3
+ # One method's direct effect record: the labels its own body contributes, grouped by the origin
4
+ # that claimed them, plus the declared (`<=`) lane, the exhaustiveness bit, and the taint causes.
5
+ class Summary
6
+ TRIVIAL_BOUND: LabelSet
7
+
8
+ # The pure-modulo-frame-ownership summary: no origins, nothing declared, exhaustive, untainted.
9
+ def self.empty: () -> Summary
10
+
11
+ # A summary carrying a single taint and no labels — the fail-soft answer for a unit the collector
12
+ # could not finish.
13
+ def self.tainted: (String cause, ?String? detail) -> Summary
14
+
15
+ # sig-gen gap: #1154 — `initialize` normalizes the `bundles:`/`declared_bundles:` kwargs through
16
+ # `normalize_bundles` (join-merging per origin), so the readers do not trace to the parameters.
17
+ attr_reader bundles: Hash[Origin, LabelSet]
18
+ # sig-gen gap: #1154 — as above.
19
+ attr_reader declared_bundles: Hash[Origin, LabelSet]
20
+ # Unmarked residue — `proven`/`declared` are flattened from the bundle tables by `initialize`,
21
+ # not assigned from a parameter, so #1154 does not cover them (same shape as
22
+ # `Registry#additional_initializers`).
23
+ attr_reader declared: LabelSet
24
+ attr_reader proven: LabelSet
25
+ # sig-gen gap: #1154 — `causes` are `[cause, detail]` pairs normalized in `initialize`.
26
+ attr_reader causes: Array[[String, String?]]
27
+
28
+ def initialize: (?bundles: Hash[Origin, LabelSet], ?declared_bundles: Hash[Origin, LabelSet],
29
+ ?exhaustive: bool, ?causes: Array[[String, String?]], ?unclaimed: bool) -> void
30
+
31
+ # Whether every call this method makes was resolved.
32
+ def exhaustive?: () -> bool
33
+
34
+ # Whether this method made a call nothing described — read by `rigor sig-gen`'s annotation
35
+ # emission alone (#391).
36
+ def unclaimed?: () -> bool
37
+
38
+ # Whether the report omits this row by default (#386).
39
+ def trivial?: () -> bool
40
+
41
+ # Union in every lane — reopenings and multi-file contributors fold through this.
42
+ def join: (Summary other) -> Summary
43
+
44
+ def ==: (untyped other) -> bool
45
+ alias eql? ==
46
+ def hash: () -> Integer
47
+ def inspect: () -> String
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module Rigor
2
+ module Effects
3
+ # The closed enum of reasons a summary is not exhaustive (ADR-103 WD14). A reporting vocabulary,
4
+ # never a diagnostic one.
5
+ module TaintCause
6
+ ALL: Array[String]
7
+
8
+ # `cause.to_s` is looked up, so any object is a fair question.
9
+ def self?.valid?: (untyped cause) -> bool
10
+ end
11
+ end
12
+ end
@@ -15,10 +15,8 @@ module Rigor
15
15
  attr_reader hkt_registry: untyped?
16
16
  # Issue #784 — `[error_class_name, first_message_line, raw_frame_or_nil, stage]` when either stage of
17
17
  # the HKT-registry build raised at its seam (`:scan`, the RBS `type`-alias scan; `:overlay`, the
18
- # plugin-manifest aggregation — #791), nil when both built or were never demanded. Declared `untyped?`
19
- # like its neighbours:
20
- # `rigor sig-gen` emits nothing for this delegating reader, and the tuple shape is documented here.
21
- def hkt_scan_failure: () -> untyped?
18
+ # plugin-manifest aggregation — #791), nil when both built or were never demanded.
19
+ def hkt_scan_failure: () -> [String, String, String?, Symbol]?
22
20
 
23
21
  def self.default: () -> Environment
24
22
  def self.for_project: (?root: String, ?libraries: Array[String], ?signature_paths: Array[String | _ToPath]?, ?cache_store: untyped?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?, ?source_rbs_synthesis_reporter: untyped?, ?bundler_bundle_path: String?, ?bundler_auto_detect: bool, ?synthetic_method_index: untyped?, ?project_patched_methods: untyped?) -> Environment
@@ -31,8 +29,12 @@ module Rigor
31
29
  def nominal_for_name: (String | Symbol name) -> Type::Nominal?
32
30
  def singleton_for_name: (String | Symbol name) -> Type::Singleton?
33
31
  def constant_for_name: (String | Symbol name) -> Type::t?
32
+ # sig-gen gap: #1154 — the answer comes through `rbs_loader`, an `attr_reader` over an ivar assigned in
33
+ # `initialize` from a parameter, which reaches `untyped`.
34
+ def global_for_name: (String | Symbol name, ?builtin: bool) -> Type::t?
34
35
  def class_known?: (String | Symbol name) -> bool
35
36
  def rbs_module?: (String | Symbol name) -> bool
37
+ def singleton_extended_modules: (String | Symbol name) -> Array[String]
36
38
  def class_ordering: (String | Symbol lhs, String | Symbol rhs) -> ordering
37
39
  def reflection: () -> untyped?
38
40
  def missing_rbs_gem_owner: (String | Symbol root_constant_name) -> String?
@@ -53,28 +55,33 @@ module Rigor
53
55
  attr_reader libraries: Array[String]
54
56
  attr_reader signature_paths: Array[String | _ToPath]
55
57
  attr_reader cache_store: untyped?
58
+ # sig-gen gap: #160 — sig-gen emits no `attr_reader` for the loader's readers; typed as the initializer stores it.
59
+ attr_reader deferred_signature_paths: Array[Pathname]
56
60
 
57
61
  def self.default: () -> RbsLoader
58
62
  def self.reset_default!: () -> void
59
- def self.build_env_for: (libraries: Array[String], signature_paths: Array[String | _ToPath]) -> untyped
63
+ def self.build_env_for: (libraries: Array[String], signature_paths: Array[String | _ToPath]) -> ::RBS::Environment
60
64
  def self.vendored_gem_sig_paths: () -> Array[Pathname]
65
+ def self.capability_role_sig_paths: () -> ([Pathname] | [])
61
66
  def self.vendored_gem_names: () -> Array[String]
62
67
 
63
68
  def initialize: (?libraries: Array[String], ?signature_paths: Array[String | _ToPath], ?cache_store: untyped?) -> void
64
69
  def class_known?: (String | Symbol name) -> bool
65
70
  def rbs_module?: (String | Symbol name) -> bool
66
- def instance_definition: (String | Symbol class_name) -> untyped?
67
- def instance_method: (class_name: String | Symbol, method_name: String | Symbol) -> untyped?
68
- def singleton_definition: (String | Symbol class_name) -> untyped?
69
- def singleton_method: (class_name: String | Symbol, method_name: String | Symbol) -> untyped?
71
+ def instance_definition: (String | Symbol class_name) -> ::RBS::Definition?
72
+ def instance_method: (class_name: String | Symbol, method_name: String | Symbol) -> ::RBS::Definition::Method?
73
+ def singleton_definition: (String | Symbol class_name) -> ::RBS::Definition?
74
+ def singleton_method: (class_name: String | Symbol, method_name: String | Symbol) -> ::RBS::Definition::Method?
70
75
  def class_type_param_names: (String | Symbol class_name) -> Array[Symbol]
71
76
  def project_declared_classes: () -> Set[String]
72
77
  def project_declared_class?: (String | Symbol class_name) -> bool
73
78
  def class_ordering: (String | Symbol lhs, String | Symbol rhs) -> ordering
74
79
  def ancestor_names_for: (String | Symbol class_name) -> Array[String]
80
+ def singleton_extended_module_names: (String | Symbol class_name) -> Array[String]
75
81
  def constant_type: (String name) -> Type::t?
76
82
  def constant_names: () -> Array[String]
77
- def each_known_class_name: () { (String name) -> void } -> untyped
83
+ def each_known_class_name: () { (String name) -> void } -> void
84
+ | () -> ::Enumerator[String, void]
78
85
  end
79
86
 
80
87
  class RbsHierarchy
@@ -0,0 +1,10 @@
1
+ module Rigor
2
+ module Inference
3
+ module OptimisticOrigin
4
+ # sig-gen gap: #1150 — sig-gen types the `BoundMark#miss` member read `untyped`, so it skips this reader
5
+ # (sig.skipped.untyped-return). The answer is the recorded `true` / `false` / `nil`, or the `UNKNOWN_MISS`
6
+ # sentinel; declaring it is what lets sig-gen type `Scope#optimistic_local_miss` / `#optimistic_ivar_miss`.
7
+ def self?.bound_miss: (untyped mark) -> Object?
8
+ end
9
+ end
10
+ end
@@ -23,8 +23,10 @@ module Rigor
23
23
  class ClassFrame
24
24
  attr_reader name: String
25
25
  attr_reader singleton: bool
26
- def self.new: (name: String, singleton: bool) -> ClassFrame
27
- def initialize: (name: String, singleton: bool) -> void
26
+ # sig-gen gap: #1150 — `Data.define` members carry no type.
27
+ attr_reader refinement: bool
28
+ def self.new: (name: String, singleton: bool, ?refinement: bool) -> ClassFrame
29
+ def initialize: (name: String, singleton: bool, ?refinement: bool) -> void
28
30
  end
29
31
 
30
32
  def initialize: (scope: Scope, ?tracer: FallbackTracer?, ?on_enter: (^(untyped, Scope) -> void)?, ?class_context: Array[ClassFrame]) -> void
@@ -45,11 +47,7 @@ module Rigor
45
47
  def singleton_def?: (untyped def_node) -> bool
46
48
  def self_type_for_class_body: (Array[ClassFrame] class_context) -> Type::t?
47
49
  def self_type_for_method_body: (singleton: bool) -> Type::t?
48
- def qualified_name_for: (untyped constant_path_node) -> String?
49
- def render_constant_path: (untyped node) -> String
50
50
  def singleton_context_for: (untyped node) -> Array[ClassFrame]
51
- def captured_local_writes: (untyped block_node, Scope base_scope) -> Array[Symbol]
52
- def block_introduced_locals: (untyped block_node) -> Set[Symbol]
53
51
  def drop_captured_narrowing: (untyped block_node, Scope base_scope) -> Scope
54
52
  def classify_closure_escape: (untyped call_node) -> closure_classification
55
53
  def record_closure_escape_if_any: (untyped node) -> Scope
@@ -108,16 +106,16 @@ module Rigor
108
106
  def self?.narrow_non_nil: (Type::t type) -> Type::t
109
107
  def self?.narrow_equal: (Type::t type, untyped literal) -> Type::t
110
108
  def self?.narrow_not_equal: (Type::t type, untyped literal) -> Type::t
111
- def self?.narrow_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment) -> Type::t
112
- def self?.narrow_not_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment) -> Type::t
109
+ def self?.narrow_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment, ?scope: Scope?) -> Type::t
110
+ def self?.narrow_not_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment, ?scope: Scope?) -> Type::t
113
111
  def self?.narrow_not_refinement: (Type::t current_type, Type::t refinement_type) -> Type::t
114
112
  def self?.narrow_for_fact: (Type::t current, untyped fact, untyped environment) -> Type::t
115
113
  def self?.predicate_certainty: (Type::t? type) -> (:truthy | :falsey | nil)
116
- def self?.class_pattern_certainty: (Type::t subject_type, String class_name, environment: Environment) -> (:yes | :no | :maybe)
114
+ def self?.class_pattern_certainty: (Type::t subject_type, String class_name, environment: Environment, ?scope: Scope?) -> (:yes | :no | :maybe)
117
115
  def self?.value_pattern_certainty: (Type::t subject_type, untyped pattern_value) -> (:yes | :no | :maybe)
118
116
  def self?.predicate_scopes: (untyped node, Scope scope) -> [Scope, Scope]
119
117
  def self?.case_when_scopes: (untyped subject, Array[untyped] conditions, Scope scope) -> [Scope, Scope]
120
- def self?.analyse: (untyped node, Scope scope) -> untyped
118
+ def self?.analyse: (untyped node, Scope scope) -> [Scope, Scope]?
121
119
  def self?.subclass_of?: (String rigor_class_name, String target_class_name, untyped context) -> bool
122
120
  def self?.class_ordering: (String lhs, String rhs, untyped context) -> Symbol
123
121
  def self?.trusted_equality_literal?: (untyped literal) -> bool
@@ -162,7 +160,6 @@ module Rigor
162
160
 
163
161
  module ScopeIndexer
164
162
  def self?.index: (untyped root, default_scope: Scope) -> Hash[untyped, Scope]
165
- def self?.build_declaration_overrides: (untyped root) -> Hash[untyped, Type::t]
166
163
  def self?.build_declaration_artifacts: (untyped root) -> [Hash[untyped, Type::t], Hash[String, Type::t]]
167
164
  def self?.build_in_source_constants: (untyped root, Scope default_scope) -> Hash[String, Type::t]
168
165
  def self?.record_declarations: (untyped node, Array[String] qualified_prefix, Hash[untyped, Type::t] identity_table, Hash[String, Type::t] discovered) -> void
@@ -175,9 +172,7 @@ module Rigor
175
172
  def self?.collect_class_decls: (untyped node, Array[String] qualified_prefix, Hash[String, Type::t] accumulator) -> void
176
173
  def self?.constant_writes_for_file: (untyped root) -> Hash[String, untyped]
177
174
  def self?.constant_literal_value: (untyped rvalue) -> Array[untyped]?
178
- def self?.finalize_constant_writes: (Hash[String, Hash[String, untyped]] writes) -> [Hash[String, Type::t], Hash[String, Set[String]]]
179
- def self?.qualified_name_for: (untyped constant_path_node) -> String?
180
- def self?.render_constant_path: (untyped node) -> String
175
+ def self?.finalize_constant_writes: (Hash[String, Hash[String, untyped]] writes) -> [Hash[String, Type::Constant], Hash[String, Set[String]]]
181
176
  def self?.propagate: (untyped node, Hash[untyped, Scope] table, Scope parent_scope) -> void
182
177
  end
183
178
 
@@ -0,0 +1,36 @@
1
+ module Rigor
2
+ module Plugin
3
+ # ADR-38 declaration — methods/def-blocks that establish ivar state like `initialize` does, so
4
+ # the read-before-write nil soundness gate does not widen their ivars. See
5
+ # lib/rigor/plugin/additional_initializer.rb for the full contract.
6
+ class AdditionalInitializer
7
+ # sig-gen gap: #1154 — `attr_reader` rows over ivars assigned from `initialize` parameters are
8
+ # skipped (untyped return); the constructor validates `receiver_constraint` is a non-empty
9
+ # String and normalizes both lists with `map(&:to_sym)`, so the stored types are hand-written.
10
+ attr_reader receiver_constraint: String
11
+
12
+ # sig-gen gap: #1154 — as above.
13
+ attr_reader methods: Array[Symbol]
14
+
15
+ # sig-gen gap: #1154 — as above.
16
+ attr_reader block_methods: Array[Symbol]
17
+
18
+ # The validators accept Symbol or non-empty String elements; `initialize` normalizes to
19
+ # Symbol before storing. At least one of `methods:`/`block_methods:` must be non-empty.
20
+ def initialize: (receiver_constraint: String, ?methods: Array[Symbol | String], ?block_methods: Array[Symbol | String]) -> void
21
+
22
+ def covers_method?: (Symbol method_name) -> bool
23
+
24
+ def covers_block_method?: (Symbol method_name) -> bool
25
+
26
+ def to_h: () -> Hash[String, String | Array[String]]
27
+
28
+ def ==: (untyped other) -> bool
29
+
30
+ # `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked residue.
31
+ def eql?: (untyped other) -> bool
32
+
33
+ def hash: () -> Integer
34
+ end
35
+ end
36
+ end
@@ -17,11 +17,11 @@ class Rigor::Plugin::Base
17
17
  def self.producer: (untyped id, ?watch: untyped, ?serialize: untyped, ?deserialize: untyped, ?generation_cap: untyped) { (untyped params) -> untyped } -> Symbol
18
18
  def self.producers: () -> Hash[Symbol, untyped]
19
19
 
20
- def self.node_rule: (untyped node_type) { (*untyped) -> untyped } -> untyped
20
+ def self.node_rule: (untyped node_type) { (*untyped) -> untyped } -> Class
21
21
  def self.node_rules: () -> Array[untyped]
22
22
 
23
- def self.node_file_context: () { (untyped root, untyped scope) -> untyped } -> untyped
24
- def self.node_file_context_block: () -> untyped
23
+ def self.node_file_context: () { (untyped root, untyped scope) -> untyped } -> void
24
+ def self.node_file_context_block: () -> (^(untyped root, untyped scope) -> untyped)?
25
25
 
26
26
  def self.dynamic_return: (?receivers: (Array[String] | ^() -> Array[String])?, ?methods: (Array[untyped] | ^() -> Array[untyped])?, ?file_methods: (^(untyped path) -> Array[untyped])?) { (untyped call_node, untyped scope) -> untyped } -> nil
27
27
  def self.dynamic_returns: () -> Array[untyped]
@@ -44,22 +44,45 @@ class Rigor::Plugin::Base
44
44
  def init: (untyped services) -> nil
45
45
  def prepare: (untyped services) -> nil
46
46
  def diagnostics_for_file: (path: untyped, scope: untyped, root: untyped) -> Array[untyped]
47
+ # authored: hook-contract widening — the element type comes from a plugin gem sig-gen never
48
+ # sees, so no engine work would let it answer; the declared `Array[Rigor::Plugin::TemplateUnit]`
49
+ # over a bare-`[]` default body is the author's contract.
50
+ def template_units_for_file: (path: untyped, source: untyped) -> Array[untyped]
51
+ # authored: hook-contract widening — the element type comes from a plugin gem sig-gen never
52
+ # sees, so no engine work would let it answer; the declared record contract over a bare-`[]`
53
+ # default body is the author's.
54
+ def declared_members: (untyped class_name) -> Array[untyped]
47
55
 
48
56
  # Engine-executed dispatch over the declared DSLs.
49
57
  def node_rule_diagnostics: (path: untyped, scope: untyped, root: untyped) -> Array[untyped]
50
- def dynamic_return_type: (call_node: untyped, scope: untyped, receiver_type: untyped) -> untyped
58
+ # sig-gen gap: #1007 — the true `return result if result` branch (base.rb:594) flows through an
59
+ # `instance_exec`'d, plugin-supplied Proc that sig-gen's inference does not fold into the return
60
+ # join, so it proposes the literal fallback `nil` instead of the honest contract.
61
+ def dynamic_return_type: (call_node: untyped, scope: untyped, receiver_type: untyped) -> Rigor::Type::t?
51
62
  def narrowing_facts_for: (call_node: untyped, scope: untyped) -> Array[untyped]
52
63
 
53
64
  # Authoring helpers.
54
- def diagnostic: (untyped node, path: untyped, message: untyped, ?severity: untyped, ?rule: untyped, ?location: untyped) -> untyped
65
+ def diagnostic: (untyped node, path: untyped, message: untyped, ?severity: untyped, ?rule: untyped, ?location: untyped) -> Rigor::Analysis::Diagnostic
55
66
  def diagnostics_for: (untyped violations, path: untyped, ?node: untyped) -> Array[untyped]
56
67
  def read_fact: (plugin_id: untyped, name: untyped) -> untyped
57
68
  def producer_value: (untyped id, ?params: untyped) -> untyped
58
69
  def producer_error: (untyped id) -> untyped
70
+ def disclose_once: (untyped key, message: untyped, ?severity: untyped, ?rule: untyped) -> nil
71
+ def emit_once: (untyped key, untyped diagnostics) -> nil
72
+ def run_disclosure_records: () -> Array[untyped]
59
73
  def manifest: () -> Rigor::Plugin::Manifest
60
74
  def signature_paths: () -> Array[String]
61
- def protocol_contracts: () -> untyped
75
+ # Defaults to `manifest.protocol_contracts`; a plugin MAY override to fold per-project config in,
76
+ # but the contract (an Array of ProtocolContract) holds either way.
77
+ def protocol_contracts: () -> Array[Rigor::Plugin::ProtocolContract]
78
+ # The ADR-103 effect surfaces delegate to the manifest by default; a plugin MAY override
79
+ # `effect_attributions` to fold per-project config in, but the contract holds either way.
80
+ def effect_labels: () -> Array[String]
81
+ def effect_attributions: () -> Array[Rigor::Plugin::EffectAttribution]
82
+ def effect_edges: () -> Array[Rigor::Plugin::EffectEdge]
83
+ def effect_entry_points: () -> Array[Rigor::Plugin::EffectEntryPoints]
84
+ def effect_ancestry: () -> Array[Rigor::Plugin::EffectAncestry]
62
85
  def io_boundary: () -> Rigor::Plugin::IoBoundary
63
- def cache_for: (untyped producer_id, ?params: untyped, ?descriptor: untyped) -> untyped
86
+ def cache_for: (untyped producer_id, ?params: untyped, ?descriptor: untyped) -> Proc
64
87
  def plugin_entry: () -> untyped
65
88
  end
@@ -0,0 +1,27 @@
1
+ module Rigor
2
+ module Plugin
3
+ # One `effect_ancestry:` row: an ancestry edge the plugin's own gem introduces and the project's
4
+ # source never writes down (ADR-103 WD17, #465). `parent:` need only be a true ancestor, not the
5
+ # immediate superclass. Bundled plugins only — `Effects::PluginFacts` enforces it. Frozen value
6
+ # object.
7
+ class EffectAncestry
8
+ # sig-gen gap: #1154 — validated in `initialize` from the parameter of the same name
9
+ # (`to_s`-normalized, frozen), so sig-gen proposes the raw parameter shape.
10
+ attr_reader child: String
11
+ # sig-gen gap: #1154 — same shape as `child`.
12
+ attr_reader parent: String
13
+ # sig-gen gap: #1154 — same shape; `why:` is required and validated non-empty.
14
+ attr_reader why: String
15
+
16
+ def initialize: (child: untyped, parent: untyped, why: untyped) -> void
17
+
18
+ def to_h: () -> Hash[String, untyped]
19
+
20
+ def ==: (untyped other) -> bool
21
+ # `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
22
+ # residue.
23
+ def eql?: (untyped other) -> bool
24
+ def hash: () -> Integer
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,66 @@
1
+ module Rigor
2
+ module Plugin
3
+ # One `effect_attributions:` row: the receiver spelling, the selector, and the labels the call
4
+ # contributes to the declared lane — plus the optional `narrow:`/`callee:`/`taint:`/`responds:`
5
+ # modifiers the engine owns the strategy for (#393/#1048/#1065). Frozen value object.
6
+ class EffectAttribution
7
+ # A receiver spelled as a `Constant::Path` — the class-name form.
8
+ CLASS_NAME: Regexp
9
+ # A receiver path: a constant head followed by one or more sends (`Rails.cache`).
10
+ RECEIVER_PATH: Regexp
11
+ # A self path: implicit self followed by one or more receiver-less sends (`self.flash.now`).
12
+ SELF_PATH: Regexp
13
+ # What a self path is rooted at, once the `self.` head is stripped.
14
+ SELF_HEAD: String
15
+ # The taint causes a plugin row may name — a closed subset of `Effects::TaintCause::ALL`.
16
+ TAINT_CAUSES: Array[String]
17
+
18
+ # sig-gen gap: #1154 — normalized/validated in `initialize` from the parameter of the same
19
+ # name (`to_s`-coerced, frozen), so sig-gen proposes the raw parameter shape.
20
+ attr_reader receiver: String
21
+ # sig-gen gap: #1154 — `to_sym`-normalized from the `method:` parameter.
22
+ attr_reader method: Symbol
23
+ attr_reader singleton: bool
24
+ # sig-gen gap: #1154 — `Array()`-normalized, deduplicated and frozen from `labels:`.
25
+ attr_reader labels: Array[String]
26
+ # sig-gen gap: #1154 — `to_s`-normalized from the `narrow:` parameter.
27
+ attr_reader narrow: String?
28
+ attr_reader discharge: bool
29
+ # sig-gen gap: #1154 — `to_s`-normalized from the `within:` parameter.
30
+ attr_reader within: String?
31
+ attr_reader on_result: bool
32
+ # sig-gen gap: #1154 — `to_s`-normalized from the `taint:` parameter.
33
+ attr_reader taint: String?
34
+ # sig-gen gap: #1154 — `to_s`-normalized from the `callee:` parameter.
35
+ attr_reader callee: String?
36
+ # sig-gen gap: #1154 — normalized from the `callee_fallbacks:` parameter.
37
+ attr_reader callee_fallbacks: Hash[String, Array[String]]?
38
+ attr_reader responds: bool
39
+ # sig-gen gap: #1154 — `to_s`-normalized from the `why:` parameter.
40
+ attr_reader why: String
41
+
42
+ # The coercion-facing constructor: every parameter is `to_s`/`to_sym`/`Array()`-normalized,
43
+ # so `untyped` is the honest parameter type throughout.
44
+ def initialize: (receiver: untyped, method: untyped, labels: untyped, why: untyped,
45
+ ?singleton: untyped, ?narrow: untyped, ?discharge: untyped,
46
+ ?within: untyped, ?on_result: untyped, ?taint: untyped, ?callee: untyped,
47
+ ?callee_fallbacks: untyped, ?responds: untyped) -> void
48
+
49
+ # Whether {#receiver} is a receiver path (`Rails.cache`) rather than a class name or a
50
+ # self path.
51
+ def receiver_path?: () -> bool
52
+ # Whether {#receiver} is a self path (`self.flash.now`).
53
+ def self_path?: () -> bool
54
+
55
+ # The key an origin and a report spell this row as.
56
+ def key: () -> String
57
+ def to_h: () -> Hash[String, untyped]
58
+
59
+ def ==: (untyped other) -> bool
60
+ # `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
61
+ # residue.
62
+ def eql?: (untyped other) -> bool
63
+ def hash: () -> Integer
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,33 @@
1
+ module Rigor
2
+ module Plugin
3
+ # One `effect_edges:` row: a framework-edge strategy naming the base `receiver` a plugin points
4
+ # the engine at, the `target` strategy slot, and an optional method-level `selector`. Frozen
5
+ # value object.
6
+ class EffectEdge
7
+ # The closed set of framework-edge strategies the engine implements.
8
+ TARGETS: Array[Symbol]
9
+
10
+ # sig-gen gap: #1154 — validated/normalized in `initialize` from the parameter of the same
11
+ # name, so sig-gen proposes the raw parameter shape.
12
+ attr_reader receiver: String
13
+ # sig-gen gap: #1154 — `to_sym`-normalized from the `method:` parameter.
14
+ attr_reader method: Symbol?
15
+ attr_reader singleton: bool
16
+ # sig-gen gap: #1154 — validated against `TARGETS` in `initialize`.
17
+ attr_reader target: (:activerecord_callbacks | :perform_now | :mailer_body)
18
+ # sig-gen gap: #1154 — `to_s`-normalized from the `why:` parameter.
19
+ attr_reader why: String
20
+
21
+ def initialize: (receiver: untyped, target: untyped, why: untyped, ?method: untyped,
22
+ ?singleton: untyped) -> void
23
+
24
+ def to_h: () -> Hash[String, untyped]
25
+
26
+ def ==: (untyped other) -> bool
27
+ # `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
28
+ # residue.
29
+ def eql?: (untyped other) -> bool
30
+ def hash: () -> Integer
31
+ end
32
+ end
33
+ end