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
@@ -3,10 +3,9 @@
3
3
  module Rigor
4
4
  module Plugin
5
5
  module Macro
6
- # ADR-36 — the nested-class emission tier of the ADR-16
7
- # macro substrate. Where Tier C ({HeredocTemplate}) synthesises
8
- # *methods* on the calling class, this tier synthesises *nested
9
- # subclasses* declared by an enum-shaped block DSL.
6
+ # ADR-36 — the nested-class emission tier of the ADR-16 macro substrate. Where Tier C ({HeredocTemplate})
7
+ # synthesises *methods* on the calling class, this tier synthesises *nested subclasses* declared by an
8
+ # enum-shaped block DSL.
10
9
  #
11
10
  # Motivating shape — Mangrove's `Enum`:
12
11
  #
@@ -18,13 +17,10 @@ module Rigor
18
17
  # end
19
18
  # end
20
19
  #
21
- # Each `variant <Const>, <Type>` row is meant to mint a nested
22
- # subclass `Shape::Circle < Shape` carrying `#inner : <Type>`.
23
- # Mangrove builds this at runtime via `const_missing` +
24
- # `class_eval`; the substrate replays the same contract
25
- # statically so `Shape::Circle.new(1.0).inner` resolves the
26
- # payload to `Float` instead of `call.undefined-constant` /
27
- # `Dynamic[Top]`.
20
+ # Each `variant <Const>, <Type>` row is meant to mint a nested subclass `Shape::Circle < Shape` carrying
21
+ # `#inner : <Type>`. Mangrove builds this at runtime via `const_missing` + `class_eval`; the substrate
22
+ # replays the same contract statically so `Shape::Circle.new(1.0).inner` resolves the payload to `Float`
23
+ # instead of `call.undefined-constant` / `Dynamic[Top]`.
28
24
  #
29
25
  # ## Authoring shape
30
26
  #
@@ -41,34 +37,24 @@ module Rigor
41
37
  #
42
38
  # ## Fields
43
39
  #
44
- # - `receiver_constraint` — fully-qualified module name (String)
45
- # the enclosing class must `extend` for the block to be
46
- # recognised (e.g. `"Mangrove::Enum"`).
47
- # - `block_method` — Symbol naming the enclosing DSL block
48
- # (`:variants`).
49
- # - `variant_method` Symbol naming each declaration call
50
- # inside the block (`:variant`).
51
- # - `symbol_arg_position` — Integer (default 0): the argument
52
- # index whose literal **constant** names the nested subclass.
53
- # (Named `name_arg_position:` before ADR-60 WD2 normalised
54
- # the macro value-object vocabulary.)
55
- # - `inner_arg_position` — Integer (default 1): the argument
56
- # index whose type expression becomes the `#inner` reader's
57
- # return type. Slice A resolves a constant type argument
58
- # (`Float`, `String`); non-constant inner shapes (shape
59
- # hashes) degrade to `Dynamic[Top]`.
60
- # - `inner_reader` — Symbol (default `:inner`): the payload
61
- # reader synthesised on each variant subclass.
40
+ # - `receiver_constraint` — fully-qualified module name (String) the enclosing class must `extend` for
41
+ # the block to be recognised (e.g. `"Mangrove::Enum"`).
42
+ # - `block_method` — Symbol naming the enclosing DSL block (`:variants`).
43
+ # - `variant_method` — Symbol naming each declaration call inside the block (`:variant`).
44
+ # - `symbol_arg_position` — Integer (default 0): the argument index whose literal **constant** names the
45
+ # nested subclass. (Named `name_arg_position:` before ADR-60 WD2 normalised the macro value-object
46
+ # vocabulary.)
47
+ # - `inner_arg_position` — Integer (default 1): the argument index whose type expression becomes the
48
+ # `#inner` reader's return type. Slice A resolves a constant type argument (`Float`, `String`);
49
+ # non-constant inner shapes (shape hashes) degrade to `Dynamic[Top]`.
50
+ # - `inner_reader` — Symbol (default `:inner`): the payload reader synthesised on each variant subclass.
62
51
  #
63
52
  # ## Floor / ceiling per ADR-16 WD13 + ADR-36 WD4
64
53
  #
65
- # Slice A ships the floor: each variant constant resolves as a
66
- # class (so `<Variant>.new(...)` and the constant reference
67
- # type), and the `#inner` reader resolves to the declared inner
68
- # type. The `sealed`-parent fact + `is_a?` cross-variant
69
- # exhaustive narrowing (ADR-36 WD3) is the ceiling, deferred —
70
- # it needs the synthetic-class hierarchy threaded into
71
- # `Environment#class_ordering`.
54
+ # Slice A ships the floor: each variant constant resolves as a class (so `<Variant>.new(...)` and the
55
+ # constant reference type), and the `#inner` reader resolves to the declared inner type. The
56
+ # `sealed`-parent fact + `is_a?` cross-variant exhaustive narrowing (ADR-36 WD3) is the ceiling,
57
+ # deferred it needs the synthetic-class hierarchy threaded into `Environment#class_ordering`.
72
58
  class NestedClassTemplate
