Public API Stability Boundary
Status: Active (v0.1.0 contract shipped; stabilising toward v0.2.0).
Lists the namespaces the plugin contract is designed against and pins
them in place via the public-API drift spec.
The v0.1.0 plugin contract shipped and the 0.1.x preview line has
extended the surface (cross-plugin facts, signature_paths:,
open_receivers:, protocol_contracts:, source_rbs_synthesizer:);
v0.2.0 is the first line where this surface is stabilised for external
rigor-* gems. (The rigor <command> CLI itself — including newer
subcommands like mcp, triage, baseline, plugin, skill — stays
internal plumbing per the exclusion list below; its user-facing
contract lives in docs/manual/.) The drift spec
catches accidental signature changes so every change stays deliberate
and reviewable.
Why this boundary exists
Section titled “Why this boundary exists”ADR-2 commits Rigor to a plugin architecture that lets gem authors
contribute capability roles, dynamic-return facts, type-specifying
plugins, and RBS::Extended directives. Plugin authors will write
against a small set of read-side surfaces:
Rigor::Scope— the per-node analysis state (locals, ivars, facts, environment).Rigor::Type+Rigor::Type::Combinator— the type-object layout and factory entry points.Rigor::Environment— the project-level RBS / class-registry / cache-store handle.Rigor::Reflection— the unified read-side facade over the three reflection sources (ClassRegistry + RbsLoader + Scope’s discovered facts).Rigor::FlowContribution— the bundle plugins return (the v0.1.0 contribution merger consumes bundles directly).Rigor::Analysis::Diagnostic— the diagnostic shape plugins emit (withsource_familyprovenance). TheDiagnostic.from_node/.from_locationconstructors (and thePlugin::Base#diagnosticwrapper) internalise the 1-basedline/start_column + 1positioning convention (ADR-37).
This document declares which methods on those namespaces are public (plugin authors may rely on them) versus internal (may change without notice). The v0.0.9 cluster grew per-namespace drift snapshots so future signature changes show up as test failures, not silent breakage.
What is currently locked
Section titled “What is currently locked”The drift spec at
spec/rigor/public_api_drift_spec.rb
pins instance and singleton method sets for:
Rigor::Scope— instance methods + theScope.empty(environment:)factory.Rigor::Environment— instance methods +Environment.default/Environment.for_project(root:, libraries:, signature_paths:, cache_store:).Rigor::Type::Combinator— every factory the inference engine reaches for (top,bot,untyped,nominal_of,singleton_of,constant_of,integer_range,positive_int,non_empty_string,lowercase_string,literal_string,union,intersection,difference,refined,key_of,value_of,indexed_access, …).Rigor::Reflection— everyclass_known?,class_ordering,class_type_param_names,constant_type_for,discovered_class?,discovered_method?,instance_definition,instance_method_definition,nominal_for_name,rbs_class_known?,singleton_definition,singleton_for_name,singleton_method_definition.Rigor::Plugin—register,registered,registered_for,unregister!(test helper). v0.1.0 slice 1.Rigor::Plugin::Base— the class-levelmanifest(**fields),producer,node_rule, andnode_file_contextDSLs; instance-levelservices/config/manifest, the override hooks#init/#prepare/#diagnostics_for_file/#flow_contribution_for, the engine-owned-walk dispatcher#node_rule_diagnostics, and the#diagnostic(node, …)builder. v0.1.0 slice 1 + ADR-37.Rigor::Plugin::Manifest—id,version,description,protocols,config_schema,validate_config(config).Rigor::Plugin::Services—reflection,type,configuration,cache_store,trust_policy,io_boundary_for(plugin_id).Rigor::Plugin::Registry—plugins,ids,find(id),load_errors,empty?,any_load_errors?.Rigor::Plugin::TrustPolicy—trusted_gems,allowed_read_roots,network_policy,allow_read?(path),network_allowed?,gem_trusted?(name),to_h. v0.1.0 slice 2.Rigor::Plugin::IoBoundary—policy,plugin_id,read_file(path),open_url(url),cache_descriptor. v0.1.0 slice 2.Rigor::Source::Literals— the argument-literal extraction gridsymbol,symbol_name,symbol_or_string,symbol_or_string_name,symbol_arguments,symbol_arg. The one deliberately-public member of the otherwise-internalRigor::Source::*namespace (see below): the shared DSL-walker helper plugin authors are pointed at (boilerplate-reduction plan § 0a). v0.1.x.
Any signature change on these methods has to update the matching
PublicApiDriftSnapshots::* constant in the same commit.
What is intentionally NOT yet locked
Section titled “What is intentionally NOT yet locked”Rigor::FlowContribution— the bundle struct shipped in v0.0.9 (c48f05f); slice 3 added#to_element_listand pinned the bundle shape via the public-API drift spec. Plugin authors should consume bundles via the public reader /to_hform and avoid pinning the per-slot value shapes (PredicateEffect,AssertEffect, …) directly until v0.1.0 ratifies them.Rigor::FlowContribution::Element/MergeResult/Conflict/Merger— slice 3 surface; pinned by the drift spec. The flattening + merge policy is normative perflow-contribution-merger.md.Rigor::Analysis::Diagnostic—source_familyandqualified_rulewere added in v0.0.8 (ed9ae0a) but the per-rule diagnostic identifiers are still in flux as the v0.1.0 plugin observability story finalises.Rigor::Cache::*— the producer-facingStore#fetch_or_compute(producer_id:, params:, descriptor:, serialize:, deserialize:)API is the most stable layer and the one plugin-side cache producers will ride. The descriptor schema is fixed by ADR-6 and the slice-taxonomy design doc; plugin authors should addPluginEntryrows rather than new slot kinds.Rigor::RbsExtendeddirective parsers — public reader methods (read_predicate_effects,read_assert_effects,read_return_type_override,read_param_type_overrides,read_flow_contribution) are stable shapes today; the per-effect Data carriers (PredicateEffect,AssertEffect,ParamOverride) are subject to the same v0.1.0 refinement asFlowContribution.Rigor::Plugin::*— registration / loading surface landed in v0.1.0 slice 1. The instance-levelRigor::Plugin::Base#inithook is stable today; protocol hooks added by slices 3–6 may refine the public method set onBase. Plugin authors should pin their gem to a specific Rigor version while v0.1.0 is in development.
Internal surfaces (NOT public)
Section titled “Internal surfaces (NOT public)”Plugin authors must NOT rely on:
Rigor::Inference::*modules (ScopeIndexer, ExpressionTyper, StatementEvaluator, MethodDispatcher, MethodParameterBinder, ClosureEscapeAnalyzer, CoverageScanner). These are the engine’s internal mechanism; their shapes change as the inference surface evolves.Rigor::Analysis::FactStore,Analysis::Result,Analysis::CheckRules,Analysis::Runner. The diagnostic catalogue and the rule definitions are not a plugin extension surface — plugins emit diagnostics via the v0.1.0 plugin protocol, not by adding rows toCheckRules.Rigor::AST::*virtual nodes. The synthetic AST nodes the engine uses internally are not a stable plugin surface.- Any
Rigor::Source::*(exceptRigor::Source::Literals, locked above),Rigor::CLI::*,Rigor::Configurationhelper. These are CLI / loader plumbing.Source::Literalsis the one carve-out: it is drift-pinned and the recommended plugin-author argument extractor.
Promotion path
Section titled “Promotion path”When a v0.1.0 plugin contract requires a currently-internal surface to become public:
- The relevant ADR is amended (ADR-2 for the plugin extension protocol, ADR-3/4 for type-object / inference engine details).
- The class is added to
spec/rigor/public_api_drift_spec.rbwith a snapshot of its method set. From that commit forward, accidental signature changes break the drift spec. - This document grows a “Promoted in v0.1.0” entry for the new namespace.
Reading order for a plugin author
Section titled “Reading order for a plugin author”docs/adr/2-extension-api.md— the plugin contract (capability roles, contribution merging, diagnostic provenance, registration, configuration, caching, trust / I/O).docs/internal-spec/internal-type-api.md— type-object public contract everyRigor::Type::*carrier satisfies.docs/internal-spec/inference-engine.md—Rigor::Scope#type_ofpurity, fact-store / effect model, environment-loading boundaries.docs/internal-spec/reflection.md— theRigor::Reflectionread-side facade.docs/internal-spec/flow-contribution.md— theRigor::FlowContributionbundle.docs/internal-spec/cache.md— the cache layer’s public read shape; plugin-side cache producers ride this API.
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.