rigortype 0.3.9 → 0.4.1
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.
- checksums.yaml +4 -4
- data/README.md +5 -4
- data/data/core_overlay/enumerable.rbs +51 -0
- data/data/core_overlay/enumerator.rbs +84 -0
- data/data/core_overlay/hash_rbs3.rbs +41 -0
- data/data/core_overlay/process.rbs +40 -0
- data/data/core_overlay/string_io.rbs +33 -0
- data/data/effects/core.yml +3 -3
- data/data/gem_overlay/activesupport/core_ext.rbs +127 -4
- data/docs/handbook/03-narrowing.md +95 -10
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/07-rbs-and-extended.md +16 -11
- data/docs/handbook/08-understanding-errors.md +3 -2
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +454 -13
- data/docs/install.md +87 -15
- data/docs/manual/02-cli-reference.md +65 -4
- data/docs/manual/03-configuration.md +12 -0
- data/docs/manual/04-diagnostics.md +4 -0
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/08-skills.md +4 -3
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/12-caching.md +43 -4
- data/docs/manual/14-rails-quickstart.md +19 -11
- data/docs/manual/16-rbs-extended-annotations.md +40 -7
- data/docs/manual/19-effect-labels.md +10 -0
- data/docs/manual/plugins/README.md +7 -0
- data/docs/manual/plugins/rigor-actioncable.md +8 -1
- data/docs/manual/plugins/rigor-actionmailer.md +7 -0
- data/docs/manual/plugins/rigor-actionpack.md +243 -0
- data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
- data/docs/manual/plugins/rigor-activejob.md +7 -0
- data/docs/manual/plugins/rigor-activerecord.md +110 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +11 -5
- data/docs/manual/plugins/rigor-grape.md +106 -0
- data/docs/manual/plugins/rigor-graphql.md +23 -2
- data/docs/manual/plugins/rigor-pundit.md +8 -1
- data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
- data/docs/manual/plugins/rigor-rails-routes.md +7 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +212 -25
- data/docs/manual/plugins/rigor-sidekiq.md +8 -1
- data/docs/manual/plugins/rigor-sorbet.md +21 -5
- data/exe/rigor +19 -4
- data/lib/rigor/analysis/baseline.rb +1 -1
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -3
- data/lib/rigor/analysis/check_rules/rule_ids.rb +20 -5
- data/lib/rigor/analysis/check_rules/rule_walk.rb +2 -1
- data/lib/rigor/analysis/check_rules/source_arity.rb +427 -0
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +36 -2
- data/lib/rigor/analysis/check_rules.rb +638 -136
- data/lib/rigor/analysis/dependency_recorder.rb +222 -17
- data/lib/rigor/analysis/fact_store.rb +9 -0
- data/lib/rigor/analysis/incremental.rb +26 -0
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +266 -0
- data/lib/rigor/analysis/incremental_run_slot.rb +171 -0
- data/lib/rigor/analysis/incremental_session.rb +309 -53
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +24 -13
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/plugin_roots.rb +0 -1
- data/lib/rigor/analysis/reachability/scan_cache.rb +3 -1
- data/lib/rigor/analysis/rule_catalog.rb +127 -0
- data/lib/rigor/analysis/run_cache_key.rb +46 -18
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +168 -12
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -4
- data/lib/rigor/analysis/runner/pool_coordinator.rb +109 -17
- data/lib/rigor/analysis/runner/project_pre_passes.rb +44 -17
- data/lib/rigor/analysis/runner.rb +603 -54
- data/lib/rigor/analysis/shadow_harness.rb +27 -0
- data/lib/rigor/analysis/source_rbs_gate.rb +157 -0
- data/lib/rigor/analysis/template_unit_collector.rb +303 -0
- data/lib/rigor/analysis/template_unit_paths.rb +93 -0
- data/lib/rigor/analysis/template_unit_positions.rb +293 -0
- data/lib/rigor/analysis/template_units.rb +409 -0
- data/lib/rigor/analysis/worker_session.rb +57 -13
- data/lib/rigor/bleeding_edge.rb +0 -2
- data/lib/rigor/builtins/hkt_builtins.rb +1 -0
- data/lib/rigor/builtins/imported_refinements.rb +4 -0
- data/lib/rigor/builtins/regex_refinement.rb +17 -9
- data/lib/rigor/builtins/static_return_refinements.rb +2 -0
- data/lib/rigor/cache/descriptor.rb +45 -1
- data/lib/rigor/cache/engine_source.rb +29 -1
- data/lib/rigor/cache/file_digest.rb +28 -0
- data/lib/rigor/cache/incremental_snapshot.rb +102 -8
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_descriptor.rb +37 -7
- data/lib/rigor/cache/store.rb +63 -4
- data/lib/rigor/cache/value_digest.rb +325 -0
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/check_command.rb +83 -13
- data/lib/rigor/cli/doc_links.rb +1 -1
- data/lib/rigor/cli/docs_command.rb +4 -4
- data/lib/rigor/cli/doctor_command.rb +1 -1
- data/lib/rigor/cli/effects_report.rb +2 -2
- data/lib/rigor/cli/plugin_command.rb +3 -3
- data/lib/rigor/cli/prism_colorizer.rb +0 -1
- data/lib/rigor/cli/sig_gen_command.rb +210 -29
- data/lib/rigor/cli/skill_command.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +0 -1
- data/lib/rigor/cli/type_of_command.rb +19 -5
- data/lib/rigor/cli/type_of_renderer.rb +20 -9
- data/lib/rigor/cli/type_of_template_probe.rb +189 -0
- data/lib/rigor/cli/unused_command.rb +3 -3
- data/lib/rigor/cli.rb +21 -3
- data/lib/rigor/config_audit.rb +3 -2
- data/lib/rigor/config_path.rb +29 -0
- data/lib/rigor/configuration/severity_profile.rb +24 -3
- data/lib/rigor/configuration.rb +71 -7
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +11 -2
- data/lib/rigor/effects/callee_rule.rb +368 -0
- data/lib/rigor/effects/catalog.rb +7 -4
- data/lib/rigor/effects/collector.rb +11 -5
- data/lib/rigor/effects/config_envelopes.rb +9 -2
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/effect_table.rb +11 -3
- data/lib/rigor/effects/envelope_check.rb +1 -1
- data/lib/rigor/effects/envelope_index.rb +15 -0
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/identity.rb +16 -0
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +21 -0
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +49 -37
- data/lib/rigor/effects/propagator.rb +295 -16
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +121 -72
- data/lib/rigor/effects/signature_sources.rb +1 -1
- data/lib/rigor/effects/snapshot.rb +2 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +385 -30
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -3
- data/lib/rigor/environment/lockfile_resolver.rb +27 -1
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/rbs_collection_discovery.rb +10 -1
- data/lib/rigor/environment/rbs_loader.rb +400 -134
- data/lib/rigor/environment/source_rbs_synthesis.rb +147 -0
- data/lib/rigor/environment.rb +104 -96
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +139 -9
- data/lib/rigor/inference/block_auto_splat.rb +216 -0
- data/lib/rigor/inference/block_call_timing.rb +338 -0
- data/lib/rigor/inference/block_parameter_binder.rb +88 -26
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +2 -1
- data/lib/rigor/inference/budget_trace.rb +2 -1
- data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
- data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
- data/lib/rigor/inference/captured_locals.rb +393 -15
- data/lib/rigor/inference/closure_escape_analyzer.rb +157 -13
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/declaration_walk/context.rb +195 -0
- data/lib/rigor/inference/declaration_walk/errors.rb +18 -0
- data/lib/rigor/inference/declaration_walk/shadow.rb +147 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +441 -0
- data/lib/rigor/inference/declaration_walk.rb +7 -0
- data/lib/rigor/inference/def_node_resolver.rb +3 -2
- data/lib/rigor/inference/def_return_typer.rb +11 -7
- data/lib/rigor/inference/define_method_block_self.rb +64 -0
- data/lib/rigor/inference/definer_resolution.rb +266 -0
- data/lib/rigor/inference/element_read_widening.rb +22 -10
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +1665 -538
- data/lib/rigor/inference/external_ancestor_resolution.rb +264 -0
- data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
- data/lib/rigor/inference/global_write_census.rb +239 -0
- data/lib/rigor/inference/guard_rebinding.rb +488 -0
- data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
- data/lib/rigor/inference/index_write_widening.rb +16 -3
- data/lib/rigor/inference/indexed_narrowing.rb +61 -9
- data/lib/rigor/inference/jump_targets.rb +82 -0
- data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
- data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
- data/lib/rigor/inference/last_line.rb +340 -0
- data/lib/rigor/inference/last_status.rb +144 -0
- data/lib/rigor/inference/macro_block_self_type.rb +179 -17
- data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
- data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
- data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
- data/lib/rigor/inference/match_rebinding.rb +392 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +85 -24
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +4 -0
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +113 -73
- data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
- data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +901 -38
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +128 -53
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +214 -13
- data/lib/rigor/inference/method_parameter_binder.rb +8 -3
- data/lib/rigor/inference/module_function_state.rb +213 -0
- data/lib/rigor/inference/multi_target_binder.rb +345 -52
- data/lib/rigor/inference/mutation_rejoin.rb +4 -1
- data/lib/rigor/inference/mutation_widening.rb +70 -48
- data/lib/rigor/inference/narrowing.rb +674 -124
- data/lib/rigor/inference/operand_effects.rb +167 -0
- data/lib/rigor/inference/operand_walk.rb +88 -0
- data/lib/rigor/inference/optimistic_origin.rb +152 -9
- data/lib/rigor/inference/parameter_inference_collector.rb +13 -11
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +7 -2
- data/lib/rigor/inference/project_patched_scanner.rb +7 -3
- data/lib/rigor/inference/receiver_alias.rb +90 -1
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +15 -11
- data/lib/rigor/inference/repeated_or_writes.rb +463 -0
- data/lib/rigor/inference/return_barrier.rb +54 -0
- data/lib/rigor/inference/rewrite_mutation.rb +120 -0
- data/lib/rigor/inference/scope_indexer/certainty.rb +176 -0
- data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +35 -0
- data/lib/rigor/inference/scope_indexer/def_nestings_collector.rb +47 -0
- data/lib/rigor/inference/scope_indexer/layered_def_nestings.rb +36 -0
- data/lib/rigor/inference/scope_indexer/member_layouts_collector.rb +61 -0
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +130 -0
- data/lib/rigor/inference/scope_indexer/superclasses_collector.rb +64 -0
- data/lib/rigor/inference/scope_indexer.rb +5913 -701
- data/lib/rigor/inference/singleton_hook_decline.rb +253 -0
- data/lib/rigor/inference/statement_evaluator.rb +3249 -497
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +44 -7
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +3 -2
- data/lib/rigor/language_server/hover_renderer.rb +3 -3
- data/lib/rigor/language_server/project_context.rb +5 -3
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +196 -13
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +1 -1
- data/lib/rigor/plugin/effect_attribution.rb +58 -4
- data/lib/rigor/plugin/io_boundary.rb +82 -4
- data/lib/rigor/plugin/isolation.rb +1 -1
- data/lib/rigor/plugin/loader.rb +2 -1
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/manifest.rb +71 -10
- data/lib/rigor/plugin/registry.rb +35 -1
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +9 -3
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin/trust_policy.rb +3 -3
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/protection/discovery_seed.rb +20 -9
- data/lib/rigor/protection/kill_signature.rb +0 -1
- data/lib/rigor/protection/mutation_cache.rb +4 -5
- data/lib/rigor/rbs_extended.rb +27 -0
- data/lib/rigor/reflection/constant_ancestors.rb +146 -0
- data/lib/rigor/reflection/constant_path.rb +41 -13
- data/lib/rigor/reflection.rb +73 -107
- data/lib/rigor/scope/discovery_index.rb +351 -2
- data/lib/rigor/scope/resolution_chain/relevance.rb +165 -0
- data/lib/rigor/scope/resolution_chain.rb +884 -0
- data/lib/rigor/scope.rb +981 -198
- data/lib/rigor/sig_gen/alias_index.rb +289 -0
- data/lib/rigor/sig_gen/classification.rb +22 -5
- data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
- data/lib/rigor/sig_gen/generator.rb +580 -47
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +1 -1
- data/lib/rigor/sig_gen/renderer.rb +124 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +44 -1
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +166 -35
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +1 -1
- data/lib/rigor/source/node_walker.rb +0 -3
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/type/combinator.rb +112 -12
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/hash_shape.rb +1 -1
- data/lib/rigor/type/refined.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +9 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +13 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +239 -4
- data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
- data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
- data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +9 -5
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +380 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +281 -35
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +25 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +171 -5
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +2 -0
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +1 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +10 -0
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
- data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
- data/plugins/rigor-grape/sig/grape.rbs +263 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +72 -2
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +11 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +35 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +1 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +9 -17
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +217 -36
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +9 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +0 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +46 -1
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/sig/rigor/analysis/baseline.rbs +69 -7
- data/sig/rigor/analysis/fact_store.rbs +1 -1
- data/sig/rigor/analysis/project_scan.rbs +74 -0
- data/sig/rigor/effects/config_envelopes.rbs +100 -0
- data/sig/rigor/effects/effect_table.rbs +60 -0
- data/sig/rigor/effects/envelope.rbs +97 -0
- data/sig/rigor/effects/envelope_index.rbs +33 -0
- data/sig/rigor/effects/file_collection.rbs +81 -0
- data/sig/rigor/effects/label.rbs +26 -0
- data/sig/rigor/effects/label_set.rbs +46 -0
- data/sig/rigor/effects/method_key.rbs +24 -0
- data/sig/rigor/effects/origin.rbs +50 -0
- data/sig/rigor/effects/plugin_facts.rbs +141 -0
- data/sig/rigor/effects/registry.rbs +68 -0
- data/sig/rigor/effects/summary.rbs +50 -0
- data/sig/rigor/effects/taint_cause.rbs +12 -0
- data/sig/rigor/environment.rbs +14 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +6 -4
- data/sig/rigor/plugin/additional_initializer.rbs +36 -0
- data/sig/rigor/plugin/base.rbs +30 -7
- data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
- data/sig/rigor/plugin/effect_attribution.rbs +66 -0
- data/sig/rigor/plugin/effect_edge.rbs +33 -0
- data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
- data/sig/rigor/plugin/io_boundary.rbs +2 -1
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +50 -11
- data/sig/rigor/plugin/protocol_contract.rbs +68 -0
- data/sig/rigor/plugin/registry.rbs +62 -1
- data/sig/rigor/plugin.rbs +1 -1
- data/sig/rigor/rbs_extended.rbs +1 -1
- data/sig/rigor/reflection.rbs +7 -6
- data/sig/rigor/scope.rbs +177 -20
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -7
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +6 -0
- data/sig/rigor.rbs +38 -20
- data/skills/rigor-ask/SKILL.md +8 -5
- data/skills/rigor-baseline-reduce/SKILL.md +4 -6
- data/skills/rigor-ci-setup/SKILL.md +17 -21
- data/skills/rigor-doctor/SKILL.md +24 -22
- data/skills/rigor-doctor/references/01-checks.md +97 -33
- data/skills/rigor-editor-setup/SKILL.md +6 -4
- data/skills/rigor-mcp-setup/SKILL.md +5 -4
- data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
- data/skills/rigor-next-steps/SKILL.md +4 -2
- data/skills/rigor-plugin-author/SKILL.md +19 -23
- data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +12 -25
- data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
- data/skills/rigor-plugin-review/SKILL.md +6 -4
- data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
- data/skills/rigor-plugin-tune/SKILL.md +4 -2
- data/skills/rigor-project-init/SKILL.md +46 -18
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +40 -10
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
- data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
- data/skills/rigor-protection-uplift/SKILL.md +4 -6
- data/skills/rigor-rbs-setup/SKILL.md +4 -2
- data/skills/rigor-type-oracle/SKILL.md +4 -6
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +12 -8
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +0 -3
- data/skills/rigor-unused-adjudicate/SKILL.md +4 -2
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +132 -1
|
@@ -165,20 +165,14 @@ Rigor::Plugin::Base.suggest(typo, known_names) # nearest match, or nil
|
|
|
165
165
|
|
|
166
166
|
## Optional — contribute a return type with `dynamic_return` / `narrowing_facts`
|
|
167
167
|
|
|
168
|
-
> **
|
|
169
|
-
>
|
|
170
|
-
>
|
|
171
|
-
>
|
|
172
|
-
>
|
|
173
|
-
>
|
|
174
|
-
>
|
|
175
|
-
>
|
|
176
|
-
> cluster on a DSL-generated method (the common reason
|
|
177
|
-
> `rigor-project-init` hands off to this skill), the fix is to make the
|
|
178
|
-
> method *exist* in Rigor's view — ship RBS declaring it (see "Shipping
|
|
179
|
-
> RBS for the DSL" below), not a return-type contribution.** Reach for
|
|
180
|
-
> these only when the call already resolves and you want a *better
|
|
181
|
-
> 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.
|
|
182
176
|
|
|
183
177
|
A plugin can do more than emit diagnostics: it can *supply* the
|
|
184
178
|
inferred return type (or narrowing facts) for a call site the core
|
|
@@ -213,10 +207,6 @@ narrowing_facts methods: [:assert_kind_of] do |call_node, scope|
|
|
|
213
207
|
end
|
|
214
208
|
```
|
|
215
209
|
|
|
216
|
-
> **`narrowing_facts` was renamed from `type_specifier` in ADR-80.**
|
|
217
|
-
> The old verb was removed in 0.3.0 — `narrowing_facts` is the only
|
|
218
|
-
> spelling a plugin can declare.
|
|
219
|
-
|
|
220
210
|
Build return types with `Rigor::Type::Combinator`:
|
|
221
211
|
|
|
222
212
|
```ruby
|
|
@@ -233,12 +223,9 @@ plugin is confident; a wrong contribution propagates downstream.
|
|
|
233
223
|
`rigor plugins --capabilities` catalogue enumerates — run it to see
|
|
234
224
|
exactly what each loaded plugin contributes.
|
|
235
225
|
|
|
236
|
-
> **
|
|
237
|
-
>
|
|
238
|
-
>
|
|
239
|
-
> expressed by `dynamic_return`'s callable gates: a **method-gated return
|
|
240
|
-
> type** (an RSpec `let(:x) { … }` binding, a Sorbet `sig`-driven return —
|
|
241
|
-
> 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
|
|
242
229
|
> `dynamic_return methods: -> { [...] }` or `file_methods: ->(path) { [...] }`;
|
|
243
230
|
> a **dynamic per-project receiver set** (ActiveStorage's `Attached::One`
|
|
244
231
|
> on discovered model classes) uses `dynamic_return receivers: -> { [...] }`,
|
|
@@ -247,7 +234,7 @@ exactly what each loaded plugin contributes.
|
|
|
247
234
|
> if the plugin genuinely needs to sharpen call-site types; a
|
|
248
235
|
> diagnostics-only plugin skips them entirely.
|
|
249
236
|
|
|
250
|
-
## Shipping RBS for the DSL —
|
|
237
|
+
## Shipping RBS for the DSL — making DSL methods exist
|
|
251
238
|
|
|
252
239
|
If the DSL introduces methods or classes that Rigor cannot see (a
|
|
253
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`
|
|
109
|
+
The plugin contract is **not frozen until `rigortype` v1.0.0** (see
|
|
110
110
|
SKILL.md). Concretely:
|
|
111
111
|
|
|
112
|
-
- Gemspec / Gemfile: `rigortype`
|
|
113
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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 —
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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) |
|
|
@@ -86,7 +88,7 @@ diagnostics.
|
|
|
86
88
|
| Today's diagnostics | Snapshotted into `.rigor-baseline.yml`; suppressed as long as the count does not grow. | All surfaced; every one is fixed or consciously suppressed. |
|
|
87
89
|
| Hard-to-fix diagnostics | Left in the baseline. The project **trusts its test / spec suite** to cover runtime correctness for those sites — the static `T | nil` reading is worst-case-sound, the suite proves the worst case is not hit. | Fixed, or annotated `# rigor:disable <rule>` with an author-intent reason at the specific line. No blanket suppression. |
|
|
88
90
|
| `severity_profile` | `lenient` (or `balanced` for a small project). | `strict`. |
|
|
89
|
-
| Best for |
|
|
91
|
+
| Best for | **Every project by default** — mature or brand-new, large or small. | Users fluent in both type theory and RBS who opt in and will resolve Rigor's inference gaps themselves. |
|
|
90
92
|
| New diagnostics later | Surface immediately — anything beyond the baseline envelope is a regression. | Surface immediately — there is no envelope; every diagnostic is live. |
|
|
91
93
|
|
|
92
94
|
Both modes give the same core guarantee: **a change that introduces
|
|
@@ -95,12 +97,35 @@ diagnostics that exist *today*. Acknowledge mode parenthesises them
|
|
|
95
97
|
behind a baseline and leans on the test suite; strict mode refuses to
|
|
96
98
|
parenthesise anything.
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
**Recommend acknowledge mode for every project, including new and
|
|
101
|
+
small ones.** Rigor's inference still has gaps, so even a fresh
|
|
102
|
+
project meets diagnostics on correct code. Under strict mode each one
|
|
103
|
+
needs a `sig/` fix, an RBS workaround, or a reasoned
|
|
104
|
+
`# rigor:disable` — work that takes type theory and RBS. Without that
|
|
105
|
+
knowledge, users rewrite correct code for the tool or scatter
|
|
106
|
+
suppressions. Acknowledge mode keeps the same regression guard with an
|
|
107
|
+
exit: a new diagnostic still fails the check, and once it is confirmed
|
|
108
|
+
as an inference gap, the baseline can absorb it (report the false
|
|
109
|
+
positive upstream). `rigor baseline regenerate` rewrites the baseline
|
|
110
|
+
from every live diagnostic, so run it only when a whole-project
|
|
111
|
+
`rigor check` (no path arguments) shows nothing but confirmed false
|
|
112
|
+
positives; otherwise it silences a real
|
|
113
|
+
bug alongside them.
|
|
114
|
+
|
|
115
|
+
Present strict mode as an opt-in for users who know type theory and
|
|
116
|
+
RBS, want the zero-diagnostic gate, and accept resolving inference
|
|
117
|
+
gaps themselves — never as the recommendation, and never because the
|
|
118
|
+
project is new, small, or a library. If the user picks it, tell them
|
|
119
|
+
how to move to acknowledge mode later: optionally relax
|
|
120
|
+
`severity_profile`, re-run triage, then run Phase 7 (generate a
|
|
121
|
+
baseline and wire `baseline:`). The profile change comes first because
|
|
122
|
+
it changes which rules fire.
|
|
123
|
+
|
|
124
|
+
For a large first run (more than ~100 errors), acknowledge mode also
|
|
125
|
+
suggests `severity_profile: lenient`; see Phase 4.
|
|
126
|
+
|
|
127
|
+
Note the ordering: the error count that feeds the `severity_profile`
|
|
128
|
+
choice in Phase 4 is only *measured* in
|
|
104
129
|
Phase 6's triage run. Any profile written in Phase 4 is therefore
|
|
105
130
|
**provisional** — Phase 6 revisits it against the measured count (see
|
|
106
131
|
[`references/02-configure.md`](references/02-configure.md)
|
|
@@ -109,12 +134,15 @@ Phase 6's triage run. Any profile written in Phase 4 is therefore
|
|
|
109
134
|
## Non-interactive / agent-driven runs
|
|
110
135
|
|
|
111
136
|
This skill has several ask-the-user points (the mode choice, the RBS
|
|
112
|
-
collection install, the final gitignore-and-commit confirmation).
|
|
113
|
-
the user
|
|
114
|
-
|
|
137
|
+
collection install, the final gitignore-and-commit confirmation). A
|
|
138
|
+
*delegation* is the user asking, before the run, for the onboarding to
|
|
139
|
+
proceed without these questions ("set it up, don't ask me"). An
|
|
140
|
+
ordinary request to set Rigor up is not one: ask as usual. Under a
|
|
141
|
+
delegation those points resolve without blocking:
|
|
115
142
|
|
|
116
143
|
- The **mode** the user pre-declared is settled; record it and skip the
|
|
117
|
-
Phase 2 presentation.
|
|
144
|
+
Phase 2 presentation. If the delegation names no mode, choose
|
|
145
|
+
acknowledge mode and say so in the report — never strict.
|
|
118
146
|
- Low-risk, reversible, in-repo confirmations (`rbs collection
|
|
119
147
|
install`, the `.gitignore` addition) are covered by the delegation —
|
|
120
148
|
act, and note each self-answer in your report.
|
|
@@ -154,7 +182,7 @@ committed `sig/` directory.
|
|
|
154
182
|
| 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. |
|
|
155
183
|
| — (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. |
|
|
156
184
|
|
|
157
|
-
## Escalation paths (Phase
|
|
185
|
+
## Escalation paths (Phase 8 preview)
|
|
158
186
|
|
|
159
187
|
Some diagnostic clusters are neither a quick fix nor honest baseline
|
|
160
188
|
material. Two of them have a dedicated answer this skill hands off to:
|
|
@@ -183,7 +211,7 @@ material. Two of them have a dedicated answer this skill hands off to:
|
|
|
183
211
|
support, **open an issue on the Rigor project** asking for it:
|
|
184
212
|
<https://github.com/rigortype/rigor/issues>.
|
|
185
213
|
|
|
186
|
-
Neither is a Phase
|
|
214
|
+
Neither is a Phase 8 obligation — they are options to *offer* the
|
|
187
215
|
user when the triage report points at one of these causes. The
|
|
188
216
|
project-DSL handoff is detailed in
|
|
189
217
|
[`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md)
|
|
@@ -223,7 +251,7 @@ only in acknowledge mode). For each, give the commit recommendation:
|
|
|
223
251
|
|
|
224
252
|
| File | What it is | Commit? |
|
|
225
253
|
| --- | --- | --- |
|
|
226
|
-
| `.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. |
|
|
254
|
+
| `.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. |
|
|
227
255
|
| `.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. |
|
|
228
256
|
| `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"). |
|
|
229
257
|
| `.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`. |
|
|
@@ -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.**
|
|
75
|
-
|
|
76
|
-
Ruby
|
|
77
|
-
|
|
78
|
-
`RBS::DuplicatedDeclarationError
|
|
79
|
-
|
|
80
|
-
|
|
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
|
|
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,7 +112,7 @@ plugins:
|
|
|
107
112
|
|
|
108
113
|
severity_profile: lenient
|
|
109
114
|
|
|
110
|
-
# Phase
|
|
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
|
```
|
|
@@ -133,14 +138,38 @@ entirely — including a `sig/` that `rigor sig-gen --write` created.
|
|
|
133
138
|
List only directories that contain `.rbs` files or subdirectories of
|
|
134
139
|
them. Rigor walks each path recursively.
|
|
135
140
|
|
|
136
|
-
A
|
|
141
|
+
A plain-Ruby gem is shorter. The `balanced` default needs no
|
|
142
|
+
`severity_profile:` key:
|
|
137
143
|
|
|
138
144
|
```yaml
|
|
139
145
|
paths:
|
|
140
146
|
- lib
|
|
141
|
-
|
|
147
|
+
test_paths:
|
|
148
|
+
- test
|
|
149
|
+
|
|
150
|
+
# Phase 7 (acknowledge mode) appends this line after generating the
|
|
151
|
+
# baseline. Strict mode (opt-in) sets `severity_profile: strict` and
|
|
152
|
+
# leaves it out.
|
|
153
|
+
# baseline: .rigor-baseline.yml
|
|
142
154
|
```
|
|
143
155
|
|
|
156
|
+
### Test roots — write `test_paths:` explicitly
|
|
157
|
+
|
|
158
|
+
Always write `test_paths:` with the test roots Phase 1 found, even
|
|
159
|
+
when they are the conventional `spec/` or `test/`. Left unset, Rigor
|
|
160
|
+
auto-detects whichever of `spec/` and `test/` exist; that covers the
|
|
161
|
+
common layouts, but the committed config is then silent about where
|
|
162
|
+
the tests are, and a suite anywhere else (a second tree, an
|
|
163
|
+
`integration/` directory) is never read. Declaring the key replaces
|
|
164
|
+
auto-detection, so list every root. A project with no tests yet
|
|
165
|
+
writes `test_paths: []`.
|
|
166
|
+
|
|
167
|
+
The key affects no diagnostic. Its reader today is `rigor sig-gen
|
|
168
|
+
--params=observed` (Phase 5), which types a parameter from the
|
|
169
|
+
arguments the tests pass. When there is no root to read, or a declared
|
|
170
|
+
root does not exist, sig-gen says so on stderr and the affected
|
|
171
|
+
parameters stay `untyped`.
|
|
172
|
+
|
|
144
173
|
### Key reference
|
|
145
174
|
|
|
146
175
|
Only the keys this skill needs. `rigor --help` and the project
|
|
@@ -150,19 +179,20 @@ handbook document the full surface.
|
|
|
150
179
|
| --- | --- |
|
|
151
180
|
| `paths:` | Directories Rigor analyses. Source roots only — not `spec/` / `test/`. |
|
|
152
181
|
| `exclude:` | Paths removed from the `paths:` walk. |
|
|
182
|
+
| `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. |
|
|
153
183
|
| `plugins:` | Plugin ids to activate (the Phase 3 set). |
|
|
154
184
|
| `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:`. |
|
|
155
185
|
| `severity_profile:` | `lenient` / `balanced` / `strict`. See the table above. |
|
|
156
186
|
| `severity_overrides:` | Per-rule severity tweaks. Leave empty at init; the baseline-reduce workflow tunes it later. |
|
|
157
|
-
| `baseline:` | Path to the baseline file. **Only acknowledge mode sets it**, and only in Phase
|
|
158
|
-
| `pre_eval:` | Project files Rigor walks before per-file inference — used to register in-project monkey-patches. Leave empty at init; Phase
|
|
159
|
-
| `dependencies.source_inference:` | Opt-in inference for gems shipping no RBS. Leave empty at init; Phase
|
|
187
|
+
| `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. |
|
|
188
|
+
| `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. |
|
|
189
|
+
| `dependencies.source_inference:` | Opt-in inference for gems shipping no RBS. Leave empty at init; Phase 8 may suggest it. |
|
|
160
190
|
|
|
161
191
|
## Do not write the baseline yet
|
|
162
192
|
|
|
163
193
|
Phase 4 writes the config with the `baseline:` line **commented out
|
|
164
|
-
or absent**. The baseline file does not exist until Phase
|
|
165
|
-
`baseline:` pointing at a missing file is an error. Phase
|
|
194
|
+
or absent**. The baseline file does not exist until Phase 7, and a
|
|
195
|
+
`baseline:` pointing at a missing file is an error. Phase 7 writes
|
|
166
196
|
the file and uncomments / appends the line in one step.
|
|
167
197
|
|
|
168
198
|
Strict mode never adds `baseline:` at all.
|
|
@@ -231,8 +261,8 @@ with the message text.
|
|
|
231
261
|
|
|
232
262
|
## Output of this module
|
|
233
263
|
|
|
234
|
-
A committed `.rigor.dist.yml` with `paths:`, `
|
|
235
|
-
`plugins:`, and `severity_profile:` set — and no active
|
|
264
|
+
A committed `.rigor.dist.yml` with `paths:`, `test_paths:`,
|
|
265
|
+
`exclude:`, `plugins:`, and `severity_profile:` set — and no active
|
|
236
266
|
`baseline:` line. `rigor plugins` reports every entry loaded,
|
|
237
267
|
zero load errors. No Gemfile changes; plugins are bundled inside
|
|
238
268
|
`rigortype`.
|
|
@@ -75,12 +75,12 @@ Use the sections like this:
|
|
|
75
75
|
| --- | --- | --- |
|
|
76
76
|
| `activesupport-core-ext` | ActiveSupport core-class monkey-patches not loaded. | Go back to Phase 3/4: add `rigor-activesupport-core-ext` to `plugins:` (it is an RBS-bundle plugin), re-run triage. This is a config gap, not a bug. |
|
|
77
77
|
| `gem-without-rbs` | A dependency ships no RBS. | If `rbs_collection.lock.yaml` was present and Phase 1 installed the collection, re-run `rigor triage` — the hint may shrink or disappear. Otherwise: Phase 8 escalation — `bundle exec rbs collection install`, or `dependencies.source_inference:`, or open a Rigor issue. |
|
|
78
|
-
| `project-monkey-patch-known` | **High confidence.** The engine proved the called method *is* defined by a project file (a reopened core/stdlib/gem class) but is not applied cross-file. The hint **names the defining file(s)**. | Phase
|
|
79
|
-
| `project-monkey-patch` | An in-project monkey-patch / refinement Rigor did not see, inferred from the *spread* of the same method across ≥3 files (no proven def site). | Phase
|
|
80
|
-
| `unresolved-toplevel` | Toplevel calls (outside any `def`/`class`/`module`) that resolve to nothing visible — usually a script relying on a monkey-patch or a `require`d helper Rigor did not walk (ADR-34). | Phase
|
|
78
|
+
| `project-monkey-patch-known` | **High confidence.** The engine proved the called method *is* defined by a project file (a reopened core/stdlib/gem class) but is not applied cross-file. The hint **names the defining file(s)**. | Phase 6a — copy the named file(s) straight into `pre_eval:`. No detective work needed; the diagnostic already found the source. |
|
|
79
|
+
| `project-monkey-patch` | An in-project monkey-patch / refinement Rigor did not see, inferred from the *spread* of the same method across ≥3 files (no proven def site). | Phase 6a — find the defining file (grep for `def <method>` / `class <Receiver>`), register it via `pre_eval:`, or (if it is a DSL) write a project plugin. |
|
|
80
|
+
| `unresolved-toplevel` | Toplevel calls (outside any `def`/`class`/`module`) that resolve to nothing visible — usually a script relying on a monkey-patch or a `require`d helper Rigor did not walk (ADR-34). | Phase 6a — if a project file defines these (toplevel `def`, or a patch on `Object`/`Kernel`), list it in `pre_eval:`. If nothing defines them, treat as genuine typos / missing requires (Phase 8). |
|
|
81
81
|
| `activerecord-relation-misinference` | An ActiveRecord relation inferred as `Array`. | Ensure `rigor-activerecord` is enabled (Phase 3). If it persists, it is an engine gap — open a Rigor issue. |
|
|
82
82
|
| `systemic-file-cluster` | One file × one rule, large count. | Acknowledge mode: a clean baseline bucket. Strict mode: a single fix may clear many — review that file first. |
|
|
83
|
-
| `genuine-bugs` | Low-count rules scattered across files. | **Phase
|
|
83
|
+
| `genuine-bugs` | Low-count rules scattered across files. | **Phase 8** — these are the localised bugs Rigor caught. Review first, in both modes. Note: the hint groups all low-count rules regardless of severity — filter for `error` severity when prioritising actionable items. |
|
|
84
84
|
|
|
85
85
|
If triage flags `activesupport-core-ext` (or any config gap),
|
|
86
86
|
**fix the config and re-run `rigor triage` before continuing**. The
|
|
@@ -170,8 +170,8 @@ bundle exec rbs collection install # if rbs is in Gemfile
|
|
|
170
170
|
# or: rbs collection install
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
Re-run `rigor triage`. If the `gem-without-rbs` count drops,
|
|
174
|
-
|
|
173
|
+
Re-run `rigor triage`. If the `gem-without-rbs` count drops, carry
|
|
174
|
+
the new, smaller count into Phase 7.
|
|
175
175
|
|
|
176
176
|
## Phase 7 — Generate the baseline (acknowledge mode only)
|
|
177
177
|
|
|
@@ -215,7 +215,8 @@ So ordinary coding cannot quietly grow the diagnostic count: the
|
|
|
215
215
|
baseline is a ceiling, not a blanket. Reducing it later is the
|
|
216
216
|
`rigor-baseline-reduce` skill's job.
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
Recommend committing `.rigor-baseline.yml` — it documents project
|
|
219
|
+
state; list it in the Final step's file inventory.
|
|
219
220
|
|
|
220
221
|
Print the suppression summary for the user: "N diagnostics recorded
|
|
221
222
|
as baseline; M will surface on subsequent runs."
|
|
@@ -288,18 +289,17 @@ sig issue.
|
|
|
288
289
|
|
|
289
290
|
#### `call.argument-type-mismatch` on regex capture variables (`$1`, `$~`)
|
|
290
291
|
|
|
291
|
-
Rigor
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
the form:
|
|
292
|
+
Rigor narrows `$1`, `$~`, and similar capture variables to non-nil
|
|
293
|
+
after a successful `=~` match and inside a `when /re/` branch. Where
|
|
294
|
+
the match is guaranteed by some other shape Rigor does not track, they
|
|
295
|
+
stay `String | nil`, and a diagnostic of the form:
|
|
295
296
|
|
|
296
297
|
```
|
|
297
298
|
expected String, got String | nil (on $1 / $~)
|
|
298
299
|
```
|
|
299
300
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
baseline.
|
|
301
|
+
is an **engine FP** (ADR-24 WD3 / known limitation). Note it as noise rather than
|
|
302
|
+
surfacing it as a bug; it belongs in the baseline.
|
|
303
303
|
|
|
304
304
|
### Escalation path A — application-specific metaprogramming
|
|
305
305
|
|
|
@@ -28,7 +28,8 @@ rigor sig-gen lib # adjust path to match the paths: key
|
|
|
28
28
|
Typical output at this point: most `new_method` candidates have
|
|
29
29
|
literal or concrete return types (`"hello"`, `42`, `:done`, `nil`).
|
|
30
30
|
Methods whose return type cannot be inferred show up with
|
|
31
|
-
`skip_reason:
|
|
31
|
+
`skip_reason: "sig.skipped.untyped-return"` — these are the sig
|
|
32
|
+
precision targets.
|
|
32
33
|
|
|
33
34
|
To get a breakdown in JSON:
|
|
34
35
|
|
|
@@ -50,6 +51,12 @@ rigor sig-gen --format json lib | ruby -e '
|
|
|
50
51
|
|
|
51
52
|
## Step 5-b — Write the baseline sigs
|
|
52
53
|
|
|
54
|
+
If the project's `Steepfile` reads inline annotations (`inline: true`
|
|
55
|
+
beside `signature "sig"`), first add `sig_gen:` / `inline_declared: skip`
|
|
56
|
+
to `.rigor.yml`. Otherwise sig-gen copies every `# @rbs` / `#:`
|
|
57
|
+
declaration into `sig/`, and Steep reports each copied method as
|
|
58
|
+
`DuplicatedMethodDefinition`.
|
|
59
|
+
|
|
53
60
|
```sh
|
|
54
61
|
rigor sig-gen --write lib
|
|
55
62
|
```
|
|
@@ -63,12 +70,18 @@ head -40 sig/lib/your_class.rbs
|
|
|
63
70
|
|
|
64
71
|
At this point, `attr_reader` and `attr_accessor` methods that rely on
|
|
65
72
|
ivar types set from `initialize` parameters will likely still be
|
|
66
|
-
absent (
|
|
73
|
+
absent (skipped as `sig.skipped.untyped-return`). Step 5-c fixes that.
|
|
74
|
+
An `attr_writer` or `attr_accessor` stays skipped even then unless its
|
|
75
|
+
ivar is assigned from an `initialize` parameter: the writer stores
|
|
76
|
+
whatever its caller passes, so the ivar reads untyped. That covers
|
|
77
|
+
`@count = 0` and `@logger = Logger.new` alike, and any other method
|
|
78
|
+
that returns the ivar.
|
|
67
79
|
|
|
68
80
|
## Step 5-c — Precision uplift with --params=observed
|
|
69
81
|
|
|
70
82
|
`--params=observed` tells sig-gen to collect observed argument types
|
|
71
|
-
from
|
|
83
|
+
from the call sites in the project's test roots — the `test_paths:`
|
|
84
|
+
Phase 4 wrote (`--observe=PATH` overrides them for one run). The most
|
|
72
85
|
important use case: **`attr_reader` / `attr_writer` / `attr_accessor`
|
|
73
86
|
methods whose `@ivar` is assigned from an `initialize` parameter**.
|
|
74
87
|
|
|
@@ -88,7 +101,8 @@ Person.new("Alice", 30)
|
|
|
88
101
|
Person.new("Bob", 25)
|
|
89
102
|
```
|
|
90
103
|
|
|
91
|
-
Without observations: `attr_reader :name` → skipped as
|
|
104
|
+
Without observations: `attr_reader :name` → skipped as
|
|
105
|
+
`sig.skipped.untyped-return`
|
|
92
106
|
(the ivar's type is unknown because the blank inference scope never
|
|
93
107
|
sees the parameter values).
|
|
94
108
|
|
|
@@ -129,9 +143,9 @@ there are a few options depending on the cause:
|
|
|
129
143
|
| Pattern | Cause | Fix |
|
|
130
144
|
|---|---|---|
|
|
131
145
|
| `attr_reader :x` with `@x` never set in `initialize` | ivar set from a DB query, config read, or side effect | Add a hand-written sig: create (or edit) `sig/your_class.rbs` with `attr_reader x: String` |
|
|
132
|
-
| Deep method chains on untyped receivers | Cascade from a gem with no RBS | `rbs collection install`; Phase
|
|
146
|
+
| Deep method chains on untyped receivers | Cascade from a gem with no RBS | `rbs collection install`; Phase 8 escalation path B |
|
|
133
147
|
| Recursive or mutually recursive methods | Return type not inferrable without a base case | Add a `# @rbs return: YourType` inline annotation, or a hand-written sig |
|
|
134
|
-
| Dynamic methods (`define_method`, DSL) | Metaprogramming Rigor cannot follow | Phase
|
|
148
|
+
| Dynamic methods (`define_method`, DSL) | Metaprogramming Rigor cannot follow | Phase 8 escalation path A (project plugin) |
|
|
135
149
|
|
|
136
150
|
Do not spend long on residual `untyped` methods at this stage — a
|
|
137
151
|
handful of `untyped` returns in `sig/` does not block adoption. The
|
|
@@ -140,12 +154,10 @@ reach perfect sig coverage.
|
|
|
140
154
|
|
|
141
155
|
## Step 5-e — Commit the sig/ directory
|
|
142
156
|
|
|
143
|
-
Once you are satisfied with the initial sig quality
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
git commit -m "Add initial RBS sigs from rigor sig-gen (--params=observed)"
|
|
148
|
-
```
|
|
157
|
+
Once you are satisfied with the initial sig quality, recommend
|
|
158
|
+
committing `sig/`: list it in the Final step's file inventory
|
|
159
|
+
(`SKILL.md` § "Final step") rather than committing it here — the user
|
|
160
|
+
confirms every commit.
|
|
149
161
|
|
|
150
162
|
A committed `sig/` is a first-class project artefact: it improves
|
|
151
163
|
inference quality on every subsequent run and is maintained alongside
|
|
@@ -164,8 +176,9 @@ the source (add new sig files when adding classes; update sigs with
|
|
|
164
176
|
|
|
165
177
|
## Output of this module
|
|
166
178
|
|
|
167
|
-
A
|
|
168
|
-
inferrable methods. Remaining
|
|
179
|
+
A `sig/` directory, ready to commit, with RBS skeletons for all
|
|
180
|
+
statically inferrable methods. Remaining `sig.skipped.untyped-return`
|
|
181
|
+
methods are noted for
|
|
169
182
|
potential manual annotation; they do not block Phase 6.
|
|
170
183
|
|
|
171
184
|
Proceed to Phase 6 ([`03-baseline-and-bugs.md`](03-baseline-and-bugs.md)).
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rigor-protection-uplift
|
|
3
|
-
description:
|
|
4
|
-
Close the
|
|
3
|
+
description: >-
|
|
4
|
+
Close the protection gaps reported by `rigor coverage --protection`, using generated signatures before
|
|
5
|
+
minimal residual annotations and a no-new-diagnostics gate. Use when increasing bug-catching coverage
|
|
6
|
+
in an adopting project; not for Rigor's own tree, bundled plugins, or first-time setup.
|
|
5
7
|
license: MPL-2.0
|
|
6
8
|
metadata:
|
|
7
9
|
version: 0.1.0
|
|
@@ -40,10 +42,6 @@ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
|
|
|
40
42
|
|
|
41
43
|
## When NOT to use
|
|
42
44
|
|
|
43
|
-
- **Rigor's own `lib/`, or the bundled `plugins/` / `examples/`** — the
|
|
44
|
-
self-check tree. Hand-authoring types there collides with the
|
|
45
|
-
sig-gen-first ethos; run `rigor sig-gen` directly and treat residual
|
|
46
|
-
gaps as engine signal to report, not a private fix.
|
|
47
45
|
- **"Make my code more precise" with no protection goal** — that is
|
|
48
46
|
`rigor coverage` (precision), not `--protection`.
|
|
49
47
|
- **A project with no Rigor config yet** — onboard first with
|