73
59
  attr_reader :receiver_constraint, :block_method, :variant_method,
74
60
  :symbol_arg_position, :inner_arg_position, :inner_reader
@@ -4,16 +4,14 @@ module Rigor
4
4
  module Plugin
5
5
  module Macro
6
6
  # ADR-16 Tier B declaration: "the class-level DSL call
7
- # `<receiver_constraint>.<method_name>(:trait_a, :trait_b, ...)`
8
- # effectively includes the modules named in
9
- # `modules_by_symbol[:trait_a]` + `[:trait_b]` (plus any
10
- # `always_included` modules) on the calling class."
7
+ # `<receiver_constraint>.<method_name>(:trait_a, :trait_b, ...)` effectively includes the modules named
8
+ # in `modules_by_symbol[:trait_a]` + `[:trait_b]` (plus any `always_included` modules) on the calling
9
+ # class."
11
10
  #
12
- # Worked target: Devise's model-side `devise :database_authenticatable,
13
- # :recoverable` DSL (per-library survey § Devise). The bundled
14
- # registry mirrors `lib/devise/modules.rb`'s symbol module table;
15
- # `always_included` carries the modules Devise always mixes in
16
- # regardless of selection (e.g. `Devise::Models::Authenticatable`).
11
+ # Worked target: Devise's model-side `devise :database_authenticatable, :recoverable` DSL (per-library
12
+ # survey § Devise). The bundled registry mirrors `lib/devise/modules.rb`'s symbol → module table;
13
+ # `always_included` carries the modules Devise always mixes in regardless of selection (e.g.
14
+ # `Devise::Models::Authenticatable`).
17
15
  #
18
16
  # ## Authoring shape
19
17
  #
@@ -37,50 +35,36 @@ module Rigor
37
35
  #
38
36
  # ## Fields
39
37
  #
40
- # - `receiver_constraint` — fully-qualified class name (String).
41
- # Synthesis fires when the call's lexical receiver class
42
- # equals or inherits from this constraint.
43
- # - `method_name` — Symbol naming the DSL method
44
- # (e.g. `:devise`).
45
- # - `symbol_arg_position` `:rest` (all positional Symbol args
46
- # are traits, slice 3a's only supported form) or a
47
- # non-negative Integer (the index of a single trait symbol
48
- # reserved for future shapes; not yet honoured by the
49
- # scanner).
50
- # - `modules_by_symbol` Hash<Symbol, String>. Maps each
51
- # recognised trait symbol to a fully-qualified module name.
52
- # Symbols not in the table fall through (silent skip; the
53
- # scanner emits a `macro.tier_b.unknown-trait` `:info`
54
- # provenance marker per WD9 / WD13).
55
- # - `always_included` — Array<String>. Fully-qualified module
56
- # names that are added to every call site (even when no
57
- # symbols match). Mirrors Devise's `always_include` modules.
38
+ # - `receiver_constraint` — fully-qualified class name (String). Synthesis fires when the call's
39
+ # lexical receiver class equals or inherits from this constraint.
40
+ # - `method_name` Symbol naming the DSL method (e.g. `:devise`).
41
+ # - `symbol_arg_position` — `:rest` (all positional Symbol args are traits, slice 3a's only supported
42
+ # form) or a non-negative Integer (the index of a single trait symbol — reserved for future shapes;
43
+ # not yet honoured by the scanner).
44
+ # - `modules_by_symbol` — Hash<Symbol, String>. Maps each recognised trait symbol to a fully-qualified
45
+ # module name. Symbols not in the table fall through (silent skip; the scanner emits a
46
+ # `macro.tier_b.unknown-trait` `:info` provenance marker per WD9 / WD13).
47
+ # - `always_included` — Array<String>. Fully-qualified module names that are added to every call site
48
+ # (even when no symbols match). Mirrors Devise's `always_include` modules.
58
49
  #
59
50
  # ## Floor / ceiling per ADR-16 WD13
60
51
  #
