rigortype 0.3.8 → 0.3.9

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 (447) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/data/capability_roles/capability_roles.rbs +36 -0
  4. data/data/gem_overlay/activesupport/core_ext.rbs +109 -13
  5. data/docs/handbook/02-everyday-types.md +17 -14
  6. data/docs/handbook/03-narrowing.md +37 -4
  7. data/docs/handbook/05-methods-and-blocks.md +1 -1
  8. data/docs/handbook/06-classes.md +2 -2
  9. data/docs/handbook/07-rbs-and-extended.md +14 -1
  10. data/docs/handbook/11-sig-gen.md +72 -1
  11. data/docs/handbook/README.md +1 -1
  12. data/docs/handbook/appendix-elixir.md +2 -2
  13. data/docs/handbook/appendix-go.md +2 -2
  14. data/docs/handbook/appendix-java-csharp.md +2 -2
  15. data/docs/handbook/appendix-mypy.md +2 -2
  16. data/docs/handbook/appendix-phpstan.md +1 -1
  17. data/docs/handbook/appendix-rust.md +1 -1
  18. data/docs/handbook/appendix-type-theory.md +4 -4
  19. data/docs/handbook/appendix-typescript.md +1 -1
  20. data/docs/llms.txt +2 -0
  21. data/docs/manual/02-cli-reference.md +32 -4
  22. data/docs/manual/03-configuration.md +11 -0
  23. data/docs/manual/04-diagnostics.md +11 -0
  24. data/docs/manual/07-plugins.md +15 -5
  25. data/docs/manual/08-skills.md +23 -2
  26. data/docs/manual/11-ci.md +9 -0
  27. data/docs/manual/15-type-protection-coverage.md +8 -0
  28. data/docs/manual/16-rbs-extended-annotations.md +6 -1
  29. data/docs/manual/18-removing-dead-code.md +10 -8
  30. data/docs/manual/plugins/rigor-actionpack.md +18 -0
  31. data/docs/manual/plugins/rigor-activerecord.md +28 -0
  32. data/docs/manual/plugins/rigor-activesupport-core-ext.md +32 -2
  33. data/docs/manual/plugins/rigor-rbs-inline.md +42 -1
  34. data/lib/rigor/analysis/baseline.rb +2 -2
  35. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
  36. data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
  37. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
  38. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +1 -1
  39. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
  40. data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
  41. data/lib/rigor/analysis/check_rules/rule_walk.rb +39 -4
  42. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
  43. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -1
  44. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +2 -2
  45. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
  46. data/lib/rigor/analysis/check_rules.rb +200 -32
  47. data/lib/rigor/analysis/crash_signature.rb +8 -24
  48. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
  49. data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
  50. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
  51. data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
  52. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
  53. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  54. data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
  55. data/lib/rigor/analysis/erb_template_detector.rb +1 -2
  56. data/lib/rigor/analysis/fact_store.rb +6 -1
  57. data/lib/rigor/analysis/incremental.rb +16 -0
  58. data/lib/rigor/analysis/incremental_session.rb +81 -22
  59. data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
  60. data/lib/rigor/analysis/reachability/graph.rb +3 -5
  61. data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -5
  62. data/lib/rigor/analysis/reachability/project_files.rb +2 -2
  63. data/lib/rigor/analysis/reachability/scan.rb +5 -5
  64. data/lib/rigor/analysis/reachability/scan_cache.rb +2 -2
  65. data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
  66. data/lib/rigor/analysis/result.rb +1 -3
  67. data/lib/rigor/analysis/rule_catalog.rb +4 -1
  68. data/lib/rigor/analysis/run_cache_key.rb +1 -1
  69. data/lib/rigor/analysis/run_cache_probe.rb +3 -5
  70. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
  71. data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
  72. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +177 -26
  73. data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
  74. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -10
  75. data/lib/rigor/analysis/runner/pool_coordinator.rb +256 -88
  76. data/lib/rigor/analysis/runner/project_pre_passes.rb +12 -6
  77. data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
  78. data/lib/rigor/analysis/runner.rb +133 -35
  79. data/lib/rigor/analysis/worker_session.rb +9 -10
  80. data/lib/rigor/bleeding_edge.rb +12 -24
  81. data/lib/rigor/builtins/hkt_builtins.rb +2 -2
  82. data/lib/rigor/builtins/imported_refinements.rb +155 -21
  83. data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
  84. data/lib/rigor/builtins/regex_refinement.rb +4 -4
  85. data/lib/rigor/builtins/static_return_refinements.rb +5 -6
  86. data/lib/rigor/cache/annotation_location.rb +2 -4
  87. data/lib/rigor/cache/descriptor.rb +58 -20
  88. data/lib/rigor/cache/engine_source.rb +4 -4
  89. data/lib/rigor/cache/file_digest.rb +9 -1
  90. data/lib/rigor/cache/incremental_snapshot.rb +40 -6
  91. data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
  92. data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
  93. data/lib/rigor/cache/rbs_constant_table.rb +0 -3
  94. data/lib/rigor/cache/rbs_descriptor.rb +79 -11
  95. data/lib/rigor/cache/rbs_environment.rb +8 -4
  96. data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
  97. data/lib/rigor/cache/store.rb +77 -32
  98. data/lib/rigor/cli/annotate_command.rb +5 -6
  99. data/lib/rigor/cli/check_command.rb +57 -10
  100. data/lib/rigor/cli/check_invocation.rb +6 -11
  101. data/lib/rigor/cli/check_runner_factory.rb +1 -5
  102. data/lib/rigor/cli/coverage_command.rb +1 -1
  103. data/lib/rigor/cli/coverage_mutation.rb +12 -3
  104. data/lib/rigor/cli/coverage_scan.rb +1 -5
  105. data/lib/rigor/cli/diff_command.rb +1 -1
  106. data/lib/rigor/cli/doc_links.rb +3 -3
  107. data/lib/rigor/cli/docs_command.rb +2 -2
  108. data/lib/rigor/cli/doctor_command.rb +85 -38
  109. data/lib/rigor/cli/effects_command.rb +2 -2
  110. data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
  111. data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
  112. data/lib/rigor/cli/explain_command.rb +34 -1
  113. data/lib/rigor/cli/fused_protection_report.rb +7 -1
  114. data/lib/rigor/cli/lsp_command.rb +1 -1
  115. data/lib/rigor/cli/mcp_command.rb +1 -1
  116. data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
  117. data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
  118. data/lib/rigor/cli/mutation_protection_report.rb +7 -1
  119. data/lib/rigor/cli/plugin_command.rb +1 -1
  120. data/lib/rigor/cli/plugins_command.rb +2 -1
  121. data/lib/rigor/cli/prism_colorizer.rb +2 -2
  122. data/lib/rigor/cli/protection_fork_scan.rb +6 -6
  123. data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
  124. data/lib/rigor/cli/sig_gen_command.rb +2 -2
  125. data/lib/rigor/cli/skill_command.rb +1 -1
  126. data/lib/rigor/cli/skill_deep_probe.rb +4 -4
  127. data/lib/rigor/cli/skill_describe.rb +36 -35
  128. data/lib/rigor/cli/trace_command.rb +4 -4
  129. data/lib/rigor/cli/trace_renderer.rb +5 -6
  130. data/lib/rigor/cli/triage_command.rb +1 -1
  131. data/lib/rigor/cli/type_of_command.rb +10 -6
  132. data/lib/rigor/cli/type_scan_command.rb +4 -4
  133. data/lib/rigor/cli/unused_command.rb +11 -3
  134. data/lib/rigor/cli/upgrade_command.rb +1 -1
  135. data/lib/rigor/cli.rb +68 -6
  136. data/lib/rigor/config_audit.rb +30 -5
  137. data/lib/rigor/configuration/severity_profile.rb +6 -6
  138. data/lib/rigor/configuration.rb +43 -4
  139. data/lib/rigor/effects/attribution.rb +1 -3
  140. data/lib/rigor/effects/config_envelopes.rb +6 -8
  141. data/lib/rigor/effects/definition_lines.rb +25 -6
  142. data/lib/rigor/effects/effect_table.rb +0 -1
  143. data/lib/rigor/effects/entry_points.rb +0 -2
  144. data/lib/rigor/effects/envelope_check.rb +8 -8
  145. data/lib/rigor/effects/envelope_index.rb +5 -8
  146. data/lib/rigor/effects/framework_units.rb +4 -6
  147. data/lib/rigor/effects/identity.rb +4 -6
  148. data/lib/rigor/effects/inline_anchor.rb +7 -7
  149. data/lib/rigor/effects/label_intent.rb +3 -4
  150. data/lib/rigor/effects/liskov_check.rb +8 -8
  151. data/lib/rigor/effects/method_key.rb +1 -1
  152. data/lib/rigor/effects/plugin_facts.rb +4 -6
  153. data/lib/rigor/effects/propagator.rb +2 -3
  154. data/lib/rigor/effects/scanner.rb +1 -1
  155. data/lib/rigor/effects/signature_sources.rb +3 -5
  156. data/lib/rigor/effects/snapshot.rb +10 -10
  157. data/lib/rigor/effects/snapshot_diff.rb +1 -1
  158. data/lib/rigor/effects/unit_scan.rb +10 -10
  159. data/lib/rigor/effects/unknown_label_check.rb +3 -8
  160. data/lib/rigor/effects/unknown_label_report.rb +3 -4
  161. data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
  162. data/lib/rigor/environment/class_registry.rb +3 -1
  163. data/lib/rigor/environment/failure_slot.rb +2 -2
  164. data/lib/rigor/environment/installed_gem_set.rb +85 -0
  165. data/lib/rigor/environment/lockfile_resolver.rb +51 -4
  166. data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
  167. data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
  168. data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
  169. data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
  170. data/lib/rigor/environment/rbs_loader.rb +388 -59
  171. data/lib/rigor/environment.rb +105 -20
  172. data/lib/rigor/flow_contribution/merger.rb +0 -2
  173. data/lib/rigor/flow_contribution.rb +11 -13
  174. data/lib/rigor/inference/acceptance.rb +153 -8
  175. data/lib/rigor/inference/block_parameter_binder.rb +2 -3
  176. data/lib/rigor/inference/body_fixpoint.rb +5 -5
  177. data/lib/rigor/inference/budget_trace.rb +1 -5
  178. data/lib/rigor/inference/captured_locals.rb +2 -3
  179. data/lib/rigor/inference/closure_escape_analyzer.rb +2 -4
  180. data/lib/rigor/inference/coverage_scanner.rb +4 -6
  181. data/lib/rigor/inference/dynamic_origin.rb +1 -1
  182. data/lib/rigor/inference/element_read_widening.rb +168 -0
  183. data/lib/rigor/inference/expression_typer.rb +763 -143
  184. data/lib/rigor/inference/fork_map.rb +5 -7
  185. data/lib/rigor/inference/hkt_reducer.rb +2 -3
  186. data/lib/rigor/inference/hkt_registry.rb +4 -7
  187. data/lib/rigor/inference/index_write_widening.rb +1 -5
  188. data/lib/rigor/inference/macro_block_self_type.rb +1 -4
  189. data/lib/rigor/inference/method_dispatcher/block_folding.rb +2 -9
  190. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
  191. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
  192. data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
  193. data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
  194. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +2 -2
  195. data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
  196. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
  197. data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
  198. data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
  199. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +61 -47
  200. data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
  201. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +165 -31
  202. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
  203. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
  204. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
  205. data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
  206. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +1 -1
  207. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
  208. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
  209. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +4 -5
  210. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
  211. data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
  212. data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
  213. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  214. data/lib/rigor/inference/method_dispatcher.rb +12 -13
  215. data/lib/rigor/inference/method_parameter_binder.rb +4 -6
  216. data/lib/rigor/inference/multi_target_binder.rb +1 -3
  217. data/lib/rigor/inference/mutation_rejoin.rb +168 -0
  218. data/lib/rigor/inference/mutation_widening.rb +100 -51
  219. data/lib/rigor/inference/narrowing.rb +299 -46
  220. data/lib/rigor/inference/optimistic_origin.rb +1 -7
  221. data/lib/rigor/inference/origin_lookup.rb +2 -3
  222. data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
  223. data/lib/rigor/inference/pre_eval_constants.rb +6 -5
  224. data/lib/rigor/inference/precision_scanner.rb +3 -4
  225. data/lib/rigor/inference/project_patched_methods.rb +2 -2
  226. data/lib/rigor/inference/project_patched_scanner.rb +3 -3
  227. data/lib/rigor/inference/protection_scanner.rb +1 -2
  228. data/lib/rigor/inference/range_constant.rb +57 -0
  229. data/lib/rigor/inference/rbs_type_translator.rb +49 -11
  230. data/lib/rigor/inference/receiver_alias.rb +3 -3
  231. data/lib/rigor/inference/refinement_mutation.rb +72 -0
  232. data/lib/rigor/inference/scope_indexer.rb +688 -151
  233. data/lib/rigor/inference/statement_evaluator.rb +221 -50
  234. data/lib/rigor/inference/string_mutation.rb +60 -0
  235. data/lib/rigor/inference/struct_fold_safety.rb +6 -7
  236. data/lib/rigor/inference/synthetic_method_index.rb +1 -2
  237. data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
  238. data/lib/rigor/inference/version_guard.rb +28 -21
  239. data/lib/rigor/inference/void_origin.rb +3 -3
  240. data/lib/rigor/inference/void_tail_summary.rb +2 -4
  241. data/lib/rigor/language_server/buffer_table.rb +4 -4
  242. data/lib/rigor/language_server/completion_provider.rb +1 -1
  243. data/lib/rigor/language_server/debouncer.rb +1 -1
  244. data/lib/rigor/language_server/diagnostic_publisher.rb +4 -4
  245. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  246. data/lib/rigor/language_server/folding_range_provider.rb +1 -1
  247. data/lib/rigor/language_server/hover_provider.rb +1 -1
  248. data/lib/rigor/language_server/hover_renderer.rb +2 -2
  249. data/lib/rigor/language_server/incremental_sync.rb +6 -6
  250. data/lib/rigor/language_server/project_context.rb +2 -5
  251. data/lib/rigor/language_server/publish_batcher.rb +2 -2
  252. data/lib/rigor/language_server/selection_range_provider.rb +2 -2
  253. data/lib/rigor/language_server/server.rb +9 -9
  254. data/lib/rigor/language_server/signature_help_provider.rb +1 -1
  255. data/lib/rigor/language_server/uri.rb +1 -1
  256. data/lib/rigor/plugin/base.rb +90 -21
  257. data/lib/rigor/plugin/bundled_catalog.rb +167 -0
  258. data/lib/rigor/plugin/effect_attribution.rb +7 -7
  259. data/lib/rigor/plugin/effect_entry_points.rb +3 -3
  260. data/lib/rigor/plugin/fact_store.rb +6 -6
  261. data/lib/rigor/plugin/io_boundary.rb +93 -8
  262. data/lib/rigor/plugin/isolation.rb +29 -6
  263. data/lib/rigor/plugin/loader.rb +31 -12
  264. data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
  265. data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
  266. data/lib/rigor/plugin/manifest.rb +23 -1
  267. data/lib/rigor/plugin/registry.rb +42 -12
  268. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +12 -1
  269. data/lib/rigor/plugin/trust_policy.rb +2 -4
  270. data/lib/rigor/plugin/type_node_resolver.rb +3 -3
  271. data/lib/rigor/plugin_gap_advisory.rb +96 -0
  272. data/lib/rigor/project_environment.rb +138 -0
  273. data/lib/rigor/protection/analysis_guard.rb +93 -14
  274. data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
  275. data/lib/rigor/protection/dependency_closure.rb +5 -8
  276. data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
  277. data/lib/rigor/protection/discovery_seed.rb +11 -11
  278. data/lib/rigor/protection/kill_signature.rb +2 -4
  279. data/lib/rigor/protection/measurement_integrity.rb +1 -3
  280. data/lib/rigor/protection/mutation_cache.rb +6 -9
  281. data/lib/rigor/protection/mutation_scanner.rb +12 -15
  282. data/lib/rigor/protection/mutator.rb +2 -1
  283. data/lib/rigor/protection/test_suite_oracle.rb +5 -5
  284. data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
  285. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  286. data/lib/rigor/rbs_extended/reporter.rb +36 -10
  287. data/lib/rigor/rbs_extended.rb +61 -21
  288. data/lib/rigor/reflection/constant_path.rb +126 -0
  289. data/lib/rigor/reflection.rb +26 -10
  290. data/lib/rigor/runtime/jit.rb +6 -8
  291. data/lib/rigor/scope/discovery_index.rb +30 -0
  292. data/lib/rigor/scope.rb +203 -4
  293. data/lib/rigor/sig_gen/generator.rb +115 -22
  294. data/lib/rigor/sig_gen/layout_index.rb +3 -4
  295. data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
  296. data/lib/rigor/sig_gen/observation_collector.rb +17 -15
  297. data/lib/rigor/sig_gen/path_mapper.rb +4 -6
  298. data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
  299. data/lib/rigor/sig_gen/renderer.rb +4 -5
  300. data/lib/rigor/sig_gen/skip_reason_catalog.rb +111 -0
  301. data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
  302. data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
  303. data/lib/rigor/sig_gen/writer.rb +23 -6
  304. data/lib/rigor/signature_path_audit.rb +153 -6
  305. data/lib/rigor/source/literals.rb +0 -23
  306. data/lib/rigor/source/node_children.rb +0 -2
  307. data/lib/rigor/source/node_locator.rb +5 -11
  308. data/lib/rigor/source/node_walker.rb +2 -5
  309. data/lib/rigor/triage/catalogue.rb +1 -3
  310. data/lib/rigor/triage.rb +3 -5
  311. data/lib/rigor/type/accepts_result.rb +24 -6
  312. data/lib/rigor/type/combinator.rb +68 -5
  313. data/lib/rigor/type/data_class.rb +2 -2
  314. data/lib/rigor/type/data_instance.rb +4 -4
  315. data/lib/rigor/type/float_range.rb +128 -0
  316. data/lib/rigor/type/hash_shape.rb +5 -5
  317. data/lib/rigor/type/integer_range.rb +13 -8
  318. data/lib/rigor/type/nominal.rb +8 -2
  319. data/lib/rigor/type/refined.rb +3 -3
  320. data/lib/rigor/type/struct_class.rb +3 -3
  321. data/lib/rigor/type/struct_instance.rb +4 -4
  322. data/lib/rigor/type.rb +1 -0
  323. data/lib/rigor/type_node/generic.rb +1 -1
  324. data/lib/rigor/type_node/range_literal.rb +25 -0
  325. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  326. data/lib/rigor/type_node.rb +1 -0
  327. data/lib/rigor/version.rb +1 -1
  328. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
  329. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
  330. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
  331. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -0
  332. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
  333. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
  334. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
  335. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +1 -0
  336. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +33 -30
  337. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
  338. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
  339. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +28 -2
  340. data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
  341. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
  342. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
  343. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
  344. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
  345. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
  346. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +1 -0
  347. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +3 -4
  348. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
  349. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
  350. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +42 -7
  351. data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
  352. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +1 -0
  353. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
  354. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +119 -14
  355. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
  356. data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +1 -0
  357. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
  358. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
  359. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
  360. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
  361. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
  362. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
  363. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
  364. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +1 -0
  365. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
  366. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
  367. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
  368. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
  369. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
  370. data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
  371. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
  372. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +6 -3
  373. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
  374. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
  375. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +0 -3
  376. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
  377. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
  378. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
  379. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
  380. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
  381. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +1 -0
  382. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
  383. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
  384. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
  385. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +1 -0
  386. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
  387. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +1 -10
  388. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +3 -3
  389. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +2 -2
  390. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
  391. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
  392. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
  393. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
  394. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +1 -0
  395. data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
  396. data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
  397. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +128 -3
  398. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
  399. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
  400. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
  401. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
  402. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
  403. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
  404. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
  405. data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
  406. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
  407. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
  408. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
  409. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
  410. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +1 -1
  411. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
  412. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
  413. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +1 -0
  414. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
  415. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
  416. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
  417. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
  418. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
  419. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
  420. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +4 -5
  421. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
  422. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +5 -5
  423. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
  424. data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
  425. data/sig/rigor/cache.rbs +2 -3
  426. data/sig/rigor/environment.rbs +5 -0
  427. data/sig/rigor/inference.rbs +3 -10
  428. data/sig/rigor/plugin/io_boundary.rbs +4 -0
  429. data/sig/rigor/plugin/manifest.rbs +2 -1
  430. data/sig/rigor/reflection.rbs +3 -1
  431. data/sig/rigor/scope.rbs +24 -3
  432. data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -0
  433. data/sig/rigor/type.rbs +27 -1
  434. data/sig/rigor.rbs +1 -0
  435. data/skills/rigor-ask/SKILL.md +8 -6
  436. data/skills/rigor-plugin-author/references/02-walker-and-types.md +13 -2
  437. data/skills/rigor-project-init/SKILL.md +6 -3
  438. data/skills/rigor-project-init/references/02-configure.md +10 -6
  439. data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
  440. data/skills/rigor-type-oracle/SKILL.md +228 -0
  441. data/skills/rigor-type-oracle/references/01-oracle-commands.md +261 -0
  442. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
  443. data/skills/rigor-type-oracle/references/03-gap-protocol.md +128 -0
  444. data/skills/rigor-unused-adjudicate/SKILL.md +8 -5
  445. metadata +26 -3
  446. data/lib/rigor/cli/probe_environment.rb +0 -85
  447. data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
