rigortype 0.3.9 → 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 (363) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/data/core_overlay/enumerable.rbs +51 -0
  4. data/data/core_overlay/enumerator.rbs +84 -0
  5. data/data/core_overlay/hash_rbs3.rbs +41 -0
  6. data/data/core_overlay/process.rbs +40 -0
  7. data/data/core_overlay/string_io.rbs +33 -0
  8. data/data/effects/core.yml +3 -3
  9. data/data/gem_overlay/activesupport/core_ext.rbs +127 -4
  10. data/docs/handbook/03-narrowing.md +95 -10
  11. data/docs/handbook/04-tuples-and-shapes.md +8 -6
  12. data/docs/handbook/07-rbs-and-extended.md +16 -11
  13. data/docs/handbook/10-sorbet.md +9 -10
  14. data/docs/handbook/11-sig-gen.md +454 -13
  15. data/docs/manual/02-cli-reference.md +63 -2
  16. data/docs/manual/03-configuration.md +7 -0
  17. data/docs/manual/04-diagnostics.md +4 -0
  18. data/docs/manual/07-plugins.md +1 -1
  19. data/docs/manual/10-mcp-server.md +3 -2
  20. data/docs/manual/16-rbs-extended-annotations.md +40 -7
  21. data/docs/manual/19-effect-labels.md +10 -0
  22. data/docs/manual/plugins/README.md +7 -0
  23. data/docs/manual/plugins/rigor-actioncable.md +8 -1
  24. data/docs/manual/plugins/rigor-actionmailer.md +7 -0
  25. data/docs/manual/plugins/rigor-actionpack.md +243 -0
  26. data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
  27. data/docs/manual/plugins/rigor-activejob.md +7 -0
  28. data/docs/manual/plugins/rigor-activerecord.md +110 -4
  29. data/docs/manual/plugins/rigor-activestorage.md +8 -1
  30. data/docs/manual/plugins/rigor-activesupport-core-ext.md +11 -5
  31. data/docs/manual/plugins/rigor-grape.md +106 -0
  32. data/docs/manual/plugins/rigor-graphql.md +23 -2
  33. data/docs/manual/plugins/rigor-pundit.md +8 -1
  34. data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
  35. data/docs/manual/plugins/rigor-rails-routes.md +7 -0
  36. data/docs/manual/plugins/rigor-rbs-inline.md +212 -25
  37. data/docs/manual/plugins/rigor-sidekiq.md +8 -1
  38. data/docs/manual/plugins/rigor-sorbet.md +21 -5
  39. data/exe/rigor +19 -4
  40. data/lib/rigor/analysis/baseline.rb +1 -1
  41. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
  42. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
  43. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -3
  44. data/lib/rigor/analysis/check_rules/rule_ids.rb +20 -5
  45. data/lib/rigor/analysis/check_rules/rule_walk.rb +2 -1
  46. data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
  47. data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
  48. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +36 -2
  49. data/lib/rigor/analysis/check_rules.rb +520 -49
  50. data/lib/rigor/analysis/dependency_recorder.rb +23 -0
  51. data/lib/rigor/analysis/fact_store.rb +9 -0
  52. data/lib/rigor/analysis/incremental.rb +26 -0
  53. data/lib/rigor/analysis/incremental_session.rb +36 -4
  54. data/lib/rigor/analysis/project_scan.rb +11 -1
  55. data/lib/rigor/analysis/reachability/plugin_roots.rb +0 -1
  56. data/lib/rigor/analysis/reachability/scan_cache.rb +1 -0
  57. data/lib/rigor/analysis/rule_catalog.rb +127 -0
  58. data/lib/rigor/analysis/run_cache_key.rb +20 -11
  59. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +167 -11
  60. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -4
  61. data/lib/rigor/analysis/runner/pool_coordinator.rb +107 -15
  62. data/lib/rigor/analysis/runner/project_pre_passes.rb +26 -7
  63. data/lib/rigor/analysis/runner.rb +278 -20
  64. data/lib/rigor/analysis/template_unit_collector.rb +303 -0
  65. data/lib/rigor/analysis/template_unit_paths.rb +91 -0
  66. data/lib/rigor/analysis/template_unit_positions.rb +293 -0
  67. data/lib/rigor/analysis/template_units.rb +399 -0
  68. data/lib/rigor/analysis/worker_session.rb +53 -10
  69. data/lib/rigor/bleeding_edge.rb +0 -2
  70. data/lib/rigor/builtins/hkt_builtins.rb +1 -0
  71. data/lib/rigor/builtins/imported_refinements.rb +4 -0
  72. data/lib/rigor/builtins/regex_refinement.rb +17 -9
  73. data/lib/rigor/builtins/static_return_refinements.rb +2 -0
  74. data/lib/rigor/cache/descriptor.rb +6 -1
  75. data/lib/rigor/cache/engine_source.rb +29 -1
  76. data/lib/rigor/cache/incremental_snapshot.rb +33 -1
  77. data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
  78. data/lib/rigor/cache/rbs_descriptor.rb +37 -7
  79. data/lib/rigor/cache/store.rb +0 -1
  80. data/lib/rigor/ci_detector.rb +1 -0
  81. data/lib/rigor/cli/doc_links.rb +1 -1
  82. data/lib/rigor/cli/docs_command.rb +4 -4
  83. data/lib/rigor/cli/plugin_command.rb +3 -3
  84. data/lib/rigor/cli/prism_colorizer.rb +0 -1
  85. data/lib/rigor/cli/sig_gen_command.rb +210 -29
  86. data/lib/rigor/cli/skill_command.rb +1 -1
  87. data/lib/rigor/cli/skill_describe.rb +0 -1
  88. data/lib/rigor/cli/type_of_command.rb +19 -5
  89. data/lib/rigor/cli/type_of_renderer.rb +20 -9
  90. data/lib/rigor/cli/type_of_template_probe.rb +189 -0
  91. data/lib/rigor/cli.rb +21 -3
  92. data/lib/rigor/configuration/severity_profile.rb +19 -3
  93. data/lib/rigor/configuration.rb +66 -3
  94. data/lib/rigor/effects/ancestry_recorder.rb +191 -0
  95. data/lib/rigor/effects/attribution.rb +11 -2
  96. data/lib/rigor/effects/callee_rule.rb +368 -0
  97. data/lib/rigor/effects/catalog.rb +7 -4
  98. data/lib/rigor/effects/collector.rb +11 -5
  99. data/lib/rigor/effects/config_envelopes.rb +9 -2
  100. data/lib/rigor/effects/definition_context.rb +179 -0
  101. data/lib/rigor/effects/effect_table.rb +11 -3
  102. data/lib/rigor/effects/envelope_check.rb +1 -1
  103. data/lib/rigor/effects/envelope_index.rb +15 -0
  104. data/lib/rigor/effects/file_collection.rb +59 -5
  105. data/lib/rigor/effects/framework_units.rb +1 -1
  106. data/lib/rigor/effects/identity.rb +16 -0
  107. data/lib/rigor/effects/local_ownership.rb +38 -12
  108. data/lib/rigor/effects/method_key.rb +21 -0
  109. data/lib/rigor/effects/mutation_classifier.rb +23 -12
  110. data/lib/rigor/effects/plugin_facts.rb +43 -31
  111. data/lib/rigor/effects/propagator.rb +295 -16
  112. data/lib/rigor/effects/registry.rb +1 -1
  113. data/lib/rigor/effects/scanner.rb +121 -72
  114. data/lib/rigor/effects/signature_sources.rb +1 -1
  115. data/lib/rigor/effects/snapshot.rb +2 -1
  116. data/lib/rigor/effects/summary.rb +27 -4
  117. data/lib/rigor/effects/unit_scan.rb +385 -30
  118. data/lib/rigor/effects/visibility.rb +101 -0
  119. data/lib/rigor/environment/lockfile_resolver.rb +17 -0
  120. data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
  121. data/lib/rigor/environment/member_consistency.rb +298 -0
  122. data/lib/rigor/environment/rbs_loader.rb +399 -133
  123. data/lib/rigor/environment.rb +103 -38
  124. data/lib/rigor/hashing/xxh3.rb +264 -0
  125. data/lib/rigor/inference/acceptance.rb +139 -9
  126. data/lib/rigor/inference/block_auto_splat.rb +216 -0
  127. data/lib/rigor/inference/block_call_timing.rb +338 -0
  128. data/lib/rigor/inference/block_parameter_binder.rb +73 -27
  129. data/lib/rigor/inference/block_repetition.rb +71 -0
  130. data/lib/rigor/inference/body_fixpoint.rb +2 -1
  131. data/lib/rigor/inference/budget_trace.rb +2 -1
  132. data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
  133. data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
  134. data/lib/rigor/inference/captured_locals.rb +387 -15
  135. data/lib/rigor/inference/closure_escape_analyzer.rb +157 -13
  136. data/lib/rigor/inference/content_join.rb +200 -27
  137. data/lib/rigor/inference/def_return_typer.rb +11 -7
  138. data/lib/rigor/inference/define_method_block_self.rb +64 -0
  139. data/lib/rigor/inference/element_read_widening.rb +22 -10
  140. data/lib/rigor/inference/error_info.rb +196 -0
  141. data/lib/rigor/inference/expression_typer.rb +1532 -496
  142. data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
  143. data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
  144. data/lib/rigor/inference/global_write_census.rb +239 -0
  145. data/lib/rigor/inference/guard_rebinding.rb +447 -0
  146. data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
  147. data/lib/rigor/inference/index_write_widening.rb +16 -3
  148. data/lib/rigor/inference/indexed_narrowing.rb +61 -9
  149. data/lib/rigor/inference/jump_targets.rb +82 -0
  150. data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
  151. data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
  152. data/lib/rigor/inference/last_line.rb +340 -0
  153. data/lib/rigor/inference/last_status.rb +144 -0
  154. data/lib/rigor/inference/macro_block_self_type.rb +167 -17
  155. data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
  156. data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
  157. data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
  158. data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
  159. data/lib/rigor/inference/match_rebinding.rb +392 -0
  160. data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
  161. data/lib/rigor/inference/method_dispatcher/block_folding.rb +85 -24
  162. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
  163. data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
  164. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +4 -0
  165. data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
  166. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +113 -73
  167. data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
  168. data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
  169. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +881 -38
  170. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
  171. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +128 -53
  172. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +1 -1
  173. data/lib/rigor/inference/method_dispatcher.rb +214 -13
  174. data/lib/rigor/inference/method_parameter_binder.rb +8 -3
  175. data/lib/rigor/inference/multi_target_binder.rb +340 -52
  176. data/lib/rigor/inference/mutation_rejoin.rb +4 -1
  177. data/lib/rigor/inference/mutation_widening.rb +70 -48
  178. data/lib/rigor/inference/narrowing.rb +540 -120
  179. data/lib/rigor/inference/operand_effects.rb +167 -0
  180. data/lib/rigor/inference/operand_walk.rb +88 -0
  181. data/lib/rigor/inference/optimistic_origin.rb +152 -9
  182. data/lib/rigor/inference/parameter_inference_collector.rb +3 -2
  183. data/lib/rigor/inference/project_method_ownership.rb +136 -0
  184. data/lib/rigor/inference/project_patched_methods.rb +7 -2
  185. data/lib/rigor/inference/project_patched_scanner.rb +7 -3
  186. data/lib/rigor/inference/receiver_alias.rb +90 -1
  187. data/lib/rigor/inference/receiver_blind_block.rb +219 -0
  188. data/lib/rigor/inference/refinement_mutation.rb +15 -11
  189. data/lib/rigor/inference/repeated_or_writes.rb +463 -0
  190. data/lib/rigor/inference/return_barrier.rb +54 -0
  191. data/lib/rigor/inference/rewrite_mutation.rb +120 -0
  192. data/lib/rigor/inference/scope_indexer.rb +4615 -551
  193. data/lib/rigor/inference/statement_evaluator.rb +3176 -490
  194. data/lib/rigor/inference/stored_block_call.rb +54 -0
  195. data/lib/rigor/inference/string_mutation.rb +44 -7
  196. data/lib/rigor/inference/unknown_store_widening.rb +200 -0
  197. data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
  198. data/lib/rigor/language_server/debouncer.rb +0 -1
  199. data/lib/rigor/language_server/diagnostic_publisher.rb +3 -2
  200. data/lib/rigor/language_server/hover_renderer.rb +3 -3
  201. data/lib/rigor/language_server/project_context.rb +5 -3
  202. data/lib/rigor/mcp/server.rb +2 -1
  203. data/lib/rigor/plugin/base.rb +168 -5
  204. data/lib/rigor/plugin/box_probe.rb +91 -0
  205. data/lib/rigor/plugin/bundled_catalog.rb +1 -1
  206. data/lib/rigor/plugin/effect_attribution.rb +58 -4
  207. data/lib/rigor/plugin/loader.rb +2 -1
  208. data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
  209. data/lib/rigor/plugin/manifest.rb +71 -10
  210. data/lib/rigor/plugin/registry.rb +35 -1
  211. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +9 -3
  212. data/lib/rigor/plugin/template_unit.rb +196 -0
  213. data/lib/rigor/plugin.rb +1 -0
  214. data/lib/rigor/protection/discovery_seed.rb +3 -1
  215. data/lib/rigor/protection/kill_signature.rb +0 -1
  216. data/lib/rigor/protection/mutation_cache.rb +1 -2
  217. data/lib/rigor/rbs_extended.rb +27 -0
  218. data/lib/rigor/reflection/constant_ancestors.rb +97 -0
  219. data/lib/rigor/reflection/constant_path.rb +19 -6
  220. data/lib/rigor/reflection.rb +72 -105
  221. data/lib/rigor/scope/discovery_index.rb +135 -2
  222. data/lib/rigor/scope.rb +859 -49
  223. data/lib/rigor/sig_gen/alias_index.rb +289 -0
  224. data/lib/rigor/sig_gen/classification.rb +22 -5
  225. data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
  226. data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
  227. data/lib/rigor/sig_gen/generator.rb +558 -31
  228. data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
  229. data/lib/rigor/sig_gen/method_candidate.rb +47 -3
  230. data/lib/rigor/sig_gen/observation_collector.rb +1 -1
  231. data/lib/rigor/sig_gen/renderer.rb +124 -9
  232. data/lib/rigor/sig_gen/skip_reason_catalog.rb +44 -1
  233. data/lib/rigor/sig_gen/write_result.rb +19 -3
  234. data/lib/rigor/sig_gen/writer.rb +166 -35
  235. data/lib/rigor/sig_gen.rb +3 -0
  236. data/lib/rigor/signature_path_audit.rb +1 -1
  237. data/lib/rigor/source/node_walker.rb +0 -3
  238. data/lib/rigor/source/parameter_envelope.rb +72 -0
  239. data/lib/rigor/source.rb +1 -0
  240. data/lib/rigor/type/combinator.rb +88 -12
  241. data/lib/rigor/type/difference.rb +1 -0
  242. data/lib/rigor/type/hash_shape.rb +1 -1
  243. data/lib/rigor/type/refined.rb +1 -0
  244. data/lib/rigor/version.rb +1 -1
  245. data/lib/rigor.rb +1 -0
  246. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
  247. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +9 -5
  248. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +13 -4
  249. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +0 -1
  250. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
  251. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
  252. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
  253. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
  254. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
  255. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
  256. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +239 -4
  257. data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
  258. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
  259. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
  260. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
  261. data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
  262. data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
  263. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -0
  264. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +9 -5
  265. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
  266. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
  267. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +380 -3
  268. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
  269. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +281 -35
  270. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
  271. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +25 -14
  272. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
  273. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +171 -5
  274. data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +2 -0
  275. data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +1 -0
  276. data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
  277. data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
  278. data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
  279. data/plugins/rigor-grape/sig/grape.rbs +263 -0
  280. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +72 -2
  281. data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
  282. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -0
  283. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +11 -7
  284. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +35 -37
  285. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -1
  286. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -0
  287. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +1 -0
  288. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +9 -17
  289. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
  290. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +217 -36
  291. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +1 -0
  292. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +9 -5
  293. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +0 -1
  294. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +46 -1
  295. data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
  296. data/sig/rigor/analysis/baseline.rbs +69 -7
  297. data/sig/rigor/analysis/fact_store.rbs +1 -1
  298. data/sig/rigor/analysis/project_scan.rbs +74 -0
  299. data/sig/rigor/effects/config_envelopes.rbs +100 -0
  300. data/sig/rigor/effects/effect_table.rbs +60 -0
  301. data/sig/rigor/effects/envelope.rbs +97 -0
  302. data/sig/rigor/effects/envelope_index.rbs +33 -0
  303. data/sig/rigor/effects/file_collection.rbs +81 -0
  304. data/sig/rigor/effects/label.rbs +26 -0
  305. data/sig/rigor/effects/label_set.rbs +46 -0
  306. data/sig/rigor/effects/method_key.rbs +24 -0
  307. data/sig/rigor/effects/origin.rbs +50 -0
  308. data/sig/rigor/effects/plugin_facts.rbs +141 -0
  309. data/sig/rigor/effects/registry.rbs +68 -0
  310. data/sig/rigor/effects/summary.rbs +50 -0
  311. data/sig/rigor/effects/taint_cause.rbs +12 -0
  312. data/sig/rigor/environment.rbs +12 -10
  313. data/sig/rigor/inference/optimistic_origin.rbs +10 -0
  314. data/sig/rigor/inference.rbs +6 -4
  315. data/sig/rigor/plugin/additional_initializer.rbs +36 -0
  316. data/sig/rigor/plugin/base.rbs +30 -7
  317. data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
  318. data/sig/rigor/plugin/effect_attribution.rbs +66 -0
  319. data/sig/rigor/plugin/effect_edge.rbs +33 -0
  320. data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
  321. data/sig/rigor/plugin/io_boundary.rbs +1 -1
  322. data/sig/rigor/plugin/loader.rbs +3 -3
  323. data/sig/rigor/plugin/manifest.rbs +50 -11
  324. data/sig/rigor/plugin/protocol_contract.rbs +68 -0
  325. data/sig/rigor/plugin/registry.rbs +62 -1
  326. data/sig/rigor/plugin.rbs +1 -1
  327. data/sig/rigor/rbs_extended.rbs +1 -1
  328. data/sig/rigor/reflection.rbs +7 -6
  329. data/sig/rigor/scope.rbs +135 -20
  330. data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -7
  331. data/sig/rigor/source.rbs +4 -4
  332. data/sig/rigor/testing.rbs +10 -4
  333. data/sig/rigor/type.rbs +6 -0
  334. data/sig/rigor.rbs +38 -20
  335. data/skills/rigor-ask/SKILL.md +8 -5
  336. data/skills/rigor-baseline-reduce/SKILL.md +4 -6
  337. data/skills/rigor-ci-setup/SKILL.md +17 -21
  338. data/skills/rigor-doctor/SKILL.md +24 -22
  339. data/skills/rigor-doctor/references/01-checks.md +97 -33
  340. data/skills/rigor-editor-setup/SKILL.md +6 -4
  341. data/skills/rigor-mcp-setup/SKILL.md +5 -4
  342. data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
  343. data/skills/rigor-next-steps/SKILL.md +4 -2
  344. data/skills/rigor-plugin-author/SKILL.md +19 -23
  345. data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
  346. data/skills/rigor-plugin-author/references/02-walker-and-types.md +12 -25
  347. data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
  348. data/skills/rigor-plugin-review/SKILL.md +6 -4
  349. data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
  350. data/skills/rigor-plugin-tune/SKILL.md +4 -2
  351. data/skills/rigor-project-init/SKILL.md +9 -7
  352. data/skills/rigor-project-init/references/01-detect.md +13 -9
  353. data/skills/rigor-project-init/references/02-configure.md +33 -8
  354. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
  355. data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
  356. data/skills/rigor-protection-uplift/SKILL.md +4 -6
  357. data/skills/rigor-rbs-setup/SKILL.md +4 -2
  358. data/skills/rigor-type-oracle/SKILL.md +4 -6
  359. data/skills/rigor-type-oracle/references/01-oracle-commands.md +12 -8
  360. data/skills/rigor-type-oracle/references/03-gap-protocol.md +0 -3
  361. data/skills/rigor-unused-adjudicate/SKILL.md +4 -2
  362. data/skills/rigor-upgrade/SKILL.md +13 -8
  363. metadata +108 -1
