rigortype 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/docs/manual/04-diagnostics.md +7 -4
  4. data/docs/manual/06-baseline.md +5 -2
  5. data/docs/manual/15-type-protection-coverage.md +6 -4
  6. data/lib/rigor/analysis/baseline.rb +56 -96
  7. data/lib/rigor/analysis/buffer_binding.rb +13 -20
  8. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
  9. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
  10. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
  11. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
  12. data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
  13. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
  14. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
  15. data/lib/rigor/analysis/check_rules.rb +174 -274
  16. data/lib/rigor/analysis/dependency_recorder.rb +26 -38
  17. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
  18. data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
  19. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
  20. data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
  21. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
  22. data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
  23. data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
  24. data/lib/rigor/analysis/diagnostic.rb +48 -75
  25. data/lib/rigor/analysis/erb_template_detector.rb +13 -18
  26. data/lib/rigor/analysis/fact_store.rb +12 -22
  27. data/lib/rigor/analysis/incremental.rb +47 -63
  28. data/lib/rigor/analysis/incremental_session.rb +74 -100
  29. data/lib/rigor/analysis/project_scan.rb +12 -23
  30. data/lib/rigor/analysis/result.rb +3 -5
  31. data/lib/rigor/analysis/rule_catalog.rb +67 -95
  32. data/lib/rigor/analysis/run_stats.rb +38 -61
  33. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
  34. data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
  35. data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
  36. data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
  37. data/lib/rigor/analysis/runner.rb +220 -333
  38. data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
  39. data/lib/rigor/analysis/worker_session.rb +64 -102
  40. data/lib/rigor/ast/type_node.rb +6 -8
  41. data/lib/rigor/ast.rb +6 -10
  42. data/lib/rigor/bleeding_edge.rb +27 -35
  43. data/lib/rigor/builtins/hkt_builtins.rb +7 -14
  44. data/lib/rigor/builtins/imported_refinements.rb +106 -149
  45. data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
  46. data/lib/rigor/builtins/regex_refinement.rb +32 -43
  47. data/lib/rigor/builtins/static_return_refinements.rb +57 -81
  48. data/lib/rigor/cache/descriptor.rb +58 -94
  49. data/lib/rigor/cache/incremental_snapshot.rb +32 -48
  50. data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
  51. data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
  52. data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
  53. data/lib/rigor/cache/rbs_constant_table.rb +8 -13
  54. data/lib/rigor/cache/rbs_descriptor.rb +8 -13
  55. data/lib/rigor/cache/rbs_environment.rb +11 -19
  56. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
  57. data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
  58. data/lib/rigor/cache/store.rb +96 -151
  59. data/lib/rigor/cli/annotate_command.rb +51 -88
  60. data/lib/rigor/cli/baseline_command.rb +10 -17
  61. data/lib/rigor/cli/check_command.rb +121 -199
  62. data/lib/rigor/cli/check_runner_factory.rb +8 -14
  63. data/lib/rigor/cli/ci_detector.rb +9 -14
  64. data/lib/rigor/cli/command.rb +8 -14
  65. data/lib/rigor/cli/coverage_command.rb +19 -26
  66. data/lib/rigor/cli/coverage_mutation.rb +14 -19
  67. data/lib/rigor/cli/coverage_report.rb +0 -2
  68. data/lib/rigor/cli/coverage_scan.rb +7 -11
  69. data/lib/rigor/cli/diagnostic_formats.rb +43 -62
  70. data/lib/rigor/cli/diff_command.rb +10 -20
  71. data/lib/rigor/cli/docs_command.rb +26 -40
  72. data/lib/rigor/cli/doctor_command.rb +8 -9
  73. data/lib/rigor/cli/explain_command.rb +4 -7
  74. data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
  75. data/lib/rigor/cli/fused_protection_report.rb +6 -8
  76. data/lib/rigor/cli/lsp_command.rb +11 -19
  77. data/lib/rigor/cli/mcp_command.rb +4 -6
  78. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
  79. data/lib/rigor/cli/mutation_protection_report.rb +6 -9
  80. data/lib/rigor/cli/options.rb +11 -19
  81. data/lib/rigor/cli/plugin_command.rb +18 -30
  82. data/lib/rigor/cli/plugins_command.rb +29 -51
  83. data/lib/rigor/cli/plugins_renderer.rb +12 -20
  84. data/lib/rigor/cli/prism_colorizer.rb +13 -19
  85. data/lib/rigor/cli/protection_renderer.rb +5 -7
  86. data/lib/rigor/cli/protection_report.rb +27 -17
  87. data/lib/rigor/cli/renderable.rb +4 -6
  88. data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
  89. data/lib/rigor/cli/sig_gen_command.rb +14 -26
  90. data/lib/rigor/cli/skill_command.rb +30 -47
  91. data/lib/rigor/cli/skill_describe.rb +40 -64
  92. data/lib/rigor/cli/trace_command.rb +9 -16
  93. data/lib/rigor/cli/trace_renderer.rb +35 -51
  94. data/lib/rigor/cli/triage_command.rb +6 -10
  95. data/lib/rigor/cli/triage_renderer.rb +1 -2
  96. data/lib/rigor/cli/type_of_command.rb +14 -23
  97. data/lib/rigor/cli/type_of_renderer.rb +3 -5
  98. data/lib/rigor/cli/type_scan_command.rb +6 -10
  99. data/lib/rigor/cli/type_scan_renderer.rb +3 -5
  100. data/lib/rigor/cli/type_scan_report.rb +2 -3
  101. data/lib/rigor/cli/upgrade_command.rb +2 -3
  102. data/lib/rigor/cli.rb +16 -28
  103. data/lib/rigor/config_audit.rb +35 -44
  104. data/lib/rigor/configuration/dependencies.rb +41 -70
  105. data/lib/rigor/configuration/severity_profile.rb +28 -42
  106. data/lib/rigor/configuration.rb +150 -241
  107. data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
  108. data/lib/rigor/environment/class_registry.rb +19 -26
  109. data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
  110. data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
  111. data/lib/rigor/environment/lockfile_resolver.rb +31 -47
  112. data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
  113. data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
  114. data/lib/rigor/environment/rbs_loader.rb +420 -518
  115. data/lib/rigor/environment/reflection.rb +28 -53
  116. data/lib/rigor/environment/reporters.rb +13 -24
  117. data/lib/rigor/environment.rb +176 -291
  118. data/lib/rigor/flow_contribution/conflict.rb +16 -27
  119. data/lib/rigor/flow_contribution/element.rb +7 -12
  120. data/lib/rigor/flow_contribution/fact.rb +33 -57
  121. data/lib/rigor/flow_contribution/merge_result.rb +6 -9
  122. data/lib/rigor/flow_contribution/merger.rb +32 -47
  123. data/lib/rigor/flow_contribution.rb +37 -55
  124. data/lib/rigor/inference/acceptance.rb +133 -219
  125. data/lib/rigor/inference/block_parameter_binder.rb +52 -82
  126. data/lib/rigor/inference/body_fixpoint.rb +22 -30
  127. data/lib/rigor/inference/budget_trace.rb +43 -63
  128. data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
  129. data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
  130. data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
  131. data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
  132. data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
  133. data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
  134. data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
  135. data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
  136. data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
  137. data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
  138. data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
  139. data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
  140. data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
  141. data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
  142. data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
  143. data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
  144. data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
  145. data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
  146. data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
  147. data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
  148. data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
  149. data/lib/rigor/inference/coverage_scanner.rb +13 -18
  150. data/lib/rigor/inference/def_return_typer.rb +8 -14
  151. data/lib/rigor/inference/dynamic_origin.rb +23 -20
  152. data/lib/rigor/inference/expression_typer.rb +774 -1152
  153. data/lib/rigor/inference/fallback.rb +8 -12
  154. data/lib/rigor/inference/fallback_tracer.rb +4 -10
  155. data/lib/rigor/inference/flow_tracer.rb +25 -36
  156. data/lib/rigor/inference/hkt_body.rb +45 -68
  157. data/lib/rigor/inference/hkt_body_parser.rb +33 -52
  158. data/lib/rigor/inference/hkt_reducer.rb +38 -59
  159. data/lib/rigor/inference/hkt_registry.rb +50 -76
  160. data/lib/rigor/inference/indexed_narrowing.rb +55 -81
  161. data/lib/rigor/inference/macro_block_self_type.rb +21 -34
  162. data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
  163. data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
  164. data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
  165. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
  166. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
  167. data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
  168. data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
  169. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
  170. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
  171. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
  172. data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
  173. data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
  174. data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
  175. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
  176. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
  177. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
  178. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
  179. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
  180. data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
  181. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
  182. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
  183. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
  184. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
  185. data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
  186. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
  187. data/lib/rigor/inference/method_dispatcher.rb +378 -524
  188. data/lib/rigor/inference/method_parameter_binder.rb +81 -114
  189. data/lib/rigor/inference/multi_target_binder.rb +51 -68
  190. data/lib/rigor/inference/mutation_widening.rb +115 -158
  191. data/lib/rigor/inference/narrowing.rb +509 -727
  192. data/lib/rigor/inference/origin_lookup.rb +38 -0
  193. data/lib/rigor/inference/parameter_inference_collector.rb +100 -100
  194. data/lib/rigor/inference/precision_scanner.rb +26 -35
  195. data/lib/rigor/inference/project_patched_methods.rb +20 -32
  196. data/lib/rigor/inference/project_patched_scanner.rb +23 -37
  197. data/lib/rigor/inference/protection_scanner.rb +16 -18
  198. data/lib/rigor/inference/rbs_type_translator.rb +49 -66
  199. data/lib/rigor/inference/scope_indexer.rb +473 -817
  200. data/lib/rigor/inference/statement_evaluator.rb +706 -1111
  201. data/lib/rigor/inference/struct_fold_safety.rb +34 -48
  202. data/lib/rigor/inference/synthetic_method.rb +9 -16
  203. data/lib/rigor/inference/synthetic_method_index.rb +20 -35
  204. data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
  205. data/lib/rigor/language_server/buffer_resolution.rb +6 -9
  206. data/lib/rigor/language_server/buffer_table.rb +11 -18
  207. data/lib/rigor/language_server/completion_provider.rb +69 -116
  208. data/lib/rigor/language_server/debouncer.rb +16 -25
  209. data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
  210. data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
  211. data/lib/rigor/language_server/folding_range_provider.rb +11 -19
  212. data/lib/rigor/language_server/hover_provider.rb +8 -11
  213. data/lib/rigor/language_server/hover_renderer.rb +56 -93
  214. data/lib/rigor/language_server/loop.rb +14 -19
  215. data/lib/rigor/language_server/project_context.rb +46 -74
  216. data/lib/rigor/language_server/selection_range_provider.rb +9 -12
  217. data/lib/rigor/language_server/server.rb +55 -83
  218. data/lib/rigor/language_server/signature_help_provider.rb +29 -46
  219. data/lib/rigor/language_server/synchronized_writer.rb +4 -7
  220. data/lib/rigor/language_server/uri.rb +8 -13
  221. data/lib/rigor/language_server.rb +4 -6
  222. data/lib/rigor/mcp/loop.rb +2 -3
  223. data/lib/rigor/mcp/server.rb +4 -7
  224. data/lib/rigor/mcp.rb +3 -6
  225. data/lib/rigor/plugin/access_denied_error.rb +5 -8
  226. data/lib/rigor/plugin/additional_initializer.rb +21 -31
  227. data/lib/rigor/plugin/base.rb +335 -518
  228. data/lib/rigor/plugin/blueprint.rb +14 -23
  229. data/lib/rigor/plugin/box.rb +18 -29
  230. data/lib/rigor/plugin/fact_store.rb +16 -26
  231. data/lib/rigor/plugin/inflector.rb +37 -53
  232. data/lib/rigor/plugin/io_boundary.rb +33 -56
  233. data/lib/rigor/plugin/isolation.rb +42 -55
  234. data/lib/rigor/plugin/load_error.rb +10 -15
  235. data/lib/rigor/plugin/loader.rb +30 -49
  236. data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
  237. data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
  238. data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
  239. data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
  240. data/lib/rigor/plugin/macro.rb +10 -15
  241. data/lib/rigor/plugin/manifest.rb +85 -144
  242. data/lib/rigor/plugin/node_context.rb +14 -22
  243. data/lib/rigor/plugin/node_rule_walk.rb +49 -74
  244. data/lib/rigor/plugin/protocol_contract.rb +25 -39
  245. data/lib/rigor/plugin/registry.rb +132 -205
  246. data/lib/rigor/plugin/services.rb +21 -33
  247. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
  248. data/lib/rigor/plugin/trust_policy.rb +24 -38
  249. data/lib/rigor/plugin/type_node_resolver.rb +15 -24
  250. data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
  251. data/lib/rigor/protection/mutation_scanner.rb +27 -35
  252. data/lib/rigor/protection/mutator.rb +50 -70
  253. data/lib/rigor/protection/test_suite_oracle.rb +20 -27
  254. data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
  255. data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
  256. data/lib/rigor/rbs_extended/reporter.rb +24 -40
  257. data/lib/rigor/rbs_extended.rb +107 -197
  258. data/lib/rigor/reflection.rb +68 -86
  259. data/lib/rigor/scope/discovery_index.rb +14 -19
  260. data/lib/rigor/scope.rb +255 -310
  261. data/lib/rigor/sig_gen/classification.rb +6 -10
  262. data/lib/rigor/sig_gen/generator.rb +197 -323
  263. data/lib/rigor/sig_gen/layout_index.rb +12 -20
  264. data/lib/rigor/sig_gen/method_candidate.rb +12 -17
  265. data/lib/rigor/sig_gen/observation_collector.rb +38 -70
  266. data/lib/rigor/sig_gen/observed_call.rb +13 -23
  267. data/lib/rigor/sig_gen/path_mapper.rb +17 -29
  268. data/lib/rigor/sig_gen/renderer.rb +7 -13
  269. data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
  270. data/lib/rigor/sig_gen/write_result.rb +8 -16
  271. data/lib/rigor/sig_gen/writer.rb +95 -174
  272. data/lib/rigor/sig_gen.rb +3 -6
  273. data/lib/rigor/signature_path_audit.rb +24 -30
  274. data/lib/rigor/source/constant_path.rb +10 -14
  275. data/lib/rigor/source/literals.rb +31 -45
  276. data/lib/rigor/source/node_locator.rb +9 -11
  277. data/lib/rigor/source/node_walker.rb +9 -13
  278. data/lib/rigor/source.rb +3 -4
  279. data/lib/rigor/testing.rb +16 -20
  280. data/lib/rigor/triage/catalogue.rb +38 -62
  281. data/lib/rigor/triage.rb +31 -52
  282. data/lib/rigor/trinary.rb +9 -13
  283. data/lib/rigor/type/acceptance_router.rb +4 -6
  284. data/lib/rigor/type/accepts_result.rb +10 -14
  285. data/lib/rigor/type/app.rb +19 -27
  286. data/lib/rigor/type/bot.rb +4 -6
  287. data/lib/rigor/type/bound_method.rb +10 -15
  288. data/lib/rigor/type/combinator.rb +165 -257
  289. data/lib/rigor/type/constant.rb +23 -34
  290. data/lib/rigor/type/data_class.rb +10 -15
  291. data/lib/rigor/type/data_instance.rb +14 -20
  292. data/lib/rigor/type/difference.rb +21 -32
  293. data/lib/rigor/type/dynamic.rb +3 -5
  294. data/lib/rigor/type/hash_shape.rb +32 -18
  295. data/lib/rigor/type/integer_range.rb +11 -16
  296. data/lib/rigor/type/intersection.rb +27 -42
  297. data/lib/rigor/type/nominal.rb +10 -15
  298. data/lib/rigor/type/plain_lattice.rb +9 -13
  299. data/lib/rigor/type/refined.rb +67 -114
  300. data/lib/rigor/type/singleton.rb +4 -6
  301. data/lib/rigor/type/struct_class.rb +11 -16
  302. data/lib/rigor/type/struct_instance.rb +15 -21
  303. data/lib/rigor/type/tuple.rb +14 -19
  304. data/lib/rigor/type/union.rb +30 -42
  305. data/lib/rigor/type_node/generic.rb +14 -26
  306. data/lib/rigor/type_node/identifier.rb +12 -19
  307. data/lib/rigor/type_node.rb +3 -12
  308. data/lib/rigor/value_semantics.rb +16 -21
  309. data/lib/rigor/version.rb +1 -1
  310. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
  311. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
  312. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
  313. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
  314. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
  315. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
  316. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
  317. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
  318. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +118 -176
  319. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
  320. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
  321. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +71 -108
  322. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
  323. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
  324. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
  325. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
  326. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +30 -47
  327. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +79 -129
  328. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +36 -57
  329. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
  330. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
  331. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +148 -235
  332. data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
  333. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
  334. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
  335. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
  336. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
  337. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
  338. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
  339. data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
  340. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
  341. data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
  342. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
  343. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
  344. data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
  345. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
  346. data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
  347. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
  348. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
  349. data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
  350. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
  351. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
  352. data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
  353. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
  354. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
  355. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
  356. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
  357. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
  358. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
  359. data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
  360. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
  361. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
  362. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
  363. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
  364. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
  365. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
  366. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
  367. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
  368. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
  369. data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
  370. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
  371. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
  372. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
  373. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
  374. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
  375. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
  376. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
  377. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
  378. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +42 -74
  379. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +280 -497
  380. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +54 -89
  381. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
  382. data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
  383. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
  384. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
  385. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
  386. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
  387. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
  388. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
  389. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
  390. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
  391. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
  392. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
  393. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
  394. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
  395. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
  396. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
  397. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
  398. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
  399. data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
  400. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
  401. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
  402. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
  403. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
  404. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
  405. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
  406. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
  407. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
  408. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
  409. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
  410. data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
  411. data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
  412. data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
  413. data/sig/rigor/scope.rbs +6 -0
  414. metadata +2 -1