@@ -45,11 +45,7 @@ module Rigor
45
45
  def singleton_def?: (untyped def_node) -> bool
46
46
  def self_type_for_class_body: (Array[ClassFrame] class_context) -> Type::t?
47
47
  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
48
  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
49
  def drop_captured_narrowing: (untyped block_node, Scope base_scope) -> Scope
54
50
  def classify_closure_escape: (untyped call_node) -> closure_classification
55
51
  def record_closure_escape_if_any: (untyped node) -> Scope
@@ -108,12 +104,12 @@ module Rigor
108
104
  def self?.narrow_non_nil: (Type::t type) -> Type::t
109
105
  def self?.narrow_equal: (Type::t type, untyped literal) -> Type::t
110
106
  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
107
+ def self?.narrow_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment, ?scope: Scope?) -> Type::t
108
+ def self?.narrow_not_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment, ?scope: Scope?) -> Type::t
113
109
  def self?.narrow_not_refinement: (Type::t current_type, Type::t refinement_type) -> Type::t
114
110
  def self?.narrow_for_fact: (Type::t current, untyped fact, untyped environment) -> Type::t
115
111
  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)
112
+ def self?.class_pattern_certainty: (Type::t subject_type, String class_name, environment: Environment, ?scope: Scope?) -> (:yes | :no | :maybe)
117
113
  def self?.value_pattern_certainty: (Type::t subject_type, untyped pattern_value) -> (:yes | :no | :maybe)
