rigortype 0.4.6 → 0.4.7
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/gem_overlay/activesupport/core_ext.rbs +16 -13
- data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
- data/docs/handbook/01-getting-started.md +5 -2
- data/docs/handbook/11-sig-gen.md +50 -3
- data/docs/handbook/appendix-phpstan.md +4 -4
- data/docs/manual/02-cli-reference.md +152 -26
- data/docs/manual/03-configuration.md +36 -3
- data/docs/manual/06-baseline.md +6 -4
- data/docs/manual/09-editor-integration.md +13 -2
- data/docs/manual/10-mcp-server.md +38 -2
- data/docs/manual/12-caching.md +4 -3
- data/docs/manual/plugins/rigor-actionpack.md +19 -11
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +20 -1
- data/lib/rigor/analysis/baseline.rb +24 -27
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +4 -4
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +85 -13
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +0 -1
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +1 -1
- data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +3 -3
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
- data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
- data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules.rb +124 -44
- data/lib/rigor/analysis/crash_signature.rb +2 -2
- data/lib/rigor/analysis/dependency_recorder.rb +4 -4
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/edit_replay.rb +93 -6
- data/lib/rigor/analysis/fact_store.rb +3 -3
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -2
- data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
- data/lib/rigor/analysis/incremental_session.rb +27 -16
- data/lib/rigor/analysis/rule_catalog.rb +2 -2
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +2 -2
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -1
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +193 -93
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +1 -1
- data/lib/rigor/analysis/runner/pool_coordinator.rb +147 -323
- data/lib/rigor/analysis/runner/project_pre_passes.rb +3 -3
- data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
- data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
- data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
- data/lib/rigor/analysis/runner.rb +77 -71
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +1 -1
- data/lib/rigor/analysis/template_unit_positions.rb +2 -3
- data/lib/rigor/analysis/template_units.rb +9 -1
- data/lib/rigor/analysis/worker_session.rb +24 -31
- data/lib/rigor/bleeding_edge.rb +3 -6
- data/lib/rigor/builtins/imported_refinements.rb +6 -8
- data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
- data/lib/rigor/builtins/regex_refinement.rb +4 -6
- data/lib/rigor/cache/descriptor.rb +6 -5
- data/lib/rigor/cache/incremental_snapshot.rb +31 -12
- data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
- data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
- data/lib/rigor/cache/rbs_constant_table.rb +1 -1
- data/lib/rigor/cache/rbs_descriptor.rb +54 -3
- data/lib/rigor/cache/rbs_environment.rb +4 -1
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
- data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
- data/lib/rigor/cache/store.rb +11 -10
- data/lib/rigor/ci_detector.rb +1 -1
- data/lib/rigor/cli/annotate_command.rb +24 -19
- data/lib/rigor/cli/baseline_command.rb +145 -55
- data/lib/rigor/cli/catalogue.rb +256 -0
- data/lib/rigor/cli/check_command.rb +108 -102
- data/lib/rigor/cli/check_runner_factory.rb +2 -2
- data/lib/rigor/cli/command.rb +15 -1
- data/lib/rigor/cli/coverage_command.rb +21 -8
- data/lib/rigor/cli/coverage_mutation.rb +5 -7
- data/lib/rigor/cli/coverage_renderer.rb +2 -1
- data/lib/rigor/cli/coverage_scan.rb +3 -5
- data/lib/rigor/cli/diff_command.rb +25 -20
- data/lib/rigor/cli/docs_command.rb +1 -2
- data/lib/rigor/cli/doctor_command.rb +12 -12
- data/lib/rigor/cli/effects_command.rb +50 -40
- data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
- data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
- data/lib/rigor/cli/effects_renderer.rb +2 -1
- data/lib/rigor/cli/effects_snapshot_command.rb +18 -17
- data/lib/rigor/cli/explain_command.rb +18 -8
- data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
- data/lib/rigor/cli/json_document.rb +41 -0
- data/lib/rigor/cli/lens_command.rb +12 -8
- data/lib/rigor/cli/lsp_command.rb +250 -23
- data/lib/rigor/cli/mcp_command.rb +12 -7
- data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
- data/lib/rigor/cli/options.rb +40 -1
- data/lib/rigor/cli/plugin_command.rb +93 -46
- data/lib/rigor/cli/plugins_command.rb +17 -18
- data/lib/rigor/cli/plugins_renderer.rb +10 -6
- data/lib/rigor/cli/protection_fork_scan.rb +2 -2
- data/lib/rigor/cli/protection_renderer.rb +2 -1
- data/lib/rigor/cli/show_bleedingedge_command.rb +21 -15
- data/lib/rigor/cli/sig_gen_command.rb +84 -27
- data/lib/rigor/cli/skill_command.rb +32 -3
- data/lib/rigor/cli/skill_deep_probe.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +1 -1
- data/lib/rigor/cli/trace_command.rb +14 -9
- data/lib/rigor/cli/triage_command.rb +10 -11
- data/lib/rigor/cli/triage_renderer.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +16 -11
- data/lib/rigor/cli/type_of_project_scope.rb +1 -4
- data/lib/rigor/cli/type_of_renderer.rb +4 -1
- data/lib/rigor/cli/type_scan_command.rb +14 -9
- data/lib/rigor/cli/type_scan_renderer.rb +2 -1
- data/lib/rigor/cli/unused_command.rb +27 -17
- data/lib/rigor/cli/upgrade_command.rb +5 -0
- data/lib/rigor/cli.rb +209 -54
- data/lib/rigor/config_audit.rb +1 -1
- data/lib/rigor/configuration/severity_profile.rb +5 -5
- data/lib/rigor/configuration.rb +72 -30
- data/lib/rigor/effects/definition_context.rb +0 -2
- data/lib/rigor/effects/envelope.rb +1 -1
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/mutation_classifier.rb +4 -7
- data/lib/rigor/effects/propagator.rb +1 -1
- data/lib/rigor/effects/registry.rb +2 -2
- data/lib/rigor/effects/snapshot.rb +1 -1
- data/lib/rigor/effects/taint_cause.rb +0 -2
- data/lib/rigor/effects/unit_scan.rb +9 -13
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -9
- data/lib/rigor/environment/class_registry.rb +3 -3
- data/lib/rigor/environment/core_root.rb +77 -0
- data/lib/rigor/environment/default_libraries.rb +1 -1
- data/lib/rigor/environment/deferred_signature_plan.rb +283 -0
- data/lib/rigor/environment/gated_signature_guard.rb +1 -1
- data/lib/rigor/environment/gated_signature_plan.rb +5 -2
- data/lib/rigor/environment/lockfile_resolver.rb +28 -12
- data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
- data/lib/rigor/environment/member_consistency.rb +56 -7
- data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
- data/lib/rigor/environment/project_path_gems.rb +124 -0
- data/lib/rigor/environment/rbs_hierarchy.rb +6 -15
- data/lib/rigor/environment/rbs_loader.rb +480 -67
- data/lib/rigor/environment/reflection.rb +7 -7
- data/lib/rigor/environment/required_features.rb +0 -3
- data/lib/rigor/environment/ruby_library_roots.rb +1 -1
- data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
- data/lib/rigor/environment.rb +41 -10
- data/lib/rigor/flow_contribution/merger.rb +4 -4
- data/lib/rigor/inference/acceptance.rb +93 -32
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/block_run_count.rb +178 -0
- data/lib/rigor/inference/budget_trace.rb +8 -2
- data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
- data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
- data/lib/rigor/inference/callee_mutation_chain.rb +88 -77
- data/lib/rigor/inference/callee_write_census.rb +815 -0
- data/lib/rigor/inference/construction_escape.rb +217 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
- data/lib/rigor/inference/deep_erasure.rb +39 -7
- data/lib/rigor/inference/def_handle.rb +1 -1
- data/lib/rigor/inference/def_node_resolver.rb +1 -1
- data/lib/rigor/inference/def_return_typer.rb +46 -4
- data/lib/rigor/inference/definer_resolution.rb +4 -2
- data/lib/rigor/inference/definers_index.rb +106 -0
- data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
- data/lib/rigor/inference/element_read_widening.rb +49 -3
- data/lib/rigor/inference/expression_typer.rb +116 -49
- data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
- data/lib/rigor/inference/global_write_census.rb +76 -2
- data/lib/rigor/inference/global_writer_reach.rb +260 -0
- data/lib/rigor/inference/hkt_body.rb +1 -2
- data/lib/rigor/inference/hkt_body_parser.rb +3 -5
- data/lib/rigor/inference/hkt_reducer.rb +2 -2
- data/lib/rigor/inference/hkt_registry.rb +3 -5
- data/lib/rigor/inference/indexed_narrowing.rb +4 -7
- data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
- data/lib/rigor/inference/ivar_writer_census.rb +51 -0
- data/lib/rigor/inference/key_presence_guard.rb +2 -1
- data/lib/rigor/inference/loop_value_record.rb +8 -4
- data/lib/rigor/inference/match_rebinding/frame.rb +46 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +45 -0
- data/lib/rigor/inference/match_rebinding.rb +11 -1
- data/lib/rigor/inference/memo_audit.rb +55 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +39 -27
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +203 -17
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +9 -7
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +83 -20
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +64 -14
- data/lib/rigor/inference/module_function_state.rb +11 -1
- data/lib/rigor/inference/multi_target_binder.rb +1 -1
- data/lib/rigor/inference/mutation_rejoin.rb +240 -4
- data/lib/rigor/inference/mutation_widening.rb +157 -27
- data/lib/rigor/inference/narrowing.rb +47 -33
- data/lib/rigor/inference/optimistic_origin.rb +1 -1
- data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +6 -3
- data/lib/rigor/inference/project_yielder.rb +11 -17
- data/lib/rigor/inference/receiver_alias.rb +20 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +3 -1
- data/lib/rigor/inference/refined_dispatch/own_method.rb +2 -1
- data/lib/rigor/inference/remover_holder_scan.rb +233 -0
- data/lib/rigor/inference/remover_narrowing.rb +224 -0
- data/lib/rigor/inference/rewrite_mutation.rb +53 -2
- data/lib/rigor/inference/scope_indexer/certainty.rb +0 -1
- data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +58 -15
- data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
- data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
- data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +135 -0
- data/lib/rigor/inference/scope_indexer.rb +137 -46
- data/lib/rigor/inference/self_call_ivar_writes.rb +84 -12
- data/lib/rigor/inference/set_mutation.rb +189 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +1 -2
- data/lib/rigor/inference/statement_evaluator.rb +2328 -138
- data/lib/rigor/inference/struct_fold_safety.rb +4 -6
- data/lib/rigor/inference/synthetic_method_scanner.rb +5 -6
- data/lib/rigor/inference/toplevel_def_census.rb +59 -0
- data/lib/rigor/inference/unknown_store_widening.rb +103 -4
- data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -1
- data/lib/rigor/language_server/buffer_table.rb +3 -3
- data/lib/rigor/language_server/completion_provider.rb +26 -20
- data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
- data/lib/rigor/language_server/diagnostic_publisher.rb +8 -3
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -2
- data/lib/rigor/language_server/hover_provider.rb +1 -7
- data/lib/rigor/language_server/hover_renderer.rb +6 -8
- data/lib/rigor/language_server/project_context.rb +39 -1
- data/lib/rigor/language_server/publish_batcher.rb +3 -4
- data/lib/rigor/language_server/selection_range_provider.rb +2 -4
- data/lib/rigor/language_server/server.rb +7 -3
- data/lib/rigor/language_server/signature_help_provider.rb +4 -4
- data/lib/rigor/lens/plugins.rb +1 -1
- data/lib/rigor/mcp/server.rb +73 -2
- data/lib/rigor/mcp.rb +1 -1
- data/lib/rigor/plugin/access_denied_error.rb +1 -2
- data/lib/rigor/plugin/bundled_catalog.rb +1 -12
- data/lib/rigor/plugin/io_boundary.rb +1 -1
- data/lib/rigor/plugin/loader.rb +25 -8
- data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
- data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
- data/lib/rigor/plugin/manifest.rb +9 -13
- data/lib/rigor/plugin/registry.rb +3 -3
- data/lib/rigor/plugin/services.rb +2 -3
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -2
- data/lib/rigor/plugin/type_node_resolver.rb +2 -4
- data/lib/rigor/plugin.rb +6 -8
- data/lib/rigor/plugin_gap_advisory.rb +5 -1
- data/lib/rigor/project_environment.rb +16 -2
- data/lib/rigor/protection/analysis_guard.rb +1 -1
- data/lib/rigor/protection/discovery_seed.rb +44 -5
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
- data/lib/rigor/rbs_extended/reporter.rb +27 -3
- data/lib/rigor/rbs_extended.rb +2 -3
- data/lib/rigor/reflection/constant_ancestors.rb +5 -3
- data/lib/rigor/rooted_glob.rb +15 -1
- data/lib/rigor/run_scoped_slots.rb +38 -0
- data/lib/rigor/runtime/jit.rb +1 -1
- data/lib/rigor/scope/discovery_index.rb +19 -6
- data/lib/rigor/scope/resolution_chain.rb +3 -1
- data/lib/rigor/scope.rb +365 -31
- data/lib/rigor/sig_gen/classification.rb +4 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
- data/lib/rigor/sig_gen/generator.rb +371 -58
- data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
- data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
- data/lib/rigor/sig_gen/layout_index.rb +3 -3
- data/lib/rigor/sig_gen/method_candidate.rb +23 -4
- data/lib/rigor/sig_gen/observation_collector.rb +3 -5
- data/lib/rigor/sig_gen/observed_call.rb +1 -1
- data/lib/rigor/sig_gen/path_mapper.rb +6 -0
- data/lib/rigor/sig_gen/renderer.rb +15 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +15 -2
- data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
- data/lib/rigor/sig_gen/write_reporter.rb +63 -14
- data/lib/rigor/sig_gen/write_result.rb +23 -12
- data/lib/rigor/sig_gen/writer.rb +217 -37
- data/lib/rigor/type/acceptance_router.rb +2 -2
- data/lib/rigor/type/accepts_result.rb +1 -1
- data/lib/rigor/type/app.rb +4 -6
- data/lib/rigor/type/combinator.rb +9 -13
- data/lib/rigor/type/constant.rb +4 -5
- data/lib/rigor/type/hash_shape.rb +21 -40
- data/lib/rigor/type/union.rb +1 -1
- data/lib/rigor/type_node/identifier.rb +1 -2
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node/string_literal.rb +1 -2
- data/lib/rigor/type_node/symbol_literal.rb +1 -2
- data/lib/rigor/type_node/union.rb +3 -6
- data/lib/rigor/value_semantics.rb +1 -10
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +38 -36
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +66 -19
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +2 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +0 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +5 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +7 -12
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +19 -6
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +26 -13
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +1 -1
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -5
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -2
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +1 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +1 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +3 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +1 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +17 -21
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +3 -2
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
- data/sig/rigor/analysis/baseline.rbs +0 -3
- data/sig/rigor/analysis/fact_store.rbs +1 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
- data/sig/rigor/cli/diff_command.rbs +1 -1
- data/sig/rigor/cli/explain_command.rbs +1 -1
- data/sig/rigor/effects/registry.rbs +2 -2
- data/sig/rigor/inference.rbs +4 -1
- data/sig/rigor/plugin/additional_initializer.rbs +0 -5
- data/sig/rigor/plugin/base.rbs +1 -0
- data/sig/rigor/plugin/effect_attribution.rbs +3 -3
- data/sig/rigor/plugin/effect_edge.rbs +1 -1
- data/sig/rigor/plugin/effect_entry_points.rbs +3 -3
- data/sig/rigor/plugin/io_boundary.rbs +2 -1
- data/sig/rigor/plugin/manifest.rbs +9 -9
- data/sig/rigor/plugin/protocol_contract.rbs +3 -7
- data/sig/rigor/scope.rbs +23 -3
- data/skills/rigor-plugin-author/SKILL.md +4 -4
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
- data/skills/rigor-plugin-review/SKILL.md +3 -3
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +12 -1
- metadata +36 -3
|
@@ -5,6 +5,7 @@ require "prism"
|
|
|
5
5
|
require "tmpdir"
|
|
6
6
|
|
|
7
7
|
require_relative "../environment"
|
|
8
|
+
require_relative "../run_scoped_slots"
|
|
8
9
|
require_relative "../scope"
|
|
9
10
|
require_relative "../cache/store"
|
|
10
11
|
require_relative "../cache/rbs_descriptor"
|
|
@@ -87,11 +88,10 @@ module Rigor
|
|
|
87
88
|
# forbids Rigor demanding in its place) and the HKT-scan outcome (whose producer is an environment a
|
|
88
89
|
# nothing-changed recheck otherwise has no reason to build). {IncrementalSession} persists what a full
|
|
89
90
|
# run answers here and hands it back to the next narrowed run.
|
|
91
|
+
#
|
|
92
|
+
# Which rows those are is declared, not listed: every {RunLevelFacts} fact marked `replay`.
|
|
90
93
|
def run_level_rows
|
|
91
|
-
Cache::IncrementalSnapshot::RunLevelRows.new(
|
|
92
|
-
definition_build_failures: @snapshots.definition_build_failures,
|
|
93
|
-
hkt_scan_failure: @snapshots.hkt_scan_failure
|
|
94
|
-
)
|
|
94
|
+
Cache::IncrementalSnapshot::RunLevelRows.new(**@snapshots.to_h.slice(*RunLevelFacts.replayable_names))
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# ADR-46 — the per-file cross-file read records this run captured (empty unless
|
|
@@ -280,8 +280,7 @@ module Rigor
|
|
|
280
280
|
# @param explain — surface fail-soft fallback events as `:info` diagnostics.
|
|
281
281
|
# @param cache_store — the persistent cache the runner exposes to producers
|
|
282
282
|
# (`RbsConstantTable` and successors). Pass `nil` to disable caching for this run; the CLI's
|
|
283
|
-
# `--no-cache` flag wires `nil` through.
|
|
284
|
-
# slices route real producers through it.
|
|
283
|
+
# `--no-cache` flag wires `nil` through.
|
|
285
284
|
# @param workers — ADR-15 Phase 4b — when greater than zero, per-file analysis dispatches
|
|
286
285
|
# across a pool of N workers. Default `0` keeps the sequential code path bit-for-bit unchanged.
|
|
287
286
|
# Controlled via the `RIGOR_RACTOR_WORKERS` env var or `.rigor.yml` `parallel.workers:` (Phase 4c,
|
|
@@ -352,8 +351,8 @@ module Rigor
|
|
|
352
351
|
@prebuilt = prebuilt
|
|
353
352
|
@environment_override = environment
|
|
354
353
|
# ADR-46 slice 1 — opt-in cross-file dependency recording. Off by default; when true,
|
|
355
|
-
# `analyze_file` records each file's cross-file reads into `file_dependencies
|
|
356
|
-
# cache
|
|
354
|
+
# `analyze_file` records each file's cross-file reads into `file_dependencies`; the incremental
|
|
355
|
+
# cache consumes them.
|
|
357
356
|
@record_dependencies = record_dependencies
|
|
358
357
|
# ADR-24 slice 4a — opt-in unresolved-implicit-self-call recording. Off by default; when true,
|
|
359
358
|
# `analyze_file` activates the engine choke-point recorder and collects each file's misses into
|
|
@@ -513,6 +512,9 @@ module Rigor
|
|
|
513
512
|
# entry across a run boundary (LSP re-check, ADR-62 warm loop); nil until the first run so
|
|
514
513
|
# runner-less probes keep the per-file fallback.
|
|
515
514
|
@run_generation = nil
|
|
515
|
+
# The return memo bucket the last `run` filled, kept for {#return_summaries} once the run has released the
|
|
516
|
+
# thread's slot; nil before the first run.
|
|
517
|
+
@return_memo = nil
|
|
516
518
|
build_collaborators
|
|
517
519
|
end
|
|
518
520
|
|
|
@@ -535,6 +537,11 @@ module Rigor
|
|
|
535
537
|
# freshness path for this run; the `auto` default resolves strict in CI (#190), stat-first elsewhere.
|
|
536
538
|
Cache::FileDigest.with_run(strict: @configuration.cache_validation_strict?) do
|
|
537
539
|
Inference::DefNodeResolver.with_run { run_analysis(paths) }
|
|
540
|
+
ensure
|
|
541
|
+
# ADR-89 WD2 — {#return_summaries} reads the return memo after the run, so the runner keeps the bucket the
|
|
542
|
+
# run filled before the thread's run-scoped slots are released (issues #2412, #2399).
|
|
543
|
+
@return_memo = Inference::ExpressionTyper.current_return_memo
|
|
544
|
+
RunScopedSlots.release
|
|
538
545
|
end
|
|
539
546
|
end
|
|
540
547
|
|
|
@@ -548,6 +555,21 @@ module Rigor
|
|
|
548
555
|
end
|
|
549
556
|
private :reset_analysis_attribution
|
|
550
557
|
|
|
558
|
+
# Issue #2392 — the sequential half of the per-run reset, beside {#reset_analysis_attribution}: the
|
|
559
|
+
# dependency graph and per-file effect collections a `--workers 0` run records, and the effect-slot state a
|
|
560
|
+
# served run leaves behind. The loader is the one that matters: a served run's collections loader would
|
|
561
|
+
# otherwise feed the next analysing run the previous run's collections. Runs before any `adopt_*`, which the
|
|
562
|
+
# served lanes call later in the same run, so an adopted slot is this run's own.
|
|
563
|
+
def reset_sequential_run_tables
|
|
564
|
+
@file_dependencies = {}
|
|
565
|
+
@file_effects = {}
|
|
566
|
+
@cached_effect_sources = nil
|
|
567
|
+
@cached_effect_ancestry = nil
|
|
568
|
+
@cached_collections_loader = nil
|
|
569
|
+
@effects_served_from_cache = false
|
|
570
|
+
end
|
|
571
|
+
private :reset_sequential_run_tables
|
|
572
|
+
|
|
551
573
|
def run_analysis(paths)
|
|
552
574
|
Inference::MethodDispatcher::FileFolding.fold_platform_specific_paths =
|
|
553
575
|
@configuration.fold_platform_specific_paths
|
|
@@ -561,6 +583,10 @@ module Rigor
|
|
|
561
583
|
@project_discovery_expansion = project_discovery_expansion(paths, expansion)
|
|
562
584
|
@discovery_widened = widen_discovery_to_project?(paths)
|
|
563
585
|
@snapshots.reset_for_run
|
|
586
|
+
# Issue #2392 — the coordinator's run-accumulated tables (disclosures, trust refusals, the dependency and
|
|
587
|
+
# effect graphs) are per run too: a reused Runner must not re-emit or sum the previous run's rows.
|
|
588
|
+
@pool_coordinator.reset_for_run
|
|
589
|
+
reset_sequential_run_tables
|
|
564
590
|
# Per-run reset of the deferred-discovery memo (see `#ensure_project_discovery`).
|
|
565
591
|
@project_discovery_done = false
|
|
566
592
|
# #392 — re-derive the template units each run: their source files can change between two runs of
|
|
@@ -768,9 +794,10 @@ module Rigor
|
|
|
768
794
|
# arg-flooring surface). Only meaningful right after a run populated the memo (baseline / recheck),
|
|
769
795
|
# before the bucket rolls. Keys are held live here; the session Marshals them for the snapshot.
|
|
770
796
|
#
|
|
771
|
-
# @return `
|
|
797
|
+
# @return the summaries keyed by `[path, "Class#method"]` (or `"Class.method"`), each holding `keys:`,
|
|
798
|
+
# `returns:` and `effects:`.
|
|
772
799
|
def return_summaries
|
|
773
|
-
memo = Inference::ExpressionTyper.harvest_return_memo
|
|
800
|
+
memo = Inference::ExpressionTyper.harvest_return_memo(@return_memo)
|
|
774
801
|
return {} if memo.empty?
|
|
775
802
|
|
|
776
803
|
result = {}
|
|
@@ -828,13 +855,15 @@ module Rigor
|
|
|
828
855
|
#
|
|
829
856
|
# @param paths — analysis roots (nil → the configuration's `paths:`).
|
|
830
857
|
# @param specs — each `{ class_name:, method_name:, singleton:, keys: [[receiver, args], …] }`.
|
|
831
|
-
# @return
|
|
858
|
+
# @return the re-evaluated return descriptors, one per key, keyed by `[class_name, method_name, singleton]`.
|
|
832
859
|
def evaluate_return_types(paths, specs)
|
|
833
860
|
return {} if specs.empty?
|
|
834
861
|
|
|
835
862
|
Cache::FileDigest.with_run(strict: @configuration.cache_validation_strict?) do
|
|
836
863
|
Inference::DefNodeResolver.with_run { evaluate_return_types_setup(paths, specs) }
|
|
837
864
|
end
|
|
865
|
+
ensure
|
|
866
|
+
RunScopedSlots.release
|
|
838
867
|
end
|
|
839
868
|
|
|
840
869
|
# Builds the discovery index + environment (a real run's prologue, minus per-file analysis) and
|
|
@@ -1021,17 +1050,12 @@ module Rigor
|
|
|
1021
1050
|
nil
|
|
1022
1051
|
end
|
|
1023
1052
|
|
|
1024
|
-
# The write half, run only after a miss, so
|
|
1025
|
-
# collections the analysis just produced — and the table the analysis already closed over them, so
|
|
1026
|
-
# a warm hit re-runs neither the merge nor the fixpoint — validated against the same post-run
|
|
1027
|
-
# dependency descriptor the diagnostics slot records. Fail-soft — a collection that will not
|
|
1028
|
-
# Marshal (which nothing in {Effects::FileCollection} should be, and the fork pool already proves
|
|
1029
|
-
# per file) costs the next run its warm start and nothing else.
|
|
1030
|
-
# The write half, run only after a miss, so neither block recomputes anything. Two entries under one
|
|
1053
|
+
# The write half, run only after a miss, so nothing here recomputes anything. Two entries under one
|
|
1031
1054
|
# key descriptor and one dependency descriptor (#482): the summary a warm run serves from, and the
|
|
1032
1055
|
# collections the incremental and fail-soft paths read. The summary is written LAST, so a run
|
|
1033
1056
|
# interrupted between the two leaves a collections entry that the next run's summary miss simply
|
|
1034
|
-
# re-collects — never a summary whose collections are absent.
|
|
1057
|
+
# re-collects — never a summary whose collections are absent. A collection that will not Marshal
|
|
1058
|
+
# costs the next run its warm start and nothing else.
|
|
1035
1059
|
def store_effect_collections(descriptor, expansion, rbs_descriptor)
|
|
1036
1060
|
return if descriptor.nil?
|
|
1037
1061
|
|
|
@@ -1233,40 +1257,13 @@ module Rigor
|
|
|
1233
1257
|
end
|
|
1234
1258
|
private :template_unit_failure_diagnostics
|
|
1235
1259
|
|
|
1236
|
-
#
|
|
1237
|
-
#
|
|
1238
|
-
#
|
|
1239
|
-
#
|
|
1240
|
-
#
|
|
1241
|
-
# run.
|
|
1260
|
+
# Every remaining post-analysis stream `#assemble_run_diagnostics` appends — the `rbs.coverage.*`
|
|
1261
|
+
# build-failure ladder (widest consequence first: quarantine, env build, definition build #696, HKT scan
|
|
1262
|
+
# #784), its notices, the conformance rows, the reporter streams, the plugin run disclosures (#1051)
|
|
1263
|
+
# and, last, the trust-refusal envelope (#959) — in the contract order ADR-116 WD3's
|
|
1264
|
+
# {RunLevelFacts} declares. Read after `analyze_targets`, so every worker payload has been merged.
|
|
1242
1265
|
def post_analysis_diagnostic_streams
|
|
1243
|
-
|
|
1244
|
-
diagnostics += @diagnostic_aggregator.rbs_environment_build_failed_diagnostics
|
|
1245
|
-
# Issue #696 — after its env-wide twin and before the synthesized-namespace notice: the four
|
|
1246
|
-
# `rbs.coverage.*` build conditions surface widest-consequence first, and their relative order is
|
|
1247
|
-
# the diagnostic output contract.
|
|
1248
|
-
diagnostics += @diagnostic_aggregator.rbs_definition_build_failed_diagnostics
|
|
1249
|
-
# Issue #784 — last of the four, deliberately: it loses only the IMPLICIT HKT registrations a
|
|
1250
|
-
# `type` alias would have contributed, never a class's own declared method surface, so it is the
|
|
1251
|
-
# narrowest-consequence rung on the same ladder.
|
|
1252
|
-
diagnostics += @diagnostic_aggregator.rbs_hkt_scan_failed_diagnostics
|
|
1253
|
-
# The synthesized-namespace notice, then (#610) the plugin-signature stand-down: the outcome that
|
|
1254
|
-
# AVOIDED a definition-build failure, so the quietest row on that ladder.
|
|
1255
|
-
diagnostics += @diagnostic_aggregator.rbs_coverage_notice_diagnostics
|
|
1256
|
-
diagnostics += @diagnostic_aggregator.conforms_to_diagnostics
|
|
1257
|
-
diagnostics += @diagnostic_aggregator.rbs_extended_reporter_diagnostics
|
|
1258
|
-
diagnostics += @diagnostic_aggregator.boundary_cross_diagnostics
|
|
1259
|
-
diagnostics += @diagnostic_aggregator.source_rbs_synthesis_diagnostics
|
|
1260
|
-
# Issue #1051 — read after `analyze_targets` for the same reason the refusal stream below is: a
|
|
1261
|
-
# plugin may register a disclosure from `#prepare` (the usual case) or while analysing a file, and
|
|
1262
|
-
# both have to be in before the table is harvested. Ordered before the refusals so the run-level
|
|
1263
|
-
# plugin rows read plugin-authored notice first, engine-authored envelope second.
|
|
1264
|
-
diagnostics += @diagnostic_aggregator.plugin_run_disclosure_diagnostics
|
|
1265
|
-
# Issue #959 — read LAST (after `analyze_targets`, which already ran before this method is called),
|
|
1266
|
-
# so every per-file plugin call has had its chance to record a refusal on its (per-plugin-instance
|
|
1267
|
-
# memoised) `IoBoundary`, alongside the prepare-time refusals the same boundary instance may
|
|
1268
|
-
# already carry.
|
|
1269
|
-
diagnostics + @diagnostic_aggregator.plugin_trust_refusal_diagnostics
|
|
1266
|
+
@diagnostic_aggregator.run_level_diagnostics
|
|
1270
1267
|
end
|
|
1271
1268
|
private :post_analysis_diagnostic_streams
|
|
1272
1269
|
|
|
@@ -1583,7 +1580,9 @@ module Rigor
|
|
|
1583
1580
|
# change time it cannot read, and passes over a `pinned` one.
|
|
1584
1581
|
BaselineRows = Data.define(:owned, :pinned)
|
|
1585
1582
|
|
|
1586
|
-
|
|
1583
|
+
# A loader's two readers {Cache::RbsDescriptor} takes signature roots from. `core_root` (issue #2517) is the
|
|
1584
|
+
# selected core, which the slot key names by path only, so its files are `owned` rows like the project's own.
|
|
1585
|
+
SignatureRoots = Struct.new(:signature_paths, :core_root)
|
|
1587
1586
|
private_constant :SignatureRoots
|
|
1588
1587
|
|
|
1589
1588
|
# @param files — the run's analysed-path set.
|
|
@@ -1604,8 +1603,9 @@ module Rigor
|
|
|
1604
1603
|
|
|
1605
1604
|
# The signature tree's rows, the project's own and the rest.
|
|
1606
1605
|
def signature_rows
|
|
1607
|
-
roots = SignatureRoots.new(@snapshots.signature_paths)
|
|
1608
|
-
own = signature_root_candidates
|
|
1606
|
+
roots = SignatureRoots.new(@snapshots.signature_paths, @configuration.core_root)
|
|
1607
|
+
own = (signature_root_candidates + [@configuration.core_root].compact)
|
|
1608
|
+
.map { |root| File.join(File.absolute_path(root.to_s), "") }
|
|
1609
1609
|
own_files, other_files = Cache::RbsDescriptor.file_entries(roots, comparator: :stat)
|
|
1610
1610
|
.partition { |row| within?(row.path, own) }
|
|
1611
1611
|
own_globs, other_globs = Cache::RbsDescriptor.glob_entries(roots).partition { |row| within?(row.root, own) }
|
|
@@ -2056,8 +2056,7 @@ module Rigor
|
|
|
2056
2056
|
# Editor mode § "Scope choice — option A". Under `buffer:` non-nil the per-file analysis emits
|
|
2057
2057
|
# diagnostics ONLY for the buffer's logical path; the rest of `paths:` is consumed by the
|
|
2058
2058
|
# project-wide pre-passes (synthetic methods, project-patched methods, plugin facts) but contributes
|
|
2059
|
-
# no per-file diagnostics.
|
|
2060
|
-
# (full project + incremental cache) is queued.
|
|
2059
|
+
# no per-file diagnostics. Option B (#146) narrows to the closure instead; see {#target_files}.
|
|
2061
2060
|
#
|
|
2062
2061
|
# The buffer's logical path is added to the file list even if it's not under `paths:` — per design §
|
|
2063
2062
|
# "Failure envelope": "--instead-of=Y with Y not under any paths: directory → treated as a valid
|
|
@@ -2090,7 +2089,13 @@ module Rigor
|
|
|
2090
2089
|
# The logical path joins even when it is not on disk under `paths:` (design § "Failure envelope"),
|
|
2091
2090
|
# the same allowance option A makes below.
|
|
2092
2091
|
files = files.select { |path| @analyze_only.include?(path) }
|
|
2093
|
-
|
|
2092
|
+
# Issue #2233 — a buffer that is a claimed template joins as its unit, appended by
|
|
2093
|
+
# {#template_unit_targets}, never as a `.rb` file: the logical path in its absolute spelling would
|
|
2094
|
+
# otherwise analyse the same template twice. The registry is loaded by now, which is why the test is here
|
|
2095
|
+
# and not in the incremental session, where it is not.
|
|
2096
|
+
if @buffer && @analyze_only.include?(@buffer.logical_path) && !template_path?(@buffer.logical_path)
|
|
2097
|
+
files |= [@buffer.logical_path]
|
|
2098
|
+
end
|
|
2094
2099
|
return template_unit_targets(files)
|
|
2095
2100
|
end
|
|
2096
2101
|
return template_unit_targets(files) if @buffer.nil?
|
|
@@ -2126,6 +2131,14 @@ module Rigor
|
|
|
2126
2131
|
end
|
|
2127
2132
|
public :template_unit_paths
|
|
2128
2133
|
|
|
2134
|
+
# Issue #2233 — whether `path` is a template of this run: a claimed glob matches it, or it names a unit. The
|
|
2135
|
+
# runner keeps the buffer's logical path out of the targets when this is true, so a template buffer is
|
|
2136
|
+
# analysed once, as a unit ({#template_unit_targets} appends it), and never also as a plain `.rb` file.
|
|
2137
|
+
def template_path?(path)
|
|
2138
|
+
template_units.claims?(path) ||
|
|
2139
|
+
template_unit_paths.include?(Analysis::TemplateUnitPaths.relative(path, Dir.pwd))
|
|
2140
|
+
end
|
|
2141
|
+
|
|
2129
2142
|
# Editor mode (`buffer:` non-nil) auto-flips the cache store to `read_only: true` so multiple
|
|
2130
2143
|
# debounced editor invocations against the same project don't churn the on-disk cache or race on
|
|
2131
2144
|
# schema-version writes. Cache reads continue unchanged; misses still run the producer block but the
|
|
@@ -2179,14 +2192,7 @@ module Rigor
|
|
|
2179
2192
|
pool_mode: -> { pool_mode? },
|
|
2180
2193
|
cached_plugin_prepare_diagnostics: -> { @cached_plugin_prepare_diagnostics },
|
|
2181
2194
|
pre_eval_diagnostics_from_scanner: -> { @pre_eval_diagnostics_from_scanner },
|
|
2182
|
-
|
|
2183
|
-
quarantined_signatures_snapshot: -> { @snapshots.quarantined_signatures },
|
|
2184
|
-
signature_standdowns_snapshot: -> { @snapshots.signature_standdowns },
|
|
2185
|
-
vendored_standdowns_snapshot: -> { @snapshots.vendored_standdowns },
|
|
2186
|
-
env_build_failure_snapshot: -> { @snapshots.env_build_failure },
|
|
2187
|
-
definition_build_failures_snapshot: -> { @snapshots.definition_build_failures },
|
|
2188
|
-
hkt_scan_failure_snapshot: -> { @snapshots.hkt_scan_failure },
|
|
2189
|
-
conformance_results_snapshot: -> { @snapshots.conformance_results },
|
|
2195
|
+
snapshots: @snapshots,
|
|
2190
2196
|
pooled_run_disclosures: -> { @pool_coordinator.collected_run_disclosures },
|
|
2191
2197
|
served_run_disclosures: -> { @served_run_disclosures },
|
|
2192
2198
|
pooled_trust_refusals: -> { @pool_coordinator.collected_trust_refusals }
|
|
@@ -2520,14 +2526,14 @@ module Rigor
|
|
|
2520
2526
|
@discovery_seed ? @discovery_seed.dup : {}
|
|
2521
2527
|
end
|
|
2522
2528
|
|
|
2523
|
-
# Seeds the
|
|
2524
|
-
#
|
|
2525
|
-
#
|
|
2529
|
+
# Seeds the parameter-inference and constant-publication tables, so a pooled `WorkerSession` scope resolves
|
|
2530
|
+
# identically to the sequential path (ADR-15 sequential equivalence). The parameter-inference table is absent
|
|
2531
|
+
# unless its opt-in ran; the constant tables are seeded whenever the run has project constants.
|
|
2526
2532
|
#
|
|
2527
2533
|
# - ADR-67 WD6a `param_inferred_types`: the call-site parameter-inference table, populated only when the
|
|
2528
2534
|
# `parameter_inference:` gate ran the pre-pass.
|
|
2529
|
-
# - Issue #352 `in_source_constants`: the `pre_eval:` constant publication,
|
|
2530
|
-
#
|
|
2535
|
+
# - Issue #352 `in_source_constants`: the `pre_eval:` constant publication, merged with the project's
|
|
2536
|
+
# literal constant table (#644, see {#merged_seed_constants}).
|
|
2531
2537
|
#
|
|
2532
2538
|
# Extracted to keep {#project_scope_seed_tables} under the complexity budget.
|
|
2533
2539
|
def seed_opt_in_pre_pass_tables(tables)
|
|
@@ -18,7 +18,7 @@ module Rigor
|
|
|
18
18
|
# recompute" lesson applied to self-calls.
|
|
19
19
|
#
|
|
20
20
|
# ADR-24 slice 4 (`call.self-undefined-method`) consumes the recorded misses behind a confidently-closed-class
|
|
21
|
-
# gate (see `CheckRules`
|
|
21
|
+
# gate (see `CheckRules`). The rule ships `:off` by default — {active?} is false on a normal run, so
|
|
22
22
|
# the instrumented choke-point pays a single integer read and records nothing. Recording is purely
|
|
23
23
|
# observational; it never changes a diagnostic.
|
|
24
24
|
#
|
|
@@ -173,9 +173,8 @@ module Rigor
|
|
|
173
173
|
# copies one tag body once, and the second `@author` is the same copy seen from the other end, not a
|
|
174
174
|
# second reading. Only a node OUTSIDE the winning run's own compiled span counts, which is what keeps
|
|
175
175
|
# the busy lines of a real view answerable while the cross-tag repeat (`<%= v %> <%= v.to_s %>`, or
|
|
176
|
-
# `<%= v %><%= "v" %>` probed at the STRING's `v`) still declines
|
|
177
|
-
# span would answer instead
|
|
178
|
-
# (see the PR), and the follow-up this rule is deliberately conservative ahead of.
|
|
176
|
+
# `<%= v %><%= "v" %>` probed at the STRING's `v`) still declines. That family is what a plugin-exported
|
|
177
|
+
# tag span would answer instead, and it is the follow-up this rule is deliberately conservative ahead of.
|
|
179
178
|
#
|
|
180
179
|
# `spill` is the nearest NON-BLANK compiled line above this template line's own, where a hoisted
|
|
181
180
|
# leading-text literal lives. Only a string literal the run does NOT contain counts there. A code
|
|
@@ -189,6 +189,15 @@ module Rigor
|
|
|
189
189
|
@entries.keys.sort
|
|
190
190
|
end
|
|
191
191
|
|
|
192
|
+
# Issue #2233 — whether a plugin claims `path` by one of its `template_globs:`, in any spelling a caller holds it
|
|
193
|
+
# (absolute, `./`-prefixed, relative). A claimed template is analysed as a unit, never as a plain `.rb` file, so
|
|
194
|
+
# the runner keeps the buffer's logical path out of the `.rb` targets, so it is not analysed twice.
|
|
195
|
+
def claims?(path)
|
|
196
|
+
return false if @claimed_globs.empty?
|
|
197
|
+
|
|
198
|
+
TemplateUnitPaths.claims?(@claimed_globs, TemplateUnitPaths.relative(path, @root))
|
|
199
|
+
end
|
|
200
|
+
|
|
192
201
|
def [](path)
|
|
193
202
|
entry_for(path)
|
|
194
203
|
end
|
|
@@ -293,7 +302,6 @@ module Rigor
|
|
|
293
302
|
[entry.locals.keys.map(&:to_sym)]
|
|
294
303
|
end
|
|
295
304
|
|
|
296
|
-
# The `view:<logical_name>` effect-unit key for a path, or nil.
|
|
297
305
|
# The file whose bytes a unit's path was READ from: the editor's buffer when one is bound to it, the
|
|
298
306
|
# project file otherwise. Read by the run's dependency descriptor, so it digests what the run read.
|
|
299
307
|
def physical_path(path, buffer)
|
|
@@ -25,6 +25,7 @@ require_relative "dependency_source_inference"
|
|
|
25
25
|
require_relative "diagnostic"
|
|
26
26
|
require_relative "erb_template_detector"
|
|
27
27
|
require_relative "template_units"
|
|
28
|
+
require_relative "runner/run_level_facts"
|
|
28
29
|
|
|
29
30
|
module Rigor
|
|
30
31
|
module Analysis
|
|
@@ -39,8 +40,8 @@ module Rigor
|
|
|
39
40
|
# - `configuration` — Phase 2a ({Rigor::Configuration} is `Ractor.shareable?`).
|
|
40
41
|
# - `cache_store` — the fork backend passes the parent runner's pre-built Store (`cache_store:
|
|
41
42
|
# @cache_store` in PoolCoordinator); workers share it rather than building their own at `cache_root`.
|
|
42
|
-
# - `plugin_blueprints` — Phase 3a (`
|
|
43
|
-
# - `explain` —
|
|
43
|
+
# - `plugin_blueprints` — Phase 3a (a list of `Plugin::Blueprint` is `Ractor.shareable?`).
|
|
44
|
+
# - `explain` — a flag.
|
|
44
45
|
# - `synthetic_method_index` / `project_patched_methods` / `project_scope_seed` — optional (default `nil`
|
|
45
46
|
# / `{}`). NOT `Ractor.shareable?` (the seed tables carry Prism def nodes), so the Ractor pool path
|
|
46
47
|
# leaves them unset; the fork backend (ADR-15 Amendment), which builds the session pre-fork on the
|
|
@@ -109,7 +110,7 @@ module Rigor
|
|
|
109
110
|
# above: a worker and the parent agree without a flag to keep in sync.
|
|
110
111
|
@effect_attribution = Effects::Attribution.build(configuration.effects_attribution)
|
|
111
112
|
@file_effects = {}
|
|
112
|
-
# ADR-32 WD4 — full project file list (frozen
|
|
113
|
+
# ADR-32 WD4 — full project file list (frozen) for env-build-time invocation of any
|
|
113
114
|
# loaded plugin's `source_rbs_synthesizer` callable.
|
|
114
115
|
@source_files = source_files
|
|
115
116
|
# #392 — the run's template units, synthesised on the PARENT before the fork and inherited here as
|
|
@@ -162,7 +163,7 @@ module Rigor
|
|
|
162
163
|
end
|
|
163
164
|
|
|
164
165
|
# Equivalent of {Rigor::Analysis::Runner#analyze_file} + `plugin_emitted_diagnostics` +
|
|
165
|
-
# `explain_diagnostics`. Returns a flat
|
|
166
|
+
# `explain_diagnostics`. Returns a flat list of diagnostics for the file. Severity profile re-stamping
|
|
166
167
|
# is intentionally NOT applied — that is a per-run aggregate concern handled by the caller. When
|
|
167
168
|
# `record_dependencies:` was set, wraps the analysis in a {DependencyRecorder} window (ADR-46) so the
|
|
168
169
|
# worker captures the file's cross-file reads for {#drain_dependencies}; the recorder's own disabled
|
|
@@ -271,7 +272,7 @@ module Rigor
|
|
|
271
272
|
# definition and never enters the failing build; a diagnostic wired off the parent's loader would
|
|
272
273
|
# appear at `--workers=0` and vanish at `--workers=N`, which is the same "reports less depending on
|
|
273
274
|
# how you ran it" defect the diagnostic exists to end. Draining it out of the workers is what makes
|
|
274
|
-
# the two paths say the same thing. The payload is
|
|
275
|
+
# the two paths say the same thing. The payload is a list of plain tuples —
|
|
275
276
|
# Marshal-clean for the fork backend and shareable for the Ractor one.
|
|
276
277
|
#
|
|
277
278
|
# Issue #784 — `hkt_scan_failure` rides the same channel for the same reason: the PARENT's own
|
|
@@ -284,33 +285,25 @@ module Rigor
|
|
|
284
285
|
# project whose `sig/` produced a single such event killed each worker HERE — after its files were
|
|
285
286
|
# analysed — and the run degraded to in-process re-analysis with a `pool-degraded` row. All three
|
|
286
287
|
# streams now carry `(path, line, column)` primitives.
|
|
288
|
+
#
|
|
289
|
+
# ADR-116 WD3 (#1195) — both halves are declared rather than listed here: each reporter snapshots its
|
|
290
|
+
# own streams ({Runner::RunLevelFacts::REPORTERS}), and the `:analysis` facts come from
|
|
291
|
+
# {Runner::RunLevelFacts.drain}, the same read the coordinator makes of an environment it analysed on.
|
|
292
|
+
# The facts are read first: their HKT demand (#784, made once per worker so a worker whose share of
|
|
293
|
+
# files demanded nothing still reports the run's outcome) is what fills the hkt-directive stream (#785).
|
|
294
|
+
# On a worker that analysed a file the demand is a memoised read; the fork backend never hands a worker
|
|
295
|
+
# an empty slice, so no idle worker pays the env load.
|
|
287
296
|
def drain_reporters
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
@
|
|
295
|
-
|
|
296
|
-
rbs_extended: {
|
|
297
|
-
unresolved_payloads: @rbs_extended_reporter.unresolved_payloads,
|
|
298
|
-
lossy_projections: @rbs_extended_reporter.lossy_projections,
|
|
299
|
-
# Issue #785 — the HKT directive stream rides the same channel for the same reason
|
|
300
|
-
# `hkt_scan_failure` does: the directives are read by the registry scan, and under the pool the
|
|
301
|
-
# PARENT never demands that scan, so a diagnostic wired off the parent's reporter would appear
|
|
302
|
-
# at `--workers=0` and vanish at `--workers=N`. The demand above is what fills this.
|
|
303
|
-
hkt_directive_errors: @rbs_extended_reporter.hkt_directive_errors,
|
|
304
|
-
# ADR-109 WD3 — the deprecated-form stream rides the same channel: the payload is read where
|
|
305
|
-
# the annotated method is dispatched, which under the pool is only ever inside a worker.
|
|
306
|
-
deprecated_forms: @rbs_extended_reporter.deprecated_forms
|
|
307
|
-
},
|
|
308
|
-
boundary_cross: @boundary_cross_reporter.entries,
|
|
309
|
-
source_rbs_synthesis: @source_rbs_synthesis_reporter.entries,
|
|
310
|
-
definition_build_failures: @environment&.rbs_loader&.definition_build_failures || [],
|
|
311
|
-
hkt_scan_failure: @environment&.hkt_scan_failure
|
|
312
|
-
}
|
|
297
|
+
facts = Runner::RunLevelFacts.drain(@environment)
|
|
298
|
+
Runner::RunLevelFacts.snapshot_reporters(reporters).merge(facts)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# The per-worker reporter accumulators, by {Runner::RunLevelFacts::REPORTERS} key.
|
|
302
|
+
def reporters
|
|
303
|
+
{ rbs_extended: @rbs_extended_reporter, boundary_cross: @boundary_cross_reporter,
|
|
304
|
+
source_rbs_synthesis: @source_rbs_synthesis_reporter }
|
|
313
305
|
end
|
|
306
|
+
private :reporters
|
|
314
307
|
|
|
315
308
|
# ADR-46 — the per-file {DependencyRecorder::Record}s captured by this session's `#analyze` calls (empty
|
|
316
309
|
# unless `record_dependencies:` was set). Marshal-clean (Data of frozen Sets / String Hashes), so the
|
|
@@ -457,7 +450,7 @@ module Rigor
|
|
|
457
450
|
return nil if gem_name.nil? || gem_name.empty?
|
|
458
451
|
|
|
459
452
|
spec = Gem.loaded_specs[gem_name]
|
|
460
|
-
spec&.full_gem_path
|
|
453
|
+
spec&.full_gem_path
|
|
461
454
|
rescue StandardError
|
|
462
455
|
nil
|
|
463
456
|
end
|
data/lib/rigor/bleeding_edge.rb
CHANGED
|
@@ -9,11 +9,9 @@ module Rigor
|
|
|
9
9
|
# *today's* rules are) and is versioned with the gem, NOT a user-supplied file: the
|
|
10
10
|
# inspectable counterpart to PHPStan's `bleedingEdge` include.
|
|
11
11
|
#
|
|
12
|
-
# The
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# {FEATURES} entry with no engine plumbing — as the first one,
|
|
16
|
-
# `reject-unparseable-signatures`, does.
|
|
12
|
+
# The surface is wired end-to-end (`bleeding_edge:` config, `rigor show-bleedingedge`, the
|
|
13
|
+
# severity-composition hook in {Configuration::SeverityProfile.resolve}), so a *severity*
|
|
14
|
+
# discipline is a single {FEATURES} entry with no engine plumbing.
|
|
17
15
|
#
|
|
18
16
|
# A queued change whose effect is not a severity move — a measurement, an algorithm, or a
|
|
19
17
|
# default that changes while every rule keeps its severity — is a `:behaviour` feature
|
|
@@ -40,7 +38,6 @@ module Rigor
|
|
|
40
38
|
# {Configuration#bleeding_edge_active?}.
|
|
41
39
|
KINDS = %i[severity behaviour].freeze
|
|
42
40
|
|
|
43
|
-
# The severity map a `:behaviour` feature carries: none.
|
|
44
41
|
NO_SEVERITY_OVERRIDES = {}.freeze
|
|
45
42
|
|
|
46
43
|
# One queued change.
|
|
@@ -113,9 +113,8 @@ module Rigor
|
|
|
113
113
|
},
|
|
114
114
|
# ADR-13 § "Canonical type-function additions" — five shape-projection type functions
|
|
115
115
|
# that the `rigor-typescript-utility-types` plugin (and any other plugin that ships a
|
|
116
|
-
# shape-projection vocabulary) maps onto.
|
|
117
|
-
#
|
|
118
|
-
# in slice 5).
|
|
116
|
+
# shape-projection vocabulary) maps onto. Non-shape inputs return the input unchanged;
|
|
117
|
+
# the Resolver records `dynamic.shape.lossy-projection` for them.
|
|
119
118
|
"pick_of" => lambda { |args|
|
|
120
119
|
return nil unless args.size == 2
|
|
121
120
|
|
|
@@ -148,7 +147,7 @@ module Rigor
|
|
|
148
147
|
# `Class[range]` — a numeric class head bounded by a Ruby range literal (ADR-109). The
|
|
149
148
|
# builder receives the `Range` value and returns the carrier, or `nil` when the range is
|
|
150
149
|
# empty or its endpoints are not literals of the head class; `nil` surfaces as the ordinary
|
|
151
|
-
# unresolved-payload diagnostic. `Float`
|
|
150
|
+
# unresolved-payload diagnostic. `Float` builds a `FloatRange` carrier.
|
|
152
151
|
RANGE_HEAD_BUILDERS = {
|
|
153
152
|
"Integer" => lambda { |range|
|
|
154
153
|
lo = range.begin
|
|
@@ -186,8 +185,7 @@ module Rigor
|
|
|
186
185
|
# `Array<Integer>` and returns a `Rigor::Type` (or `nil`). Bounds are signed integer
|
|
187
186
|
# literals. A reversed pair (`min` > `max`) is declined as `nil` like every other shape
|
|
188
187
|
# mismatch, so the caller surfaces `dynamic.rbs-extended.unresolved` at the annotation;
|
|
189
|
-
# `Type::IntegerRange`
|
|
190
|
-
# `internal analyzer error` that abandoned the whole Ruby file.
|
|
188
|
+
# `Type::IntegerRange` would raise on it instead, which must not escape the analyzer.
|
|
191
189
|
PARAMETERISED_INT_BUILDERS = {
|
|
192
190
|
"int" => lambda { |bounds|
|
|
193
191
|
return nil unless bounds.size == 2
|
|
@@ -276,14 +274,14 @@ module Rigor
|
|
|
276
274
|
# grammar:
|
|
277
275
|
#
|
|
278
276
|
# type := simple_name | parametric
|
|
279
|
-
# simple_name := /[a-z][a-z0-
|
|
277
|
+
# simple_name := /[a-z][a-z0-9_-]*/
|
|
280
278
|
# parametric := simple_name '[' type_arg_list ']'
|
|
281
279
|
# | simple_name '<' int_bound_list '>'
|
|
282
280
|
# type_arg_list := type_arg (',' type_arg)*
|
|
283
281
|
# type_arg := range_literal | type | class_name
|
|
284
282
|
# class_name := /[A-Z][A-Za-z0-9_]*(?:::[A-Z][A-Za-z0-9_]*)*/
|
|
285
283
|
# range_literal := endpoint? ('..' | '...') endpoint? (at least one side written)
|
|
286
|
-
# endpoint := signed_int | 'nil'
|
|
284
|
+
# endpoint := signed_int | float_literal | 'nil' | 'Float::INFINITY' | 'Float::MAX'
|
|
287
285
|
# int_bound_list := signed_int (',' signed_int)*
|
|
288
286
|
# signed_int := /-?\d+/
|
|
289
287
|
#
|
|
@@ -62,7 +62,7 @@ module Rigor
|
|
|
62
62
|
# `RBS::VERSION` while Rigor checks itself, rubygems and Bundler internals while it checks
|
|
63
63
|
# CRuby's `lib/` — and that is worse than no answer: identical source would type differently
|
|
64
64
|
# depending on how the analyzer was installed. Removing an ad hoc `Object.const_get` from an
|
|
65
|
-
# analysis path is the same move ADR-4
|
|
65
|
+
# analysis path is the same move ADR-4 already made for predicate narrowing.
|
|
66
66
|
#
|
|
67
67
|
# This module is consulted by `Environment#constant_for_name` BEFORE the RBS
|
|
68
68
|
# constant-type table (widest types) but AFTER in-source constant writes (the user's own
|
|
@@ -8,13 +8,11 @@ module Rigor
|
|
|
8
8
|
# carriers Rigor already ships (`decimal-int-string`, `hex-int-string`,
|
|
9
9
|
# `octal-int-string`, `lowercase-string`, `uppercase-string`, `numeric-string`). See
|
|
10
10
|
# `docs/type-specification/imported-built-in-types.md` for the registry the refinements
|
|
11
|
-
# come from
|
|
12
|
-
# scope of this recogniser.
|
|
11
|
+
# come from.
|
|
13
12
|
#
|
|
14
|
-
# The
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# whenever the named-capture body matches one of the rows in {RULES}.
|
|
13
|
+
# The consumer is `Inference::Narrowing.analyse_match_write`: given `if /(?<year>\d+)/ =~ str;
|
|
14
|
+
# year; end`, `year` narrows to `decimal-int-string` when the named-capture body matches a row
|
|
15
|
+
# in {RULES}, and stays plain `String` otherwise.
|
|
18
16
|
#
|
|
19
17
|
# Recognised body shapes (each row admits the `+` quantifier and the bounded `{n}` /
|
|
20
18
|
# `{n,m}` forms with `n >= 1`):
|
|
@@ -10,7 +10,8 @@ module Rigor
|
|
|
10
10
|
module Cache
|
|
11
11
|
# Cache invalidation descriptor — the typed-slot schema fixed by
|
|
12
12
|
# [`docs/design/20260505-cache-slice-taxonomy.md`](../../../docs/design/20260505-cache-slice-taxonomy.md).
|
|
13
|
-
#
|
|
13
|
+
# Value object, fully immutable after construction. Filesystem reads happen only in the `FileEntry.stat`,
|
|
14
|
+
# `FileEntry.kind` and `GlobEntry.compute` builders and in {#fresh?}. The storage layer
|
|
14
15
|
# ([`Rigor::Cache::Store`](store.rb), v0.0.8 slice 2) consumes descriptors but does not extend them.
|
|
15
16
|
#
|
|
16
17
|
# The descriptor has six slots (`files`, `gems`, `plugins`, `configs`, `dependencies`, `globs`); every slot is
|
|
@@ -462,10 +463,10 @@ module Rigor
|
|
|
462
463
|
|
|
463
464
|
# ADR-45 — re-validates this descriptor's recorded {FileEntry}s against the current filesystem. Used by
|
|
464
465
|
# the record-and-validate run-result cache: a value cached alongside its dependency descriptor is fresh
|
|
465
|
-
# iff every recorded file still matches. Only `files` are checked — non-file inputs (config / gems /
|
|
466
|
+
# iff every recorded file still matches. Only `files` and `globs` are checked — non-file inputs (config / gems /
|
|
466
467
|
# version) belong in the cache *key*, not the validated dependency set — so a descriptor carrying any
|
|
467
468
|
# non-file slot is never considered fresh (it was built wrong for this use). ADR-60 WD3 adds `globs`
|
|
468
|
-
# alongside `files` as a re-validatable slot: a {GlobEntry} is fresh when re-globbing
|
|
469
|
+
# alongside `files` as a re-validatable slot: a {GlobEntry} is fresh when re-globbing
|
|
469
470
|
# reproduces its recorded value. ADR-45 WD1 (#577): an absence row ({FileEntry.absent}) is fresh
|
|
470
471
|
# while its path is still missing — the negative half of the dependency set.
|
|
471
472
|
def fresh?
|
|
@@ -581,8 +582,8 @@ module Rigor
|
|
|
581
582
|
false
|
|
582
583
|
end
|
|
583
584
|
|
|
584
|
-
# ADR-60 WD3 / ADR-87 WD2 —
|
|
585
|
-
#
|
|
585
|
+
# ADR-60 WD3 / ADR-87 WD2 — recomputes the entry's signature over the live tree and compares it. Any
|
|
586
|
+
# failure reads as stale (recompute), never a crash.
|
|
586
587
|
def glob_entry_fresh?(entry)
|
|
587
588
|
GlobEntry.fresh?(entry)
|
|
588
589
|
end
|