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 =
{
  builtin: 0,
  rbs_extended: 1,
  generated: 1
}.freeze

Class Method Summary collapse

Class Method Details

.merge(contributions) ⇒ MergeResult

Parameters:

Returns:



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rigor/flow_contribution/merger.rb', line 58

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



71
72
73
74
75
76
77
# File 'lib/rigor/flow_contribution/merger.rb', line 71

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