118
114
  def self?.predicate_scopes: (untyped node, Scope scope) -> [Scope, Scope]
119
115
  def self?.case_when_scopes: (untyped subject, Array[untyped] conditions, Scope scope) -> [Scope, Scope]
@@ -162,7 +158,6 @@ module Rigor
162
158
 
163
159
  module ScopeIndexer
164
160
  def self?.index: (untyped root, default_scope: Scope) -> Hash[untyped, Scope]
165
- def self?.build_declaration_overrides: (untyped root) -> Hash[untyped, Type::t]
166
161
  def self?.build_declaration_artifacts: (untyped root) -> [Hash[untyped, Type::t], Hash[String, Type::t]]
167
162
  def self?.build_in_source_constants: (untyped root, Scope default_scope) -> Hash[String, Type::t]
168
163
  def self?.record_declarations: (untyped node, Array[String] qualified_prefix, Hash[untyped, Type::t] identity_table, Hash[String, Type::t] discovered) -> void
@@ -176,8 +171,6 @@ module Rigor
176
171
  def self?.constant_writes_for_file: (untyped root) -> Hash[String, untyped]
177
172
  def self?.constant_literal_value: (untyped rvalue) -> Array[untyped]?
178
173
  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
181
174
  def self?.propagate: (untyped node, Hash[untyped, Scope] table, Scope parent_scope) -> void
