Module: Rigor::FlowContribution::Merger
- Defined in:
- lib/rigor/flow_contribution/merger.rb
Overview
Composes any number of Rigor::FlowContribution bundles into a single MergeResult per ADR-2 § “Plugin Contribution Merging”. The merger is the **single point of integration** the analyzer uses to combine contributions from built-in narrowing rules, ‘RBS::Extended` annotations, and plugins; slice 4 routes the existing internal narrowing through it and slice 6 wires plugin-side cache producers around it.
## Authority tiers
-
Tier 0: ‘:builtin` — Core Ruby semantics and accepted RBS contracts. Authoritative; lower tiers may not contradict.
-
Tier 1: ‘:rbs_extended` (`RBS::Extended` directive bundles, v0.0.9 group D reference impl) and `:generated` (generated signatures / metadata).
-
Tier 2: ‘:plugin` and `plugin.<id>` source families.
-
Tier 3: anything else — treated as the lowest tier.
Within a tier, contributions are merged in deterministic order: provenance-supplied ‘plugin_id` alphabetical (nil plugin ids sort first to keep `:rbs_extended` / `:generated` pre-plugin contributions stable), then by their original input position as the final tie-break.
## Composition rules (ADR-2)
-
‘:return_type` — Intersect via `Type::Combinator.intersection`; collapse to bot raises `:return_type_collapse`.
-
‘:truthy_fact` / `:falsey_fact` / `:post_return_fact` —Edge-local; accumulate while deduping by payload equality.
-
‘:mutation` / `:invalidation` / `:role` — Union; dedupe by equality.
-
‘:exception` — Single-valued. Two non-`nil` non-equal exceptional effects raise `:exceptional_disagreement`.
## Cross-tier contradictions
Lower tiers may refine higher tiers but must not weaken them. Slice 3 surfaces contradictions through ‘:lower_tier_contradiction` when:
-
the higher tier already pinned a ‘return_type` and a lower tier’s intersection collapses to ‘bot`;
-
the higher tier set ‘exceptional` to a non-`nil` value and a lower tier disagrees.
In every conflict case the result keeps the higher-tier value for that slot, records a Conflict with both provenances, and continues processing the remaining slots / contributions.
Constant Summary collapse
- AUTHORITY_TIERS =
rubocop:disable Metrics/ModuleLength
{ builtin: 0, rbs_extended: 1, generated: 1 }.freeze
Class Method Summary collapse
Class Method Details
.merge(contributions) ⇒ MergeResult
65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/rigor/flow_contribution/merger.rb', line 65 def merge(contributions) contributions = Array(contributions) return MergeResult.new if contributions.empty? ordered = order_contributions(contributions) state = MergeState.new ordered.each do |contribution| tier = tier_for(contribution.provenance) fold_into(state, contribution, tier) end state.to_result end |
.tier_for(provenance) ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/rigor/flow_contribution/merger.rb', line 78 def tier_for(provenance) family = provenance.respond_to?(:source_family) ? provenance.source_family : nil return AUTHORITY_TIERS[family] if AUTHORITY_TIERS.key?(family) return 2 if family == :plugin || family.to_s.start_with?("plugin.") 3 end |