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
@@ -37,8 +37,7 @@ module Rigor
37
37
  # run, so the same Prism node object is seen in both the `dynamic_return` rule and
38
38
  # `diagnostics_for_file`.
39
39
  module AbsurdRecognizer
40
- # @param call_node [Prism::CallNode]
41
- # @return [Boolean] true when `call_node` is `T.absurd(x)`.
40
+ # @return true when `call_node` is `T.absurd(x)`.
42
41
  def self.absurd_call?(call_node)
43
42
  return false unless call_node.is_a?(Prism::CallNode)
44
43
  return false unless call_node.name == :absurd
@@ -50,9 +49,7 @@ module Rigor
50
49
  arguments&.size == 1
51
50
  end
52
51
 
53
- # @param call_node [Prism::CallNode]
54
- # @param scope [Rigor::Scope, nil]
55
- # @return [Boolean] true when the discriminant has been narrowed to `bot` (the branch is
52
+ # @return true when the discriminant has been narrowed to `bot` (the branch is
56
53
  # unreachable, so `T.absurd` is correct). The caller suppresses the `absurd-reachable` diagnostic
57
54
  # in this case.
58
55
  def self.exhaustive?(call_node, scope)
@@ -53,10 +53,7 @@ module Rigor
53
53
 
54
54
  module_function
55
55
 
56
- # @param call_node [Prism::CallNode]
57
- # @param scope [Rigor::Scope]
58
- # @param plugin_id [String] used for the contribution's `provenance.source_family`.
59
- # @return [Rigor::FlowContribution, nil]
56
+ # @param plugin_id — used for the contribution's `provenance.source_family`.
60
57
  def recognize(call_node:, scope:, plugin_id:)
61
58
  return nil unless TypeTranslator.sorbet_t_namespaced?(call_node.receiver)
62
59
  return nil unless SORBET_ASSERTIONS.include?(call_node.name)
@@ -23,7 +23,6 @@ module Rigor
23
23
  @frozen_after_build = false
24
24
  end
25
25
 
26
- # @param signature [MethodSignature]
27
26
  def record(signature)
28
27
  raise "Catalog already finalised" if @frozen_after_build
29
28
 
@@ -31,10 +30,9 @@ module Rigor
31
30
  @entries[key] = signature
32
31
  end
33
32
 
34
- # @param class_name [String] the class / module that carries the mixin (`class Post; include Foo;
33
+ # @param class_name — the class / module that carries the mixin (`class Post; include Foo;
35
34
  # end` records under `"Post"`).
36
- # @param kind [:include, :extend]
37
- # @param module_name [String] the textual name of the mixed-in module as it appeared at the
35
+ # @param module_name — the textual name of the mixed-in module as it appeared at the
38
36
  # include / extend site (`"Foo"`, `"Foo::Bar"`, `"::Foo"`).
39
37
  def record_mixin(class_name:, kind:, module_name:)
40
38
  raise "Catalog already finalised" if @frozen_after_build
@@ -55,13 +53,11 @@ module Rigor
55
53
  freeze
56
54
  end
57
55
 
58
- # @return [MethodSignature, nil]
59
56
  def lookup(class_name:, method_name:, kind:)
60
57
  @entries[key_for(class_name, method_name, kind)]
61
58
  end
62
59
 
63
- # @param class_name [String]
64
- # @return [Hash{Symbol => Array<String>}] frozen mapping `{ include: [...], extend: [...] }`.
60
+ # @return frozen mapping `{ include: [...], extend: [...] }`.
65
61
  # Returns {EMPTY_MIXINS} when no mixins were recorded.
66
62
  def mixins_for(class_name)
67
63
  @mixins[class_name] || EMPTY_MIXINS
@@ -77,8 +73,6 @@ module Rigor
77
73
  # static assertion vocabulary), and the precise `(class, kind)` lookup stays in the rule block.
78
74
  # Computed fresh per call — the plugin memoises the resolved set, and `freeze!` freezes the
79
75
  # catalog itself so a lazy memo ivar here would raise.
80
- #
81
- # @return [Array<Symbol>]
82
76
  def method_names
83
77
  @entries.keys.map { |key| key[1] }.uniq
84
78
  end
@@ -26,10 +26,10 @@ module Rigor
26
26
 
27
27
  module_function
28
28
 
29
- # @param root [Prism::Node] the file's program node.
30
- # @param catalog [Catalog] mutable; signatures are recorded into it.
31
- # @param path [String] file path used for diagnostic provenance.
32
- # @return [Array<ParseError>] errors observed during the walk; empty when the file is sig-clean.
29
+ # @param root — the file's program node.
30
+ # @param catalog — mutable; signatures are recorded into it.
31
+ # @param path — file path used for diagnostic provenance.
32
+ # @return errors observed during the walk; empty when the file is sig-clean.
33
33
  def walk(root:, catalog:, path:)