61
- # Slice 3 ships at the **floor**: the substrate per-method-
62
- # explodes each included module's RBS instance methods into
63
- # the existing `SyntheticMethodIndex` (slice 2b primitive).
64
- # The synthesised methods adopt the module's authored RBS
65
- # return types Tier B is NOT subject to the Tier C
66
- # `Dynamic[T]` floor because the source-of-truth (the
67
- # module's authored RBS) is not a manifest-declared string.
68
- # Per ADR-5 robustness, the substrate does not fabricate
69
- # precision; it simply replays the modules's signatures.
52
+ # Slice 3 ships at the **floor**: the substrate per-method-explodes each included module's RBS instance
53
+ # methods into the existing `SyntheticMethodIndex` (slice 2b primitive). The synthesised methods adopt
54
+ # the module's authored RBS return types — Tier B is NOT subject to the Tier C `Dynamic[T]` floor
55
+ # because the source-of-truth (the module's authored RBS) is not a manifest-declared string. Per ADR-5
56
+ # robustness, the substrate does not fabricate precision; it simply replays the modules's signatures.
70
57
  #
71
58
  # **Out of scope for slice 3** (deferred follow-ups):
72
- # - `class_methods_module:` per-trait (Devise's `ClassMethods`
73
- # extend-pattern); slice 3 covers instance methods only.
74
- # - `sort_key:` for controlled include ordering across traits;
75
- # slice 3 uses plugin-registration order then registry
76
- # declaration order.
77
- # - `included_do_digest:` the per-module `included do` block
78
- # facts (attr_reader / after_save / etc.); slice 3 emits
79
- # only the module's plain instance methods.
59
+ # - `class_methods_module:` per-trait (Devise's `ClassMethods` extend-pattern); slice 3 covers instance
60
+ # methods only.
61
+ # - `sort_key:` for controlled include ordering across traits; slice 3 uses plugin-registration order
62
+ # then registry declaration order.
63
+ # - `included_do_digest:` — the per-module `included do` block facts (attr_reader / after_save / etc.);
64
+ # slice 3 emits only the module's plain instance methods.
80
65
  #
81
- # Engine wiring: `Inference::SyntheticMethodScanner#collect_trait_registries`
82
- # (slice 3b) walks Tier B call sites and explodes per-method
83
- # entries. Worked consumer: `plugins/rigor-devise/` (slice 3c).
66
+ # Engine wiring: `Inference::SyntheticMethodScanner#collect_trait_registries` (slice 3b) walks Tier B
67
+ # call sites and explodes per-method entries. Worked consumer: `plugins/rigor-devise/` (slice 3c).
84
68
  class TraitRegistry
85
69
  REST_POSITION = :rest
86
70
 
@@ -121,10 +105,9 @@ module Rigor
121
105
  to_h.hash
122
106
  end
123
107
 
124
- # @return [String, nil] fully-qualified module name for the
125
- # given trait symbol, or nil when the registry doesn't
126
- # know the symbol (caller emits a tier_b.unknown-trait
127
- # provenance marker and falls through).
108
+ # @return [String, nil] fully-qualified module name for the given trait symbol, or nil when the
109
+ # registry doesn't know the symbol (caller emits a tier_b.unknown-trait provenance marker and falls
110
+ # through).
128
111
  def module_for(symbol)
129
112
  modules_by_symbol[symbol.to_sym]
130
113
  end
@@ -7,23 +7,18 @@ require_relative "macro/trait_registry"
7
7
 
8
8
  module Rigor
9
9
  module Plugin
10
- # Substrate declarations for the macro / DSL expansion tiers
11
- # introduced by ADR-16. Plugin authors declare entries under
12
- # `Plugin::Manifest` slots (`block_as_methods:`,
13
- # `trait_registries:`, `heredoc_templates:`,
14
- # `nested_class_templates:`) and the substrate consumes them
15
- # to recognise the call shapes a library exposes to its users.
10
+ # Substrate declarations for the macro / DSL expansion tiers introduced by ADR-16. Plugin authors declare
11
+ # entries under `Plugin::Manifest` slots (`block_as_methods:`, `trait_registries:`, `heredoc_templates:`,
12
+ # `nested_class_templates:`) and the substrate consumes them to recognise the call shapes a library exposes
13
+ # to its users.
16
14
  #
17
- # Tier A (`BlockAsMethod`), Tier B (`TraitRegistry`), Tier C
18
- # (`HeredocTemplate`), and ADR-36 nested-class emission
19
- # (`NestedClassTemplate`) value classes are all shipped here.
20
- # Engine wiring lives in `lib/rigor/inference/`.
15
+ # Tier A (`BlockAsMethod`), Tier B (`TraitRegistry`), Tier C (`HeredocTemplate`), and ADR-36 nested-class
16
+ # emission (`NestedClassTemplate`) value classes are all shipped here. Engine wiring lives in
17
+ # `lib/rigor/inference/`.
21
18
  #