@@ -8,9 +8,70 @@ class Rigor::Plugin::Registry
8
8
  def self.materialize: (blueprints: untyped, services: untyped) -> Rigor::Plugin::Registry
9
9
 
10
10
  def initialize: (?plugins: untyped, ?load_errors: untyped, ?blueprints: untyped) -> void
11
- def find: (String | Symbol id) -> untyped
11
+ def find: (String | Symbol id) -> Rigor::Plugin::Base?
12
12
  def ids: () -> Array[String]
13
13
  def empty?: () -> bool
14
14
  def any_load_errors?: () -> bool
15
15
  def type_node_resolvers: () -> Array[untyped]
16
+ def rbs_complete_ancestors: () -> Array[String]
17
+ def rbs_complete_ancestor?: (untyped class_name) -> bool
18
+
19
+ # Newly declared — the attr_reader was absent from the sig. `compile_aggregates` builds the ivar
20
+ # with `flat_map` over the manifests (not from an `initialize` parameter, so this is unmarked
21
+ # residue like the `rbs_complete_ancestors` sibling rather than a #1154 row); the element type is
22
+ # `AdditionalInitializer`, enforced per manifest by `validate_additional_initializers!`.
23
+ attr_reader additional_initializers: Array[Rigor::Plugin::AdditionalInitializer]
24
+
25
+ # Newly declared — same unmarked-residue shape as `additional_initializers` (a
26
+ # `compile_aggregates` flat_map ivar, not an initialize-parameter read).
27
+ attr_reader protocol_contracts: Array[Rigor::Plugin::ProtocolContract]
28
+
29
+ # The subset of `protocol_contracts` whose `path_glob` matches `path` (memoised per path).
30
+ def contracts_for_path: (untyped path) -> Array[Rigor::Plugin::ProtocolContract]
31
+
32
+ # ADR-103 WD2/WD6/WD10/WD14 — every loaded plugin's effect contribution, in registration order.
33
+ # Lazy and memoised like `contracts_for_path`: computing it can force a plugin's project-facts
34
+ # read, which a run with effects off must never pay. Unmarked residue — a memoised
35
+ # `filter_map` aggregate, not an `initialize`-parameter read.
36
+ def effect_contributions: () -> Array[Contribution]
37
+
38
+ # One plugin's effect contribution, flattened off whichever surface answered it. Carries the two
39
+ # authority answers — `owner`, the label root this plugin may open, and `discharge_allowed`,
40
+ # whether its attributions may discharge — so nothing downstream re-derives who is first-party.
41
+ class Contribution < ::Data
42
+ # sig-gen gap: #1150 — a `Data.define` member; sig-gen proposes `untyped`.
43
+ attr_reader id: String
44
+ # sig-gen gap: #1150 — a `Data.define` member.
45
+ attr_reader owner: String
46
+ # sig-gen gap: #1150 — a `Data.define` member.
47
+ attr_reader requested_root: String?
48
+ # sig-gen gap: #1150 — a `Data.define` member.
49
+ attr_reader discharge_allowed: bool
50
+ # sig-gen gap: #1150 — a `Data.define` member.
51
+ attr_reader labels: Array[String]
52
+ # sig-gen gap: #1150 — a `Data.define` member.
53
+ attr_reader attributions: Array[EffectAttribution]
54
+ # sig-gen gap: #1150 — a `Data.define` member.
55
+ attr_reader edges: Array[EffectEdge]
56
+ # sig-gen gap: #1150 — a `Data.define` member.
57
+ attr_reader entry_points: Array[EffectEntryPoints]
58
+ # sig-gen gap: #1150 — a `Data.define` member.
59
+ attr_reader ancestry: Array[EffectAncestry]
60
+
61
+ # sig-gen gap: #1150 — member constructor. The custom `initialize` defaults `ancestry:`;
62
+ # the positional arm `Data` dispatches bypasses it, so only the kwargs arm is declared
63
+ # (same shape as `Effects::PluginFacts::Row`).
64
+ def self.new: (id: String, owner: String, requested_root: String?, discharge_allowed: bool,
65
+ labels: Array[String], attributions: Array[EffectAttribution],
66
+ edges: Array[EffectEdge], entry_points: Array[EffectEntryPoints],
67
+ ?ancestry: Array[EffectAncestry]) -> instance
68
+ # sig-gen gap: #1150 — as above.
69
+ def self.[]: (id: String, owner: String, requested_root: String?, discharge_allowed: bool,
70
+ labels: Array[String], attributions: Array[EffectAttribution],
71
+ edges: Array[EffectEdge], entry_points: Array[EffectEntryPoints],
72
+ ?ancestry: Array[EffectAncestry]) -> instance
73
+
74
+ # Whether the row carries nothing — no labels, attributions, edges, entry points, or ancestry.
75
+ def empty?: () -> bool
76
+ end
16
77
  end