@@ -2,26 +2,20 @@
2
2
 
3
3
  module Rigor
4
4
  class FlowContribution
5
- # Records a contradiction between two or more flow contributions
6
- # detected during {Merger.merge}. Carried on {MergeResult#conflicts}
7
- # so the analyzer / formatter can surface a `:contribution_merge`
8
- # diagnostic per ADR-2 § "Plugin Contribution Merging".
5
+ # Records a contradiction between two or more flow contributions detected during {Merger.merge}. Carried on
6
+ # {MergeResult#conflicts} so the analyzer / formatter can surface a `:contribution_merge` diagnostic per
7
+ # ADR-2 § "Plugin Contribution Merging".
9
8
  #
10
- # ADR-2 § "Plugin Contribution Merging" rules out first-wins /
11
- # last-wins behaviour: when contributions conflict, both sources
12
- # are reported and the merger falls back to the nearest non-
13
- # conflicting higher-tier (or default) value for the affected
14
- # `(target, edge, kind)` slot. The conflict object is the
15
- # carrier of that report.
9
+ # ADR-2 § "Plugin Contribution Merging" rules out first-wins / last-wins behaviour: when contributions
10
+ # conflict, both sources are reported and the merger falls back to the nearest non-conflicting higher-tier
11
+ # (or default) value for the affected `(target, edge, kind)` slot. The conflict object is the carrier of
12
+ # that report.
16
13
  #