22
- # Per ADR-16 § WD13, substrate-produced output ships at a
23
- # **floor** in v0.1.x ("substrate-affected code parses cleanly
24
- # and has its identifiers resolved"); precise return-type
25
- # emission is the ceiling and arrives in a later slice through
26
- # the ADR-13 `Plugin::TypeNodeResolver` chain.
19
+ # Per ADR-16 § WD13, substrate-produced output ships at a **floor** in v0.1.x ("substrate-affected code
20
+ # parses cleanly and has its identifiers resolved"); precise return-type emission is the ceiling and arrives
21
+ # in a later slice through the ADR-13 `Plugin::TypeNodeResolver` chain.
27
22
  module Macro
28
23
  end
29
24
  end
@@ -6,35 +6,27 @@ require_relative "additional_initializer"
6
6
 
7
7
  module Rigor
8
8
  module Plugin
9
- # Value object describing one plugin's identity and metadata.
10
- # Constructed once per plugin class through {Rigor::Plugin::Base.manifest};
11
- # consumed by {Rigor::Plugin::Loader} when matching project
12
- # configuration entries to registered plugins and by
13
- # {Rigor::Cache::Descriptor::PluginEntry} when deriving cache keys.
9
+ # Value object describing one plugin's identity and metadata. Constructed once per plugin class through
10
+ # {Rigor::Plugin::Base.manifest}; consumed by {Rigor::Plugin::Loader} when matching project configuration
11
+ # entries to registered plugins and by {Rigor::Cache::Descriptor::PluginEntry} when deriving cache keys.
14
12
  #
15
- # The fields are pinned by ADR-2 § "Registration, Configuration,
16
- # and Caching"; the v0.1.0 plugin contract surface treats this
17
- # struct as the public manifest shape.
13
+ # The fields are pinned by ADR-2 § "Registration, Configuration, and Caching"; the v0.1.0 plugin contract
14
+ # surface treats this struct as the public manifest shape.
18
15
  class Manifest # rubocop:disable Metrics/ClassLength
19
- # Same regex {Rigor::Cache::Store::VALID_PRODUCER_ID} uses,
20
- # so plugin ids round-trip through cache producer ids and
21
- # `plugin.<id>.<rule>` diagnostic identifiers without escape.
16
+ # Same regex {Rigor::Cache::Store::VALID_PRODUCER_ID} uses, so plugin ids round-trip through cache
17
+ # producer ids and `plugin.<id>.<rule>` diagnostic identifiers without escape.
22
18
  VALID_ID = /\A[a-z][a-z0-9._-]*\z/
23
19
 
24
- # The first-implementation `config_schema` accepts these value
25
- # kinds. Slice 1 only checks key presence and shallow value
26
- # kind; richer schemas (nested maps, enums) land later when
27
- # the v0.1.0 protocol slices need them.
20
+ # The first-implementation `config_schema` accepts these value kinds. Slice 1 only checks key presence
21
+ # and shallow value kind; richer schemas (nested maps, enums) land later when the v0.1.0 protocol slices
22
+ # need them.
28
23
  VALID_VALUE_KINDS = %i[string boolean integer array hash any].freeze
29
24
 
30
- # ADR-9 slice 4 — declared cross-plugin fact dependencies.
31
- # `produces:` lists the names this plugin publishes through
32
- # its `#prepare(services)` hook. `consumes:` lists the
33
- # `(plugin_id, name)` pairs this plugin reads from
34
- # `services.fact_store`. The loader uses both for
35
- # topological sort + missing-producer detection; slice 4
36
- # added the declarations; slice 5 (`Loader#topo_sort_plugins`)
37
- # enforces ordering and missing-producer validation.
25
+ # ADR-9 slice 4 — declared cross-plugin fact dependencies. `produces:` lists the names this plugin
26
+ # publishes through its `#prepare(services)` hook. `consumes:` lists the `(plugin_id, name)` pairs this
27
+ # plugin reads from `services.fact_store`. The loader uses both for topological sort + missing-producer
28
+ # detection; slice 4 added the declarations; slice 5 (`Loader#topo_sort_plugins`) enforces ordering and
29
+ # missing-producer validation.
38
30
  class Consumption < Data.define(:plugin_id, :name, :optional)
39
31
  def initialize(plugin_id:, name:, optional: false)
40
32
  super(plugin_id: plugin_id.to_s, name: name.to_sym, optional: optional ? true : false)
@@ -110,17 +102,15 @@ module Rigor
110
102
  @source_rbs_synthesizer = source_rbs_synthesizer
111
103
  end
112
104
 
113
- # Assigned outside assign_fields (which already carries the
114
- # maximum positional arity) set in `initialize` before the
115
- # final freeze. ADR-36 nested-class emission tier.
105
+ # Assigned outside assign_fields (which already carries the maximum positional arity) — set in
106
+ # `initialize` before the final freeze. ADR-36 nested-class emission tier.
116
107
  def assign_nested_class_templates(nested_class_templates)
