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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- 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/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +454 -13
- data/docs/manual/02-cli-reference.md +63 -2
- data/docs/manual/03-configuration.md +7 -0
- data/docs/manual/04-diagnostics.md +4 -0
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/10-mcp-server.md +3 -2
- 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 +323 -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 +520 -49
- data/lib/rigor/analysis/dependency_recorder.rb +23 -0
- data/lib/rigor/analysis/fact_store.rb +9 -0
- data/lib/rigor/analysis/incremental.rb +26 -0
- data/lib/rigor/analysis/incremental_session.rb +36 -4
- 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 +1 -0
- data/lib/rigor/analysis/rule_catalog.rb +127 -0
- data/lib/rigor/analysis/run_cache_key.rb +20 -11
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +167 -11
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -4
- data/lib/rigor/analysis/runner/pool_coordinator.rb +107 -15
- data/lib/rigor/analysis/runner/project_pre_passes.rb +26 -7
- data/lib/rigor/analysis/runner.rb +278 -20
- data/lib/rigor/analysis/template_unit_collector.rb +303 -0
- data/lib/rigor/analysis/template_unit_paths.rb +91 -0
- data/lib/rigor/analysis/template_unit_positions.rb +293 -0
- data/lib/rigor/analysis/template_units.rb +399 -0
- data/lib/rigor/analysis/worker_session.rb +53 -10
- 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 +6 -1
- data/lib/rigor/cache/engine_source.rb +29 -1
- data/lib/rigor/cache/incremental_snapshot.rb +33 -1
- 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 +0 -1
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/doc_links.rb +1 -1
- data/lib/rigor/cli/docs_command.rb +4 -4
- 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.rb +21 -3
- data/lib/rigor/configuration/severity_profile.rb +19 -3
- data/lib/rigor/configuration.rb +66 -3
- 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 +43 -31
- 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/lockfile_resolver.rb +17 -0
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/rbs_loader.rb +399 -133
- data/lib/rigor/environment.rb +103 -38
- 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 +73 -27
- 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 +387 -15
- data/lib/rigor/inference/closure_escape_analyzer.rb +157 -13
- data/lib/rigor/inference/content_join.rb +200 -27
- 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/element_read_widening.rb +22 -10
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +1532 -496
- data/lib/rigor/inference/external_ancestor_resolution.rb +267 -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 +447 -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 +167 -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 +881 -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/multi_target_binder.rb +340 -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 +540 -120
- 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 +3 -2
- 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.rb +4615 -551
- data/lib/rigor/inference/statement_evaluator.rb +3176 -490
- 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 +168 -5
- 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/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.rb +1 -0
- data/lib/rigor/protection/discovery_seed.rb +3 -1
- data/lib/rigor/protection/kill_signature.rb +0 -1
- data/lib/rigor/protection/mutation_cache.rb +1 -2
- data/lib/rigor/rbs_extended.rb +27 -0
- data/lib/rigor/reflection/constant_ancestors.rb +97 -0
- data/lib/rigor/reflection/constant_path.rb +19 -6
- data/lib/rigor/reflection.rb +72 -105
- data/lib/rigor/scope/discovery_index.rb +135 -2
- data/lib/rigor/scope.rb +859 -49
- 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 +558 -31
- 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 +88 -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-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 +12 -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 +1 -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 +135 -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 +9 -7
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +33 -8
- 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 +108 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Effects
|
|
3
|
+
# One method's direct effect record: the labels its own body contributes, grouped by the origin
|
|
4
|
+
# that claimed them, plus the declared (`<=`) lane, the exhaustiveness bit, and the taint causes.
|
|
5
|
+
class Summary
|
|
6
|
+
TRIVIAL_BOUND: LabelSet
|
|
7
|
+
|
|
8
|
+
# The pure-modulo-frame-ownership summary: no origins, nothing declared, exhaustive, untainted.
|
|
9
|
+
def self.empty: () -> Summary
|
|
10
|
+
|
|
11
|
+
# A summary carrying a single taint and no labels — the fail-soft answer for a unit the collector
|
|
12
|
+
# could not finish.
|
|
13
|
+
def self.tainted: (String cause, ?String? detail) -> Summary
|
|
14
|
+
|
|
15
|
+
# sig-gen gap: #1154 — `initialize` normalizes the `bundles:`/`declared_bundles:` kwargs through
|
|
16
|
+
# `normalize_bundles` (join-merging per origin), so the readers do not trace to the parameters.
|
|
17
|
+
attr_reader bundles: Hash[Origin, LabelSet]
|
|
18
|
+
# sig-gen gap: #1154 — as above.
|
|
19
|
+
attr_reader declared_bundles: Hash[Origin, LabelSet]
|
|
20
|
+
# Unmarked residue — `proven`/`declared` are flattened from the bundle tables by `initialize`,
|
|
21
|
+
# not assigned from a parameter, so #1154 does not cover them (same shape as
|
|
22
|
+
# `Registry#additional_initializers`).
|
|
23
|
+
attr_reader declared: LabelSet
|
|
24
|
+
attr_reader proven: LabelSet
|
|
25
|
+
# sig-gen gap: #1154 — `causes` are `[cause, detail]` pairs normalized in `initialize`.
|
|
26
|
+
attr_reader causes: Array[[String, String?]]
|
|
27
|
+
|
|
28
|
+
def initialize: (?bundles: Hash[Origin, LabelSet], ?declared_bundles: Hash[Origin, LabelSet],
|
|
29
|
+
?exhaustive: bool, ?causes: Array[[String, String?]], ?unclaimed: bool) -> void
|
|
30
|
+
|
|
31
|
+
# Whether every call this method makes was resolved.
|
|
32
|
+
def exhaustive?: () -> bool
|
|
33
|
+
|
|
34
|
+
# Whether this method made a call nothing described — read by `rigor sig-gen`'s annotation
|
|
35
|
+
# emission alone (#391).
|
|
36
|
+
def unclaimed?: () -> bool
|
|
37
|
+
|
|
38
|
+
# Whether the report omits this row by default (#386).
|
|
39
|
+
def trivial?: () -> bool
|
|
40
|
+
|
|
41
|
+
# Union in every lane — reopenings and multi-file contributors fold through this.
|
|
42
|
+
def join: (Summary other) -> Summary
|
|
43
|
+
|
|
44
|
+
def ==: (untyped other) -> bool
|
|
45
|
+
alias eql? ==
|
|
46
|
+
def hash: () -> Integer
|
|
47
|
+
def inspect: () -> String
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Effects
|
|
3
|
+
# The closed enum of reasons a summary is not exhaustive (ADR-103 WD14). A reporting vocabulary,
|
|
4
|
+
# never a diagnostic one.
|
|
5
|
+
module TaintCause
|
|
6
|
+
ALL: Array[String]
|
|
7
|
+
|
|
8
|
+
# `cause.to_s` is looked up, so any object is a fair question.
|
|
9
|
+
def self?.valid?: (untyped cause) -> bool
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/sig/rigor/environment.rbs
CHANGED
|
@@ -15,10 +15,8 @@ module Rigor
|
|
|
15
15
|
attr_reader hkt_registry: untyped?
|
|
16
16
|
# Issue #784 — `[error_class_name, first_message_line, raw_frame_or_nil, stage]` when either stage of
|
|
17
17
|
# the HKT-registry build raised at its seam (`:scan`, the RBS `type`-alias scan; `:overlay`, the
|
|
18
|
-
# plugin-manifest aggregation — #791), nil when both built or were never demanded.
|
|
19
|
-
|
|
20
|
-
# `rigor sig-gen` emits nothing for this delegating reader, and the tuple shape is documented here.
|
|
21
|
-
def hkt_scan_failure: () -> untyped?
|
|
18
|
+
# plugin-manifest aggregation — #791), nil when both built or were never demanded.
|
|
19
|
+
def hkt_scan_failure: () -> [String, String, String?, Symbol]?
|
|
22
20
|
|
|
23
21
|
def self.default: () -> Environment
|
|
24
22
|
def self.for_project: (?root: String, ?libraries: Array[String], ?signature_paths: Array[String | _ToPath]?, ?cache_store: untyped?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?, ?source_rbs_synthesis_reporter: untyped?, ?bundler_bundle_path: String?, ?bundler_auto_detect: bool, ?synthetic_method_index: untyped?, ?project_patched_methods: untyped?) -> Environment
|
|
@@ -31,6 +29,9 @@ module Rigor
|
|
|
31
29
|
def nominal_for_name: (String | Symbol name) -> Type::Nominal?
|
|
32
30
|
def singleton_for_name: (String | Symbol name) -> Type::Singleton?
|
|
33
31
|
def constant_for_name: (String | Symbol name) -> Type::t?
|
|
32
|
+
# sig-gen gap: #1154 — the answer comes through `rbs_loader`, an `attr_reader` over an ivar assigned in
|
|
33
|
+
# `initialize` from a parameter, which reaches `untyped`.
|
|
34
|
+
def global_for_name: (String | Symbol name, ?builtin: bool) -> Type::t?
|
|
34
35
|
def class_known?: (String | Symbol name) -> bool
|
|
35
36
|
def rbs_module?: (String | Symbol name) -> bool
|
|
36
37
|
def singleton_extended_modules: (String | Symbol name) -> Array[String]
|
|
@@ -59,7 +60,7 @@ module Rigor
|
|
|
59
60
|
|
|
60
61
|
def self.default: () -> RbsLoader
|
|
61
62
|
def self.reset_default!: () -> void
|
|
62
|
-
def self.build_env_for: (libraries: Array[String], signature_paths: Array[String | _ToPath]) ->
|
|
63
|
+
def self.build_env_for: (libraries: Array[String], signature_paths: Array[String | _ToPath]) -> ::RBS::Environment
|
|
63
64
|
def self.vendored_gem_sig_paths: () -> Array[Pathname]
|
|
64
65
|
def self.capability_role_sig_paths: () -> ([Pathname] | [])
|
|
65
66
|
def self.vendored_gem_names: () -> Array[String]
|
|
@@ -67,10 +68,10 @@ module Rigor
|
|
|
67
68
|
def initialize: (?libraries: Array[String], ?signature_paths: Array[String | _ToPath], ?cache_store: untyped?) -> void
|
|
68
69
|
def class_known?: (String | Symbol name) -> bool
|
|
69
70
|
def rbs_module?: (String | Symbol name) -> bool
|
|
70
|
-
def instance_definition: (String | Symbol class_name) ->
|
|
71
|
-
def instance_method: (class_name: String | Symbol, method_name: String | Symbol) ->
|
|
72
|
-
def singleton_definition: (String | Symbol class_name) ->
|
|
73
|
-
def singleton_method: (class_name: String | Symbol, method_name: String | Symbol) ->
|
|
71
|
+
def instance_definition: (String | Symbol class_name) -> ::RBS::Definition?
|
|
72
|
+
def instance_method: (class_name: String | Symbol, method_name: String | Symbol) -> ::RBS::Definition::Method?
|
|
73
|
+
def singleton_definition: (String | Symbol class_name) -> ::RBS::Definition?
|
|
74
|
+
def singleton_method: (class_name: String | Symbol, method_name: String | Symbol) -> ::RBS::Definition::Method?
|
|
74
75
|
def class_type_param_names: (String | Symbol class_name) -> Array[Symbol]
|
|
75
76
|
def project_declared_classes: () -> Set[String]
|
|
76
77
|
def project_declared_class?: (String | Symbol class_name) -> bool
|
|
@@ -79,7 +80,8 @@ module Rigor
|
|
|
79
80
|
def singleton_extended_module_names: (String | Symbol class_name) -> Array[String]
|
|
80
81
|
def constant_type: (String name) -> Type::t?
|
|
81
82
|
def constant_names: () -> Array[String]
|
|
82
|
-
def each_known_class_name: () { (String name) -> void } ->
|
|
83
|
+
def each_known_class_name: () { (String name) -> void } -> void
|
|
84
|
+
| () -> ::Enumerator[String, void]
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
class RbsHierarchy
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Inference
|
|
3
|
+
module OptimisticOrigin
|
|
4
|
+
# sig-gen gap: #1150 — sig-gen types the `BoundMark#miss` member read `untyped`, so it skips this reader
|
|
5
|
+
# (sig.skipped.untyped-return). The answer is the recorded `true` / `false` / `nil`, or the `UNKNOWN_MISS`
|
|
6
|
+
# sentinel; declaring it is what lets sig-gen type `Scope#optimistic_local_miss` / `#optimistic_ivar_miss`.
|
|
7
|
+
def self?.bound_miss: (untyped mark) -> Object?
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
data/sig/rigor/inference.rbs
CHANGED
|
@@ -23,8 +23,10 @@ module Rigor
|
|
|
23
23
|
class ClassFrame
|
|
24
24
|
attr_reader name: String
|
|
25
25
|
attr_reader singleton: bool
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type.
|
|
27
|
+
attr_reader refinement: bool
|
|
28
|
+
def self.new: (name: String, singleton: bool, ?refinement: bool) -> ClassFrame
|
|
29
|
+
def initialize: (name: String, singleton: bool, ?refinement: bool) -> void
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
def initialize: (scope: Scope, ?tracer: FallbackTracer?, ?on_enter: (^(untyped, Scope) -> void)?, ?class_context: Array[ClassFrame]) -> void
|
|
@@ -113,7 +115,7 @@ module Rigor
|
|
|
113
115
|
def self?.value_pattern_certainty: (Type::t subject_type, untyped pattern_value) -> (:yes | :no | :maybe)
|
|
114
116
|
def self?.predicate_scopes: (untyped node, Scope scope) -> [Scope, Scope]
|
|
115
117
|
def self?.case_when_scopes: (untyped subject, Array[untyped] conditions, Scope scope) -> [Scope, Scope]
|
|
116
|
-
def self?.analyse: (untyped node, Scope scope) ->
|
|
118
|
+
def self?.analyse: (untyped node, Scope scope) -> [Scope, Scope]?
|
|
117
119
|
def self?.subclass_of?: (String rigor_class_name, String target_class_name, untyped context) -> bool
|
|
118
120
|
def self?.class_ordering: (String lhs, String rhs, untyped context) -> Symbol
|
|
119
121
|
def self?.trusted_equality_literal?: (untyped literal) -> bool
|
|
@@ -170,7 +172,7 @@ module Rigor
|
|
|
170
172
|
def self?.collect_class_decls: (untyped node, Array[String] qualified_prefix, Hash[String, Type::t] accumulator) -> void
|
|
171
173
|
def self?.constant_writes_for_file: (untyped root) -> Hash[String, untyped]
|
|
172
174
|
def self?.constant_literal_value: (untyped rvalue) -> Array[untyped]?
|
|
173
|
-
def self?.finalize_constant_writes: (Hash[String, Hash[String, untyped]] writes) -> [Hash[String, Type::
|
|
175
|
+
def self?.finalize_constant_writes: (Hash[String, Hash[String, untyped]] writes) -> [Hash[String, Type::Constant], Hash[String, Set[String]]]
|
|
174
176
|
def self?.propagate: (untyped node, Hash[untyped, Scope] table, Scope parent_scope) -> void
|
|
175
177
|
end
|
|
176
178
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Plugin
|
|
3
|
+
# ADR-38 declaration — methods/def-blocks that establish ivar state like `initialize` does, so
|
|
4
|
+
# the read-before-write nil soundness gate does not widen their ivars. See
|
|
5
|
+
# lib/rigor/plugin/additional_initializer.rb for the full contract.
|
|
6
|
+
class AdditionalInitializer
|
|
7
|
+
# sig-gen gap: #1154 — `attr_reader` rows over ivars assigned from `initialize` parameters are
|
|
8
|
+
# skipped (untyped return); the constructor validates `receiver_constraint` is a non-empty
|
|
9
|
+
# String and normalizes both lists with `map(&:to_sym)`, so the stored types are hand-written.
|
|
10
|
+
attr_reader receiver_constraint: String
|
|
11
|
+
|
|
12
|
+
# sig-gen gap: #1154 — as above.
|
|
13
|
+
attr_reader methods: Array[Symbol]
|
|
14
|
+
|
|
15
|
+
# sig-gen gap: #1154 — as above.
|
|
16
|
+
attr_reader block_methods: Array[Symbol]
|
|
17
|
+
|
|
18
|
+
# The validators accept Symbol or non-empty String elements; `initialize` normalizes to
|
|
19
|
+
# Symbol before storing. At least one of `methods:`/`block_methods:` must be non-empty.
|
|
20
|
+
def initialize: (receiver_constraint: String, ?methods: Array[Symbol | String], ?block_methods: Array[Symbol | String]) -> void
|
|
21
|
+
|
|
22
|
+
def covers_method?: (Symbol method_name) -> bool
|
|
23
|
+
|
|
24
|
+
def covers_block_method?: (Symbol method_name) -> bool
|
|
25
|
+
|
|
26
|
+
def to_h: () -> Hash[String, String | Array[String]]
|
|
27
|
+
|
|
28
|
+
def ==: (untyped other) -> bool
|
|
29
|
+
|
|
30
|
+
# `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked residue.
|
|
31
|
+
def eql?: (untyped other) -> bool
|
|
32
|
+
|
|
33
|
+
def hash: () -> Integer
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/sig/rigor/plugin/base.rbs
CHANGED
|
@@ -17,11 +17,11 @@ class Rigor::Plugin::Base
|
|
|
17
17
|
def self.producer: (untyped id, ?watch: untyped, ?serialize: untyped, ?deserialize: untyped, ?generation_cap: untyped) { (untyped params) -> untyped } -> Symbol
|
|
18
18
|
def self.producers: () -> Hash[Symbol, untyped]
|
|
19
19
|
|
|
20
|
-
def self.node_rule: (untyped node_type) { (*untyped) -> untyped } ->
|
|
20
|
+
def self.node_rule: (untyped node_type) { (*untyped) -> untyped } -> Class
|
|
21
21
|
def self.node_rules: () -> Array[untyped]
|
|
22
22
|
|
|
23
|
-
def self.node_file_context: () { (untyped root, untyped scope) -> untyped } ->
|
|
24
|
-
def self.node_file_context_block: () -> untyped
|
|
23
|
+
def self.node_file_context: () { (untyped root, untyped scope) -> untyped } -> void
|
|
24
|
+
def self.node_file_context_block: () -> (^(untyped root, untyped scope) -> untyped)?
|
|
25
25
|
|
|
26
26
|
def self.dynamic_return: (?receivers: (Array[String] | ^() -> Array[String])?, ?methods: (Array[untyped] | ^() -> Array[untyped])?, ?file_methods: (^(untyped path) -> Array[untyped])?) { (untyped call_node, untyped scope) -> untyped } -> nil
|
|
27
27
|
def self.dynamic_returns: () -> Array[untyped]
|
|
@@ -44,22 +44,45 @@ class Rigor::Plugin::Base
|
|
|
44
44
|
def init: (untyped services) -> nil
|
|
45
45
|
def prepare: (untyped services) -> nil
|
|
46
46
|
def diagnostics_for_file: (path: untyped, scope: untyped, root: untyped) -> Array[untyped]
|
|
47
|
+
# authored: hook-contract widening — the element type comes from a plugin gem sig-gen never
|
|
48
|
+
# sees, so no engine work would let it answer; the declared `Array[Rigor::Plugin::TemplateUnit]`
|
|
49
|
+
# over a bare-`[]` default body is the author's contract.
|
|
50
|
+
def template_units_for_file: (path: untyped, source: untyped) -> Array[untyped]
|
|
51
|
+
# authored: hook-contract widening — the element type comes from a plugin gem sig-gen never
|
|
52
|
+
# sees, so no engine work would let it answer; the declared record contract over a bare-`[]`
|
|
53
|
+
# default body is the author's.
|
|
54
|
+
def declared_members: (untyped class_name) -> Array[untyped]
|
|
47
55
|
|
|
48
56
|
# Engine-executed dispatch over the declared DSLs.
|
|
49
57
|
def node_rule_diagnostics: (path: untyped, scope: untyped, root: untyped) -> Array[untyped]
|
|
50
|
-
|
|
58
|
+
# sig-gen gap: #1007 — the true `return result if result` branch (base.rb:594) flows through an
|
|
59
|
+
# `instance_exec`'d, plugin-supplied Proc that sig-gen's inference does not fold into the return
|
|
60
|
+
# join, so it proposes the literal fallback `nil` instead of the honest contract.
|
|
61
|
+
def dynamic_return_type: (call_node: untyped, scope: untyped, receiver_type: untyped) -> Rigor::Type::t?
|
|
51
62
|
def narrowing_facts_for: (call_node: untyped, scope: untyped) -> Array[untyped]
|
|
52
63
|
|
|
53
64
|
# Authoring helpers.
|
|
54
|
-
def diagnostic: (untyped node, path: untyped, message: untyped, ?severity: untyped, ?rule: untyped, ?location: untyped) ->
|
|
65
|
+
def diagnostic: (untyped node, path: untyped, message: untyped, ?severity: untyped, ?rule: untyped, ?location: untyped) -> Rigor::Analysis::Diagnostic
|
|
55
66
|
def diagnostics_for: (untyped violations, path: untyped, ?node: untyped) -> Array[untyped]
|
|
56
67
|
def read_fact: (plugin_id: untyped, name: untyped) -> untyped
|
|
57
68
|
def producer_value: (untyped id, ?params: untyped) -> untyped
|
|
58
69
|
def producer_error: (untyped id) -> untyped
|
|
70
|
+
def disclose_once: (untyped key, message: untyped, ?severity: untyped, ?rule: untyped) -> nil
|
|
71
|
+
def emit_once: (untyped key, untyped diagnostics) -> nil
|
|
72
|
+
def run_disclosure_records: () -> Array[untyped]
|
|
59
73
|
def manifest: () -> Rigor::Plugin::Manifest
|
|
60
74
|
def signature_paths: () -> Array[String]
|
|
61
|
-
|
|
75
|
+
# Defaults to `manifest.protocol_contracts`; a plugin MAY override to fold per-project config in,
|
|
76
|
+
# but the contract (an Array of ProtocolContract) holds either way.
|
|
77
|
+
def protocol_contracts: () -> Array[Rigor::Plugin::ProtocolContract]
|
|
78
|
+
# The ADR-103 effect surfaces delegate to the manifest by default; a plugin MAY override
|
|
79
|
+
# `effect_attributions` to fold per-project config in, but the contract holds either way.
|
|
80
|
+
def effect_labels: () -> Array[String]
|
|
81
|
+
def effect_attributions: () -> Array[Rigor::Plugin::EffectAttribution]
|
|
82
|
+
def effect_edges: () -> Array[Rigor::Plugin::EffectEdge]
|
|
83
|
+
def effect_entry_points: () -> Array[Rigor::Plugin::EffectEntryPoints]
|
|
84
|
+
def effect_ancestry: () -> Array[Rigor::Plugin::EffectAncestry]
|
|
62
85
|
def io_boundary: () -> Rigor::Plugin::IoBoundary
|
|
63
|
-
def cache_for: (untyped producer_id, ?params: untyped, ?descriptor: untyped) ->
|
|
86
|
+
def cache_for: (untyped producer_id, ?params: untyped, ?descriptor: untyped) -> Proc
|
|
64
87
|
def plugin_entry: () -> untyped
|
|
65
88
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Plugin
|
|
3
|
+
# One `effect_ancestry:` row: an ancestry edge the plugin's own gem introduces and the project's
|
|
4
|
+
# source never writes down (ADR-103 WD17, #465). `parent:` need only be a true ancestor, not the
|
|
5
|
+
# immediate superclass. Bundled plugins only — `Effects::PluginFacts` enforces it. Frozen value
|
|
6
|
+
# object.
|
|
7
|
+
class EffectAncestry
|
|
8
|
+
# sig-gen gap: #1154 — validated in `initialize` from the parameter of the same name
|
|
9
|
+
# (`to_s`-normalized, frozen), so sig-gen proposes the raw parameter shape.
|
|
10
|
+
attr_reader child: String
|
|
11
|
+
# sig-gen gap: #1154 — same shape as `child`.
|
|
12
|
+
attr_reader parent: String
|
|
13
|
+
# sig-gen gap: #1154 — same shape; `why:` is required and validated non-empty.
|
|
14
|
+
attr_reader why: String
|
|
15
|
+
|
|
16
|
+
def initialize: (child: untyped, parent: untyped, why: untyped) -> void
|
|
17
|
+
|
|
18
|
+
def to_h: () -> Hash[String, untyped]
|
|
19
|
+
|
|
20
|
+
def ==: (untyped other) -> bool
|
|
21
|
+
# `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
|
|
22
|
+
# residue.
|
|
23
|
+
def eql?: (untyped other) -> bool
|
|
24
|
+
def hash: () -> Integer
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Plugin
|
|
3
|
+
# One `effect_attributions:` row: the receiver spelling, the selector, and the labels the call
|
|
4
|
+
# contributes to the declared lane — plus the optional `narrow:`/`callee:`/`taint:`/`responds:`
|
|
5
|
+
# modifiers the engine owns the strategy for (#393/#1048/#1065). Frozen value object.
|
|
6
|
+
class EffectAttribution
|
|
7
|
+
# A receiver spelled as a `Constant::Path` — the class-name form.
|
|
8
|
+
CLASS_NAME: Regexp
|
|
9
|
+
# A receiver path: a constant head followed by one or more sends (`Rails.cache`).
|
|
10
|
+
RECEIVER_PATH: Regexp
|
|
11
|
+
# A self path: implicit self followed by one or more receiver-less sends (`self.flash.now`).
|
|
12
|
+
SELF_PATH: Regexp
|
|
13
|
+
# What a self path is rooted at, once the `self.` head is stripped.
|
|
14
|
+
SELF_HEAD: String
|
|
15
|
+
# The taint causes a plugin row may name — a closed subset of `Effects::TaintCause::ALL`.
|
|
16
|
+
TAINT_CAUSES: Array[String]
|
|
17
|
+
|
|
18
|
+
# sig-gen gap: #1154 — normalized/validated in `initialize` from the parameter of the same
|
|
19
|
+
# name (`to_s`-coerced, frozen), so sig-gen proposes the raw parameter shape.
|
|
20
|
+
attr_reader receiver: String
|
|
21
|
+
# sig-gen gap: #1154 — `to_sym`-normalized from the `method:` parameter.
|
|
22
|
+
attr_reader method: Symbol
|
|
23
|
+
attr_reader singleton: bool
|
|
24
|
+
# sig-gen gap: #1154 — `Array()`-normalized, deduplicated and frozen from `labels:`.
|
|
25
|
+
attr_reader labels: Array[String]
|
|
26
|
+
# sig-gen gap: #1154 — `to_s`-normalized from the `narrow:` parameter.
|
|
27
|
+
attr_reader narrow: String?
|
|
28
|
+
attr_reader discharge: bool
|
|
29
|
+
# sig-gen gap: #1154 — `to_s`-normalized from the `within:` parameter.
|
|
30
|
+
attr_reader within: String?
|
|
31
|
+
attr_reader on_result: bool
|
|
32
|
+
# sig-gen gap: #1154 — `to_s`-normalized from the `taint:` parameter.
|
|
33
|
+
attr_reader taint: String?
|
|
34
|
+
# sig-gen gap: #1154 — `to_s`-normalized from the `callee:` parameter.
|
|
35
|
+
attr_reader callee: String?
|
|
36
|
+
# sig-gen gap: #1154 — normalized from the `callee_fallbacks:` parameter.
|
|
37
|
+
attr_reader callee_fallbacks: Hash[String, Array[String]]?
|
|
38
|
+
attr_reader responds: bool
|
|
39
|
+
# sig-gen gap: #1154 — `to_s`-normalized from the `why:` parameter.
|
|
40
|
+
attr_reader why: String
|
|
41
|
+
|
|
42
|
+
# The coercion-facing constructor: every parameter is `to_s`/`to_sym`/`Array()`-normalized,
|
|
43
|
+
# so `untyped` is the honest parameter type throughout.
|
|
44
|
+
def initialize: (receiver: untyped, method: untyped, labels: untyped, why: untyped,
|
|
45
|
+
?singleton: untyped, ?narrow: untyped, ?discharge: untyped,
|
|
46
|
+
?within: untyped, ?on_result: untyped, ?taint: untyped, ?callee: untyped,
|
|
47
|
+
?callee_fallbacks: untyped, ?responds: untyped) -> void
|
|
48
|
+
|
|
49
|
+
# Whether {#receiver} is a receiver path (`Rails.cache`) rather than a class name or a
|
|
50
|
+
# self path.
|
|
51
|
+
def receiver_path?: () -> bool
|
|
52
|
+
# Whether {#receiver} is a self path (`self.flash.now`).
|
|
53
|
+
def self_path?: () -> bool
|
|
54
|
+
|
|
55
|
+
# The key an origin and a report spell this row as.
|
|
56
|
+
def key: () -> String
|
|
57
|
+
def to_h: () -> Hash[String, untyped]
|
|
58
|
+
|
|
59
|
+
def ==: (untyped other) -> bool
|
|
60
|
+
# `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
|
|
61
|
+
# residue.
|
|
62
|
+
def eql?: (untyped other) -> bool
|
|
63
|
+
def hash: () -> Integer
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Plugin
|
|
3
|
+
# One `effect_edges:` row: a framework-edge strategy naming the base `receiver` a plugin points
|
|
4
|
+
# the engine at, the `target` strategy slot, and an optional method-level `selector`. Frozen
|
|
5
|
+
# value object.
|
|
6
|
+
class EffectEdge
|
|
7
|
+
# The closed set of framework-edge strategies the engine implements.
|
|
8
|
+
TARGETS: Array[Symbol]
|
|
9
|
+
|
|
10
|
+
# sig-gen gap: #1154 — validated/normalized in `initialize` from the parameter of the same
|
|
11
|
+
# name, so sig-gen proposes the raw parameter shape.
|
|
12
|
+
attr_reader receiver: String
|
|
13
|
+
# sig-gen gap: #1154 — `to_sym`-normalized from the `method:` parameter.
|
|
14
|
+
attr_reader method: Symbol?
|
|
15
|
+
attr_reader singleton: bool
|
|
16
|
+
# sig-gen gap: #1154 — validated against `TARGETS` in `initialize`.
|
|
17
|
+
attr_reader target: (:activerecord_callbacks | :perform_now | :mailer_body)
|
|
18
|
+
# sig-gen gap: #1154 — `to_s`-normalized from the `why:` parameter.
|
|
19
|
+
attr_reader why: String
|
|
20
|
+
|
|
21
|
+
def initialize: (receiver: untyped, target: untyped, why: untyped, ?method: untyped,
|
|
22
|
+
?singleton: untyped) -> void
|
|
23
|
+
|
|
24
|
+
def to_h: () -> Hash[String, untyped]
|
|
25
|
+
|
|
26
|
+
def ==: (untyped other) -> bool
|
|
27
|
+
# `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
|
|
28
|
+
# residue.
|
|
29
|
+
def eql?: (untyped other) -> bool
|
|
30
|
+
def hash: () -> Integer
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Plugin
|
|
3
|
+
# One `effect_entry_points:` row: a named set of globs marking project files whose methods are
|
|
4
|
+
# framework entry points (ADR-103 WD6). Frozen value object; {#globs} are deduplicated and
|
|
5
|
+
# sorted in `initialize`.
|
|
6
|
+
class EffectEntryPoints
|
|
7
|
+
# sig-gen gap: #1154 — `to_s`-normalized in `initialize` from the `name:` parameter.
|
|
8
|
+
attr_reader name: String
|
|
9
|
+
# sig-gen gap: #1154 — deduplicated/sorted/frozen in `initialize` from `globs:`.
|
|
10
|
+
attr_reader globs: Array[String]
|
|
11
|
+
# sig-gen gap: #1154 — `to_s`-normalized in `initialize` from `why:`.
|
|
12
|
+
attr_reader why: String
|
|
13
|
+
|
|
14
|
+
def initialize: (name: untyped, globs: untyped, ?why: untyped) -> void
|
|
15
|
+
|
|
16
|
+
def to_h: () -> Hash[String, untyped]
|
|
17
|
+
|
|
18
|
+
def ==: (untyped other) -> bool
|
|
19
|
+
# `alias eql? ==` — the alias row has no sig-gen shape, so it stays unmarked
|
|
20
|
+
# residue.
|
|
21
|
+
def eql?: (untyped other) -> bool
|
|
22
|
+
def hash: () -> Integer
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -4,7 +4,7 @@ class Rigor::Plugin::IoBoundary
|
|
|
4
4
|
def file?: (untyped) -> bool
|
|
5
5
|
def directory?: (untyped) -> bool
|
|
6
6
|
def list_directory: (untyped) -> Array[String]
|
|
7
|
-
# sig-gen gap: #
|
|
7
|
+
# sig-gen gap: #1156 — the generator pins the empty-summary literal (`count: 0, first_path: nil`); the
|
|
8
8
|
# record's fields are the running count and the first refused path, nil when nothing was refused.
|
|
9
9
|
def refusal_summary: () -> { count: Integer, first_path: String?, nearest_root: String? }?
|
|
10
10
|
def open_url: (untyped url) -> String
|
data/sig/rigor/plugin/loader.rbs
CHANGED
|
@@ -12,9 +12,9 @@ module Rigor
|
|
|
12
12
|
attr_reader services: untyped
|
|
13
13
|
attr_reader requirer: ^(String) -> untyped
|
|
14
14
|
|
|
15
|
-
def self.load: (configuration: Configuration, services: untyped, ?requirer: ^(String) -> untyped) ->
|
|
16
|
-
def initialize: (services: untyped, ?requirer: ^(String) -> untyped) -> void
|
|
17
|
-
def load: (Array[String | Hash[untyped, untyped]] entries) ->
|
|
15
|
+
def self.load: (configuration: Configuration, services: untyped, ?requirer: ^(String) -> untyped, ?feature_resolver: untyped) -> Registry
|
|
16
|
+
def initialize: (services: untyped, ?requirer: ^(String) -> untyped, ?feature_resolver: untyped) -> void
|
|
17
|
+
def load: (Array[String | Hash[untyped, untyped]] entries) -> Registry
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -3,35 +3,74 @@ class Rigor::Plugin::Manifest::Consumption
|
|
|
3
3
|
end
|
|
4
4
|
|
|
5
5
|
class Rigor::Plugin::Manifest
|
|
6
|
-
def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?target_gems: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts:
|
|
6
|
+
def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?target_gems: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?rbs_complete_ancestors: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: Array[Rigor::Plugin::ProtocolContract], ?source_rbs_synthesizer: untyped, ?additional_initializers: Array[Rigor::Plugin::AdditionalInitializer], ?effect_root: String?, ?effect_labels: Array[String], ?effect_attributions: Array[Rigor::Plugin::EffectAttribution], ?effect_edges: Array[Rigor::Plugin::EffectEdge], ?effect_entry_points: Array[Rigor::Plugin::EffectEntryPoints], ?effect_ancestry: Array[Rigor::Plugin::EffectAncestry], ?template_globs: untyped) -> void
|
|
7
7
|
|
|
8
8
|
# Public attribute readers (the full `attr_reader` surface). Plugins
|
|
9
9
|
# read `manifest.id` / `manifest.protocol_contracts` etc.; declaring
|
|
10
10
|
# them keeps the contract surface resolvable so ADR-43 ancestor
|
|
11
11
|
# resolution does not surface a false `call.undefined-method` on a
|
|
12
|
-
# real reader.
|
|
13
|
-
#
|
|
12
|
+
# real reader. Slots whose element classes are sig-covered carry the
|
|
13
|
+
# validated element type (the `validate_*!` constructors prove it);
|
|
14
|
+
# the rest stay `untyped` per the sparse `sig/` tree.
|
|
14
15
|
def id: () -> String
|
|
15
16
|
def version: () -> String
|
|
16
17
|
def description: () -> String?
|
|
17
18
|
def config_schema: () -> untyped
|
|
18
19
|
def config_defaults: () -> Hash[String, untyped]
|
|
19
20
|
def target_gems: () -> Array[String]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def
|
|
24
|
-
def
|
|
21
|
+
# sig-gen gap: #1154 — an `attr_reader` over an ivar assigned in `initialize` from a parameter the
|
|
22
|
+
# manifest validates but does not type, so inference reaches `untyped` where the contract is
|
|
23
|
+
# `Array[String]` (the same gap every other reader in this block carries).
|
|
24
|
+
def template_globs: () -> Array[String]
|
|
25
|
+
def produces: () -> Array[Symbol]
|
|
26
|
+
def consumes: () -> Array[Rigor::Plugin::Manifest::Consumption]
|
|
27
|
+
def owns_receivers: () -> Array[String]
|
|
28
|
+
def open_receivers: () -> Array[String]
|
|
29
|
+
def rbs_complete_ancestors: () -> Array[String]
|
|
30
|
+
def type_node_resolvers: () -> Array[Rigor::Plugin::TypeNodeResolver]
|
|
25
31
|
def block_as_methods: () -> untyped
|
|
26
32
|
def heredoc_templates: () -> untyped
|
|
27
33
|
def nested_class_templates: () -> untyped
|
|
28
34
|
def trait_registries: () -> untyped
|
|
29
35
|
def hkt_registrations: () -> untyped
|
|
30
36
|
def hkt_definitions: () -> untyped
|
|
31
|
-
def signature_paths: () ->
|
|
32
|
-
|
|
37
|
+
def signature_paths: () -> Array[String]
|
|
38
|
+
# sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter;
|
|
39
|
+
# `validate_protocol_contracts!` requires every element `is_a?(ProtocolContract)`.
|
|
40
|
+
def protocol_contracts: () -> Array[Rigor::Plugin::ProtocolContract]
|
|
41
|
+
# ADR-32 WD6/WD12 — any object responding to `call`, and its result is a documented multi-shape
|
|
42
|
+
# outcome (`String` / nil / `[:error, msg]` / `[:ok, src, msgs]`), not `String?` — `untyped` is the
|
|
43
|
+
# honest claim until the outcome has a sig'd shape.
|
|
33
44
|
def source_rbs_synthesizer: () -> untyped
|
|
34
|
-
|
|
45
|
+
# sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter;
|
|
46
|
+
# the validator (`validate_additional_initializers!`) requires every element
|
|
47
|
+
# `is_a?(AdditionalInitializer)`, so the element type is hand-written.
|
|
48
|
+
def additional_initializers: () -> Array[Rigor::Plugin::AdditionalInitializer]
|
|
49
|
+
|
|
50
|
+
# sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter
|
|
51
|
+
# (`to_s`-normalized); `validate_effect_root!` bounds the spelling.
|
|
52
|
+
def effect_root: () -> String?
|
|
53
|
+
# sig-gen gap: #1154 — `attr_reader` over an ivar normalized in `initialize` from a parameter;
|
|
54
|
+
# `validate_effect_labels!` requires non-empty `String` elements.
|
|
55
|
+
def effect_labels: () -> Array[String]
|
|
56
|
+
# sig-gen gap: #1154 — `attr_reader` over an ivar assigned in `initialize` from a parameter;
|
|
57
|
+
# `validate_effect_attributions!` requires every element `is_a?(EffectAttribution)`.
|
|
58
|
+
def effect_attributions: () -> Array[Rigor::Plugin::EffectAttribution]
|
|
59
|
+
# sig-gen gap: #1154 — same shape; `validate_effect_edges!` requires `is_a?(EffectEdge)`.
|
|
60
|
+
def effect_edges: () -> Array[Rigor::Plugin::EffectEdge]
|
|
61
|
+
# sig-gen gap: #1154 — same shape; `validate_effect_entry_points!` requires
|
|
62
|
+
# `is_a?(EffectEntryPoints)`.
|
|
63
|
+
def effect_entry_points: () -> Array[Rigor::Plugin::EffectEntryPoints]
|
|
64
|
+
# sig-gen gap: #1154 — same shape; `validate_effect_ancestry!` requires `is_a?(EffectAncestry)`.
|
|
65
|
+
def effect_ancestry: () -> Array[Rigor::Plugin::EffectAncestry]
|
|
66
|
+
|
|
67
|
+
# The identity opening a root when this plugin's labels join the run's vocabulary: the
|
|
68
|
+
# `effect_root` for a bundled first-party plugin that declares one, the plugin `id` otherwise.
|
|
69
|
+
def effect_owner: () -> String
|
|
70
|
+
# Whether this plugin's `effect_attributions:` may carry `discharge: true` (ADR-103 WD6).
|
|
71
|
+
def effect_discharge_allowed?: () -> bool
|
|
72
|
+
# Whether the plugin contributes anything to the effect surfaces at all.
|
|
73
|
+
def effects?: () -> bool
|
|
35
74
|
|
|
36
75
|
def validate_config: (untyped) -> Array[String]
|
|
37
76
|
def to_h: () -> Hash[String, untyped]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Rigor
|
|
2
|
+
module Plugin
|
|
3
|
+
# ADR-28 declaration — "every instance/singleton method named `method_name` in a file matching
|
|
4
|
+
# `path_glob` carries the declared parameter + return-type protocol" (provide-and-check). See
|
|
5
|
+
# lib/rigor/plugin/protocol_contract.rb for the full contract.
|
|
6
|
+
class ProtocolContract
|
|
7
|
+
VALID_SEVERITIES: Array[Symbol]
|
|
8
|
+
|
|
9
|
+
# One positional-parameter provision: zero-based index + fully-qualified type name.
|
|
10
|
+
class ParamType < ::Data
|
|
11
|
+
# sig-gen gap: #1150 — `Data.define` member reads carry no type; `coerce_param_type` proves
|
|
12
|
+
# `index` is a non-negative Integer and `type_name` a non-empty String, so the member rows
|
|
13
|
+
# are hand-written.
|
|
14
|
+
def index: () -> Integer
|
|
15
|
+
|
|
16
|
+
# sig-gen gap: #1150 — as above.
|
|
17
|
+
def type_name: () -> String
|
|
18
|
+
|
|
19
|
+
# sig-gen gap: #1150 — as above.
|
|
20
|
+
def self.new: (index: Integer, type_name: String) -> instance | (Integer index, String type_name) -> instance
|
|
21
|
+
|
|
22
|
+
# sig-gen gap: #1150 — as above.
|
|
23
|
+
def self.[]: (index: Integer, type_name: String) -> instance | (Integer index, String type_name) -> instance
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# sig-gen gap: #1154 — `attr_reader` rows over ivars assigned in `initialize`; each is
|
|
27
|
+
# validated/normalized first (`dup.freeze`/`to_sym`/truthiness collapse/coerce), so the
|
|
28
|
+
# stored types are hand-written.
|
|
29
|
+
attr_reader path_glob: String
|
|
30
|
+
|
|
31
|
+
# sig-gen gap: #1154 — as above (`to_sym` normalizes the accepted Symbol|String).
|
|
32
|
+
attr_reader method_name: Symbol
|
|
33
|
+
|
|
34
|
+
# `singleton ? true : false` collapses any truthy input to bool — sig-gen already infers
|
|
35
|
+
# `false | true`, so this row is generated-equivalent rather than a #1154 gap.
|
|
36
|
+
attr_reader singleton: bool
|
|
37
|
+
|
|
38
|
+
# sig-gen gap: #1154 — as above (`coerce_param_types` guarantees `Array[ParamType]`).
|
|
39
|
+
attr_reader param_types: Array[ParamType]
|
|
40
|
+
|
|
41
|
+
# sig-gen gap: #1154 — as above (nil or a non-empty `dup.freeze`d String).
|
|
42
|
+
attr_reader return_type_name: String?
|
|
43
|
+
|
|
44
|
+
# sig-gen gap: #1154 — as above (`VALID_SEVERITIES.include?(to_sym)` bounds the stored value
|
|
45
|
+
# to the three declared literals).
|
|
46
|
+
attr_reader severity: :error | :warning | :info
|
|
47
|
+
|
|
48
|
+
# `method_name`/`severity` accept String too (both are `to_sym`'d); `param_types` entries are
|
|
49
|
+
# ParamType or a Hash with `index`/`type_name` keys (String or Symbol keys accepted by the
|
|
50
|
+
# coercion). `singleton` is documented Boolean; the impl collapses any truthy value.
|
|
51
|
+
def initialize: (path_glob: String, method_name: Symbol | String, ?return_type_name: String?, ?param_types: Array[ParamType | Hash[untyped, untyped]], ?singleton: bool, ?severity: Symbol | String) -> void
|
|
52
|
+
|
|
53
|
+
# Copy with `path_glob` replaced — plugin config-folding hook for the convention path.
|
|
54
|
+
def with_path_glob: (String glob) -> ProtocolContract
|
|
55
|
+
|
|
56
|
+
# Values are String/bool/nil or the per-param `Hash[String, Integer | String]` rows — kept
|
|
57
|
+
# `untyped` to match the manifest's `to_h` convention.
|
|
58
|
+
def to_h: () -> Hash[String, untyped]
|
|
59
|
+
|
|
60
|
+
def ==: (untyped other) -> bool
|
|
61
|
+
|
|
62
|
+
# `alias eql? ==` — no sig-gen shape for alias rows; unmarked residue.
|
|
63
|
+
def eql?: (untyped other) -> bool
|
|
64
|
+
|
|
65
|
+
def hash: () -> Integer
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|