Component Comparison
{{ left_label }} vs {{ right_label }}
{% if empty_side == 'both' %}
No data. Both scopes had no component data — nothing to compare.
{% elif empty_side == 'left' %}
{{ left_label }}: no data. The {{ left_label }} scope had no component data — nothing to compare.
{% elif empty_side == 'right' %}
{{ right_label }}: no data. The {{ right_label }} scope had no component data — nothing to compare.
{% endif %}
{{ shared_count }} shared · {{ left_only_count }} only in {{ left_label }} · {{ right_only_count }} only in {{ right_label }} · {{ version_skew_count }} shared component{{ 's' if version_skew_count != 1 }} at a different version.
{{ fs.panel_head("Shared vs. divergent surface", meta=(union_count | string) ~ " component" ~ ("s" if union_count != 1 else "") ~ " in union") }}
{# Version skew cards — both versions side by side; NO newer/older ordering #}
{% if version_skew and version_skew | length > 0 %}
{{ fs.panel_head("Version skew", meta=(version_skew | length | string) ~ " shared component" ~ ("s" if version_skew | length != 1 else "")) }}
{% endif %}
{# Right-only inventory table (reuses .data-table). Project column binds to
row.right_project_names (the variants carrying the component). When the
whole table shares a single owner, the panel-head names it. #}
{% if right_only and right_only | length > 0 %}
{% set rcount = right_only | length %}
{% set rcollapse = rcount > 12 %}
{% set r_owner_ns = namespace(items=[]) %}
{% for row in right_only %}{% for p in (row.right_project_names or []) %}{% if p and p not in r_owner_ns.items %}{% set _ = r_owner_ns.items.append(p) %}{% endif %}{% endfor %}{% endfor %}
{% set r_all_in = (r_owner_ns.items | first) if (r_owner_ns.items | length) == 1 else None %}
{% for row in version_skew %}
{% if loop.last %}
{% endfor %}
{{ left_label | short_scope }}
{{ row.left_version or '—' }}
{# Owners per side — which variants carry the left version.
NEVER merged with the right side. #}
{% if row.left_project_names %}{{ row.left_project_names | join(', ') }}
{% endif %}
{{ row.name or '—' }}{% if row.type %} · {{ row.type }}{% endif %}
{{ right_label | short_scope }}
{{ row.right_version or '—' }}
{% if row.right_project_names %}{{ row.right_project_names | join(', ') }}
{% endif %}
Shared components carried at differing versions. Aligning the version closes the version-specific findings on the lower side.
{% endif %}
{{ fs.panel_head(
(right_label | short_scope) ~ "-only components",
meta=(rcount | string) ~ " component" ~ ("s" if rcount != 1 else "") ~ (" · all in " ~ r_all_in if r_all_in else "")) }}
{% if rcollapse %}
{% endif %}
{% endif %}
{# Left-only inventory table (reuses .data-table). Project column binds to
row.left_project_names (mirror of right-only). #}
{% if left_only and left_only | length > 0 %}
{% set lcount = left_only | length %}
{% set lcollapse = lcount > 12 %}
{% set l_owner_ns = namespace(items=[]) %}
{% for row in left_only %}{% for p in (row.left_project_names or []) %}{% if p and p not in l_owner_ns.items %}{% set _ = l_owner_ns.items.append(p) %}{% endif %}{% endfor %}{% endfor %}
{% set l_all_in = (l_owner_ns.items | first) if (l_owner_ns.items | length) == 1 else None %}
| Component | Type | Version | Project |
|---|---|---|---|
| {{ row.name or '—' }} | {% if row.type %}{{ row.type }}{% else %}—{% endif %} | {{ row.version or '—' }} | {{ (row.right_project_names | join(', ')) if row.right_project_names else '—' }} |
{{ fs.panel_head(
(left_label | short_scope) ~ "-only components",
meta=(lcount | string) ~ " component" ~ ("s" if lcount != 1 else "") ~ (" · all in " ~ l_all_in if l_all_in else "")) }}
{% if lcollapse %}
{% endif %}
{% endif %}
{# Empty-side confident strip — conditional on *_only_count == 0 #}
{% if right_only_count == 0 %}
| Component | Type | Version | Project |
|---|---|---|---|
| {{ row.name or '—' }} | {% if row.type %}{{ row.type }}{% else %}—{% endif %} | {{ row.version or '—' }} | {{ (row.left_project_names | join(', ')) if row.left_project_names else '—' }} |
{{ right_label }} only: 0. {{ right_label }} introduces no components {{ left_label }} lacks.
{{ left_label }} only: 0. {{ left_label }} introduces no components {{ right_label }} lacks.
Component inventories match. No component differences between {{ left_label }} and {{ right_label }}.