data/sig/rigor/plugin.rbs CHANGED
@@ -3,6 +3,6 @@ module Rigor
3
3
  def self.register: (Class plugin_class) -> Class
4
4
  def self.registered_for: (String | Symbol id) -> Class?
5
5
  def self.registered: () -> Hash[String, Class]
6
- def self.unregister!: (?(String | Symbol)? id) -> untyped
6
+ def self.unregister!: (?(String | Symbol)? id) -> void
7
7
  end
8
8
  end
@@ -51,7 +51,7 @@ module Rigor
51
51
  # (`RBS::Definition::Method#annotations`, or a declaration / member's own `#annotations`); the result
52
52
  # is a `Rigor::Effects::Envelope`, or nil when the list carries neither purity spelling.
53
53
  def self?.pure_annotation?: (String? string) -> bool
54
- def self?.read_effect_envelope: (untyped annotations, owner_key: String, ?source: Symbol, ?registry: untyped, ?reporter: untyped) -> untyped?
54
+ def self?.read_effect_envelope: (untyped annotations, owner_key: String, ?source: Symbol, ?registry: untyped, ?reporter: untyped) -> Effects::Envelope?
55
55
 
56
56
  class ParamOverride
57
57
  attr_reader param_name: Symbol
@@ -7,14 +7,15 @@ module Rigor
7
7
  def self?.nominal_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Nominal?