117
108
  @nested_class_templates = nested_class_templates.dup.freeze
118
109
  end
119
110
  private :assign_nested_class_templates
120
111
 
121
- # ADR-38 — assigned outside assign_fields (which already carries
122
- # the maximum positional arity), set in `initialize` before the
123
- # final freeze.
112
+ # ADR-38 — assigned outside assign_fields (which already carries the maximum positional arity), set in
113
+ # `initialize` before the final freeze.
124
114
  def assign_additional_initializers(additional_initializers)
125
115
  @additional_initializers = additional_initializers.dup.freeze
126
116
  end
@@ -129,11 +119,9 @@ module Rigor
129
119
 
130
120
  public
131
121
 
132
- # Validates the user-supplied plugin config block against this
133
- # manifest's `config_schema`. Returns an array of human-readable
134
- # error strings (empty when the config is valid). Slice 1 checks
135
- # only unknown keys and shallow value kind; nested schemas come
136
- # with later slices.
122
+ # Validates the user-supplied plugin config block against this manifest's `config_schema`. Returns an
123
+ # array of human-readable error strings (empty when the config is valid). Slice 1 checks only unknown
124
+ # keys and shallow value kind; nested schemas come with later slices.
137
125
  def validate_config(config)
138
126
  return ["plugin config must be a Hash, got #{config.class}"] unless config.is_a?(Hash)
139
127
 
@@ -226,9 +214,8 @@ module Rigor
226
214
  end
227
215
  end
228
216
 
229
- # ADR-40 — a `config_schema` value is either a bare kind
230
- # (`Symbol`/`String`, the original form) or a `{kind:, default:}`
231
- # Hash. These three helpers read whichever shape was given.
217
+ # ADR-40 — a `config_schema` value is either a bare kind (`Symbol`/`String`, the original form) or a
218
+ # `{kind:, default:}` Hash. These three helpers read whichever shape was given.
232
219
  def schema_kind(value)
233
220
  if value.is_a?(Hash)
234
221
  kind = value[:kind] || value["kind"]
@@ -277,10 +264,9 @@ module Rigor
277
264
  end
278
265
  end
279
266
 
280
- # Shared shape check for the Array-of-X manifest fields. Every entry
281
- # must satisfy the block; otherwise raise the uniform "must be an
282
- # Array of <label>" message. Centralises the message format the
283
- # field validators below share so it cannot drift between them.
267
+ # Shared shape check for the Array-of-X manifest fields. Every entry must satisfy the block; otherwise
268
+ # raise the uniform "must be an Array of <label>" message. Centralises the message format the field
269
+ # validators below share so it cannot drift between them.
284
270
  def validate_array_of!(field, value, label, &)
285
271
  return if value.is_a?(Array) && value.all?(&)
286
272
 
@@ -291,73 +277,56 @@ module Rigor
291
277
  validate_array_of!("produces", produces, "Symbol/String") { |p| p.is_a?(Symbol) || p.is_a?(String) }
292
278
  end
293
279
 
294
- # ADR-10 5a — `owns_receivers:` declares the class names
295
- # this plugin claims sole ownership of. The dispatcher's
296
- # dependency-source-inference tier consults this list
297
- # before consulting its own catalog: receivers owned by a
298
- # registered plugin (directly or via subclass) decline,
299
- # so plugin contributions stay authoritative for those
300
- # types.
280
+ # ADR-10 5a — `owns_receivers:` declares the class names this plugin claims sole ownership of. The
281
+ # dispatcher's dependency-source-inference tier consults this list before consulting its own catalog:
282
+ # receivers owned by a registered plugin (directly or via subclass) decline, so plugin contributions
283
+ # stay authoritative for those types.
301
284
  def validate_owns_receivers!(owns_receivers)
302
285
  validate_array_of!("owns_receivers", owns_receivers, "non-empty String") { |c| c.is_a?(String) && !c.empty? }
303
286
  end
304
287
 
305
- # ADR-26 — `open_receivers:` declares the class names this
306
- # plugin marks as "open": statically known to respond beyond
307
- # their RBS-declared method surface (e.g. `ActiveRecord::Relation`,
308
- # which delegates an unbounded set of user-defined scopes to
309
- # its model). `Analysis::CheckRules` skips the
310
- # `call.undefined-method` rule for a receiver whose class any
311
- # loaded plugin lists here — flagging a method on a class
312
- # with an open dynamic surface is unsound. Distinct from
313
- # `owns_receivers:` (which routes dispatch); this one only
314
- # suppresses the diagnostic.
288
+ # ADR-26 — `open_receivers:` declares the class names this plugin marks as "open": statically known to
289
+ # respond beyond their RBS-declared method surface (e.g. `ActiveRecord::Relation`, which delegates an
290
+ # unbounded set of user-defined scopes to its model). `Analysis::CheckRules` skips the
291
+ # `call.undefined-method` rule for a receiver whose class any loaded plugin lists here — flagging a
292
+ # method on a class with an open dynamic surface is unsound. Distinct from `owns_receivers:` (which
293
+ # routes dispatch); this one only suppresses the diagnostic.
315
294
  def validate_open_receivers!(open_receivers)