34
34
  state = State.new(catalog: catalog, path: path)
35
35
  walk_node(root, state, lexical_path: [], in_singleton_class: false)
@@ -44,8 +44,7 @@ module Rigor
44
44
 
45
45
  module_function
46
46
 
47
- # @param sig_call [Prism::CallNode] the `sig { ... }` / `sig do ... end` call.
48
- # @return [ParseResult, ParseError]
47
+ # @param sig_call — the `sig { ... }` / `sig do ... end` call.
49
48
  def parse(sig_call)
50
49
  return ParseError.new(reason: :no_block, node: sig_call) if sig_call.block.nil?
51
50
 
@@ -30,8 +30,7 @@ module Rigor
30
30
 
31
31
  module_function
32
32
 
33
- # @param contents [String] raw file contents.
34
- # @return [Symbol] one of {VALID_LEVELS}; defaults to {DEFAULT_LEVEL} for sigil-less or
33
+ # @return one of {VALID_LEVELS}; defaults to {DEFAULT_LEVEL} for sigil-less or
35
34
  # malformed-sigil files.
36
35
  def detect(contents)
37
36
  return DEFAULT_LEVEL if contents.nil? || contents.empty?
@@ -52,14 +51,13 @@ module Rigor
52
51
  DEFAULT_LEVEL
53
52
  end
54
53
 
55
- # @param level [Symbol]
56
- # @return [Boolean] true when `# typed: ignore`. The harvest pipeline calls this to short-circuit
54
+ # @return true when `# typed: ignore`. The harvest pipeline calls this to short-circuit
57
55
  # walking the file's AST.
58
56
  def ignored?(level)
59
57
  level == :ignore
60
58
  end
61
59
 
62
- # @return [Boolean] true when `level` is at or above the `# typed: true` mark. Used by the
60
+ # @return true when `level` is at or above the `# typed: true` mark. Used by the
63
61
  # `enforce_sigil` config gate (default `true`): with the gate on, only files marked `:true` /
64
62
  # `:strict` / `:strong` contribute their sigs to the catalog. The `:false` (and sigil-less)
65
63
  # levels still get walked (so RBI files outside the project can be loaded regardless), but their
@@ -52,8 +52,7 @@ module Rigor
52
52
 
53
53
  module_function
54
54
 
55
- # @param node [Prism::Node, nil]
56
- # @return [Rigor::Type] never `nil`; unrecognised forms degrade to `Type::Combinator.untyped`.
55
+ # @return never `nil`; unrecognised forms degrade to `Type::Combinator.untyped`.
57
56
  def translate(node)
58
57
  return Rigor::Type::Combinator.untyped if node.nil?
59
58
 
@@ -67,7 +66,6 @@ module Rigor
67
66
  end
68
67
  end
69
68
 
70
- # @param node [Prism::ConstantReadNode]
71
69
  def translate_constant_read(node)
72
70
  name = node.name.to_s
73
71
  return Rigor::Type::Combinator.untyped if name.empty?
@@ -75,7 +73,6 @@ module Rigor
75
73
  Rigor::Type::Combinator.nominal_of(name)
76
74
  end
77
75
 
78
- # @param node [Prism::ConstantPathNode]
79
76
  def translate_constant_path(node)
80
77
  name = constant_path_name(node)
81
78
  return degraded if name.nil?
@@ -233,7 +230,12 @@ module Rigor
233
230
 
234
231
  pairs << [element.key.unescaped.to_sym, translate(element.value)]
235
232
  end
236
- Rigor::Type::Combinator.hash_shape_of(pairs)
233
+ # `.to_h`: `hash_shape_of` validates its argument is a Hash and raises `ArgumentError` on the
234
+ # array-of-pairs form, so `sig { returns({name: String}) }` degraded to `Dynamic[top]` through
235
+ # the plugin's rescue instead of producing a shape. Found by #673, when relaxing
236
+ # `call.argument-type-mismatch` to check the positional arguments of keyword-bearing
237
+ # signatures made the call site visible.
238
+ Rigor::Type::Combinator.hash_shape_of(pairs.to_h)
237
239
  end
238
240
 
239
241
  # Renders a constant-path node (`Foo::Bar`, `::Foo::Bar`) as a `::`-joined String. Mirrors the
@@ -29,6 +29,14 @@ module Rigor
29
29
  # The {TypeTranslator} table documents coverage. Most of Sorbet's vocabulary translates; remaining
30
30
  # gaps (`T.proc`, `T::Struct` subclasses, `T.attached_class`, etc.) degrade silently to `Dynamic[top]`.