17
14
  # Slice-3 conflict reasons:
18
15
  #
19
- # - `:return_type_collapse` — two return-type contributions
20
- # intersect to `bot`.
21
- # - `:exceptional_disagreement` — two contributions assert
22
- # incompatible non-`nil` exceptional effects.
23
- # - `:lower_tier_contradiction` — a lower-tier contribution
24
- # would weaken or contradict a higher-tier proof.
16
+ # - `:return_type_collapse` — two return-type contributions intersect to `bot`.
17
+ # - `:exceptional_disagreement` — two contributions assert incompatible non-`nil` exceptional effects.
18
+ # - `:lower_tier_contradiction` — a lower-tier contribution would weaken or contradict a higher-tier proof.
25
19
  CONFLICT_VALID_REASONS = %i[
26
20
  return_type_collapse
27
21
  exceptional_disagreement
@@ -51,19 +45,14 @@ module Rigor
51
45
  }
52
46
  end
53
47
 
54
- # ADR-7 § "Slice 5-C" — converts the conflict into a
55
- # `Rigor::Analysis::Diagnostic` for the run result.
56
- # Carries `source_family: :contribution_merge` so the
57
- # qualified-rule formatter (slice 5 formatter half,
58
- # `ef730b2`) prefixes the rule id with
59
- # `contribution_merge.` and the JSON output side-bands
48
+ # ADR-7 § "Slice 5-C" — converts the conflict into a `Rigor::Analysis::Diagnostic` for the run result.
49
+ # Carries `source_family: :contribution_merge` so the qualified-rule formatter (slice 5 formatter half,
50
+ # `ef730b2`) prefixes the rule id with `contribution_merge.` and the JSON output side-bands
60
51
  # `source_family` + `rule` for plugin attribution.