316
295
  validate_array_of!("open_receivers", open_receivers, "non-empty String") { |c| c.is_a?(String) && !c.empty? }
317
296
  end
318
297
 
319
- # ADR-13 slice 2 — `type_node_resolvers:` declares the
320
- # plugin-supplied `TypeNodeResolver` instances the parser
321
- # consults (in slice 3) when an RBS::Extended payload's
322
- # named- or generic-type head misses the built-in registry.
323
- # Slice 2 carries the declarations on the manifest and the
324
- # registry exposes them in registration order; the parser
325
- # integration that actually drives the chain lands in
326
- # slice 3.
298
+ # ADR-13 slice 2 — `type_node_resolvers:` declares the plugin-supplied `TypeNodeResolver` instances the
299
+ # parser consults (in slice 3) when an RBS::Extended payload's named- or generic-type head misses the
300
+ # built-in registry. Slice 2 carries the declarations on the manifest and the registry exposes them in
301
+ # registration order; the parser integration that actually drives the chain lands in slice 3.
327
302
  def validate_type_node_resolvers!(resolvers)
328
303
  validate_array_of!("type_node_resolvers", resolvers, "Rigor::Plugin::TypeNodeResolver instances") do |r|
329
304
  r.is_a?(TypeNodeResolver)
330
305
  end
331
306
  end
332
307
 
333
- # ADR-16 slice 1a — `block_as_methods:` declares the Tier A
334
- # substrate entries the plugin contributes. Slice 1a carries
335
- # the declarations on the manifest; the engine hook that
336
- # actually narrows `Scope#self_type` for matching blocks
337
- # arrives in a subsequent slice.
308
+ # ADR-16 slice 1a — `block_as_methods:` declares the Tier A substrate entries the plugin contributes.
309
+ # Slice 1a carries the declarations on the manifest; the engine hook that actually narrows
310
+ # `Scope#self_type` for matching blocks arrives in a subsequent slice.
338
311
  def validate_block_as_methods!(entries)
339
312
  validate_array_of!("block_as_methods", entries, "Rigor::Plugin::Macro::BlockAsMethod instances") do |e|
340
313
  e.is_a?(Macro::BlockAsMethod)
341
314
  end
342
315
  end
343
316
 
344
- # ADR-16 slice 2a — `heredoc_templates:` declares the Tier C
345
- # substrate entries (heredoc-template synthesis on class-level
346
- # DSL calls). Slice 2a carries the declarations on the
347
- # manifest; the pre-pass + `SyntheticMethodIndex` that actually
348
- # emit synthetic methods arrive in slice 2b.
317
+ # ADR-16 slice 2a — `heredoc_templates:` declares the Tier C substrate entries (heredoc-template
318
+ # synthesis on class-level DSL calls). Slice 2a carries the declarations on the manifest; the pre-pass +
319
+ # `SyntheticMethodIndex` that actually emit synthetic methods arrive in slice 2b.
349
320
  def validate_heredoc_templates!(entries)
350
321
  validate_array_of!("heredoc_templates", entries, "Rigor::Plugin::Macro::HeredocTemplate instances") do |e|
351
322
  e.is_a?(Macro::HeredocTemplate)
352
323
  end
353
324
  end
354
325
 
355
- # ADR-36 — `nested_class_templates:` declares the
356
- # nested-class emission tier (enum-shaped block DSLs that mint
357
- # nested subclasses, e.g. Mangrove's `variants do variant
358
- # Const, Type end`). The scanner synthesises the variant
359
- # subclasses + their `#inner` reader through the existing
360
- # `SyntheticMethodIndex` primitive.
326
+ # ADR-36 — `nested_class_templates:` declares the nested-class emission tier (enum-shaped block DSLs
327
+ # that mint nested subclasses, e.g. Mangrove's `variants do variant Const, Type end`). The scanner
328
+ # synthesises the variant subclasses + their `#inner` reader through the existing `SyntheticMethodIndex`
329
+ # primitive.
361
330
  def validate_nested_class_templates!(entries)
362
331
  validate_array_of!("nested_class_templates", entries,
363
332
  "Rigor::Plugin::Macro::NestedClassTemplate instances") do |e|
