rigortype 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (634) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/data/capability_roles/capability_roles.rbs +36 -0
  4. data/data/core_overlay/enumerable.rbs +51 -0
  5. data/data/core_overlay/enumerator.rbs +84 -0
  6. data/data/core_overlay/hash_rbs3.rbs +41 -0
  7. data/data/core_overlay/process.rbs +40 -0
  8. data/data/core_overlay/string_io.rbs +33 -0
  9. data/data/effects/core.yml +3 -3
  10. data/data/gem_overlay/activesupport/core_ext.rbs +236 -17
  11. data/docs/handbook/02-everyday-types.md +17 -14
  12. data/docs/handbook/03-narrowing.md +132 -14
  13. data/docs/handbook/04-tuples-and-shapes.md +8 -6
  14. data/docs/handbook/05-methods-and-blocks.md +1 -1
  15. data/docs/handbook/06-classes.md +2 -2
  16. data/docs/handbook/07-rbs-and-extended.md +19 -1
  17. data/docs/handbook/10-sorbet.md +9 -10
  18. data/docs/handbook/11-sig-gen.md +525 -13
  19. data/docs/handbook/README.md +1 -1
  20. data/docs/handbook/appendix-elixir.md +2 -2
  21. data/docs/handbook/appendix-go.md +2 -2
  22. data/docs/handbook/appendix-java-csharp.md +2 -2
  23. data/docs/handbook/appendix-mypy.md +2 -2
  24. data/docs/handbook/appendix-phpstan.md +1 -1
  25. data/docs/handbook/appendix-rust.md +1 -1
  26. data/docs/handbook/appendix-type-theory.md +4 -4
  27. data/docs/handbook/appendix-typescript.md +1 -1
  28. data/docs/llms.txt +2 -0
  29. data/docs/manual/02-cli-reference.md +95 -6
  30. data/docs/manual/03-configuration.md +18 -0
  31. data/docs/manual/04-diagnostics.md +15 -0
  32. data/docs/manual/07-plugins.md +15 -5
  33. data/docs/manual/08-skills.md +23 -2
  34. data/docs/manual/10-mcp-server.md +3 -2
  35. data/docs/manual/11-ci.md +9 -0
  36. data/docs/manual/15-type-protection-coverage.md +8 -0
  37. data/docs/manual/16-rbs-extended-annotations.md +46 -8
  38. data/docs/manual/18-removing-dead-code.md +10 -8
  39. data/docs/manual/19-effect-labels.md +10 -0
  40. data/docs/manual/plugins/README.md +7 -0
  41. data/docs/manual/plugins/rigor-actioncable.md +8 -1
  42. data/docs/manual/plugins/rigor-actionmailer.md +7 -0
  43. data/docs/manual/plugins/rigor-actionpack.md +261 -0
  44. data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
  45. data/docs/manual/plugins/rigor-activejob.md +7 -0
  46. data/docs/manual/plugins/rigor-activerecord.md +138 -4
  47. data/docs/manual/plugins/rigor-activestorage.md +8 -1
  48. data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
  49. data/docs/manual/plugins/rigor-grape.md +106 -0
  50. data/docs/manual/plugins/rigor-graphql.md +23 -2
  51. data/docs/manual/plugins/rigor-pundit.md +8 -1
  52. data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
  53. data/docs/manual/plugins/rigor-rails-routes.md +7 -0
  54. data/docs/manual/plugins/rigor-rbs-inline.md +229 -1
  55. data/docs/manual/plugins/rigor-sidekiq.md +8 -1
  56. data/docs/manual/plugins/rigor-sorbet.md +21 -5
  57. data/exe/rigor +19 -4
  58. data/lib/rigor/analysis/baseline.rb +3 -3
  59. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
  60. data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
  61. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
  62. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
  63. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
  64. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
  65. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
  66. data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
  67. data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
  68. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
  69. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -1
  70. data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
  71. data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
  72. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +38 -4
  73. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
  74. data/lib/rigor/analysis/check_rules.rb +718 -79
  75. data/lib/rigor/analysis/crash_signature.rb +8 -24
  76. data/lib/rigor/analysis/dependency_recorder.rb +23 -0
  77. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
  78. data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
  79. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
  80. data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
  81. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
  82. data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
  83. data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
  84. data/lib/rigor/analysis/erb_template_detector.rb +1 -2
  85. data/lib/rigor/analysis/fact_store.rb +15 -1
  86. data/lib/rigor/analysis/incremental.rb +42 -0
  87. data/lib/rigor/analysis/incremental_session.rb +117 -26
  88. data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
  89. data/lib/rigor/analysis/project_scan.rb +11 -1
  90. data/lib/rigor/analysis/reachability/graph.rb +3 -5
  91. data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
  92. data/lib/rigor/analysis/reachability/project_files.rb +2 -2
  93. data/lib/rigor/analysis/reachability/scan.rb +5 -5
  94. data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
  95. data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
  96. data/lib/rigor/analysis/result.rb +1 -3
  97. data/lib/rigor/analysis/rule_catalog.rb +131 -1
  98. data/lib/rigor/analysis/run_cache_key.rb +21 -12
  99. data/lib/rigor/analysis/run_cache_probe.rb +3 -5
  100. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
  101. data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
  102. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
  103. data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
  104. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
  105. data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
  106. data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
  107. data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
  108. data/lib/rigor/analysis/runner.rb +407 -51
  109. data/lib/rigor/analysis/template_unit_collector.rb +303 -0
  110. data/lib/rigor/analysis/template_unit_paths.rb +91 -0
  111. data/lib/rigor/analysis/template_unit_positions.rb +293 -0
  112. data/lib/rigor/analysis/template_units.rb +399 -0
  113. data/lib/rigor/analysis/worker_session.rb +62 -20
  114. data/lib/rigor/bleeding_edge.rb +10 -24
  115. data/lib/rigor/builtins/hkt_builtins.rb +3 -2
  116. data/lib/rigor/builtins/imported_refinements.rb +159 -21
  117. data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
  118. data/lib/rigor/builtins/regex_refinement.rb +21 -13
  119. data/lib/rigor/builtins/static_return_refinements.rb +7 -6
  120. data/lib/rigor/cache/annotation_location.rb +2 -4
  121. data/lib/rigor/cache/descriptor.rb +63 -20
  122. data/lib/rigor/cache/engine_source.rb +33 -5
  123. data/lib/rigor/cache/file_digest.rb +9 -1
  124. data/lib/rigor/cache/incremental_snapshot.rb +72 -6
  125. data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
  126. data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
  127. data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
  128. data/lib/rigor/cache/rbs_constant_table.rb +0 -3
  129. data/lib/rigor/cache/rbs_descriptor.rb +112 -14
  130. data/lib/rigor/cache/rbs_environment.rb +8 -4
  131. data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
  132. data/lib/rigor/cache/store.rb +76 -32
  133. data/lib/rigor/ci_detector.rb +1 -0
  134. data/lib/rigor/cli/annotate_command.rb +5 -6
  135. data/lib/rigor/cli/check_command.rb +57 -10
  136. data/lib/rigor/cli/check_invocation.rb +6 -11
  137. data/lib/rigor/cli/check_runner_factory.rb +1 -5
  138. data/lib/rigor/cli/coverage_command.rb +1 -1
  139. data/lib/rigor/cli/coverage_mutation.rb +12 -3
  140. data/lib/rigor/cli/coverage_scan.rb +1 -5
  141. data/lib/rigor/cli/diff_command.rb +1 -1
  142. data/lib/rigor/cli/doc_links.rb +4 -4
  143. data/lib/rigor/cli/docs_command.rb +6 -6
  144. data/lib/rigor/cli/doctor_command.rb +85 -38
  145. data/lib/rigor/cli/effects_command.rb +2 -2
  146. data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
  147. data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
  148. data/lib/rigor/cli/explain_command.rb +34 -1
  149. data/lib/rigor/cli/fused_protection_report.rb +7 -1
  150. data/lib/rigor/cli/lsp_command.rb +1 -1
  151. data/lib/rigor/cli/mcp_command.rb +1 -1
  152. data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
  153. data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
  154. data/lib/rigor/cli/mutation_protection_report.rb +7 -1
  155. data/lib/rigor/cli/plugin_command.rb +4 -4
  156. data/lib/rigor/cli/plugins_command.rb +2 -1
  157. data/lib/rigor/cli/prism_colorizer.rb +1 -2
  158. data/lib/rigor/cli/protection_fork_scan.rb +6 -6
  159. data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
  160. data/lib/rigor/cli/sig_gen_command.rb +212 -31
  161. data/lib/rigor/cli/skill_command.rb +2 -2
  162. data/lib/rigor/cli/skill_deep_probe.rb +4 -4
  163. data/lib/rigor/cli/skill_describe.rb +35 -35
  164. data/lib/rigor/cli/trace_command.rb +4 -4
  165. data/lib/rigor/cli/trace_renderer.rb +5 -6
  166. data/lib/rigor/cli/triage_command.rb +1 -1
  167. data/lib/rigor/cli/type_of_command.rb +29 -11
  168. data/lib/rigor/cli/type_of_renderer.rb +20 -9
  169. data/lib/rigor/cli/type_of_template_probe.rb +189 -0
  170. data/lib/rigor/cli/type_scan_command.rb +4 -4
  171. data/lib/rigor/cli/unused_command.rb +11 -3
  172. data/lib/rigor/cli/upgrade_command.rb +1 -1
  173. data/lib/rigor/cli.rb +89 -9
  174. data/lib/rigor/config_audit.rb +30 -5
  175. data/lib/rigor/configuration/severity_profile.rb +25 -9
  176. data/lib/rigor/configuration.rb +109 -7
  177. data/lib/rigor/effects/ancestry_recorder.rb +191 -0
  178. data/lib/rigor/effects/attribution.rb +12 -5
  179. data/lib/rigor/effects/callee_rule.rb +368 -0
  180. data/lib/rigor/effects/catalog.rb +7 -4
  181. data/lib/rigor/effects/collector.rb +11 -5
  182. data/lib/rigor/effects/config_envelopes.rb +15 -10
  183. data/lib/rigor/effects/definition_context.rb +179 -0
  184. data/lib/rigor/effects/definition_lines.rb +25 -6
  185. data/lib/rigor/effects/effect_table.rb +11 -4
  186. data/lib/rigor/effects/entry_points.rb +0 -2
  187. data/lib/rigor/effects/envelope_check.rb +9 -9
  188. data/lib/rigor/effects/envelope_index.rb +20 -8
  189. data/lib/rigor/effects/file_collection.rb +59 -5
  190. data/lib/rigor/effects/framework_units.rb +5 -7
  191. data/lib/rigor/effects/identity.rb +20 -6
  192. data/lib/rigor/effects/inline_anchor.rb +7 -7
  193. data/lib/rigor/effects/label_intent.rb +3 -4
  194. data/lib/rigor/effects/liskov_check.rb +8 -8
  195. data/lib/rigor/effects/local_ownership.rb +38 -12
  196. data/lib/rigor/effects/method_key.rb +22 -1
  197. data/lib/rigor/effects/mutation_classifier.rb +23 -12
  198. data/lib/rigor/effects/plugin_facts.rb +47 -37
  199. data/lib/rigor/effects/propagator.rb +297 -19
  200. data/lib/rigor/effects/registry.rb +1 -1
  201. data/lib/rigor/effects/scanner.rb +122 -73
  202. data/lib/rigor/effects/signature_sources.rb +4 -6
  203. data/lib/rigor/effects/snapshot.rb +12 -11
  204. data/lib/rigor/effects/snapshot_diff.rb +1 -1
  205. data/lib/rigor/effects/summary.rb +27 -4
  206. data/lib/rigor/effects/unit_scan.rb +393 -38
  207. data/lib/rigor/effects/unknown_label_check.rb +3 -8
  208. data/lib/rigor/effects/unknown_label_report.rb +3 -4
  209. data/lib/rigor/effects/visibility.rb +101 -0
  210. data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
  211. data/lib/rigor/environment/class_registry.rb +3 -1
  212. data/lib/rigor/environment/failure_slot.rb +2 -2
  213. data/lib/rigor/environment/installed_gem_set.rb +85 -0
  214. data/lib/rigor/environment/lockfile_resolver.rb +68 -4
  215. data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
  216. data/lib/rigor/environment/member_consistency.rb +298 -0
  217. data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
  218. data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
  219. data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
  220. data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
  221. data/lib/rigor/environment/rbs_loader.rb +674 -79
  222. data/lib/rigor/environment.rb +174 -24
  223. data/lib/rigor/flow_contribution/merger.rb +0 -2
  224. data/lib/rigor/flow_contribution.rb +11 -13
  225. data/lib/rigor/hashing/xxh3.rb +264 -0
  226. data/lib/rigor/inference/acceptance.rb +292 -17
  227. data/lib/rigor/inference/block_auto_splat.rb +216 -0
  228. data/lib/rigor/inference/block_call_timing.rb +338 -0
  229. data/lib/rigor/inference/block_parameter_binder.rb +75 -30
  230. data/lib/rigor/inference/block_repetition.rb +71 -0
  231. data/lib/rigor/inference/body_fixpoint.rb +7 -6
  232. data/lib/rigor/inference/budget_trace.rb +3 -6
  233. data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
  234. data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
  235. data/lib/rigor/inference/captured_locals.rb +389 -18
  236. data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
  237. data/lib/rigor/inference/content_join.rb +200 -27
  238. data/lib/rigor/inference/coverage_scanner.rb +4 -6
  239. data/lib/rigor/inference/def_return_typer.rb +11 -7
  240. data/lib/rigor/inference/define_method_block_self.rb +64 -0
  241. data/lib/rigor/inference/dynamic_origin.rb +1 -1
  242. data/lib/rigor/inference/element_read_widening.rb +180 -0
  243. data/lib/rigor/inference/error_info.rb +196 -0
  244. data/lib/rigor/inference/expression_typer.rb +2124 -468
  245. data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
  246. data/lib/rigor/inference/fork_map.rb +5 -7
  247. data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
  248. data/lib/rigor/inference/global_write_census.rb +239 -0
  249. data/lib/rigor/inference/guard_rebinding.rb +447 -0
  250. data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
  251. data/lib/rigor/inference/hkt_reducer.rb +2 -3
  252. data/lib/rigor/inference/hkt_registry.rb +4 -7
  253. data/lib/rigor/inference/index_write_widening.rb +16 -7
  254. data/lib/rigor/inference/indexed_narrowing.rb +61 -9
  255. data/lib/rigor/inference/jump_targets.rb +82 -0
  256. data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
  257. data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
  258. data/lib/rigor/inference/last_line.rb +340 -0
  259. data/lib/rigor/inference/last_status.rb +144 -0
  260. data/lib/rigor/inference/macro_block_self_type.rb +168 -21
  261. data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
  262. data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
  263. data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
  264. data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
  265. data/lib/rigor/inference/match_rebinding.rb +392 -0
  266. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
  267. data/lib/rigor/inference/method_dispatcher/block_folding.rb +87 -33
  268. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
  269. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
  270. data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
  271. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
  272. data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
  273. data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
  274. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
  275. data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
  276. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
  277. data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
  278. data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
  279. data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
  280. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
  281. data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
  282. data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
  283. data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
  284. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
  285. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
  286. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
  287. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
  288. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
  289. data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
  290. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
  291. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
  292. data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
  293. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
  294. data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
  295. data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
  296. data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
  297. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
  298. data/lib/rigor/inference/method_dispatcher.rb +225 -25
  299. data/lib/rigor/inference/method_parameter_binder.rb +12 -9
  300. data/lib/rigor/inference/multi_target_binder.rb +341 -55
  301. data/lib/rigor/inference/mutation_rejoin.rb +171 -0
  302. data/lib/rigor/inference/mutation_widening.rb +156 -85
  303. data/lib/rigor/inference/narrowing.rb +835 -162
  304. data/lib/rigor/inference/operand_effects.rb +167 -0
  305. data/lib/rigor/inference/operand_walk.rb +88 -0
  306. data/lib/rigor/inference/optimistic_origin.rb +153 -16
  307. data/lib/rigor/inference/origin_lookup.rb +2 -3
  308. data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
  309. data/lib/rigor/inference/pre_eval_constants.rb +6 -5
  310. data/lib/rigor/inference/precision_scanner.rb +3 -4
  311. data/lib/rigor/inference/project_method_ownership.rb +136 -0
  312. data/lib/rigor/inference/project_patched_methods.rb +9 -4
  313. data/lib/rigor/inference/project_patched_scanner.rb +10 -6
  314. data/lib/rigor/inference/protection_scanner.rb +1 -2
  315. data/lib/rigor/inference/range_constant.rb +57 -0
  316. data/lib/rigor/inference/rbs_type_translator.rb +49 -11
  317. data/lib/rigor/inference/receiver_alias.rb +93 -4
  318. data/lib/rigor/inference/receiver_blind_block.rb +219 -0
  319. data/lib/rigor/inference/refinement_mutation.rb +76 -0
  320. data/lib/rigor/inference/repeated_or_writes.rb +463 -0
  321. data/lib/rigor/inference/return_barrier.rb +54 -0
  322. data/lib/rigor/inference/rewrite_mutation.rb +120 -0
  323. data/lib/rigor/inference/scope_indexer.rb +5228 -627
  324. data/lib/rigor/inference/statement_evaluator.rb +3452 -595
  325. data/lib/rigor/inference/stored_block_call.rb +54 -0
  326. data/lib/rigor/inference/string_mutation.rb +97 -0
  327. data/lib/rigor/inference/struct_fold_safety.rb +6 -7
  328. data/lib/rigor/inference/synthetic_method_index.rb +1 -2
  329. data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
  330. data/lib/rigor/inference/unknown_store_widening.rb +200 -0
  331. data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
  332. data/lib/rigor/inference/version_guard.rb +28 -21
  333. data/lib/rigor/inference/void_origin.rb +3 -3
  334. data/lib/rigor/inference/void_tail_summary.rb +2 -4
  335. data/lib/rigor/language_server/buffer_table.rb +4 -4
  336. data/lib/rigor/language_server/completion_provider.rb +1 -1
  337. data/lib/rigor/language_server/debouncer.rb +0 -1
  338. data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
  339. data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
  340. data/lib/rigor/language_server/folding_range_provider.rb +1 -1
  341. data/lib/rigor/language_server/hover_provider.rb +1 -1
  342. data/lib/rigor/language_server/hover_renderer.rb +4 -4
  343. data/lib/rigor/language_server/incremental_sync.rb +6 -6
  344. data/lib/rigor/language_server/project_context.rb +7 -8
  345. data/lib/rigor/language_server/publish_batcher.rb +2 -2
  346. data/lib/rigor/language_server/selection_range_provider.rb +2 -2
  347. data/lib/rigor/language_server/server.rb +9 -9
  348. data/lib/rigor/language_server/signature_help_provider.rb +1 -1
  349. data/lib/rigor/language_server/uri.rb +1 -1
  350. data/lib/rigor/mcp/server.rb +2 -1
  351. data/lib/rigor/plugin/base.rb +258 -26
  352. data/lib/rigor/plugin/box_probe.rb +91 -0
  353. data/lib/rigor/plugin/bundled_catalog.rb +167 -0
  354. data/lib/rigor/plugin/effect_attribution.rb +65 -11
  355. data/lib/rigor/plugin/effect_entry_points.rb +3 -3
  356. data/lib/rigor/plugin/fact_store.rb +6 -6
  357. data/lib/rigor/plugin/io_boundary.rb +93 -8
  358. data/lib/rigor/plugin/isolation.rb +29 -6
  359. data/lib/rigor/plugin/loader.rb +33 -13
  360. data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
  361. data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
  362. data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
  363. data/lib/rigor/plugin/manifest.rb +94 -11
  364. data/lib/rigor/plugin/registry.rb +76 -12
  365. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
  366. data/lib/rigor/plugin/template_unit.rb +196 -0
  367. data/lib/rigor/plugin/trust_policy.rb +2 -4
  368. data/lib/rigor/plugin/type_node_resolver.rb +3 -3
  369. data/lib/rigor/plugin.rb +1 -0
  370. data/lib/rigor/plugin_gap_advisory.rb +96 -0
  371. data/lib/rigor/project_environment.rb +138 -0
  372. data/lib/rigor/protection/analysis_guard.rb +93 -14
  373. data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
  374. data/lib/rigor/protection/dependency_closure.rb +5 -8
  375. data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
  376. data/lib/rigor/protection/discovery_seed.rb +14 -12
  377. data/lib/rigor/protection/kill_signature.rb +1 -4
  378. data/lib/rigor/protection/measurement_integrity.rb +1 -3
  379. data/lib/rigor/protection/mutation_cache.rb +7 -11
  380. data/lib/rigor/protection/mutation_scanner.rb +12 -15
  381. data/lib/rigor/protection/mutator.rb +2 -1
  382. data/lib/rigor/protection/test_suite_oracle.rb +5 -5
  383. data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
  384. data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
  385. data/lib/rigor/rbs_extended/reporter.rb +36 -10
  386. data/lib/rigor/rbs_extended.rb +88 -21
  387. data/lib/rigor/reflection/constant_ancestors.rb +97 -0
  388. data/lib/rigor/reflection/constant_path.rb +139 -0
  389. data/lib/rigor/reflection.rb +93 -110
  390. data/lib/rigor/runtime/jit.rb +6 -8
  391. data/lib/rigor/scope/discovery_index.rb +165 -2
  392. data/lib/rigor/scope.rb +1041 -32
  393. data/lib/rigor/sig_gen/alias_index.rb +289 -0
  394. data/lib/rigor/sig_gen/classification.rb +22 -5
  395. data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
  396. data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
  397. data/lib/rigor/sig_gen/generator.rb +673 -53
  398. data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
  399. data/lib/rigor/sig_gen/layout_index.rb +3 -4
  400. data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
  401. data/lib/rigor/sig_gen/method_candidate.rb +47 -3
  402. data/lib/rigor/sig_gen/observation_collector.rb +18 -16
  403. data/lib/rigor/sig_gen/path_mapper.rb +4 -6
  404. data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
  405. data/lib/rigor/sig_gen/renderer.rb +128 -14
  406. data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
  407. data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
  408. data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
  409. data/lib/rigor/sig_gen/write_result.rb +19 -3
  410. data/lib/rigor/sig_gen/writer.rb +189 -41
  411. data/lib/rigor/sig_gen.rb +3 -0
  412. data/lib/rigor/signature_path_audit.rb +153 -6
  413. data/lib/rigor/source/literals.rb +0 -23
  414. data/lib/rigor/source/node_children.rb +0 -2
  415. data/lib/rigor/source/node_locator.rb +5 -11
  416. data/lib/rigor/source/node_walker.rb +0 -6
  417. data/lib/rigor/source/parameter_envelope.rb +72 -0
  418. data/lib/rigor/source.rb +1 -0
  419. data/lib/rigor/triage/catalogue.rb +1 -3
  420. data/lib/rigor/triage.rb +3 -5
  421. data/lib/rigor/type/accepts_result.rb +24 -6
  422. data/lib/rigor/type/combinator.rb +144 -5
  423. data/lib/rigor/type/data_class.rb +2 -2
  424. data/lib/rigor/type/data_instance.rb +4 -4
  425. data/lib/rigor/type/difference.rb +1 -0
  426. data/lib/rigor/type/float_range.rb +128 -0
  427. data/lib/rigor/type/hash_shape.rb +6 -6
  428. data/lib/rigor/type/integer_range.rb +13 -8
  429. data/lib/rigor/type/nominal.rb +8 -2
  430. data/lib/rigor/type/refined.rb +4 -3
  431. data/lib/rigor/type/struct_class.rb +3 -3
  432. data/lib/rigor/type/struct_instance.rb +4 -4
  433. data/lib/rigor/type.rb +1 -0
  434. data/lib/rigor/type_node/generic.rb +1 -1
  435. data/lib/rigor/type_node/range_literal.rb +25 -0
  436. data/lib/rigor/type_node/resolver_chain.rb +1 -1
  437. data/lib/rigor/type_node.rb +1 -0
  438. data/lib/rigor/version.rb +1 -1
  439. data/lib/rigor.rb +1 -0
  440. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
  441. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
  442. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
  443. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
  444. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
  445. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
  446. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
  447. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
  448. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
  449. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
  450. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
  451. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
  452. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
  453. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
  454. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
  455. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
  456. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
  457. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
  458. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +264 -3
  459. data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
  460. data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
  461. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
  462. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
  463. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
  464. data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
  465. data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
  466. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
  467. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
  468. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
  469. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
  470. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
  471. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -5
  472. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
  473. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
  474. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +383 -7
  475. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
  476. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
  477. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
  478. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
  479. data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
  480. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
  481. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
  482. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
  483. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
  484. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
  485. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
  486. data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
  487. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
  488. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
  489. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
  490. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
  491. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
  492. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
  493. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
  494. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
  495. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
  496. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
  497. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
  498. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
  499. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
  500. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
  501. data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
  502. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
  503. data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
  504. data/plugins/rigor-grape/sig/grape.rbs +263 -0
  505. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
  506. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
  507. data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
  508. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
  509. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
  510. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
  511. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
  512. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
  513. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
  514. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
  515. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
  516. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
  517. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
  518. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
  519. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
  520. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
  521. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
  522. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
  523. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
  524. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
  525. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
  526. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
  527. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
  528. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
  529. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
  530. data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
  531. data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
  532. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
  533. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +324 -18
  534. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
  535. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
  536. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
  537. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
  538. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
  539. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
  540. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
  541. data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
  542. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
  543. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
  544. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
  545. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
  546. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
  547. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
  548. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
  549. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
  550. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
  551. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
  552. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
  553. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
  554. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
  555. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
  556. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
  557. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
  558. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
  559. data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
  560. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
  561. data/sig/rigor/analysis/baseline.rbs +69 -7
  562. data/sig/rigor/analysis/fact_store.rbs +1 -1
  563. data/sig/rigor/analysis/project_scan.rbs +74 -0
  564. data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
  565. data/sig/rigor/cache.rbs +2 -3
  566. data/sig/rigor/effects/config_envelopes.rbs +100 -0
  567. data/sig/rigor/effects/effect_table.rbs +60 -0
  568. data/sig/rigor/effects/envelope.rbs +97 -0
  569. data/sig/rigor/effects/envelope_index.rbs +33 -0
  570. data/sig/rigor/effects/file_collection.rbs +81 -0
  571. data/sig/rigor/effects/label.rbs +26 -0
  572. data/sig/rigor/effects/label_set.rbs +46 -0
  573. data/sig/rigor/effects/method_key.rbs +24 -0
  574. data/sig/rigor/effects/origin.rbs +50 -0
  575. data/sig/rigor/effects/plugin_facts.rbs +141 -0
  576. data/sig/rigor/effects/registry.rbs +68 -0
  577. data/sig/rigor/effects/summary.rbs +50 -0
  578. data/sig/rigor/effects/taint_cause.rbs +12 -0
  579. data/sig/rigor/environment.rbs +17 -10
  580. data/sig/rigor/inference/optimistic_origin.rbs +10 -0
  581. data/sig/rigor/inference.rbs +9 -14
  582. data/sig/rigor/plugin/additional_initializer.rbs +36 -0
  583. data/sig/rigor/plugin/base.rbs +30 -7
  584. data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
  585. data/sig/rigor/plugin/effect_attribution.rbs +66 -0
  586. data/sig/rigor/plugin/effect_edge.rbs +33 -0
  587. data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
  588. data/sig/rigor/plugin/io_boundary.rbs +4 -0
  589. data/sig/rigor/plugin/loader.rbs +3 -3
  590. data/sig/rigor/plugin/manifest.rbs +51 -11
  591. data/sig/rigor/plugin/protocol_contract.rbs +68 -0
  592. data/sig/rigor/plugin/registry.rbs +62 -1
  593. data/sig/rigor/plugin.rbs +1 -1
  594. data/sig/rigor/rbs_extended.rbs +1 -1
  595. data/sig/rigor/reflection.rbs +9 -6
  596. data/sig/rigor/scope.rbs +148 -12
  597. data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
  598. data/sig/rigor/source.rbs +4 -4
  599. data/sig/rigor/testing.rbs +10 -4
  600. data/sig/rigor/type.rbs +33 -1
  601. data/sig/rigor.rbs +39 -20
  602. data/skills/rigor-ask/SKILL.md +16 -11
  603. data/skills/rigor-baseline-reduce/SKILL.md +4 -6
  604. data/skills/rigor-ci-setup/SKILL.md +17 -21
  605. data/skills/rigor-doctor/SKILL.md +24 -22
  606. data/skills/rigor-doctor/references/01-checks.md +97 -33
  607. data/skills/rigor-editor-setup/SKILL.md +6 -4
  608. data/skills/rigor-mcp-setup/SKILL.md +5 -4
  609. data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
  610. data/skills/rigor-next-steps/SKILL.md +4 -2
  611. data/skills/rigor-plugin-author/SKILL.md +19 -23
  612. data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
  613. data/skills/rigor-plugin-author/references/02-walker-and-types.md +25 -27
  614. data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
  615. data/skills/rigor-plugin-review/SKILL.md +6 -4
  616. data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
  617. data/skills/rigor-plugin-tune/SKILL.md +4 -2
  618. data/skills/rigor-project-init/SKILL.md +15 -10
  619. data/skills/rigor-project-init/references/01-detect.md +13 -9
  620. data/skills/rigor-project-init/references/02-configure.md +43 -14
  621. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
  622. data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
  623. data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
  624. data/skills/rigor-protection-uplift/SKILL.md +4 -6
  625. data/skills/rigor-rbs-setup/SKILL.md +4 -2
  626. data/skills/rigor-type-oracle/SKILL.md +226 -0
  627. data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
  628. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
  629. data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
  630. data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
  631. data/skills/rigor-upgrade/SKILL.md +13 -8
  632. metadata +133 -3
  633. data/lib/rigor/cli/probe_environment.rb +0 -85
  634. data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: rigor-mcp-setup
