{% if render_mode != 'fragment' %} {% if domain %}{% endif %} Version Comparison - Finite State Report {% include "_design_system.html" %} {% include "_console_shell.html" %} {% include "_echarts_ready.html" %} {% endif %} {% if render_mode != 'fragment' %} {% endif %} {% import "_console_macros.html" as fs with context %} {# Defensive context defaults — defined OUTSIDE the gate so any downstream reference (status_bar, topbar) is safe in both branches. The non-empty branch overwrites `result` below. #} {% set result = transform_result | default({}) %} {% if not result is mapping %}{% set result = {} %}{% endif %} {# Chrome (topbar) renders in both branches — it's identifying info for the page, not data-conditional. #} {% if render_mode != 'fragment' %} {{ fs.topbar( crumbs=["Finite State", "Version Comparison"], meta=[ {"label": "Domain", "value": domain or "—"}, {"label": "Projects", "value": (result.get('project_count', 0)) | string}, {"label": "Filter", "value": (project_label if project_label else (metadata.folder_filter if metadata is defined and metadata.folder_filter else "—"))}, {"label": "Generated", "value": generated_at or "—"}, ], controls=[], ) }} {% endif %}
{# Data gate. The non-empty branch sets richer locals + renders the per-project tree; the {% else %} branch renders the empty-state guidance card. `
` is opened OUTSIDE this gate so both branches sit inside well-formed chrome — round-2 multi-review M1-1 / M2-1 caught the prior version's orphan `
` bug. #} {# Page head renders in BOTH branches so empty-portfolio runs still get the H1 + subtitle (round-2 M1-4). #}

Version Comparison

Per-project progression of findings across versions; fixed + new counts per pair; component churn; externally-driven CVE changes.

{% if transform_result and transform_result.projects and transform_result.projects | length > 0 %} {% set result = transform_result %} {% set kpi = result.kpi | default({}) %} {% set projects = result.projects | default([]) %} {# Partial-report banner — top-level `partial_report` and `failed_version_names` (not under transform_result). #} {% if partial_report %}
⚠ Partial report: {{ failed_version_names | length }} version{{ 's' if failed_version_names | length != 1 else '' }} could not be fetched ({{ failed_version_names | join(", ") }}). These appear as placeholders below.
{% endif %} {# Aggregate KPI row — nested baseline→current shape per _aggregate_kpi (`total_findings.baseline/current/delta/pct`). The fs.kpi_cell macro takes a single label + value; render the arrow form (baseline → current) inside the value so the existing --sev-low/--sev-critical dot still signals improvement vs regression. #} {% set tf = kpi.total_findings | default({'baseline': 0, 'current': 0, 'delta': 0, 'pct': 0.0}) %} {% set cf = kpi.critical_findings | default({'baseline': 0, 'current': 0, 'delta': 0, 'pct': 0.0}) %} {% set hf = kpi.high_findings | default({'baseline': 0, 'current': 0, 'delta': 0, 'pct': 0.0}) %} {% set cp = kpi.components | default({'baseline': 0, 'current': 0, 'delta': 0, 'pct': 0.0}) %} {# Use `.kpi-row` (from _design_system.html) — the spaced grid designed for `.kpi-card` children. The compact `.kpi-bar` (from _console_shell.html) is intended for `.kpi-cell` children and would squash these baseline→current delta cards in standalone HTML/PDF. Round-1 multi-review M1-1 caught the double-class regression. #}
Total Findings
{{ tf.baseline }} {{ tf.current }}
{% if tf.delta > 0 %}+{% endif %}{{ tf.delta }} ({% if tf.delta > 0 %}+{% endif %}{{ tf.pct }}%)
Critical
{{ cf.baseline }} {{ cf.current }}
{% if cf.delta > 0 %}+{% endif %}{{ cf.delta }}
High
{{ hf.baseline }} {{ hf.current }}
{% if hf.delta > 0 %}+{% endif %}{{ hf.delta }}
Components
{{ cp.baseline }} {{ cp.current }}
{% if cp.delta > 0 %}+{% endif %}{{ cp.delta }}
Fixed (latest)
{{ kpi.fixed_count | default(0) }}
New (latest)
{{ kpi.new_count | default(0) }}
{# Per-project sections. #} {% for proj in projects %} {% set proj_idx = loop.index %} {% set is_pair = proj.get('is_pair_comparison', False) %} {% set body_id = fragment_scope_class ~ '-vc-project-body-' ~ proj_idx %} {% set chart_id = fragment_scope_class ~ '-vc-chart-' ~ proj_idx %}
{# In fragment mode ` {% include '_action_buttons.html' %} {% endif %}