Skip to content

Add the US block -> congressional-district plan registry (117th-120th) - #1041

Merged
MaxGhenis merged 2 commits into
mainfrom
us-cd-plan-registry
Sep 28, 2026
Merged

MaxGhenis merged 2 commits into
mainfrom
us-cd-plan-registry

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

What this adds

A versioned, SHA-pinned registry of every populated 2020 census block's congressional district under each registered plan. A household's location is one block and every other geography is a lookup from it. This file supplies the district lookup for every map, so the block draw (the separate location v1 PR, owned by another session) can derive each plan's district from the chosen block. It also makes SOI's 117th-plan district tables exact sums of blocks under the registry's assignments, so consumers need no crosswalk. The assignments follow Census's whole-block tabulation, and North Carolina's 117th rows are carried from 2010 blocks, so they approximate the official boundaries.

No household assignment code is touched. congressional_district_geography.py, geography_ladder.py and puma_ladder.py are unchanged, and the new module is outside the spec engine's hashed kernel list. The PUMA × county × district atom table is deliberately out of scope (it is a later optimization under the version 1 location design).

Plan id Source Apportionment
117th_congress (SOI CD tables, TY2020–2022) 2020 BAF CD layer; North Carolina carried from its 2019 plan (below) 2010
118th_congress Census 118th CD block equivalency file 2020
119th_congress (primary; the block ladder's plan) Census 119th CD block equivalency file 2020
120th_congress (the 2026 elections) Census 120th CD block equivalency file, published 2026-08-31; Missouri on its 2022 map (below) 2020

Files:

  • us_runtime/cd_plan_registry.py: parsers, assembly, the validating loader load_us_cd_plan_registry and the pinned loader load_pinned_us_cd_plan_registry, the ladder differential, and the 2010→2020 crosswalk.
  • tools/build_us_cd_plan_registry_artifact.py: the builder.
  • us_cd_plan_registry.provenance.json: the receipt, holding the artifact SHA-256 6b16fc21…, every source's URL and SHA-256, per-plan totals and every check's result.
  • US_CD_PLAN_REGISTRY.md: the documentation.

The built artifact (17.8 MB) is at _buildf-runtime/inputs/us_cd_plan_registry_2020.npz, next to the Route A block ladder.

Two places the registry departs from a single Census file

  • North Carolina, 117th. Census says NC is the only state whose districts changed between the 116th and 117th Congress, and it never tabulated the 117th on 2020 blocks. The BAF CD layer is NC's 2016 plan, which puts only 55% of NC's population in the same district as the 2019 plan the 117th used. So NC's rows carry the General Assembly's 2019 block file (HB 1029, S.L. 2019-249; 2010 blocks) onto 2020 blocks through the Census 2010→2020 relationship file, by largest intersecting land area.
    • Method check: the same method run on the 2016 plan reproduces Census's own 2020-block version for 99.992% of NC's population. The build refuses below 99.9%.
    • Result check: district populations are within 704 people (0.09%) of NCGA's official 2020 figures for the 2019 plan. The build refuses above 0.5%.
  • Missouri, 120th. Census's 120th rows encode the 2025 HB 1 map, and Census's own landing page warns they may not be the districts in place. The Missouri Supreme Court held on 2026-09-03 (von Glahn v. Hoskins) that HB 1 cannot take effect before the referendum. The U.S. Supreme Court held on 2026-09-25 (26A388, per curiam) that "the 2022 map—not the 2025 map—must be used in the 2026 congressional election." Missouri's rows are therefore its 2022 map, from the 119th file (checked unchanged since the 118th).
    • Every other Census redraw was checked against primary sources and stands: AL, CA, FL, LA, NC, OH, TN, TX, UT. Virginia correctly keeps its 119th map.

Both are recorded in plan_sources[plan]["known_deviations"].

Invariants

Structural invariants hold for every registry the loader accepts. They are checked at build time and again on every load:

  1. Shape: the block, population and plan arrays are 1-D and aligned; the blocks are 15-digit geoids, sorted and unique, with positive population.
  2. Partition: every block has exactly one district under every plan, in its own state. A populated block a source leaves unassigned is an error, never a gap.
  3. Apportionment: each state's districts are exactly 00 (at-large or DC) or 01..n, where n is its House seats for that plan's census. So every district holds a populated block.
  4. Conservation: for every plan, district populations sum exactly to state populations, and states sum to the national total.
  5. Determinism: the artifact's bytes depend only on the inputs' contents. Two independent national builds gave the same SHA-256.

These checks are structural, so a --states subset also passes them. National completeness comes from three things: the build covers every 2020 P.L. 94-171 block with positive population in the 50 states and DC (5,769,942 blocks, 331,449,281 people); the registry agrees exactly with the block ladder; and load_pinned_us_cd_plan_registry enforces the SHA-256 pin.

Differential checks (run by the builder, fail closed)

  • The packaged seat counts match the Census apportionment table.
  • Each Census file's state files match that state's rows in its national file.
  • The states whose blocks change 118th→119th and 119th→120th are exactly Census's redrawn-state lists (AL, GA, LA, NY, NC; and AL, CA, FL, LA, MO, NC, OH, TN, TX, UT).
  • The one block Census lists as split by a district line (Colorado 080010096072000) is tabulated with the district Census names. The split notes are pinned by SHA-256, so a changed note fails the build.
  • Against the Route A block ladder (SHA 7ba39b95…): exact agreement on all 5,769,942 blocks, their populations and their 119th districts.
  • NC's method and result checks above.

Tests

  • test_us_cd_plan_registry_properties.py: Hypothesis properties on random multi-state geographies.
    • Partition, conservation and apportionment hold for every plan, and the bytes are independent of input order.
    • Dropping, crossing or merging any assignment is refused, and the ladder differential refuses any single change.
    • The crosswalk matches a reference implementation, is independent of row order, and the fill preserves the districts the crosswalk assigned.
    • Ran with 10 seeds locally, all passing.
  • test_us_cd_plan_registry.py: parser formats (BAF, all three BEF layouts, legislature CSV) and refusals, round-trip and tamper tests, the pinned SHA, the ladder differential, and the packaged receipt's contents. An opt-in test (MICROCOSM_US_CD_PLAN_REGISTRY / MICROCOSM_US_BLOCK_LADDER) re-checks a real artifact; it passed locally against the built file.
  • test_us_cd_plan_registry_crosswalk.py: crosswalk examples, including a minimized counterexample the property tests missed and the fix now covers (a state whose 2010 counterparts are all outside the plan).

Review

Astra (GPT-6, hard tier) reviewed the first head and requested changes. All eight findings are addressed in fd9a022:

  • Shapes: the loader and the ladder differential refuse arrays that are not 1-D and aligned.
  • Split notes: pinned by SHA-256, so a changed note fails the build.
  • Claims: the universe and "exact sums" wording is narrowed as described above.
  • Tests: a county, tract and block-group fill property checked against a reference implementation, a lazy-parse test, and tamper tests.
  • Benchmark: the build's time and memory are labelled as an unrecorded local observation.

The CI classification failure is fixed: cd_plan_registry.py is registered as a reviewed non-registry runtime module.

Local results on fd9a022:

  • The registry tests all pass, including the opt-in test against the built artifact.
  • test_us_spine_blindness.py passes (498 tests).
  • ruff check ., tools/ci_test_groups.py --verify and tools/build_and_inspect_wheels.sh pass.

axiom: n/a: geography data infrastructure, no policy rules

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits September 27, 2026 18:49
Record, for every populated 2020 census block, its district under each
registered plan, so a block draw can derive every plan's district from the
chosen block and SOI's 117th-plan district tables become exact block sums.

- 117th_congress: 2020 BAF CD layer; North Carolina carried from its 2019
  plan onto 2020 blocks through the Census 2010-2020 block relationship
  file (method reproduces Census's 2016 plan for 99.992% of NC population;
  districts within 0.09% of NCGA's official 2020 figures).
- 118th/119th_congress: Census block equivalency files.
- 120th_congress: Census's 120th file (2026-08-31), with Missouri on its
  2022 map per the 2026-09-25 Supreme Court order in 26A388.

The builder cross-checks apportionment, Census state vs national files,
Census's redrawn-state lists and split blocks, and agrees exactly with the
block ladder; the loader re-checks every invariant; the artifact is
byte-reproducible and pinned in us_cd_plan_registry.provenance.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Loader and ladder differential refuse arrays that are not 1-D and
  aligned (a (n, 1) population or trailing ladder values used to pass).
- The builder pins the reviewed Census block-split notes by SHA-256 and
  refuses a changed note, since CENSUS_BLOCK_SPLITS transcribes them.
- Docs and docstrings: the loader's checks are structural; national
  completeness comes from the build, the ladder agreement and the pin.
  "Exact block sums" is qualified for North Carolina's carried plan.
- The 120th note says "the 2026 elections" (Louisiana's Nov 3 is a
  primary). District data unchanged; artifact sha256 6b16fc21...
- Tests: tamper cases for shapes, misaligned ladder arrays, a lazy-parse
  test that fails if the stream is materialized, split-note pin tests,
  and a fill property over several counties, tracts and block groups
  checked against a reference implementation.
- Classify cd_plan_registry.py as a reviewed non-registry runtime module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Merging on behalf of the Route A session that spawned this work (the authoring session is gone). Gates: gh pr checks exits 0 on the latest run at head fd9a022; mergeable MERGEABLE; no CHANGES_REQUESTED. Independent review: subfleet gate 20260928-010434-pr-c347f9b8, Astra peer round 1 verdict approve with no findings at head fd9a022 (base 9e5b0ce), following an earlier Astra request-changes round whose eight findings fd9a022 addressed. Main has since moved only by #1012 (UK spine; no overlap with this PR's files), and main is green at 937aca4. #1043 (stacked) will be retargeted to main next.

🤖 Generated with Claude Code

@MaxGhenis
MaxGhenis merged commit 8d18463 into main Sep 28, 2026
11 checks passed
juaristi22 added a commit that referenced this pull request Sep 28, 2026
…rminal tests

Rebase onto main 4b57d15 (#1007 unified calibration diagnostics, #1041,
#1046). The calibrated gate battery now hands a typed rotated-holdout report
to the diagnostics, so the kernel test's holdout fixture is a complete
UKMeasuredRotatedHoldout; the synthetic graph driver's fake diagnostics
declare the legacy schema, like the rowwise-tool candidate fixture in the
assembler tests, because the assembler validates only the current schema,
which the real gate kernel emits. The lock pin is re-recorded on the merged
lock (696ea49c...), inside the graph-registration commit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis deleted the us-cd-plan-registry branch September 28, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant