# How Conservation and Geometry Verification Work in Sankey Diagrams

> Discover how Sankey diagrams enforce conservation using five invariants and verify geometry to prevent clipped labels. Learn about this crucial diagram design technique.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: deep-dive
- Published: 2026-09-05

---

**Conservation in Sankey diagrams is enforced through five ordered invariants in [`scripts/verify-sankey.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-sankey.py), while geometry verification in [`scripts/verify-geometry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-geometry.py) prevents label masks from being clipped by later-declared node rectangles.**

The **diagram-design** repository by Cathryn Lavery contains a specialized validation system for Sankey diagrams and diagram assets. Understanding how these verification scripts work is essential for contributors who need to ensure their diagrams meet the repository's strict visual and data integrity standards.

## Conservation Rules in Sankey Diagrams

Sankey diagrams represent flowing quantities through interconnected nodes. To guarantee that the visual representation accurately reflects the underlying data, [`scripts/verify-sankey.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-sankey.py) implements five sequential conservation checks.

### The Five Conservation Invariants

The script enforces these rules in order, as documented in the header at lines 13-20:

1. **Conservation** — Total inflow to each node must equal total outflow
2. **Column totals** — Every stage (column) must carry identical total volume
3. **Ribbon-width constancy** — A ribbon's width must match at both endpoints
4. **Value fidelity** — Drawn node height must correspond to the printed numeric value (within relative error tolerance)
5. **Control-point placement** — Bezier curve handles must align with corridor mid-lines at correct Y-coordinates

### Implementation Details

Each invariant maps to specific functions in [`verify-sankey.py`](https://github.com/cathrynlavery/diagram-design/blob/main/verify-sankey.py):

- `parse_ribbons()` extracts and validates flow geometry
- `parse_bars()` and `attach_values()` handle node dimensions and numeric labels
- Width comparisons use `RIBBON_WIDTH_TOL` for tolerance checking
- Bezier validation employs `CONTROL_TOL` for control-point accuracy

The script also supports `--all` mode, which verifies that three skin variants (light, dark, full-editorial) remain geometrically identical and that shipped SVG snippets match their reference implementations.

### Running the Sankey Checker

```bash

# Single diagram validation

python3 scripts/verify-sankey.py skills/diagram-design/assets/example-sankey.html

# Full suite across all shipped assets

python3 scripts/verify-sankey.py --all

```

Exit codes communicate results: **0** (pass), **1** (invariant violation), **2** (usage error).

## Geometry Verification for Diagram Assets

Separate from conservation, [`scripts/verify-geometry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-geometry.py) protects label readability by analyzing the spatial relationships between diagram elements.

### The Mask-Node Overlap Rule

The geometry linter enforces a painting-order constraint derived from [`SKILL.md`](https://github.com/cathrynlavery/diagram-design/blob/main/SKILL.md) §6:

- **Nodes** are identified as rectangles ≥ 60 × 40 pixels
- **Label masks** are classified as rectangles between 20-200 × 8-14 pixels
- A mask declared **after** a node must never overlap that node
- Overlaps are permitted only when the mask is fully contained (badge-chip exception)

### Core Implementation

The verification logic resides in `check()` (lines 11-34) with supporting utilities:

- `parse_rects()` — regex-based `<rect>` extraction from SVG source
- `overlap()` — intersection detection between rectangles
- `contained()` — fully-contained relationship testing (lines 79-108)

The linter compares document offset positions to determine painting order, then reports any violating spatial relationships.

### Running the Geometry Checker

```bash

# Single diagram verification

python3 scripts/verify-geometry.py skills/diagram-design/assets/example-x.html

# Batch validation of all HTML diagrams

python3 scripts/verify-geometry.py --all

```

Findings include precise location data:

```

example-x.html:23: label mask (30,12 45x10) is clipped by node (20,8 80x50) declared later at line 45 (overlap 5x3px) - move the label onto a free segment of its connector

```

## Why Verification Matters

**Data integrity** — Conservation rules ensure that Sankey visual flows genuinely represent numeric data. Without automated invariant checking, "evaporation" of flow (discrepancies between input and output volumes) could remain undetected.

**Design contract enforcement** — Geometry verification guarantees that label masks remain readable. Because masks render before nodes in the document order, any subsequent node overlapping a mask would obscure the label, violating the repository's design specifications.

**Contributor guardrails** — Both scripts use deterministic SVG parsing without browser dependencies. They employ a "fail-open" strategy aborting on unrecognized constructs (transforms, clip paths, external paint servers), which forces contributors to maintain diagram simplicity and verifiability.

## CI/CD Integration

These pure-Python scripts integrate directly into continuous integration pipelines. Example GitHub Actions configuration:

```yaml
- name: Verify Sankey conservation
  run: python3 scripts/verify-sankey.py --all

- name: Verify diagram geometry
  run: python3 scripts/verify-geometry.py --all

```

Any pull request introducing diagrams that violate conservation invariants or geometry constraints will fail automated checks before merge.

## Summary

- **[`scripts/verify-sankey.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-sankey.py)** enforces five ordered conservation invariants: flow balance, column totals, ribbon width constancy, value fidelity, and Bezier control-point placement
- **[`scripts/verify-geometry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-geometry.py)** prevents label-mask clipping by validating spatial relationships and painting order between nodes and masks
- Both scripts operate deterministically on raw SVG source without browser rendering
- Exit codes and human-readable findings support both local development and automated CI enforcement
- The "fail-open" design philosophy maintains diagram simplicity by rejecting unverifiable constructs

## Frequently Asked Questions

### What tolerance values does the Sankey verifier use?

The script defines `RIBBON_WIDTH_TOL` for width consistency checks and `CONTROL_TOL` for Bezier handle validation. Exact numeric thresholds are configurable in the script header to accommodate different precision requirements across diagram scales.

### Can the geometry checker handle rotated or transformed elements?

No. According to the source implementation in [`verify-geometry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/verify-geometry.py), the linter explicitly rejects transforms, clip paths, and external paint servers. This constraint enforces the repository's "keep diagrams simple and verifiable" principle—complex transformations must be flattened before validation.

### How does `--all` mode differ from single-file checking in the Sankey script?

The `--all` flag activates additional variant-consistency checks beyond the core five invariants. It verifies that light, dark, and full-editorial skin variants share identical geometry and that shipped SVG snippets match their reference specifications, ensuring cross-theme uniformity.

### What happens if a label mask partially overlaps a node?

The geometry checker reports the specific overlap dimensions and document positions. If the mask is declared after the overlapping node and is not fully contained (the badge-chip exception), the check fails with guidance to relocate the label onto an unobstructed connector segment.