# Block Registry Structural Gate: Validating data-block-id and Parent Chain Integrity in Diagram Design

> Enhance diagram design with the block registry structural gate. Validate data-block-id and parent chain integrity for robust SVG files in cathrynlavery/diagram-design.

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

---

**The block registry structural gate enforces five strict validation rules—non-blank unique IDs, valid parent references, present names, and acyclic hierarchies—on every HTML/SVG diagram file in the cathrynlavery/diagram-design repository.**

The **cathrynlavery/diagram-design** repository implements a metadata side-car pattern to enable traceable block decomposition in architectural diagrams. The structural gate, located in [`scripts/verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-block-registry.py), ensures that `data-block-id` and parent chain attributes form a consistent, queryable tree structure before diagrams are committed or exported. This validation layer guarantees that downstream tooling can reliably navigate block hierarchies without encountering orphaned references or circular dependencies.

## How the Structural Gate Validates Block Metadata

The validator treats every HTML or SVG file as a potential registry of blocks. During execution, it extracts elements bearing `data-block-*` attributes and subjects them to a five-stage validation pipeline.

### The Five Validation Rules

According to the source code in [`scripts/verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-block-registry.py), the gate enforces the following constraints:

1. **Non-blank IDs** – Every block must declare a non-empty `data-block-id`. Empty or whitespace-only IDs are reported as structural errors with precise line numbers.
2. **Global Uniqueness** – Within a single file, a `data-block-id` value may appear exactly once. Duplicate IDs trigger diagnostics listing every offending line.
3. **Parent Resolution** – If `data-block-parent` is present, its value must match an existing `data-block-id` within the same file. Unmatched parents are flagged as orphan references.
4. **Name Presence** – Each block must carry a non-blank `data-block-name` attribute to ensure human-readable identification.
5. **Acyclic Hierarchy** – The parent chain must form a directed acyclic graph. The validator traces each ancestry path; if a node repeats, it emits a cycle description such as `A → B → C → A`.

These checks are metadata-only and do not inspect visual geometry or connector routing, which is handled separately by [`scripts/verify-geometry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-geometry.py).

### Parsing Strategy and Data Model

The validator relies on Python’s standard-library `html.parser.HTMLParser` to ensure browser-equivalent parsing behavior, handling case-insensitive attributes and ignoring content inside `<script>` or `<style>` blocks.

During the parse phase, every start tag containing `data-block-id` is instantiated as a `Block` dataclass storing:

- `id`: The unique identifier string
- `parent`: Optional parent reference
- `name`: Human-readable label
- `line`: Source file line number for diagnostics

After parsing, dedicated functions—`find_blank_ids()`, `find_duplicates()`, `find_orphan_parents()`, `find_missing_names()`, and `find_cycles()`—scan the list of `Block` objects and return structured diagnostic messages. The main `check()` function aggregates these results, returning an empty list only when all five rules pass.

## Architectural Foundation: ADR 0010

The structural gate was mandated by **ADR 0010 – Block registry metadata contract**, located at [`docs/adr/0010-block-registry-metadata-contract.md`](https://github.com/cathrynlavery/diagram-design/blob/main/docs/adr/0010-block-registry-metadata-contract.md). This architectural decision record formalized the metadata side-car pattern for *Traceable block decomposition*, requiring that every diagram block expose stable identifiers and parent pointers to support automated audit trails.

The ADR defines the contract that [`verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/verify-block-registry.py) enforces, ensuring that block hierarchies remain navigable across Tree, Architecture, and other diagram types exported from the repository.

## Running the Validator

### Command-Line Interface

You can invoke the gate directly against specific files or entire asset directories:

```bash

# Validate a single diagram

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

# Validate all HTML/SVG assets in the skill

python3 scripts/verify-block-registry.py --all

```

**Sample error output:**

```

example-x.html:12: block has a blank data-block-id
example-x.html:24: duplicate data-block-id "node42" at lines 24, 37
example-x.html:31: data-block-parent "node99" on block "node7" does not match any data-block-id in this file
example-x.html:45: block "node12" has a missing or blank data-block-name
example-x.html: parent cycle: node5 -> node8 -> node5

```