8
8
  def self?.singleton_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Singleton?
9
9
  def self?.constant_type_for: (String | Symbol constant_name, ?scope: Scope) -> Type::t?
10
- def self?.resolve_constant_type: (String | Symbol name, ?scope: Scope, ?rooted: bool) -> Type::t?
11
- # sig-gen gap: #656 — sig-gen skips the method (untyped return), so the resolved-name-or-decline is hand-written.
10
+ def self?.resolve_constant_type: (String | Symbol name, ?scope: Scope, ?rooted: bool, ?caller_derived: bool) -> Type::t?
11
+ # sig-gen gap: #1157 — sig-gen skips the method (untyped return: the `&known` block-taking resolver
12
+ # declines through `nil` paths), so the resolved-name-or-decline is hand-written.
12
13
  def self?.resolve_constant_path_name: (String | Symbol name, Scope scope) { (String candidate) -> boolish } -> String?
13
14
  def self?.lexical_nesting_chain: (Scope scope) -> Array[String]
14
- def self?.instance_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
15
- def self?.singleton_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
16
- def self?.instance_definition: (String | Symbol class_name, ?scope: Scope) -> untyped
17
- def self?.singleton_definition: (String | Symbol class_name, ?scope: Scope) -> untyped
15
+ def self?.instance_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> ::RBS::Definition::Method?
16
+ def self?.singleton_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> ::RBS::Definition::Method?
17
+ def self?.instance_definition: (String | Symbol class_name, ?scope: Scope) -> ::RBS::Definition?
18
+ def self?.singleton_definition: (String | Symbol class_name, ?scope: Scope) -> ::RBS::Definition?
18
19
  def self?.class_type_param_names: (String | Symbol class_name, ?scope: Scope) -> Array[Symbol]
19
20
  def self?.discovered_class?: (String | Symbol class_name, ?scope: Scope) -> bool
20
21
  def self?.discovered_method?: (String | Symbol class_name, String | Symbol method_name, ?kind: Symbol, ?scope: Scope) -> bool
data/sig/rigor/scope.rbs CHANGED
@@ -14,14 +14,29 @@ module Rigor
14
14
  attr_reader void_origins: Hash[untyped, Inference::VoidOrigin]
15
15
  attr_reader plugin_typed_calls: Hash[untyped, bool]
16
16
  attr_reader optimistic_origins: Hash[untyped, Symbol]
17
- attr_reader optimistic_locals: Hash[Symbol, Symbol]
18
- attr_reader optimistic_ivars: Hash[Symbol, Symbol]
17
+ # A marked binding whose miss answer is known stores an `Inference::OptimisticOrigin::BoundMark` (a `Data`)
18
+ # in place of its bare cause (issue #1302).
19
+ attr_reader optimistic_locals: Hash[Symbol, Symbol | Data]
20
+ attr_reader optimistic_ivars: Hash[Symbol, Symbol | Data]
21
+ # sig-gen gap: #1154 — an `attr_reader` over an ivar assigned in `initialize` from a parameter reaches `untyped`.
22
+ attr_reader repeated_or_writes: Hash[untyped, bool]
23
+ # sig-gen gap: #1154 — the same reader shape; `Inference::MatchRebinding::Frame` carries no signature.
24
+ attr_reader match_frame: untyped
19
25
  attr_reader indexed_narrowings: Hash[IndexedKey, Type::t]
20
26
  attr_reader method_chain_narrowings: Hash[ChainKey, Type::t]
21
27
  attr_reader source_path: String?
22
28
  attr_reader struct_fold_safe_locals: Set[Symbol]
23
29
  attr_reader opaque_block_self: bool
30
+ # sig-gen gap: #1154 — sig-gen skips the reader (sig.skipped.untyped-return): an `attr_reader`
31
+ # over an ivar assigned in `initialize` from a parameter, so inference reaches `untyped`.
32
+ attr_reader singleton_class_body: bool
24
33
  attr_reader lexical_nesting: Array[String]?
34
+ # Issue #1429 — a guard's narrowing of a constant reference, keyed by its spelling.
35
+ # sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
36
+ attr_reader constant_narrowings: Hash[String, Type::t]
37
+ # Issue #1429 — the pre-guard type of each global or constant a guard narrowed.
38
+ # sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
39
+ attr_reader guard_records: Hash[[Symbol, Symbol | String], Type::t]
25
40
 
26
41
  # ADR-53 Track A — the seed-time discovery tables live on the
27
42
  # DiscoveryIndex; Scope keeps per-table readers as delegates.
@@ -37,15 +52,34 @@ module Rigor
37
52
  def discovered_def_sources: () -> Hash[String, Hash[Symbol, String]]
38
53
  def discovered_singleton_def_sources: () -> Hash[String, Hash[Symbol, String]]
39
54
  def discovered_method_visibilities: () -> Hash[String, Hash[Symbol, Symbol]]
55
+ # sig-gen gap: #1148 — sig-gen skips an endless-def reader (untyped return); the row is hand-written.
56
+ def discovered_parameter_envelopes: () -> Hash[String, Hash[untyped, untyped]]
57
+ # sig-gen gap: #1149 — sig-gen skips the `||` fallback reader (untyped return); the row is hand-written.
58
+ def parameter_envelopes_of: (String class_name) -> Hash[untyped, untyped]
40
59
  def discovered_superclasses: () -> Hash[String, String]