31
31
  #
32
+ # Issue #1097 — the plugin also ships `sig/sorbet.rbs`, a bundled declaration of the annotation DSL
33
+ # surface itself: `T`'s type-expression functions, the `T::X[...]` constructors, `T::Sig`'s `sig`
34
+ # verb (reached via the manifest `rbs_complete_extends:` bridge over `extend T::Sig`), the
35
+ # `DeclBuilder` the sig block `instance_eval`s on (via `block_as_methods:`), and the
36
+ # `T::Struct` / `T::Enum` family (via `rbs_complete_ancestors:`). The value-side assertions
37
+ # (`T.let`/`T.cast`/`T.must`/…) stay recogniser-owned — RBS cannot express "return the asserted
38
+ # type" — and `T`'s declared surface is intentionally partial behind `open_receivers:`.
39
+ #
32
40
  # Architecture: per-run `Catalog` is built lazily on first access by walking every configured `paths:`
33
41
  # entry's `.rb` files plus every `rbi_paths:` entry's `.rbi` files (slice 4) via the plugin's
34
42
  # `IoBoundary`. The catalog is frozen after the first build and consulted by the `dynamic_return` rule
@@ -57,6 +65,7 @@ module Rigor
57
65
  class Sorbet < Rigor::Plugin::Base
58
66
  manifest(
59
67
  id: "sorbet",
68
+ target_gems: ["sorbet-runtime"],
60
69
  version: "0.1.0",
61
70
  description: "Ingests Sorbet `sig` blocks as method-signature contributions.",
62
71
  config_schema: {
@@ -69,7 +78,43 @@ module Rigor
69
78
  # effect of recursing into the parent root.
70
79
  "rbi_paths" => { kind: :array, default: ["sorbet/rbi"] },
71
80
  "enforce_sigil" => { kind: :boolean, default: true }
72
- }
81
+ },
82
+ # #1097 — bundled sorbet-runtime DSL surface (`sig/sorbet.rbs`). `sig` itself reaches the
83
+ # class object through `extend T::Sig` (or the `< T::ImmutableStruct` / `< T::Enum`
84
+ # family, which carry the edge themselves), which is
85
+ # why `rbs_complete_extends:` — the extend-edge allow-list — carries `T::Sig` /
86
+ # `T::Helpers` / `T::Generic`, and `rbs_complete_ancestors:` carries the Struct/Enum family
87
+ # for the subclass bridge.
88
+ signature_paths: ["sig"],
89
+ rbs_complete_extends: %w[T::Sig T::Helpers T::Generic],
90
+ rbs_complete_ancestors: %w[T::Struct T::InexactStruct T::ImmutableStruct T::Enum],
91
+ # `sig { ... }` bodies are `instance_eval`'d on a `DeclBuilder`
92
+ # (`T::Private::Methods._run_builder`), so `params` / `returns` / `void` resolve on the
93
+ # builder, not the enclosing class. `T::Sig::WithoutRuntime.sig` is the direct-call twin —
94
+ # a singleton method on the module, matching by name equality.
95
+ block_as_methods: [
96
+ Rigor::Plugin::Macro::BlockAsMethod.new(
97
+ receiver_constraint: "T::Sig",
98
+ method_names: %i[sig],
99
+ self_type: "T::Private::Methods::DeclBuilder"
100
+ ),
101
+ Rigor::Plugin::Macro::BlockAsMethod.new(
102
+ receiver_constraint: "T::Sig::WithoutRuntime",
103
+ method_names: %i[sig],
104
+ self_type: "T::Private::Methods::DeclBuilder"
105
+ )
106
+ ],
107
+ # The declared surface is deliberately partial — `T` is an open module whose runtime
108
+ # surface is much larger than the DSL (version-dependent internals, `T::Private::*`,
109
+ # `T::Configuration`, `T::Utils`). Open receivers keep an unmodelled `T.something` opaque
110
+ # rather than a `call.undefined-method` false positive. `DeclBuilder` is NOT open —
111
+ # `sig { typo }` is a real bug and stays a diagnostic.
112
+ open_receivers: %w[T T::Sig T::Sig::WithoutRuntime T::Helpers T::Generic
113
+ T::Utils T::Configuration T::Private T::Private::Methods
114
+ T::Props T::Props::ClassMethods T::Props::CustomType
115
+ T::Types T::Types::Base T::Array T::Hash T::Set
116
+ T::Enumerable T::Enumerator T::Range T::Class
117
+ T::InexactStruct T::Struct T::ImmutableStruct T::Enum]
73
118
  )
74
119
 
75
120
  def init(services)