182
175
  end
183
176
 
@@ -3,6 +3,10 @@ class Rigor::Plugin::IoBoundary
3
3
  def read_file: (untyped) -> String
4
4
  def file?: (untyped) -> bool
5
5
  def directory?: (untyped) -> bool
6
+ def list_directory: (untyped) -> Array[String]
7
+ # sig-gen gap: #959 — the generator pins the empty-summary literal (`count: 0, first_path: nil`); the
8
+ # record's fields are the running count and the first refused path, nil when nothing was refused.
9
+ def refusal_summary: () -> { count: Integer, first_path: String?, nearest_root: String? }?
6
10
  def open_url: (untyped url) -> String
7
11
  # Returns a frozen `Rigor::Cache::Descriptor` (no RBS yet -> untyped).
8
12
  def cache_descriptor: () -> untyped
@@ -3,7 +3,7 @@ class Rigor::Plugin::Manifest::Consumption
3
3
  end
4
4
 
5
5
  class Rigor::Plugin::Manifest
6
- def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: untyped, ?source_rbs_synthesizer: untyped, ?additional_initializers: untyped) -> void
6
+ def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?target_gems: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: untyped, ?source_rbs_synthesizer: untyped, ?additional_initializers: untyped) -> void
7
7
 
8
8
  # Public attribute readers (the full `attr_reader` surface). Plugins