60
+ # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the per-file
61
+ # deferred-range table's row shape is hand-written.
62
+ def discovered_deferred_ranges: () -> Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]]
63
+ # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the refinement table's
64
+ # shape is hand-written.
65
+ def discovered_refinements: () -> Hash[String, Hash[Symbol, Array[String]]]
66
+ # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the census shape is
67
+ # hand-written.
68
+ def discovered_global_write_census: () -> Set[Array[untyped]]
41
69
  def discovered_includes: () -> Hash[String, Array[String]]
42
- # sig-gen gap: #898 — sig-gen skips the endless-def reader (untyped return), so the table shape is hand-written.
70
+ # Issue #1123 — the instance-ancestor-ORDER table beside the include one.
71
+ def discovered_prepends: () -> Hash[String, Array[String]]
72
+ # sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the table shape is hand-written.
43
73
  def discovered_extends: () -> Hash[String, Array[String]]
44
74
  def discovered_class_sources: () -> Hash[String, Set[String]]
45
75
  def constant_sources: () -> Hash[String, Set[String]]
46
76
  def published_constant_names: () -> Set[String]
47
77
  def local_constant_names: () -> Set[String]
48
- # sig-gen gap: #667 — sig-gen types the `||` fallback `untyped`, so the element type is hand-written.
78
+ # sig-gen gap: #1150 — the `Data.define` table it reads carries no type, so sig-gen skips the return; the shape is hand-written.
79
+ def bound_constant_names: (String name) -> Array[String]
80
+ # sig-gen gap: #1150 — the `Data.define` table it reads carries no type, so sig-gen skips the return; the shape is hand-written.
81
+ def shadowing_constant_names: (String name) -> Array[String]
82
+ # sig-gen gap: #1149 — sig-gen types the `||` fallback `untyped`, so the element type is hand-written.
49
83
  def published_constant_ivars_for: (String class_name) -> Set[Symbol]
50
84
  def published_constant?: (String name) -> bool
51
85
  def record_constant_dependency: (String name) -> void
@@ -62,11 +96,17 @@ module Rigor
62
96
  def record_plugin_typed_call: (untyped node) -> Scope
63
97
  def plugin_typed_call?: (untyped node) -> bool
64
98
 
99
+ def with_repeated_or_writes: (untyped nodes) -> Rigor::Scope
100
+ # sig-gen gap: #1154 — `Hash#key?` over that reader reaches `untyped`, so the `bool` is hand-written.
101
+ def repeated_or_write?: (untyped node) -> bool
102
+
65
103
  class DiscoveryIndex
66
104
  attr_reader declared_types: Hash[untyped, Type::t]
67
105
  attr_reader class_ivars: Hash[String, Hash[Symbol, Type::t]]
68
106
  attr_reader class_cvars: Hash[String, Hash[Symbol, Type::t]]
69
107
  attr_reader program_globals: Hash[Symbol, Type::t]
108
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
109
+ attr_reader program_global_seeds: Hash[Symbol, Type::t]
70
110
  attr_reader discovered_classes: Hash[String, Type::Singleton]
71
111
  attr_reader in_source_constants: Hash[String, Type::t]
72
112
  attr_reader discovered_methods: Hash[String, Hash[Symbol, Symbol]]
@@ -76,26 +116,48 @@ module Rigor
76
116
  attr_reader discovered_def_sources: Hash[String, Hash[Symbol, String]]
77
117
  attr_reader discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]]
78
118
  attr_reader discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]]
119
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
120
+ attr_reader discovered_parameter_envelopes: Hash[String, Hash[untyped, untyped]]
79
121
  attr_reader discovered_superclasses: Hash[String, String]
80
122
  attr_reader discovered_includes: Hash[String, Array[String]]
81
- # sig-gen gap: #898 — `Data.define` members carry no type, as for every other row in this class.
123
+ attr_reader discovered_prepends: Hash[String, Array[String]]
124
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
82
125
  attr_reader discovered_extends: Hash[String, Array[String]]
83
126
  attr_reader discovered_class_sources: Hash[String, Set[String]]
84
127
  attr_reader constant_sources: Hash[String, Set[String]]
128
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
129
+ attr_reader constant_writers: Hash[String, Array[String]]
130
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
131
+ attr_reader constant_shadowers: Hash[String, Array[String]]
85
132
  attr_reader published_constant_names: Set[String]
86
133
  attr_reader local_constant_names: Set[String]
87
- # sig-gen gap: #667 — `Data.define` members carry no type, so every row in this class is authored.
134
+ # sig-gen gap: #1150 — `Data.define` members carry no type, so every row in this class is authored.
88
135
  attr_reader published_constant_alias_names: Set[String]
89
- # sig-gen gap: #667 — as above.
136
+ # sig-gen gap: #1150 — as above.
90
137
  attr_reader published_constant_ivars: Hash[String, Set[Symbol]]
91
138
  attr_reader data_member_layouts: Hash[String, Array[Symbol]]
92
139
  attr_reader struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }]
93
140
  attr_reader param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
141
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
142
+ attr_reader discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]]
143
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
144
+ attr_reader discovered_refinements: Hash[String, Hash[Symbol, Array[String]]]
145
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
146
+ attr_reader discovered_global_write_census: Set[Array[untyped]]
94
147
  attr_reader run_generation: Object?
148
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
149
+ attr_reader patched_line_readers: Set[Symbol]
150
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
151
+ attr_reader clears_last_status: bool
152
+ # sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
153
+ attr_reader defines_case_equality: bool
154
+ # `untyped`: the value is an `Inference::LastLine::SelfEvidence` (or nil), and that class carries no signature,
155
+ # as `Inference::MatchRebinding::Frame` carries none for `match_frame`.
156
+ attr_reader implicit_self_evidence: untyped
95
157
 
96
158
  EMPTY: DiscoveryIndex
97
159
 
98
- def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?run_generation: Object?) -> DiscoveryIndex
160
+ def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?program_global_seeds: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_parameter_envelopes: Hash[String, Hash[untyped, untyped]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_prepends: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?constant_writers: Hash[String, Array[String]], ?constant_shadowers: Hash[String, Array[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?discovered_refinements: Hash[String, Hash[Symbol, Array[String]]], ?discovered_global_write_census: Set[Array[untyped]], ?run_generation: Object?, ?patched_line_readers: Set[Symbol], ?clears_last_status: bool, ?defines_case_equality: bool, ?implicit_self_evidence: untyped) -> DiscoveryIndex
99
161
  end
100
162
 
101
163
  class IndexedKey
@@ -119,6 +181,9 @@ module Rigor
119
181
  def struct_fold_safe?: (String | Symbol name) -> bool
120
182
  def entering_opaque_block: () -> Scope
121
183
  def opaque_block_self?: () -> bool
184
+ def with_singleton_class_body: (bool) -> Scope
185
+ # sig-gen gap: #1148 — sig-gen skips the endless-def reader (sig.skipped.untyped-return); the row is hand-written.
186
+ def singleton_class_body?: () -> bool
122
187
  def with_discovery: (DiscoveryIndex index) -> Scope
123
188
  def local: (String | Symbol name) -> Type::t?
124
189
  def ivar: (String | Symbol name) -> Type::t?
@@ -128,54 +193,104 @@ module Rigor
128
193
  def ivar_origin: (String | Symbol name) -> Symbol?
129
194
  def optimistic_local: (String | Symbol name) -> Symbol?
130
195
  def optimistic_ivar: (String | Symbol name) -> Symbol?
196
+ def optimistic_local_miss: (String | Symbol name) -> Object?
197
+ def optimistic_ivar_miss: (String | Symbol name) -> Object?
131
198
  def with_local: (String | Symbol name, Type::t type) -> Scope
132
199
  def with_ivar: (String | Symbol name, Type::t type) -> Scope
133
200
  def with_local_origin: (String | Symbol name, Symbol? cause) -> Scope
134
- def with_optimistic_local: (String | Symbol name, Symbol? cause) -> Scope
135
- def with_optimistic_ivar: (String | Symbol name, Symbol? cause) -> Scope
201
+ def with_optimistic_local: (String | Symbol name, Symbol? cause, ?miss: Object?) -> Scope
202
+ def with_optimistic_ivar: (String | Symbol name, Symbol? cause, ?miss: Object?) -> Scope
136
203
  def with_ivar_origin: (String | Symbol name, Symbol? cause) -> Scope
137
204
  def with_cvar: (String | Symbol name, Type::t type) -> Scope
138
205
  def with_global: (String | Symbol name, Type::t type) -> Scope
139
- # sig-gen gap: #667 — an `attr_reader` over a frozen Set literal types `untyped`, as the sibling
206
+ # Issue #1429 — `rigor sig-gen` output; the parameters are not inferred here, as for `with_mutated_local`.
207
+ def with_guarded_global: (untyped name, untyped type, untyped pre_guard, ?record: untyped) -> Scope
208
+ def with_constant_narrowing: (untyped key, untyped type, untyped pre_guard) -> Scope
209
+ def without_constant_narrowing: (untyped key) -> Scope
210
+ def guard_narrowed?: () -> bool
211
+ def forget_guard_narrowings: () -> Scope
212
+ def forget_guard_narrowing_of: (untyped kind, untyped name) -> Scope
213
+ def without_constant_narrowings_named: (untyped name) -> Scope
214
+ # sig-gen gap: #1154 — the table reader over an ivar `initialize` assigns from a parameter reaches `untyped`.
215
+ def constant_narrowing: (String key) -> Type::t?
216
+ # sig-gen gap: #1151 — an `attr_reader` over a frozen Set literal types `untyped`, as the sibling
140
217
  # `declaration_sourced` row does.
141
218
  def published_constant_sourced: () -> Set[[Symbol, Symbol]]
142
- # sig-gen gap: #667 — `Set#include?` over a tuple key types `untyped`, so the `bool` is hand-written.
219
+ # sig-gen gap: #1152 — `Set#include?` over a tuple key types `untyped`, so the `bool` is hand-written.
143
220
  def published_constant_sourced?: (Symbol kind, String | Symbol name) -> bool
144
221
  def with_published_constant_mark: (Symbol kind, String | Symbol name) -> Scope
145
- def declaration_sourced: () -> Set[[Symbol, Symbol]]
222
+ # Issue #1362 — a `[:global_copy, local, global]` record rides beside the `(kind, name)` refs.
223
+ def declaration_sourced: () -> Set[[Symbol, Symbol] | [Symbol, Symbol, Symbol]]
146
224
  def seed_declaration_sourced_ivar: (String | Symbol name, Type::t type) -> Scope
225
+ def seed_declaration_sourced_global: (String | Symbol name, Type::t type) -> Scope
226
+ def with_global_copy_marks: (String | Symbol name, Array[String | Symbol] globals) -> Scope
227
+ def without_local_declaration_marks: (String | Symbol name) -> Scope
228
+ # sig-gen gap: #1154 — the records come out of `@declaration_sourced`, an ivar assigned in `initialize` from a
229
+ # parameter, which reaches `untyped`.
230
+ def declaration_sourced_global_copies: (String | Symbol name) -> Array[Symbol]
147
231
  def with_declaration_sourced_local: (String | Symbol name, Type::t type) -> Scope
148
232
  def with_local_declaration_mark: (String | Symbol name) -> Scope
233
+ # `rigor sig-gen --params=observed` output; the siblings' hand-written `String | Symbol` / `Type::t`
234
+ # parameters are not inferred here either.
235
+ def with_mutated_local: (untyped name, untyped type) -> Scope
149
236
  def declaration_sourced?: (Symbol kind, String | Symbol name) -> bool
150
237
  def with_inferred_param_mark: (String | Symbol name) -> Scope
151
238
  def without_inferred_param_mark: (String | Symbol name) -> Scope
152
239
  def inferred_param?: (String | Symbol name) -> bool
153
240
  def forget_match_globals: () -> Scope
241
+ def untyped_match_globals: () -> Scope
242
+ def match_globals_bound?: () -> bool
243
+ def with_match_frame: (untyped body, ?untyped parameters) -> Scope
244
+ # sig-gen gap: #1154 — the frame reader over an ivar assigned in `initialize` from a parameter reaches
245
+ # `untyped`, so the `bool` is hand-written.
246
+ def match_rebinding_closure?: () -> bool
247
+ def forget_last_line: () -> Scope
248
+ def untyped_last_line: () -> Scope
249
+ # sig-gen gap: #1154 — the reader over the `@globals` ivar `initialize` assigns from a parameter reaches
250
+ # `untyped`, so the `bool` is hand-written.
251
+ def last_line_bound?: () -> bool
252
+ # sig-gen gap: #1154 — the frame reader over the `@match_frame` ivar `initialize` assigns from a parameter
253
+ # reaches `untyped`, so the `bool` is hand-written.
254
+ def last_line_closure?: () -> bool
255
+ def forget_error_info: () -> Scope
256
+ def untyped_error_info: () -> Scope
257
+ def forget_last_status: () -> Scope
258
+ def untyped_last_status: () -> Scope
154
259
  def class_ivars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
155
260
  def class_cvars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
156
261
  def discovered_method?: (String | Symbol class_name, String | Symbol method_name, Symbol kind) -> bool
157
- def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
158
- def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([untyped, String] | [nil, nil])
262
+ def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
263
+ def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
159
264
  def discovered_method_through_ancestors?: (String | Symbol? class_name, String | Symbol method_name, Symbol kind, ?name_memo: Hash[untyped, untyped]) -> bool
160
265
  def external_ancestor_name_candidates: (String | Symbol class_name, ?name_memo: Hash[untyped, untyped]) -> Array[Array[String]]
161
266
  def enqueue_ancestors: (String current, Array[String] queue, Hash[untyped, untyped] name_memo, ?mixins: bool) -> void
162
267
  def ancestor_name_candidates: (String | Symbol subclass_qualified, String | Symbol raw_ancestor) -> Array[String]
163
268
 
269
+ # sig-gen gap: #1148 — sig-gen skips the method (sig.skipped.untyped-return: every decline returns the
270
+ # frozen EMPTY_HEADER_NESTING constant); the row is hand-written.
271
+ def ambiguous_ancestor_resolutions: (String | Symbol subclass_qualified, String | Symbol raw_ancestor) -> Array[String]
272
+
164
273
  # Issue #530 — public so the external-gem ancestry probe asks the same question the walk does.
165
274
  def known_user_class?: (String | Symbol name) -> bool
166
- def singleton_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
167
- def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([untyped, String] | [nil, nil])
275
+ def singleton_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
276
+ def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
168
277
  def user_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
169
278
  def user_singleton_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
170
- def top_level_def_for: (String | Symbol method_name) -> untyped?
171
- def bindable_top_level_def_for: (String | Symbol method_name) -> untyped?
279
+ # sig-gen gap: #1167 — the predicate forwards its untyped `Prism::CallNode` into the range scan,
280
+ # which reads `call_node.location` off it: a `Dynamic` receiver answers `Dynamic`, not `bool`, so
281
+ # sig-gen skips the method (and `def_shadows_call?` above it) as an untyped return.
282
+ def singleton_def_shadows_call?: (String | Symbol class_name, String | Symbol method_name, untyped call_node) -> bool
283
+ # sig-gen gap: #1167 — the instance-side twin: the same untyped `call_node`, the same untyped-return skip.
284
+ def instance_def_shadows_call?: (String | Symbol class_name, String | Symbol method_name, untyped call_node) -> bool
285
+ def top_level_def_for: (String | Symbol method_name) -> ::Prism::DefNode?
286
+ def bindable_top_level_def_for: (String | Symbol method_name) -> ::Prism::DefNode?
172
287
  def toplevel?: () -> bool
173
288
  def discovered_method_visibility: (String | Symbol class_name, String | Symbol method_name) -> Symbol?
174
289
  def superclass_of: (String | Symbol class_name) -> String?
175
290
  def data_member_layout: (String | Symbol class_name) -> Array[Symbol]?
176
291
  def struct_member_layout: (String | Symbol class_name) -> { members: Array[Symbol], keyword_init: bool }?
177
292
  def includes_of: (String | Symbol class_name) -> Array[String]
178
- # sig-gen gap: #898 — sig-gen proposes `Array[untyped] | []` off the empty-table early return, so the
293
+ # sig-gen gap: #1153 — sig-gen proposes `Array[untyped] | []` off the empty-table early return, so the
179
294
  # element type is hand-written, matching {#includes_of}.
180
295
  def singleton_extends_of: (String | Symbol class_name) -> Array[String]
181
296
  def indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Type::t?
@@ -1,11 +1,18 @@
1
+ # `Rigor::SigGen` itself has no other declaration under `sig/`; without this shell `rbs validate`
2
+ # rejects the two declarations below with `Could not find ::Rigor::SigGen`.
3
+ module Rigor::SigGen
4
+ end
5
+
6
+ # Every entry is built from string literals in `SkipReasonCatalog::ENTRIES`, so the four readers
7
+ # answer `String`.
1
8
  class Rigor::SigGen::SkipReasonCatalog::Entry < ::Data
2
- def id: () -> untyped
3
- def summary: () -> untyped
4
- def explanation: () -> untyped
5
- def next_step: () -> untyped
6
- def self.new: (id: untyped, summary: untyped, explanation: untyped, next_step: untyped) -> instance | (untyped id, untyped summary, untyped explanation, untyped next_step) -> instance
7
- def self.[]: (id: untyped, summary: untyped, explanation: untyped, next_step: untyped) -> instance | (untyped id, untyped summary, untyped explanation, untyped next_step) -> instance
8
- def to_h: () -> Hash[String, untyped]
9
+ def id: () -> String
10
+ def summary: () -> String
11
+ def explanation: () -> String
12
+ def next_step: () -> String
13
+ def self.new: (id: String, summary: String, explanation: String, next_step: String) -> instance | (String id, String summary, String explanation, String next_step) -> instance
14
+ def self.[]: (id: String, summary: String, explanation: String, next_step: String) -> instance | (String id, String summary, String explanation, String next_step) -> instance
15
+ def to_h: () -> Hash[String, String]
9
16
  end
10
17
 
11
18
  module Rigor::SigGen::SkipReasonCatalog
data/sig/rigor/source.rbs CHANGED
@@ -4,11 +4,11 @@ module Rigor
4
4
  class OutOfRangeError < StandardError
5
5
  end
6
6
 
7
- def self.at_position: (source: String, root: untyped, line: Integer, column: Integer) -> untyped?
8
- def self.at_offset: (root: untyped, offset: Integer) -> untyped?
7
+ def self.at_position: (source: String, root: untyped, line: Integer, column: Integer) -> ::Prism::Node?
8
+ def self.at_offset: (root: untyped, offset: Integer) -> ::Prism::Node?
9
9
  def initialize: (source: String, root: untyped) -> void
10
- def at_position: (line: Integer, column: Integer) -> untyped?
11
- def at_offset: (Integer offset) -> untyped?
10
+ def at_position: (line: Integer, column: Integer) -> ::Prism::Node?
11
+ def at_offset: (Integer offset) -> ::Prism::Node?
12
12
  end
13
13
 
14
14
  module Literals
@@ -1,9 +1,15 @@
1
1
  module Rigor
2
2
  module Testing
3
- def self?.dump_type: (untyped value) -> untyped
4
- def self?.assert_type: (String expected, untyped value) -> untyped
3
+ # Both helpers return `value` unchanged (lib/rigor/testing.rb); the type variable carries the
4
+ # argument's type through so a probed expression stays typed downstream instead of widening to
5
+ # `Dynamic[top]`. `A` binds only on a dispatch that carries a scope — a `Rigor.` /
6
+ # `Rigor::Testing.` receiver, or an including class that is RBS-known. A bare `dump_type(x)` after
7
+ # `include Rigor::Testing` in a discovered-only class still reaches the ancestor fallback without a
8
+ # scope and answers `Dynamic[top]`, as it did under `-> untyped` (#303 follow-up).
9
+ def self?.dump_type: [A] (A value) -> A
10
+ def self?.assert_type: [A] (String expected, A value) -> A
5
11
  end
6
12
 
7
- def self.dump_type: (untyped value) -> untyped
8
- def self.assert_type: (String expected, untyped value) -> untyped
13
+ def self.dump_type: [A] (A value) -> A
14
+ def self.assert_type: [A] (String expected, A value) -> A
9
15
  end
data/sig/rigor/type.rbs CHANGED
@@ -429,8 +429,14 @@ module Rigor
429
429
  attr_reader trinary: Trinary
430
430
  attr_reader mode: accepts_mode
431
431
  attr_reader reasons: Array[String]
432
+ # sig-gen gap: #1155 — the memoized `||=` return is an honest union with an
433
+ # untyped arm (the slot read cannot prove the memoized value), so sig-gen
434
+ # skips it (sig.skipped.untyped-return); the runtime result is always
435
+ # AcceptsResult and the row is hand-written.
432
436
  def self.yes: (?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> AcceptsResult
437
+ # sig-gen gap: #1155 — same memoized `||=` untyped-return gap as `self.yes`.
433
438
  def self.no: (?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> AcceptsResult
439
+ # sig-gen gap: #1155 — same memoized `||=` untyped-return gap as `self.yes`.
434
440
  def self.maybe: (?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> AcceptsResult
435
441
  def initialize: (Trinary trinary, ?mode: accepts_mode, ?reasons: (Array[String] | String)?) -> void
436
442
  def yes?: () -> bool
data/sig/rigor.rbs CHANGED
@@ -124,32 +124,50 @@ module Rigor
124
124
  attr_reader buffer: untyped
125
125
  attr_reader file_dependencies: Hash[String, untyped]
126
126
  attr_reader analyzed_files: Array[String]
127
- def initialize: (configuration: Configuration, ?explain: bool, ?cache_store: untyped, ?plugin_requirer: untyped, ?workers: Integer, ?collect_stats: bool, ?buffer: untyped, ?prebuilt: untyped, ?environment: untyped, ?record_dependencies: bool, ?analyze_only: untyped) -> void
127
+ def initialize: (configuration: Configuration, ?explain: bool, ?cache_store: untyped, ?plugin_requirer: untyped, ?workers: Integer, ?collect_stats: bool, ?buffer: untyped, ?prebuilt: Analysis::ProjectScan?, ?environment: untyped, ?record_dependencies: bool, ?analyze_only: untyped) -> void
128
128
  def run: (?Array[String] paths) -> Result
129
129
  def run_source: (source: String, ?path: String) -> Result
130
130
  def analysis_file_set: (?Array[String] paths) -> Array[String]
131
131
  def file_dependents: () -> Hash[String, untyped]
132
- def prepare_project_scan: (?paths: Array[String]) -> untyped
132
+ def prepare_project_scan: (?paths: Array[String]) -> Analysis::ProjectScan
133
133
  # ADR-103 — the propagated effect graph and the merged per-file collections behind it. A report
134
- # surface: never a diagnostic, empty when the configuration carries no `effects:` block. Typed
135
- # `untyped` for the same reason `cache_store` is — `Rigor::Effects` is not sig-covered yet
136
- # (`spec/rigor/public_api_drift_spec.rb`), and a named reference would raise `RBS::UnknownTypeName`.
137
- def effect_table: () -> untyped
138
- def effect_collection: () -> untyped
139
- # #381 — `{ "Class#m" => [path] }`, which the snapshot's `reach:` globs match against. Same
140
- # `untyped` reasoning as its two siblings above.
141
- def effect_sources: () -> untyped
142
- # #387 — the loaded plugins' compiled effect contributions, read by `rigor effects` so the snapshot's
143
- # vocabulary is the one the collection window scanned under. Same `untyped` reasoning again.
144
- def effect_plugin_facts: () -> untyped
134
+ # surface: never a diagnostic, empty when the configuration carries no `effects:` block.
135
+ def effect_table: () -> Effects::EffectTable
136
+ def effect_collection: () -> Effects::FileCollection
137
+ # ADR-103 WD9 (#391): the resolved envelope index `rigor sig-gen`'s annotation emission
138
+ # consults, built on demand so a warm-cache run still serves the same strata.
139
+ def effect_envelopes: () -> Effects::EnvelopeIndex
140
+ # #381 — `{ "Class#m" => [path] }`, which the snapshot's `reach:` globs match against.
141
+ def effect_sources: () -> Hash[String, Array[String]]
142
+ # #387 — the loaded plugins' compiled effect contributions, read by `rigor effects` so the
143
+ # snapshot's vocabulary is the one the collection window scanned under.
144
+ def effect_plugin_facts: () -> Effects::PluginFacts
145
+ # The run's as-written superclass table — what `effect.liskov-widened` reads.
146
+ def effect_ancestry: () -> Hash[String, String]
147
+ # `{ "lib/a.rb" => FileCollection, … }` — the per-file collections the caches persist (#382).
148
+ def effect_collections_by_path: () -> Hash[String, Effects::FileCollection]
149
+ # Issue #382 — adopt persisted collections as this run's own (the warm-hit half of the
150
+ # whole-run effects slot).
151
+ def adopt_effect_collections: (Hash[String, Effects::FileCollection] collections,
152
+ ?table: Effects::EffectTable?) -> void
153
+ # #482 — adopt the served run's small summary entry, collections left behind a loader.
154
+ def adopt_effect_summary: (table: Effects::EffectTable, sources: Hash[String, Array[String]],
155
+ ancestry: Hash[String, String], collections_loader: untyped) -> void
156
+ # Whether this run's effect collections came from the whole-run effects slot (#382).
157
+ def effects_served_from_cache?: () -> bool
145
158
  # The incremental session's read surface (ADR-46 / ADR-67 / ADR-103) — `IncrementalSession`
146
- # drives a live Runner through these between rechecks. Typed `untyped` like the cache / effects
147
- # readers above until their namespaces are sig-covered.
148
- def return_summaries: () -> untyped
149
- def param_inferred_types: () -> untyped
150
- def effect_collections_by_path: () -> untyped
151
- def collect_param_inference_table: (untyped files) -> untyped
152
- def evaluate_return_types: (untyped paths, untyped specs) -> untyped
159
+ # drives a live Runner through these between rechecks.
160
+ # sig-gen gap: #1008 — `result` is populated by `collect_return_summaries` mutating it by
161
+ # reference from a sibling method; sig-gen folds only the `{}` seed and the empty-memo early
162
+ # return, so it proposes the seed shape instead of the honest, usually-non-empty contract.
163
+ # Keys are `[path, "Class#method"]` pairs; values are `{ keys:, returns:, effects: }` bundles.
164
+ def return_summaries: () -> Hash[[String, String], Hash[Symbol, untyped]]
165
+ # ADR-67 — `[class_name, method_name, kind] => { param_name => Type }`.
166
+ def param_inferred_types: () -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
167
+ def collect_param_inference_table: (untyped files) -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
168
+ # `{ class_name:, method_name:, singleton: }` spec triple => the per-key return descriptors
169
+ # (`describe(:short)` strings; nil for a missing/bodyless def).
170
+ def evaluate_return_types: (untyped paths, untyped specs) -> Hash[[String, Symbol, bool], Array[String?]]
153
171
  end
154
172
  end
155
173
 
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-ask
3
- description: |
4
- Answer any question about Rigor by investigating, not from memory — Rigor is niche and version-specific, so run its tools and read its bundled docs, then answer from what you saw. Use `rigor docs` (handbook + manual, offline and version-matched) and `rigor explain <rule>`; for the user's own code, `rigor check` / `annotate` / `type-of`. Covers: why a line is flagged or whether it's a false positive; the type model (narrowing, refinements, `Dynamic`, RBS); config keys, flags, baselines; comparisons to Sorbet, Steep, mypy, PHPStan; whether Rigor handles Rails, RSpec, or a given gem; how to type a method; "what is Rigor / why use it / is it right for us?". Trigger on any Rigor question seeking understanding — even casual, comparative, or grumbling. Skip only when it's purely "set it up / fix / reduce it for me" (use rigor-next-steps).
3
+ description: >-
4
+ Answer a question about Rigor from version-matched bundled docs and tool output. Use when the user
5
+ asks why a diagnostic fired, how a type/config/flag works, or how Rigor compares with another tool; not
6
+ when they ask you to set up, fix, or reduce something.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.2.0
@@ -51,8 +53,9 @@ rigor --help # the live command + flag list
51
53
  rigor skill --full rigor-ask # the current version of this skill itself
52
54
  ```
53
55
 
54
- Never cite a page, flag, or rule id you have not just seen in one of these
55
- — that is this skill's whole discipline. If `rigor` is not installed, you
56
+ Cite a page, flag, or rule id only after you have seen it in this
57
+ install — `rigor docs`, `rigor --help`, `rigor explain`, or the gem's own
58
+ files (see "If the docs don't cover it"). If `rigor` is not installed, you
56
59
  can still answer high-level "what is Rigor?" questions from the web
57
60
  <https://rigor.typedduck.fail/llms.txt>, but for anything version-specific
58
61
  install it first (see `rigor-next-steps`).
@@ -80,7 +83,7 @@ Everything here is read-only and needs no network.
80
83
  | `rigor triage` | Cluster the project's diagnostics by rule / receiver / method — for "what's the shape of my errors?". |
81
84
  | `rigor coverage [--protection]` | Type / type-protection coverage — for "how well-typed is this?" and "where are the holes?". |
82
85
  | `rigor plugins` | Which plugins are installed and enabled *here* — the honest answer to "does Rigor support <gem/framework>?". |
83
- | `rigor sig-gen <path>` | Generate RBS for code — for "how do I type this?". Offer it and show the result; this project prefers sig-gen over hand-written RBS. |
86
+ | `rigor sig-gen <path>` | Generate RBS for code — for "how do I type this?". Offer it and show the result — generated RBS is derived; hand-written RBS is a guess until `rigor check` agrees (see `rigor-type-oracle`). |
84
87
 
85
88
  ## Where the answer lives
86
89
 
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: rigor-baseline-reduce
3
- description: |
4
- Work a Rigor project's `.rigor-baseline.yml` down rule by rule: prioritise with `rigor triage`, sample call sites, classify each as real bug / stylistic-safe / false positive, then fix, `# rigor:disable`, or open a Rigor issue — and regenerate the baseline. Triggers: "reduce the rigor baseline", "fix some baseline diagnostics", "what rigor issue should I fix next?". NOT for first-time setup (use rigor-project-init) or authoring a plugin (use rigor-plugin-author).
3
+ description: >-
4
+ Reduce an existing `.rigor-baseline.yml` rule by rule by triaging sites, fixing or intentionally
5
+ suppressing them, and regenerating the baseline. Use for baseline diagnostics already acknowledged by a
6
+ project; not for first-time setup or plugin authoring.
5
7
  license: MPL-2.0
6
8
  metadata:
7
9
  version: 0.1.0
@@ -37,10 +39,6 @@ header names). If `rigor` is not on `PATH`, this task needs it: run
37
39
 
38
40
  ## Phase 0 — When to use this skill
39
41
 
40
- Trigger when the user says "reduce the rigor baseline", "fix some
41
- baseline diagnostics", "what should I fix next in rigor?", or asks to
42
- work down the diagnostics a previous onboarding parenthesised.
43
-
44
42
  **Precondition: the project is in acknowledge mode.** This skill
45
43
  operates on a `.rigor-baseline.yml` that `.rigor.yml` /
46
44
  `.rigor.dist.yml` declares via `baseline:`. A strict-mode project