rigortype 0.4.6 → 0.4.8
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 +4 -2
- data/data/core_overlay/bigdecimal.rbs +33 -0
- data/data/core_overlay/resolv.rbs +30 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +45 -13
- data/data/gem_overlay/addressable/addressable.rbs +40 -0
- data/data/vendored_gem_sigs/bundler/bundler.rbs +1 -1
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +4 -3
- data/docs/handbook/01-getting-started.md +6 -3
- data/docs/handbook/11-sig-gen.md +85 -3
- data/docs/handbook/appendix-phpstan.md +4 -4
- data/docs/install.md +20 -0
- data/docs/manual/01-installation.md +67 -26
- data/docs/manual/02-cli-reference.md +455 -113
- data/docs/manual/03-configuration.md +76 -5
- data/docs/manual/04-diagnostics.md +5 -4
- data/docs/manual/06-baseline.md +6 -4
- data/docs/manual/08-skills.md +11 -0
- data/docs/manual/09-editor-integration.md +21 -2
- data/docs/manual/10-mcp-server.md +38 -2
- data/docs/manual/12-caching.md +4 -3
- data/docs/manual/14-rails-quickstart.md +1 -1
- data/docs/manual/19-effect-labels.md +3 -4
- data/docs/manual/plugins/rigor-actionpack.md +32 -15
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +23 -1
- data/docs/manual/plugins/rigor-sorbet.md +17 -3
- data/lib/rigor/analysis/baseline.rb +24 -27
- data/lib/rigor/analysis/check_rules/always_raises_shield.rb +147 -0
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +5 -6
- data/lib/rigor/analysis/check_rules/call_facts.rb +58 -0
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +12 -4
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +85 -13
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +16 -4
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +6 -1
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +5 -8
- data/lib/rigor/analysis/check_rules/plugin_api_surface.rb +195 -0
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +41 -12
- data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +27 -1
- data/lib/rigor/analysis/check_rules/rebinding_block_callees.rb +3 -3
- data/lib/rigor/analysis/check_rules/replaced_singleton_defs.rb +96 -0
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +1 -2
- data/lib/rigor/analysis/check_rules/rule_ids.rb +9 -2
- data/lib/rigor/analysis/check_rules/rule_walk.rb +9 -7
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +3 -4
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +3 -3
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +2 -2
- data/lib/rigor/analysis/check_rules.rb +720 -141
- data/lib/rigor/analysis/crash_signature.rb +45 -3
- data/lib/rigor/analysis/dependency_recorder.rb +237 -80
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +14 -3
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/index.rb +6 -8
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/edit_replay.rb +93 -6
- data/lib/rigor/analysis/fact_store.rb +3 -3
- data/lib/rigor/analysis/incremental.rb +11 -1
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +4 -3
- data/lib/rigor/analysis/incremental_run_slot.rb +2 -2
- data/lib/rigor/analysis/incremental_session.rb +306 -53
- data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -3
- data/lib/rigor/analysis/rule_catalog.rb +39 -3
- data/lib/rigor/analysis/run_cache_key.rb +27 -3
- data/lib/rigor/analysis/run_disclosure_credit.rb +26 -6
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -2
- data/lib/rigor/analysis/runner/declaration_position.rb +8 -8
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +264 -112
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +4 -9
- data/lib/rigor/analysis/runner/pool_coordinator.rb +173 -328
- data/lib/rigor/analysis/runner/project_pre_passes.rb +4 -37
- data/lib/rigor/analysis/runner/run_level_facts.rb +304 -0
- data/lib/rigor/analysis/runner/run_snapshots.rb +44 -54
- data/lib/rigor/analysis/runner/worker_payload.rb +36 -0
- data/lib/rigor/analysis/runner.rb +298 -109
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +62 -23
- data/lib/rigor/analysis/template_unit_positions.rb +2 -3
- data/lib/rigor/analysis/template_units.rb +9 -1
- data/lib/rigor/analysis/worker_session.rb +65 -71
- data/lib/rigor/bleeding_edge.rb +22 -10
- data/lib/rigor/builtins/imported_refinements.rb +6 -8
- data/lib/rigor/builtins/predefined_constant_refinements.rb +1 -1
- data/lib/rigor/builtins/regex_refinement.rb +4 -6
- data/lib/rigor/cache/descriptor.rb +6 -5
- data/lib/rigor/cache/file_digest.rb +39 -31
- data/lib/rigor/cache/incremental_snapshot.rb +95 -17
- data/lib/rigor/cache/rbs_cache_producer.rb +2 -2
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +1 -1
- data/lib/rigor/cache/rbs_class_type_param_names.rb +2 -2
- data/lib/rigor/cache/rbs_constant_table.rb +1 -1
- data/lib/rigor/cache/rbs_descriptor.rb +90 -4
- data/lib/rigor/cache/rbs_environment.rb +8 -1
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +2 -2
- data/lib/rigor/cache/rbs_known_class_names.rb +1 -1
- data/lib/rigor/cache/store.rb +11 -10
- data/lib/rigor/ci_detector.rb +1 -1
- data/lib/rigor/cli/annotate_command.rb +24 -19
- data/lib/rigor/cli/baseline_command.rb +160 -57
- data/lib/rigor/cli/catalogue.rb +256 -0
- data/lib/rigor/cli/check_command.rb +112 -104
- data/lib/rigor/cli/check_runner_factory.rb +2 -2
- data/lib/rigor/cli/command.rb +15 -1
- data/lib/rigor/cli/coverage_command.rb +21 -8
- data/lib/rigor/cli/coverage_mutation.rb +5 -7
- data/lib/rigor/cli/coverage_renderer.rb +2 -1
- data/lib/rigor/cli/coverage_scan.rb +3 -5
- data/lib/rigor/cli/diff_command.rb +25 -20
- data/lib/rigor/cli/docs_command.rb +1 -2
- data/lib/rigor/cli/doctor_command.rb +12 -12
- data/lib/rigor/cli/effects_command.rb +50 -40
- data/lib/rigor/cli/effects_diff_renderer.rb +18 -17
- data/lib/rigor/cli/effects_explain_renderer.rb +13 -12
- data/lib/rigor/cli/effects_renderer.rb +2 -1
- data/lib/rigor/cli/effects_snapshot_command.rb +26 -18
- data/lib/rigor/cli/explain_command.rb +18 -8
- data/lib/rigor/cli/fused_protection_renderer.rb +2 -1
- data/lib/rigor/cli/json_document.rb +41 -0
- data/lib/rigor/cli/lens_command.rb +29 -10
- data/lib/rigor/cli/lsp_command.rb +250 -23
- data/lib/rigor/cli/mcp_command.rb +12 -7
- data/lib/rigor/cli/mutation_fork_scan.rb +1 -1
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -2
- data/lib/rigor/cli/options.rb +40 -1
- data/lib/rigor/cli/plugin_command.rb +93 -46
- data/lib/rigor/cli/plugins_command.rb +17 -18
- data/lib/rigor/cli/plugins_renderer.rb +10 -6
- data/lib/rigor/cli/protection_fork_scan.rb +2 -2
- data/lib/rigor/cli/protection_renderer.rb +2 -1
- data/lib/rigor/cli/show_bleedingedge_command.rb +21 -15
- data/lib/rigor/cli/sig_gen_command.rb +92 -27
- data/lib/rigor/cli/skill_command.rb +32 -3
- data/lib/rigor/cli/skill_deep_probe.rb +1 -1
- data/lib/rigor/cli/skill_describe.rb +2 -1
- data/lib/rigor/cli/trace_command.rb +14 -9
- data/lib/rigor/cli/triage_command.rb +10 -11
- data/lib/rigor/cli/triage_renderer.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +16 -11
- data/lib/rigor/cli/type_of_project_scope.rb +1 -4
- data/lib/rigor/cli/type_of_renderer.rb +4 -1
- data/lib/rigor/cli/type_scan_command.rb +14 -9
- data/lib/rigor/cli/type_scan_renderer.rb +2 -1
- data/lib/rigor/cli/unused_command.rb +27 -17
- data/lib/rigor/cli/upgrade_command.rb +5 -0
- data/lib/rigor/cli.rb +214 -56
- data/lib/rigor/config_audit.rb +33 -19
- data/lib/rigor/configuration/severity_profile.rb +14 -5
- data/lib/rigor/configuration.rb +104 -35
- data/lib/rigor/effects/collector.rb +53 -21
- data/lib/rigor/effects/definition_context.rb +0 -2
- data/lib/rigor/effects/envelope.rb +1 -1
- data/lib/rigor/effects/framework_units.rb +1 -1
- data/lib/rigor/effects/mutation_classifier.rb +4 -7
- data/lib/rigor/effects/propagator.rb +1 -1
- data/lib/rigor/effects/registry.rb +2 -2
- data/lib/rigor/effects/snapshot.rb +1 -1
- data/lib/rigor/effects/taint_cause.rb +0 -2
- data/lib/rigor/effects/unit_scan.rb +9 -13
- data/lib/rigor/environment/bundle_sig_discovery.rb +64 -33
- data/lib/rigor/environment/class_registry.rb +3 -3
- data/lib/rigor/environment/constant_type_cache_holder.rb +5 -0
- data/lib/rigor/environment/core_root.rb +77 -0
- data/lib/rigor/environment/default_libraries.rb +18 -1
- data/lib/rigor/environment/deferred_signature_plan.rb +381 -0
- data/lib/rigor/environment/gated_signature_guard.rb +1 -1
- data/lib/rigor/environment/gated_signature_plan.rb +5 -2
- data/lib/rigor/environment/hkt_registry_holder.rb +6 -0
- data/lib/rigor/environment/lockfile_resolver.rb +28 -12
- data/lib/rigor/environment/member_consistency/comparator.rb +18 -1
- data/lib/rigor/environment/member_consistency.rb +56 -7
- data/lib/rigor/environment/missing_gem_constant_index.rb +3 -2
- data/lib/rigor/environment/project_path_gems.rb +124 -0
- data/lib/rigor/environment/rbs_collection_discovery.rb +123 -8
- data/lib/rigor/environment/rbs_coverage_report.rb +12 -11
- data/lib/rigor/environment/rbs_hierarchy.rb +12 -15
- data/lib/rigor/environment/rbs_loader.rb +772 -110
- data/lib/rigor/environment/reflection.rb +7 -7
- data/lib/rigor/environment/required_features.rb +0 -3
- data/lib/rigor/environment/ruby_library_roots.rb +1 -1
- data/lib/rigor/environment/vendored_signature_plan.rb +153 -0
- data/lib/rigor/environment.rb +169 -42
- data/lib/rigor/flow_contribution/merger.rb +4 -4
- data/lib/rigor/inference/acceptance.rb +136 -40
- data/lib/rigor/inference/alias_mutation_floor/foreign_locals.rb +117 -0
- data/lib/rigor/inference/alias_mutation_floor/memos.rb +85 -0
- data/lib/rigor/inference/alias_mutation_floor/reach.rb +119 -0
- data/lib/rigor/inference/alias_mutation_floor/site_collector.rb +252 -0
- data/lib/rigor/inference/alias_mutation_floor.rb +339 -0
- data/lib/rigor/inference/anonymous_meta_class.rb +18 -0
- data/lib/rigor/inference/block_auto_splat.rb +1 -1
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/block_run_count.rb +185 -0
- data/lib/rigor/inference/budget_trace.rb +8 -2
- data/lib/rigor/inference/builtins/array_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/exception_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/numeric_catalog.rb +2 -5
- data/lib/rigor/inference/builtins/random_catalog.rb +2 -2
- data/lib/rigor/inference/callee_mutation_chain.rb +88 -77
- data/lib/rigor/inference/callee_write_census.rb +815 -0
- data/lib/rigor/inference/captured_locals.rb +2 -0
- data/lib/rigor/inference/census_foreign_block.rb +354 -0
- data/lib/rigor/inference/clause_widening.rb +1 -1
- data/lib/rigor/inference/closure_escape_analyzer.rb +11 -4
- data/lib/rigor/inference/construction_escape.rb +258 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +1 -1
- data/lib/rigor/inference/declaration_walk.rb +4 -0
- data/lib/rigor/inference/deep_erasure.rb +39 -7
- data/lib/rigor/inference/def_handle.rb +1 -1
- data/lib/rigor/inference/def_node_resolver.rb +33 -15
- data/lib/rigor/inference/def_return_typer.rb +47 -5
- data/lib/rigor/inference/definer_resolution.rb +19 -9
- data/lib/rigor/inference/definers_index.rb +162 -0
- data/lib/rigor/inference/direct_ivar_writes.rb +300 -0
- data/lib/rigor/inference/element_read_widening.rb +49 -3
- data/lib/rigor/inference/error_info.rb +16 -0
- data/lib/rigor/inference/expression_typer.rb +1559 -320
- data/lib/rigor/inference/external_ancestor_resolution.rb +3 -4
- data/lib/rigor/inference/flow_tracer.rb +31 -14
- data/lib/rigor/inference/fork_map.rb +3 -0
- data/lib/rigor/inference/fresh_frame_blocks.rb +52 -1
- data/lib/rigor/inference/global_write_census.rb +81 -5
- data/lib/rigor/inference/global_writer_reach.rb +260 -0
- data/lib/rigor/inference/hkt_body.rb +1 -2
- data/lib/rigor/inference/hkt_body_parser.rb +3 -5
- data/lib/rigor/inference/hkt_reducer.rb +2 -2
- data/lib/rigor/inference/hkt_registry.rb +3 -5
- data/lib/rigor/inference/in_effect_refinements.rb +7 -0
- data/lib/rigor/inference/indexed_narrowing.rb +61 -15
- data/lib/rigor/inference/intervening_ivar_reset.rb +26 -4
- data/lib/rigor/inference/ivar_writer_census.rb +154 -8
- data/lib/rigor/inference/key_presence_guard.rb +51 -24
- data/lib/rigor/inference/last_line/self_evidence.rb +30 -0
- data/lib/rigor/inference/last_line.rb +5 -2
- data/lib/rigor/inference/loop_value_record.rb +66 -14
- data/lib/rigor/inference/match_rebinding/frame.rb +57 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +101 -0
- data/lib/rigor/inference/match_rebinding.rb +28 -5
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/argument_distribution.rb +40 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +44 -30
- data/lib/rigor/inference/method_dispatcher/class_keyed_block_params.rb +65 -0
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/contested_overloads.rb +89 -0
- data/lib/rigor/inference/method_dispatcher/core_enumerable_receiver.rb +44 -0
- data/lib/rigor/inference/method_dispatcher/declared_constructor.rb +151 -0
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/interface_shape.rb +181 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/no_match_fallback.rb +54 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +51 -27
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +606 -78
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +9 -7
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +467 -84
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +0 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +50 -17
- data/lib/rigor/inference/method_dispatcher/singleton_type_params.rb +104 -0
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -5
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +4 -6
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +123 -25
- data/lib/rigor/inference/method_parameter_binder.rb +136 -56
- data/lib/rigor/inference/module_function_state/spellings.rb +2 -2
- data/lib/rigor/inference/module_function_state.rb +24 -3
- data/lib/rigor/inference/multi_target_binder.rb +2 -2
- data/lib/rigor/inference/mutation_rejoin.rb +240 -4
- data/lib/rigor/inference/mutation_widening.rb +199 -29
- data/lib/rigor/inference/narrowing.rb +238 -50
- data/lib/rigor/inference/operand_effects.rb +43 -2
- data/lib/rigor/inference/optimistic_origin.rb +134 -9
- data/lib/rigor/inference/origin_lookup.rb +1 -1
- data/lib/rigor/inference/out_buffer_mutation.rb +72 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +5 -6
- data/lib/rigor/inference/pre_eval_constants.rb +1 -1
- data/lib/rigor/inference/precision_scanner.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +30 -9
- data/lib/rigor/inference/project_patched_methods.rb +65 -13
- data/lib/rigor/inference/project_patched_scanner.rb +120 -25
- data/lib/rigor/inference/project_patched_visibility.rb +39 -3
- data/lib/rigor/inference/project_yielder.rb +11 -17
- data/lib/rigor/inference/rbs_type_translator.rb +68 -15
- data/lib/rigor/inference/receiver_alias.rb +20 -0
- data/lib/rigor/inference/receiver_writer_call.rb +67 -0
- data/lib/rigor/inference/recursion_rebinding.rb +157 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +57 -17
- data/lib/rigor/inference/refined_dispatch/own_method.rb +51 -16
- data/lib/rigor/inference/refined_dispatch.rb +13 -0
- data/lib/rigor/inference/reflective_ivar_write.rb +19 -11
- data/lib/rigor/inference/remover_holder_scan.rb +287 -0
- data/lib/rigor/inference/remover_narrowing.rb +224 -0
- data/lib/rigor/inference/rewrite_mutation.rb +53 -2
- data/lib/rigor/inference/scope_indexer/certainty.rb +0 -1
- data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +13 -6
- data/lib/rigor/inference/scope_indexer/constant_ivar_value.rb +93 -0
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +70 -26
- data/lib/rigor/inference/scope_indexer/derived_param_value.rb +112 -0
- data/lib/rigor/inference/scope_indexer/empty_seed.rb +99 -0
- data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +295 -0
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +136 -9
- data/lib/rigor/inference/scope_indexer.rb +2213 -226
- data/lib/rigor/inference/self_call_ivar_writes.rb +103 -12
- data/lib/rigor/inference/self_preserving_block.rb +87 -0
- data/lib/rigor/inference/set_mutation.rb +189 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +42 -8
- data/lib/rigor/inference/singleton_object_constant.rb +32 -2
- data/lib/rigor/inference/statement_evaluator.rb +3268 -358
- data/lib/rigor/inference/string_mutation.rb +14 -0
- data/lib/rigor/inference/struct_fold_safety.rb +4 -6
- data/lib/rigor/inference/synthetic_method_scanner.rb +40 -17
- data/lib/rigor/inference/toplevel_def_census.rb +67 -0
- data/lib/rigor/inference/unknown_store_widening.rb +103 -4
- data/lib/rigor/inference/unthreaded_rebinds.rb +2 -3
- data/lib/rigor/inference/untyped_rejoin.rb +1 -1
- data/lib/rigor/inference/void_tail_summary.rb +29 -9
- data/lib/rigor/language_server/buffer_table.rb +3 -3
- data/lib/rigor/language_server/completion_provider.rb +26 -20
- data/lib/rigor/language_server/config_warning_announcer.rb +28 -0
- data/lib/rigor/language_server/diagnostic_publisher.rb +8 -3
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -2
- data/lib/rigor/language_server/hover_provider.rb +1 -7
- data/lib/rigor/language_server/hover_renderer.rb +6 -8
- data/lib/rigor/language_server/project_context.rb +39 -1
- data/lib/rigor/language_server/publish_batcher.rb +3 -4
- data/lib/rigor/language_server/selection_range_provider.rb +2 -4
- data/lib/rigor/language_server/server.rb +7 -3
- data/lib/rigor/language_server/signature_help_provider.rb +4 -4
- data/lib/rigor/lens/claims/comparison.rb +78 -0
- data/lib/rigor/lens/claims/request.rb +131 -0
- data/lib/rigor/lens/claims/type_reader.rb +216 -0
- data/lib/rigor/lens/claims.rb +208 -0
- data/lib/rigor/lens/contract_reader.rb +5 -0
- data/lib/rigor/lens/document.rb +1 -1
- data/lib/rigor/lens/file_reader.rb +21 -8
- data/lib/rigor/lens/plugins.rb +1 -1
- data/lib/rigor/lens/run.rb +8 -0
- data/lib/rigor/lens.rb +1 -1
- data/lib/rigor/library_probe.rb +68 -0
- data/lib/rigor/mcp/server.rb +73 -2
- data/lib/rigor/mcp.rb +1 -1
- data/lib/rigor/memo_audit.rb +282 -0
- data/lib/rigor/plugin/access_denied_error.rb +1 -2
- data/lib/rigor/plugin/base.rb +15 -2
- data/lib/rigor/plugin/bundled_catalog.rb +1 -12
- data/lib/rigor/plugin/io_boundary.rb +26 -4
- data/lib/rigor/plugin/loader.rb +25 -8
- data/lib/rigor/plugin/macro/heredoc_template.rb +7 -8
- data/lib/rigor/plugin/macro/trait_registry.rb +6 -9
- data/lib/rigor/plugin/manifest.rb +16 -16
- data/lib/rigor/plugin/registry.rb +16 -5
- data/lib/rigor/plugin/services.rb +2 -3
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -0
- data/lib/rigor/plugin/trust_policy.rb +48 -2
- data/lib/rigor/plugin/type_node_resolver.rb +2 -4
- data/lib/rigor/plugin.rb +6 -8
- data/lib/rigor/plugin_gap_advisory.rb +5 -1
- data/lib/rigor/project_environment.rb +16 -2
- data/lib/rigor/protection/analysis_guard.rb +1 -1
- data/lib/rigor/protection/discovery_seed.rb +44 -5
- data/lib/rigor/protection/mutation_cache.rb +4 -1
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/hkt_directives.rb +6 -10
- data/lib/rigor/rbs_extended/reporter.rb +27 -3
- data/lib/rigor/rbs_extended.rb +2 -3
- data/lib/rigor/reflection/constant_ancestors.rb +81 -22
- data/lib/rigor/reflection/declaration_collectors.rb +55 -0
- data/lib/rigor/reflection/declarations.rb +58 -0
- data/lib/rigor/reflection/project_method.rb +177 -0
- data/lib/rigor/reflection.rb +2 -0
- data/lib/rigor/rooted_glob.rb +32 -1
- data/lib/rigor/run_scoped_slots.rb +38 -0
- data/lib/rigor/runtime/jit.rb +1 -1
- data/lib/rigor/scope/discovery_index.rb +168 -8
- data/lib/rigor/scope/resolution_chain/relevance.rb +14 -1
- data/lib/rigor/scope/resolution_chain.rb +901 -54
- data/lib/rigor/scope.rb +644 -37
- data/lib/rigor/sig_gen/bot_proposal_guard.rb +306 -0
- data/lib/rigor/sig_gen/classification.rb +18 -1
- data/lib/rigor/sig_gen/effect_annotation.rb +3 -3
- data/lib/rigor/sig_gen/generator.rb +588 -66
- data/lib/rigor/sig_gen/generic_header_scan.rb +189 -0
- data/lib/rigor/sig_gen/inline_declarations.rb +2 -2
- data/lib/rigor/sig_gen/layout_index.rb +3 -3
- data/lib/rigor/sig_gen/method_candidate.rb +37 -4
- data/lib/rigor/sig_gen/observation_collector.rb +14 -7
- data/lib/rigor/sig_gen/observed_call.rb +1 -1
- data/lib/rigor/sig_gen/path_mapper.rb +6 -0
- data/lib/rigor/sig_gen/platform_guarded_files.rb +184 -0
- data/lib/rigor/sig_gen/renderer.rb +15 -9
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +62 -2
- data/lib/rigor/sig_gen/type_name_qualification.rb +69 -0
- data/lib/rigor/sig_gen/write_reporter.rb +63 -14
- data/lib/rigor/sig_gen/write_result.rb +23 -12
- data/lib/rigor/sig_gen/writer.rb +238 -37
- data/lib/rigor/sig_gen.rb +1 -0
- data/lib/rigor/source/forwardable_delegators.rb +122 -0
- data/lib/rigor/source/node_children.rb +13 -0
- data/lib/rigor/type/acceptance_router.rb +2 -2
- data/lib/rigor/type/accepts_result.rb +1 -1
- data/lib/rigor/type/app.rb +4 -6
- data/lib/rigor/type/combinator.rb +173 -21
- data/lib/rigor/type/constant.rb +4 -5
- data/lib/rigor/type/hash_shape.rb +21 -40
- data/lib/rigor/type/interface.rb +60 -0
- data/lib/rigor/type/union.rb +1 -1
- data/lib/rigor/type.rb +1 -0
- data/lib/rigor/type_node/identifier.rb +1 -2
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node/string_literal.rb +1 -2
- data/lib/rigor/type_node/symbol_literal.rb +1 -2
- data/lib/rigor/type_node/union.rb +3 -6
- data/lib/rigor/type_of_memo/serving.rb +99 -0
- data/lib/rigor/type_of_memo/stats.rb +43 -0
- data/lib/rigor/type_of_memo.rb +337 -0
- data/lib/rigor/typing_state.rb +1094 -0
- data/lib/rigor/value_semantics.rb +1 -10
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +2 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +2 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +1 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +38 -36
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +4 -2
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -5
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +2 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +3 -3
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +115 -36
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +3 -6
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +25 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +16 -6
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +4 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +4 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +2 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +21 -31
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +10 -16
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +132 -33
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +20 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +7 -4
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +54 -17
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +19 -5
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +3 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +1 -1
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +11 -14
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +1 -1
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/symbolize_keys.rb +102 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +30 -9
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +55 -13
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +15 -21
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +1 -6
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +3 -3
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +1 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +6 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +5 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +1 -1
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/params_shape.rb +2 -3
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +5 -8
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +10 -18
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +0 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +0 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +8 -7
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +0 -2
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +6 -7
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +12 -2
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +2 -4
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +2 -5
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +8 -2
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +6 -6
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +3 -8
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +2 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +5 -8
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +200 -4
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +4 -11
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +4 -3
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +2 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +5 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +2 -2
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +3 -4
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +6 -8
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +3 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +6 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +210 -3
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +146 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +52 -34
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +97 -24
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +2 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +16 -16
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +4 -8
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +4 -4
- data/sig/rigor/analysis/baseline.rbs +0 -3
- data/sig/rigor/analysis/check_rules/rule_walk.rbs +6 -0
- data/sig/rigor/analysis/fact_store.rbs +2 -2
- data/sig/rigor/analysis/reachability/scan_cache.rbs +1 -1
- data/sig/rigor/cache/descriptor.rbs +14 -0
- data/sig/rigor/cli/diff_command.rbs +1 -1
- data/sig/rigor/cli/explain_command.rbs +1 -1
- data/sig/rigor/effects/registry.rbs +2 -2
- data/sig/rigor/environment.rbs +4 -1
- data/sig/rigor/inference.rbs +4 -1
- data/sig/rigor/plugin/additional_initializer.rbs +0 -5
- data/sig/rigor/plugin/base.rbs +53 -18
- data/sig/rigor/plugin/effect_attribution.rbs +3 -3
- data/sig/rigor/plugin/effect_edge.rbs +1 -1
- data/sig/rigor/plugin/effect_entry_points.rbs +3 -3
- data/sig/rigor/plugin/interfaces.rbs +51 -0
- data/sig/rigor/plugin/io_boundary.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +9 -9
- data/sig/rigor/plugin/node_context.rbs +21 -0
- data/sig/rigor/plugin/protocol_contract.rbs +3 -7
- data/sig/rigor/reflection.rbs +37 -0
- data/sig/rigor/scope.rbs +43 -4
- data/sig/rigor/trinary.rbs +1 -0
- data/sig/rigor/type.rbs +9 -3
- data/sig/rigor.rbs +3 -2
- data/skills/rigor-ask/SKILL.md +1 -0
- data/skills/rigor-plugin-author/SKILL.md +4 -4
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +5 -5
- data/skills/rigor-plugin-review/SKILL.md +3 -3
- data/skills/rigor-project-init/references/01-detect.md +1 -0
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +17 -2
- data/skills/rigor-project-init/references/06-agent-contract.md +4 -4
- data/skills/rigor-rbs-contract/SKILL.md +147 -0
- data/skills/rigor-rbs-contract/references/01-finding-candidates.md +212 -0
- data/skills/rigor-rbs-contract/references/02-contract-rules.md +157 -0
- data/skills/rigor-rbs-contract/references/03-target-own-code.md +90 -0
- data/skills/rigor-rbs-contract/references/04-target-gem-rbs-collection.md +210 -0
- data/skills/rigor-rbs-contract/references/05-declaration-mutants.md +182 -0
- data/skills/rigor-rbs-setup/SKILL.md +3 -1
- data/skills/rigor-type-oracle/SKILL.md +26 -1
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +4 -3
- metadata +82 -3
|
@@ -10,6 +10,8 @@ rigor <command> [options] [arguments]
|
|
|
10
10
|
`rigor help` prints the command list; `rigor version` prints
|
|
11
11
|
the installed version. An unknown command, or a malformed
|
|
12
12
|
option, exits `64` — the conventional "usage error" code.
|
|
13
|
+
See [`rigor help`](#rigor-help) for a single command's help and
|
|
14
|
+
the machine-readable list of commands and flags.
|
|
13
15
|
|
|
14
16
|
Every command that loads your project configuration also
|
|
15
17
|
accepts `--config=PATH` to point at a specific config file
|
|
@@ -46,7 +48,7 @@ check their arity, since another file may redefine them.
|
|
|
46
48
|
| `--no-cache` | Skip the persistent cache for this run. With `--incremental` it is a cold full analysis: the incremental snapshot and the run-result cache are neither read nor written, so the next plain `--incremental` run still uses the snapshot it had before. |
|
|
47
49
|
| `--incremental` | Re-analyse only the files changed since the last run plus the files that depend on them, serving the rest from a cross-process disk snapshot (ADR-46). Diagnostics are identical to a full run; a config / gem / version change (or a file added or removed) transparently forces a full re-analysis. A run with nothing changed is answered from the cache without starting the analyzer. See [Caching](12-caching.md). |
|
|
48
50
|
| `--verify-incremental` | Acceptance gate: run the incremental analyzer against a full `--no-cache` run and assert the diagnostics agree as a set and in the same order, then exit (0 on match, 1 on mismatch: the differing diagnostics for a set mismatch, or the first index where the order diverges for a same-set, different-order mismatch). It re-analyses half of an unchanged tree and serves the other half from cache, so it checks the cache-merge path but not that an edit re-checks every file it affects; `--verify-incremental-edits` adds that. |
|
|
49
|
-
| `--verify-incremental-edits=N` | With `--verify-incremental` (and implying it): after the check above, replay
|
|
51
|
+
| `--verify-incremental-edits=N` | With `--verify-incremental` (and implying it): after the check above, replay edits on each of `N` files spread over the analysed list, through an editor buffer, never on disk: the file emptied; the file reduced to its `class` / `module` declarations with every body dropped (skipped when that is the file itself, or holds no declaration); and up to two copies of the file each missing one statement of a `class` / `module` body, with everything else kept, so a finer dependency edge is the only thing that re-checks a reader (visibility calls such as `private` and `module_function` are dropped first, then other statements spread over the file). After each edit, the warm recheck of the baseline must equal a full analysis of the edited tree, or the run fails naming the edit and the file. Each replay costs a recheck and a full analysis. A replay the recheck declines (it would have been a full analysis) is counted in the OK line, and the run fails if every replay declined. Only removals are replayed, never an addition. Default 0. |
|
|
50
52
|
| `--clear-cache` | Delete the cache directory before running. |
|
|
51
53
|
| `--cache-stats` | Print the on-disk cache inventory when finished — on stdout under `--format text`, on stderr under every other format, so machine-readable output stays a parseable document. `--clear-cache`'s and `--verify-incremental`'s notes follow the same rule. |
|
|
52
54
|
| `--[no-]stats` | Print a run summary (files, classes, memory, wall time) to stderr. Default on. |
|
|
@@ -60,7 +62,7 @@ check their arity, since another file may redefine them.
|
|
|
60
62
|
| `--bleeding-edge[=ids]` | Adopt the bleeding-edge overlay for this run, overriding the configured [`bleeding_edge:`](03-configuration.md) selection (ADR-50 § WD2). Bare adopts every queued feature; `--bleeding-edge=a,b` adopts only the named feature ids. Inspect it with [`rigor show-bleedingedge`](#rigor-show-bleedingedge). |
|
|
61
63
|
| `--no-bleeding-edge` | Ignore any configured `bleeding_edge:` selection for this run (adopt none). |
|
|
62
64
|
| `--no-tolerated-effects` | Check effect envelopes as if [`effects.tolerated:`](03-configuration.md) were empty — the audit switch for your discharge policy (ADR-103). Judgment only: the run, what it collects and its cache entry are identical either way, so this never costs a re-analysis. |
|
|
63
|
-
| `--tmp-file=PATH --instead-of=PATH` | Editor mode: analyse `PATH` using the buffer in `--tmp-file`. Both required together. Alone, only the buffer's own file produces diagnostics; add `--incremental` for whole-project scope (see below). |
|
|
65
|
+
| `--tmp-file=PATH --instead-of=PATH` | Editor mode: analyse `PATH` using the buffer in `--tmp-file`. Both required together, once per run (a repeat is a usage error). Alone, only the buffer's own file produces diagnostics; add `--incremental` for whole-project scope (see below). |
|
|
64
66
|
|
|
65
67
|
Exit `0` when no error-severity diagnostics remain, `1` when
|
|
66
68
|
any are reported, `64` on a usage error. `--fail-on` raises that
|
|
@@ -70,14 +72,16 @@ that want the stricter reading.
|
|
|
70
72
|
### Editor mode scope
|
|
71
73
|
|
|
72
74
|
`--tmp-file` / `--instead-of` on their own analyse **only** the
|
|
73
|
-
buffer's file.
|
|
74
|
-
|
|
75
|
+
buffer's file. The `--instead-of` logical path is analysed even when it
|
|
76
|
+
lies outside `paths:`, as it always has been. It still reads the rest of the
|
|
77
|
+
project's declarations (the classes and methods other files define), as `rigor check FILE`
|
|
75
78
|
does, but it reports nothing about what the unsaved edit does to the
|
|
76
79
|
rest of the project.
|
|
77
80
|
|
|
78
81
|
Adding `--incremental` analyses the **whole project with the buffer
|
|
79
82
|
substituted** — the edited file and the files that depend on it are
|
|
80
83
|
re-analysed, everything else is served from the incremental snapshot.
|
|
84
|
+
A buffer for a claimed template is analysed as its template unit, once.
|
|
81
85
|
An unsaved change to a method's return type therefore surfaces in its
|
|
82
86
|
callers, not just in the file being edited.
|
|
83
87
|
|
|
@@ -91,6 +95,11 @@ Two things to know:
|
|
|
91
95
|
exist only in your editor, and recording them would make the next
|
|
92
96
|
ordinary run believe it had already analysed a file in a state it
|
|
93
97
|
was never in.
|
|
98
|
+
- The buffer's file need not exist on disk yet: a new file is analysed
|
|
99
|
+
as an added file, with or without path arguments.
|
|
100
|
+
- Editor mode binds one buffer per run. Repeating `--tmp-file` or
|
|
101
|
+
`--instead-of` is a usage error (exit `64`), not a silent replacement
|
|
102
|
+
of the earlier pair.
|
|
94
103
|
|
|
95
104
|
`--verify-incremental` refuses a buffer: it compares against a full
|
|
96
105
|
analysis of the files on disk, which a buffer contradicts by
|
|
@@ -101,31 +110,82 @@ construction.
|
|
|
101
110
|
Write a starter configuration file.
|
|
102
111
|
|
|
103
112
|
```sh
|
|
104
|
-
rigor init [--path=PATH] [--force]
|
|
113
|
+
rigor init [--path=PATH] [--force] [--no-plugins]
|
|
105
114
|
```
|
|
106
115
|
|
|
107
116
|
Writes `.rigor.dist.yml` by default. `--path` chooses a
|
|
108
117
|
different target; `--force` overwrites an existing file.
|
|
109
|
-
Exit `1` if the file exists and `--force` was not given.
|
|
118
|
+
Exit `1` if the file exists and `--force` was not given. A `--path` whose
|
|
119
|
+
directory does not exist, or that cannot be written, is a usage error: one
|
|
120
|
+
`rigor init: cannot write PATH: REASON` line on stderr and exit `64`. The
|
|
121
|
+
directory is not created.
|
|
122
|
+
|
|
123
|
+
When the project has a `Gemfile.lock` in the working directory,
|
|
124
|
+
`rigor init` suggests the bundled plugins whose gems the lockfile
|
|
125
|
+
declares (the same read as [`rigor doctor`](#rigor-doctor)'s
|
|
126
|
+
plugin-gap check). The suggestions are commented out under
|
|
127
|
+
`plugins: []`, so nothing loads until you enable one: delete the
|
|
128
|
+
`[]` on the `plugins:` line, uncomment the entries you want, then
|
|
129
|
+
run `rigor plugins --strict`. A Rails project's `rails` also brings
|
|
130
|
+
in the Rails family, so the list can be long. Without a lockfile,
|
|
131
|
+
or when no locked gem has a bundled plugin, the template has no
|
|
132
|
+
suggestions.
|
|
133
|
+
|
|
134
|
+
Suggesting rather than enabling follows ADR-96 Criterion 2: a
|
|
135
|
+
lockfile's presence does not by itself opt a project into a
|
|
136
|
+
plugin's code.
|
|
137
|
+
|
|
138
|
+
In a Rails application (a `config/application.rb` in the working
|
|
139
|
+
directory), `rigor init` also suggests the source directories that
|
|
140
|
+
exist, `app` and `lib`. The active `paths:` stays `lib`; the
|
|
141
|
+
suggestion is a commented `paths:` line under it, which names what
|
|
142
|
+
was detected. A bare `rigor check` analyses only `lib` until you
|
|
143
|
+
delete the `paths:` list above and uncomment the line below. Other
|
|
144
|
+
layouts get no directory suggestion.
|
|
145
|
+
|
|
146
|
+
`--no-plugins` writes the template with no plugin suggestions, even
|
|
147
|
+
when a lockfile is present.
|
|
110
148
|
|
|
111
149
|
## `rigor annotate`
|
|
112
150
|
|
|
113
|
-
Reprint a file with every line tagged by the type of the
|
|
114
|
-
expression it evaluates to, as a trailing `#=>` comment. See
|
|
115
|
-
[Inspecting inferred types](05-inspecting-types.md).
|
|
151
|
+
Reprint a source file with every line tagged by the inferred type of the expression it evaluates to, as a trailing `#=>` comment (following the xmpfilter / seeing_is_believing convention). See [Inspecting inferred types](05-inspecting-types.md).
|
|
116
152
|
|
|
117
153
|
```sh
|
|
118
|
-
rigor annotate [
|
|
154
|
+
rigor annotate [options] FILE
|
|
119
155
|
```
|
|
120
156
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
`
|
|
125
|
-
`--
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
157
|
+
| Flag | Purpose |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| `--config=PATH` | Path to `.rigor.yml`. Overrides auto-discovery. |
|
|
160
|
+
| `--format=FORMAT` | Output format (`text` or `json`). Default: `text`. |
|
|
161
|
+
| `--[no-]color` | Force or disable ANSI color (default: auto-detected for a tty; honors `NO_COLOR`). |
|
|
162
|
+
| `--[no-]bat` | Force or disable syntax highlighting through [`bat`](https://github.com/sharkdp/bat) (default: enabled when color is on and `bat` is found on `PATH`). |
|
|
163
|
+
|
|
164
|
+
The positional `FILE` argument is required. For each line, the command locates the last expression evaluated on that line (e.g. the last statement in `1; 2; 3` reports `3`, and a conditional header `if nil` reports its condition) and annotates it with `#=> <type>`. On method definition headers (`def`), the line is annotated with the method's inferred return type rather than the header expression.
|
|
165
|
+
|
|
166
|
+
Annotations are idempotent: re-running `rigor annotate` matches existing `#=>` comments (as well as legacy `#=> dump_type:` comments) and replaces them in-place instead of stacking comments.
|
|
167
|
+
|
|
168
|
+
When color is enabled and `bat` is installed, output is syntax-highlighted via `bat --language=ruby --style=plain --paging=never`. Passing `--no-bat` disables `bat` integration in favor of Rigor's built-in Prism colorizer. `--bat` warns on stderr and falls back to the built-in colorizer if `bat` is not found on `PATH`.
|
|
169
|
+
|
|
170
|
+
In `--format=json`, the command emits a JSON object mapping line numbers to type strings conforming to schema version 1:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"schema_version": 1,
|
|
175
|
+
"annotations": {
|
|
176
|
+
"1": "Integer",
|
|
177
|
+
"2": "String | nil"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Exit `0` on success, `1` if the file does not exist or contains a Prism syntax error, and `64` on usage errors (such as a missing `FILE` argument).
|
|
183
|
+
|
|
184
|
+
## JSON documents
|
|
185
|
+
|
|
186
|
+
Every `--format=json` document Rigor defines whose top level is an object, except the three named below, starts with an integer `schema_version` (currently `1`). Where a flag selects which document is printed, `mode` follows it: `rigor coverage` prints `precision`, `protection`, `mutation` or `protection-fused`, and `rigor plugins` prints `status` or `capabilities`. The key set is contract from v1.0.0: a minor release may add a key, and removing or renaming one needs a major.
|
|
187
|
+
|
|
188
|
+
`rigor lens` (its own `schema` / `revision`), `rigor baseline dump` (`version`) and `rigor check`'s CI formats (`sarif`, `gitlab`, ...) keep their own markers. `rigor type-of`, `rigor explain` and `rigor trace` are the exceptions and still print their current top-level shape (an array; for `type-of` a flat object or `{ results }`; for `explain <skip-reason>` a flat object); the next minor release switches them to `{ "schema_version": 1, "results" | "rules" | "skip_reasons" | "events": [...] }`. Until then each prints a note on stderr, and the matching MCP tools append the same note as an extra text block.
|
|
129
189
|
|
|
130
190
|
## `rigor type-of`
|
|
131
191
|
|
|
@@ -148,7 +208,8 @@ wraps several results in a `results` array. Line queries add a
|
|
|
148
208
|
`line_enumerations` array whose `shown` and `total` counts make
|
|
149
209
|
truncation explicit. `--trace` records fail-soft fallbacks,
|
|
150
210
|
after the rows of a line table in text output. The editor-mode
|
|
151
|
-
`--tmp-file` / `--instead-of` pair is accepted as on `check
|
|
211
|
+
`--tmp-file` / `--instead-of` pair is accepted as on `check`, and a repeated flag is a usage error
|
|
212
|
+
(exit `64`) there too.
|
|
152
213
|
|
|
153
214
|
A class or constant that another project file declares reads as
|
|
154
215
|
`rigor check` types it (`singleton(User)`) when a bare
|
|
@@ -159,9 +220,13 @@ and never writes it. With no reusable snapshot (none yet, or one a
|
|
|
159
220
|
change made unusable, for example a changed configuration, lockfile, `sig/`, `pre_eval:`
|
|
160
221
|
file or required feature, an engine upgrade, or a snapshot written
|
|
161
222
|
for other roots) the probe types the one file on its own, so such a name reads
|
|
162
|
-
`Dynamic[top]`, and it prints nothing about it.
|
|
163
|
-
|
|
164
|
-
parameter
|
|
223
|
+
`Dynamic[top]`, and it prints nothing about it. With
|
|
224
|
+
`parameter_inference: true`, the types `check` infers for an
|
|
225
|
+
unannotated parameter come from the same snapshot (its recorded
|
|
226
|
+
call-site table), so `@v = v` reads as `check` types it, but only
|
|
227
|
+
while no project file has changed since the snapshot (an editor
|
|
228
|
+
buffer whose bytes differ from the snapshot counts as a change); once any file differs, or with the setting off
|
|
229
|
+
or no snapshot, those types are not shared.
|
|
165
230
|
|
|
166
231
|
A template a plugin compiles into Ruby (an ERB view under
|
|
167
232
|
`rigor-actionpack`) is probed the way `rigor check` analyses
|
|
@@ -200,58 +265,144 @@ against `rigor check --no-cache` removes that variable.
|
|
|
200
265
|
|
|
201
266
|
## `rigor lens`
|
|
202
267
|
|
|
203
|
-
Map the declarations of one or more files with their types and
|
|
204
|
-
type provenance (experimental). See
|
|
205
|
-
[Inspecting inferred types](05-inspecting-types.md).
|
|
268
|
+
Map the declarations of one or more files with their types and type provenance (experimental). See [Inspecting inferred types](05-inspecting-types.md).
|
|
206
269
|
|
|
207
270
|
```sh
|
|
208
|
-
rigor lens [
|
|
271
|
+
rigor lens [options] FILE...
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
| Flag | Purpose |
|
|
275
|
+
| --- | --- |
|
|
276
|
+
| `--config=PATH` | Path to `.rigor.yml`. Overrides auto-discovery. |
|
|
277
|
+
| `--format=FORMAT` | Output format (`text` or `json`). Default: `text`. |
|
|
278
|
+
| `--workers=N` | Worker process count for a cold run. |
|
|
279
|
+
| `--claims=REQUEST` | Check documentation type claims against authored contracts (unreleased). Requires `--format=json`. |
|
|
280
|
+
|
|
281
|
+
`rigor lens` performs the same incremental analysis as `rigor check --incremental` and shares its cache (`.rigor/cache`). The first execution on a file costs a full check, while subsequent runs reuse the recorded cache.
|
|
282
|
+
|
|
283
|
+
`--claims=REQUEST` checks documentation type claims against authored contracts in the same run (unreleased). It requires `--format=json` and a UTF-8 JSON request following the [claims contract](../internal-spec/lens-claims.md). The `claims` section reports each claim's verdict; a conflict does not change the exit status. An invalid or stale request exits `64` without a document. Claims do not alter analysis, diagnostics or cached types.
|
|
284
|
+
|
|
285
|
+
### Text representation
|
|
286
|
+
|
|
287
|
+
Text output lists each declaration preceded by an anchor identifier:
|
|
288
|
+
|
|
289
|
+
```text
|
|
290
|
+
lib/shop.rb xxh3-64:845f7426b6acfe12 (2 omitted)
|
|
291
|
+
4:7c90 class Shop
|
|
292
|
+
8:e37e Shop#label: (::Integer n) -> ::String [contract inline]
|
|
293
|
+
14:ce93 Shop#total: () -> Integer [single_site inferred]
|
|
294
|
+
16:182b Shop#fetch [contested; also lib/legacy_shop.rb:2]
|
|
295
|
+
omitted constant Shop::LIMIT (line 5)
|
|
209
296
|
```
|
|
210
297
|
|
|
211
|
-
|
|
212
|
-
`
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
298
|
+
- **`LINE:HASH`**: Stable anchor hash identifying the declaration. It changes when the declaration signature or preceding type comments change, but remains unchanged across prose comment edits.
|
|
299
|
+
- **`provenance`**: The origin of the type in square brackets (e.g. `[contract sig]`, `[contract inline]`, `[single_site inferred]`, `[plugin <name>]`).
|
|
300
|
+
- **`contested`**: Denotes methods where multiple definitions exist in the project (e.g. reopened classes across files); Rigor prints no signature rather than guessing runtime dispatch.
|
|
301
|
+
- **`omitted`**: Constructs not yet modeled by the lens (constants, `alias`, `define_method`) are explicitly recorded as omitted rather than discarded.
|
|
302
|
+
|
|
303
|
+
In `--format=json`, the command outputs a `lens/v0` JSON document (specified in [the lens output contract](../internal-spec/lens.md)).
|
|
304
|
+
|
|
305
|
+
Exit `0` when at least one input file is successfully analysed (`status: "ok"`), `1` when no target achieves `status: "ok"` (the JSON document is still written to stdout), and `64` on usage errors (such as missing `FILE` arguments or an unreadable `--config` path). Diagnostics present in the analysed files do not affect the exit code.
|
|
218
306
|
|
|
219
307
|
## `rigor trace`
|
|
220
308
|
|
|
221
|
-
Replay
|
|
222
|
-
terminal animation. It is a teaching probe over the same
|
|
223
|
-
inference `rigor check` runs.
|
|
309
|
+
Replay how the engine typed a file step-by-step as an interactive terminal animation. It is a teaching and debugging probe operating over the inference engine. See [Inspecting inferred types](05-inspecting-types.md).
|
|
224
310
|
|
|
225
311
|
```sh
|
|
226
|
-
rigor trace [
|
|
312
|
+
rigor trace [options] FILE
|
|
227
313
|
```
|
|
228
314
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
315
|
+
| Flag | Purpose |
|
|
316
|
+
| --- | --- |
|
|
317
|
+
| `--config=PATH` | Path to `.rigor.yml`. Overrides auto-discovery. |
|
|
318
|
+
| `--delay=SECONDS` | Autoplay frames with `SECONDS` delay between steps (default: step manually on key press). |
|
|
319
|
+
| `--line=N` | Replay only inference events whose source range starts on line `N`. |
|
|
320
|
+
| `--verbose` | Include every expression `enter` and `result` frame (default: only teachable inference milestones). |
|
|
321
|
+
| `--format=FORMAT` | Output format: `text` (interactive terminal animation) or `json` (raw event stream). Default: `text`. |
|
|
322
|
+
|
|
323
|
+
### Inference events
|
|
324
|
+
|
|
325
|
+
By default, the replay highlights the AST expression being evaluated alongside the current local variable environment, presenting three core inference event kinds:
|
|
326
|
+
- **`bind`**: A local variable binding enters the active scope.
|
|
327
|
+
- **`union`**: Types from distinct control-flow branches merge into a union type.
|
|
328
|
+
- **`dispatch`**: A method call resolves against its receiver or falls back to `Dynamic[top]`.
|
|
329
|
+
|
|
330
|
+
With `--verbose`, every AST node entry and evaluated type result is captured as a frame.
|
|
331
|
+
|
|
332
|
+
### Interactive navigation
|
|
333
|
+
|
|
334
|
+
On a terminal TTY, the animation advances one frame per key press. Press `q` to exit playback early. Specifying `--delay=SECONDS` enables hands-free autoplay.
|
|
335
|
+
|
|
336
|
+
In `--format=json`, the raw stream of event objects is emitted as a top-level JSON array for external tooling or courseware integration. Like `rigor explain`, it prints a deprecation notice on stderr noting the upcoming `schema_version: 1` envelope migration (see [JSON documents](#json-documents)).
|
|
337
|
+
|
|
338
|
+
Exit `0` on successful playback or stream emission, `1` if the file does not exist or contains syntax errors (Prism parse errors), and `64` on usage errors (such as missing `FILE`, passing multiple files, or invalid flags).
|
|
239
339
|
|
|
240
340
|
## `rigor type-scan`
|
|
241
341
|
|
|
242
|
-
Report `type_of` inference coverage across paths —
|
|
243
|
-
diagnostic-of-the-diagnoser, useful when investigating why a
|
|
244
|
-
class infers poorly.
|
|
342
|
+
Report `Scope#type_of` inference coverage across paths — an engine diagnostic measuring how much of the target source is directly typed without falling back to `Dynamic[top]`.
|
|
245
343
|
|
|
246
344
|
```sh
|
|
247
|
-
rigor type-scan PATH...
|
|
345
|
+
rigor type-scan [options] PATH...
|
|
248
346
|
```
|
|
249
347
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
`--
|
|
253
|
-
|
|
254
|
-
|
|
348
|
+
| Flag | Purpose |
|
|
349
|
+
| --- | --- |
|
|
350
|
+
| `--config=PATH` | Path to `.rigor.yml`. Overrides auto-discovery. |
|
|
351
|
+
| `--format=FORMAT` | Output format (`text` or `json`). Default: `text`. |
|
|
352
|
+
| `--limit=N` | Maximum unrecognized example events to display in text mode. Default: `10`. |
|
|
353
|
+
| `--show-recognized` | Include AST node classes with 0 unrecognized visits in the summary table. |
|
|
354
|
+
| `--threshold=RATIO` | Exit non-zero (`1`) when the ratio of unrecognized nodes (`unrecognized / visits`) exceeds `RATIO` (float). |
|
|
355
|
+
|
|
356
|
+
At least one `PATH` argument is required. The command traverses every Prism node across the specified paths and queries `Scope#type_of` against a discovery-seeded project environment (matching `rigor coverage`).
|
|
357
|
+
|
|
358
|
+
### Output format
|
|
359
|
+
|
|
360
|
+
In text mode, `rigor type-scan` prints a summary block, class breakdown, and unrecognized examples:
|
|
361
|
+
|
|
362
|
+
```text
|
|
363
|
+
Type-of scan: 1 file
|
|
364
|
+
- lib/user.rb
|
|
365
|
+
|
|
366
|
+
Summary:
|
|
367
|
+
files processed: 1
|
|
368
|
+
parse errors: 0
|
|
369
|
+
AST nodes visited: 165
|
|
370
|
+
unrecognized: 14 ( 8.5%)
|
|
371
|
+
|
|
372
|
+
Coverage by node class (unrecognized/visits):
|
|
373
|
+
Prism::CallNode 12/120 ( 10.0%)
|
|
374
|
+
Prism::ConstantReadNode 2/ 45 ( 4.4%)
|
|
375
|
+
|
|
376
|
+
Unrecognized examples (showing 10 of 14):
|
|
377
|
+
Prism::CallNode @ lib/user.rb:14:5
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Passing `--show-recognized` includes node classes with 0 unrecognized visits in the class breakdown. `--limit=N` caps the total number of examples shown in the unrecognized events section.
|
|
381
|
+
|
|
382
|
+
In `--format=json`, the command emits a JSON document conforming to schema version 1:
|
|
383
|
+
|
|
384
|
+
```json
|
|
385
|
+
{
|
|
386
|
+
"schema_version": 1,
|
|
387
|
+
"files": [ "lib/user.rb" ],
|
|
388
|
+
"summary": {
|
|
389
|
+
"files_processed": 1,
|
|
390
|
+
"parse_errors": 0,
|
|
391
|
+
"visited": 165,
|
|
392
|
+
"unrecognized": 14,
|
|
393
|
+
"unrecognized_ratio": 0.0848
|
|
394
|
+
},
|
|
395
|
+
"by_class": {
|
|
396
|
+
"Prism::CallNode": { "visits": 120, "unrecognized": 12 }
|
|
397
|
+
},
|
|
398
|
+
"events": [
|
|
399
|
+
{ "file": "lib/user.rb", "node_class": "Prism::CallNode", "family": "call", "line": 14, "column": 5 }
|
|
400
|
+
],
|
|
401
|
+
"parse_errors": []
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Exit `0` if the unrecognized ratio is within `--threshold` (or when no threshold is set) and no parse errors occurred. Exit `1` if the ratio exceeds `--threshold` or if any scanned file contains parse errors. Exit `64` if no paths are provided, a specified path does not exist, or flags are invalid.
|
|
255
406
|
|
|
256
407
|
## `rigor effects`
|
|
257
408
|
|
|
@@ -384,6 +535,12 @@ origin/main:.rigor-effects.yml)` in a bot),
|
|
|
384
535
|
`explain` additionally accepts `--symbol=KEY` to explain one
|
|
385
536
|
specific unit instead of the changed ones.
|
|
386
537
|
|
|
538
|
+
`update` writes `effects.snapshot.path:` (default
|
|
539
|
+
`.rigor-effects.yml`). A path whose directory does not exist, or
|
|
540
|
+
that cannot be written, is a usage error: one
|
|
541
|
+
`rigor effects: cannot write PATH: REASON` line on stderr and
|
|
542
|
+
exit `64`. The directory is not created.
|
|
543
|
+
|
|
387
544
|
The file records two tables. `methods:` holds each method's
|
|
388
545
|
**direct** summary — what its own body does, block literals
|
|
389
546
|
and catalogued callees included, but not what the project
|
|
@@ -501,38 +658,107 @@ reviewer's judgment, which is what makes it a review artefact.
|
|
|
501
658
|
|
|
502
659
|
## `rigor explain`
|
|
503
660
|
|
|
504
|
-
Print the catalogue entry for a diagnostic rule, or list every
|
|
505
|
-
rule when called with no argument.
|
|
661
|
+
Print the catalogue entry for a diagnostic rule, or list every rule when called with no argument.
|
|
506
662
|
|
|
507
663
|
```sh
|
|
508
|
-
rigor explain [options] [rule]
|
|
664
|
+
rigor explain [options] [<rule>]
|
|
509
665
|
```
|
|
510
666
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
`
|
|
514
|
-
|
|
667
|
+
| Flag | Purpose |
|
|
668
|
+
| --- | --- |
|
|
669
|
+
| `--format=FORMAT` | Output format (`text` or `json`). Default: `text`. |
|
|
670
|
+
|
|
671
|
+
### Invocation modes
|
|
672
|
+
|
|
673
|
+
| Form | Purpose |
|
|
674
|
+
| --- | --- |
|
|
675
|
+
| (none) | Print the complete rule catalogue index (rule ID and one-line summary) followed by every `rigor sig-gen` skip reason. |
|
|
676
|
+
| `<rule>` | Print the full catalogue entry for a canonical rule ID (e.g. `call.undefined-method`) or a legacy alias (e.g. `undefined-method`). |
|
|
677
|
+
| `<family>` | Family wildcard (`call`, `flow`, `def`, `assert`, `dump`, `global`, `suppression`, `static`, `effect`). Prints every rule under that prefix. |
|
|
678
|
+
| `<skip-reason>` | Print the explanation and recommended next action for an exact `rigor sig-gen` skip reason token (e.g. `sig.skipped.untyped-return`). Does not accept wildcards. |
|
|
679
|
+
|
|
680
|
+
A rule entry includes its summary, legacy aliases, authored severity, severity mapped across configuration profiles (`lenient`, `balanced`, `strict`), evidence tier, `Fires when:` conditions, `Does not fire when:` exceptions, inline suppression syntax (`# rigor:disable <rule>`), documentation link, and the Rigor release where the rule was introduced.
|
|
681
|
+
|
|
682
|
+
A `<skip-reason>` token explains why `rigor sig-gen` declined to write a signature (such as dynamic returns or unbounded blocks) and suggests what to address instead. Because skip reasons report signatures that were not written rather than code findings, they carry no severity and nothing to suppress.
|
|
683
|
+
|
|
684
|
+
In `--format=json`, diagnostic rules (whether requested by a single rule ID, legacy alias, family wildcard, or with no arguments) always emit a JSON array of catalogue entry objects. In contrast, querying an individual `<skip-reason>` emits a single JSON object. In the index mode with no arguments, `--format=json` outputs only the diagnostic rule array; individual skip reasons must be queried by token. Top-level JSON shapes currently print a stderr deprecation notice regarding the future envelope migration (see [JSON documents](#json-documents)).
|
|
515
685
|
|
|
516
|
-
|
|
517
|
-
prints when it declines to write a signature — `rigor explain
|
|
518
|
-
sig.skipped.untyped-return` says what the skip means and what to do
|
|
519
|
-
instead. Those are not diagnostic rules, so they are rendered without
|
|
520
|
-
a severity or a suppression line.
|
|
686
|
+
Exit `0` on success, `64` on an unknown rule name or invalid options.
|
|
521
687
|
|
|
522
688
|
## `rigor diff`
|
|
523
689
|
|
|
524
|
-
Compare
|
|
525
|
-
|
|
690
|
+
Compare current diagnostics against a saved `rigor check --format=json` result and report the delta.
|
|
691
|
+
|
|
692
|
+
```sh
|
|
693
|
+
rigor diff [options] <rigor-check.json> [paths...]
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
| Flag | Purpose |
|
|
697
|
+
| --- | --- |
|
|
698
|
+
| `--current=PATH` | Compare against a saved diagnostics JSON file instead of executing a fresh `rigor check` run. |
|
|
699
|
+
| `--config=PATH` | Custom `.rigor.yml` configuration forwarded to the implicit `rigor check` run. Ignored when `--current` is supplied. |
|
|
700
|
+
| `--format=FORMAT` | Output format (`text` or `json`). Default: `text`. |
|
|
701
|
+
|
|
702
|
+
The positional `<rigor-check.json>` file is required. Per ADR-126 § WD1, this file is a saved `rigor check --format=json` result or JSON snapshot, distinct from the rule-bucket `.rigor-baseline.yml` managed by `rigor baseline`.
|
|
703
|
+
|
|
704
|
+
When `[paths...]` are given, only those source paths are evaluated by the implicit check. Note that if `<rigor-check.json>` covers the entire repository, restricting the implicit check to a subset of paths causes all diagnostics in omitted files to be reported as `- FIXED`. When `--current=PATH` is provided, `[paths...]` are ignored.
|
|
705
|
+
|
|
706
|
+
### Identity matching
|
|
707
|
+
|
|
708
|
+
Diagnostic identity is determined by the 6-element tuple:
|
|
709
|
+
|
|
710
|
+
```
|
|
711
|
+
(path, line, column, rule, source_family, message)
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
Diagnostics matching a saved tuple are considered pre-existing. Current diagnostics missing from the saved snapshot are classified as `+ NEW` (regressions). Saved diagnostics missing from the current run are classified as `- FIXED` (progress). Moving code to another line or changing a message produces one fixed and one new entry. Severity is not part of the identity tuple; changing a diagnostic's severity without moving its location does not register as a diff.
|
|
715
|
+
|
|
716
|
+
### Output format
|
|
717
|
+
|
|
718
|
+
Text output reports the diff header, line-by-line additions and removals, and summary counts:
|
|
719
|
+
|
|
720
|
+
```text
|
|
721
|
+
# diff against rigor-check.json (10 baseline / 9 current)
|
|
722
|
+
+ NEW lib/user.rb:14:5 [call.undefined-method] Method `full_name` does not exist on `User`
|
|
723
|
+
- FIXED lib/auth.rb:22:9 [call.argument-type-mismatch] Expected `String`, got `Integer`
|
|
724
|
+
|
|
725
|
+
1 new, 1 fixed
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
With `--format=json`, the output conforms to schema version 1:
|
|
729
|
+
|
|
730
|
+
```json
|
|
731
|
+
{
|
|
732
|
+
"schema_version": 1,
|
|
733
|
+
"baseline": "rigor-check.json",
|
|
734
|
+
"baseline_count": 10,
|
|
735
|
+
"current_count": 9,
|
|
736
|
+
"new": [ ... ],
|
|
737
|
+
"fixed": [ ... ]
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### CI integration
|
|
742
|
+
|
|
743
|
+
`rigor diff` enables regression gating in repositories adopting Rigor incrementally by catching newly introduced diagnostics without requiring all legacy diagnostics to be fixed first.
|
|
744
|
+
|
|
745
|
+
In standard CI workflows, commit a saved snapshot in-tree (e.g. `rigor-check.json`) generated by `rigor check --format=json > rigor-check.json`. In CI, run:
|
|
526
746
|
|
|
527
747
|
```sh
|
|
528
|
-
rigor diff
|
|
748
|
+
rigor diff rigor-check.json
|
|
529
749
|
```
|
|
530
750
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
751
|
+
When comparing against a dynamic base branch in a multi-step job (where `rigor check` on the base branch may exit non-zero due to pre-existing diagnostics), guard the exit code under `set -e`:
|
|
752
|
+
|
|
753
|
+
```sh
|
|
754
|
+
# On base branch (or via git show / artifact)
|
|
755
|
+
rigor check --format=json > /tmp/base-check.json || true
|
|
756
|
+
|
|
757
|
+
# On PR branch
|
|
758
|
+
rigor diff /tmp/base-check.json
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
Exit `0` when no new diagnostics appear (`new` is empty, even if `fixed` contains entries). Exit `1` when any new diagnostic of any severity (`error`, `warning`, or `info`) appears. Exit `64` if either JSON file is missing, contains invalid JSON, or command usage is incorrect.
|
|
536
762
|
|
|
537
763
|
## `rigor sig-gen`
|
|
538
764
|
|
|
@@ -571,10 +797,27 @@ refuse a file, so a tighter return `--write` declines without
|
|
|
571
797
|
`--overwrite` does not fail it; `--check --overwrite` counts one.
|
|
572
798
|
See [handbook chapter 11](../handbook/11-sig-gen.md#keeping-sig-current-in-ci).
|
|
573
799
|
|
|
800
|
+
`--write` also repairs a header in any file under the signature directory it writes to (the directory
|
|
801
|
+
under the project root named like the last path component of the first `signature_paths:` entry, `sig/` by
|
|
802
|
+
default, vendored or generated `.rbs` under it included) that opens a generic class such as
|
|
803
|
+
`class Array` or `class Hash` without its type parameters (an earlier release wrote them), reporting
|
|
804
|
+
`repaired N generic header(s)`, and `--check` fails until it is written. In `--format=json` the row of a file
|
|
805
|
+
no method of the run maps to has `"source": null`. A class is repaired in all of its bare headers or in none:
|
|
806
|
+
when the body of any of them names a type spelt like one of the parameters (`def old: () -> E`), which the
|
|
807
|
+
parameter would capture, or one of them is in another `signature_paths:` entry, which `--write` never
|
|
808
|
+
rewrites, none is repaired. A `generic header left bare` line (`left_bare` in `--format=json`) names the files
|
|
809
|
+
and the reason, and `--check` does not fail on it. Write the name as `::E`, or fix the other file, to let the
|
|
810
|
+
repair through.
|
|
811
|
+
|
|
574
812
|
`--write` names each proposal it skipped (a member `sig/` already declares, an `alias` included, or one that
|
|
575
813
|
routes to a signature path it does not write to, because it is declared there or its class lives there) on its own `skipped Class#method (reason)` line; the exit status is
|
|
576
814
|
unchanged. See [handbook chapter 11](../handbook/11-sig-gen.md#safety-what---write-will-and-will-not-do).
|
|
577
815
|
|
|
816
|
+
A `sig/` target `--write` cannot write — a permission denial, a directory sitting where the `.rbs`
|
|
817
|
+
belongs, or a parent path that is a regular file — is a usage error: one `rigor sig-gen: cannot
|
|
818
|
+
write PATH: REASON` line on stderr and exit `64`. A missing parent directory is created as before.
|
|
819
|
+
The run stops at the first failure; targets already written stay written.
|
|
820
|
+
|
|
578
821
|
A method declared inline with `# @rbs` / `#:` is written as that
|
|
579
822
|
declaration, not as what its body infers; a parameter-only
|
|
580
823
|
annotation keeps its parameters and takes the return from the body,
|
|
@@ -614,7 +857,13 @@ would take every other type in the file down with it. Under
|
|
|
614
857
|
**refused** (the existing file is left untouched) and the command
|
|
615
858
|
exits `1`: you asked for a write and did not get one. Such a skip
|
|
616
859
|
is a bug in Rigor's RBS rendering, not in your code — please
|
|
617
|
-
report it.
|
|
860
|
+
report it. An existing target that does not parse as RBS in the
|
|
861
|
+
first place, and that sig-gen would write into, is refused the same
|
|
862
|
+
way, named on stdout as `REFUSED` with the parse location (the JSON
|
|
863
|
+
action is `skipped_unparseable`); `--check` fails on it too, so such a
|
|
864
|
+
target is never reported as up to date. An unparseable `sig/` file that
|
|
865
|
+
no emittable candidate maps to is not refused and still passes
|
|
866
|
+
`--check`. Fix its syntax error and re-run.
|
|
618
867
|
|
|
619
868
|
A method the generator declined for any other reason (a body
|
|
620
869
|
that proves only `untyped`, a user-authored declaration it will
|
|
@@ -634,10 +883,20 @@ Run the Language Server over stdio. See
|
|
|
634
883
|
rigor lsp [--transport=stdio] [--log=PATH] [--config=PATH]
|
|
635
884
|
```
|
|
636
885
|
|
|
637
|
-
`stdio` is the only transport in v1. `--log=PATH`
|
|
638
|
-
|
|
639
|
-
the server
|
|
640
|
-
|
|
886
|
+
`stdio` is the only transport in v1. `--log=PATH` appends the LSP
|
|
887
|
+
wire log to PATH: each JSON-RPC message the client sends (`<-`) and
|
|
888
|
+
each one the server writes (`->`), one line per message with a
|
|
889
|
+
timestamp, plus the server's debug output from the start of the
|
|
890
|
+
server loop to its end. The file is opened for appending before the
|
|
891
|
+
server starts, so an unwritable PATH exits with a usage error. An
|
|
892
|
+
exception that escapes the loop is written to the file with its
|
|
893
|
+
backtrace. Output written before the loop starts (configuration
|
|
894
|
+
loading and server setup) and any crash outside the loop still go to
|
|
895
|
+
stderr, as does the server's output when the file becomes unwritable
|
|
896
|
+
mid-session. A message the JSON encoder rejects (raw invalid UTF-8) is
|
|
897
|
+
logged in a scrubbed form. Without `--log`, no wire log is written and
|
|
898
|
+
the server's debug output goes to stderr; stdout carries only the
|
|
899
|
+
protocol.
|
|
641
900
|
|
|
642
901
|
## `rigor baseline`
|
|
643
902
|
|
|
@@ -661,6 +920,18 @@ rigor baseline <generate|regenerate|dump|drift|prune> [options]
|
|
|
661
920
|
`--baseline=PATH` to read a non-default baseline file. `dump`
|
|
662
921
|
also accepts `--format=text|json` for machine-readable output.
|
|
663
922
|
|
|
923
|
+
A write target — `generate` and `regenerate`'s `--output`, or the
|
|
924
|
+
`--baseline` file `prune` rewrites — whose directory does not exist,
|
|
925
|
+
or that cannot be written, is a usage error: one
|
|
926
|
+
`rigor baseline: cannot write PATH: REASON` line on stderr and exit
|
|
927
|
+
`64`. The directory is not created.
|
|
928
|
+
|
|
929
|
+
No subcommand takes a positional path: `generate` and `regenerate`
|
|
930
|
+
analyse the configured `paths:`, `drift` and `prune` audit them, and
|
|
931
|
+
`dump` reads the baseline file and filters with `--rule`/`--file`. A path argument is a usage error
|
|
932
|
+
(exit `64`). Narrow the scope with `paths:` in the configuration, not on
|
|
933
|
+
the command line.
|
|
934
|
+
|
|
664
935
|
## `rigor triage`
|
|
665
936
|
|
|
666
937
|
Summarise a diagnostic stream — rule distribution, **class/method
|
|
@@ -1011,30 +1282,50 @@ toolchain, so you can read a real, working plugin as a worked
|
|
|
1011
1282
|
example when authoring your own.
|
|
1012
1283
|
|
|
1013
1284
|
```sh
|
|
1014
|
-
rigor plugin <
|
|
1285
|
+
rigor plugin [<name>] [--path <name>] [--list] [--root]
|
|
1015
1286
|
```
|
|
1016
1287
|
|
|
1017
|
-
|
|
1288
|
+
The positional slot is a plugin *name*; alternative outputs are
|
|
1289
|
+
flags, the same grammar as `rigor skill` and `rigor docs`.
|
|
1290
|
+
|
|
1291
|
+
| Form | Purpose |
|
|
1018
1292
|
| --- | --- |
|
|
1019
|
-
| `list` | Table of every bundled plugin and example, name + absolute directory path (default
|
|
1020
|
-
|
|
|
1021
|
-
|
|
|
1022
|
-
|
|
|
1293
|
+
| `rigor plugin`, `--list` | Table of every bundled plugin and example, name + absolute directory path (the default). |
|
|
1294
|
+
| `<name>` | A header (dir / lib / sig / README paths) followed by the plugin's main source body inlined. |
|
|
1295
|
+
| `--path <name>` | One-line absolute path to the plugin's directory. |
|
|
1296
|
+
| `--root` | The `rigortype` gem root and its key subdirectories. |
|
|
1297
|
+
|
|
1298
|
+
The earlier verbs `list`, `path <name>`, `print <name>` and `root`
|
|
1299
|
+
still work for one minor release and print a deprecation notice on
|
|
1300
|
+
stderr naming the replacement; the output on stdout is the same.
|
|
1023
1301
|
|
|
1024
1302
|
Paths resolve at runtime from the gem location (a documented
|
|
1025
1303
|
caveat for container / cross-filesystem setups).
|
|
1026
1304
|
|
|
1027
1305
|
## `rigor playground`
|
|
1028
1306
|
|
|
1029
|
-
Start
|
|
1030
|
-
real-time diagnostics). Requires the separate `rigor-playground`
|
|
1031
|
-
gem; if it is not installed the command prints an install hint
|
|
1032
|
-
and exits `64`.
|
|
1307
|
+
Start a local browser playground (a CodeMirror editor with real-time Rigor diagnostics and type inspection).
|
|
1033
1308
|
|
|
1034
1309
|
```sh
|
|
1035
|
-
rigor playground
|
|
1310
|
+
rigor playground [options]
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
| Flag | Purpose |
|
|
1314
|
+
| --- | --- |
|
|
1315
|
+
| `--port=PORT` | Port to bind the playground HTTP server to (default: `9393`). |
|
|
1316
|
+
| `--no-open` | Do not automatically open the playground URL in the default browser on launch. |
|
|
1317
|
+
|
|
1318
|
+
The playground requires the separate `rigor-playground` companion gem. When the gem is not installed in the active Ruby environment, the command prints an installation hint on stderr and exits `64` (`CLI::EXIT_USAGE`):
|
|
1319
|
+
|
|
1320
|
+
```text
|
|
1321
|
+
rigor playground requires the rigor-playground gem.
|
|
1322
|
+
Install it with: gem install rigor-playground
|
|
1036
1323
|
```
|
|
1037
1324
|
|
|
1325
|
+
When installed, the command boots the local web server and opens an interactive browser playground where Ruby code can be written, edited, and analyzed with immediate feedback.
|
|
1326
|
+
|
|
1327
|
+
Exit `0` on clean shutdown, `1` if server startup fails (e.g. port already in use), and `64` if `rigor-playground` is missing or on usage errors.
|
|
1328
|
+
|
|
1038
1329
|
## `rigor skill`
|
|
1039
1330
|
|
|
1040
1331
|
List or print the bundled Agent Skills shipped inside the
|
|
@@ -1092,24 +1383,27 @@ they now read as an unknown skill. Use the forms above.
|
|
|
1092
1383
|
|
|
1093
1384
|
## `rigor describe`
|
|
1094
1385
|
|
|
1095
|
-
Top-level alias for [`rigor skill describe`](#rigor-skill) — the
|
|
1096
|
-
onboarding entry point that recommends the next skill for this project.
|
|
1097
|
-
A bare `rigor describe` is the intuitive guess most users reach for
|
|
1098
|
-
first, so it is surfaced as its own command ([ADR-73](../adr/73-skill-driven-user-experience.md)
|
|
1099
|
-
§ WD2).
|
|
1386
|
+
Top-level alias for [`rigor skill describe`](#rigor-skill) — the onboarding entry point that assesses the project's state and recommends the next skill to run ([ADR-73](../adr/73-skill-driven-user-experience.md) § WD2).
|
|
1100
1387
|
|
|
1101
1388
|
```sh
|
|
1102
|
-
rigor describe
|
|
1389
|
+
rigor describe [--deep]
|
|
1103
1390
|
```
|
|
1104
1391
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1392
|
+
| Flag | Purpose |
|
|
1393
|
+
| --- | --- |
|
|
1394
|
+
| `--deep` | Run `rigor check` first and route the headline recommendation on the diagnostic results. |
|
|
1395
|
+
|
|
1396
|
+
### Audit modes
|
|
1397
|
+
|
|
1398
|
+
By default, `rigor describe` performs a presence-only probe checking for the existence of `.rigor.yml`, `.rigor-baseline.yml`, a `sig/` directory, and CI configurations. This default mode is read-only, fast, and side-effect-free — it never executes `rigor check` and never reads or writes `.rigor/cache`.
|
|
1109
1399
|
|
|
1110
|
-
`
|
|
1111
|
-
|
|
1112
|
-
|
|
1400
|
+
Passing `--deep` opts into running `rigor check` before generating recommendations, routing based on analysis health:
|
|
1401
|
+
- **`rigor-doctor`**: Selected if the RBS environment builds with 0 classes or any `configuration-error` diagnostic is raised.
|
|
1402
|
+
- **`rigor-monkeypatch-resolve`**: Selected if at least one third of remaining error diagnostics stem from calls resolving to project-side reopened core or gem definitions (addressable via `pre_eval:`).
|
|
1403
|
+
- **`rigor-baseline-reduce`**: Selected when remaining error diagnostics exist.
|
|
1404
|
+
- **Presence-only recommendation**: Retained when the analysis is completely clean or when no configuration exists yet.
|
|
1405
|
+
|
|
1406
|
+
Output is identical to `rigor skill describe`. Exit `0` on completion, or `64` on invalid options.
|
|
1113
1407
|
|
|
1114
1408
|
## `rigor docs`
|
|
1115
1409
|
|
|
@@ -1175,9 +1469,10 @@ Queued today:
|
|
|
1175
1469
|
| --- | --- | --- |
|
|
1176
1470
|
| `reject-unparseable-signatures` | severity | A broken RBS set **fails the run** instead of degrading it silently: an unparseable `.rbs` under `signature_paths:` (`rbs.coverage.quarantined-signature` → `error`), a declaration that collides on resolve and collapses the whole environment (`rbs.coverage.environment-build-failed` → `error`), and a duplicate method definition that collapses one class's method surface (`rbs.coverage.definition-build-failed` → `error`). |
|
|
1177
1471
|
| `use-of-void-value` | severity | Using a value recovered from an author-declared `-> void` return in value context is reported as `static.value-use.void` (`warning`). |
|
|
1472
|
+
| `plugin-api-surface` | severity | In plugin source (a class that inherits `Rigor::Plugin::Base`), a call on a `Rigor::Plugin` interface value (a hook's `scope`, `scope.environment`, ...) to a member the interface does not declare is reported as `plugin.api-surface` (`warning`). |
|
|
1178
1473
|
| `discovery-seeded-mutation-sites` | behaviour | [`rigor coverage --protection --mutation`](15-type-protection-coverage.md) measures against the same cross-file project discovery Tier 1 already uses — both when picking the sites and when deciding whether a breakage was caught — so a call on a project class declared in a *sibling* file is measured instead of dropped, and a breakage there can actually be caught. **Adds sites to the denominator, so the reported effectiveness ratio moves** — check it against any `--threshold` you pin in CI before adopting. |
|
|
1179
1474
|
| `dependent-closure-kill-oracle` | behaviour | [`rigor coverage --protection --mutation`](15-type-protection-coverage.md) counts a breakage as caught when the diagnostic appears anywhere in the mutated file **or the files that depend on it**, instead of in the mutated file alone — so changing what a method returns counts as caught when the error lands in its callers. Can only **add** kills, so the ratio moves up or not at all; it costs about a third more wall time per mutant, and a ratio measured under it is not comparable with one measured without it. |
|
|
1180
|
-
| `effects-on-by-default` | behaviour | A project whose `.rigor.yml` carries no [`effects:`](03-configuration.md#effect-labels) key at all is treated as if it had written `effects: {}` — [effect collection](03-configuration.md#effect-labels), the `rigor effects` verbs' cache sharing, and `effects.check` all turn on with every sub-key at its default. Writing `effects: false` explicitly still opts out. **Scheduled to graduate at v0.
|
|
1475
|
+
| `effects-on-by-default` | behaviour | A project whose `.rigor.yml` carries no [`effects:`](03-configuration.md#effect-labels) key at all is treated as if it had written `effects: {}` — [effect collection](03-configuration.md#effect-labels), the `rigor effects` verbs' cache sharing, and `effects.check` all turn on with every sub-key at its default. Writing `effects: false` explicitly still opts out. **Scheduled to graduate at v0.5.0** ([ADR-103](../adr/103-effect-labels.md) § WD15, moved from v0.4.0 by § WD18) rather than at the next major — an owner ruling specific to this feature, ahead of the general v1.0.0 majors-only cadence below. |
|
|
1181
1476
|
|
|
1182
1477
|
Once a feature **graduates** — it becomes the default at a major
|
|
1183
1478
|
([ADR-50](../adr/50-release-engineering-and-stability-strategy.md) § WD7)
|
|
@@ -1262,18 +1557,65 @@ Exits `1` when any check fails, `0` when all pass.
|
|
|
1262
1557
|
|
|
1263
1558
|
## `rigor upgrade`
|
|
1264
1559
|
|
|
1265
|
-
Migration command skeleton ([ADR-50](../adr/50-release-engineering-and-stability-strategy.md)
|
|
1266
|
-
WD7). The real body lands when a concrete backwards-compatibility
|
|
1267
|
-
break gives it a target (e.g. re-running `baseline regenerate`
|
|
1268
|
-
against a strengthened default profile, surfacing renamed
|
|
1269
|
-
suppression ids, reporting `bleeding_edge:` graduations).
|
|
1560
|
+
Migration command skeleton for major version transitions and breaking changes ([ADR-50](../adr/50-release-engineering-and-stability-strategy.md) § WD7).
|
|
1270
1561
|
|
|
1271
1562
|
```sh
|
|
1272
1563
|
rigor upgrade
|
|
1273
1564
|
```
|
|
1274
1565
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1566
|
+
### Design and future role
|
|
1567
|
+
|
|
1568
|
+
The upgrade command is designed to automate project migrations when major version transitions or breaking changes occur:
|
|
1569
|
+
- **Baseline regeneration**: Re-running `rigor baseline regenerate` against strengthened default rules or profiles.
|
|
1570
|
+
- **Suppression updates**: Surfacing and updating renamed or deprecated inline `# rigor:disable` rules.
|
|
1571
|
+
- **Bleeding-edge consolidation**: Reporting and removing graduated features from `bleeding_edge:` configurations.
|
|
1572
|
+
|
|
1573
|
+
### Current status
|
|
1574
|
+
|
|
1575
|
+
Until a backward-incompatible release provides an active migration target, the command serves as a placeholder. It prints the current Rigor version and reports that migrations are queued:
|
|
1576
|
+
|
|
1577
|
+
```text
|
|
1578
|
+
rigor upgrade: No migration target available yet (ADR-50 WD7, queued).
|
|
1579
|
+
Current version: <version>
|
|
1580
|
+
```
|
|
1581
|
+
|
|
1582
|
+
Exit `0` on completion.
|
|
1583
|
+
|
|
1584
|
+
## `rigor help`
|
|
1585
|
+
|
|
1586
|
+
```sh
|
|
1587
|
+
rigor help # the command list
|
|
1588
|
+
rigor help <command> # the same as `rigor <command> --help`
|
|
1589
|
+
rigor help --format=json # every command, its flags and formats
|
|
1590
|
+
```
|
|
1591
|
+
|
|
1592
|
+
`rigor help --format=json` prints the whole CLI surface as one JSON
|
|
1593
|
+
document, for tools and agents that would otherwise parse the help
|
|
1594
|
+
text:
|
|
1595
|
+
|
|
1596
|
+
```json
|
|
1597
|
+
{ "schema_version": 1, "version": "…", "commands": [ … ] }
|
|
1598
|
+
```
|
|
1599
|
+
|
|
1600
|
+
Each entry of `commands` has:
|
|
1601
|
+
|
|
1602
|
+
| Key | Value |
|
|
1603
|
+
| --- | --- |
|
|
1604
|
+
| `name` | The command name. |
|
|
1605
|
+
| `summary` | The one-line description `rigor help` prints. |
|
|
1606
|
+
| `usage` | The usage line (`Usage: rigor …`). |
|
|
1607
|
+
| `flags` | The command's own switches, each `{ "name", "arg", "optional", "desc" }`. `arg` is the argument's name, `null` for a switch that takes none, and `optional` is `true` when the argument may be left out (`--bleeding-edge[=LIST]`). `--[no-]x` is listed as the two flags `--x` and `--no-x`. |
|
|
1608
|
+
| `formats` | The values the command's own `--format` accepts, empty when it has none. A command that only has subcommands with the flag (`baseline`) lists none here. |
|
|
1609
|
+
| `subcommands` | One `{ "name", "usage", "flags", "formats" }` object per subcommand (`baseline dump`, `effects check`, `skill describe`), with the same meaning as above and empty arrays where the subcommand has nothing to list. |
|
|
1610
|
+
| `mcp_tool` | The [MCP](10-mcp-server.md) tool that mirrors the command, or `null`. |
|
|
1611
|
+
|
|
1612
|
+
The list covers every command above plus `help` and `version`. The
|
|
1613
|
+
text help is rendered from the same list.
|
|
1614
|
+
|
|
1615
|
+
`rigor help <command>` takes one command: a second word
|
|
1616
|
+
(`rigor help baseline drift`) is refused with exit `64`, and an
|
|
1617
|
+
unknown command exits `64` too. Flags after the command name are
|
|
1618
|
+
ignored rather than parsed.
|
|
1277
1619
|
|
|
1278
1620
|
## Environment variables
|
|
1279
1621
|
|