@@ -440,13 +485,13 @@ module Rigor
440
485
  # Frozen empty bundle used when the `:catalog` producer failed (e.g. a project I/O error) so downstream
441
486
  # reads see a well-formed shape rather than nil.
442
487
  EMPTY_CATALOG_BUNDLE = { catalog: Catalog.new.freeze!, sigil_by_path: {}, parse_errors_by_path: {} }.freeze
488
+ Ractor.make_shareable(EMPTY_CATALOG_BUNDLE)
443
489
  private_constant :EMPTY_CATALOG_BUNDLE
444
490
 
445
- # @param root [String] directory or single file.
446
- # @param catalog [Catalog]
447
- # @param sigil_by_path [Hash{String=>Symbol}] accumulator: harvested file → detected sigil level.
448
- # @param parse_errors_by_path [Hash{String=>Array<Hash>}] accumulator: file → `{kind:,line:,column:}` tuples.
449
- # @param extensions [Array<String>] file extensions to accept (e.g. `[".rb"]` for project source,
491
+ # @param root — directory or single file.
492
+ # @param sigil_by_path — accumulator: harvested file → detected sigil level.
493
+ # @param parse_errors_by_path — accumulator: file → `{kind:,line:,column:}` tuples.
494
+ # @param extensions — file extensions to accept (e.g. `[".rb"]` for project source,
450
495
  # `[".rbi"]` for Sorbet RBI tree).
451
496
  def harvest_path(root, catalog, sigil_by_path, parse_errors_by_path, extensions)
452
497
  absolute = canonicalize(root)