9
9
  # read `manifest.id` / `manifest.protocol_contracts` etc.; declaring
@@ -16,6 +16,7 @@ class Rigor::Plugin::Manifest
16
16
  def description: () -> String?
17
17
  def config_schema: () -> untyped
18
18
  def config_defaults: () -> Hash[String, untyped]
19
+ def target_gems: () -> Array[String]
19
20
  def produces: () -> untyped
20
21
  def consumes: () -> untyped
21
22
  def owns_receivers: () -> untyped
@@ -3,11 +3,13 @@ module Rigor
3
3
  def self?.class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
4
4
  def self?.rbs_class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
5
5
  def self?.project_declared_class?: (String | Symbol class_name, ?scope: Scope?, ?environment: Environment?) -> bool
6
- def self?.class_ordering: (String | Symbol lhs, String | Symbol rhs, ?scope: Scope) -> Symbol
6
+ def self?.class_ordering: (String | Symbol lhs, String | Symbol rhs, ?scope: Scope) -> (:disjoint | :equal | :subclass | :superclass | :unknown)
7
7
  def self?.nominal_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Nominal?
8
8
  def self?.singleton_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Singleton?
9
9
  def self?.constant_type_for: (String | Symbol constant_name, ?scope: Scope) -> Type::t?
10
10
  def self?.resolve_constant_type: (String | Symbol name, ?scope: Scope, ?rooted: bool) -> Type::t?
11
+ # sig-gen gap: #656 — sig-gen skips the method (untyped return), so the resolved-name-or-decline is hand-written.
12
+ def self?.resolve_constant_path_name: (String | Symbol name, Scope scope) { (String candidate) -> boolish } -> String?
11
13
  def self?.lexical_nesting_chain: (Scope scope) -> Array[String]
12
14
  def self?.instance_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
13
15
  def self?.singleton_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
data/sig/rigor/scope.rbs CHANGED
@@ -39,12 +39,17 @@ module Rigor
39
39
  def discovered_method_visibilities: () -> Hash[String, Hash[Symbol, Symbol]]
40
40
  def discovered_superclasses: () -> Hash[String, String]
41
41
  def discovered_includes: () -> Hash[String, Array[String]]
42
+ # sig-gen gap: #898 — sig-gen skips the endless-def reader (untyped return), so the table shape is hand-written.
43
+ def discovered_extends: () -> Hash[String, Array[String]]
42
44
  def discovered_class_sources: () -> Hash[String, Set[String]]
43
45
  def constant_sources: () -> Hash[String, Set[String]]
44
46
  def published_constant_names: () -> Set[String]
45
47
  def local_constant_names: () -> Set[String]
48
+ # sig-gen gap: #667 — sig-gen types the `||` fallback `untyped`, so the element type is hand-written.
49
+ def published_constant_ivars_for: (String class_name) -> Set[Symbol]
46
50
  def published_constant?: (String name) -> bool
47
51
  def record_constant_dependency: (String name) -> void
52
+ def record_class_existence: (String class_name) -> void
48
53
  def data_member_layouts: () -> Hash[String, Array[Symbol]]
49
54
  def struct_member_layouts: () -> Hash[String, { members: Array[Symbol], keyword_init: bool }]
50
55
  def param_inferred_types: () -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
@@ -73,10 +78,16 @@ module Rigor
73
78
  attr_reader discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]]
74
79
  attr_reader discovered_superclasses: Hash[String, String]
75
80
  attr_reader discovered_includes: Hash[String, Array[String]]
81
+ # sig-gen gap: #898 — `Data.define` members carry no type, as for every other row in this class.
82
+ attr_reader discovered_extends: Hash[String, Array[String]]
76
83
  attr_reader discovered_class_sources: Hash[String, Set[String]]
77
84
  attr_reader constant_sources: Hash[String, Set[String]]
78
85
  attr_reader published_constant_names: Set[String]
79
86
  attr_reader local_constant_names: Set[String]
87
+ # sig-gen gap: #667 — `Data.define` members carry no type, so every row in this class is authored.
88
+ attr_reader published_constant_alias_names: Set[String]
89
+ # sig-gen gap: #667 — as above.
90
+ attr_reader published_constant_ivars: Hash[String, Set[Symbol]]
80
91
  attr_reader data_member_layouts: Hash[String, Array[Symbol]]
81
92
  attr_reader struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }]
82
93
  attr_reader param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
@@ -84,7 +95,7 @@ module Rigor
84
95
 
85
96
  EMPTY: DiscoveryIndex
86
97
 
87
- def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?run_generation: Object?) -> DiscoveryIndex
98
+ def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?run_generation: Object?) -> DiscoveryIndex
88
99
  end
89
100
 
90
101
  class IndexedKey
@@ -125,6 +136,12 @@ module Rigor
125
136
  def with_ivar_origin: (String | Symbol name, Symbol? cause) -> Scope
126
137
  def with_cvar: (String | Symbol name, Type::t type) -> Scope
127
138
  def with_global: (String | Symbol name, Type::t type) -> Scope
139
+ # sig-gen gap: #667 — an `attr_reader` over a frozen Set literal types `untyped`, as the sibling
140
+ # `declaration_sourced` row does.
141
+ def published_constant_sourced: () -> Set[[Symbol, Symbol]]
142
+ # sig-gen gap: #667 — `Set#include?` over a tuple key types `untyped`, so the `bool` is hand-written.
143
+ def published_constant_sourced?: (Symbol kind, String | Symbol name) -> bool
144
+ def with_published_constant_mark: (Symbol kind, String | Symbol name) -> Scope
128
145
  def declaration_sourced: () -> Set[[Symbol, Symbol]]
129
146
  def seed_declaration_sourced_ivar: (String | Symbol name, Type::t type) -> Scope
130
147
  def with_declaration_sourced_local: (String | Symbol name, Type::t type) -> Scope
@@ -138,15 +155,16 @@ module Rigor
138
155
  def class_cvars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
139
156
  def discovered_method?: (String | Symbol class_name, String | Symbol method_name, Symbol kind) -> bool
140
157
  def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
141
- def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> [untyped?, String?]
158
+ def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([untyped, String] | [nil, nil])
142
159
  def discovered_method_through_ancestors?: (String | Symbol? class_name, String | Symbol method_name, Symbol kind, ?name_memo: Hash[untyped, untyped]) -> bool
