Problem
ArchSpec::validate() (validate.rs:60) — the gate that every from_components and from_json_validated call passes through — performs no AOD geometry validation whatsoever. It is purely structural: minimum counts, non-negative grid spacings, uniform grid dimensions and word site counts, index ranges for site/word/zone bus refs and entangling pairs, bus relation well-formedness (unique sources, unique destinations, acyclic), zone-crossing for zone buses, mode validity, and zone bounding-box non-overlap. For paths it checks only finite coordinates, a valid zone_id, and waypoints.len() >= 2.
Nothing checks that a bus is physically realizable by an AOD: no Cartesian-product (complete-grid) check on bus endpoints, no uniform-displacement (single-shift) check, no check on the set of words participating in a site bus, and no check that a stored path bears any relation to the lane it is keyed by.
Today the only enforcement of AOD rectangle geometry is _validate_aod_rectangle in the Python ZoneBuilder (arch/build/imperative.py), plus a warnings.warn for the single-shift invariant in _compute_paths. A spec loaded from JSON never sees either — and that is how the production architecture is loaded (_physical_spec.json → from_json_validated). So the shipped Gemini physical spec's own buses have never been machine-checked for AOD feasibility; the "always go through the builder" guidance is the sole mechanism, and it is advisory.
Reproducer
A zone with two words whose intra-word site pitch differs — word 0's sites at x = 0/10 µm, word 1's at x = 100/130 µm — and a site bus [0] -> [1]:
ZoneBuilder.add_site_bus accepts it (its rectangle check runs in word-template index space, (s % nx, s // nx), which is identical for every word).
_compute_paths accepts it silently — its single-shift check reads self._site_nm(0, ...), i.e. word 0's coordinates only, so it never sees word 1's differing displacement.
- The generated path for word 1 runs
(100.0, 0.0) -> (110.0, 0.0), while that lane's own destination site is at (130.0, 0.0). The path terminates on empty space.
ArchSpec.from_components() and from_json_validated() both accept the resulting spec with zero errors and zero warnings.
The spec carries the contradiction internally: lane_endpoints() returns the correct destination, get_path() returns a path that does not go there, and nothing compares them.
The same class of hole exists one level up for word buses, whose displacement check is per-pair but reads only site 0 (self._site_nm(dw, 0)), so it assumes uniform intra-word geometry across words. Two words with 1 µm and 2 µm internal pitch produce a site-1 path ending at 51 µm when its destination is at 52 µm — again silent, again accepted by validate().
The check we already have, in the wrong place
check_lane_group_geometry (query.rs:859) is exactly the complete-grid / Cartesian-product test we want. It just never runs at spec-validation time — it is invoked from check_lanes on a runtime LaneAddr group about to execute as one AOD shot.
It also only covers the source side. Per lane_endpoints (query.rs:428), "site_id and word_id always encode the forward-direction source", and check_lane_group_geometry resolves position from those fields directly — so it validates the src rectangle and says nothing about destinations or displacement uniformity.
Proposal
In ArchSpec::validate(), synthesize the fully occupied lane group for every bus in every zone — the maximal set of lanes the bus can carry — and run the geometry check over it.
Group construction, per zone z:
- word bus
b: { LaneAddr(WordBus, w, s, b, Forward, z) | w in bus.src, s in z.sites_with_word_buses }
- site bus
b: { LaneAddr(SiteBus, w, s, b, Forward, z) | w in z.words_with_site_buses, s in bus.src }
Then assert, for each group:
- Source positions form a complete grid —
check_lane_group_geometry verbatim.
- Destination positions form a complete grid — same test applied to
lane_endpoints(lane).1. Needs either a variant taking LocationAddrs or a small refactor of check_lane_group_geometry into a helper over (f64, f64) positions.
- Uniform src→dst displacement across the whole group (the AOD single-shift invariant). Not covered by
check_lane_group_geometry at all; this is the check that catches the reproducer above. Promoting it from a Python warnings.warn to a spec-level error also makes it apply per-word/per-site rather than against word 0 alone.
- Path/lane endpoint consistency — for each entry in
paths, first waypoint == lane_endpoints(lane).0 position and last waypoint == .1 position. Cheapest of the four, catches the most, and is a pure consistency check between two fields the spec already carries.
(3) and (4) are independently valuable and could land first; (1) and (2) are the direct reuse the title refers to.
Blast radius
I audited both bundled specs against all four checks — everything passes, so this is additive with no expected churn on the Python side:
| Check |
gemini.physical |
gemini.logical |
| bus src & dst endpoints each form a Cartesian product |
pass (3 site + 19 word buses) |
pass (19 word buses) |
| uniform src→dst displacement across all participating words and sites |
pass |
pass |
| site-bus participating word set is rectangular |
pass (odd words = cols 1,3 × rows 0–4) |
pass |
| path first/last waypoint matches lane src/dst |
pass, 1120/1120 |
pass, 110/110 |
The real implementation cost is the hand-constructed specs in Rust tests — validate.rs's own ~30 test fixtures, arch/query.rs, atom_state.rs, bloqade-lanes-search/src/test_utils.rs, the CLI integration and C-API fixtures. Those are minimal specs built for structural coverage and were never required to be AOD-feasible; each will need auditing or adjusting. That is the bulk of the work, not the checks themselves.
Open questions
- Empty
words_with_site_buses with non-empty site_buses. build() emits [] both when a zone has no site buses and when no word opted in, so the fully-occupied site-bus group can come out empty. Decide whether that is a skip or an error (it is arguably already a malformed spec — site buses that no word can use).
- Zone buses. Left out of the proposal above; whether an inter-zone bus should satisfy the same complete-grid constraint depends on how the AOD hands off across zones, and I did not want to assume.
- Error taxonomy. Whether these become a new
ArchSpecError variant or reuse LaneGroupError::AODConstraintViolation wrapped into one.
Context
Found while reviewing #1006 (ArchBuilder.from_spec / ZoneBuilder.from_zone, implementing the spec in QuEraComputing/bloqade-internal#445). That PR makes the validating builder reachable for JSON-loaded specs, which is real progress — but it leaves AOD enforcement in the layer that can be bypassed rather than the layer that cannot. Deliberately kept out of #1006's scope.
Problem
ArchSpec::validate()(validate.rs:60) — the gate that everyfrom_componentsandfrom_json_validatedcall passes through — performs no AOD geometry validation whatsoever. It is purely structural: minimum counts, non-negative grid spacings, uniform grid dimensions and word site counts, index ranges for site/word/zone bus refs and entangling pairs, bus relation well-formedness (unique sources, unique destinations, acyclic), zone-crossing for zone buses, mode validity, and zone bounding-box non-overlap. Forpathsit checks only finite coordinates, a validzone_id, andwaypoints.len() >= 2.Nothing checks that a bus is physically realizable by an AOD: no Cartesian-product (complete-grid) check on bus endpoints, no uniform-displacement (single-shift) check, no check on the set of words participating in a site bus, and no check that a stored path bears any relation to the lane it is keyed by.
Today the only enforcement of AOD rectangle geometry is
_validate_aod_rectanglein the PythonZoneBuilder(arch/build/imperative.py), plus awarnings.warnfor the single-shift invariant in_compute_paths. A spec loaded from JSON never sees either — and that is how the production architecture is loaded (_physical_spec.json→from_json_validated). So the shipped Gemini physical spec's own buses have never been machine-checked for AOD feasibility; the "always go through the builder" guidance is the sole mechanism, and it is advisory.Reproducer
A zone with two words whose intra-word site pitch differs — word 0's sites at x = 0/10 µm, word 1's at x = 100/130 µm — and a site bus
[0] -> [1]:ZoneBuilder.add_site_busaccepts it (its rectangle check runs in word-template index space,(s % nx, s // nx), which is identical for every word)._compute_pathsaccepts it silently — its single-shift check readsself._site_nm(0, ...), i.e. word 0's coordinates only, so it never sees word 1's differing displacement.(100.0, 0.0) -> (110.0, 0.0), while that lane's own destination site is at(130.0, 0.0). The path terminates on empty space.ArchSpec.from_components()andfrom_json_validated()both accept the resulting spec with zero errors and zero warnings.The spec carries the contradiction internally:
lane_endpoints()returns the correct destination,get_path()returns a path that does not go there, and nothing compares them.The same class of hole exists one level up for word buses, whose displacement check is per-pair but reads only site 0 (
self._site_nm(dw, 0)), so it assumes uniform intra-word geometry across words. Two words with 1 µm and 2 µm internal pitch produce a site-1 path ending at 51 µm when its destination is at 52 µm — again silent, again accepted byvalidate().The check we already have, in the wrong place
check_lane_group_geometry(query.rs:859) is exactly the complete-grid / Cartesian-product test we want. It just never runs at spec-validation time — it is invoked fromcheck_laneson a runtimeLaneAddrgroup about to execute as one AOD shot.It also only covers the source side. Per
lane_endpoints(query.rs:428), "site_id and word_id always encode the forward-direction source", andcheck_lane_group_geometryresolves position from those fields directly — so it validates the src rectangle and says nothing about destinations or displacement uniformity.Proposal
In
ArchSpec::validate(), synthesize the fully occupied lane group for every bus in every zone — the maximal set of lanes the bus can carry — and run the geometry check over it.Group construction, per zone
z:b:{ LaneAddr(WordBus, w, s, b, Forward, z) | w in bus.src, s in z.sites_with_word_buses }b:{ LaneAddr(SiteBus, w, s, b, Forward, z) | w in z.words_with_site_buses, s in bus.src }Then assert, for each group:
check_lane_group_geometryverbatim.lane_endpoints(lane).1. Needs either a variant takingLocationAddrs or a small refactor ofcheck_lane_group_geometryinto a helper over(f64, f64)positions.check_lane_group_geometryat all; this is the check that catches the reproducer above. Promoting it from a Pythonwarnings.warnto a spec-level error also makes it apply per-word/per-site rather than against word 0 alone.paths, first waypoint ==lane_endpoints(lane).0position and last waypoint ==.1position. Cheapest of the four, catches the most, and is a pure consistency check between two fields the spec already carries.(3) and (4) are independently valuable and could land first; (1) and (2) are the direct reuse the title refers to.
Blast radius
I audited both bundled specs against all four checks — everything passes, so this is additive with no expected churn on the Python side:
gemini.physicalgemini.logicalThe real implementation cost is the hand-constructed specs in Rust tests —
validate.rs's own ~30 test fixtures,arch/query.rs,atom_state.rs,bloqade-lanes-search/src/test_utils.rs, the CLI integration and C-API fixtures. Those are minimal specs built for structural coverage and were never required to be AOD-feasible; each will need auditing or adjusting. That is the bulk of the work, not the checks themselves.Open questions
words_with_site_buseswith non-emptysite_buses.build()emits[]both when a zone has no site buses and when no word opted in, so the fully-occupied site-bus group can come out empty. Decide whether that is a skip or an error (it is arguably already a malformed spec — site buses that no word can use).ArchSpecErrorvariant or reuseLaneGroupError::AODConstraintViolationwrapped into one.Context
Found while reviewing #1006 (
ArchBuilder.from_spec/ZoneBuilder.from_zone, implementing the spec in QuEraComputing/bloqade-internal#445). That PR makes the validating builder reachable for JSON-loaded specs, which is real progress — but it leaves AOD enforcement in the layer that can be bypassed rather than the layer that cannot. Deliberately kept out of #1006's scope.