@@ -0,0 +1,277 @@
1
+ # Bundled RBS for the sorbet-runtime annotation DSL (issue #1097).
2
+ #
3
+ # sorbet-runtime ships RBI, not RBS, so none of the annotation surface (`T`, `T::Sig`, the
4
+ # `DeclBuilder` behind `sig { ... }`, the `T::Array[...]` constructors, the `T::Helpers` /
5
+ # `T::Generic` class macros) resolves for the analyzer. This file declares that surface so the
6
+ # DSL *expressions themselves* type; the plugin's `AssertionRecognizer` continues to own the
7
+ # value-sensitive calls (`T.let` / `T.cast` / `T.must` / `T.bind` / `T.assert_type!` /
8
+ # `T.reveal_type` / `T.unsafe`) ahead of this RBS — the signatures here deliberately agree with
9
+ # it (`T.unsafe` stays `untyped`, `T.bind` returns `nil`) for the cases the recognizer declines.
10
+ #
11
+ # Provenance (docs/agents/type-authoring.md): `rigor sig-gen` cannot produce this file — the DSL
12
+ # methods are installed by `Module#extend` hooks and `instance_eval` in sorbet-runtime's source
13
+ # (sorbet-runtime 0.5.11766, `lib/types/{sig,_types,generic,helpers,struct,enum}.rb` and
14
+ # `lib/types/private/methods/decl_builder.rb`), so every entry was hand-derived by reading that
15
+ # source. Members that do not exist at that version's runtime location are deliberately absent.
16
+ #
17
+ # Two Rigor-side mechanisms complete the picture (manifest fields):
18
+ #
19
+ # - `rbs_complete_extends:` — `extend T::Sig` in a class/module body is what puts `sig` on the
20
+ # class object's singleton; the dispatch bridge resolves those calls through the module's
21
+ # instance surface declared here.
22
+ # - `block_as_methods:` — `sig`'s block is `instance_eval`'d on a `DeclBuilder`
23
+ # (`T::Private::Methods.declare_sig` → `DeclBuilder#instance_eval`), so `sig` bodies bind
24
+ # `self` to `T::Private::Methods::DeclBuilder`, NOT to the enclosing class.
25
+
26
+ module T
27
+ # `T::Boolean` is a runtime constant (`T.any(TrueClass, FalseClass)` → a `T::Types::Union`
28
+ # instance), not a module — it appears in `params`/`returns` argument position as a const read.
29
+ Boolean: ::T::Types::Union
30
+
31
+ # The type-ASSERTION functions (`T.let`, `T.cast`, `T.assert_type!`, `T.bind`, `T.must`,
32
+ # `T.must_because`, `T.reveal_type`, `T.absurd`, `T.unsafe`) are deliberately NOT declared here.
33
+ # Their static return is the *asserted* type (the second argument, translated) or the nil-stripped
34
+ # inner type — semantics RBS cannot express — so the plugin's `AssertionRecognizer` /
35
+ # `AbsurdRecognizer` owns them ahead of dispatch, and a declined call degrades through `T`'s
36
+ # `open_receivers:` entry to opaque rather than a wrong `X` reading.
37
+
38
+ # Type-expression constructors — used in `params`/`returns` argument position.
39
+ def self.nilable: (untyped type) -> ::T::Types::Base
40
+ def self.untyped: () -> ::T::Types::Base
41
+ def self.noreturn: () -> ::T::Types::Base
42
+ def self.anything: () -> ::T::Types::Base
43
+ def self.all: (untyped type_a, untyped type_b, *untyped types) -> ::T::Types::Base
44
+ def self.any: (untyped type_a, untyped type_b, *untyped types) -> ::T::Types::Base
45
+ def self.class_of: (untyped arg) -> ::T::Types::Base
46
+ def self.self_type: () -> ::T::Types::Base
47
+ def self.attached_class: () -> ::T::Types::Base
48
+ def self.type_parameter: (::Symbol name) -> ::T::Types::TypeParameter
49
+ # `type=nil, &blk` — the positional form is a kept-for-migration legacy path (`_types.rb`);
50
+ # the block form wraps in `T::Private::Types::TypeAlias`.
51
+ def self.type_alias: (?untyped type) ?{ () -> untyped } -> ::T::Types::Base
52
+
53
+ # `T.proc` returns a DeclBuilder in `Modes.proc` (`T::Private::Methods.start_proc`), so the
54
+ # `T.proc.params(x: Integer).returns(String)` chain resolves through the same builder surface.
55
+ def self.proc: () -> ::T::Private::Methods::DeclBuilder
56
+ end
57
+
58
+ # `T::Sig` is a mixin a class EXTENDS (`extend T::Sig`) to gain the class-level `sig` verb —
59
+ # sorbet-runtime does not patch `Module`. `sig` itself returns nil at runtime
60
+ # (`declare_sig` stores the DeclarationBlock and returns nil).
61
+ module T::Sig
62
+ def sig: (?untyped arg0) ?{ () -> untyped } -> nil
63
+
64
+ # `T::Sig::WithoutRuntime.sig { ... }` is a no-op shim for contexts where the runtime wrapper
65
+ # cannot be installed; it is called ON the module, so `sig` here is a module-singleton method.
66
+ # `extend T::Sig::WithoutRuntime` installs nothing at runtime, so no instance `sig` is declared.
67
+ module WithoutRuntime
68
+ def self.sig: (?untyped arg0) ?{ () -> untyped } -> nil
69
+ end
70
+ end
71
+
72
+ # The builder `sig`'s block is `instance_eval`'d on (`DeclBuilder#instance_eval(&blk)` via
73
+ # `T::Private::Methods._run_builder`). Every DSL method returns `self` so the
74
+ # `params(...).returns(...).checked(:always)` chain keeps typing.
75
+ class T::Private::Methods::DeclBuilder
76
+ def params: (*untyped unused_positional_params, **untyped params) -> self
77
+ def returns: (untyped type) -> self
78
+ def void: () -> self
79
+ def bind: (untyped type) -> self
80
+ def checked: (untyped level) -> self
81
+ def on_failure: (*untyped args) -> self
82
+ def abstract: () -> self
83
+ def final: () -> self
84
+ def override: (?allow_incompatible: bool | Symbol) -> self
85
+ def overridable: () -> self
86
+ def type_parameters: (*untyped names) -> self
87
+ end
88
+
89
+ # The `T::X[...]` type constructors are modules with a singleton `[]` (`_types.rb`), returning the
90
+ # corresponding `T::Types::TypedX` instance. The carriers below exist so the constructor's return
91
+ # reads as a real nominal rather than `Dynamic[top]`.
92
+ module T::Array
93
+ def self.[]: (untyped type) -> ::T::Types::TypedArray
94
+ end
95
+
96
+ module T::Hash
97
+ def self.[]: (untyped keys, untyped values) -> ::T::Types::TypedHash
98
+ end
99
+
100
+ module T::Set
101
+ def self.[]: (untyped type) -> ::T::Types::TypedSet
102
+ end
103
+
104
+ module T::Enumerable
105
+ def self.[]: (untyped type) -> ::T::Types::TypedEnumerable
106
+ end
107
+
108
+ module T::Enumerator
109
+ def self.[]: (untyped type) -> ::T::Types::TypedEnumerator
110
+ end
111
+
112
+ module T::Range
113
+ def self.[]: (untyped type) -> ::T::Types::TypedRange
114
+ end
115
+
116
+ module T::Class
117
+ def self.[]: (untyped type) -> ::T::Types::TypedClass
118
+ end
119
+
120
+ # Carrier classes for the `T::X[...]` constructors and the `T.*` type-expression functions. The
121
+ # internal `T::Types::*` class names are the runtime classes (`types/types/*.rb`).
122
+ module T::Types
123
+ class Base
124
+ end
125
+
126
+ class TypedArray < Base
127
+ end
128
+
129
+ class TypedHash < Base
130
+ end
131
+
132
+ class TypedSet < Base
133
+ end
134
+
135
+ class TypedEnumerable < Base
136
+ end
137
+
138
+ class TypedEnumerator < Base
139
+ end
140
+
141
+ class TypedRange < Base
142
+ end
143
+
144
+ class TypedClass < Base
145
+ end
146
+
147
+ class Union < Base
148
+ end
149
+
150
+ class Intersection < Base
151
+ end
152
+
153
+ class TypeParameter < Base
154
+ end
155
+
156
+ class TypeMember < Base
157
+ end
158
+
159
+ class TypeTemplate < Base
160
+ end
161
+
162
+ class Proc < Base
163
+ end
164
+ end
165
+
166
+ # `extend T::Helpers` installs the class/module declaration macros (`abstract!`, `interface!`,
167
+ # `final!`, `sealed!`, `requires_ancestor`, `mixes_in_class_methods`). All return void-ish values
168
+ # from `T::Private::{Abstract,Final,Sealed}` bookkeeping (`helpers.rb`).
169
+ module T::Helpers
170
+ def abstract!: () -> void
171
+ def interface!: () -> void
172
+ def final!: () -> void
173
+ def sealed!: () -> void
174
+ def mixes_in_class_methods: (::Module mod, *::Module mods) -> void
175
+ def requires_ancestor: () { () -> untyped } -> void
176
+ end
177
+
178
+ # `extend T::Generic` installs the type-member macros — `Elem = type_member` is the common shape
179
+ # (`generic.rb`). `[]` is the generic-application stub (`def [](*types); self; end`).
180
+ module T::Generic
181
+ # `generic.rb` — `extend T::Generic` alone also installs the helper macros: the module
182
+ # `include`s `T::Helpers` (and `Kernel`), so its instance surface carries `abstract!` et al.
183
+ include T::Helpers
184
+
185
+ def []: (*untyped types) -> self
186
+ def type_member: (?untyped variance) ?{ () -> untyped } -> ::T::Types::TypeMember
187
+ def type_template: (?untyped variance) ?{ () -> untyped } -> ::T::Types::TypeTemplate
188
+ def has_attached_class!: (?untyped variance) ?{ () -> untyped } -> void
189
+ end
190
+
191
+ # `T::Props` is the property mixin; its `included` hook `extend`s the includer with
192
+ # `ClassMethods` (`mixes_in_class_methods`), which is where `prop` / `const` live. The hook itself
193
+ # is not modelled — `include T::Props` alone does not put `prop` on the class in this
194
+ # declaration either — but the `T::Struct` family below declares the same `extend` edges directly,
195
+ # matching the runtime outcome for `< T::Struct` subclasses.
196
+ module T::Props
197
+ module ClassMethods
198
+ def prop: (::Symbol name, untyped cls, **untyped rules) -> void
199
+ def const: (::Symbol name, untyped cls_or_args, **untyped args) -> void
200
+ def props: () -> ::Hash[untyped, untyped]
201
+ def plugins: () -> ::Array[untyped]
202
+ def decorator: () -> ::T::Props::Decorator
203
+ def decorator_class: () -> ::Class
204
+ def validate_prop_value: (untyped prop, untyped val) -> void
205
+ def plugin: (untyped mod) -> void
206
+ end
207
+
208
+ class Decorator
209
+ end
210
+
211
+ module CustomType
212
+ end
213
+
214
+ module Serializable
215
+ # `serializable.rb` — lifted onto includers via `mixes_in_class_methods`.
216
+ module ClassMethods
217
+ def prop_by_serialized_forms: () -> ::Hash[untyped, untyped]
218
+ def from_hash: (untyped hash, ?bool strict) -> untyped
219
+ def from_hash!: (untyped hash) -> untyped
220
+ end
221
+ end
222
+
223
+ module Plugin
224
+ # `plugin.rb` — `mixes_in_class_methods(ClassMethods)`; `included` re-registers the plugin
225
+ # (`child.plugin(self)`), which is what extends `plugin::ClassMethods` onto the target.
226
+ module ClassMethods
227
+ def included: (untyped child) -> void
228
+ end
229
+ end
230
+ end
231
+
232
+ # The `T::Struct` family. `struct.rb` has `T::InexactStruct` `include T::Props` (+Serializable,
233
+ # +Constructor); the `mixes_in_class_methods` hooks extend `T::Props::ClassMethods` (then the
234
+ # registered `T::Props::Plugin::ClassMethods`) and `T::Props::Serializable::ClassMethods` onto the
235
+ # class — verified against the runtime singleton ancestry. Neither `T::Sig` nor `T::Helpers` is
236
+ # extended here: `sig` inside a `class Doc < T::Struct` body raises at runtime unless the subclass
237
+ # adds `extend T::Sig` itself (dependabot's `TokenBucket` does exactly that). Only
238
+ # `T::ImmutableStruct` extends `T::Sig` (`struct.rb` — it annotates its own `initialize`). The
239
+ # edges are declared directly so subclasses resolve `prop` / `const` / `from_hash` through the
240
+ # `rbs_complete_ancestors` superclass bridge.
241
+ class T::InexactStruct
242
+ extend T::Props::ClassMethods
243
+ extend T::Props::Plugin::ClassMethods
244
+ extend T::Props::Serializable::ClassMethods
245
+ end
246
+
247
+ class T::Struct < T::InexactStruct
248
+ end
249
+
250
+ class T::ImmutableStruct < T::InexactStruct
251
+ extend T::Sig
252
+ end
253
+
254
+ # `T::Enum` — `enum.rb` `extend`s `T::Sig` and `T::Props::CustomType`; `enums` `yield`s its block
255
+ # so `X = new` inside keeps the subclass's class-object self.
256
+ class T::Enum
257
+ extend T::Sig
258
+ extend T::Props::CustomType
259
+
260
+ def self.enums: () { () -> untyped } -> void
261
+ def serialize: () -> ::String
262
+ end
263
+
264
+ # Namespace-only declarations so bare const reads (`T::Utils`, `T::Configuration`,
265
+ # `T::Private::Methods`) type as `Singleton[...]` instead of `Dynamic[top]`. Their singleton
266
+ # surface is intentionally NOT modelled — they are covered by `open_receivers:` so calls on them
267
+ # degrade to opaque rather than firing `call.undefined-method` on an unmodelled private API.
268
+ module T::Utils
269
+ end
270
+
271
+ module T::Configuration
272
+ end
273
+
274
+ module T::Private
275
+ module Methods
276
+ end
277
+ end
@@ -43,6 +43,7 @@ module Rigor
43
43
  class Statesman < Rigor::Plugin::Base
