From ec31c97bfc059ecab5a145a9b076d3d675a4f570 Mon Sep 17 00:00:00 2001 From: Eli Salamie Date: Tue, 15 Sep 2026 02:12:56 -0500 Subject: [PATCH 1/2] fix(matrix): wrapped runs enter the font subset --- src/hyperweave/compose/resolvers/matrix.py | 3 ++ tests/render/test_tofu_and_destinations.py | 49 ++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/hyperweave/compose/resolvers/matrix.py b/src/hyperweave/compose/resolvers/matrix.py index ba923d5..3f03ed8 100644 --- a/src/hyperweave/compose/resolvers/matrix.py +++ b/src/hyperweave/compose/resolvers/matrix.py @@ -226,6 +226,7 @@ def _text_surface(layout: MatrixLayout) -> list[str]: strings.append(text_spec.text) for header in layout.colheaders: strings.append(header.label.text) + strings.extend(line.text for line in header.lines) if header.sublabel is not None: strings.append(header.sublabel.text) for band in layout.section_bands: @@ -233,8 +234,10 @@ def _text_surface(layout: MatrixLayout) -> list[str]: for cell in layout.cells: if cell.text: strings.append(cell.text) + strings.extend(line.text for line in cell.text_lines) if cell.sub_text: strings.append(cell.sub_text) + strings.extend(line.text for line in cell.sub_lines) for chip in cell.chips: strings.append(chip.text) if layout.axis is not None: diff --git a/tests/render/test_tofu_and_destinations.py b/tests/render/test_tofu_and_destinations.py index 36f5da5..da9e3e2 100644 --- a/tests/render/test_tofu_and_destinations.py +++ b/tests/render/test_tofu_and_destinations.py @@ -38,8 +38,37 @@ _NS = "{http://www.w3.org/2000/svg}" _UNCOVERABLE = {0x25AE} # marquee separator bar: absent from every shipped font +_WRAPPED_MATRIX = { + "title": "Ømega ledger", + "subtitle": "wrapped runs carry glyphs the header set never sees", + "headline": {"value": "99.9%", "label": "Ωmega availability"}, + "columns": [ + {"id": "l", "label": "Ünit", "role": "label"}, + {"id": "t", "label": "DESCRIPTION OF THE BEHAVIOUR UNDER TEST", "kind": "text", "width": 120}, + {"id": "c", "label": "TAGS", "kind": "chip", "width": 90}, + {"id": "k", "label": "STATE", "kind": "check"}, + {"id": "b", "label": "SIZE", "kind": "bar"}, + ], + "rows": [ + { + "label": "Straße parsing of unicode text", + "sublabel": "μ-benchmark", + "cells": [ + { + "value": "Ωmega binding digits map every sigma into the ledger " * 2, + "note": "naïve first pass over the corpus", + }, + {"chips": ["none (opaque html)", "ß"]}, + {"state": "partial"}, + {"value": 3420}, + ], + } + ], +} + _TOFU_SPECS: tuple[tuple[str, ComposeSpec], ...] = ( ("badge", ComposeSpec(type="badge", genome_id="brutalist", title="BUILD", value="passing")), + ("matrix", ComposeSpec(type="matrix", genome_id="primer", matrix=_WRAPPED_MATRIX)), ("strip", ComposeSpec(type="strip", genome_id="primer", title="repo", value="STARS:1")), ("marquee", ComposeSpec(type="marquee", genome_id="brutalist", title="HW|TEST")), ( @@ -85,6 +114,26 @@ def test_every_rendered_codepoint_is_in_the_embedded_subset(self, label: str, sp missing = _rendered_codepoints(svg) - cmap - _UNCOVERABLE assert not missing, f"{label}: tofu — rendered but not in the subset: {[hex(cp) for cp in sorted(missing)]}" + def test_the_matrix_corpus_is_tofu_free(self) -> None: + """Every matrix fixture and every audit probe: wrapped cell runs, + note runs, and wrapped header runs all ride the subset surface.""" + import json + from pathlib import Path + + root = Path(__file__).parents[1] / "fixtures" + specs = {p.stem: json.loads(p.read_text()) for p in sorted((root / "matrix").glob("*.json"))} + for probe in sorted((root / "spatial" / "probes").glob("mat-audit-*.json")): + specs[probe.stem] = json.loads(probe.read_text())["compose"]["matrix"] + failures: list[str] = [] + for name, payload in specs.items(): + svg = compose(ComposeSpec(type="matrix", genome_id="primer", matrix=payload)).svg + cmap = _embedded_cmap(svg) + assert cmap, f"{name}: matrix must embed its fonts" + missing = _rendered_codepoints(svg) - cmap - _UNCOVERABLE + if missing: + failures.append(f"{name}: {[hex(cp) for cp in sorted(missing)]}") + assert not failures, "tofu in the matrix corpus:\n" + "\n".join(failures) + def test_the_full_preset_corpus_is_tofu_free(self) -> None: # The FULL corpus, not a sample — a 3-preset spot check missed five # presets whose chip, legend, and tint text rode fields the subsetter From f5c6b216cb340f5e027d9c462e0bf2d88c859772 Mon Sep 17 00:00:00 2001 From: Eli Salamie Date: Tue, 15 Sep 2026 02:13:15 -0500 Subject: [PATCH 2/2] test: placeholder-leak checks read the text layer --- tests/compose/test_chart_frame.py | 5 +++-- tests/compose/test_stats_card.py | 5 +++-- tests/helpers.py | 13 ++++++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/compose/test_chart_frame.py b/tests/compose/test_chart_frame.py index 67e5f5f..eea467c 100644 --- a/tests/compose/test_chart_frame.py +++ b/tests/compose/test_chart_frame.py @@ -13,6 +13,7 @@ from hyperweave.compose.engine import compose from hyperweave.core.models import ComposeSpec +from tests.helpers import rendered_text MOCK_POINTS = [ {"date": "2025-01-01T00:00:00Z", "count": 100}, @@ -129,7 +130,7 @@ def test_chart_graceful_degradation_without_data() -> None: assert 'data-hw-status="stale"' in result.svg # No fabricated polyline and no leak of the old placeholder numbers. assert " None: assert 'data-hw-status="empty"' in svg assert "NEW REPO" in svg # No placeholder leakage. - assert "1200" not in svg and "1,200" not in svg + assert "1200" not in rendered_text(svg) and "1,200" not in rendered_text(svg) # No fabricated polyline. assert " None: ) svg = compose(spec).svg # No placeholder leakage in the embedded chart. - assert "1200" not in svg - assert "1,200" not in svg + assert "1200" not in rendered_text(svg) + assert "1,200" not in rendered_text(svg) # Compose still completes successfully with data-hw-frame marker (public name). assert 'data-hw-frame="card"' in svg diff --git a/tests/helpers.py b/tests/helpers.py index aae9b3e..c4e2eda 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,4 +1,4 @@ -"""Test-only helpers for constructing inline genomes. +"""Test-only helpers: inline genomes and the rendered text layer. ``build_minimal_genome_for_testing`` emits a COMPLETE minimal genome — one that passes the full custom-genome boundary (GenomeSpec grammar, the @@ -13,6 +13,7 @@ from __future__ import annotations +import xml.etree.ElementTree as ET from typing import Any _CHROMATIC_PREFIXES = ("#", "rgba(", "rgb(", "linear-gradient", "radial-gradient") @@ -64,3 +65,13 @@ def build_minimal_genome_for_testing(**overrides: Any) -> dict[str, Any]: ] defaults["roles"] = {"core": chromatic} return defaults + + +def rendered_text(svg: str) -> str: + """Every string the SVG paints, joined — the text layer only. + + Provenance timestamps, digests, and base64 font bytes are volatile and can + spell any digit run; assertions about what a reader sees must look here. + """ + ns = "{http://www.w3.org/2000/svg}" + return "\n".join(el.text for el in ET.fromstring(svg).iter() if el.tag in (f"{ns}text", f"{ns}tspan") and el.text)