### CI Integration

Add the validator to a GitHub Actions workflow to block merges containing broken metadata:

```yaml
- name: Verify block registry
  run: |
    python3 scripts/verify-block-registry.py --all

```

A non-zero exit code indicates validation failure, preventing the merge of diagrams with registry errors.

### Programmatic Usage

Import the validation logic into other Python scripts:

```python
from pathlib import Path
from scripts.verify_block_registry import check

path = Path('skills/diagram-design/assets/example-x.html')
issues = check(path)

if issues:
    for issue in issues:
        print(issue)
    exit(1)
else:
    print('All block metadata valid')

```

## Export Registry Integration

When exporting diagrams with the `--registry` flag, the CLI relies on the structural gate to guarantee metadata integrity. Successfully validated blocks are serialized into a JSON side-car:

```json
[
  {
    "id": "auth-service",
    "name": "Auth Service",
    "parent": "gateway",
    "attributes": {}
  },
  {
    "id": "gateway",
    "name": "API Gateway",
    "parent": null,
    "attributes": {}
  }
]

```

This integration ensures that consumers of the exported registry receive a verified, acyclic hierarchy that complies with the ADR 0010 contract.

## Key Files and References

| File | Purpose |
|------|---------|
| [`scripts/verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-block-registry.py) | Core validator implementing the five structural rules |
| [`scripts/test-verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/test-verify-block-registry.py) | Test suite providing edge-case coverage and regression protection |
| [`docs/adr/0010-block-registry-metadata-contract.md`](https://github.com/cathrynlavery/diagram-design/blob/main/docs/adr/0010-block-registry-metadata-contract.md) | Architectural Decision Record defining the metadata contract |
| [`skills/diagram-design/references/semantic-patterns.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/semantic-patterns.md) | Documentation for the *Traceable block decomposition* pattern (Section 8) |
| [`commands/export-diagram.md`](https://github.com/cathrynlavery/diagram-design/blob/main/commands/export-diagram.md) | CLI reference for the `--registry` export flag |

## Summary

- The **block registry structural gate** enforces five validation rules on `data-block-id`, `data-block-parent`, and `data-block-name` attributes in diagram HTML/SVG files.
- Implemented in [`scripts/verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-block-registry.py), the validator uses `html.parser.HTMLParser` to extract blocks and runs checks for blank IDs, duplicates, orphan parents, missing names, and cyclic hierarchies.
- **ADR 0010** mandates this gate to support traceable block decomposition across diagram types.
- The tool operates as a CLI utility with `--all` flag support, integrates into CI pipelines via exit codes, and exposes a Python API via the `check()` function.
- Validated block metadata can be exported as JSON using the `--registry` flag, ensuring downstream consumers receive structurally sound hierarchies.

## Frequently Asked Questions

### What happens if two blocks share the same data-block-id?

The validator detects duplicates via `find_duplicates()` and emits an error message listing every line number where the duplicate ID appears. The check fails until the ID is made unique or the redundant block is removed.

### Can a block have a parent from a different file?

No. The structural gate validates parent references only within the scope of a single file. The `find_orphan_parents()` function flags any `data-block-parent` value that does not match a `data-block-id` present in the same HTML or SVG document.

### How does the validator detect circular parent chains?

The `find_cycles()` function performs an ancestry walk for each block, tracking visited nodes. If a node is encountered twice during the traversal, the function constructs a cycle string (e.g., `A -> B -> C -> A`) and reports it as a validation error, preventing infinite loops in downstream tree processors.

### Is the validator required before exporting a diagram?

While the export command can run independently, using the `--registry` flag implicitly relies on valid metadata. The test suite in [`scripts/test-verify-block-registry.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/test-verify-block-registry.py) ensures the gate catches errors early, and CI integration blocks merges that would break the registry contract, effectively enforcing validation prior to export.