rigortype 0.3.7 → 0.3.9
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 +1 -1
- data/data/capability_roles/capability_roles.rbs +36 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +109 -13
- data/docs/handbook/02-everyday-types.md +17 -14
- data/docs/handbook/03-narrowing.md +37 -4
- 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 +14 -1
- data/docs/handbook/11-sig-gen.md +96 -15
- 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 +39 -4
- data/docs/manual/03-configuration.md +11 -0
- data/docs/manual/04-diagnostics.md +12 -1
- data/docs/manual/07-plugins.md +15 -5
- data/docs/manual/08-skills.md +23 -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 +6 -1
- data/docs/manual/18-removing-dead-code.md +10 -8
- data/docs/manual/plugins/rigor-actionpack.md +18 -0
- data/docs/manual/plugins/rigor-activerecord.md +28 -0
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +32 -2
- data/docs/manual/plugins/rigor-rbs-inline.md +42 -1
- data/lib/rigor/analysis/baseline.rb +2 -2
- 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/ivar_write_collector.rb +10 -2
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
- data/lib/rigor/analysis/check_rules/rule_ids.rb +1 -1
- data/lib/rigor/analysis/check_rules/rule_walk.rb +39 -4
- 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/unreachable_clause_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
- data/lib/rigor/analysis/check_rules.rb +200 -32
- data/lib/rigor/analysis/crash_signature.rb +69 -13
- 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 +6 -1
- data/lib/rigor/analysis/incremental.rb +16 -0
- data/lib/rigor/analysis/incremental_session.rb +100 -29
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
- data/lib/rigor/analysis/reachability/graph.rb +3 -5
- data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -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 +2 -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 +4 -1
- data/lib/rigor/analysis/run_cache_key.rb +1 -1
- 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 +316 -40
- data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +9 -10
- data/lib/rigor/analysis/runner/pool_coordinator.rb +430 -77
- data/lib/rigor/analysis/runner/project_pre_passes.rb +12 -6
- data/lib/rigor/analysis/runner/run_snapshots.rb +13 -3
- data/lib/rigor/analysis/runner.rb +200 -43
- data/lib/rigor/analysis/worker_session.rb +36 -12
- data/lib/rigor/bleeding_edge.rb +12 -24
- data/lib/rigor/builtins/hkt_builtins.rb +2 -2
- data/lib/rigor/builtins/imported_refinements.rb +166 -30
- data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
- data/lib/rigor/builtins/regex_refinement.rb +4 -4
- data/lib/rigor/builtins/static_return_refinements.rb +5 -6
- data/lib/rigor/cache/annotation_location.rb +70 -0
- data/lib/rigor/cache/descriptor.rb +58 -20
- data/lib/rigor/cache/engine_source.rb +4 -4
- data/lib/rigor/cache/file_digest.rb +9 -1
- data/lib/rigor/cache/incremental_snapshot.rb +40 -6
- 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 +79 -11
- data/lib/rigor/cache/rbs_environment.rb +8 -4
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +39 -0
- data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +85 -33
- 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 +3 -3
- data/lib/rigor/cli/docs_command.rb +2 -2
- 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 +1 -1
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/prism_colorizer.rb +2 -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 +31 -2
- data/lib/rigor/cli/skill_command.rb +1 -1
- data/lib/rigor/cli/skill_deep_probe.rb +4 -4
- data/lib/rigor/cli/skill_describe.rb +36 -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 +10 -6
- 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 +68 -6
- data/lib/rigor/config_audit.rb +30 -5
- data/lib/rigor/configuration/severity_profile.rb +6 -6
- data/lib/rigor/configuration.rb +43 -4
- data/lib/rigor/effects/attribution.rb +1 -3
- data/lib/rigor/effects/config_envelopes.rb +6 -8
- data/lib/rigor/effects/definition_lines.rb +25 -6
- data/lib/rigor/effects/effect_table.rb +0 -1
- data/lib/rigor/effects/entry_points.rb +0 -2
- data/lib/rigor/effects/envelope_check.rb +8 -8
- data/lib/rigor/effects/envelope_index.rb +5 -8
- data/lib/rigor/effects/framework_units.rb +4 -6
- data/lib/rigor/effects/identity.rb +4 -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/method_key.rb +1 -1
- data/lib/rigor/effects/plugin_facts.rb +4 -6
- data/lib/rigor/effects/propagator.rb +2 -3
- data/lib/rigor/effects/scanner.rb +1 -1
- data/lib/rigor/effects/signature_sources.rb +3 -5
- data/lib/rigor/effects/snapshot.rb +10 -10
- data/lib/rigor/effects/snapshot_diff.rb +1 -1
- data/lib/rigor/effects/unit_scan.rb +10 -10
- data/lib/rigor/effects/unknown_label_check.rb +3 -8
- data/lib/rigor/effects/unknown_label_report.rb +3 -4
- 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 +28 -0
- data/lib/rigor/environment/installed_gem_set.rb +85 -0
- data/lib/rigor/environment/lockfile_resolver.rb +51 -4
- 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 +613 -113
- data/lib/rigor/environment.rb +189 -27
- data/lib/rigor/flow_contribution/merger.rb +0 -2
- data/lib/rigor/flow_contribution.rb +11 -13
- data/lib/rigor/inference/acceptance.rb +153 -8
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/body_fixpoint.rb +5 -5
- data/lib/rigor/inference/budget_trace.rb +1 -5
- data/lib/rigor/inference/captured_locals.rb +2 -3
- data/lib/rigor/inference/closure_escape_analyzer.rb +2 -4
- data/lib/rigor/inference/coverage_scanner.rb +4 -6
- data/lib/rigor/inference/dynamic_origin.rb +1 -1
- data/lib/rigor/inference/element_read_widening.rb +168 -0
- data/lib/rigor/inference/expression_typer.rb +763 -143
- data/lib/rigor/inference/fork_map.rb +5 -7
- data/lib/rigor/inference/hkt_reducer.rb +2 -3
- data/lib/rigor/inference/hkt_registry.rb +19 -10
- data/lib/rigor/inference/hkt_sugar_translator.rb +15 -21
- data/lib/rigor/inference/index_write_widening.rb +1 -5
- data/lib/rigor/inference/macro_block_self_type.rb +1 -4
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +2 -9
- 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/file_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +2 -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/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 +61 -47
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +165 -31
- 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/set_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +1 -1
- 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 +4 -5
- 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 +12 -13
- data/lib/rigor/inference/method_parameter_binder.rb +4 -6
- data/lib/rigor/inference/multi_target_binder.rb +1 -3
- data/lib/rigor/inference/mutation_rejoin.rb +168 -0
- data/lib/rigor/inference/mutation_widening.rb +100 -51
- data/lib/rigor/inference/narrowing.rb +299 -46
- data/lib/rigor/inference/optimistic_origin.rb +1 -7
- data/lib/rigor/inference/origin_lookup.rb +2 -3
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +6 -5
- data/lib/rigor/inference/precision_scanner.rb +3 -4
- data/lib/rigor/inference/project_patched_methods.rb +2 -2
- data/lib/rigor/inference/project_patched_scanner.rb +3 -3
- 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 +3 -3
- data/lib/rigor/inference/refinement_mutation.rb +72 -0
- data/lib/rigor/inference/scope_indexer.rb +688 -151
- data/lib/rigor/inference/statement_evaluator.rb +221 -50
- data/lib/rigor/inference/string_mutation.rb +60 -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/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 +1 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +4 -4
- 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 +2 -2
- data/lib/rigor/language_server/incremental_sync.rb +6 -6
- data/lib/rigor/language_server/project_context.rb +2 -5
- 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/plugin/base.rb +90 -21
- data/lib/rigor/plugin/bundled_catalog.rb +167 -0
- data/lib/rigor/plugin/effect_attribution.rb +7 -7
- 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 +31 -12
- 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 +23 -1
- data/lib/rigor/plugin/registry.rb +67 -14
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +12 -1
- data/lib/rigor/plugin/trust_policy.rb +2 -4
- data/lib/rigor/plugin/type_node_resolver.rb +3 -3
- 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 +11 -11
- data/lib/rigor/protection/kill_signature.rb +2 -4
- data/lib/rigor/protection/measurement_integrity.rb +1 -3
- data/lib/rigor/protection/mutation_cache.rb +6 -9
- 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 +12 -13
- data/lib/rigor/rbs_extended/hkt_directives.rb +16 -1
- data/lib/rigor/rbs_extended/reporter.rb +122 -16
- data/lib/rigor/rbs_extended.rb +67 -22
- data/lib/rigor/reflection/constant_path.rb +126 -0
- data/lib/rigor/reflection.rb +26 -10
- data/lib/rigor/runtime/jit.rb +6 -8
- data/lib/rigor/scope/discovery_index.rb +30 -0
- data/lib/rigor/scope.rb +203 -4
- data/lib/rigor/sig_gen/generator.rb +181 -102
- 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/observation_collector.rb +17 -15
- 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 +17 -11
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +111 -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/writer.rb +23 -6
- 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 +2 -5
- 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 +68 -5
- data/lib/rigor/type/data_class.rb +2 -2
- data/lib/rigor/type/data_instance.rb +4 -4
- data/lib/rigor/type/float_range.rb +128 -0
- data/lib/rigor/type/hash_shape.rb +5 -5
- data/lib/rigor/type/integer_range.rb +13 -8
- data/lib/rigor/type/nominal.rb +8 -2
- data/lib/rigor/type/refined.rb +3 -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/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.rb +1 -0
- 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 +1 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +33 -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.rb +28 -2
- data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -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 +1 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +3 -4
- 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 +42 -7
- data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +1 -0
- 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 +119 -14
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +1 -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 +1 -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.rb +36 -4
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +6 -3
- 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 +0 -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 +1 -0
- 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 +1 -0
- 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 +1 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +3 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +2 -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 +1 -0
- 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.rb +128 -3
- 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 +1 -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 +1 -0
- 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 +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +5 -5
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
- data/sig/rigor/cache.rbs +2 -3
- data/sig/rigor/environment.rbs +11 -0
- data/sig/rigor/inference.rbs +3 -10
- data/sig/rigor/plugin/io_boundary.rbs +4 -0
- data/sig/rigor/plugin/manifest.rbs +2 -1
- data/sig/rigor/reflection.rbs +3 -1
- data/sig/rigor/scope.rbs +24 -3
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +14 -0
- data/sig/rigor/type.rbs +27 -1
- data/sig/rigor.rbs +1 -0
- data/skills/rigor-ask/SKILL.md +8 -6
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +13 -2
- data/skills/rigor-project-init/SKILL.md +6 -3
- data/skills/rigor-project-init/references/02-configure.md +10 -6
- data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
- data/skills/rigor-type-oracle/SKILL.md +228 -0
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +261 -0
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +128 -0
- data/skills/rigor-unused-adjudicate/SKILL.md +8 -5
- metadata +28 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
|
@@ -43,9 +43,9 @@ module Rigor
|
|
|
43
43
|
RACY_WINDOW_NS = 2_000_000_000
|
|
44
44
|
private_constant :RACY_WINDOW_NS
|
|
45
45
|
|
|
46
|
-
# @param cache_path
|
|
46
|
+
# @param cache_path — the configuration's cache root; nil or empty is an inert
|
|
47
47
|
# cache (every fetch computes, nothing persists).
|
|
48
|
-
# @param target_ruby
|
|
48
|
+
# @param target_ruby — parse-affecting configuration, part of the identity.
|
|
49
49
|
def self.open(cache_path, target_ruby: nil)
|
|
50
50
|
return new(path: nil, header: nil) if cache_path.nil? || cache_path.to_s.empty?
|
|
51
51
|
|
|
@@ -26,8 +26,8 @@ module Rigor
|
|
|
26
26
|
module SignatureScan
|
|
27
27
|
module_function
|
|
28
28
|
|
|
29
|
-
# @param file
|
|
30
|
-
# @return
|
|
29
|
+
# @param file — path to a `.rbs` file.
|
|
30
|
+
# @return one file-level reference per distinct referenced name. Empty when the
|
|
31
31
|
# file cannot be read or parsed — a broken signature is the analyzer's business, not this scan's.
|
|
32
32
|
def call(file)
|
|
33
33
|
_, _, decls = ::RBS::Parser.parse_signature(::RBS::Buffer.new(name: file, content: File.read(file)))
|
|
@@ -7,7 +7,7 @@ module Rigor
|
|
|
7
7
|
class Result
|
|
8
8
|
attr_reader :diagnostics, :stats
|
|
9
9
|
|
|
10
|
-
# @param stats
|
|
10
|
+
# @param stats — end-of-run telemetry (target file count, RBS class
|
|
11
11
|
# breakdown, wall + RSS) collected by the Runner. Nil when stats collection wasn't requested or wasn't
|
|
12
12
|
# applicable (early-exit paths like `validate_target_ruby` failure).
|
|
13
13
|
def initialize(diagnostics: [], stats: nil)
|
|
@@ -43,8 +43,6 @@ module Rigor
|
|
|
43
43
|
|
|
44
44
|
# The diagnostics {#crashed?} answers true for, so a caller can name what it saw rather than only that
|
|
45
45
|
# it saw something.
|
|
46
|
-
#
|
|
47
|
-
# @return [Array<Rigor::Analysis::Diagnostic>]
|
|
48
46
|
def crash_diagnostics
|
|
49
47
|
diagnostics.select { |diagnostic| CrashSignature.discards_file_analysis?(diagnostic) }
|
|
50
48
|
end
|
|
@@ -642,7 +642,10 @@ module Rigor
|
|
|
642
642
|
"Later write is `nil` — the `@cache = nil` clear-idiom is allowlisted.",
|
|
643
643
|
"Either side is Union / Dynamic / IntegerRange / a shape-varied carrier.",
|
|
644
644
|
"Writes live in different classes that happen to share an ivar name.",
|
|
645
|
-
"Writes are in `def self.foo`
|
|
645
|
+
"Writes are in a singleton body — `def self.foo` or a `class << self` def — those track " \
|
|
646
|
+
"separately.",
|
|
647
|
+
"Writes are in a `def` inside an anonymous-class factory block (`Class.new do … end`, " \
|
|
648
|
+
"`Module.new`, `Struct.new`, `Data.define`): that body defines another class."
|
|
646
649
|
],
|
|
647
650
|
suppression: "`# rigor:disable ivar-write-mismatch` on the offending write.",
|
|
648
651
|
severity_authored: :error,
|
|
@@ -80,7 +80,7 @@ module Rigor
|
|
|
80
80
|
# collecting project's path-set churn is the same churn, and over-evicting costs one recompute.
|
|
81
81
|
EFFECTS_GENERATION_CAP = GENERATION_CAP
|
|
82
82
|
|
|
83
|
-
# @param rbs_config_entries
|
|
83
|
+
# @param rbs_config_entries — the RBS-derived config slots
|
|
84
84
|
# (`rbs.libraries` [+ `rbs.virtual_rbs`]). nil on any failure so a malformed key disables the cache.
|
|
85
85
|
def descriptor(configuration:, files:, explain:, rbs_config_entries:)
|
|
86
86
|
Cache::Descriptor.new(
|
|
@@ -51,17 +51,15 @@ module Rigor
|
|
|
51
51
|
# serves it instead. The decline is measured against the declarations alone, never against what they
|
|
52
52
|
# would judge to, so it costs one glob and never a wrong answer.
|
|
53
53
|
class RunCacheProbe
|
|
54
|
-
# @param
|
|
55
|
-
# @param cache_root [String]
|
|
56
|
-
# @param explain [Boolean] the `--explain` flag (folded into the key, as the runner does).
|
|
54
|
+
# @param explain — the `--explain` flag (folded into the key, as the runner does).
|
|
57
55
|
def initialize(configuration:, cache_root:, explain:)
|
|
58
56
|
@configuration = configuration
|
|
59
57
|
@cache_root = cache_root
|
|
60
58
|
@explain = explain
|
|
61
59
|
end
|
|
62
60
|
|
|
63
|
-
# @param paths
|
|
64
|
-
# @return
|
|
61
|
+
# @param paths — the analysis roots (`@argv` or `configuration.paths`).
|
|
62
|
+
# @return the cached run result with the severity profile applied and no stats
|
|
65
63
|
# (matching a cache-served `Runner#run`), or nil to DECLINE — a miss / stale / unavailable cache — so
|
|
66
64
|
# the caller loads the engine and runs the full path. Any failure declines rather than raising: the
|
|
67
65
|
# probe must never turn a servable run into a crash.
|
|
@@ -66,7 +66,7 @@ module Rigor
|
|
|
66
66
|
# via `RIGOR_LSP_POOL_MIN_BATCH` (mirrors `RIGOR_RACTOR_WORKERS`'s override shape).
|
|
67
67
|
DEFAULT_MIN_BATCH_SIZE = 16
|
|
68
68
|
|
|
69
|
-
# @return
|
|
69
|
+
# @return `RIGOR_LSP_POOL_MIN_BATCH` when set to a non-empty value, else
|
|
70
70
|
# {DEFAULT_MIN_BATCH_SIZE}.
|
|
71
71
|
def self.resolve_min_batch_size
|
|
72
72
|
env_value = ENV.fetch("RIGOR_LSP_POOL_MIN_BATCH", nil)
|
|
@@ -75,19 +75,17 @@ module Rigor
|
|
|
75
75
|
Integer(env_value)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
# @param
|
|
79
|
-
# @param cache_store [Rigor::Cache::Store, nil]
|
|
80
|
-
# @param environment [Rigor::Environment] the warm, shared per-session Environment
|
|
78
|
+
# @param environment — the warm, shared per-session Environment
|
|
81
79
|
# (`ProjectContext#environment`) every job's Runner reuses instead of rebuilding.
|
|
82
|
-
# @param prebuilt
|
|
80
|
+
# @param prebuilt — the warm, shared pre-pass snapshot
|
|
83
81
|
# (`ProjectContext#project_scan`) every job's Runner adopts instead of re-scanning.
|
|
84
|
-
# @param workers
|
|
82
|
+
# @param workers — pool size. `#analyze` degrades to sequential in-process execution — one
|
|
85
83
|
# job at a time, no `fork` — when fewer than 2 bindings are submitted, fewer than `min_batch_size`
|
|
86
84
|
# bindings are submitted, `workers` is not positive, `fork` is unavailable on this platform, or
|
|
87
85
|
# `cache_store` is nil. The middle two are the fork-pool-is-not-worth-it-yet gate documented on
|
|
88
86
|
# {DEFAULT_MIN_BATCH_SIZE}; the last two mirror
|
|
89
87
|
# {PoolCoordinator#analyze_files_in_pool}'s own fork-pool preconditions.
|
|
90
|
-
# @param min_batch_size
|
|
88
|
+
# @param min_batch_size — see {DEFAULT_MIN_BATCH_SIZE}. Exposed as a constructor param
|
|
91
89
|
# (rather than read from the env internally) purely for spec control; production callers get the
|
|
92
90
|
# resolved default.
|
|
93
91
|
def initialize(configuration:, cache_store:, environment:, prebuilt:, workers:,
|
|
@@ -185,7 +183,7 @@ module Rigor
|
|
|
185
183
|
degraded
|
|
186
184
|
end
|
|
187
185
|
|
|
188
|
-
# @return
|
|
186
|
+
# @return the child's `{index => diagnostics}` payload, or nil when the child exited
|
|
189
187
|
# abnormally or wrote no readable payload. `Marshal.load` is safe here: the blob was written by our
|
|
190
188
|
# own forked child to a temp file we created.
|
|
191
189
|
def fork_worker_payload(status, out_path)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../crash_signature"
|
|
3
4
|
require_relative "../diagnostic"
|
|
4
5
|
require_relative "../severity_stamp"
|
|
5
6
|
|
|
@@ -21,31 +22,36 @@ module Rigor
|
|
|
21
22
|
# end-of-pass snapshots) is read through injected reader procs so this collaborator never calls back
|
|
22
23
|
# into the {Runner} and the read happens at the exact point in the run the original inline read did.
|
|
23
24
|
class DiagnosticAggregator # rubocop:disable Metrics/ClassLength
|
|
24
|
-
# @param
|
|
25
|
-
# @param
|
|
26
|
-
# @param boundary_cross_reporter [DependencySourceInference::BoundaryCrossReporter]
|
|
27
|
-
# @param source_rbs_synthesis_reporter [Plugin::SourceRbsSynthesisReporter]
|
|
28
|
-
# @param plugin_registry [#call] reader returning the current {Plugin::Registry} (varies per run).
|
|
29
|
-
# @param dependency_source_index [#call] reader returning the current
|
|
25
|
+
# @param plugin_registry — reader returning the current {Plugin::Registry} (varies per run).
|
|
26
|
+
# @param dependency_source_index — reader returning the current
|
|
30
27
|
# {DependencySourceInference::Index}.
|
|
31
|
-
# @param pool_mode
|
|
32
|
-
# @param cached_plugin_prepare_diagnostics
|
|
33
|
-
# @param pre_eval_diagnostics_from_scanner
|
|
34
|
-
# @param synthesized_namespaces_snapshot
|
|
35
|
-
# @param quarantined_signatures_snapshot
|
|
28
|
+
# @param pool_mode — reader returning the pool-mode flag.
|
|
29
|
+
# @param cached_plugin_prepare_diagnostics — reader returning the prepare-diagnostic snapshot.
|
|
30
|
+
# @param pre_eval_diagnostics_from_scanner — reader returning the pre-eval scanner diagnostics.
|
|
31
|
+
# @param synthesized_namespaces_snapshot — reader.
|
|
32
|
+
# @param quarantined_signatures_snapshot — reader returning the `signature_paths:` files skipped
|
|
36
33
|
# because they do not parse (`[path, first_error_line]` pairs).
|
|
37
|
-
# @param
|
|
34
|
+
# @param signature_standdowns_snapshot — reader returning the plugin-contributed signature files
|
|
35
|
+
# that stood down against a colliding generic arity (#610), as
|
|
36
|
+
# `[path, class_name, existing_arity, incoming_arity, existing_file]` tuples. Defaults to none so
|
|
37
|
+
# a caller that snapshots nothing of the kind need not say so.
|
|
38
|
+
# @param env_build_failure_snapshot — reader returning the total RBS env-build failure tuple
|
|
38
39
|
# (`[error_class, first_error_line, conflicting_buffer_names]`) or nil when the env built.
|
|
39
|
-
# @param definition_build_failures_snapshot
|
|
40
|
+
# @param definition_build_failures_snapshot — issue #696 — reader returning the per-class
|
|
40
41
|
# `RBS::DefinitionBuilder` failures the run observed, as `[class_name, error_class, member,
|
|
41
42
|
# conflicting_buffer_names]` tuples. Empty for a healthy sig set.
|
|
42
|
-
# @param
|
|
43
|
+
# @param hkt_scan_failure_snapshot — issue #784 — reader returning the `[error_class_name,
|
|
44
|
+
# first_message_line, raw_frame_or_nil, stage]` tuple whichever stage of the HKT-registry build
|
|
45
|
+
# raised, or nil when both built (or were never demanded). `stage` is `:scan` (the RBS `type`-alias
|
|
46
|
+
# scan) or `:overlay` (the plugin-manifest aggregation, #791), and picks the row's wording.
|
|
47
|
+
# @param conformance_results_snapshot — reader.
|
|
43
48
|
def initialize(configuration:, rbs_extended_reporter:, boundary_cross_reporter:, # rubocop:disable Metrics/ParameterLists
|
|
44
49
|
source_rbs_synthesis_reporter:, plugin_registry:, dependency_source_index:,
|
|
45
50
|
pool_mode:, cached_plugin_prepare_diagnostics:,
|
|
46
51
|
pre_eval_diagnostics_from_scanner:, synthesized_namespaces_snapshot:,
|
|
47
52
|
quarantined_signatures_snapshot:, env_build_failure_snapshot:,
|
|
48
|
-
definition_build_failures_snapshot:,
|
|
53
|
+
definition_build_failures_snapshot:, hkt_scan_failure_snapshot:,
|
|
54
|
+
conformance_results_snapshot:, signature_standdowns_snapshot: -> { [] })
|
|
49
55
|
@configuration = configuration
|
|
50
56
|
@rbs_extended_reporter = rbs_extended_reporter
|
|
51
57
|
@boundary_cross_reporter = boundary_cross_reporter
|
|
@@ -57,8 +63,10 @@ module Rigor
|
|
|
57
63
|
@pre_eval_diagnostics_from_scanner_reader = pre_eval_diagnostics_from_scanner
|
|
58
64
|
@synthesized_namespaces_snapshot_reader = synthesized_namespaces_snapshot
|
|
59
65
|
@quarantined_signatures_snapshot_reader = quarantined_signatures_snapshot
|
|
66
|
+
@signature_standdowns_snapshot_reader = signature_standdowns_snapshot
|
|
60
67
|
@env_build_failure_snapshot_reader = env_build_failure_snapshot
|
|
61
68
|
@definition_build_failures_snapshot_reader = definition_build_failures_snapshot
|
|
69
|
+
@hkt_scan_failure_snapshot_reader = hkt_scan_failure_snapshot
|
|
62
70
|
@conformance_results_snapshot_reader = conformance_results_snapshot
|
|
63
71
|
end
|
|
64
72
|
|
|
@@ -315,9 +323,11 @@ module Rigor
|
|
|
315
323
|
# user knows their sig set is malformed (`rbs validate` rejects it) and can fix it at the source.
|
|
316
324
|
# Authored `:info`: the analysis already succeeded; this is advisory, never a gate. Empty for a
|
|
317
325
|
# well-formed sig set.
|
|
318
|
-
# An unparseable `.rbs` under `signature_paths:` is QUARANTINED so the
|
|
319
|
-
#
|
|
320
|
-
#
|
|
326
|
+
# An unparseable or declaration-colliding `.rbs` under `signature_paths:` is QUARANTINED so the
|
|
327
|
+
# rest of the env survives (PR #50; issue #777 extends this to class-vs-module / constant
|
|
328
|
+
# collisions against bundled RBS), which means the types it declares are silently absent — calls
|
|
329
|
+
# into them read `Dynamic[top]`, and the run gets *quieter*, not louder. The stderr banner alone
|
|
330
|
+
# never reached CI:
|
|
321
331
|
# it is not a diagnostic, so it is absent from `--format json` / SARIF / GitHub annotations / the LSP
|
|
322
332
|
# and cannot move the exit code. This puts it in the diagnostic stream where every channel sees it.
|
|
323
333
|
#
|
|
@@ -381,6 +391,25 @@ module Rigor
|
|
|
381
391
|
[build_rbs_definition_build_failed_diagnostic(failures)]
|
|
382
392
|
end
|
|
383
393
|
|
|
394
|
+
# Issue #784 — the fourth rung, narrowest consequence: one of the two builds behind
|
|
395
|
+
# `Environment#hkt_registry` raised instead of building. The `:scan` stage is the implicit HKT scan
|
|
396
|
+
# over RBS `type` aliases (ADR-20 WD2's `%a{rigor:v1:hkt_register / hkt_define}` overlay AND any
|
|
397
|
+
# recursive `type` alias in the project's own `.rbs` or an installed `rbs collection`); analysis
|
|
398
|
+
# proceeds over the PRE-scan registry — bundled builtins (`json::value`, …) plus the plugin overlay
|
|
399
|
+
# — so a `type` alias that would have registered as a type constructor reads its bound
|
|
400
|
+
# (`Dynamic[top]`) instead. The `:overlay` stage (#791) is the plugin-manifest aggregation, which
|
|
401
|
+
# sat ABOVE the seam until the run-owned demands made a raise there abort the run; it degrades one
|
|
402
|
+
# step further in and one step narrower — the plugin entries are dropped, the `.rbs` scan still
|
|
403
|
+
# runs. Either way everything else this run reports is unaffected: no class loses its method
|
|
404
|
+
# surface, no signature file is skipped, the environment builds. That is why this sits LAST on the
|
|
405
|
+
# ladder, after its two `rbs.coverage.*` siblings above.
|
|
406
|
+
def rbs_hkt_scan_failed_diagnostics
|
|
407
|
+
failure = hkt_scan_failure_snapshot
|
|
408
|
+
return [] if failure.nil?
|
|
409
|
+
|
|
410
|
+
[build_rbs_hkt_scan_failed_diagnostic(failure)]
|
|
411
|
+
end
|
|
412
|
+
|
|
384
413
|
def rbs_synthesized_namespace_diagnostics
|
|
385
414
|
synthesized = synthesized_namespaces_snapshot
|
|
386
415
|
return [] if synthesized.nil? || synthesized.empty?
|
|
@@ -388,6 +417,26 @@ module Rigor
|
|
|
388
417
|
[build_rbs_synthesized_namespace_diagnostic(synthesized)]
|
|
389
418
|
end
|
|
390
419
|
|
|
420
|
+
# Issue #610 — the outcome that AVOIDED `rbs.coverage.definition-build-failed`'s rung: a signature
|
|
421
|
+
# file a loaded plugin contributes re-declared a class another loaded source (typically an `rbs
|
|
422
|
+
# collection install`) already declares at a DIFFERENT generic arity, so the plugin's file stood
|
|
423
|
+
# down rather than fail the class's definition build. One `:info` per file: the user is told what
|
|
424
|
+
# typing they are not getting and why, and — unlike the quarantine row this file used to be
|
|
425
|
+
# misreported as — is not sent to remove a declaration the plugin owns.
|
|
426
|
+
def rbs_plugin_signature_stood_down_diagnostics
|
|
427
|
+
standdowns = signature_standdowns_snapshot
|
|
428
|
+
return [] if standdowns.nil? || standdowns.empty?
|
|
429
|
+
|
|
430
|
+
standdowns.map { |entry| build_rbs_plugin_signature_stood_down_diagnostic(entry) }
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
# The two `:info` notices that close the `rbs.coverage.*` ladder, in this order: the namespace
|
|
434
|
+
# synthesis first, then the stand-down (#610) — the outcome that AVOIDED a definition-build failure
|
|
435
|
+
# and so the quietest row on it. One method so the runner's assembly reads them as one slot.
|
|
436
|
+
def rbs_coverage_notice_diagnostics
|
|
437
|
+
rbs_synthesized_namespace_diagnostics + rbs_plugin_signature_stood_down_diagnostics
|
|
438
|
+
end
|
|
439
|
+
|
|
391
440
|
# Maps the per-run `rigor:v1:conforms-to` scan results into diagnostics (spec: `rbs-extended.md` §
|
|
392
441
|
# "Explicit conformance directive"). A class that declares `conforms-to _Interface` but is missing
|
|
393
442
|
# a required interface method surfaces as `rbs_extended.unsatisfied-conformance`; an unresolvable
|
|
@@ -408,16 +457,28 @@ module Rigor
|
|
|
408
457
|
when RbsExtended::ConformanceChecker::IncompatibleSignature
|
|
409
458
|
build_incompatible_signature_diagnostic(record)
|
|
410
459
|
else # UnresolvedInterface
|
|
411
|
-
|
|
412
|
-
record.location,
|
|
413
|
-
rule: "dynamic.rbs-extended.unresolved",
|
|
414
|
-
message: "`#{record.class_name}` declares `conforms-to #{record.interface_name}` but " \
|
|
415
|
-
"interface `#{record.interface_name}` is not loaded. Check for a typo or add " \
|
|
416
|
-
"the `sig`/library that declares it to the RBS load path."
|
|
417
|
-
)
|
|
460
|
+
build_unresolved_conformance_diagnostic(record)
|
|
418
461
|
end
|
|
419
462
|
end
|
|
420
463
|
|
|
464
|
+
# Issue #928 — `:warning`, not the `:info` the other `dynamic.rbs-extended.unresolved` producers
|
|
465
|
+
# stamp. Those report that an inference fell back; this one reports that an assertion the author
|
|
466
|
+
# deliberately wrote is checking NOTHING, and the whole point of `conforms-to` is to be checked. It
|
|
467
|
+
# is not unsolicited either: only a project that wrote the directive can see it. Now that the
|
|
468
|
+
# capability-role catalog ships, the remaining way to reach this row is a name that does not exist.
|
|
469
|
+
def build_unresolved_conformance_diagnostic(record)
|
|
470
|
+
path, line, column = location_fields(record.location)
|
|
471
|
+
Diagnostic.new(
|
|
472
|
+
path: path, line: line, column: column,
|
|
473
|
+
message: "`#{record.class_name}` declares `conforms-to #{record.interface_name}` but " \
|
|
474
|
+
"interface `#{record.interface_name}` is not loaded. Check for a typo or add " \
|
|
475
|
+
"the `sig`/library that declares it to the RBS load path.",
|
|
476
|
+
severity: :warning,
|
|
477
|
+
rule: "dynamic.rbs-extended.unresolved",
|
|
478
|
+
source_family: :builtin
|
|
479
|
+
)
|
|
480
|
+
end
|
|
481
|
+
|
|
421
482
|
def build_unsatisfied_conformance_diagnostic(record)
|
|
422
483
|
path, line, column = location_fields(record.location)
|
|
423
484
|
Diagnostic.new(
|
|
@@ -458,11 +519,12 @@ module Rigor
|
|
|
458
519
|
path: ".rigor.yml",
|
|
459
520
|
line: 1,
|
|
460
521
|
column: 1,
|
|
461
|
-
message: "#{quarantined.size} RBS file(s) under `signature_paths:`
|
|
462
|
-
"
|
|
463
|
-
"loaded, but the types those files declare
|
|
464
|
-
"`Dynamic[top]`, so this run is quieter than it
|
|
465
|
-
"parse error(s)
|
|
522
|
+
message: "#{quarantined.size} RBS file(s) under `signature_paths:` were SKIPPED " \
|
|
523
|
+
"(unparseable, or duplicated against bundled RBS): #{sample.join(', ')}#{suffix}. " \
|
|
524
|
+
"The rest of your RBS environment still loaded, but the types those files declare " \
|
|
525
|
+
"are absent — calls into them read `Dynamic[top]`, so this run is quieter than it " \
|
|
526
|
+
"should be, not cleaner. Fix the parse error(s) or remove the conflicting " \
|
|
527
|
+
"declaration(s) (`rbs validate`) to restore that coverage.",
|
|
466
528
|
severity: :warning,
|
|
467
529
|
rule: "rbs.coverage.quarantined-signature",
|
|
468
530
|
source_family: :builtin
|
|
@@ -515,14 +577,27 @@ module Rigor
|
|
|
515
577
|
"#{first_failure_clause(failures.first)}#{conflicting_files_clause(files, sample_size)} " \
|
|
516
578
|
"Rigor still treats each class as KNOWN, so calls into it — real methods and typos " \
|
|
517
579
|
"alike — silently read `Dynamic[top]` instead of resolving, and this run is quieter " \
|
|
518
|
-
"than it should be rather than cleaner.
|
|
519
|
-
"member; remove the duplicate declaration (`rbs validate`) to restore type coverage.",
|
|
580
|
+
"than it should be rather than cleaner. #{definition_build_advice(failures.first)}",
|
|
520
581
|
severity: :warning,
|
|
521
582
|
rule: "rbs.coverage.definition-build-failed",
|
|
522
583
|
source_family: :builtin
|
|
523
584
|
)
|
|
524
585
|
end
|
|
525
586
|
|
|
587
|
+
# The closing advice follows the FIRST failure's error class: `GenericParameterMismatchError` is two
|
|
588
|
+
# declarations of one CLASS at different generic arity (#610), and "remove the duplicate member"
|
|
589
|
+
# sends its reader after a member that does not exist.
|
|
590
|
+
def definition_build_advice(failure)
|
|
591
|
+
_, error_class, = failure
|
|
592
|
+
if error_class.to_s.end_with?("GenericParameterMismatchError")
|
|
593
|
+
"Two signature sources declare the class with a different number of type parameters; make " \
|
|
594
|
+
"the declarations agree (`rbs validate`) to restore type coverage."
|
|
595
|
+
else
|
|
596
|
+
"Two signature sources declare the same member; remove the duplicate declaration " \
|
|
597
|
+
"(`rbs validate`) to restore type coverage."
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
526
601
|
# `[class_name, error_class, member, buffers]`. The member is nil for the error classes that carry no
|
|
527
602
|
# name at all (`RecursiveAncestorError`), and the clause then names the error class alone rather than
|
|
528
603
|
# inventing a member.
|
|
@@ -550,6 +625,66 @@ module Rigor
|
|
|
550
625
|
"#{sample.join(', ')}#{suffix}"
|
|
551
626
|
end
|
|
552
627
|
|
|
628
|
+
# Issue #784 — one `:error` row per run, unlike its two `:warning` `rbs.coverage.*` siblings above.
|
|
629
|
+
# Those two are typically a collision between the user's OWN `sig/` and Rigor's bundled RBS, so an
|
|
630
|
+
# `:error` default would let a Rigor release turn a green project red with zero user change (ADR-5
|
|
631
|
+
# / AGENTS.md § FP discipline) — the reason both stay `:warning` by default. This row has no such
|
|
632
|
+
# neighbour: post-#783 the scan itself raising is an ANALYZER defect, never something a user's
|
|
633
|
+
# `sig/` could trigger on its own, so there is no green project this could newly redden. And the
|
|
634
|
+
# run was already non-zero before this row existed — issue #784's seam is what stopped the raise
|
|
635
|
+
# from reaching every file as N identical `internal analyzer error` rows in the first place, and
|
|
636
|
+
# THAT per-file rescue is what `Result#success?` was already reading as a failure; this row only
|
|
637
|
+
# makes the reason legible.
|
|
638
|
+
#
|
|
639
|
+
# One row per RUN, not per file: the scan is one build over the whole `signature_paths:` overlay
|
|
640
|
+
# (memoised — see {Environment#hkt_registry}), so every file that would have demanded it hit the
|
|
641
|
+
# exact same failure, and a row per file would say the same thing N times.
|
|
642
|
+
#
|
|
643
|
+
# `:rbs_build` (via {CrashSignature::RBS_BUILD_FAILURE_RULES}), not `:check_rule`: the analysis ran
|
|
644
|
+
# to completion over a DEGRADED type universe — every rule still fired, unlike `:check_rule`'s
|
|
645
|
+
# whole-file replacement — so a consumer gating on {CrashSignature.discards_file_analysis?} must
|
|
646
|
+
# keep reading this run's diagnostics rather than refuse it as a crash.
|
|
647
|
+
def build_rbs_hkt_scan_failed_diagnostic(failure)
|
|
648
|
+
error_class, first_line, frame, stage = failure
|
|
649
|
+
relative_frame = CrashSignature.relativize_frame(frame)
|
|
650
|
+
frame_clause = relative_frame ? " at #{relative_frame}" : ""
|
|
651
|
+
raised = "(#{error_class}): #{first_line}#{frame_clause}."
|
|
652
|
+
Diagnostic.new(
|
|
653
|
+
path: ".rigor.yml",
|
|
654
|
+
line: 1,
|
|
655
|
+
column: 1,
|
|
656
|
+
message: stage == :overlay ? hkt_overlay_failed_message(raised) : hkt_scan_failed_message(raised),
|
|
657
|
+
severity: :error,
|
|
658
|
+
rule: "rbs.coverage.hkt-scan-failed",
|
|
659
|
+
source_family: :builtin
|
|
660
|
+
)
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
def hkt_scan_failed_message(raised)
|
|
664
|
+
"The implicit HKT scan over RBS `type` aliases raised #{raised} Rigor fell back to the bundled " \
|
|
665
|
+
"and plugin HKT registrations, so a recursive `type` alias in your `.rbs` or an installed " \
|
|
666
|
+
"`rbs collection` no longer registers as a type constructor and reads its bound " \
|
|
667
|
+
"(`Dynamic[top]`) instead — this run is quieter than it should be, not cleaner. " \
|
|
668
|
+
"This is an analyzer defect, not a problem with your signatures; please report it " \
|
|
669
|
+
"with the message above."
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
# Issue #791 — the overlay stage of the same build, worded for the plugin it came from. The scan
|
|
673
|
+
# wording would send a user to their `.rbs` for a defect that is not there: what failed is the
|
|
674
|
+
# aggregation of the loaded plugins' manifest-declared HKT entries, and the message names the
|
|
675
|
+
# plugin whenever the raise was attributable to one (`Plugin::Registry#hkt_overlay_registry` puts
|
|
676
|
+
# the id in the message it re-raises). The degradation is narrower than the scan's, so the fallback
|
|
677
|
+
# sentence differs too: only the plugin entries are missing, and the user's own `.rbs` scan still
|
|
678
|
+
# ran on top of the bundled registrations.
|
|
679
|
+
def hkt_overlay_failed_message(raised)
|
|
680
|
+
"Building the plugin HKT overlay raised #{raised} Rigor skipped every plugin-declared HKT " \
|
|
681
|
+
"registration and analysed with the bundled ones plus your own `.rbs` overlay, so a type " \
|
|
682
|
+
"constructor a plugin declares reads its bound (`Dynamic[top]`) instead — this run is " \
|
|
683
|
+
"quieter than it should be, not cleaner. This is a defect in the named plugin or in Rigor, " \
|
|
684
|
+
"not a problem with your signatures; report it with the message above, or remove the plugin " \
|
|
685
|
+
"from `plugins:` to analyse without it."
|
|
686
|
+
end
|
|
687
|
+
|
|
553
688
|
# The absolute path is what the loader records; the user thinks in project-relative terms.
|
|
554
689
|
def relative_signature_path(path)
|
|
555
690
|
root = "#{Dir.pwd}#{File::SEPARATOR}"
|
|
@@ -576,6 +711,42 @@ module Rigor
|
|
|
576
711
|
)
|
|
577
712
|
end
|
|
578
713
|
|
|
714
|
+
def build_rbs_plugin_signature_stood_down_diagnostic(entry)
|
|
715
|
+
path, class_name, existing_arity, incoming_arity, existing_file = entry
|
|
716
|
+
displaced_by = displacing_source_phrase(existing_file)
|
|
717
|
+
Diagnostic.new(
|
|
718
|
+
path: ".rigor.yml",
|
|
719
|
+
line: 1,
|
|
720
|
+
column: 1,
|
|
721
|
+
message: "`#{relative_signature_path(path.to_s)}` (a signature file a plugin contributes) declares " \
|
|
722
|
+
"`#{class_name.to_s.delete_prefix('::')}` with #{type_parameter_phrase(incoming_arity)}, " \
|
|
723
|
+
"but #{displaced_by} already declares it with #{type_parameter_phrase(existing_arity)}. " \
|
|
724
|
+
"Two declarations of one class at different generic arity fail its definition build, so " \
|
|
725
|
+
"the plugin's file stood down: calls into the class resolve against the other " \
|
|
726
|
+
"declaration, and the plugin's element typing for it is unavailable while both are " \
|
|
727
|
+
"loaded. Expected when a bundled plugin and an `rbs collection install` both declare " \
|
|
728
|
+
"the class; nothing to fix unless you want the plugin's typing back, which needs the " \
|
|
729
|
+
"other source to stop declaring the class.",
|
|
730
|
+
severity: :info,
|
|
731
|
+
rule: "rbs.coverage.plugin-signature-stood-down",
|
|
732
|
+
source_family: :builtin
|
|
733
|
+
)
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def displacing_source_phrase(existing_file)
|
|
737
|
+
return "another loaded signature source" if existing_file.nil?
|
|
738
|
+
|
|
739
|
+
"`#{relative_signature_path(existing_file.to_s)}`"
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
def type_parameter_phrase(arity)
|
|
743
|
+
case arity
|
|
744
|
+
when nil, 0 then "no type parameters"
|
|
745
|
+
when 1 then "1 type parameter"
|
|
746
|
+
else "#{arity} type parameters"
|
|
747
|
+
end
|
|
748
|
+
end
|
|
749
|
+
|
|
579
750
|
def build_rbs_coverage_missing_diagnostic(missing)
|
|
580
751
|
sample_size = 5
|
|
581
752
|
sample = missing.first(sample_size).map(&:gem_name)
|
|
@@ -603,16 +774,19 @@ module Rigor
|
|
|
603
774
|
# enable.
|
|
604
775
|
# - `dynamic.shape.lossy-projection` for every shape-projection type function (`pick_of`, …) applied
|
|
605
776
|
# to a carrier that loses precision (anything other than `HashShape` / `Tuple`).
|
|
777
|
+
# - `dynamic.rbs-extended.hkt-directive-invalid` for every malformed ADR-20 `rigor:v1:hkt_register` /
|
|
778
|
+
# `rigor:v1:hkt_define` the directive parser declined (issue #785).
|
|
606
779
|
#
|
|
607
|
-
#
|
|
608
|
-
# column
|
|
609
|
-
#
|
|
780
|
+
# All three are authored `:info`; the severity profile re-stamps them per project taste. Every stream
|
|
781
|
+
# carries its `(path, line, column)` already flattened off the annotation's `RBS::Location`, because
|
|
782
|
+
# all three cross the pool drain channel (see {RbsExtended::Reporter}); an entry with no position
|
|
783
|
+
# falls back to `.rigor.yml`-style file-level attribution.
|
|
610
784
|
def rbs_extended_reporter_diagnostics
|
|
611
785
|
return [] if @rbs_extended_reporter.empty?
|
|
612
786
|
|
|
613
787
|
unresolved = @rbs_extended_reporter.unresolved_payloads.map do |entry|
|
|
614
|
-
|
|
615
|
-
entry
|
|
788
|
+
build_positioned_reporter_diagnostic(
|
|
789
|
+
entry,
|
|
616
790
|
rule: "dynamic.rbs-extended.unresolved",
|
|
617
791
|
message: "`RBS::Extended` directive payload could not be resolved: " \
|
|
618
792
|
"#{entry.payload.inspect}. Check for typos or enable a plugin " \
|
|
@@ -621,8 +795,8 @@ module Rigor
|
|
|
621
795
|
end
|
|
622
796
|
|
|
623
797
|
lossy = @rbs_extended_reporter.lossy_projections.map do |entry|
|
|
624
|
-
|
|
625
|
-
entry
|
|
798
|
+
build_positioned_reporter_diagnostic(
|
|
799
|
+
entry,
|
|
626
800
|
rule: "dynamic.shape.lossy-projection",
|
|
627
801
|
message: "Shape projection `#{entry.head}` applied to a carrier without a " \
|
|
628
802
|
"literal shape; the projection degrades to the input type. Author " \
|
|
@@ -630,7 +804,37 @@ module Rigor
|
|
|
630
804
|
)
|
|
631
805
|
end
|
|
632
806
|
|
|
633
|
-
unresolved + lossy
|
|
807
|
+
unresolved + lossy + hkt_directive_diagnostics + deprecated_form_diagnostics
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
# ADR-109 WD3 — one row per annotation still written in a spelling the grammar accepts but no
|
|
811
|
+
# longer displays. The row names the replacement because the deprecation window exists for exactly
|
|
812
|
+
# this edit, and it stays `:info`: the annotation resolved, the run is as green as it was.
|
|
813
|
+
def deprecated_form_diagnostics
|
|
814
|
+
@rbs_extended_reporter.deprecated_forms.map do |entry|
|
|
815
|
+
build_positioned_reporter_diagnostic(
|
|
816
|
+
entry,
|
|
817
|
+
rule: "dynamic.rbs-extended.deprecated-form",
|
|
818
|
+
message: "`#{entry.payload}` is a deprecated spelling; write `#{entry.replacement}`. The " \
|
|
819
|
+
"angle-bracket integer range is accepted for one deprecation window and removed " \
|
|
820
|
+
"at the next compatibility break (ADR-109)."
|
|
821
|
+
)
|
|
822
|
+
end
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
# Issue #785 — one row per declined HKT directive. The consequence sentence is the point: the parser
|
|
826
|
+
# is fail-soft, so nothing else in the run tells the author that the constructor they registered is
|
|
827
|
+
# not there and that every `App[…]` naming it silently reads its bound.
|
|
828
|
+
def hkt_directive_diagnostics
|
|
829
|
+
@rbs_extended_reporter.hkt_directive_errors.map do |entry|
|
|
830
|
+
build_positioned_reporter_diagnostic(
|
|
831
|
+
entry,
|
|
832
|
+
rule: "dynamic.rbs-extended.hkt-directive-invalid",
|
|
833
|
+
message: "`RBS::Extended` HKT directive was declined: #{entry.message}. The type " \
|
|
834
|
+
"constructor stays unregistered, so an `App[...]` carrier naming it reads " \
|
|
835
|
+
"its bound (`Dynamic[top]`) instead of the type function."
|
|
836
|
+
)
|
|
837
|
+
end
|
|
634
838
|
end
|
|
635
839
|
|
|
636
840
|
# ADR-32 WD6 — drains the per-run {Plugin::SourceRbsSynthesisReporter} into
|
|
@@ -704,6 +908,56 @@ module Rigor
|
|
|
704
908
|
end
|
|
705
909
|
end
|
|
706
910
|
|
|
911
|
+
# Issue #959 — surfaces the {Plugin::IoBoundary} refusal history each loaded plugin accumulated over
|
|
912
|
+
# the whole run (prepare AND every per-file call: `#io_boundary` is memoised per plugin instance, so
|
|
913
|
+
# one boundary sees both). `TrustPolicy#allow_read?` stays `File.expand_path`-only per ADR-2 — a
|
|
914
|
+
# project rooted under a symlink (macOS' `/tmp` → `/private/tmp` is the common case) can have every
|
|
915
|
+
# plugin read fall outside its own read roots with nothing said about it. One `:info` row per plugin
|
|
916
|
+
# that hit this, never one per path, naming the count and the first path so the row stays legible on
|
|
917
|
+
# a plugin that walked a whole out-of-scope subtree.
|
|
918
|
+
#
|
|
919
|
+
# Positioned here, in `#pre_file_diagnostics`'s post-analysis sibling list (called from
|
|
920
|
+
# `Runner#assemble_run_diagnostics`, which only runs on an ADR-45 cache MISS): the refusal history is
|
|
921
|
+
# a function of the plugin code and the resolved paths for THIS configuration, so it is deterministic
|
|
922
|
+
# across runs of the same inputs and the row that lands in a miss's cached diagnostics blob is the
|
|
923
|
+
# row a later warm HIT correctly re-serves — the same regeneration contract every other stream
|
|
924
|
+
# aggregated in `#pre_file_diagnostics` / `#assemble_run_diagnostics` already relies on (see
|
|
925
|
+
# `docs/type-specification/diagnostic-policy.md` § "Run-level rows and the record-and-validate
|
|
926
|
+
# cache"). It is also never routed through `IncrementalSession`'s per-file cache (`#788`): that cache
|
|
927
|
+
# holds only `Runner#per_file_diagnostics`, and this row is not part of that stream.
|
|
928
|
+
#
|
|
929
|
+
# Scope: `plugin_registry` here is the coordinator-side registry, which only actually RUNS `#prepare`
|
|
930
|
+
# / per-file analysis in sequential mode (`--workers` unset, the default) — a pooled run (`--workers
|
|
931
|
+
# N`) prepares and analyses on per-worker `WorkerSession` registries this reader never sees, so a
|
|
932
|
+
# refusal confined to a pooled worker's slice is not reported. Left out deliberately: draining it
|
|
933
|
+
# needs a fourth marshalled channel beside `drain_reporters` / `drain_dependencies` / `drain_effects`
|
|
934
|
+
# in `Runner::PoolCoordinator`, and the default (unpooled) path already covers the reported bug.
|
|
935
|
+
def plugin_trust_refusal_diagnostics
|
|
936
|
+
return [] if plugin_registry.empty?
|
|
937
|
+
|
|
938
|
+
plugin_registry.plugins.filter_map { |plugin| plugin_trust_refusal_diagnostic(plugin) }
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
def plugin_trust_refusal_diagnostic(plugin)
|
|
942
|
+
summary = plugin.io_boundary.refusal_summary
|
|
943
|
+
return nil if summary.nil?
|
|
944
|
+
|
|
945
|
+
plugin_id = plugin.manifest.id
|
|
946
|
+
Diagnostic.new(
|
|
947
|
+
path: ".rigor.yml", line: 1, column: 1,
|
|
948
|
+
message: "plugin #{plugin_id.inspect} had #{summary[:count]} read(s) refused by the trust " \
|
|
949
|
+
"policy; first refused path: #{summary[:first_path].inspect}, outside read root " \
|
|
950
|
+
"#{summary[:nearest_root].inspect}. Spell the path the way that read root spells it " \
|
|
951
|
+
"(a symlink alias such as macOS' /tmp does not match its real path), or add a " \
|
|
952
|
+
"`plugins_io.allowed_paths:` entry in .rigor.yml covering the path.",
|
|
953
|
+
severity: :info,
|
|
954
|
+
rule: "plugin_trust.read-refused",
|
|
955
|
+
source_family: :builtin
|
|
956
|
+
)
|
|
957
|
+
rescue StandardError
|
|
958
|
+
nil
|
|
959
|
+
end
|
|
960
|
+
|
|
707
961
|
def build_reporter_diagnostic(source_location, rule:, message:)
|
|
708
962
|
path, line, column = location_fields(source_location)
|
|
709
963
|
Diagnostic.new(
|
|
@@ -712,6 +966,20 @@ module Rigor
|
|
|
712
966
|
)
|
|
713
967
|
end
|
|
714
968
|
|
|
969
|
+
# The {RbsExtended::Reporter} form of the builder above: its three streams carry the position as
|
|
970
|
+
# `(path, line, column)` primitives rather than as the `RBS::Location` a conformance record holds,
|
|
971
|
+
# because they cross the pool drain channel (#785, #805). A missing component falls back exactly as
|
|
972
|
+
# {#location_fields} does for a missing location.
|
|
973
|
+
def build_positioned_reporter_diagnostic(entry, rule:, message:)
|
|
974
|
+
path = entry.path.to_s
|
|
975
|
+
Diagnostic.new(
|
|
976
|
+
path: path.empty? ? ".rigor.yml" : path,
|
|
977
|
+
line: entry.line || 1,
|
|
978
|
+
column: entry.column || 1,
|
|
979
|
+
message: message, severity: :info, rule: rule, source_family: :builtin
|
|
980
|
+
)
|
|
981
|
+
end
|
|
982
|
+
|
|
715
983
|
def location_fields(source_location)
|
|
716
984
|
return [".rigor.yml", 1, 1] if source_location.nil?
|
|
717
985
|
|
|
@@ -768,6 +1036,10 @@ module Rigor
|
|
|
768
1036
|
@quarantined_signatures_snapshot_reader.call
|
|
769
1037
|
end
|
|
770
1038
|
|
|
1039
|
+
def signature_standdowns_snapshot
|
|
1040
|
+
@signature_standdowns_snapshot_reader.call
|
|
1041
|
+
end
|
|
1042
|
+
|
|
771
1043
|
def env_build_failure_snapshot
|
|
772
1044
|
@env_build_failure_snapshot_reader.call
|
|
773
1045
|
end
|
|
@@ -776,6 +1048,10 @@ module Rigor
|
|
|
776
1048
|
@definition_build_failures_snapshot_reader.call
|
|
777
1049
|
end
|
|
778
1050
|
|
|
1051
|
+
def hkt_scan_failure_snapshot
|
|
1052
|
+
@hkt_scan_failure_snapshot_reader.call
|
|
1053
|
+
end
|
|
1054
|
+
|
|
779
1055
|
def conformance_results_snapshot
|
|
780
1056
|
@conformance_results_snapshot_reader.call
|
|
781
1057
|
end
|