@@ -365,105 +334,77 @@ module Rigor
365
334
  end
366
335
  end
367
336
 
368
- # ADR-16 slice 3a — `trait_registries:` declares the Tier B
369
- # substrate entries (trait-inlining via bundled module
370
- # registry). Slice 3a carries the declarations on the
371
- # manifest; the scanner + per-method explosion through
372
- # `SyntheticMethodIndex` (slice 2b primitive) arrives in
373
- # slice 3b.
337
+ # ADR-16 slice 3a — `trait_registries:` declares the Tier B substrate entries (trait-inlining via
338
+ # bundled module registry). Slice 3a carries the declarations on the manifest; the scanner + per-method
339
+ # explosion through `SyntheticMethodIndex` (slice 2b primitive) arrives in slice 3b.
374
340
  def validate_trait_registries!(entries)
375
341
  validate_array_of!("trait_registries", entries, "Rigor::Plugin::Macro::TraitRegistry instances") do |e|
376
342
  e.is_a?(Macro::TraitRegistry)
377
343
  end
378
344
  end
379
345
 
380
- # ADR-20 slice 6 — `hkt_registrations:` declares the
381
- # Lightweight HKT URI registrations this plugin ships
382
- # (analogous to `%a{rigor:v1:hkt_register: ...}` directives
383
- # but published via the manifest contract instead of a
384
- # shipped `.rbs` file). Each entry MUST be an
385
- # `Rigor::Inference::HktRegistry::Registration`. The
386
- # registry aggregator on `Plugin::Registry` flattens
387
- # entries from every loaded plugin and merges them into
388
- # `env.hkt_registry` on top of `Builtins::HktBuiltins.registry`;
389
- # user `.rbs` overlays merge on top of plugin entries
390
- # last-write-wins.
346
+ # ADR-20 slice 6 — `hkt_registrations:` declares the Lightweight HKT URI registrations this plugin
347
+ # ships (analogous to `%a{rigor:v1:hkt_register: ...}` directives but published via the manifest
348
+ # contract instead of a shipped `.rbs` file). Each entry MUST be an
349
+ # `Rigor::Inference::HktRegistry::Registration`. The registry aggregator on `Plugin::Registry` flattens
350
+ # entries from every loaded plugin and merges them into `env.hkt_registry` on top of
351
+ # `Builtins::HktBuiltins.registry`; user `.rbs` overlays merge on top of plugin entries last-write-wins.
391
352
  def validate_hkt_registrations!(entries)
392
353
  validate_array_of!("hkt_registrations", entries, "Rigor::Inference::HktRegistry::Registration instances") do |e|
393
354
  e.is_a?(Inference::HktRegistry::Registration)
394
355
  end
395
356
  end
396
357
 
397
- # ADR-20 slice 6 — `hkt_definitions:` declares the
398
- # plugin's HKT type-function bodies (analogous to
399
- # `%a{rigor:v1:hkt_define: ...}` directives). Each entry
400
- # MUST be an `Rigor::Inference::HktRegistry::Definition`
401
- # typically built via
402
- # `Rigor::Inference::HktRegistry.definition_with_body_tree(...)`
403
- # so plugin authors can build the body programmatically
404
- # via {Rigor::Inference::HktBody}'s node-constructor API
405
- # without parsing a string.
358
+ # ADR-20 slice 6 — `hkt_definitions:` declares the plugin's HKT type-function bodies (analogous to
359
+ # `%a{rigor:v1:hkt_define: ...}` directives). Each entry MUST be an
360
+ # `Rigor::Inference::HktRegistry::Definition` typically built via
361
+ # `Rigor::Inference::HktRegistry.definition_with_body_tree(...)` so plugin authors can build the body
362
+ # programmatically via {Rigor::Inference::HktBody}'s node-constructor API without parsing a string.
406
363
  def validate_hkt_definitions!(entries)
407
364
  validate_array_of!("hkt_definitions", entries, "Rigor::Inference::HktRegistry::Definition instances") do |e|
408
365
  e.is_a?(Inference::HktRegistry::Definition)
409
366
  end
410
367
  end
411
368
 
412
- # ADR-25 — `signature_paths:` declares the RBS signature
413
- # directories this plugin gem ships, as paths relative to the
414
- # plugin's own gem root (e.g. `["sig"]`). `Plugin::Base#signature_paths`
415
- # resolves them to absolute dirs against the gem root; the
416
- # loader validates each exists and `Environment.for_project`
369
+ # ADR-25 — `signature_paths:` declares the RBS signature directories this plugin gem ships, as paths
370
+ # relative to the plugin's own gem root (e.g. `["sig"]`). `Plugin::Base#signature_paths` resolves them
371
+ # to absolute dirs against the gem root; the loader validates each exists and `Environment.for_project`
417
372
  # merges the resolved set into the RBS environment.