160
+ def external_ancestor_name_candidates: (String | Symbol class_name, ?name_memo: Hash[untyped, untyped]) -> Array[Array[String]]
143
161
  def enqueue_ancestors: (String current, Array[String] queue, Hash[untyped, untyped] name_memo, ?mixins: bool) -> void
144
162
  def ancestor_name_candidates: (String | Symbol subclass_qualified, String | Symbol raw_ancestor) -> Array[String]
145
163
 
146
164
  # Issue #530 — public so the external-gem ancestry probe asks the same question the walk does.
147
165
  def known_user_class?: (String | Symbol name) -> bool
148
166
  def singleton_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
149
- def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> [untyped?, String?]
167
+ def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([untyped, String] | [nil, nil])
150
168
  def user_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
151
169
  def user_singleton_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
152
170
  def top_level_def_for: (String | Symbol method_name) -> untyped?
@@ -157,6 +175,9 @@ module Rigor
157
175
  def data_member_layout: (String | Symbol class_name) -> Array[Symbol]?
158
176
  def struct_member_layout: (String | Symbol class_name) -> { members: Array[Symbol], keyword_init: bool }?
159
177
  def includes_of: (String | Symbol class_name) -> Array[String]
178
+ # sig-gen gap: #898 — sig-gen proposes `Array[untyped] | []` off the empty-table early return, so the
179
+ # element type is hand-written, matching {#includes_of}.
180
+ def singleton_extends_of: (String | Symbol class_name) -> Array[String]
160
181
  def indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Type::t?
161
182
  def with_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key, Type::t type) -> Scope
162
183
  def without_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Scope
@@ -0,0 +1,14 @@
1
+ class Rigor::SigGen::SkipReasonCatalog::Entry < ::Data
2
+ def id: () -> untyped
3
+ def summary: () -> untyped
4
+ def explanation: () -> untyped
5
+ def next_step: () -> untyped
6
+ def self.new: (id: untyped, summary: untyped, explanation: untyped, next_step: untyped) -> instance | (untyped id, untyped summary, untyped explanation, untyped next_step) -> instance
7
+ def self.[]: (id: untyped, summary: untyped, explanation: untyped, next_step: untyped) -> instance | (untyped id, untyped summary, untyped explanation, untyped next_step) -> instance
8
+ def to_h: () -> Hash[String, untyped]
9
+ end
10
+
11
+ module Rigor::SigGen::SkipReasonCatalog
12
+ def self?.resolve: (untyped) -> Rigor::SigGen::SkipReasonCatalog::Entry?
13
+ def self?.all: () -> Array[Rigor::SigGen::SkipReasonCatalog::Entry]
14
+ end
data/sig/rigor/type.rbs CHANGED
@@ -1,6 +1,6 @@
1
1
  module Rigor
2
2
  module Type
3
- type t = Top | Bot | Dynamic | Constant | IntegerRange | Nominal | Singleton | Union | Difference | Refined | Intersection | Tuple | HashShape | DataClass | DataInstance | StructClass | StructInstance | BoundMethod | Result | Maybe | App
3
+ type t = Top | Bot | Dynamic | Constant | IntegerRange | FloatRange | Nominal | Singleton | Union | Difference | Refined | Intersection | Tuple | HashShape | DataClass | DataInstance | StructClass | StructInstance | BoundMethod | Result | Maybe | App
4
4
 
5
5
  type accepts_mode = :strict | :gradual | :loose
6
6
 
@@ -115,7 +115,30 @@ module Rigor
115
115
  def inspect: () -> String
116
116
  end
117
117
 
118
+ class FloatRange
119
+ ALIAS_NAMES: Hash[[Float, Float], String]
120
+ attr_reader min: Float
121
+ attr_reader max: Float
122
+ def initialize: (Float min, Float max, ?exclude_end: bool) -> void
123
+ def exclude_end?: () -> bool
124
+ def canonical_max: () -> Float
125
+ def universal?: () -> bool
126
+ def covers?: (untyped value) -> bool
127
+ def describe: (?Symbol verbosity) -> String
128
+ def generic_description: () -> String
129
+ def erase_to_rbs: () -> "Float"
130
+ def top: () -> Trinary
131
+ def bot: () -> Trinary
132
+ def dynamic: () -> Trinary
133
+ def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
134
+ def ==: (untyped other) -> bool
135
+ def eql?: (untyped other) -> bool
136
+ def hash: () -> Integer
137
+ def inspect: () -> String
138
+ end
139
+
118
140
  class Nominal
141
+ EMPTY_TYPE_ARGS: Array[Type::t]
119
142
  attr_reader class_name: String
120
143
  attr_reader type_args: Array[Type::t]
121
144
  def initialize: (String class_name, ?Array[Type::t] type_args) -> void
@@ -460,6 +483,9 @@ module Rigor
460
483
  def self?.negative_int: () -> IntegerRange
461
484
  def self?.non_positive_int: () -> IntegerRange
462
485
  def self?.universal_int: () -> IntegerRange
486
+ def self?.float_range: (Float min, Float max, ?exclude_end: bool) -> FloatRange
487
+ def self?.non_nan_float: () -> FloatRange
488
+ def self?.finite_float: () -> FloatRange
463
489
  def self?.tuple_of: (*Type::t elements) -> Tuple
464
490
  def self?.hash_shape_of: (?Hash[untyped, Type::t]? pairs, **untyped options) -> HashShape
465
491
  def self?.data_class_of: (members: Array[Symbol], ?class_name: String?) -> DataClass
data/sig/rigor.rbs CHANGED
@@ -24,6 +24,7 @@ module Rigor
24
24
 
25
25
  class CLI
26
26
  EXIT_USAGE: Integer
27
+ EXIT_INTERNAL_ERROR: Integer
27
28
 
28
29
  def self.start: (?Array[String] argv, ?out: untyped, ?err: untyped) -> Integer
29
30
 
@@ -30,11 +30,12 @@ Two things make that easy, and you have both offline:
30
30
  `type-of` / `triage` / `coverage` answer from what Rigor inferred. A
31
31
  concrete inferred type beats any abstract explanation.
32
32
 