61
52
  #
62
- # The `rule` identifier is the kebab-case form of the
63
- # conflict reason (`return_type_collapse`
64
- # `return-type-collapse`, etc.) so the qualified rule
65
- # reads `[contribution_merge.return-type-collapse]` in
66
- # the standard text stream.
53
+ # The `rule` identifier is the kebab-case form of the conflict reason (`return_type_collapse` →
54
+ # `return-type-collapse`, etc.) so the qualified rule reads `[contribution_merge.return-type-collapse]`
55
+ # in the standard text stream.
67
56
  def to_diagnostic(path:, line:, column:, severity: :error)
68
57
  require_relative "../analysis/diagnostic" unless defined?(Rigor::Analysis::Diagnostic)
69
58
  Rigor::Analysis::Diagnostic.new(
@@ -2,20 +2,15 @@
2
2
 
3
3
  module Rigor
4
4
  class FlowContribution
5
- # Tagged element flattening of a {FlowContribution} bundle —
6
- # the analyzer-internal representation [ADR-2 § "Flow
7
- # Contribution Bundle"](../../../docs/adr/2-extension-api.md)
8
- # routes through the {Merger}.
5
+ # Tagged element flattening of a {FlowContribution} bundle — the analyzer-internal representation
6
+ # [ADR-2 § "Flow Contribution Bundle"](../../../docs/adr/2-extension-api.md) routes through the {Merger}.
9
7
  #
10
- # The flattening is **mechanical, deterministic, and round-
11
- # trippable** with the bundle: every non-empty slot expands
12
- # into one or more elements keyed by `(target, edge, kind)`,
13
- # and an array of elements rebuilds an equivalent bundle when
14
- # routed through `Merger.merge`.
8
+ # The flattening is **mechanical, deterministic, and round-trippable** with the bundle: every non-empty slot
9
+ # expands into one or more elements keyed by `(target, edge, kind)`, and an array of elements rebuilds an
10
+ # equivalent bundle when routed through `Merger.merge`.
15
11
  #
16
- # Plugin authors should not depend on the element shape — the
17
- # bundle is the public contract; the element list is the
18
- # implementation surface the merge policy operates over.
12
+ # Plugin authors should not depend on the element shape — the bundle is the public contract; the element
13
+ # list is the implementation surface the merge policy operates over.
19
14
  ELEMENT_VALID_EDGES = %i[normal truthy falsey post_return exceptional].freeze
20
15
  ELEMENT_VALID_KINDS = %i[
21
16
  return_type
@@ -2,63 +2,43 @@
2
2
 
3
3
  module Rigor
4
4
  class FlowContribution
5
- # Canonical slot payload for the four edge-aware fact slots
6
- # (`truthy_facts`, `falsey_facts`, `post_return_facts`, plus
7
- # the equivalent under `mutations` / `invalidations` /
8
- # `role_conformance` once those carriers grow Fact-shaped
9
- # variants).
5
+ # Canonical slot payload for the four edge-aware fact slots (`truthy_facts`, `falsey_facts`,
6
+ # `post_return_facts`, plus the equivalent under `mutations` / `invalidations` / `role_conformance` once
7
+ # those carriers grow Fact-shaped variants).
10
8
  #
11
- # ADR-7 § "Slice 4-A" pins this object as the **single
12
- # canonical translation target** for the four parallel
9
+ # ADR-7 § "Slice 4-A" pins this object as the **single canonical translation target** for the four parallel
13
10
  # contribution carriers the engine has carried so far:
14
11
  #
15
- # 1. Built-in narrowing rules' direct fact emission
16
- # (Inference::Narrowing#predicate_scopes).
17
- # 2. RBS::Extended `predicate-if-*` directives
18
- # (`Rigor::RbsExtended::PredicateEffect`).
19
- # 3. RBS::Extended `assert*` directives
20
- # (`Rigor::RbsExtended::AssertEffect`).
12
+ # 1. Built-in narrowing rules' direct fact emission (Inference::Narrowing#predicate_scopes).
13
+ # 2. RBS::Extended `predicate-if-*` directives (`Rigor::RbsExtended::PredicateEffect`).
14
+ # 3. RBS::Extended `assert*` directives (`Rigor::RbsExtended::AssertEffect`).
21
15
  # 4. Plugin contributions via `narrowing_facts` DSL (ADR-52).
22
16
  #
23
- # Each of those four carriers translates to / from Fact at
24
- # its boundary; downstream of {Rigor::FlowContribution#to_element_list}
25
- # and {Rigor::FlowContribution::Merger.merge}, every slot
26
- # payload is a Fact (or a value that the merger compares by
27
- # equality and never inspects). The typed `RbsExtended::*Effect`
28
- # carriers stay internal to the parser side — they hold the
29
- # source-text shape, but lose their identity at the
30
- # `read_flow_contribution` boundary.
17
+ # Each of those four carriers translates to / from Fact at its boundary; downstream of
18
+ # {Rigor::FlowContribution#to_element_list} and {Rigor::FlowContribution::Merger.merge}, every slot payload
19
+ # is a Fact (or a value that the merger compares by equality and never inspects). The typed
20
+ # `RbsExtended::*Effect` carriers stay internal to the parser side — they hold the source-text shape, but
21
+ # lose their identity at the `read_flow_contribution` boundary.
31
22
  #
32
23
  # ## Field set
33
24
  #
34
- # - `target_kind`: `:parameter` (call-site argument), `:self`
35
- # (receiver), or `:local` (a named local in the surrounding
36
- # scope). v0.1.8 Pillar 2 Slice 1 added `:local` so plugins
37
- # recognising bespoke call shapes (`expect(x).to be_a(T)`)
38
- # can narrow a specific scope-bound local without routing
39
- # through the parameter-name lookup that requires an
40
- # authoritative RBS sig on the called method. Future slices
41
- # may extend further (`:ivar`, `:result`). The merger is
42
- # agnostic to the concrete kinds and only requires equality.
43
- # - `target_name`: a `Symbol`. For `:parameter` it's the
44
- # declared parameter name. For `:self` it is the literal
45
- # `:self` symbol so the field stays non-nil and the merge
46
- # key is well-defined. For `:local` it's the local-variable
47
- # name (e.g. `:x` for `expect(x).to be_a(T)`).
48
- # - `type`: a `Rigor::Type::*` (Nominal, Refined,
49
- # IntegerRange, Difference, …) the fact narrows the
50
- # target toward (when `negative` is false) or away from
51
- # (when `negative` is true).
52
- # - `negative`: `true` for the `~T` negation form
53
- # (`predicate-if-true x is ~Integer`), `false` for the
54
- # plain positive form. Mirrors the `negative` field on
55
- # `PredicateEffect` / `AssertEffect`.
25
+ # - `target_kind`: `:parameter` (call-site argument), `:self` (receiver), or `:local` (a named local in the
26
+ # surrounding scope). v0.1.8 Pillar 2 Slice 1 added `:local` so plugins recognising bespoke call shapes
27
+ # (`expect(x).to be_a(T)`) can narrow a specific scope-bound local without routing through the
28
+ # parameter-name lookup that requires an authoritative RBS sig on the called method. Future slices may
29
+ # extend further (`:ivar`, `:result`). The merger is agnostic to the concrete kinds and only requires
30
+ # equality.
31
+ # - `target_name`: a `Symbol`. For `:parameter` it's the declared parameter name. For `:self` it is the
32
+ # literal `:self` symbol so the field stays non-nil and the merge key is well-defined. For `:local` it's
33
+ # the local-variable name (e.g. `:x` for `expect(x).to be_a(T)`).
34
+ # - `type`: a `Rigor::Type::*` (Nominal, Refined, IntegerRange, Difference, …) the fact narrows the target
35
+ # toward (when `negative` is false) or away from (when `negative` is true).
36
+ # - `negative`: `true` for the `~T` negation form (`predicate-if-true x is ~Integer`), `false` for the plain
37
+ # positive form. Mirrors the `negative` field on `PredicateEffect` / `AssertEffect`.
56
38
  #
57
- # The `target` accessor returns `:self` for self-targeted
58
- # facts and `[:parameter, name]` otherwise that's the
59
- # value {Element#target} keys on, so two facts that narrow
60
- # the same parameter from different contribution sources
61
- # land in the same merge bucket.
39
+ # The `target` accessor returns `:self` for self-targeted facts and `[:parameter, name]` otherwise — that's
40
+ # the value {Element#target} keys on, so two facts that narrow the same parameter from different
41
+ # contribution sources land in the same merge bucket.
62
42
  FACT_VALID_TARGET_KINDS = %i[parameter self local].freeze
63
43
 
64
44
  class Fact < Data.define(:target_kind, :target_name, :type, :negative)
@@ -77,15 +57,11 @@ module Rigor
77
57
  super
78
58
  end
79
59
 
80
- # Composite target identifier the merger keys on. `:self`
81
- # for self-targeted facts; otherwise `[kind, name]` so two
82
- # contributions that narrow the same `(kind, name)` pair
83
- # regardless of source family land in the same merge
84
- # bucket. `:local` and `:parameter` facts that name the
85
- # same symbol stay in separate buckets, which is the
86
- # correct semantics: a `:local` fact narrows the surrounding
87
- # scope's named local, a `:parameter` fact narrows the
88
- # call-site argument matching the parameter declaration.
60
+ # Composite target identifier the merger keys on. `:self` for self-targeted facts; otherwise
61
+ # `[kind, name]` so two contributions that narrow the same `(kind, name)` pair — regardless of source
62
+ # family land in the same merge bucket. `:local` and `:parameter` facts that name the same symbol stay
63
+ # in separate buckets, which is the correct semantics: a `:local` fact narrows the surrounding scope's
64
+ # named local, a `:parameter` fact narrows the call-site argument matching the parameter declaration.
89
65
  def target
90
66
  target_kind == :self ? :self : [target_kind, target_name]
91
67
  end
@@ -2,16 +2,13 @@
2
2
 
3
3
  module Rigor
4
4
  class FlowContribution
5
- # Result of folding any number of {FlowContribution} bundles
6
- # through {Merger.merge}. Surfaces the merged content slot-by-
7
- # slot, the ordered list of contributing provenances, and the
8
- # {Conflict} list collected along the way.
5
+ # Result of folding any number of {FlowContribution} bundles through {Merger.merge}. Surfaces the merged
6
+ # content slot-by-slot, the ordered list of contributing provenances, and the {Conflict} list collected
7
+ # along the way.
9
8
  #
10
- # The merge result is a sibling shape of {FlowContribution} —
11
- # the analyzer reads from it to drive narrowing / dispatch /
12
- # diagnostics, and the formatter reads from it to surface
13
- # plugin / RBS::Extended provenance. The shape is derived per
14
- # ADR-2 § "Plugin Contribution Merging"; see
9
+ # The merge result is a sibling shape of {FlowContribution} — the analyzer reads from it to drive narrowing
10
+ # / dispatch / diagnostics, and the formatter reads from it to surface plugin / RBS::Extended provenance.
11
+ # The shape is derived per ADR-2 § "Plugin Contribution Merging"; see
15
12
  # [`docs/internal-spec/flow-contribution-merger.md`](../../../docs/internal-spec/flow-contribution-merger.md)
16
13
  # for the slice-3 normative description.
17
14
  class MergeResult
@@ -6,55 +6,44 @@ require_relative "merge_result"
6
6
 
7
7
  module Rigor
8
8
  class FlowContribution
9
- # Composes any number of {FlowContribution} bundles into a
10
- # single {MergeResult} per ADR-2 § "Plugin Contribution
11
- # Merging". The merger is the **single point of integration**
12
- # the analyzer uses to combine contributions from built-in
13
- # narrowing rules, `RBS::Extended` annotations, and plugins;
14
- # slice 4 routes the existing internal narrowing through it
15
- # and slice 6 wires plugin-side cache producers around it.
9
+ # Composes any number of {FlowContribution} bundles into a single {MergeResult} per ADR-2 § "Plugin
10
+ # Contribution Merging". The merger is the **single point of integration** the analyzer uses to combine
11
+ # contributions from built-in narrowing rules, `RBS::Extended` annotations, and plugins; slice 4 routes
12
+ # the existing internal narrowing through it and slice 6 wires plugin-side cache producers around it.
16
13
  #
17
14
  # ## Authority tiers
18
15
  #
19
- # - Tier 0: `:builtin` — Core Ruby semantics and accepted RBS
20
- # contracts. Authoritative; lower tiers may not contradict.
21
- # - Tier 1: `:rbs_extended` (`RBS::Extended` directive bundles,
22
- # v0.0.9 group D reference impl) and `:generated` (generated
23
- # signatures / metadata).
16
+ # - Tier 0: `:builtin` — Core Ruby semantics and accepted RBS contracts. Authoritative; lower tiers may
17
+ # not contradict.
18
+ # - Tier 1: `:rbs_extended` (`RBS::Extended` directive bundles, v0.0.9 group D reference impl) and
19
+ # `:generated` (generated signatures / metadata).
24
20
  # - Tier 2: `:plugin` and `plugin.<id>` source families.
25
21
  # - Tier 3: anything else — treated as the lowest tier.
26
22
  #
27
- # Within a tier, contributions are merged in deterministic
28
- # order: provenance-supplied `plugin_id` alphabetical (nil
29
- # plugin ids sort first to keep `:rbs_extended` / `:generated`
30
- # pre-plugin contributions stable), then by their original
31
- # input position as the final tie-break.
23
+ # Within a tier, contributions are merged in deterministic order: provenance-supplied `plugin_id`
24
+ # alphabetical (nil plugin ids sort first to keep `:rbs_extended` / `:generated` pre-plugin contributions
25
+ # stable), then by their original input position as the final tie-break.
32
26
  #
33
27
  # ## Composition rules (ADR-2)
34
28
  #
35
- # - `:return_type` — Intersect via `Type::Combinator.intersection`;
36
- # collapse to bot raises `:return_type_collapse`.
37
- # - `:truthy_fact` / `:falsey_fact` / `:post_return_fact` —
38
- # Edge-local; accumulate while deduping by payload equality.
39
- # - `:mutation` / `:invalidation` / `:role` — Union; dedupe by
40
- # equality.
41
- # - `:exception` — Single-valued. Two non-`nil` non-equal
42
- # exceptional effects raise `:exceptional_disagreement`.
29
+ # - `:return_type` — Intersect via `Type::Combinator.intersection`; collapse to bot raises
30
+ # `:return_type_collapse`.
31
+ # - `:truthy_fact` / `:falsey_fact` / `:post_return_fact` — Edge-local; accumulate while deduping by
32
+ # payload equality.
33
+ # - `:mutation` / `:invalidation` / `:role` — Union; dedupe by equality.
34
+ # - `:exception` — Single-valued. Two non-`nil` non-equal exceptional effects raise
35
+ # `:exceptional_disagreement`.
43
36
  #
44
37
  # ## Cross-tier contradictions
45
38
  #
46
- # Lower tiers may refine higher tiers but must not weaken them.
47
- # Slice 3 surfaces contradictions through `:lower_tier_contradiction`
48
- # when:
39
+ # Lower tiers may refine higher tiers but must not weaken them. Slice 3 surfaces contradictions through
40
+ # `:lower_tier_contradiction` when:
49
41
  #
50
- # - the higher tier already pinned a `return_type` and a lower
51
- # tier's intersection collapses to `bot`;
52
- # - the higher tier set `exceptional` to a non-`nil` value and a
53
- # lower tier disagrees.
42
+ # - the higher tier already pinned a `return_type` and a lower tier's intersection collapses to `bot`;
43
+ # - the higher tier set `exceptional` to a non-`nil` value and a lower tier disagrees.
54
44
  #
55
- # In every conflict case the result keeps the higher-tier value
56
- # for that slot, records a {Conflict} with both provenances, and
57
- # continues processing the remaining slots / contributions.
45
+ # In every conflict case the result keeps the higher-tier value for that slot, records a {Conflict} with
46
+ # both provenances, and continues processing the remaining slots / contributions.
58
47
  module Merger
59
48
  AUTHORITY_TIERS = {
60
49
  builtin: 0,
@@ -91,8 +80,8 @@ module Rigor
91
80
  private
92
81
 
93
82
  def order_contributions(contributions)
94
- # Stable sort: tier ascending, then provenance plugin_id
95
- # alphabetical (nil first), then original input position.
83
+ # Stable sort: tier ascending, then provenance plugin_id alphabetical (nil first), then original
84
+ # input position.
96
85
  contributions.each_with_index
97
86
  .sort_by { |c, i| [tier_for(c.provenance), plugin_id_key(c.provenance), i] }
98
87
  .map { |c, _| c }
@@ -140,13 +129,10 @@ module Rigor
140
129
  state.return_type_tier = [state.return_type_tier, tier].min
141
130
  end
142
131
 
143
- # Two types' intersection collapses to bot when neither
144
- # accepts the other under gradual mode — i.e. the value
145
- # domains are disjoint. `Rigor::Type::Combinator.intersection`
146
- # itself does not collapse incompatible nominals (`String
147
- # Integer` builds a structurally-empty `Intersection`
148
- # carrier), so the merger checks the disjointness condition
149
- # directly via the `accepts` trinary.
132
+ # Two types' intersection collapses to bot when neither accepts the other under gradual mode — i.e.
133
+ # the value domains are disjoint. `Rigor::Type::Combinator.intersection` itself does not collapse
134
+ # incompatible nominals (`String ∩ Integer` builds a structurally-empty `Intersection` carrier), so
135
+ # the merger checks the disjointness condition directly via the `accepts` trinary.
150
136
  def intersection_empty?(lhs, rhs)
151
137
  return false if lhs.equal?(rhs)
152
138
 
@@ -227,9 +213,8 @@ module Rigor
227
213
  end
228
214
  end
229
215
 
230
- # Internal accumulator carried through a single merge call.
231
- # Not part of the public API; folds into a {MergeResult} at
232
- # the end via {#to_result}.
216
+ # Internal accumulator carried through a single merge call. Not part of the public API; folds into a
217
+ # {MergeResult} at the end via {#to_result}.
233
218
  class MergeState
234
219
  attr_accessor :return_type, :return_type_tier, :return_type_provenance,
235
220
  :exceptional, :exceptional_tier, :exceptional_provenance
@@ -3,33 +3,26 @@
3
3
  require_relative "flow_contribution/element"
4
4
 
5
5
  module Rigor
6
- # The public packaging of a flow contribution at a single call edge.
7
- # Plugins, `RBS::Extended` annotations, and built-in narrowing rules
8
- # all hand the analyzer this same bundle shape; the inference engine
9
- # merges contributions through the policy described in
10
- # [ADR-2 § "Plugin Contribution Merging"](../../docs/adr/2-extension-api.md)
11
- # rather than letting any one source override another silently.
6
+ # The public packaging of a flow contribution at a single call edge. Plugins, `RBS::Extended` annotations,
7
+ # and built-in narrowing rules all hand the analyzer this same bundle shape; the inference engine merges
8
+ # contributions through the policy described in
9
+ # [ADR-2 § "Plugin Contribution Merging"](../../docs/adr/2-extension-api.md) rather than letting any one
10
+ # source override another silently.
12
11
  #
13
- # Eight content slots plus a {Provenance} block. A slot left as `nil`
14
- # (or, for collection-shaped slots, an empty collection) means the
15
- # contribution does not assert anything in that dimension; the merge
16
- # policy treats it as absent.
12
+ # Eight content slots plus a {Provenance} block. A slot left as `nil` (or, for collection-shaped slots, an
13
+ # empty collection) means the contribution does not assert anything in that dimension; the merge policy
14
+ # treats it as absent.
17
15
  #
18
- # The struct is the only shape plugin authors need to learn. Richer
19
- # or more permissive shapes are not part of the first public
20
- # contract — see ADR-2 § "Flow Contribution Bundle" for the binding
21
- # definition.
16
+ # The struct is the only shape plugin authors need to learn. Richer or more permissive shapes are not part
17
+ # of the first public contract see ADR-2 § "Flow Contribution Bundle" for the binding definition.
22
18
  #
23
- # `to_element_list` and `Merger` are implemented; plugin authors
24
- # should not depend on the `Element` shape the bundle is the
25
- # public contract.
19
+ # `to_element_list` and `Merger` are implemented; plugin authors should not depend on the `Element` shape —
20
+ # the bundle is the public contract.
26
21
  class FlowContribution
27
- # Provenance carries the metadata every contribution needs for
28
- # diagnostic attribution and cache invalidation. `source_family`
29
- # mirrors {Rigor::Analysis::Diagnostic::DEFAULT_SOURCE_FAMILY};
30
- # `descriptor` is the {Rigor::Cache::Descriptor} this
31
- # contribution attaches to (or `nil` when the contribution does
32
- # not need its own cache slice).
22
+ # Provenance carries the metadata every contribution needs for diagnostic attribution and cache
23
+ # invalidation. `source_family` mirrors {Rigor::Analysis::Diagnostic::DEFAULT_SOURCE_FAMILY}; `descriptor`
24
+ # is the {Rigor::Cache::Descriptor} this contribution attaches to (or `nil` when the contribution does not
25
+ # need its own cache slice).
33
26
  class Provenance < Data.define(:source_family, :plugin_id, :node, :descriptor)
34
27
  def self.builtin
35
28
  new(source_family: :builtin, plugin_id: nil, node: nil, descriptor: nil)
@@ -49,27 +42,20 @@ module Rigor
49
42
 
50
43
  attr_reader(*SLOT_NAMES, :provenance)
51
44
 
52
- # @param return_type [Object, nil] normal-edge return type. Use
53
- # `nil` when the contribution does not refine the return type
54
- # selected from the RBS contract.
55
- # @param truthy_facts [Array, nil] facts that hold only on the
56
- # truthy control-flow edge. Edge-local: a truthy-edge fact does
57
- # NOT imply its falsey-edge complement (ADR-2 § "Plugin
58
- # Contribution Merging").
45
+ # @param return_type [Object, nil] normal-edge return type. Use `nil` when the contribution does not
46
+ # refine the return type selected from the RBS contract.
47
+ # @param truthy_facts [Array, nil] facts that hold only on the truthy control-flow edge. Edge-local: a
48
+ # truthy-edge fact does NOT imply its falsey-edge complement (ADR-2 § "Plugin Contribution Merging").
59
49
  # @param falsey_facts [Array, nil] dual of `truthy_facts`.
60
- # @param post_return_facts [Array, nil] facts that hold after the
61
- # call returns normally on every edge — the carrier for
62
- # assertion-style contributions.
63
- # @param mutations [Array, nil] receiver and argument mutation
64
- # effects.
65
- # @param invalidations [Array, nil] targeted fact invalidations
66
- # beyond what mutation effects already imply.
67
- # @param exceptional [Object, nil] non-returning, raising, or
68
- # unreachable effect.
69
- # @param role_conformance [Array, nil] capability-role conformance
70
- # facts the contribution provides.
71
- # @param provenance [Provenance] source-family, plugin-id, node,
72
- # and cache-descriptor metadata. Defaults to `Provenance.builtin`.
50
+ # @param post_return_facts [Array, nil] facts that hold after the call returns normally on every edge —
51
+ # the carrier for assertion-style contributions.
52
+ # @param mutations [Array, nil] receiver and argument mutation effects.
53
+ # @param invalidations [Array, nil] targeted fact invalidations beyond what mutation effects already
54
+ # imply.
55
+ # @param exceptional [Object, nil] non-returning, raising, or unreachable effect.
56
+ # @param role_conformance [Array, nil] capability-role conformance facts the contribution provides.
57
+ # @param provenance [Provenance] source-family, plugin-id, node, and cache-descriptor metadata. Defaults
58
+ # to `Provenance.builtin`.
73
59
  # rubocop:disable Metrics/ParameterLists
74
60
  def initialize(return_type: nil, truthy_facts: nil, falsey_facts: nil,
75
61
  post_return_facts: nil, mutations: nil, invalidations: nil,
@@ -88,9 +74,8 @@ module Rigor
88
74
  freeze
89
75
  end
90
76
 
91
- # @return [Boolean] true when every content slot is unset (nil or
92
- # an empty collection). Provenance does not count toward
93
- # emptiness — an empty bundle still carries source attribution.
77
+ # @return [Boolean] true when every content slot is unset (nil or an empty collection). Provenance does
78
+ # not count toward emptiness — an empty bundle still carries source attribution.
94
79
  def empty?
95
80
  SLOT_NAMES.all? { |slot| slot_empty?(public_send(slot)) }
96
81
  end
@@ -101,10 +86,9 @@ module Rigor
101
86
  end
102
87
  end
103
88
 
104
- # Flattens this bundle into a tagged element list keyed by
105
- # `(target, edge, kind)`. The flattening is mechanical and
106
- # round-trippable through {Merger.merge}: feeding the result
107
- # back through the merger produces an equivalent bundle.
89
+ # Flattens this bundle into a tagged element list keyed by `(target, edge, kind)`. The flattening is
90
+ # mechanical and round-trippable through {Merger.merge}: feeding the result back through the merger
91
+ # produces an equivalent bundle.
108
92
  #
109
93
  # Layout:
110
94
  #
@@ -150,11 +134,9 @@ module Rigor
150
134
  Element.new(target: target, edge: edge, kind: kind, payload: payload, provenance: provenance)
151
135
  end
152
136
 
153
- # Best-effort target extraction. Payloads that expose a
154
- # `#target` accessor (typed-fact carriers, mutation effects)
155
- # provide their own; everything else falls through with the
156
- # payload itself as the merge key, which keeps deduplication
157
- # well-defined for opaque entries.
137
+ # Best-effort target extraction. Payloads that expose a `#target` accessor (typed-fact carriers, mutation
138
+ # effects) provide their own; everything else falls through with the payload itself as the merge key,
139
+ # which keeps deduplication well-defined for opaque entries.
158
140
  def fact_target(payload)
159
141
  return payload.target if payload.respond_to?(:target)
160
142