rigortype 0.3.8 → 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 +72 -1
- 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 +32 -4
- data/docs/manual/03-configuration.md +11 -0
- data/docs/manual/04-diagnostics.md +11 -0
- 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 +8 -24
- 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 +81 -22
- 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 +177 -26
- 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 +256 -88
- data/lib/rigor/analysis/runner/project_pre_passes.rb +12 -6
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +133 -35
- data/lib/rigor/analysis/worker_session.rb +9 -10
- data/lib/rigor/bleeding_edge.rb +12 -24
- data/lib/rigor/builtins/hkt_builtins.rb +2 -2
- data/lib/rigor/builtins/imported_refinements.rb +155 -21
- 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 +2 -4
- 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_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +77 -32
- 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 +2 -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 +2 -2
- 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 +388 -59
- data/lib/rigor/environment.rb +105 -20
- 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 +4 -7
- 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 +42 -12
- 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 +4 -6
- data/lib/rigor/rbs_extended/reporter.rb +36 -10
- data/lib/rigor/rbs_extended.rb +61 -21
- 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 +115 -22
- 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 +4 -5
- 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 +5 -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 +26 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
data/sig/rigor/inference.rbs
CHANGED
|
@@ -45,11 +45,7 @@ module Rigor
|
|
|
45
45
|
def singleton_def?: (untyped def_node) -> bool
|
|
46
46
|
def self_type_for_class_body: (Array[ClassFrame] class_context) -> Type::t?
|
|
47
47
|
def self_type_for_method_body: (singleton: bool) -> Type::t?
|
|
48
|
-
def qualified_name_for: (untyped constant_path_node) -> String?
|
|
49
|
-
def render_constant_path: (untyped node) -> String
|
|
50
48
|
def singleton_context_for: (untyped node) -> Array[ClassFrame]
|
|
51
|
-
def captured_local_writes: (untyped block_node, Scope base_scope) -> Array[Symbol]
|
|
52
|
-
def block_introduced_locals: (untyped block_node) -> Set[Symbol]
|
|
53
49
|
def drop_captured_narrowing: (untyped block_node, Scope base_scope) -> Scope
|
|
54
50
|
def classify_closure_escape: (untyped call_node) -> closure_classification
|
|
55
51
|
def record_closure_escape_if_any: (untyped node) -> Scope
|
|
@@ -108,12 +104,12 @@ module Rigor
|
|
|
108
104
|
def self?.narrow_non_nil: (Type::t type) -> Type::t
|
|
109
105
|
def self?.narrow_equal: (Type::t type, untyped literal) -> Type::t
|
|
110
106
|
def self?.narrow_not_equal: (Type::t type, untyped literal) -> Type::t
|
|
111
|
-
def self?.narrow_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment) -> Type::t
|
|
112
|
-
def self?.narrow_not_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment) -> Type::t
|
|
107
|
+
def self?.narrow_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment, ?scope: Scope?) -> Type::t
|
|
108
|
+
def self?.narrow_not_class: (Type::t type, String class_name, ?exact: bool, ?environment: Environment, ?scope: Scope?) -> Type::t
|
|
113
109
|
def self?.narrow_not_refinement: (Type::t current_type, Type::t refinement_type) -> Type::t
|
|
114
110
|
def self?.narrow_for_fact: (Type::t current, untyped fact, untyped environment) -> Type::t
|
|
115
111
|
def self?.predicate_certainty: (Type::t? type) -> (:truthy | :falsey | nil)
|
|
116
|
-
def self?.class_pattern_certainty: (Type::t subject_type, String class_name, environment: Environment) -> (:yes | :no | :maybe)
|
|
112
|
+
def self?.class_pattern_certainty: (Type::t subject_type, String class_name, environment: Environment, ?scope: Scope?) -> (:yes | :no | :maybe)
|
|
117
113
|
def self?.value_pattern_certainty: (Type::t subject_type, untyped pattern_value) -> (:yes | :no | :maybe)
|
|
118
114
|
def self?.predicate_scopes: (untyped node, Scope scope) -> [Scope, Scope]
|
|
119
115
|
def self?.case_when_scopes: (untyped subject, Array[untyped] conditions, Scope scope) -> [Scope, Scope]
|
|
@@ -162,7 +158,6 @@ module Rigor
|
|
|
162
158
|
|
|
163
159
|
module ScopeIndexer
|
|
164
160
|
def self?.index: (untyped root, default_scope: Scope) -> Hash[untyped, Scope]
|
|
165
|
-
def self?.build_declaration_overrides: (untyped root) -> Hash[untyped, Type::t]
|
|
166
161
|
def self?.build_declaration_artifacts: (untyped root) -> [Hash[untyped, Type::t], Hash[String, Type::t]]
|
|
167
162
|
def self?.build_in_source_constants: (untyped root, Scope default_scope) -> Hash[String, Type::t]
|
|
168
163
|
def self?.record_declarations: (untyped node, Array[String] qualified_prefix, Hash[untyped, Type::t] identity_table, Hash[String, Type::t] discovered) -> void
|
|
@@ -176,8 +171,6 @@ module Rigor
|
|
|
176
171
|
def self?.constant_writes_for_file: (untyped root) -> Hash[String, untyped]
|
|
177
172
|
def self?.constant_literal_value: (untyped rvalue) -> Array[untyped]?
|
|
178
173
|
def self?.finalize_constant_writes: (Hash[String, Hash[String, untyped]] writes) -> [Hash[String, Type::t], Hash[String, Set[String]]]
|
|
179
|
-
def self?.qualified_name_for: (untyped constant_path_node) -> String?
|
|
180
|
-
def self?.render_constant_path: (untyped node) -> String
|
|
181
174
|
def self?.propagate: (untyped node, Hash[untyped, Scope] table, Scope parent_scope) -> void
|
|
182
175
|
end
|
|
183
176
|
|
|
@@ -3,6 +3,10 @@ class Rigor::Plugin::IoBoundary
|
|
|
3
3
|
def read_file: (untyped) -> String
|
|
4
4
|
def file?: (untyped) -> bool
|
|
5
5
|
def directory?: (untyped) -> bool
|
|
6
|
+
def list_directory: (untyped) -> Array[String]
|
|
7
|
+
# sig-gen gap: #959 — the generator pins the empty-summary literal (`count: 0, first_path: nil`); the
|
|
8
|
+
# record's fields are the running count and the first refused path, nil when nothing was refused.
|
|
9
|
+
def refusal_summary: () -> { count: Integer, first_path: String?, nearest_root: String? }?
|
|
6
10
|
def open_url: (untyped url) -> String
|
|
7
11
|
# Returns a frozen `Rigor::Cache::Descriptor` (no RBS yet -> untyped).
|
|
8
12
|
def cache_descriptor: () -> untyped
|
|
@@ -3,7 +3,7 @@ class Rigor::Plugin::Manifest::Consumption
|
|
|
3
3
|
end
|
|
4
4
|
|
|
5
5
|
class Rigor::Plugin::Manifest
|
|
6
|
-
def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: untyped, ?source_rbs_synthesizer: untyped, ?additional_initializers: untyped) -> void
|
|
6
|
+
def initialize: (id: untyped, version: untyped, ?description: untyped, ?config_schema: untyped, ?target_gems: untyped, ?produces: untyped, ?consumes: untyped, ?owns_receivers: untyped, ?open_receivers: untyped, ?type_node_resolvers: untyped, ?block_as_methods: untyped, ?heredoc_templates: untyped, ?nested_class_templates: untyped, ?trait_registries: untyped, ?hkt_registrations: untyped, ?hkt_definitions: untyped, ?signature_paths: untyped, ?protocol_contracts: untyped, ?source_rbs_synthesizer: untyped, ?additional_initializers: untyped) -> void
|
|
7
7
|
|
|
8
8
|
# Public attribute readers (the full `attr_reader` surface). Plugins
|
|
9
9
|
# read `manifest.id` / `manifest.protocol_contracts` etc.; declaring
|
|
@@ -16,6 +16,7 @@ class Rigor::Plugin::Manifest
|
|
|
16
16
|
def description: () -> String?
|
|
17
17
|
def config_schema: () -> untyped
|
|
18
18
|
def config_defaults: () -> Hash[String, untyped]
|
|
19
|
+
def target_gems: () -> Array[String]
|
|
19
20
|
def produces: () -> untyped
|
|
20
21
|
def consumes: () -> untyped
|
|
21
22
|
def owns_receivers: () -> untyped
|
data/sig/rigor/reflection.rbs
CHANGED
|
@@ -3,11 +3,13 @@ module Rigor
|
|
|
3
3
|
def self?.class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
|
|
4
4
|
def self?.rbs_class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
|
|
5
5
|
def self?.project_declared_class?: (String | Symbol class_name, ?scope: Scope?, ?environment: Environment?) -> bool
|
|
6
|
-
def self?.class_ordering: (String | Symbol lhs, String | Symbol rhs, ?scope: Scope) ->
|
|
6
|
+
def self?.class_ordering: (String | Symbol lhs, String | Symbol rhs, ?scope: Scope) -> (:disjoint | :equal | :subclass | :superclass | :unknown)
|
|
7
7
|
def self?.nominal_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Nominal?
|
|
8
8
|
def self?.singleton_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Singleton?
|
|
9
9
|
def self?.constant_type_for: (String | Symbol constant_name, ?scope: Scope) -> Type::t?
|
|
10
10
|
def self?.resolve_constant_type: (String | Symbol name, ?scope: Scope, ?rooted: bool) -> Type::t?
|
|
11
|
+
# sig-gen gap: #656 — sig-gen skips the method (untyped return), so the resolved-name-or-decline is hand-written.
|
|
12
|
+
def self?.resolve_constant_path_name: (String | Symbol name, Scope scope) { (String candidate) -> boolish } -> String?
|
|
11
13
|
def self?.lexical_nesting_chain: (Scope scope) -> Array[String]
|
|
12
14
|
def self?.instance_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
|
|
13
15
|
def self?.singleton_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
|
data/sig/rigor/scope.rbs
CHANGED
|
@@ -39,12 +39,17 @@ module Rigor
|
|
|
39
39
|
def discovered_method_visibilities: () -> Hash[String, Hash[Symbol, Symbol]]
|
|
40
40
|
def discovered_superclasses: () -> Hash[String, String]
|
|
41
41
|
def discovered_includes: () -> Hash[String, Array[String]]
|
|
42
|
+
# sig-gen gap: #898 — sig-gen skips the endless-def reader (untyped return), so the table shape is hand-written.
|
|
43
|
+
def discovered_extends: () -> Hash[String, Array[String]]
|
|
42
44
|
def discovered_class_sources: () -> Hash[String, Set[String]]
|
|
43
45
|
def constant_sources: () -> Hash[String, Set[String]]
|
|
44
46
|
def published_constant_names: () -> Set[String]
|
|
45
47
|
def local_constant_names: () -> Set[String]
|
|
48
|
+
# sig-gen gap: #667 — sig-gen types the `||` fallback `untyped`, so the element type is hand-written.
|
|
49
|
+
def published_constant_ivars_for: (String class_name) -> Set[Symbol]
|
|
46
50
|
def published_constant?: (String name) -> bool
|
|
47
51
|
def record_constant_dependency: (String name) -> void
|
|
52
|
+
def record_class_existence: (String class_name) -> void
|
|
48
53
|
def data_member_layouts: () -> Hash[String, Array[Symbol]]
|
|
49
54
|
def struct_member_layouts: () -> Hash[String, { members: Array[Symbol], keyword_init: bool }]
|
|
50
55
|
def param_inferred_types: () -> Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
|
|
@@ -73,10 +78,16 @@ module Rigor
|
|
|
73
78
|
attr_reader discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]]
|
|
74
79
|
attr_reader discovered_superclasses: Hash[String, String]
|
|
75
80
|
attr_reader discovered_includes: Hash[String, Array[String]]
|
|
81
|
+
# sig-gen gap: #898 — `Data.define` members carry no type, as for every other row in this class.
|
|
82
|
+
attr_reader discovered_extends: Hash[String, Array[String]]
|
|
76
83
|
attr_reader discovered_class_sources: Hash[String, Set[String]]
|
|
77
84
|
attr_reader constant_sources: Hash[String, Set[String]]
|
|
78
85
|
attr_reader published_constant_names: Set[String]
|
|
79
86
|
attr_reader local_constant_names: Set[String]
|
|
87
|
+
# sig-gen gap: #667 — `Data.define` members carry no type, so every row in this class is authored.
|
|
88
|
+
attr_reader published_constant_alias_names: Set[String]
|
|
89
|
+
# sig-gen gap: #667 — as above.
|
|
90
|
+
attr_reader published_constant_ivars: Hash[String, Set[Symbol]]
|
|
80
91
|
attr_reader data_member_layouts: Hash[String, Array[Symbol]]
|
|
81
92
|
attr_reader struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }]
|
|
82
93
|
attr_reader param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]]
|
|
@@ -84,7 +95,7 @@ module Rigor
|
|
|
84
95
|
|
|
85
96
|
EMPTY: DiscoveryIndex
|
|
86
97
|
|
|
87
|
-
def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?run_generation: Object?) -> DiscoveryIndex
|
|
98
|
+
def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?run_generation: Object?) -> DiscoveryIndex
|
|
88
99
|
end
|
|
89
100
|
|
|
90
101
|
class IndexedKey
|
|
@@ -125,6 +136,12 @@ module Rigor
|
|
|
125
136
|
def with_ivar_origin: (String | Symbol name, Symbol? cause) -> Scope
|
|
126
137
|
def with_cvar: (String | Symbol name, Type::t type) -> Scope
|
|
127
138
|
def with_global: (String | Symbol name, Type::t type) -> Scope
|
|
139
|
+
# sig-gen gap: #667 — an `attr_reader` over a frozen Set literal types `untyped`, as the sibling
|
|
140
|
+
# `declaration_sourced` row does.
|
|
141
|
+
def published_constant_sourced: () -> Set[[Symbol, Symbol]]
|
|
142
|
+
# sig-gen gap: #667 — `Set#include?` over a tuple key types `untyped`, so the `bool` is hand-written.
|
|
143
|
+
def published_constant_sourced?: (Symbol kind, String | Symbol name) -> bool
|
|
144
|
+
def with_published_constant_mark: (Symbol kind, String | Symbol name) -> Scope
|
|
128
145
|
def declaration_sourced: () -> Set[[Symbol, Symbol]]
|
|
129
146
|
def seed_declaration_sourced_ivar: (String | Symbol name, Type::t type) -> Scope
|
|
130
147
|
def with_declaration_sourced_local: (String | Symbol name, Type::t type) -> Scope
|
|
@@ -138,15 +155,16 @@ module Rigor
|
|
|
138
155
|
def class_cvars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
|
|
139
156
|
def discovered_method?: (String | Symbol class_name, String | Symbol method_name, Symbol kind) -> bool
|
|
140
157
|
def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
|
|
141
|
-
def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> [untyped
|
|
158
|
+
def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([untyped, String] | [nil, nil])
|
|
142
159
|
def discovered_method_through_ancestors?: (String | Symbol? class_name, String | Symbol method_name, Symbol kind, ?name_memo: Hash[untyped, untyped]) -> bool
|
|
160
|
+
def external_ancestor_name_candidates: (String | Symbol class_name, ?name_memo: Hash[untyped, untyped]) -> Array[Array[String]]
|
|
143
161
|
def enqueue_ancestors: (String current, Array[String] queue, Hash[untyped, untyped] name_memo, ?mixins: bool) -> void
|
|
144
162
|
def ancestor_name_candidates: (String | Symbol subclass_qualified, String | Symbol raw_ancestor) -> Array[String]
|
|
145
163
|
|
|
146
164
|
# Issue #530 — public so the external-gem ancestry probe asks the same question the walk does.
|
|
147
165
|
def known_user_class?: (String | Symbol name) -> bool
|
|
148
166
|
def singleton_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
|
|
149
|
-
def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> [untyped
|
|
167
|
+
def singleton_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([untyped, String] | [nil, nil])
|
|
150
168
|
def user_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
|
|
151
169
|
def user_singleton_def_site_for: (String | Symbol class_name, String | Symbol method_name) -> String?
|
|
152
170
|
def top_level_def_for: (String | Symbol method_name) -> untyped?
|
|
@@ -157,6 +175,9 @@ module Rigor
|
|
|
157
175
|
def data_member_layout: (String | Symbol class_name) -> Array[Symbol]?
|
|
158
176
|
def struct_member_layout: (String | Symbol class_name) -> { members: Array[Symbol], keyword_init: bool }?
|
|
159
177
|
def includes_of: (String | Symbol class_name) -> Array[String]
|
|
178
|
+
# sig-gen gap: #898 — sig-gen proposes `Array[untyped] | []` off the empty-table early return, so the
|
|
179
|
+
# element type is hand-written, matching {#includes_of}.
|
|
180
|
+
def singleton_extends_of: (String | Symbol class_name) -> Array[String]
|
|
160
181
|
def indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Type::t?
|
|
161
182
|
def with_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key, Type::t type) -> Scope
|
|
162
183
|
def without_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Scope
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class Rigor::SigGen::SkipReasonCatalog::Entry < ::Data
|
|
2
|
+
def id: () -> untyped
|
|
3
|
+
def summary: () -> untyped
|
|
4
|
+
def explanation: () -> untyped
|
|
5
|
+
def next_step: () -> untyped
|
|
6
|
+
def self.new: (id: untyped, summary: untyped, explanation: untyped, next_step: untyped) -> instance | (untyped id, untyped summary, untyped explanation, untyped next_step) -> instance
|
|
7
|
+
def self.[]: (id: untyped, summary: untyped, explanation: untyped, next_step: untyped) -> instance | (untyped id, untyped summary, untyped explanation, untyped next_step) -> instance
|
|
8
|
+
def to_h: () -> Hash[String, untyped]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Rigor::SigGen::SkipReasonCatalog
|
|
12
|
+
def self?.resolve: (untyped) -> Rigor::SigGen::SkipReasonCatalog::Entry?
|
|
13
|
+
def self?.all: () -> Array[Rigor::SigGen::SkipReasonCatalog::Entry]
|
|
14
|
+
end
|
data/sig/rigor/type.rbs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Rigor
|
|
2
2
|
module Type
|
|
3
|
-
type t = Top | Bot | Dynamic | Constant | IntegerRange | Nominal | Singleton | Union | Difference | Refined | Intersection | Tuple | HashShape | DataClass | DataInstance | StructClass | StructInstance | BoundMethod | Result | Maybe | App
|
|
3
|
+
type t = Top | Bot | Dynamic | Constant | IntegerRange | FloatRange | Nominal | Singleton | Union | Difference | Refined | Intersection | Tuple | HashShape | DataClass | DataInstance | StructClass | StructInstance | BoundMethod | Result | Maybe | App
|
|
4
4
|
|
|
5
5
|
type accepts_mode = :strict | :gradual | :loose
|
|
6
6
|
|
|
@@ -115,7 +115,30 @@ module Rigor
|
|
|
115
115
|
def inspect: () -> String
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
+
class FloatRange
|
|
119
|
+
ALIAS_NAMES: Hash[[Float, Float], String]
|
|
120
|
+
attr_reader min: Float
|
|
121
|
+
attr_reader max: Float
|
|
122
|
+
def initialize: (Float min, Float max, ?exclude_end: bool) -> void
|
|
123
|
+
def exclude_end?: () -> bool
|
|
124
|
+
def canonical_max: () -> Float
|
|
125
|
+
def universal?: () -> bool
|
|
126
|
+
def covers?: (untyped value) -> bool
|
|
127
|
+
def describe: (?Symbol verbosity) -> String
|
|
128
|
+
def generic_description: () -> String
|
|
129
|
+
def erase_to_rbs: () -> "Float"
|
|
130
|
+
def top: () -> Trinary
|
|
131
|
+
def bot: () -> Trinary
|
|
132
|
+
def dynamic: () -> Trinary
|
|
133
|
+
def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
|
|
134
|
+
def ==: (untyped other) -> bool
|
|
135
|
+
def eql?: (untyped other) -> bool
|
|
136
|
+
def hash: () -> Integer
|
|
137
|
+
def inspect: () -> String
|
|
138
|
+
end
|
|
139
|
+
|
|
118
140
|
class Nominal
|
|
141
|
+
EMPTY_TYPE_ARGS: Array[Type::t]
|
|
119
142
|
attr_reader class_name: String
|
|
120
143
|
attr_reader type_args: Array[Type::t]
|
|
121
144
|
def initialize: (String class_name, ?Array[Type::t] type_args) -> void
|
|
@@ -460,6 +483,9 @@ module Rigor
|
|
|
460
483
|
def self?.negative_int: () -> IntegerRange
|
|
461
484
|
def self?.non_positive_int: () -> IntegerRange
|
|
462
485
|
def self?.universal_int: () -> IntegerRange
|
|
486
|
+
def self?.float_range: (Float min, Float max, ?exclude_end: bool) -> FloatRange
|
|
487
|
+
def self?.non_nan_float: () -> FloatRange
|
|
488
|
+
def self?.finite_float: () -> FloatRange
|
|
463
489
|
def self?.tuple_of: (*Type::t elements) -> Tuple
|
|
464
490
|
def self?.hash_shape_of: (?Hash[untyped, Type::t]? pairs, **untyped options) -> HashShape
|
|
465
491
|
def self?.data_class_of: (members: Array[Symbol], ?class_name: String?) -> DataClass
|
data/sig/rigor.rbs
CHANGED
data/skills/rigor-ask/SKILL.md
CHANGED
|
@@ -30,11 +30,12 @@ Two things make that easy, and you have both offline:
|
|
|
30
30
|
`type-of` / `triage` / `coverage` answer from what Rigor inferred. A
|
|
31
31
|
concrete inferred type beats any abstract explanation.
|
|
32
32
|
|
|
33
|
-
This is the user's shortcut: they only ever need to remember
|
|
34
|
-
**`rigor-next-steps`** ("what should we do next?")
|
|
35
|
-
("answer this about Rigor")
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
This is the user's shortcut: they only ever need to remember three
|
|
34
|
+
skills — **`rigor-next-steps`** ("what should we do next?"),
|
|
35
|
+
**`rigor-ask`** ("answer this about Rigor"), and **`rigor-type-oracle`**
|
|
36
|
+
("before you write a type, ask Rigor"). They ask in plain language; *you*
|
|
37
|
+
turn it into the right lookup or analysis so they never have to remember
|
|
38
|
+
the command.
|
|
38
39
|
|
|
39
40
|
## Prefer the live map over this skill's tables
|
|
40
41
|
|
|
@@ -125,8 +126,9 @@ A good hand-off is two or three sentences of orientation plus the pointer:
|
|
|
125
126
|
- CI → **`rigor-ci-setup`** · editor → **`rigor-editor-setup`** · MCP agent → **`rigor-mcp-setup`**
|
|
126
127
|
- baseline reduction → **`rigor-baseline-reduce`** · coverage holes → **`rigor-protection-uplift`**
|
|
127
128
|
- a missing gem/DSL → **`rigor-plugin-author`** · monkey-patch clusters → **`rigor-monkeypatch-resolve`**
|
|
129
|
+
- about to *write* a type (RBS, `#:`, a Sorbet `sig`, a YARD tag, a doc sentence) → **`rigor-type-oracle`**
|
|
128
130
|
|
|
129
|
-
When in doubt, give less and point — it respects the user's "
|
|
131
|
+
When in doubt, give less and point — it respects the user's "three skills
|
|
130
132
|
to remember" promise and keeps each answer to the part only `rigor-ask`
|
|
131
133
|
can give.
|
|
132
134
|
|
|
@@ -152,8 +152,9 @@ For your own target library, follow the same harness: a **fixed
|
|
|
152
152
|
allow-list** of pure methods, inputs derived from source, and **decline
|
|
153
153
|
(return nil / emit nothing) when the library is unavailable — never
|
|
154
154
|
approximate**. How the call is isolated from Rigor (in-process, a forked
|
|
155
|
-
worker, or a `Ruby::Box`) is a configurable strategy the user picks
|
|
156
|
-
|
|
155
|
+
worker, or a `Ruby::Box`) is a configurable strategy the user picks with
|
|
156
|
+
`.rigor.yml`'s `plugins_isolation:` key or the `RIGOR_PLUGIN_ISOLATION`
|
|
157
|
+
environment variable (which wins over it); you just call the method.
|
|
157
158
|
|
|
158
159
|
For the common "did you mean …?" suggestion, use the shared helper
|
|
159
160
|
rather than hand-rolling Levenshtein:
|
|
@@ -194,6 +195,16 @@ dynamic_return receivers: ["Money"] do |call_node, scope|
|
|
|
194
195
|
Rigor::Type::Combinator.nominal_of("Money")
|
|
195
196
|
end
|
|
196
197
|
|
|
198
|
+
# A `receivers:` entry names the receiver KIND too. `"Money"` matches an
|
|
199
|
+
# INSTANCE receiver; the class object itself is `"singleton(Money)"`,
|
|
200
|
+
# spelled as RBS spells it; a rule for both lists both. Write the kind
|
|
201
|
+
# the rule actually models: a plugin answer suppresses that call site's
|
|
202
|
+
# `call.undefined-method`, so an instance rule that also answered on the
|
|
203
|
+
# class would silence a genuine miss on the class-level call.
|
|
204
|
+
dynamic_return receivers: ["singleton(Money)"], methods: [:from_cents] do |call_node, scope|
|
|
205
|
+
Rigor::Type::Combinator.nominal_of("Money")
|
|
206
|
+
end
|
|
207
|
+
|
|
197
208
|
# Post-return NARROWING FACTS, gated on the call's method name.
|
|
198
209
|
# Return an Array of facts (or nil). Used for assertion / predicate
|
|
199
210
|
# narrowing (`assert_kind_of(Foo, x)` ⇒ x is Foo afterwards).
|
|
@@ -135,6 +135,7 @@ mode — those points resolve without blocking:
|
|
|
135
135
|
| 6a | **Pre-baseline cleanup** — apply quick fixes that triage diagnosed (`pre_eval:` for monkey-patch hints, `rbs collection install` if still needed). Re-run triage; repeat until the count is stable. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) § "Phase 6a" |
|
|
136
136
|
| 7 | Acknowledge mode only — generate the baseline and wire `baseline:`. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) |
|
|
137
137
|
| 8 | Surface likely real bugs; distinguish sig quality FPs from real bugs; offer escalation paths. | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) |
|
|
138
|
+
| 8a | Install the agent type-contract into `AGENTS.md` / `CLAUDE.md`, so an AI contributor sources types from Rigor instead of guessing them. | [`references/06-agent-contract.md`](references/06-agent-contract.md) |
|
|
138
139
|
| 9 | Confirm the generated files with the user — what each is, and whether to commit it. | (this file — § "Final step") |
|
|
139
140
|
|
|
140
141
|
Load each reference when you reach its phase. Phases run in order;
|
|
@@ -150,6 +151,7 @@ committed `sig/` directory.
|
|
|
150
151
|
| 2 | [`references/02-configure.md`](references/02-configure.md) | **Phase 4.** Severity-profile choice tied to the mode. The `.rigor.dist.yml` template and every key it uses. The `.rigor.dist.yml` vs `.rigor.yml` convention. |
|
|
151
152
|
| 3 | [`references/04-sig-uplift.md`](references/04-sig-uplift.md) | **Phase 5.** `rigor sig-gen --write` baseline. `rigor sig-gen --params=observed --write` attr_reader precision uplift. Handling residual `untyped` methods. Committing `sig/`. |
|
|
152
153
|
| 4 | [`references/03-baseline-and-bugs.md`](references/03-baseline-and-bugs.md) | **Phases 6–8.** `rigor triage` as the diagnosis layer. Phase 6a pre-baseline cleanup loop (`pre_eval:` for monkey-patch hints, `rbs collection install`). `rigor baseline generate` + wiring `baseline:`. Surfacing likely real bugs; sig quality FP recognition (Struct `call.wrong-arity`, `-> bot` return-type-mismatch, regex-capture `$1` FPs). The two escalation paths — write a project plugin, or open a Rigor issue. |
|
|
154
|
+
| 5 | [`references/06-agent-contract.md`](references/06-agent-contract.md) | **Phase 8a.** The one paragraph the project's `AGENTS.md` / `CLAUDE.md` keeps so every agent session sources types from Rigor rather than guessing them. Where to append it, when to create the file, and what never to overwrite. |
|
|
153
155
|
| — (optional) | [`references/05-jit-performance.md`](references/05-jit-performance.md) | **Operational, not a phase.** Run speed via a Ruby JIT: Rigor auto-enables YJIT for long runs (~5 s break-even), how to detect JIT support in your install, the override env vars, and why YJIT beats ZJIT for Rigor on Ruby 4.0. Read only when a large project's `rigor check` wall time matters. |
|
|
154
156
|
|
|
155
157
|
## Escalation paths (Phase 7 preview)
|
|
@@ -227,10 +229,11 @@ only in acknowledge mode). For each, give the commit recommendation:
|
|
|
227
229
|
| `.rigor/` (contains `cache/`) | The per-file analysis cache `rigor check` writes to speed up re-runs. Regenerable and machine-local. | **No** — add `.rigor/` to `.gitignore`. |
|
|
228
230
|
| `.rigor.yml` | Optional per-developer local override (not written by this skill). Takes precedence over `.rigor.dist.yml`; used to opt out locally (e.g. run without the baseline). | **No** — gitignore it if a developer creates one. |
|
|
229
231
|
| `rbs_collection.lock.yaml` | Not a Rigor artefact — but if Phase 1 ran `rbs collection install`, the install may have regenerated this pre-existing project file (e.g. the stdlib gem list for the resolved Ruby). | **Yes**, but flag it separately: it is a change to an existing project file, not part of the Rigor file set. |
|
|
232
|
+
| `AGENTS.md` / `CLAUDE.md` | The agent type-contract section added in Phase 8a — "a type you did not obtain from Rigor is a guess". Created only if neither file existed; otherwise this is an appended section in a pre-existing file. | **Yes** — commit it; the point is that every contributor's agent reads the same rule. Flag an appended section separately, as with `rbs_collection.lock.yaml`. |
|
|
230
233
|
|
|
231
234
|
Recommend the two concrete actions and **ask before doing them**
|
|
232
235
|
(both touch the user's repo): (1) add `.rigor/` — and `.rigor.yml`
|
|
233
236
|
if present — to `.gitignore`; (2) commit `.rigor.dist.yml`,
|
|
234
|
-
`.rigor-baseline.yml`,
|
|
235
|
-
|
|
236
|
-
confirm.
|
|
237
|
+
`.rigor-baseline.yml`, `sig/`, and the Phase 8a `AGENTS.md` /
|
|
238
|
+
`CLAUDE.md` section as the shared Rigor setup. Per the git-safety
|
|
239
|
+
default, do not commit on the user's behalf until they confirm.
|
|
@@ -114,10 +114,11 @@ severity_profile: lenient
|
|
|
114
114
|
|
|
115
115
|
### Existing `sig/` directory
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
A plain `<project root>/sig` directory needs no wiring: with
|
|
118
|
+
`signature_paths:` unset, Rigor auto-detects it and loads it recursively.
|
|
119
|
+
Phase 5 (sig uplift) can be skipped. Declare `signature_paths:` when the
|
|
120
|
+
layout is something else — several trees, or a `sig/` that is not at the
|
|
121
|
+
project root:
|
|
121
122
|
|
|
122
123
|
```yaml
|
|
123
124
|
signature_paths:
|
|
@@ -125,9 +126,12 @@ signature_paths:
|
|
|
125
126
|
- sig/generated
|
|
126
127
|
```
|
|
127
128
|
|
|
129
|
+
Declaring the key REPLACES the auto-detected `sig`, so list it too if you
|
|
130
|
+
want it. `signature_paths: []` is the way to opt out of project RBS
|
|
131
|
+
entirely — including a `sig/` that `rigor sig-gen --write` created.
|
|
132
|
+
|
|
128
133
|
List only directories that contain `.rbs` files or subdirectories of
|
|
129
|
-
them. Rigor walks each path recursively.
|
|
130
|
-
flat `sig/` directory, use `- sig` instead.
|
|
134
|
+
them. Rigor walks each path recursively.
|
|
131
135
|
|
|
132
136
|
A strict-mode plain-Ruby gem is shorter:
|
|
133
137
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# 06 — Install the agent type-contract into AGENTS.md / CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Covers **Phase 8a**. Input: an onboarded project (config written, sigs
|
|
4
|
+
generated, baseline decided). Output: one section in the file the
|
|
5
|
+
project's coding agents read at startup.
|
|
6
|
+
|
|
7
|
+
## Why this is part of onboarding
|
|
8
|
+
|
|
9
|
+
Everything the earlier phases produced — `sig/`, the baseline, the
|
|
10
|
+
severity profile — is a record of what Rigor *proved*. The moment an AI
|
|
11
|
+
agent starts contributing to the project, it can write types that Rigor
|
|
12
|
+
never proved: a `@param currency [String]` in a doc comment, an
|
|
13
|
+
rbs-inline `#:` that Rigor then ingests as a live contract. Those enter
|
|
14
|
+
the same files, look identical to derived types, and are believed.
|
|
15
|
+
|
|
16
|
+
The fix is not a tool. It is one paragraph in the project's agent
|
|
17
|
+
contract, so the rule is in context every session rather than only when
|
|
18
|
+
a skill happens to trigger: **a type not obtained from Rigor is a guess,
|
|
19
|
+
and a guessed type is never written.**
|
|
20
|
+
|
|
21
|
+
## The text
|
|
22
|
+
|
|
23
|
+
The canonical fragment is served by the installed Rigor, so it stays
|
|
24
|
+
current with the CLI it names:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
rigor skill --full rigor-type-oracle
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Its `references/02-agents-md-fragment.md` section carries the paragraph
|
|
31
|
+
and the five bullets. Copy that block **verbatim** — including its
|
|
32
|
+
single-long-line shape, which is deliberate (some renderers turn a
|
|
33
|
+
newline inside a paragraph into a line break).
|
|
34
|
+
|
|
35
|
+
Do not paraphrase it from memory, and do not shorten it: the five bullets
|
|
36
|
+
are the load-bearing part — expression, method signature, parameter,
|
|
37
|
+
the gap rule, and provenance.
|
|
38
|
+
|
|
39
|
+
## Where it goes
|
|
40
|
+
|
|
41
|
+
| Project state | What to do |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `AGENTS.md` exists | **Append** the section at the end. Do not reorganise the file. |
|
|
44
|
+
| Only `CLAUDE.md` exists | Append it there. |
|
|
45
|
+
| Both exist | Put it in `AGENTS.md`. Add `@AGENTS.md` to `CLAUDE.md` only if it is not already pulled in. |
|
|
46
|
+
| Neither exists | **Create `AGENTS.md`** with this as its first section. |
|
|
47
|
+
| A types / type-checking section already exists | Merge into it; keep the five bullets intact. Never write a second, competing rule. |
|
|
48
|
+
|
|
49
|
+
Never overwrite unrelated content. If the project already states a rule
|
|
50
|
+
about type authorship that contradicts this one, stop and show the user
|
|
51
|
+
the conflict — the project's own rule wins until they say otherwise.
|
|
52
|
+
|
|
53
|
+
## Report it in the final step
|
|
54
|
+
|
|
55
|
+
This is a change to the file that governs every future agent session in
|
|
56
|
+
the repo, so it belongs in Phase 9's file inventory, not in a silent
|
|
57
|
+
diff. Recommend committing it: the point is that every contributor's
|
|
58
|
+
agent reads the same rule.
|
|
59
|
+
|
|
60
|
+
## When to skip
|
|
61
|
+
|
|
62
|
+
- The project has no coding-agent contract file **and** the user has said
|
|
63
|
+
they do not use AI agents on it. Offer once, accept "no".
|
|
64
|
+
- The user declined it earlier in this session.
|
|
65
|
+
|
|
66
|
+
Otherwise install it — an unonboarded agent is the one contributor that
|
|
67
|
+
cannot be trained by review.
|