418
373
  def validate_signature_paths!(paths)
419
374
  validate_array_of!("signature_paths", paths, "non-empty String") { |p| p.is_a?(String) && !p.empty? }
420
375
  end
421
376
 
422
- # ADR-28 — `protocol_contracts:` declares the path-scoped
423
- # method-protocol contracts the plugin contributes. Each
424
- # entry MUST be a `Rigor::Plugin::ProtocolContract`. The
425
- # registry aggregator on `Plugin::Registry` flattens
426
- # contracts across loaded plugins; the engine consults them
427
- # in two places `MethodParameterBinder` provides the
428
- # declared parameter types into matching method bodies, and
429
- # the contributing plugin's `#diagnostics_for_file` checks
430
- # method presence + return-type conformance. The manifest
431
- # field carries the plugin's *default* contracts; a plugin
432
- # MAY override `Plugin::Base#protocol_contracts` to fold in
433
- # per-project config (e.g. a custom convention path).
377
+ # ADR-28 — `protocol_contracts:` declares the path-scoped method-protocol contracts the plugin
378
+ # contributes. Each entry MUST be a `Rigor::Plugin::ProtocolContract`. The registry aggregator on
379
+ # `Plugin::Registry` flattens contracts across loaded plugins; the engine consults them in two places —
380
+ # `MethodParameterBinder` provides the declared parameter types into matching method bodies, and the
381
+ # contributing plugin's `#diagnostics_for_file` checks method presence + return-type conformance. The
382
+ # manifest field carries the plugin's *default* contracts; a plugin MAY override
383
+ # `Plugin::Base#protocol_contracts` to fold in per-project config (e.g. a custom convention path).
434
384
  def validate_protocol_contracts!(entries)
435
385
  validate_array_of!("protocol_contracts", entries, "Rigor::Plugin::ProtocolContract instances") do |e|
436
386
  e.is_a?(ProtocolContract)
437
387
  end
438
388
  end
439
389
 
440
- # ADR-38 — `additional_initializers:` declares the
441
- # (receiver_constraint, methods) pairs whose `def`-form methods
442
- # the engine treats like `initialize` for the read-before-write
443
- # nil soundness gate. Each entry MUST be a
444
- # `Rigor::Plugin::AdditionalInitializer`. The registry
445
- # aggregator on `Plugin::Registry` flattens entries across
446
- # loaded plugins; `Inference::ScopeIndexer` consults the set at
447
- # its single gate.
390
+ # ADR-38 — `additional_initializers:` declares the (receiver_constraint, methods) pairs whose `def`-form
391
+ # methods the engine treats like `initialize` for the read-before-write nil soundness gate. Each entry
392
+ # MUST be a `Rigor::Plugin::AdditionalInitializer`. The registry aggregator on `Plugin::Registry`
393
+ # flattens entries across loaded plugins; `Inference::ScopeIndexer` consults the set at its single gate.
448
394
  def validate_additional_initializers!(entries)
449
395
  validate_array_of!("additional_initializers", entries, "Rigor::Plugin::AdditionalInitializer instances") do |e|
450
396
  e.is_a?(AdditionalInitializer)
451
397
  end
452
398
  end
453
399
 
454
- # ADR-32 WD4 — `source_rbs_synthesizer:` declares a callable
455
- # the engine invokes once per analysed Ruby source file at
456
- # env-build time. The callable receives a source file path
457
- # (String) and returns either an RBS source String to merge
458
- # into the analysis environment or `nil` (no contribution
459
- # for this file). Distinct from `signature_paths:` (static,
460
- # bundled RBS): the synthesizer derives RBS from project
400
+ # ADR-32 WD4 — `source_rbs_synthesizer:` declares a callable the engine invokes once per analysed Ruby
401
+ # source file at env-build time. The callable receives a source file path (String) and returns either
402
+ # an RBS source String to merge into the analysis environment or `nil` (no contribution for this file).
403
+ # Distinct from `signature_paths:` (static, bundled RBS): the synthesizer derives RBS from project
461
404
  # source on each run.
462
405
  #
463
- # The value is held as-given (no dup / freeze) because a
464
- # callable instance is opaque to the manifest; the plugin
465
- # author is responsible for thread-/Ractor-safety of any
466
- # captured state (per ADR-15).
406
+ # The value is held as-given (no dup / freeze) because a callable instance is opaque to the manifest;
407
+ # the plugin author is responsible for thread-/Ractor-safety of any captured state (per ADR-15).
467
408
  def validate_source_rbs_synthesizer!(synthesizer)
468
409
  return if synthesizer.nil?
469
410
  return if synthesizer.respond_to?(:call)