3
- description: |
4
- Wire Rigor's bundled MCP server (`rigor mcp`) into an AI coding agent (Claude Code, Claude Desktop, Cursor, Cline) so the agent can call Rigor's read-only analysis tools — rigor_check, rigor_type_of, rigor_triage, rigor_coverage, and more — during a session. The per-client config lives in the manual; this skill identifies the client, applies the right one, and verifies the handshake. Triggers: "set up rigor mcp", "give my AI agent Rigor tools", "wire Rigor into Claude Code / Cursor / Cline", "rigor MCP server". NOT for editor LSP integration (use rigor-editor-setup) or CI (use rigor-ci-setup).
3
+ description: >-
4
+ Set up Rigor's bundled MCP server for an AI coding agent and verify the connection. Use when wiring
5
+ `rigor mcp` into Claude Code, Cursor, Cline, or another MCP client; not for editor LSP or CI setup.
5
6
  license: MPL-2.0
6
7
  metadata:
7
8
  version: 0.1.0
@@ -26,7 +27,7 @@ rigor docs mcp-server
26
27
  ```
27
28
 
28
29
  (Web fallback, only before Rigor is installed:
29
- **[Rigor MCP Server — AI Agent Integration](../../docs/manual/10-mcp-server.md)**.)
30
+ **[Rigor MCP Server — AI Agent Integration](https://github.com/rigortype/rigor/blob/master/docs/manual/10-mcp-server.md)**.)
30
31
  This skill is the *workflow* around it (identify the client → apply the
31
32
  manual's snippet → verify the handshake), so it does not duplicate (and
32
33
  cannot stale-out) the config details.
@@ -70,7 +71,7 @@ Every client config simply launches **`rigor mcp`** (stdio) and needs
70
71
  **`rigor` on the agent's `PATH`** — the same executable `rigor check`
71
72
  uses. For agents that do not inherit your shell, the `mise` shim path is
72
73
  the most reliable channel (see `rigor docs install`, or
73
- [Installing Rigor](../../docs/install.md)
74
+ [Installing Rigor](https://github.com/rigortype/rigor/blob/master/docs/install.md)
74
75
  on the web). Do **not** add `rigortype` to the project's `Gemfile` — it
75
76
  is a tool, not a library.
76
77
 
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-monkeypatch-resolve
3
- description: |
4
- Resolve a cluster of `call.unresolved-toplevel` / `call.undefined-method` diagnostics that are really the project's own monkey-patches (core-extension files that add methods with literal `def`) by wiring them into `pre_eval:` so Rigor pre-evaluates them and learns the added methods. Triggers: "Rigor flags methods my core-ext adds", "undefined-method on my own monkey-patch", "set up pre_eval", "lots of unresolved-toplevel from my lib/core_ext". NOT for dynamically-generated methods (define_method / method_missing / class_eval heredocs) — those need a plugin (use rigor-plugin-author) — and NOT for an external gem with no RBS (use rigor-rbs-setup).
3
+ description: >-
4
+ Resolve Rigor diagnostics caused by literal `def` methods in a project's own monkey-patches by wiring
5
+ their files into `pre_eval:`. Use when project core extensions cause undefined-method findings; not for
6
+ dynamic method generation or an external gem without RBS.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -14,7 +16,7 @@ When a project adds methods to existing classes in its own files — the
14
16
  classic `lib/core_ext/*.rb` `class String; def squish; …; end` pattern —
15
17
  Rigor does not see them unless told to, so every call to the added method
16
18
  fires `call.undefined-method` (or `call.unresolved-toplevel` for a
17
- top-level helper). `pre_eval:` ([ADR-17](../../docs/adr/17-monkey-patch-pre-evaluation.md))
19
+ top-level helper). `pre_eval:` ([ADR-17](https://github.com/rigortype/rigor/blob/master/docs/adr/17-monkey-patch-pre-evaluation.md))
18
20
  fixes this: it pre-evaluates the listed project files and registers every
19
21
  method they define with a **literal** `def` / `def self.`.
20
22
 
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-next-steps
3
- description: |
4
- Route a project to its next Rigor step from a single entry point: resolve the `rigor` command (install it if missing), onboard the project if it has no Rigor config, then ask `rigor skill describe` what to do next and hand off to the matching skill. Triggers: "what should we do next with Rigor?", "I want to use Rigor on this project", "help me move this project forward with Rigor", "where do I start with Rigor?". NOT a replacement for the task-specific skills it routes to — it hands off to them.
3
+ description: >-
4
+ Route a project to its next Rigor step, installing or onboarding Rigor when needed and then delegating
5
+ to `rigor skill describe`. Use when the user asks where to start or what to do next with Rigor; not
6
+ instead of a task-specific skill the route selects.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-plugin-author
3
- description: |
4
- Author a Rigor plugin in your own repository — a standalone rigor-prefixed gem or a project-private plugin — to teach Rigor about an application DSL, framework, or metaprogramming pattern. Covers gemspec / Gemfile wiring, the plugin class and AST walker, return-type contributions, fixture-based testing (RSpec or Minitest), and version pinning against the pre-1.0 plugin contract. Triggers: "write a Rigor plugin for our DSL", "extend Rigor for X in this project", "make Rigor understand our macro". NOT for onboarding a project (use rigor-project-init) or reducing a baseline (use rigor-baseline-reduce).
3
+ description: >-
4
+ Author a Rigor plugin in an adopting project or standalone `rigor-*` gem for a DSL, framework, or
5
+ metaprogramming pattern. Use when Rigor needs project-specific extension support; not for onboarding a
6
+ project, reducing a baseline, or editing Rigor's bundled plugins.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -43,21 +45,20 @@ If you already loaded this skill *via* `rigor skill` you have the current
43
45
  copy — just proceed. If the `rigor` command is not available, run
44
46
  **`rigor-next-steps`** to install Rigor first, then come back.
45
47
 
46
- ## Important — the plugin contract is a preview (pre-1.0)
48
+ ## The plugin contract is pre-1.0
47
49
 
48
- Rigor's plugin contract (ADR-2) is **not yet frozen**. It stabilises
49
- at `rigortype` v0.2.0. Until then, treat each `rigortype` minor
50
- release as potentially contract-changing:
50
+ Rigor's plugin contract (ADR-2) freezes at `rigortype` v1.0.0. Until
51
+ then, treat each `rigortype` minor release as potentially
52
+ contract-changing:
51
53
 
52
- - **Pin `rigortype` tightly** — `>= 0.1.0, < 0.2.0` in your gemspec
53
- or Gemfile. Do not float across the v0.2.0 boundary blind.
54
- - Expect to **revisit your plugin** when you bump `rigortype` to the
55
- next minor. The walker hook signature, the `Diagnostic` shape, and
56
- the type carriers may shift.
57
- - After v0.2.0 the contract is stable and ordinary semver applies.
54
+ - **Pin `rigortype` to the minor you built against** — `"~> X.Y.0"`
55
+ in your gemspec or Gemfile, where `X.Y` comes from `rigor --version`.
56
+ - Expect to **revisit your plugin** when you move to the next minor.
57
+ The node-rule block signature, the `Diagnostic` shape, and the type
58
+ carriers may shift.
58
59
 
59
- Tell the user this up front. A plugin written today is a preview
60
- artefact, valuable but not yet on a stable foundation.
60
+ Tell the user this up front: a plugin written today is valuable but
61
+ not yet on a frozen foundation.
61
62
 
62
63
  ## Read a real plugin — `rigor plugin`
63
64
 
@@ -114,14 +115,9 @@ AST walk per file — hands every matching node to the block along with a
114
115
  `Rigor::Analysis::Diagnostic` (built via the `diagnostic` helper).
115
116
  Optionally the plugin also declares `dynamic_return(receivers:)` /
116
117
  `narrowing_facts(methods:)` to *supply* a return type or narrowing facts
117
- for call sites the core analyzer types as `Dynamic`. (`narrowing_facts`
118
- was renamed from `type_specifier` in ADR-80; the old verb was removed in
119
- 0.3.0, so `narrowing_facts` is the only spelling.)
120
- `#diagnostics_for_file`
121
- is the file-rule surface for whole-file diagnostics a per-node walk can't
122
- express. (`flow_contribution_for` was removed pre-1.0 in ADR-52 WD3 —
123
- defining it now raises `ArgumentError`; use `dynamic_return` /
124
- `narrowing_facts`. See Phase 2.)
118
+ for call sites the core analyzer types as `Dynamic`.
119
+ `#diagnostics_for_file` is the file-rule surface for whole-file
120
+ diagnostics a per-node walk can't express. See Phase 2.
125
121
 
126
122
  ## Phase outline
127
123
 
@@ -136,5 +132,5 @@ defining it now raises `ArgumentError`; use `dynamic_return` /
136
132
  | Module | Read | Covers |
137
133
  | --- | --- | --- |
138
134
  | 1 | [`references/01-plan-and-scaffold.md`](references/01-plan-and-scaffold.md) | **Phase 1.** The gem vs project-private packaging split, directory trees for both, gemspec template, project-private path-gem / `RUBYLIB` activation, the `Rigor::Plugin::Base` skeleton, `.rigor.yml` `plugins:` wiring. |
139
- | 2 | [`references/02-walker-and-types.md`](references/02-walker-and-types.md) | **Phase 2.** The `node_rule` engine-owned AST walk over Prism nodes, the `Base#diagnostic` helper, asking the analyzer for inferred types via `scope.type_of`, two-pass / lexical context (`node_file_context` / `NodeContext`), the optional `dynamic_return` / `narrowing_facts` return-type hooks (`narrowing_facts` was renamed from `type_specifier` in ADR-80, the alias removed in 0.3.0; `flow_contribution_for` was removed pre-1.0 in ADR-52 WD3), calling the target library's pure methods directly rather than reimplementing them (ADR-39: `Plugin::Inflector` over the real `ActiveSupport::Inflector`; `Base.suggest` for did-you-mean), and shipping `sig/*.rbs` so the DSL's types are visible. |
135
+ | 2 | [`references/02-walker-and-types.md`](references/02-walker-and-types.md) | **Phase 2.** The `node_rule` engine-owned AST walk over Prism nodes, the `Base#diagnostic` helper, asking the analyzer for inferred types via `scope.type_of`, two-pass / lexical context (`node_file_context` / `NodeContext`), the optional `dynamic_return` / `narrowing_facts` return-type hooks, calling the target library's pure methods directly rather than reimplementing them (ADR-39: `Plugin::Inflector` over the real `ActiveSupport::Inflector`; `Base.suggest` for did-you-mean), and shipping `sig/*.rbs` so the DSL's types are visible. |
140
136
  | 3 | [`references/03-test-and-ship.md`](references/03-test-and-ship.md) | **Phase 3.** Testing a plugin from outside the monorepo — fixture projects driven through `rigor check --format json`, plus pure unit tests of dispatch tables — with RSpec or Minitest. Version pinning against the pre-1.0 contract. README. Publishing to RubyGems or keeping the plugin private. |
@@ -52,8 +52,9 @@ Gem::Specification.new do |spec|
52
52
  spec.require_paths = ["lib"]
53
53
 
54
54
  spec.add_dependency "prism", ">= 1.0", "< 2.0"
55
- # Pin tightly — the plugin contract is pre-1.0 (see SKILL.md).
56
- spec.add_dependency "rigortype", ">= 0.1.0", "< 0.2.0"
55
+ # Pin to the minor you built against — the contract is pre-1.0
56
+ # (see SKILL.md). X.Y comes from `rigor --version`.
57
+ spec.add_dependency "rigortype", "~> X.Y.0"
57
58
  end
58
59
  ```
59
60
 
@@ -131,7 +132,7 @@ your-app/
131
132
 
132
133
  ```ruby
133
134
  # your-app/Gemfile
134
- gem "rigortype", "~> 0.1.0"
135
+ gem "rigortype", "~> X.Y.0" # the minor you built against
135
136
  gem "rigor-myapp", path: "rigor-plugin"
136
137
  ```
137
138
 
@@ -172,16 +173,16 @@ module Rigor
172
173
  # Optional: declare config keys the user may set under
173
174
  # `.rigor.yml` plugins: [{ gem:, config: { … } }].
174
175
  config_schema: {
175
- # "module_name" => :string,
176
- # "rules" => :array,
176
+ "module_name" => { kind: :string, default: "Default" }
177
+ # "rules" => :array,
177
178
  }
178
179
  )
179
180
 
180
181
  # Called once at load time with the service container.
181
- # Read config defaults here. `config` is the validated
182
- # user config Hash.
182
+ # `config` is the validated user config Hash, with declared
183
+ # defaults merged beneath it.
183
184
  def init(_services)
184
- @module_name = config.fetch("module_name", "Default")
185
+ @module_name = config["module_name"]
185
186
  end
186
187
 
187
188
  # The engine owns the AST walk and hands every matching node to
@@ -152,8 +152,9 @@ For your own target library, follow the same harness: a **fixed
152
152
  allow-list** of pure methods, inputs derived from source, and **decline
153
153
  (return nil / emit nothing) when the library is unavailable — never
154
154
  approximate**. How the call is isolated from Rigor (in-process, a forked
155
- worker, or a `Ruby::Box`) is a configurable strategy the user picks
156
- (`plugins_isolation:`); you just call the method.
155
+ worker, or a `Ruby::Box`) is a configurable strategy the user picks with
156
+ `.rigor.yml`'s `plugins_isolation:` key or the `RIGOR_PLUGIN_ISOLATION`
157
+ environment variable (which wins over it); you just call the method.
157
158
 
158
159
  For the common "did you mean …?" suggestion, use the shared helper
159
160
  rather than hand-rolling Levenshtein:
@@ -164,20 +165,14 @@ Rigor::Plugin::Base.suggest(typo, known_names) # nearest match, or nil
164
165
 
165
166
  ## Optional — contribute a return type with `dynamic_return` / `narrowing_facts`
166
167
 
167
- > **Critical — these hooks do NOT make a method "defined", so they do
168
- > NOT suppress `call.undefined-method`.** Method *existence* and call
169
- > *type* are two independent checks. A return-type contribution sharpens
170
- > the type of a call the analyzer has **already resolved to a real
171
- > method** (turning a `Dynamic` return into something precise). It is
172
- > never consulted for a receiver/method the analyzer cannot find — that
173
- > fires `call.undefined-method` first, and a contribution does nothing
174
- > to silence it. **If your goal is to kill a `call.undefined-method`
175
- > cluster on a DSL-generated method (the common reason
176
- > `rigor-project-init` hands off to this skill), the fix is to make the
177
- > method *exist* in Rigor's view — ship RBS declaring it (see "Shipping
178
- > RBS for the DSL" below), not a return-type contribution.** Reach for
179
- > these only when the call already resolves and you want a *better
180
- > return type*.
168
+ > **Prefer RBS to make a DSL method exist.** A `dynamic_return` answer
169
+ > suppresses `call.undefined-method` only at the call sites where the
170
+ > rule fires (its gated receiver kind and methods); RBS makes the method
171
+ > defined for all of core inference — arity, argument types, every call
172
+ > site. To clear a `call.undefined-method` cluster on DSL-generated
173
+ > methods (the common reason `rigor-project-init` hands off to this
174
+ > skill), ship RBS (see "Shipping RBS for the DSL" below). Reach for
175
+ > these hooks when you want a better *return type* for a call.
181
176
 
182
177
  A plugin can do more than emit diagnostics: it can *supply* the
183
178
  inferred return type (or narrowing facts) for a call site the core
@@ -194,6 +189,16 @@ dynamic_return receivers: ["Money"] do |call_node, scope|
194
189
  Rigor::Type::Combinator.nominal_of("Money")
195
190
  end
196
191
 
192
+ # A `receivers:` entry names the receiver KIND too. `"Money"` matches an
193
+ # INSTANCE receiver; the class object itself is `"singleton(Money)"`,
194
+ # spelled as RBS spells it; a rule for both lists both. Write the kind
195
+ # the rule actually models: a plugin answer suppresses that call site's
196
+ # `call.undefined-method`, so an instance rule that also answered on the
197
+ # class would silence a genuine miss on the class-level call.
198
+ dynamic_return receivers: ["singleton(Money)"], methods: [:from_cents] do |call_node, scope|
199
+ Rigor::Type::Combinator.nominal_of("Money")
200
+ end
201
+
197
202
  # Post-return NARROWING FACTS, gated on the call's method name.
198
203
  # Return an Array of facts (or nil). Used for assertion / predicate
199
204
  # narrowing (`assert_kind_of(Foo, x)` ⇒ x is Foo afterwards).
@@ -202,10 +207,6 @@ narrowing_facts methods: [:assert_kind_of] do |call_node, scope|
202
207
  end
203
208
  ```
204
209
 
205
- > **`narrowing_facts` was renamed from `type_specifier` in ADR-80.**
206
- > The old verb was removed in 0.3.0 — `narrowing_facts` is the only
207
- > spelling a plugin can declare.
208
-
209
210
  Build return types with `Rigor::Type::Combinator`:
210
211
 
211
212
  ```ruby
@@ -222,12 +223,9 @@ plugin is confident; a wrong contribution propagates downstream.
222
223
  `rigor plugins --capabilities` catalogue enumerates — run it to see
223
224
  exactly what each loaded plugin contributes.
224
225
 
225
- > **The removed fat hook.** The original `flow_contribution_for(call_node:,
226
- > scope:)` was **deleted pre-1.0 in ADR-52 WD3** — defining it now raises
227
- > `ArgumentError` at load time. The two shapes it used to cover are
228
- > expressed by `dynamic_return`'s callable gates: a **method-gated return
229
- > type** (an RSpec `let(:x) { … }` binding, a Sorbet `sig`-driven return —
230
- > keyed on the method, not a fixed receiver class) uses
226
+ > **Callable gates.** A **method-gated return type** (an RSpec
227
+ > `let(:x) { … }` binding, a Sorbet `sig`-driven return — keyed on the
228
+ > method, not a fixed receiver class) uses
231
229
  > `dynamic_return methods: -> { [...] }` or `file_methods: ->(path) { [...] }`;
232
230
  > a **dynamic per-project receiver set** (ActiveStorage's `Attached::One`
233
231
  > on discovered model classes) uses `dynamic_return receivers: -> { [...] }`,
@@ -236,7 +234,7 @@ exactly what each loaded plugin contributes.
236
234
  > if the plugin genuinely needs to sharpen call-site types; a
237
235
  > diagnostics-only plugin skips them entirely.
238
236
 
239
- ## Shipping RBS for the DSL — the way to suppress `call.undefined-method`
237
+ ## Shipping RBS for the DSL — making DSL methods exist
240
238
 
241
239
  If the DSL introduces methods or classes that Rigor cannot see (a
242
240
  `Money` class defined by metaprogramming, `Setting.<name>` accessors a
@@ -106,11 +106,12 @@ CLI tests for the end-to-end wiring.
106
106
 
107
107
  ## Version pinning — the pre-1.0 contract
108
108
 
109
- The plugin contract is **not frozen until `rigortype` v0.2.0** (see
109
+ The plugin contract is **not frozen until `rigortype` v1.0.0** (see
110
110
  SKILL.md). Concretely:
111
111
 
112
- - Gemspec / Gemfile: `rigortype` `>= 0.1.0, < 0.2.0`. Never `>= 0.1`
113
- alone — that floats across the contract-changing v0.2.0 boundary.
112
+ - Gemspec / Gemfile: `rigortype` `~> X.Y.0` for the minor you tested
113
+ (`rigor --version`). Never an open `>=` range — that floats across
114
+ contract-changing minors.
114
115
  - Your plugin's own version is normal semver, independent of
115
116
  `rigortype`'s.
116
117
  - When you bump the `rigortype` pin to a new minor, **re-run the
@@ -120,9 +121,6 @@ SKILL.md). Concretely:
120
121
  - State the supported `rigortype` range in the README so users do
121
122
  not pair the plugin with an incompatible Rigor.
122
123
 
123
- When v0.2.0 lands, re-pin to the stable range and ordinary
124
- compatibility rules apply.
125
-
126
124
  ## README
127
125
 
128
126
  A plugin README should carry:
@@ -151,13 +149,13 @@ wired and the fixture tests run.
151
149
  Either way, if the plugin uncovered a gap that *should* be core
152
150
  Rigor behaviour — or if you hit a plugin-contract rough edge — report
153
151
  it: <https://github.com/rigortype/rigor/issues>. External plugin
154
- authors are the main source of pre-v0.2.0 contract feedback.
152
+ authors are the main source of contract feedback before v1.0.
155
153
 
156
154
  ## Output of this module — plugin shipped
157
155
 
158
156
  - A test suite: fast unit tests + fixture-driven `rigor check`
159
157
  tests, in RSpec or Minitest.
160
- - A `rigortype` pin tight to `< 0.2.0`.
158
+ - A `rigortype` pin tight to the tested minor.
161
159
  - A README stating the compatibility range.
162
160
  - The plugin published as a gem, or committed project-private with
163
161
  CI wired.
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-plugin-review
3
- description: |
4
- Review an existing Rigor plugin's source against the current authoring contract and produce a prioritized upgrade path — the modernization counterpart to rigor-plugin-author. Audits config-default declaration (ADR-40), the AST-walk model (node_rule vs a hand-rolled traversal), return-type / narrowing hooks (dynamic_return / narrowing_facts, not the removed flow_contribution_for or type_specifier), the ADR-60 WD4 authoring helpers (diagnostic / diagnostics_for / suggest / producer_value / read_fact), engine-collaboration vs reimplementation, cache-producer soundness, manifest-field hygiene, and doc freshness. Triggers: "review this Rigor plugin", "does my plugin follow best practices", "upgrade our rigor-prefixed plugin to the latest contract", "modernize this plugin", "is this plugin using the current API". NOT for authoring a new plugin (use rigor-plugin-author), enabling bundled plugins on a project (use rigor-plugin-tune), or tuning plugin config.
3
+ description: >-
4
+ Audit an existing Rigor plugin against the current authoring contract and produce a prioritized upgrade
5
+ path. Use when modernizing or reviewing a `rigor-*` plugin; not for authoring a new plugin, enabling
6
+ bundled plugins, or tuning project config.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -120,7 +122,7 @@ green first, so you can prove each later step is a faithful refactor:
120
122
  # external gem:
121
123
  bundle exec rspec spec/
122
124
  # in the rigor monorepo:
123
- nix … develop --command bundle exec rspec spec/integration/<plugins|examples>/<id>_plugin_spec.rb
125
+ nix develop --command bundle exec rspec spec/integration/<plugins|examples>/<id>_plugin_spec.rb
124
126
  ```
125
127
 
126
128
  If there is no spec, **write one first** (per `rigor-plugin-author`
@@ -148,7 +150,7 @@ step**:
148
150
  ### Phase 5 — Verify
149
151
 
150
152
  ```sh
151
- rigor check <plugin>/lib # ADR-43 contract self-check — MUST be clean
153
+ rigor check <plugin>/lib # ADR-43 contract self-check — must be clean
152
154
  rigor plugins --strict # the plugin still loads
153
155
  rigor plugins --capabilities # node-rule types / dynamic_return receivers look right
154
156
  bundle exec rspec … # the oracle spec, still green
@@ -205,7 +205,8 @@ and put that in a CHANGELOG / migration note, not the class docstring.
205
205
 
206
206
  - `rigor check <plugin>/lib` — the ADR-43 contract self-check resolves
207
207
  the plugin's inherited `Plugin::Base` calls and warns on contract
208
- misuse. MUST be clean; fix the cause, never disable the rule.
208
+ misuse. It must be clean; fix the cause rather than disabling the
209
+ rule.
209
210
  - `rigor plugins --strict` — the plugin still activates.
210
211
  - `rigor plugins --capabilities` — `node_rule_types` /
211
212
  `dynamic_return_receivers` / `narrowing_facts_methods` reflect the
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-plugin-tune
3
- description: |
4
- Re-scan a configured project's Gemfile.lock against Rigor's bundled plugin catalogue and enable the plugins that match its current dependencies (Rails, RSpec, dry-rb, Sidekiq, Devise, …), then verify they all load. Run it after adding a gem, or when an onboarding predates a dependency the project now uses. Triggers: "enable the right Rigor plugins", "I added gem X, does Rigor have a plugin?", "which rigor plugins should this project use?", "rigor plugins for my stack". NOT for first-time onboarding (use rigor-project-init, which does the initial selection) and NOT for authoring a new plugin (use rigor-plugin-author).
3
+ description: >-
4
+ Match a configured project's `Gemfile.lock` to Rigor's bundled plugin catalogue and enable the plugins
5
+ its current dependencies need. Use after adding a gem or when plugin selection is stale; not for
6
+ first-time onboarding or authoring a new plugin.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-project-init
3
- description: |
4
- Onboard a project to Rigor type-checking from scratch: detect the stack, choose an adoption mode (baseline vs. strict), select plugins, write `.rigor.dist.yml`, then snapshot a baseline or commit to a zero-diagnostic gate. Triggers: "set up Rigor in this project", "configure rigor for X", "add type checking", or running `rigor check` in a Gemfile directory with no `.rigor.yml`. NOT for reducing an existing baseline (use rigor-baseline-reduce) or authoring a plugin (use rigor-plugin-author).
3
+ description: >-
4
+ Onboard a project to Rigor from scratch by detecting the stack, selecting plugins and an adoption mode,
5
+ and writing the initial config and baseline or strict gate. Use for first-time Rigor setup; not for an
6
+ existing baseline or plugin authoring.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -52,7 +54,7 @@ Do NOT trigger for:
52
54
  `rigor-baseline-reduce` skill.
53
55
  - **Writing a Rigor plugin** for the project's own DSL /
54
56
  metaprogramming — that is the `rigor-plugin-author` skill. (This
55
- skill *points at* plugin authoring as an escalation in Phase 7;
57
+ skill *points at* plugin authoring as an escalation in Phase 8;
56
58
  it does not do it.)
57
59
  - **Tweaking an already-configured project** — ordinary edits to an
58
60
  existing `.rigor.yml`; no onboarding pipeline needed.
@@ -77,7 +79,7 @@ adoption entirely.
77
79
 
78
80
  So **before writing any config, present the user with two modes**
79
81
  and let them choose. The mode drives the severity profile, whether a
80
- baseline is generated, and how Phase 7 frames the leftover
82
+ baseline is generated, and how Phase 8 frames the leftover
81
83
  diagnostics.
82
84
 
83
85
  | | **Acknowledge mode** (baseline adoption) | **Strict mode** (no compromise) |
@@ -135,6 +137,7 @@ mode — those points resolve without blocking:
135
137
  | 6a | **Pre-baseline cleanup** — apply quick fixes that triage diagnosed (`pre_eval:` for monkey-patch hints, `rbs collection install` if still needed). Re-run triage; repeat until the count is stable. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) § "Phase 6a" |
136
138
  | 7 | Acknowledge mode only — generate the baseline and wire `baseline:`. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) |
137
139
  | 8 | Surface likely real bugs; distinguish sig quality FPs from real bugs; offer escalation paths. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) |
140
+ | 8a | Install the agent type-contract into `AGENTS.md` / `CLAUDE.md`, so an AI contributor sources types from Rigor instead of guessing them. | [`references/06-agent-contract.md`](references/06-agent-contract.md) |
138
141
  | 9 | Confirm the generated files with the user — what each is, and whether to commit it. | (this file — § "Final step") |
139
142
 
140
143
  Load each reference when you reach its phase. Phases run in order;
@@ -150,9 +153,10 @@ committed `sig/` directory.
150
153
  | 2 | [`references/02-configure.md`](references/02-configure.md) | **Phase 4.** Severity-profile choice tied to the mode. The `.rigor.dist.yml` template and every key it uses. The `.rigor.dist.yml` vs `.rigor.yml` convention. |
151
154
  | 3 | [`references/04-sig-uplift.md`](references/04-sig-uplift.md) | **Phase 5.** `rigor sig-gen --write` baseline. `rigor sig-gen --params=observed --write` attr_reader precision uplift. Handling residual `untyped` methods. Committing `sig/`. |
152
155
  | 4 | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) | **Phases 6–8.** `rigor triage` as the diagnosis layer. Phase 6a pre-baseline cleanup loop (`pre_eval:` for monkey-patch hints, `rbs collection install`). `rigor baseline generate` + wiring `baseline:`. Surfacing likely real bugs; sig quality FP recognition (Struct `call.wrong-arity`, `-> bot` return-type-mismatch, regex-capture `$1` FPs). The two escalation paths — write a project plugin, or open a Rigor issue. |
156
+ | 5 | [`references/06-agent-contract.md`](references/06-agent-contract.md) | **Phase 8a.** The one paragraph the project's `AGENTS.md` / `CLAUDE.md` keeps so every agent session sources types from Rigor rather than guessing them. Where to append it, when to create the file, and what never to overwrite. |
153
157
  | — (optional) | [`references/05-jit-performance.md`](references/05-jit-performance.md) | **Operational, not a phase.** Run speed via a Ruby JIT: Rigor auto-enables YJIT for long runs (~5 s break-even), how to detect JIT support in your install, the override env vars, and why YJIT beats ZJIT for Rigor on Ruby 4.0. Read only when a large project's `rigor check` wall time matters. |
154
158
 
155
- ## Escalation paths (Phase 7 preview)
159
+ ## Escalation paths (Phase 8 preview)
156
160
 
157
161
  Some diagnostic clusters are neither a quick fix nor honest baseline
158
162
  material. Two of them have a dedicated answer this skill hands off to:
@@ -181,7 +185,7 @@ material. Two of them have a dedicated answer this skill hands off to:
181
185
  support, **open an issue on the Rigor project** asking for it:
182
186
  <https://github.com/rigortype/rigor/issues>.
183
187
 
184
- Neither is a Phase 7 obligation — they are options to *offer* the
188
+ Neither is a Phase 8 obligation — they are options to *offer* the
185
189
  user when the triage report points at one of these causes. The
186
190
  project-DSL handoff is detailed in
187
191
  [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md)
@@ -221,16 +225,17 @@ only in acknowledge mode). For each, give the commit recommendation:
221
225
 
222
226
  | File | What it is | Commit? |
223
227
  | --- | --- | --- |
224
- | `.rigor.dist.yml` | The shared project config (Phase 4) — `target_ruby`, `paths:`, `plugins:`, `severity_profile:`, and the `baseline:` pointer. The single source of truth every contributor's `rigor check` reads. | **Yes** — it is the shared config; sharing it is the whole point. |
228
+ | `.rigor.dist.yml` | The shared project config (Phase 4) — `target_ruby`, `paths:`, `test_paths:`, `plugins:`, `severity_profile:`, and the `baseline:` pointer. The single source of truth every contributor's `rigor check` reads. | **Yes** — it is the shared config; sharing it is the whole point. |
225
229
  | `.rigor-baseline.yml` | Acknowledge mode only (Phase 7) — the snapshot of today's known diagnostics. Doubles as a record of project state; without it each developer's baseline diverges and the regression guard means different things per machine. | **Yes** — commit it; it documents project state and pins the regression envelope. |
226
230
  | `sig/` | RBS skeletons from `rigor sig-gen` (Phase 5), if that phase ran. A first-class project artefact — it sharpens inference for everyone. | **Yes** — commit it (see [`references/04-sig-uplift.md`](references/04-sig-uplift.md) § "Commit the sig/ directory"). |
227
231
  | `.rigor/` (contains `cache/`) | The per-file analysis cache `rigor check` writes to speed up re-runs. Regenerable and machine-local. | **No** — add `.rigor/` to `.gitignore`. |
228
232
  | `.rigor.yml` | Optional per-developer local override (not written by this skill). Takes precedence over `.rigor.dist.yml`; used to opt out locally (e.g. run without the baseline). | **No** — gitignore it if a developer creates one. |
229
233
  | `rbs_collection.lock.yaml` | Not a Rigor artefact — but if Phase 1 ran `rbs collection install`, the install may have regenerated this pre-existing project file (e.g. the stdlib gem list for the resolved Ruby). | **Yes**, but flag it separately: it is a change to an existing project file, not part of the Rigor file set. |
234
+ | `AGENTS.md` / `CLAUDE.md` | The agent type-contract section added in Phase 8a — "a type you did not obtain from Rigor is a guess". Created only if neither file existed; otherwise this is an appended section in a pre-existing file. | **Yes** — commit it; the point is that every contributor's agent reads the same rule. Flag an appended section separately, as with `rbs_collection.lock.yaml`. |
230
235
 
231
236
  Recommend the two concrete actions and **ask before doing them**
232
237
  (both touch the user's repo): (1) add `.rigor/` — and `.rigor.yml`
233
238
  if present — to `.gitignore`; (2) commit `.rigor.dist.yml`,
234
- `.rigor-baseline.yml`, and `sig/` as the shared Rigor setup. Per the
235
- git-safety default, do not commit on the user's behalf until they
236
- confirm.
239
+ `.rigor-baseline.yml`, `sig/`, and the Phase 8a `AGENTS.md` /
240
+ `CLAUDE.md` section as the shared Rigor setup. Per the git-safety
241
+ default, do not commit on the user's behalf until they confirm.
@@ -71,14 +71,13 @@ The directory should contain RBS gem subdirectories. Continue to
71
71
  Phase 2 — the collection will be auto-detected by Rigor at analysis
72
72
  time.
73
73
 
74
- **Note: RBS collision after install.** Some gems (e.g. `cgi`, `logger`,
75
- `base64`) were extracted from Ruby's stdlib into standalone gems from
76
- Ruby 3.3 onwards. When these appear in both `.gem_rbs_collection/` and
77
- Rigor's bundled stdlib, `rigor triage` may print a
78
- `RBS::DuplicatedDeclarationError`. If this happens, note the error and
79
- continue — plugin-based diagnostics are unaffected. File a Rigor issue
80
- at <https://github.com/rigortype/rigor/issues> so the engine can
81
- deduplicate stdlib gems from the collection automatically.
74
+ **Note: RBS collision after install.** Rigor skips collection entries
75
+ for gems it already loads from its bundled RBS — including gems
76
+ extracted from Ruby's stdlib, such as `cgi` and `logger` — so the
77
+ collection does not double-declare them. If `rigor triage` still prints
78
+ an `RBS::DuplicatedDeclarationError`, note it and continue, and report
79
+ it at <https://github.com/rigortype/rigor/issues> with the gem names the
80
+ error mentions.
82
81
 
83
82
  ### Path scope
84
83
 
@@ -92,6 +91,11 @@ Note the conventional source roots so Phase 4 can set `paths:`:
92
91
  are checked differently and inflate the diagnostic count. `vendor/`
93
92
  and `tmp/` are always excluded.
94
93
 
94
+ Note the **test roots** too — every directory holding the project's
95
+ tests, not only the conventional one (`spec/`, `test/`, and any
96
+ extra suite such as `test/system` kept elsewhere or an
97
+ `integration/` tree). Phase 4 writes them to `test_paths:`.
98
+
95
99
  ## Phase 3 — Plugin selection
96
100
 
97
101
  Propose a plugin set from the detected families. Present it to the
@@ -120,7 +124,7 @@ ActiveSupport monkey-patches the core classes (`3.days`,
120
124
  `rigor-activesupport-core-ext` bundle, every such call reports
121
125
  `call.undefined-method` — on a real Rails app this is the single
122
126
  largest diagnostic cluster (a measured Mastodon run: ~365 of 489
123
- diagnostics were exactly this). Phase 5's `rigor triage` flags it as
127
+ diagnostics were exactly this). Phase 6's `rigor triage` flags it as
124
128
  hint `activesupport-core-ext`.
125
129
 
126
130
  `rigor-activesupport-core-ext` is a **plugin** (an RBS-bundle plugin
@@ -91,6 +91,11 @@ paths:
91
91
  - app
92
92
  - lib
93
93
 
94
+ # Where the tests live. `rigor sig-gen --params=observed` reads their
95
+ # call sites to type parameters (Phase 5). Not analysed by `rigor check`.
96
+ test_paths:
97
+ - spec
98
+
94
99
  exclude:
95
100
  - vendor
96
101
  - tmp
@@ -107,17 +112,18 @@ plugins:
107
112
 
108
113
  severity_profile: lenient
109
114
 
110
- # Phase 6 (acknowledge mode) appends this line after generating the
115
+ # Phase 7 (acknowledge mode) appends this line after generating the
111
116
  # baseline. Strict mode leaves it out entirely.
112
117
  # baseline: .rigor-baseline.yml
113
118
  ```
114
119
 
115
120
  ### Existing `sig/` directory
116
121
 
117
- If the project already has a `sig/` directory (from Steep, `rbs_rails`,
118
- or handwritten annotations), wire it into `signature_paths:` so Rigor
119
- consumes it. Phase 5 (sig uplift) can be skipped, but the paths must
120
- still be declared — Rigor does not auto-detect `sig/`:
122
+ A plain `<project root>/sig` directory needs no wiring: with
123
+ `signature_paths:` unset, Rigor auto-detects it and loads it recursively.
124
+ Phase 5 (sig uplift) can be skipped. Declare `signature_paths:` when the
125
+ layout is something else — several trees, or a `sig/` that is not at the
126
+ project root:
121
127
 
122
128
  ```yaml
123
129
  signature_paths:
@@ -125,18 +131,40 @@ signature_paths:
125
131
  - sig/generated
126
132
  ```
127
133
 
134
+ Declaring the key REPLACES the auto-detected `sig`, so list it too if you
135
+ want it. `signature_paths: []` is the way to opt out of project RBS
136
+ entirely — including a `sig/` that `rigor sig-gen --write` created.
137
+
128
138
  List only directories that contain `.rbs` files or subdirectories of
129
- them. Rigor walks each path recursively. If the sig layout is a single
130
- flat `sig/` directory, use `- sig` instead.
139
+ them. Rigor walks each path recursively.
131
140
 
132
141
  A strict-mode plain-Ruby gem is shorter:
133
142
 
134
143
  ```yaml
135
144
  paths:
136
145
  - lib
146
+ test_paths:
147
+ - test
137
148
  severity_profile: strict
138
149
  ```
139
150
 
151
+ ### Test roots — write `test_paths:` explicitly
152
+
153
+ Always write `test_paths:` with the test roots Phase 1 found, even
154
+ when they are the conventional `spec/` or `test/`. Left unset, Rigor
155
+ auto-detects whichever of `spec/` and `test/` exist; that covers the
156
+ common layouts, but the committed config is then silent about where
157
+ the tests are, and a suite anywhere else (a second tree, an
158
+ `integration/` directory) is never read. Declaring the key replaces
159
+ auto-detection, so list every root. A project with no tests yet
160
+ writes `test_paths: []`.
161
+
162
+ The key affects no diagnostic. Its reader today is `rigor sig-gen
163
+ --params=observed` (Phase 5), which types a parameter from the
164
+ arguments the tests pass. When there is no root to read, or a declared
165
+ root does not exist, sig-gen says so on stderr and the affected
166
+ parameters stay `untyped`.
167
+
140
168
  ### Key reference
141
169
 
142
170
  Only the keys this skill needs. `rigor --help` and the project
@@ -146,19 +174,20 @@ handbook document the full surface.
146
174
  | --- | --- |
147
175
  | `paths:` | Directories Rigor analyses. Source roots only — not `spec/` / `test/`. |
148
176
  | `exclude:` | Paths removed from the `paths:` walk. |
177
+ | `test_paths:` | The project's test roots (`spec`, `test`, or several). Write it explicitly; see § "Test roots". Relative entries resolve against the config file. `rigor check` ignores it; `sig-gen` names a declared root that does not exist. |
149
178
  | `plugins:` | Plugin ids to activate (the Phase 3 set). |
150
179
  | `signature_paths:` | Extra RBS source **directories** (paths, not gem names; resolved relative to the config file). Use it for the project's own local `sig/` if it has one. RBS-bundle *plugins* like `rigor-activesupport-core-ext` ship their own `sig/` and need no entry here — list them under `plugins:`. |
151
180
  | `severity_profile:` | `lenient` / `balanced` / `strict`. See the table above. |
152
181
  | `severity_overrides:` | Per-rule severity tweaks. Leave empty at init; the baseline-reduce workflow tunes it later. |
153
- | `baseline:` | Path to the baseline file. **Only acknowledge mode sets it**, and only in Phase 6 *after* the file exists. Per Rigor's no-magic rule, a `.rigor-baseline.yml` on disk does nothing until this key names it. |
154
- | `pre_eval:` | Project files Rigor walks before per-file inference — used to register in-project monkey-patches. Leave empty at init; Phase 7 may suggest it. |
155
- | `dependencies.source_inference:` | Opt-in inference for gems shipping no RBS. Leave empty at init; Phase 7 may suggest it. |
182
+ | `baseline:` | Path to the baseline file. **Only acknowledge mode sets it**, and only in Phase 7 *after* the file exists. Per Rigor's no-magic rule, a `.rigor-baseline.yml` on disk does nothing until this key names it. |
183
+ | `pre_eval:` | Project files Rigor walks before per-file inference — used to register in-project monkey-patches. Leave empty at init; Phase 6a may add it. |
184
+ | `dependencies.source_inference:` | Opt-in inference for gems shipping no RBS. Leave empty at init; Phase 8 may suggest it. |
156
185
 
157
186
  ## Do not write the baseline yet
158
187
 
159
188
  Phase 4 writes the config with the `baseline:` line **commented out
160
- or absent**. The baseline file does not exist until Phase 6, and a
161
- `baseline:` pointing at a missing file is an error. Phase 6 writes
189
+ or absent**. The baseline file does not exist until Phase 7, and a
190
+ `baseline:` pointing at a missing file is an error. Phase 7 writes
162
191
  the file and uncomments / appends the line in one step.
163
192
 
164
193
  Strict mode never adds `baseline:` at all.
@@ -227,8 +256,8 @@ with the message text.
227
256
 
228
257
  ## Output of this module
229
258
 
230
- A committed `.rigor.dist.yml` with `paths:`, `exclude:`,
231
- `plugins:`, and `severity_profile:` set — and no active
259
+ A committed `.rigor.dist.yml` with `paths:`, `test_paths:`,
260
+ `exclude:`, `plugins:`, and `severity_profile:` set — and no active
232
261
  `baseline:` line. `rigor plugins` reports every entry loaded,
233
262
  zero load errors. No Gemfile changes; plugins are bundled inside
234
263
  `rigortype`.