rigortype 0.3.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/data/capability_roles/capability_roles.rbs +36 -0
- 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 +236 -17
- data/docs/handbook/02-everyday-types.md +17 -14
- data/docs/handbook/03-narrowing.md +132 -14
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/05-methods-and-blocks.md +1 -1
- data/docs/handbook/06-classes.md +2 -2
- data/docs/handbook/07-rbs-and-extended.md +19 -1
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +525 -13
- data/docs/handbook/README.md +1 -1
- data/docs/handbook/appendix-elixir.md +2 -2
- data/docs/handbook/appendix-go.md +2 -2
- data/docs/handbook/appendix-java-csharp.md +2 -2
- data/docs/handbook/appendix-mypy.md +2 -2
- data/docs/handbook/appendix-phpstan.md +1 -1
- data/docs/handbook/appendix-rust.md +1 -1
- data/docs/handbook/appendix-type-theory.md +4 -4
- data/docs/handbook/appendix-typescript.md +1 -1
- data/docs/llms.txt +2 -0
- data/docs/manual/02-cli-reference.md +95 -6
- data/docs/manual/03-configuration.md +18 -0
- data/docs/manual/04-diagnostics.md +15 -0
- data/docs/manual/07-plugins.md +15 -5
- data/docs/manual/08-skills.md +23 -2
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/11-ci.md +9 -0
- data/docs/manual/15-type-protection-coverage.md +8 -0
- data/docs/manual/16-rbs-extended-annotations.md +46 -8
- data/docs/manual/18-removing-dead-code.md +10 -8
- 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 +261 -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 +138 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
- 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 +229 -1
- 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 +3 -3
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
- data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
- data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -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 +38 -4
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
- data/lib/rigor/analysis/check_rules.rb +718 -79
- data/lib/rigor/analysis/crash_signature.rb +8 -24
- data/lib/rigor/analysis/dependency_recorder.rb +23 -0
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
- data/lib/rigor/analysis/erb_template_detector.rb +1 -2
- data/lib/rigor/analysis/fact_store.rb +15 -1
- data/lib/rigor/analysis/incremental.rb +42 -0
- data/lib/rigor/analysis/incremental_session.rb +117 -26
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/graph.rb +3 -5
- data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
- data/lib/rigor/analysis/reachability/project_files.rb +2 -2
- data/lib/rigor/analysis/reachability/scan.rb +5 -5
- data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
- data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
- data/lib/rigor/analysis/result.rb +1 -3
- data/lib/rigor/analysis/rule_catalog.rb +131 -1
- data/lib/rigor/analysis/run_cache_key.rb +21 -12
- data/lib/rigor/analysis/run_cache_probe.rb +3 -5
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
- data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
- data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
- data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +407 -51
- 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 +62 -20
- data/lib/rigor/bleeding_edge.rb +10 -24
- data/lib/rigor/builtins/hkt_builtins.rb +3 -2
- data/lib/rigor/builtins/imported_refinements.rb +159 -21
- data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
- data/lib/rigor/builtins/regex_refinement.rb +21 -13
- data/lib/rigor/builtins/static_return_refinements.rb +7 -6
- data/lib/rigor/cache/annotation_location.rb +2 -4
- data/lib/rigor/cache/descriptor.rb +63 -20
- data/lib/rigor/cache/engine_source.rb +33 -5
- data/lib/rigor/cache/file_digest.rb +9 -1
- data/lib/rigor/cache/incremental_snapshot.rb +72 -6
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
- data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
- data/lib/rigor/cache/rbs_constant_table.rb +0 -3
- data/lib/rigor/cache/rbs_descriptor.rb +112 -14
- data/lib/rigor/cache/rbs_environment.rb +8 -4
- data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +76 -32
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/annotate_command.rb +5 -6
- data/lib/rigor/cli/check_command.rb +57 -10
- data/lib/rigor/cli/check_invocation.rb +6 -11
- data/lib/rigor/cli/check_runner_factory.rb +1 -5
- data/lib/rigor/cli/coverage_command.rb +1 -1
- data/lib/rigor/cli/coverage_mutation.rb +12 -3
- data/lib/rigor/cli/coverage_scan.rb +1 -5
- data/lib/rigor/cli/diff_command.rb +1 -1
- data/lib/rigor/cli/doc_links.rb +4 -4
- data/lib/rigor/cli/docs_command.rb +6 -6
- data/lib/rigor/cli/doctor_command.rb +85 -38
- data/lib/rigor/cli/effects_command.rb +2 -2
- data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
- data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
- data/lib/rigor/cli/explain_command.rb +34 -1
- data/lib/rigor/cli/fused_protection_report.rb +7 -1
- data/lib/rigor/cli/lsp_command.rb +1 -1
- data/lib/rigor/cli/mcp_command.rb +1 -1
- data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
- data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
- data/lib/rigor/cli/mutation_protection_report.rb +7 -1
- data/lib/rigor/cli/plugin_command.rb +4 -4
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/prism_colorizer.rb +1 -2
- data/lib/rigor/cli/protection_fork_scan.rb +6 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
- data/lib/rigor/cli/sig_gen_command.rb +212 -31
- data/lib/rigor/cli/skill_command.rb +2 -2
- data/lib/rigor/cli/skill_deep_probe.rb +4 -4
- data/lib/rigor/cli/skill_describe.rb +35 -35
- data/lib/rigor/cli/trace_command.rb +4 -4
- data/lib/rigor/cli/trace_renderer.rb +5 -6
- data/lib/rigor/cli/triage_command.rb +1 -1
- data/lib/rigor/cli/type_of_command.rb +29 -11
- 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/type_scan_command.rb +4 -4
- data/lib/rigor/cli/unused_command.rb +11 -3
- data/lib/rigor/cli/upgrade_command.rb +1 -1
- data/lib/rigor/cli.rb +89 -9
- data/lib/rigor/config_audit.rb +30 -5
- data/lib/rigor/configuration/severity_profile.rb +25 -9
- data/lib/rigor/configuration.rb +109 -7
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +12 -5
- 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 +15 -10
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/definition_lines.rb +25 -6
- data/lib/rigor/effects/effect_table.rb +11 -4
- data/lib/rigor/effects/entry_points.rb +0 -2
- data/lib/rigor/effects/envelope_check.rb +9 -9
- data/lib/rigor/effects/envelope_index.rb +20 -8
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +5 -7
- data/lib/rigor/effects/identity.rb +20 -6
- data/lib/rigor/effects/inline_anchor.rb +7 -7
- data/lib/rigor/effects/label_intent.rb +3 -4
- data/lib/rigor/effects/liskov_check.rb +8 -8
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +22 -1
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +47 -37
- data/lib/rigor/effects/propagator.rb +297 -19
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +122 -73
- data/lib/rigor/effects/signature_sources.rb +4 -6
- data/lib/rigor/effects/snapshot.rb +12 -11
- data/lib/rigor/effects/snapshot_diff.rb +1 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +393 -38
- data/lib/rigor/effects/unknown_label_check.rb +3 -8
- data/lib/rigor/effects/unknown_label_report.rb +3 -4
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
- data/lib/rigor/environment/class_registry.rb +3 -1
- data/lib/rigor/environment/failure_slot.rb +2 -2
- data/lib/rigor/environment/installed_gem_set.rb +85 -0
- data/lib/rigor/environment/lockfile_resolver.rb +68 -4
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
- data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
- data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
- data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
- data/lib/rigor/environment/rbs_loader.rb +674 -79
- data/lib/rigor/environment.rb +174 -24
- data/lib/rigor/flow_contribution/merger.rb +0 -2
- data/lib/rigor/flow_contribution.rb +11 -13
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +292 -17
- 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 +75 -30
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +7 -6
- data/lib/rigor/inference/budget_trace.rb +3 -6
- 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 +389 -18
- data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/coverage_scanner.rb +4 -6
- 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/dynamic_origin.rb +1 -1
- data/lib/rigor/inference/element_read_widening.rb +180 -0
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +2124 -468
- data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
- data/lib/rigor/inference/fork_map.rb +5 -7
- 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/hkt_reducer.rb +2 -3
- data/lib/rigor/inference/hkt_registry.rb +4 -7
- data/lib/rigor/inference/index_write_widening.rb +16 -7
- 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 +168 -21
- 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 +87 -33
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
- data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
- 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/random_folding.rb +82 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +225 -25
- data/lib/rigor/inference/method_parameter_binder.rb +12 -9
- data/lib/rigor/inference/multi_target_binder.rb +341 -55
- data/lib/rigor/inference/mutation_rejoin.rb +171 -0
- data/lib/rigor/inference/mutation_widening.rb +156 -85
- data/lib/rigor/inference/narrowing.rb +835 -162
- 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 +153 -16
- data/lib/rigor/inference/origin_lookup.rb +2 -3
- data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
- data/lib/rigor/inference/pre_eval_constants.rb +6 -5
- data/lib/rigor/inference/precision_scanner.rb +3 -4
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +9 -4
- data/lib/rigor/inference/project_patched_scanner.rb +10 -6
- data/lib/rigor/inference/protection_scanner.rb +1 -2
- data/lib/rigor/inference/range_constant.rb +57 -0
- data/lib/rigor/inference/rbs_type_translator.rb +49 -11
- data/lib/rigor/inference/receiver_alias.rb +93 -4
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +76 -0
- 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 +5228 -627
- data/lib/rigor/inference/statement_evaluator.rb +3452 -595
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +97 -0
- data/lib/rigor/inference/struct_fold_safety.rb +6 -7
- data/lib/rigor/inference/synthetic_method_index.rb +1 -2
- data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/inference/version_guard.rb +28 -21
- data/lib/rigor/inference/void_origin.rb +3 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -4
- data/lib/rigor/language_server/buffer_table.rb +4 -4
- data/lib/rigor/language_server/completion_provider.rb +1 -1
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -1
- data/lib/rigor/language_server/hover_provider.rb +1 -1
- data/lib/rigor/language_server/hover_renderer.rb +4 -4
- data/lib/rigor/language_server/incremental_sync.rb +6 -6
- data/lib/rigor/language_server/project_context.rb +7 -8
- data/lib/rigor/language_server/publish_batcher.rb +2 -2
- data/lib/rigor/language_server/selection_range_provider.rb +2 -2
- data/lib/rigor/language_server/server.rb +9 -9
- data/lib/rigor/language_server/signature_help_provider.rb +1 -1
- data/lib/rigor/language_server/uri.rb +1 -1
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +258 -26
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +167 -0
- data/lib/rigor/plugin/effect_attribution.rb +65 -11
- data/lib/rigor/plugin/effect_entry_points.rb +3 -3
- data/lib/rigor/plugin/fact_store.rb +6 -6
- data/lib/rigor/plugin/io_boundary.rb +93 -8
- data/lib/rigor/plugin/isolation.rb +29 -6
- data/lib/rigor/plugin/loader.rb +33 -13
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
- data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
- data/lib/rigor/plugin/manifest.rb +94 -11
- data/lib/rigor/plugin/registry.rb +76 -12
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -4
- data/lib/rigor/plugin/type_node_resolver.rb +3 -3
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/plugin_gap_advisory.rb +96 -0
- data/lib/rigor/project_environment.rb +138 -0
- data/lib/rigor/protection/analysis_guard.rb +93 -14
- data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
- data/lib/rigor/protection/dependency_closure.rb +5 -8
- data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
- data/lib/rigor/protection/discovery_seed.rb +14 -12
- data/lib/rigor/protection/kill_signature.rb +1 -4
- data/lib/rigor/protection/measurement_integrity.rb +1 -3
- data/lib/rigor/protection/mutation_cache.rb +7 -11
- data/lib/rigor/protection/mutation_scanner.rb +12 -15
- data/lib/rigor/protection/mutator.rb +2 -1
- data/lib/rigor/protection/test_suite_oracle.rb +5 -5
- data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/reporter.rb +36 -10
- data/lib/rigor/rbs_extended.rb +88 -21
- data/lib/rigor/reflection/constant_ancestors.rb +97 -0
- data/lib/rigor/reflection/constant_path.rb +139 -0
- data/lib/rigor/reflection.rb +93 -110
- data/lib/rigor/runtime/jit.rb +6 -8
- data/lib/rigor/scope/discovery_index.rb +165 -2
- data/lib/rigor/scope.rb +1041 -32
- 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 +673 -53
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/layout_index.rb +3 -4
- data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +18 -16
- data/lib/rigor/sig_gen/path_mapper.rb +4 -6
- data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
- data/lib/rigor/sig_gen/renderer.rb +128 -14
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
- data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
- data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +189 -41
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +153 -6
- data/lib/rigor/source/literals.rb +0 -23
- data/lib/rigor/source/node_children.rb +0 -2
- data/lib/rigor/source/node_locator.rb +5 -11
- data/lib/rigor/source/node_walker.rb +0 -6
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/triage/catalogue.rb +1 -3
- data/lib/rigor/triage.rb +3 -5
- data/lib/rigor/type/accepts_result.rb +24 -6
- data/lib/rigor/type/combinator.rb +144 -5
- data/lib/rigor/type/data_class.rb +2 -2
- data/lib/rigor/type/data_instance.rb +4 -4
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/float_range.rb +128 -0
- data/lib/rigor/type/hash_shape.rb +6 -6
- data/lib/rigor/type/integer_range.rb +13 -8
- data/lib/rigor/type/nominal.rb +8 -2
- data/lib/rigor/type/refined.rb +4 -3
- data/lib/rigor/type/struct_class.rb +3 -3
- data/lib/rigor/type/struct_instance.rb +4 -4
- data/lib/rigor/type.rb +1 -0
- data/lib/rigor/type_node/generic.rb +1 -1
- data/lib/rigor/type_node/range_literal.rb +25 -0
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
- 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 +264 -3
- data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
- 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/analyzer.rb +0 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -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 +383 -7
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
- data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -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/type_scanner.rb +8 -6
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
- data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
- data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
- 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 +324 -18
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
- data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -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/analysis/reachability/scan_cache.rbs +12 -0
- data/sig/rigor/cache.rbs +2 -3
- 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 +17 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +9 -14
- 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 +4 -0
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +51 -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 +9 -6
- data/sig/rigor/scope.rbs +148 -12
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +33 -1
- data/sig/rigor.rbs +39 -20
- data/skills/rigor-ask/SKILL.md +16 -11
- 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 +25 -27
- 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 +15 -10
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +43 -14
- 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-project-init/references/06-agent-contract.md +67 -0
- 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 +226 -0
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
- data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +133 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
|
@@ -48,7 +48,17 @@ module Rigor
|
|
|
48
48
|
# added to a schema-less project) invalidates the warm entry. A pre-8 entry carries no absence rows
|
|
49
49
|
# and would validate fresh across exactly that edit, so cached entries must read as misses once and
|
|
50
50
|
# rebuild carrying the rows.
|
|
51
|
-
|
|
51
|
+
# v9: #979 — the run-result dependency descriptor now carries a names-only {GlobEntry} directory
|
|
52
|
+
# listing per RBS signature root, so a `.rbs` file APPEARING under one (a `sig/roles.rbs` declaring the
|
|
53
|
+
# interface a `conforms-to` names) invalidates the warm entry. A pre-9 entry carries no signature-root
|
|
54
|
+
# row and would validate fresh across exactly that edit — the #577 reasoning, one slot over — so cached
|
|
55
|
+
# entries must read as misses once and rebuild carrying the rows.
|
|
56
|
+
# v10: #1123 — the def-index seed bundles gain the `:prepends` table, the instance-ancestor-ORDER half
|
|
57
|
+
# of the `include` table (`prepend M`, and `Recv.prepend(M)`), which `Scope#user_def_through_ancestors`
|
|
58
|
+
# searches ahead of a class's own `def`s. A pre-10 bundle would silently contribute no prepends for an
|
|
59
|
+
# unchanged file, so that file's consumers would keep answering with the pre-fix MRO — cached bundles
|
|
60
|
+
# must read as misses once and rebuild carrying the slot.
|
|
61
|
+
SCHEMA_VERSION = 10
|
|
52
62
|
|
|
53
63
|
# Per-slot entry value objects. Constructors validate enums / required fields and freeze the resulting
|
|
54
64
|
# struct so no caller can mutate after the entry is in a Descriptor.
|
|
@@ -114,7 +124,7 @@ module Rigor
|
|
|
114
124
|
new(path: path, comparator: :exists, value: PRESENT)
|
|
115
125
|
end
|
|
116
126
|
|
|
117
|
-
# @return
|
|
127
|
+
# @return whether this row records the path as absent (see {.absent}).
|
|
118
128
|
def absent?
|
|
119
129
|
comparator == :exists && value == ABSENT
|
|
120
130
|
end
|
|
@@ -235,31 +245,58 @@ module Rigor
|
|
|
235
245
|
FIELD_SEPARATOR = "\0"
|
|
236
246
|
private_constant :ROW_SEPARATOR, :FIELD_SEPARATOR
|
|
237
247
|
|
|
248
|
+
# `:stat` is the ADR-87 WD2 signature above — it answers "did anything under this glob change",
|
|
249
|
+
# appearance and edit alike. `:names` (#979) answers only "did the SET of matching paths change":
|
|
250
|
+
# its rows are the sorted relative names, so a file whose bytes are unchanged never moves the
|
|
251
|
+
# signature however its stat tuple moved. A row exists to catch appearance/disappearance only —
|
|
252
|
+
# edits to the files it lists are already carried by their own `:stat` {FileEntry} rows — and a
|
|
253
|
+
# names row must therefore survive what those rows survive. A `:stat` glob over a signature tree
|
|
254
|
+
# would not: ADR-87 WD1 lets a `:stat` file row fall back to its recorded content digest when the
|
|
255
|
+
# tuple moves, so a `git checkout`, a `bundle install` or a CI cache restored over a fresh checkout
|
|
256
|
+
# keeps the file rows fresh while it would move every glob signature, turning every such run into a
|
|
257
|
+
# full re-analysis. `:names` also reads no stat at all, so it costs a `Dir.glob` and nothing else.
|
|
258
|
+
VALID_MODES = %i[stat names].freeze
|
|
259
|
+
|
|
238
260
|
attr_reader :root, :pattern, :value
|
|
239
261
|
|
|
240
|
-
value_fields :root, :pattern, :value
|
|
262
|
+
value_fields :root, :pattern, :mode, :value
|
|
263
|
+
|
|
264
|
+
def initialize(root:, pattern:, value:, mode: :stat)
|
|
265
|
+
raise ArgumentError, "GlobEntry mode must be one of #{VALID_MODES.inspect}, got #{mode.inspect}" \
|
|
266
|
+
unless VALID_MODES.include?(mode)
|
|
241
267
|
|
|
242
|
-
def initialize(root:, pattern:, value:)
|
|
243
268
|
@root = root.to_s.dup.freeze
|
|
244
269
|
@pattern = pattern.to_s.dup.freeze
|
|
270
|
+
@mode = mode
|
|
245
271
|
@value = value.to_s.dup.freeze
|
|
246
272
|
freeze
|
|
247
273
|
end
|
|
248
274
|
|
|
275
|
+
# Defaulted rather than an `attr_reader` because an entry Marshal-loaded from a store written before
|
|
276
|
+
# the field existed carries no `@mode` ivar; every such entry was recorded under the stat signature.
|
|
277
|
+
def mode
|
|
278
|
+
@mode || :stat
|
|
279
|
+
end
|
|
280
|
+
|
|
249
281
|
# Builds the entry for the glob's CURRENT filesystem state.
|
|
250
|
-
def self.compute(root:, pattern:)
|
|
251
|
-
new(root: root, pattern: pattern,
|
|
282
|
+
def self.compute(root:, pattern:, mode: :stat)
|
|
283
|
+
new(root: root, pattern: pattern, mode: mode,
|
|
284
|
+
value: signature_for(root: root, pattern: pattern, mode: mode))
|
|
252
285
|
end
|
|
253
286
|
|
|
254
287
|
# The aggregate signature the entry's `value` carries: SHA-256 over the sorted per-file rows. In the
|
|
255
288
|
# default (`:stat`) mode a row is the file's `(path, size, mtime_ns, ctime_ns, inode)` tuple — NO
|
|
256
289
|
# content read; in strict mode a row is `(path, content-sha256)`, restoring the pre-ADR-87 authority.
|
|
290
|
+
# In `:names` mode a row is the path alone, stat-free, so only the matching SET moves the signature.
|
|
257
291
|
# Per-file stat failures (a file vanishing between the glob and the stat) drop the row — same race
|
|
258
292
|
# posture as {Descriptor#file_entry_fresh?}. `Dir.glob` returns sorted entries by default so the row
|
|
259
293
|
# order — and therefore the signature — is stable.
|
|
260
|
-
def self.signature_for(root:, pattern:)
|
|
294
|
+
def self.signature_for(root:, pattern:, mode: :stat)
|
|
295
|
+
paths = Dir.glob(File.join(root, pattern))
|
|
296
|
+
return Digest::SHA256.hexdigest(paths.map { |path| "#{path}#{ROW_SEPARATOR}" }.join) if mode == :names
|
|
297
|
+
|
|
261
298
|
strict = FileDigest.strict_validation?
|
|
262
|
-
rows =
|
|
299
|
+
rows = paths.filter_map do |path|
|
|
263
300
|
st = File.stat(path)
|
|
264
301
|
next nil unless st.file?
|
|
265
302
|
|
|
@@ -276,23 +313,30 @@ module Rigor
|
|
|
276
313
|
end
|
|
277
314
|
|
|
278
315
|
# ADR-87 WD2 — fresh iff re-globbing + re-stat-ing reproduces the recorded signature. Zero file-content
|
|
279
|
-
# bytes are read in the default mode
|
|
280
|
-
# signature recorded under the opposite validation mode simply
|
|
316
|
+
# bytes are read in the default mode, and no stat at all in `:names`. Any failure reads as stale
|
|
317
|
+
# (recompute), never a crash. A stored signature recorded under the opposite validation mode simply
|
|
318
|
+
# mismatches and recomputes.
|
|
281
319
|
def self.fresh?(entry)
|
|
282
|
-
signature_for(root: entry.root, pattern: entry.pattern) == entry.value
|
|
320
|
+
signature_for(root: entry.root, pattern: entry.pattern, mode: entry.mode) == entry.value
|
|
283
321
|
rescue StandardError
|
|
284
322
|
false
|
|
285
323
|
end
|
|
286
324
|
|
|
287
|
-
# Composition key — {.compose} unions per (root, pattern) slot; two contributions for the same
|
|
288
|
-
# must agree on the value or {Conflict} is raised. Within one run the same glob stat-reads
|
|
289
|
-
# so contributions never conflict.
|
|
325
|
+
# Composition key — {.compose} unions per (root, pattern, mode) slot; two contributions for the same
|
|
326
|
+
# slot must agree on the value or {Conflict} is raised. Within one run the same glob stat-reads
|
|
327
|
+
# identically, so contributions never conflict. The mode is part of the key because the two signatures
|
|
328
|
+
# over one (root, pattern) are different questions, not rival answers to the same one.
|
|
290
329
|
def slot_key
|
|
291
|
-
"#{root}\0#{pattern}"
|
|
330
|
+
"#{root}\0#{pattern}\0#{mode}"
|
|
292
331
|
end
|
|
293
332
|
|
|
294
333
|
def to_h
|
|
295
|
-
{ "root" => root, "pattern" => pattern, "value" => value }
|
|
334
|
+
h = { "root" => root, "pattern" => pattern, "value" => value }
|
|
335
|
+
# Omitted in the default mode so a descriptor carrying only stat globs keeps its pre-#979 canonical
|
|
336
|
+
# bytes: this FIELD moves no producer's key. (Every key still moved once with SCHEMA_VERSION 9,
|
|
337
|
+
# which the storage layer mixes in; that is the #979 migration, not the mode.)
|
|
338
|
+
h["mode"] = mode.to_s unless mode == :stat
|
|
339
|
+
h
|
|
296
340
|
end
|
|
297
341
|
end
|
|
298
342
|
|
|
@@ -352,9 +396,8 @@ module Rigor
|
|
|
352
396
|
dependencies: dependencies, globs: globs)
|
|
353
397
|
end
|
|
354
398
|
|
|
355
|
-
# @param
|
|
356
|
-
# @
|
|
357
|
-
# @return [String] hex SHA-256 cache key for the value
|
|
399
|
+
# @param params — inputs the producer was called with
|
|
400
|
+
# @return hex SHA-256 cache key for the value
|
|
358
401
|
def cache_key_for(producer_id:, params: {})
|
|
359
402
|
payload = {
|
|
360
403
|
"schema_version" => SCHEMA_VERSION,
|
|
@@ -377,7 +420,7 @@ module Rigor
|
|
|
377
420
|
"dependencies" => sort_entries(dependencies, "gem_name").map(&:to_h),
|
|
378
421
|
"files" => sort_entries(files, "path").map(&:to_h),
|
|
379
422
|
"gems" => sort_entries(gems, "name").map(&:to_h),
|
|
380
|
-
"globs" => globs.sort_by { |e| [e.root, e.pattern] }.map(&:to_h),
|
|
423
|
+
"globs" => globs.sort_by { |e| [e.root, e.pattern, e.mode.to_s] }.map(&:to_h),
|
|
381
424
|
"plugins" => sort_entries(plugins, "id").map(&:to_h)
|
|
382
425
|
}
|
|
383
426
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "digest"
|
|
4
4
|
|
|
5
5
|
require_relative "../version"
|
|
6
|
+
require_relative "descriptor"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Cache
|
|
@@ -63,17 +64,20 @@ module Rigor
|
|
|
63
64
|
# to whatever else happened to be there, which is exactly the weakening this module forbids.
|
|
64
65
|
REQUIRED_DIRECTORY = "lib"
|
|
65
66
|
|
|
67
|
+
# The config-row key every computed-value slot carries the identity under.
|
|
68
|
+
CONFIG_KEY = "engine-source"
|
|
69
|
+
|
|
66
70
|
module_function
|
|
67
71
|
|
|
68
|
-
# @return
|
|
72
|
+
# @return the gem root — the directory holding `lib/`, three levels above this file.
|
|
69
73
|
def root
|
|
70
74
|
@root ||= File.expand_path("../../..", __dir__)
|
|
71
75
|
end
|
|
72
76
|
|
|
73
|
-
# @param root
|
|
74
|
-
# @return
|
|
77
|
+
# @param root — the gem root, defaulted through {.root} so a spec can relocate the tree.
|
|
78
|
+
# @return a digest identifying the engine's current source, or nil when the tree is
|
|
75
79
|
# version-pinned and the caller should add no slot at all.
|
|
76
|
-
# @raise
|
|
80
|
+
# @raise Unavailable — when a mutable tree's source cannot be read.
|
|
77
81
|
def identity(root = self.root)
|
|
78
82
|
return nil if version_pinned?(root)
|
|
79
83
|
|
|
@@ -100,10 +104,34 @@ module Rigor
|
|
|
100
104
|
# exists at all. The same reading covers the long-running `rigor lsp` process.
|
|
101
105
|
#
|
|
102
106
|
# {Unavailable} propagates and is deliberately NOT memoised: the ivar is only assigned on success.
|
|
107
|
+
#
|
|
108
|
+
# The memo is FROZEN because a Ractor-pool worker reads it (#1055): the auto-wired ADR-93
|
|
109
|
+
# `rigor-rbs-inline` synthesizer reaches `.key_config_entries` from inside
|
|
110
|
+
# `Environment.for_project`, which is inside `WorkerSession#initialize`, which is inside the worker's
|
|
111
|
+
# own Ractor — and a non-main Ractor may read a class/module ivar only when its value is shareable.
|
|
112
|
+
# An unfrozen digest String therefore killed every worker in its constructor on any run with the
|
|
113
|
+
# synthesizer on, which is every real CLI run (the spec suite pins it off). The worker never WRITES
|
|
114
|
+
# it: `PoolCoordinator#analyze_files_in_pool` pre-warms this on the main Ractor first, which is where
|
|
115
|
+
# the argument above already says the value belongs.
|
|
103
116
|
def process_identity
|
|
104
117
|
return @process_identity if defined?(@process_identity)
|
|
105
118
|
|
|
106
|
-
@process_identity = identity
|
|
119
|
+
@process_identity = identity.freeze
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# The `engine-source` key row for a cache whose value this engine computed, built from
|
|
123
|
+
# {.process_identity}: empty for a version-pinned tree, so a released gem's keys stay byte-identical.
|
|
124
|
+
#
|
|
125
|
+
# Issue #1009 — a slot keyed only on its inputs and a plugin's manifest version outlives the engine
|
|
126
|
+
# that filled it. The per-file synthesizer slot and every plugin producer were keyed that way, so after
|
|
127
|
+
# an engine or bundled-plugin edit the run-result key moved and the run re-analysed, but through the
|
|
128
|
+
# previous build's synthesized RBS and producer values. {Unavailable} propagates, so a caller that
|
|
129
|
+
# cannot identify the engine bypasses its cache instead of falling back to the weaker key.
|
|
130
|
+
def key_config_entries
|
|
131
|
+
identity = process_identity
|
|
132
|
+
return [] if identity.nil?
|
|
133
|
+
|
|
134
|
+
[Descriptor::ConfigEntry.new(key: CONFIG_KEY, value_hash: Digest::SHA256.hexdigest(identity))]
|
|
107
135
|
end
|
|
108
136
|
|
|
109
137
|
# Discards the {.process_identity} memo; production code MUST NOT call this — a run that recomputed
|
|
@@ -74,7 +74,7 @@ module Rigor
|
|
|
74
74
|
memo[path] ||= Digest::SHA256.file(path).hexdigest
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
# @return
|
|
77
|
+
# @return whether digest-always validation is forced for this run. The env var wins over the
|
|
78
78
|
# run-scoped config flag so an operator can bypass the stat tier without editing `.rigor.yml`.
|
|
79
79
|
def self.strict_validation?
|
|
80
80
|
return true if ENV[STRICT_ENV] == "1"
|
|
@@ -112,6 +112,14 @@ module Rigor
|
|
|
112
112
|
hexdigest(path) == digest
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
+
# The content-digest field of a packed `:stat` entry ({.pack_stat}); nil when the entry is absent or not
|
|
116
|
+
# well-formed. Exposed for the caller that must compare the recorded digest against bytes it hashes
|
|
117
|
+
# itself rather than against the file on disk — the incremental session's editor-mode freshness check,
|
|
118
|
+
# whose authority is the editor's buffer.
|
|
119
|
+
def self.content_digest(packed)
|
|
120
|
+
parse_stat(packed)&.first
|
|
121
|
+
end
|
|
122
|
+
|
|
115
123
|
# The VALIDATION-side stat, served from the per-run table when one is installed — a collecting run
|
|
116
124
|
# validates the effects entry and the diagnostics entry against the same ~thousands-of-files
|
|
117
125
|
# dependency descriptor, and the second pass is pure repetition under the run's own stable-filesystem
|
|
@@ -84,7 +84,61 @@ module Rigor
|
|
|
84
84
|
# `[]`, deserialises cleanly, and would send every unchanged file's top-level helper back to the peel
|
|
85
85
|
# on a warm run while a cold run resolved at the top level — the `--verify-incremental` divergence 14
|
|
86
86
|
# was bumped for, in the same table.
|
|
87
|
-
|
|
87
|
+
# 18: issue #728 re-keys each seed bundle's `header_nestings` VALUE from one chain per class to one
|
|
88
|
+
# chain per ancestor NAME the class's sites wrote, plus an unkeyed chain holding the old union. A
|
|
89
|
+
# pre-18 blob's Array value is not a Hash and the resolver's per-name lookup would raise on it, so the
|
|
90
|
+
# gate has to reject it — and even a reader that tolerated the old shape would serve the per-class
|
|
91
|
+
# union for every unchanged file, which is the answer this issue exists to stop giving.
|
|
92
|
+
# 19: issue #668 re-keys a constant write through a base no name reaches — `k::LIMIT = 7` — from the
|
|
93
|
+
# bare last segment to the wildcard `*::LIMIT`, in `constant_decls` and in each seed bundle's
|
|
94
|
+
# `constant_writes` census alike. A pre-19 blob's `LIMIT` key deserialises cleanly and reads as an
|
|
95
|
+
# ordinary top-level write, so every unchanged file would keep publishing the `Foo::LIMIT` the write
|
|
96
|
+
# may already have replaced while a cold run made it gradual — the `--verify-incremental` divergence
|
|
97
|
+
# 14 was bumped for.
|
|
98
|
+
# 20: issue #722 residue 2 adds each seed bundle's compact-header re-anchor census, without which a
|
|
99
|
+
# warm fold sees no candidate for an unchanged file and keeps serving the pre-fix `Wrap::Outer::Leaf`
|
|
100
|
+
# for a `class Outer::Leaf` that reopens `::Outer::Leaf`.
|
|
101
|
+
# 21: issue #915 widens the seed bundle's `extends` table to a singleton-body `include` / `prepend`;
|
|
102
|
+
# a pre-21 bundle for an unchanged file would keep the narrower record and still report the
|
|
103
|
+
# `case Widget when M` arm unreachable.
|
|
104
|
+
# 22: issues #796 / #794 add `run_level_rows` — the cold run's `definition-build-failed` set and its
|
|
105
|
+
# HKT-scan outcome, the two rows a narrowed run cannot re-derive from the files it analyses. A pre-22
|
|
106
|
+
# blob has no such section and would deserialise it as nil, which reads as "nothing cached" and is
|
|
107
|
+
# therefore not misread — but a snapshot written by an engine that did not yet REPLAY them was also
|
|
108
|
+
# written by one whose narrowed runs under-reported, so the gate rejects it and the next run is cold.
|
|
109
|
+
# 23: issue #992 gives each seed bundle a `parameter_envelopes` table — the joined positional envelope
|
|
110
|
+
# of every method a file records, plus its module / dynamic-surface marks — which `call.wrong-arity`
|
|
111
|
+
# reads for a method no signature declares. A pre-23 bundle folds as "no envelopes", which only ever
|
|
112
|
+
# withholds a check, but a warm run that withholds where a cold run fires is still the
|
|
113
|
+
# `--verify-incremental` divergence 14 was bumped for.
|
|
114
|
+
# 24: issue #1097 gives each seed bundle a `deferred_ranges` table — the per-file def / block /
|
|
115
|
+
# lambda body ranges `Scope#*_def_shadows_call?` orders a project-defined `sig` override
|
|
116
|
+
# against. A pre-24 bundle would fold as "no ranges", which the predicate reads as "cannot
|
|
117
|
+
# order → shadow" — a warm run declining the binding where a cold run binds.
|
|
118
|
+
# 25: issue #1097 extends each `deferred_ranges` row to `[start, end, name, kind, owner]` —
|
|
119
|
+
# owner-scoped ordering. A 24 bundle folds as "owner = nil", which the predicate reads as
|
|
120
|
+
# "cannot order", under-shadowing `module_function` defs whose only table evidence is the row
|
|
121
|
+
# itself.
|
|
122
|
+
# 26: issue #1123 gives each seed bundle a `prepends` table — the instance-ancestor ORDER of a
|
|
123
|
+
# class's `prepend`ed modules, which `Scope#user_def_through_ancestors` searches ahead of the
|
|
124
|
+
# class's own `def`s. A pre-26 bundle would fold as "prepends nothing": the warm run would answer
|
|
125
|
+
# the pre-fix MRO where a cold run answers the prepended module, exactly the `--verify-incremental`
|
|
126
|
+
# divergence 14 was bumped for (and a silently WRONG dispatch answer, not a withheld check).
|
|
127
|
+
# 27: issue #1173 re-MEANs each seed bundle's `includes` VALUES without changing their shape: the
|
|
128
|
+
# lists now store instance-ancestor SEARCH order (nearest first, prepends ahead of includes)
|
|
129
|
+
# instead of call order — the same flip 17 made for def-row `nesting`. A pre-27 blob deserialises
|
|
130
|
+
# cleanly and would serve the old call order on a warm run while a cold run searches nearer-first:
|
|
131
|
+
# `include A; include B` would resolve A's methods where a cold run resolves B's — the
|
|
132
|
+
# `--verify-incremental` divergence 14 was bumped for.
|
|
133
|
+
# 28: issue #1120 gives each seed bundle a `refinements` table — the `def`s of every `refine X do … end`
|
|
134
|
+
# body, which `call.undefined-method` reads where a `using` of the refining module is in effect. A
|
|
135
|
+
# pre-28 bundle would fold as "refines nothing", and a warm run would report a refined call a cold run
|
|
136
|
+
# declines.
|
|
137
|
+
# 29: issue #1367 gives each seed bundle a `global_write_census` — the globals its `alias` statements name and
|
|
138
|
+
# the `write` / `to_str` / `to_int` / hatch definitions and top-level mixins it holds, which the `global.*`
|
|
139
|
+
# write rules decline on project-wide. A pre-29 bundle would fold as "none of those", and a warm run would
|
|
140
|
+
# report a write a cold run exempts.
|
|
141
|
+
SCHEMA = 29
|
|
88
142
|
|
|
89
143
|
# The persisted per-file state.
|
|
90
144
|
# `cache` maps an analyzed file to its diagnostics.
|
|
@@ -136,11 +190,21 @@ module Rigor
|
|
|
136
190
|
# collection was off). It is a SEPARATE gate from the global `fingerprint`: the `effects:` block is
|
|
137
191
|
# deliberately absent from `Configuration#to_h`, so turning collection on invalidates no diagnostics,
|
|
138
192
|
# and a vocabulary / catalogue / `effects:` change must invalidate the summaries alone.
|
|
193
|
+
# Issues #796 / #794 — the run-level rows a narrowed run replays instead of re-deriving; see
|
|
194
|
+
# docs/internal-spec/cache.md § "Run-level rows the snapshot carries" for why exactly these two are
|
|
195
|
+
# fresh under the fingerprint and why no other `.rigor.yml`-level row may join them.
|
|
139
196
|
Payload = Data.define(:cache, :sources, :digests, :analyzed,
|
|
140
197
|
:symbol_sources, :ancestry_sources, :symbol_fingerprints,
|
|
141
198
|
:missing, :class_decls, :constant_decls, :seed_bundles, :plugin_fact_digest,
|
|
142
199
|
:return_summaries, :param_table,
|
|
143
|
-
:effect_collections, :effects_identity)
|
|
200
|
+
:effect_collections, :effects_identity, :run_level_rows)
|
|
201
|
+
|
|
202
|
+
# Issues #796 / #794 — the two run-level rows the snapshot carries. `definition_build_failures` is the
|
|
203
|
+
# reported per-class detail list ({Environment::RbsLoader#definition_build_failures}); `hkt_scan_failure`
|
|
204
|
+
# is the `[error_class, first_line, frame, stage]` tuple ({Rigor::Environment#hkt_scan_failure}), nil
|
|
205
|
+
# when the scan succeeded — which is why the presence of this object, not the tuple, is what says a
|
|
206
|
+
# replay is available.
|
|
207
|
+
RunLevelRows = Data.define(:definition_build_failures, :hkt_scan_failure)
|
|
144
208
|
|
|
145
209
|
# The global fingerprint that gates a snapshot load: a digest of the inputs whose change requires a full
|
|
146
210
|
# rebuild — the engine version + schema, the engine's own SOURCE when the version does not pin it, the
|
|
@@ -222,8 +286,8 @@ module Rigor
|
|
|
222
286
|
# The fingerprint that matched is returned alongside the payload so the caller can mix it into ITS own
|
|
223
287
|
# cache key — the snapshot's identity is exactly what "these dependency edges came from that world" means.
|
|
224
288
|
#
|
|
225
|
-
# @param fingerprints
|
|
226
|
-
# @return
|
|
289
|
+
# @param fingerprints — candidates, most-specific first.
|
|
290
|
+
# @return `[matched fingerprint, payload]`, or nil on any miss.
|
|
227
291
|
def load_any(fingerprints:)
|
|
228
292
|
data = read_data
|
|
229
293
|
return nil if data.nil?
|
|
@@ -259,7 +323,8 @@ module Rigor
|
|
|
259
323
|
return_summaries: data[:return_summaries] || {},
|
|
260
324
|
param_table: data[:param_table] || {},
|
|
261
325
|
effect_collections: data[:effect_collections] || {},
|
|
262
|
-
effects_identity: data[:effects_identity]
|
|
326
|
+
effects_identity: data[:effects_identity],
|
|
327
|
+
run_level_rows: data[:run_level_rows]
|
|
263
328
|
)
|
|
264
329
|
end
|
|
265
330
|
private :payload_from
|
|
@@ -283,7 +348,8 @@ module Rigor
|
|
|
283
348
|
return_summaries: payload.return_summaries,
|
|
284
349
|
param_table: payload.param_table,
|
|
285
350
|
effect_collections: payload.effect_collections,
|
|
286
|
-
effects_identity: payload.effects_identity
|
|
351
|
+
effects_identity: payload.effects_identity,
|
|
352
|
+
run_level_rows: payload.run_level_rows
|
|
287
353
|
)
|
|
288
354
|
blob = Zlib::Deflate.deflate(raw)
|
|
289
355
|
tmp = "#{@path}.#{Process.pid}.tmp"
|
|
@@ -29,6 +29,10 @@ module Rigor
|
|
|
29
29
|
# files, same libraries), so the loader memoises one build per process instead of re-digesting every
|
|
30
30
|
# .rbs file once per producer.
|
|
31
31
|
descriptor = loader.rbs_cache_descriptor
|
|
32
|
+
# Issue #1014 — nil is an engine the descriptor could not identify ({EngineSource::Unavailable}).
|
|
33
|
+
# Compute uncached rather than keying the value without the engine that produced it.
|
|
34
|
+
return compute(loader) if descriptor.nil?
|
|
35
|
+
|
|
32
36
|
store.fetch_or_compute(producer_id: self::PRODUCER_ID, params: {}, descriptor: descriptor,
|
|
33
37
|
generation_cap: generation_cap) do
|
|
34
38
|
compute(loader)
|
|
@@ -20,9 +20,6 @@ module Rigor
|
|
|
20
20
|
class RbsClassAncestorTable < RbsCacheProducer
|
|
21
21
|
PRODUCER_ID = "rbs.class_ancestor_table"
|
|
22
22
|
|
|
23
|
-
# @param loader [Rigor::Environment::RbsLoader]
|
|
24
|
-
# @param store [Rigor::Cache::Store]
|
|
25
|
-
# @return [Hash{String => Array<String>}]
|
|
26
23
|
def self.compute(loader)
|
|
27
24
|
table = {}
|
|
28
25
|
loader.each_known_class_name do |name|
|
|
@@ -20,9 +20,6 @@ module Rigor
|
|
|
20
20
|
class RbsClassTypeParamNames < RbsCacheProducer
|
|
21
21
|
PRODUCER_ID = "rbs.class_type_param_names"
|
|
22
22
|
|
|
23
|
-
# @param loader [Rigor::Environment::RbsLoader]
|
|
24
|
-
# @param store [Rigor::Cache::Store]
|
|
25
|
-
# @return [Hash{String => Array<Symbol>}]
|
|
26
23
|
def self.compute(loader)
|
|
27
24
|
table = {}
|
|
28
25
|
loader.each_known_class_name do |name|
|
|
@@ -15,9 +15,6 @@ module Rigor
|
|
|
15
15
|
class RbsConstantTable < RbsCacheProducer
|
|
16
16
|
PRODUCER_ID = "rbs.constant_type_table"
|
|
17
17
|
|
|
18
|
-
# @param loader [Rigor::Environment::RbsLoader]
|
|
19
|
-
# @param store [Rigor::Cache::Store]
|
|
20
|
-
# @return [Hash{String => Rigor::Type}]
|
|
21
18
|
def self.compute(loader)
|
|
22
19
|
table = {}
|
|
23
20
|
loader.each_constant_decl do |name, entry|
|
|
@@ -3,22 +3,47 @@
|
|
|
3
3
|
require "digest"
|
|
4
4
|
|
|
5
5
|
require_relative "descriptor"
|
|
6
|
+
require_relative "engine_source"
|
|
6
7
|
require_relative "file_digest"
|
|
7
8
|
|
|
8
9
|
module Rigor
|
|
9
10
|
module Cache
|
|
10
11
|
# Shared descriptor builder for cache producers that depend on the RBS environment (constant table,
|
|
11
|
-
# known-class set, future Marshal-clean reflection artefacts). Every consumer attaches the same
|
|
12
|
-
#
|
|
13
|
-
#
|
|
12
|
+
# known-class set, future Marshal-clean reflection artefacts). Every consumer attaches the same slots —
|
|
13
|
+
# the `rbs` gem row, a digest row per signature file, and the `rbs.libraries` / `rbs.virtual_rbs` /
|
|
14
|
+
# `rbs.deferred_signature_paths` / `engine-source` config rows — so factoring the construction here keeps
|
|
15
|
+
# the producers small and ensures invalidation behaves identically across them.
|
|
14
16
|
module RbsDescriptor
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
+
# The key every `rbs.*` producer shares ({RbsCacheProducer#fetch}): `rbs.environment`,
|
|
18
|
+
# `rbs.constant_type_table`, `rbs.class_ancestor_table`, `rbs.known_class_names`,
|
|
19
|
+
# `rbs.class_type_param_names`.
|
|
20
|
+
#
|
|
21
|
+
# Issue #1014 — the engine-source row is here, not in {.config_entries}, because these are
|
|
22
|
+
# computed-value slots: what they hold is not the RBS the descriptor digests but what Rigor's own code
|
|
23
|
+
# made of it. `rbs.constant_type_table` stores `Inference::RbsTypeTranslator.translate` output and
|
|
24
|
+
# `rbs.class_ancestor_table` the chains `RbsClassAncestorTable.compute` walks out of
|
|
25
|
+
# `instance_definition`, so an engine edit to either moved the value while the key stood still: the
|
|
26
|
+
# run-result key moved (#285) and the run re-analysed, then read the previous build's table. Both were
|
|
27
|
+
# reproduced cross-build on a fixture — a true positive dropped, and a `flow.unreachable-clause` false
|
|
28
|
+
# positive served — before this row was added.
|
|
29
|
+
#
|
|
30
|
+
# {.config_entries} deliberately does NOT get it: that half is what the ADR-45 run cache key reads
|
|
31
|
+
# ({.build_run}), and `RunCacheKey` already contributes the identical row from
|
|
32
|
+
# `EngineSource.key_config_entries` itself. Adding it there would duplicate the row in the run key and
|
|
33
|
+
# would have to be reconstructible by the boot-slimming probe, which builds `config_entries` without a
|
|
34
|
+
# loader.
|
|
35
|
+
#
|
|
36
|
+
# @raise EngineSource::Unavailable — an engine that cannot be identified must not be keyed by its
|
|
37
|
+
# inputs alone; {RbsCacheProducer.fetch} turns this into an uncached compute.
|
|
17
38
|
def self.build(loader)
|
|
39
|
+
# FIRST, before {.file_entries} digests the whole signature tree: the {EngineSource::Unavailable}
|
|
40
|
+
# path discards this descriptor entirely, and a SHA-256 of every `.rbs` under every signature root is
|
|
41
|
+
# the expensive way to reach that conclusion.
|
|
42
|
+
engine = EngineSource.key_config_entries
|
|
18
43
|
Descriptor.new(
|
|
19
44
|
gems: [rbs_gem_entry],
|
|
20
45
|
files: file_entries(loader),
|
|
21
|
-
configs: config_entries(loader)
|
|
46
|
+
configs: config_entries(loader) + env_only_config_entries(loader) + engine
|
|
22
47
|
)
|
|
23
48
|
end
|
|
24
49
|
|
|
@@ -26,8 +51,11 @@ module Rigor
|
|
|
26
51
|
# `gems` + `configs` ({Runner#run_key_descriptor}); the RBS signature-tree `files` are read solely on a
|
|
27
52
|
# MISS, by the dependency descriptor ({Runner#run_dependency_descriptor}). So a warm HIT never digests
|
|
28
53
|
# the (large, vendored) RBS tree. {RunDescriptor} is NOT a {Descriptor} — it is never composed, hashed,
|
|
29
|
-
# or `==`'d, only its
|
|
30
|
-
# / `configs`
|
|
54
|
+
# or `==`'d, only its four readers are consulted — so deferring `files` costs no soundness, and `gems`
|
|
55
|
+
# / `configs` match {.build}'s shared slots (the key is unchanged; the slots the env key adds on top,
|
|
56
|
+
# {.env_only_config_entries} and the #1014 `engine-source` row, are never read here — `RunCacheKey`
|
|
57
|
+
# contributes the identical engine-source row itself, from the same
|
|
58
|
+
# `EngineSource.key_config_entries`).
|
|
31
59
|
def self.build_run(loader)
|
|
32
60
|
RunDescriptor.new(loader: loader, gems: [rbs_gem_entry], configs: config_entries(loader))
|
|
33
61
|
end
|
|
@@ -38,19 +66,47 @@ module Rigor
|
|
|
38
66
|
[libraries_entry(loader.libraries), virtual_rbs_entry(loader)].compact
|
|
39
67
|
end
|
|
40
68
|
|
|
69
|
+
# Issue #610 — the slots only the env-cache KEY reads, on top of {.config_entries}. Which of the
|
|
70
|
+
# loader's `signature_paths:` are DEFERRED (a bundled plugin's `sig/`, loaded last and allowed to
|
|
71
|
+
# stand down against a colliding generic arity) changes the env built from byte-identical files, so
|
|
72
|
+
# the partition belongs in the key: moving a plugin's `sig/` between `plugins:` and an explicit
|
|
73
|
+
# `signature_paths:` entry changes no file, and an env cached before the producer honoured the
|
|
74
|
+
# partition must read as a miss once. Kept OUT of {.config_entries} deliberately — the run-result
|
|
75
|
+
# key already digests the whole resolved configuration (`RunCacheKey`), and its boot-slimming probe
|
|
76
|
+
# reconstructs {.config_entries} without loading a plugin, so an entry there that it cannot rebuild
|
|
77
|
+
# would turn the warm fast lane into a permanent miss on every project that enables a bundled plugin.
|
|
78
|
+
def self.env_only_config_entries(loader)
|
|
79
|
+
[deferred_signature_paths_entry(loader)].compact
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.deferred_signature_paths_entry(loader)
|
|
83
|
+
return nil unless loader.respond_to?(:deferred_signature_paths)
|
|
84
|
+
|
|
85
|
+
deferred = Array(loader.deferred_signature_paths).map(&:to_s).sort
|
|
86
|
+
return nil if deferred.empty?
|
|
87
|
+
|
|
88
|
+
Descriptor::ConfigEntry.new(
|
|
89
|
+
key: "rbs.deferred_signature_paths",
|
|
90
|
+
value_hash: Digest::SHA256.hexdigest(deferred.join("\n"))
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private_class_method :deferred_signature_paths_entry
|
|
95
|
+
|
|
41
96
|
# Public (ADR-87 WD4) so the boot-slimming run-cache probe reconstructs the identical `gems` +
|
|
42
97
|
# `rbs.libraries` key slots the runner writes, from the config-derived library list, without a loader.
|
|
43
98
|
def self.rbs_gem_entry
|
|
44
99
|
Descriptor::GemEntry.new(name: "rbs", requirement: ">= 0", locked: ::RBS::VERSION.to_s)
|
|
45
100
|
end
|
|
46
101
|
|
|
47
|
-
# @param comparator
|
|
102
|
+
# @param comparator — `:digest` (default) for the env-cache KEY descriptor ({.build}), where the
|
|
48
103
|
# value must be deterministic; `:stat` (ADR-87 WD1) for the validation-only run-dependency descriptor
|
|
49
104
|
# ({RunDescriptor#files}), where the stat tier short-circuits the SHA-256 on an unmoved file.
|
|
50
105
|
def self.file_entries(loader, comparator: :digest)
|
|
51
106
|
roots = loader.signature_paths +
|
|
52
107
|
Rigor::Environment::RbsLoader.vendored_gem_sig_paths +
|
|
53
|
-
Rigor::Environment::RbsLoader.core_overlay_sig_paths
|
|
108
|
+
Rigor::Environment::RbsLoader.core_overlay_sig_paths +
|
|
109
|
+
Rigor::Environment::RbsLoader.capability_role_sig_paths
|
|
54
110
|
roots.flat_map do |root|
|
|
55
111
|
next [] unless root.directory?
|
|
56
112
|
|
|
@@ -65,7 +121,41 @@ module Rigor
|
|
|
65
121
|
end
|
|
66
122
|
end
|
|
67
123
|
|
|
68
|
-
#
|
|
124
|
+
# Issue #979 — the directory-LISTING rows for the signature roots, one {Descriptor::GlobEntry} per
|
|
125
|
+
# root over `**/*.rbs`. {.file_entries} answers "did any signature file I read change", which is a
|
|
126
|
+
# question only about files that existed when the run recorded its dependencies; a `sig/roles.rbs`
|
|
127
|
+
# written afterwards is in no row, so the ADR-45 run-result slot validated fresh and the warm run kept
|
|
128
|
+
# serving diagnostics computed without it. A glob row is the same edge {Plugin::IoBoundary} records
|
|
129
|
+
# for a listed directory (#954): re-globbing on the next run sees the appearance, and one row per root
|
|
130
|
+
# (not per file) keeps the cost a single `Dir.glob`.
|
|
131
|
+
#
|
|
132
|
+
# The rows are `:names` mode, not the default `:stat`: the question they add is which signature files
|
|
133
|
+
# EXIST, and every edit to one of them is already carried by that file's own ADR-87 WD1 `:stat` row —
|
|
134
|
+
# which survives a moved stat tuple by falling back to its recorded content digest. A stat-mode glob
|
|
135
|
+
# would not, so a `git checkout`, a `bundle install`, or a CI run with a restored cache over a fresh
|
|
136
|
+
# checkout — none of which changes a byte of RBS — would turn every warm run into a full re-analysis.
|
|
137
|
+
# Names mode also reads no stat, so it neither pays for nor perturbs the per-run validation-stat memo.
|
|
138
|
+
#
|
|
139
|
+
# Scoped to the loader's own roots — the project's `signature_paths:` (including the auto-detected
|
|
140
|
+
# `sig/`), the bundled-plugin `sig/` trees (ADR-25), the bundle walk, `rbs collection`, the ADR-72
|
|
141
|
+
# overlays. Rigor's own `data/` trees ({RbsLoader.vendored_gem_sig_paths}, `.core_overlay_sig_paths`,
|
|
142
|
+
# `.capability_role_sig_paths`) are engine-owned: a file appears under one only when the engine tree is
|
|
143
|
+
# edited, which normally arrives with the `lib/` change that reads it and so re-keys every
|
|
144
|
+
# computed-value slot through {EngineSource} — including, since #1014, this descriptor itself, which
|
|
145
|
+
# until then carried no such row. They get file rows and no glob — a glob there would cost
|
|
146
|
+
# every project a stat walk of the vendored gem-signature tree per warm run to catch an
|
|
147
|
+
# engine-development edit.
|
|
148
|
+
def self.glob_entries(loader)
|
|
149
|
+
# Deduplicated by path: a root reachable twice (an explicit `signature_paths:` entry that is also a
|
|
150
|
+
# bundled plugin's `sig/`, #610) would otherwise contribute two rows whose stat signatures race.
|
|
151
|
+
loader.signature_paths.uniq(&:to_s).filter_map do |root|
|
|
152
|
+
next unless root.directory?
|
|
153
|
+
|
|
154
|
+
Descriptor::GlobEntry.compute(root: root.to_s, pattern: File.join("**", "*.rbs"), mode: :names)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# @param library_names — the loader's merged library list (or, on the WD4 probe
|
|
69
159
|
# path, `Environment::DEFAULT_LIBRARIES + config.libraries` reconstructed without a loader).
|
|
70
160
|
def self.libraries_entry(library_names)
|
|
71
161
|
sorted = library_names.map(&:to_s).sort
|
|
@@ -93,10 +183,11 @@ module Rigor
|
|
|
93
183
|
|
|
94
184
|
private_class_method :virtual_rbs_entry
|
|
95
185
|
|
|
96
|
-
# The lazy-files run descriptor {RbsDescriptor.build_run} returns. Exposes the
|
|
186
|
+
# The lazy-files run descriptor {RbsDescriptor.build_run} returns. Exposes the four readers the
|
|
97
187
|
# run-diagnostics cache consults — `gems` + `configs` are supplied eagerly (they feed the cache KEY,
|
|
98
|
-
# and are cheap); `files` (the RBS signature-tree digests
|
|
99
|
-
# first access and memoised, so a warm HIT
|
|
188
|
+
# and are cheap); `files` (the RBS signature-tree digests) and `globs` (#979, the per-root listing
|
|
189
|
+
# rows) are read only on a MISS, computed once on first access and memoised, so a warm HIT pays for
|
|
190
|
+
# neither.
|
|
100
191
|
class RunDescriptor
|
|
101
192
|
attr_reader :gems, :configs
|
|
102
193
|
|
|
@@ -106,6 +197,13 @@ module Rigor
|
|
|
106
197
|
@configs = configs
|
|
107
198
|
end
|
|
108
199
|
|
|
200
|
+
# Issue #979 — one directory-listing row per signature root, so a `.rbs` file APPEARING under one
|
|
201
|
+
# (or vanishing from it) invalidates the run-result slot. Memoised for the same reason `files` is:
|
|
202
|
+
# a collecting run asks twice about the same post-run world.
|
|
203
|
+
def globs
|
|
204
|
+
@globs ||= RbsDescriptor.glob_entries(@loader)
|
|
205
|
+
end
|
|
206
|
+
|
|
109
207
|
def files
|
|
110
208
|
# ADR-87 WD1 — this descriptor is validated (never a cache key), so the RBS signature tree rides the
|
|
111
209
|
# stat-then-digest `:stat` tier: a warm run stat-checks the (large, vendored) tree instead of
|
|
@@ -22,14 +22,18 @@ module Rigor
|
|
|
22
22
|
class RbsEnvironment < RbsCacheProducer
|
|
23
23
|
PRODUCER_ID = "rbs.environment"
|
|
24
24
|
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
25
|
+
# Issue #610 — the deferred (plugin-contributed) subset rides through too. This is the build path every
|
|
26
|
+
# cached run takes: a cache store is the CLI default and only `--no-cache` reaches the loader's own
|
|
27
|
+
# `build_env`, so a list threaded through the loader but not through here ran the arity stand-down on
|
|
28
|
+
# no real `rigor check` at all — 0.3.8 shipped exactly that, behind a green gate built over a
|
|
29
|
+
# store-less loader. Any input `build_env_for` takes MUST be passed from here as well.
|
|
28
30
|
def self.compute(loader)
|
|
29
31
|
Rigor::Environment::RbsLoader.build_env_for(
|
|
30
32
|
libraries: loader.libraries,
|
|
31
33
|
signature_paths: loader.signature_paths,
|
|
32
|
-
virtual_rbs: loader.respond_to?(:virtual_rbs) ? loader.virtual_rbs : []
|
|
34
|
+
virtual_rbs: loader.respond_to?(:virtual_rbs) ? loader.virtual_rbs : [],
|
|
35
|
+
deferred_signature_paths:
|
|
36
|
+
loader.respond_to?(:deferred_signature_paths) ? loader.deferred_signature_paths : []
|
|
33
37
|
)
|
|
34
38
|
end
|
|
35
39
|
|
|
@@ -18,9 +18,6 @@ module Rigor
|
|
|
18
18
|
class RbsKnownClassNames < RbsCacheProducer
|
|
19
19
|
PRODUCER_ID = "rbs.known_class_names"
|
|
20
20
|
|
|
21
|
-
# @param loader [Rigor::Environment::RbsLoader]
|
|
22
|
-
# @param store [Rigor::Cache::Store]
|
|
23
|
-
# @return [Set<String>]
|
|
24
21
|
def self.compute(loader)
|
|
25
22
|
names = Set.new
|
|
26
23
|
loader.each_known_class_name { |name| names << name }
|