33
- This is the user's shortcut: they only ever need to remember two skills —
34
- **`rigor-next-steps`** ("what should we do next?") and **`rigor-ask`**
35
- ("answer this about Rigor"). They ask in plain language; *you* turn it
36
- into the right lookup or analysis so they never have to remember the
37
- command.
33
+ This is the user's shortcut: they only ever need to remember three
34
+ skills — **`rigor-next-steps`** ("what should we do next?"),
35
+ **`rigor-ask`** ("answer this about Rigor"), and **`rigor-type-oracle`**
36
+ ("before you write a type, ask Rigor"). They ask in plain language; *you*
37
+ turn it into the right lookup or analysis so they never have to remember
38
+ the command.
38
39
 
39
40
  ## Prefer the live map over this skill's tables
40
41
 
@@ -125,8 +126,9 @@ A good hand-off is two or three sentences of orientation plus the pointer:
125
126
  - CI → **`rigor-ci-setup`** · editor → **`rigor-editor-setup`** · MCP agent → **`rigor-mcp-setup`**
126
127
  - baseline reduction → **`rigor-baseline-reduce`** · coverage holes → **`rigor-protection-uplift`**
127
128
  - a missing gem/DSL → **`rigor-plugin-author`** · monkey-patch clusters → **`rigor-monkeypatch-resolve`**
129
+ - about to *write* a type (RBS, `#:`, a Sorbet `sig`, a YARD tag, a doc sentence) → **`rigor-type-oracle`**
128
130
 
129
- When in doubt, give less and point — it respects the user's "two skills
131
+ When in doubt, give less and point — it respects the user's "three skills
130
132
  to remember" promise and keeps each answer to the part only `rigor-ask`
131
133
  can give.
132
134
 
@@ -152,8 +152,9 @@ For your own target library, follow the same harness: a **fixed
152
152
  allow-list** of pure methods, inputs derived from source, and **decline
153
153
  (return nil / emit nothing) when the library is unavailable — never
154
154
  approximate**. How the call is isolated from Rigor (in-process, a forked
155
- worker, or a `Ruby::Box`) is a configurable strategy the user picks
156
- (`plugins_isolation:`); you just call the method.
155
+ worker, or a `Ruby::Box`) is a configurable strategy the user picks with
156
+ `.rigor.yml`'s `plugins_isolation:` key or the `RIGOR_PLUGIN_ISOLATION`
157
+ environment variable (which wins over it); you just call the method.
157
158
 
158
159
  For the common "did you mean …?" suggestion, use the shared helper
159
160
  rather than hand-rolling Levenshtein:
@@ -194,6 +195,16 @@ dynamic_return receivers: ["Money"] do |call_node, scope|
194
195
  Rigor::Type::Combinator.nominal_of("Money")
195
196
  end
196
197
 
198
+ # A `receivers:` entry names the receiver KIND too. `"Money"` matches an
199
+ # INSTANCE receiver; the class object itself is `"singleton(Money)"`,
200
+ # spelled as RBS spells it; a rule for both lists both. Write the kind
201
+ # the rule actually models: a plugin answer suppresses that call site's
202
+ # `call.undefined-method`, so an instance rule that also answered on the
203
+ # class would silence a genuine miss on the class-level call.
204
+ dynamic_return receivers: ["singleton(Money)"], methods: [:from_cents] do |call_node, scope|
205
+ Rigor::Type::Combinator.nominal_of("Money")
206
+ end
207
+
197
208
  # Post-return NARROWING FACTS, gated on the call's method name.
198
209
  # Return an Array of facts (or nil). Used for assertion / predicate
199
210
  # narrowing (`assert_kind_of(Foo, x)` ⇒ x is Foo afterwards).
@@ -135,6 +135,7 @@ mode — those points resolve without blocking:
135
135
  | 6a | **Pre-baseline cleanup** — apply quick fixes that triage diagnosed (`pre_eval:` for monkey-patch hints, `rbs collection install` if still needed). Re-run triage; repeat until the count is stable. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) § "Phase 6a" |
136
136
  | 7 | Acknowledge mode only — generate the baseline and wire `baseline:`. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) |
137
137
  | 8 | Surface likely real bugs; distinguish sig quality FPs from real bugs; offer escalation paths. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) |
138
+ | 8a | Install the agent type-contract into `AGENTS.md` / `CLAUDE.md`, so an AI contributor sources types from Rigor instead of guessing them. | [`references/06-agent-contract.md`](references/06-agent-contract.md) |
138
139
  | 9 | Confirm the generated files with the user — what each is, and whether to commit it. | (this file — § "Final step") |
139
140
 
140
141
  Load each reference when you reach its phase. Phases run in order;
@@ -150,6 +151,7 @@ committed `sig/` directory.
150
151
  | 2 | [`references/02-configure.md`](references/02-configure.md) | **Phase 4.** Severity-profile choice tied to the mode. The `.rigor.dist.yml` template and every key it uses. The `.rigor.dist.yml` vs `.rigor.yml` convention. |
151
152
  | 3 | [`references/04-sig-uplift.md`](references/04-sig-uplift.md) | **Phase 5.** `rigor sig-gen --write` baseline. `rigor sig-gen --params=observed --write` attr_reader precision uplift. Handling residual `untyped` methods. Committing `sig/`. |
152
153
  | 4 | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) | **Phases 6–8.** `rigor triage` as the diagnosis layer. Phase 6a pre-baseline cleanup loop (`pre_eval:` for monkey-patch hints, `rbs collection install`). `rigor baseline generate` + wiring `baseline:`. Surfacing likely real bugs; sig quality FP recognition (Struct `call.wrong-arity`, `-> bot` return-type-mismatch, regex-capture `$1` FPs). The two escalation paths — write a project plugin, or open a Rigor issue. |
154
+ | 5 | [`references/06-agent-contract.md`](references/06-agent-contract.md) | **Phase 8a.** The one paragraph the project's `AGENTS.md` / `CLAUDE.md` keeps so every agent session sources types from Rigor rather than guessing them. Where to append it, when to create the file, and what never to overwrite. |
153
155
  | — (optional) | [`references/05-jit-performance.md`](references/05-jit-performance.md) | **Operational, not a phase.** Run speed via a Ruby JIT: Rigor auto-enables YJIT for long runs (~5 s break-even), how to detect JIT support in your install, the override env vars, and why YJIT beats ZJIT for Rigor on Ruby 4.0. Read only when a large project's `rigor check` wall time matters. |
154
156
 
155
157
  ## Escalation paths (Phase 7 preview)
@@ -227,10 +229,11 @@ only in acknowledge mode). For each, give the commit recommendation:
227
229
  | `.rigor/` (contains `cache/`) | The per-file analysis cache `rigor check` writes to speed up re-runs. Regenerable and machine-local. | **No** — add `.rigor/` to `.gitignore`. |