44
44
  manifest(
45
45
  id: "statesman",
46
+ target_gems: ["statesman"],
46
47
  version: "0.1.0",
47
48
  description: "Validates state-machine transition references against declared states.",
48
49
  config_schema: {
@@ -6,26 +6,88 @@ module Rigor
6
6
  class LoadError < ::StandardError
7
7
  end
8
8
 
9
+ # Tuple-shaped bucket key so rule-ID rows and message-pattern rows coexist: `message_regex` is
10
+ # `nil` for rule-ID rows and a `Regexp` for message-pattern rows; `rule` and `file` are always
11
+ # present (parse_row raises without them; the generator's group key carries both). `count`
12
+ # intentionally shadows `Struct#count` — PHPStan-compatible field name.
13
+ class Bucket < ::Struct[untyped]
14
+ # sig-gen gap: #1183 — Struct member types are not inferred from construction sites; every
15
+ # member row in this class (and the keyword ctor below) is hand-written.
16
+ def file: () -> String
17
+ # sig-gen gap: #1183 — as above.
18
+ def rule: () -> String
19
+ # sig-gen gap: #1183 — as above.
20
+ def message_regex: () -> Regexp?
21
+ # sig-gen gap: #1183 — as above.
22
+ def count: () -> Integer
23
+ # sig-gen gap: #1183 — as above.
24
+ def file=: (String) -> String
25
+ # sig-gen gap: #1183 — as above.
26
+ def rule=: (String) -> String
27
+ # sig-gen gap: #1183 — as above.
28
+ def message_regex=: (Regexp?) -> Regexp?
29
+ # sig-gen gap: #1183 — as above.
30
+ def count=: (Integer) -> Integer
31
+ # sig-gen gap: #1183 — as above.
32
+ def self.new: (?file: String, ?rule: String, ?message_regex: Regexp?, ?count: Integer) -> instance
33
+ # sig-gen gap: #1183 — as above.
34
+ def self.[]: (?file: String, ?rule: String, ?message_regex: Regexp?, ?count: Integer) -> instance
35
+ end
36
+
37
+ # One bucket's drift state for `audit`. `status` is the four-way verdict `status_for` returns;
38
+ # `delta` is `actual_count - bucket.count` (positive = over threshold).
39
+ class DriftRow < ::Struct[untyped]
40
+ # sig-gen gap: #1183 — Struct member types are not inferred from construction sites; as above.
41
+ def bucket: () -> Bucket
42
+ # sig-gen gap: #1183 — as above.
43
+ def actual_count: () -> Integer
44
+ # sig-gen gap: #1183 — as above.
45
+ def status: () -> (:within | :over | :cleared | :reducible)
46
+ def delta: () -> Integer
47
+ # sig-gen gap: #1183 — as above.
48
+ def bucket=: (Bucket) -> Bucket
49
+ # sig-gen gap: #1183 — as above.
50
+ def actual_count=: (Integer) -> Integer
51
+ # sig-gen gap: #1183 — as above.
52
+ def status=: (:within | :over | :cleared | :reducible) -> (:within | :over | :cleared | :reducible)
53
+ # sig-gen gap: #1183 — as above.
54
+ def self.new: (?bucket: Bucket, ?actual_count: Integer, ?status: :within | :over | :cleared | :reducible) -> instance
55
+ # sig-gen gap: #1183 — as above.
56
+ def self.[]: (?bucket: Bucket, ?actual_count: Integer, ?status: :within | :over | :cleared | :reducible) -> instance
57
+ end
58
+
9
59
  # Load a baseline file from disk.
10
60
  # Returns `nil` when `path` is nil (no baseline configured).
11
61
  # Raises {LoadError} on malformed or unsupported content.
12
62
  def self.load: (::String? path, ?project_root: ::String) -> Baseline?
13
63
 
14
64
  # Build a baseline from a current run's diagnostic stream.
15
- def self.from_diagnostics: (untyped diagnostics, ?match_mode: :rule | :message) -> Baseline
65
+ def self.from_diagnostics: (untyped diagnostics, ?match_mode: :rule | :message, ?project_root: ::String | ::Pathname) -> Baseline
16
66
 
17
- attr_reader buckets: untyped
67
+ # Always an Array of Bucket — `initialize` freezes what it is given and every caller hands it
68
+ # Bucket instances (parse_row rows, from_diagnostics groups, `without`'s reject, or `[]`).
69
+ # sig-gen gap: #1154 — an `attr_reader` over an ivar assigned in `initialize` from a parameter
70
+ # is skipped (untyped return); the element type is hand-written.
71
+ attr_reader buckets: Array[Bucket]
18
72
 
19
- def initialize: (untyped buckets) -> void
73
+ # `project_root` is `Pathname.new`'d, so a `Pathname` is accepted as well as a `String`
74
+ # (`without` re-passes the stored Pathname).
75
+ def initialize: (Array[Bucket] buckets, ?project_root: ::String | ::Pathname) -> void
20
76
 
21
77
  # Apply the baseline filter. Returns [surfaced_diagnostics, silenced_count].
22
- def filter: (untyped diagnostics) -> [untyped, ::Integer]
78
+ # `diagnostics` stays `untyped`: `Analysis::Diagnostic`'s sig is partial (no `qualified_rule`),
79
+ # so a tighter param would put `diag.qualified_rule` behind an unsigned member. The declared
80
+ # `[Array[untyped], Integer]` diverges from sig-gen's inference
81
+ # (`[Array[untyped], untyped] | [untyped, 0]` — the literal seed and the accumulated local are
82
+ # unproven); the `Integer` count is the author's intent.
83
+ def filter: (untyped diagnostics) -> [Array[untyped], ::Integer]
23
84
 
24
- # Report bucket-level drift for each recorded baseline bucket.
25
- def audit: (untyped diagnostics) -> untyped
85
+ # Report bucket-level drift for each recorded baseline bucket — one DriftRow per bucket, in
86
+ # baseline-file order.
87
+ def audit: (untyped diagnostics) -> Array[DriftRow]
26
88
 
27
89
  # Return a new Baseline with the given buckets removed.
28
- def without: (untyped buckets_to_drop) -> Baseline
90
+ def without: (Array[Bucket] buckets_to_drop) -> Baseline
29
91
 
30
92
  # Serialise to a YAML string.
31
93
  def to_yaml: () -> ::String
@@ -2,7 +2,7 @@ module Rigor
2
2
  module Analysis
3
3
  module CheckRules
4
4
  def self?.diagnose: (path: String, root: untyped, scope_index: Hash[untyped, Scope]) -> Array[Diagnostic]
5
- def self?.build_node_collectors: (String path, untyped scope_index) -> Hash[Symbol, untyped]
5
+ def self?.build_node_collectors: (String path, untyped scope_index, ?untyped root) -> Hash[Symbol, untyped]
6
6
  def self?.node_collector_driver: (Hash[Symbol, untyped] collectors) -> untyped
7
7
  def self?.shadow_verify_converged_collectors: (String path, untyped root, untyped scope_index, Hash[Symbol, untyped]? collectors) -> void
8
8
  def self?.filter_suppressed: (Array[Diagnostic] diagnostics, comments: untyped, disabled_rules: Array[String]) -> Array[Diagnostic]