228
230
  | `.rigor.yml` | Optional per-developer local override (not written by this skill). Takes precedence over `.rigor.dist.yml`; used to opt out locally (e.g. run without the baseline). | **No** — gitignore it if a developer creates one. |
229
231
  | `rbs_collection.lock.yaml` | Not a Rigor artefact — but if Phase 1 ran `rbs collection install`, the install may have regenerated this pre-existing project file (e.g. the stdlib gem list for the resolved Ruby). | **Yes**, but flag it separately: it is a change to an existing project file, not part of the Rigor file set. |
232
+ | `AGENTS.md` / `CLAUDE.md` | The agent type-contract section added in Phase 8a — "a type you did not obtain from Rigor is a guess". Created only if neither file existed; otherwise this is an appended section in a pre-existing file. | **Yes** — commit it; the point is that every contributor's agent reads the same rule. Flag an appended section separately, as with `rbs_collection.lock.yaml`. |
230
233
 
231
234
  Recommend the two concrete actions and **ask before doing them**
232
235
  (both touch the user's repo): (1) add `.rigor/` — and `.rigor.yml`
233
236
  if present — to `.gitignore`; (2) commit `.rigor.dist.yml`,
234
- `.rigor-baseline.yml`, and `sig/` as the shared Rigor setup. Per the
235
- git-safety default, do not commit on the user's behalf until they
236
- confirm.
237
+ `.rigor-baseline.yml`, `sig/`, and the Phase 8a `AGENTS.md` /
238
+ `CLAUDE.md` section as the shared Rigor setup. Per the git-safety
239
+ default, do not commit on the user's behalf until they confirm.
@@ -114,10 +114,11 @@ severity_profile: lenient
114
114
 
115
115
  ### Existing `sig/` directory
116
116
 
117
- If the project already has a `sig/` directory (from Steep, `rbs_rails`,
118
- or handwritten annotations), wire it into `signature_paths:` so Rigor
119
- consumes it. Phase 5 (sig uplift) can be skipped, but the paths must
120
- still be declaredRigor does not auto-detect `sig/`:
117
+ A plain `<project root>/sig` directory needs no wiring: with
118
+ `signature_paths:` unset, Rigor auto-detects it and loads it recursively.
119
+ Phase 5 (sig uplift) can be skipped. Declare `signature_paths:` when the
120
+ layout is something else several trees, or a `sig/` that is not at the
121
+ project root:
121
122
 
122
123
  ```yaml
123
124
  signature_paths:
@@ -125,9 +126,12 @@ signature_paths:
125
126
  - sig/generated
126
127
  ```
127
128
 
129
+ Declaring the key REPLACES the auto-detected `sig`, so list it too if you
130
+ want it. `signature_paths: []` is the way to opt out of project RBS
131
+ entirely — including a `sig/` that `rigor sig-gen --write` created.
132
+
128
133
  List only directories that contain `.rbs` files or subdirectories of
129
- them. Rigor walks each path recursively. If the sig layout is a single
130
- flat `sig/` directory, use `- sig` instead.
134
+ them. Rigor walks each path recursively.
131
135
 
132
136
  A strict-mode plain-Ruby gem is shorter:
133
137
 
@@ -0,0 +1,67 @@
1
+ # 06 — Install the agent type-contract into AGENTS.md / CLAUDE.md
2
+
3
+ Covers **Phase 8a**. Input: an onboarded project (config written, sigs
4
+ generated, baseline decided). Output: one section in the file the
5
+ project's coding agents read at startup.
6
+
7
+ ## Why this is part of onboarding
8
+
9
+ Everything the earlier phases produced — `sig/`, the baseline, the
10
+ severity profile — is a record of what Rigor *proved*. The moment an AI
11
+ agent starts contributing to the project, it can write types that Rigor
12
+ never proved: a `@param currency [String]` in a doc comment, an
13
+ rbs-inline `#:` that Rigor then ingests as a live contract. Those enter
14
+ the same files, look identical to derived types, and are believed.
15
+
16
+ The fix is not a tool. It is one paragraph in the project's agent
17
+ contract, so the rule is in context every session rather than only when
18
+ a skill happens to trigger: **a type not obtained from Rigor is a guess,
19
+ and a guessed type is never written.**
20
+
21
+ ## The text
22
+
23
+ The canonical fragment is served by the installed Rigor, so it stays
24
+ current with the CLI it names:
25
+
26
+ ```sh
27
+ rigor skill --full rigor-type-oracle
28
+ ```
29
+
30
+ Its `references/02-agents-md-fragment.md` section carries the paragraph
31
+ and the five bullets. Copy that block **verbatim** — including its
32
+ single-long-line shape, which is deliberate (some renderers turn a
33
+ newline inside a paragraph into a line break).
34
+
35
+ Do not paraphrase it from memory, and do not shorten it: the five bullets
36
+ are the load-bearing part — expression, method signature, parameter,
37
+ the gap rule, and provenance.
38
+
39
+ ## Where it goes
40
+
41
+ | Project state | What to do |
42
+ | --- | --- |
43
+ | `AGENTS.md` exists | **Append** the section at the end. Do not reorganise the file. |
44
+ | Only `CLAUDE.md` exists | Append it there. |
45
+ | Both exist | Put it in `AGENTS.md`. Add `@AGENTS.md` to `CLAUDE.md` only if it is not already pulled in. |
46
+ | Neither exists | **Create `AGENTS.md`** with this as its first section. |
47
+ | A types / type-checking section already exists | Merge into it; keep the five bullets intact. Never write a second, competing rule. |
48
+
49
+ Never overwrite unrelated content. If the project already states a rule
50
+ about type authorship that contradicts this one, stop and show the user
51
+ the conflict — the project's own rule wins until they say otherwise.
52
+
53
+ ## Report it in the final step
54
+
55
+ This is a change to the file that governs every future agent session in
56
+ the repo, so it belongs in Phase 9's file inventory, not in a silent
57
+ diff. Recommend committing it: the point is that every contributor's
58
+ agent reads the same rule.
59
+
60
+ ## When to skip
61
+
62
+ - The project has no coding-agent contract file **and** the user has said
63
+ they do not use AI agents on it. Offer once, accept "no".
64
+ - The user declined it earlier in this session.
65
+
66
+ Otherwise install it — an unonboarded agent is the one contributor that
67
+ cannot be trained by review.