Atlas resolved every existing municipal officeholder to its Census place
GEOID at the source (PostGIS). build.py now prefers that exact geoid over
the name-based fuzzy resolver, so filled cities land on their node exactly
rather than by 98.8% name match. Resolved 2,217 -> 2,224; dedup against the
skeleton tightened (a few fuzzy mismatches now collapse correctly).
Note: this is the GEOID *backfill*, not the *fill* — zero net-new
officeholders; the 17,286 empty skeleton cities remain empty. Nationwide
municipal officeholder acquisition is a separate, per-state source problem.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Code empowers the executive branch, but the mirror only had legislative
Bodies — every authority reference pointed at nothing. Fixed by minting the
executive branch from the Code's OWN enumerations: 15 Cabinet departments
(5 U.S.C. § 101) + 21 Executive-Schedule Level I offices (§ 5312), 42 Body
nodes under us/executive/.
Then the axis: scripts/extract_authority.py matches named office/department
references across all 59,740 sections (guarding against Deputy/Assistant/Under
subordinates) and emits data/section_authority_edges.jsonl — 27,804 edges from
17,031 sections (28.7% of the Code) to the offices they empower. build.py
renders reciprocal 'empowered by' links on each office node; the section files
are never touched. Now: click the Attorney General, see all 2,386 sections that
vest authority in it.
Named references only in v1 (cabinet-level). Deterministic; body.schema
classification enum extended (executive-department/-agency/-office); make check
green at 105,746 records.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ingested titles 12–51 and 54 from OLRC USLM XML @119-100 (the whole Code
now, uniform edition; Title 53 is reserved/empty). LegalText 11,221 ->
59,740; repo total 105,704 records. Deterministic (byte-identical rerun,
verified on Title 42's 8,356 sections); make check green. make
legal-us-code default now covers every title.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This repo is a prototype testing a theory, not yet a mirror the public
relies on. The immutability disciplines (never-overwrite, never-rewrite,
raw-first-in-repo) are reframed as the v1.0 target, not day-3 law — a
mirror that force-pushes while preaching immutability would betray its
own founding principle. Until v1: history is malleable and raw source
snapshots live off-repo on the depot (.gitignore'd), with only the
product (records) and provenance (manifests + SHA-256) committed. The
147MB of already-tracked raw zips are dropped from HEAD (git rm --cached,
a forward delete — the bytes stay on the depot).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
README/roadmap/data-model updated for the city nodes: entity counts,
the places tree layout, and the roadmap pivot from 'mint local bodies'
to 'fill the municipal skeleton.'
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Regenerated data/jurisdictions with the municipal layer: 10,253 cities,
4,331 towns, 3,716 villages, 1,218 boroughs. Jurisdiction records
10,390 -> 29,908.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A city was a string buried in a job title; now it is a node. build.py
mints all 19,513 incorporated Census places (CDPs filtered out — they
are statistical, not governed) as Jurisdiction nodes keyed by place
GEOID, modelled exactly like a county: place + government fused, with
officeholders nested beneath, not a separate Body.
Officeholders join to their city by a name+state match (county-hint
disambiguated) off the same jurisdiction_label that city_slug uses for
placement, so node and people co-locate by construction. 2,229 cities
are filled today (2,217 GEOID-resolved, a 98.8% join); the other 17,289
are truthful skeleton stubs — 'governed, not yet mirrored' — the same
discipline as the nationwide county skeleton.
Deterministic (byte-identical on rerun); classification enum extended
with city/town/village/borough; validation green at 57,185 records.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
make build + make validate on GitHub Actions, plus a determinism
check: the committed tree must be byte-identical to the build output,
or the push fails. The mirror now guards itself.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
README and roadmap had drifted two syncs behind reality: 10,390
jurisdictions (incl. 6,824 state legislative districts), 13,329
people, 11,221 legal sections.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Raw OLRC USLM XML zips @ release 119-100 (retrieved 2026-07-04 via
Atlas depot), ingested with the standard pipeline: raw snapshot ->
per-section OKF markdown -> manifest + checksums. Title 52 untouched.
LegalText: 171 -> 11,221. Titles 12-54 await a clean OLRC retry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Code genuinely contains distinct sections sharing one number (two
5 U.S.C. 5757, two 10 U.S.C. 130g, two 5 U.S.C. 3598). The ingest
silently overwrote the first with the second — data loss in a mirror.
Later occurrences now get a deterministic -N suffix.
The 'elections' tag was hardcoded from the Title 52 seed; it now
applies only to Title 52, with a per-title EXTRA_TAGS map. Makefile
gains TITLES override: make legal-us-code TITLES="7 10".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fourth lens on the Board, coloring each county by the D/R balance of the
state + federal representatives who cover it — the offices that are
actually partisan (99% D/R coverage vs ~0% for nonpartisan local seats).
Pipeline (build_viz.py):
- Carry each district rep's party alongside their name through the
county<->district edge mapping.
- Per county, tally reps by party over districts covering >=5% of its
area (slivers excluded), and store lean = (R-D)/(R+D) in [-1,+1] plus
repD/repR counts. Head-count, not area-weighted, so the number matches
the readout and isn't skewed toward large rural districts. 3130/3131
counties resolve.
Board (board.html):
- "Partisan lean" lens with a diverging blue<->grey<->red ramp (centered
at 0, skipped in the percentile-rank machinery the other lenses use).
- Diverging legend (More Democratic / More Republican).
- Readout gains a Representation row (e.g. "8 D · 3 R D+45").
- Drill-down district reps get a D/R party badge.
Verified in preview: no console errors; Manhattan -1.0 (21D/0R), LA -0.46,
Palm Beach even (3D/3R), Loving TX +1.0; readout, color, and badges agree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wrap the county paths in a <g id="mapg"> and drive a translate/scale
transform from the mouse:
- scroll to zoom toward the cursor (1x-16x)
- drag to pan, clamped so the map can't leave the frame
- double-click to reset to the full view
County borders use vector-effect:non-scaling-stroke so they stay crisp
at every zoom level instead of thickening. The existing hover readout and
click-to-open county sheet keep working through event delegation; the
click handler is guarded (dragMoved / e.detail) so a pan gesture or the
reset double-click never pops a county sheet.
Pure view interaction — no data touched. Safe against `make board`, which
only rewrites the D/CDETAIL/TOTALS data lines.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Surfaces the new graph layer on the Board. build_viz.py resolves each
county's district edges to their current representatives (via
build.person_district_node) and injects a per-county `districts` block into
CDETAIL; board.html renders "In Congress / State Senate / State House"
sections in the drill-down, each rep with their district and % of county
covered. County detail now spans 3,221 counties (was 1,049) since every
county with district edges gets a drill-down, not only those with local
officials. Deterministic (board.html byte-identical on rerun).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first edges in the repo. Every US county now links to the districts it
sits in, weighted by area overlap, and every legislator links to the district
they represent — county → district → representative, traversable.
Data (PostGIS, no Atlas dependency — computed directly from geometry):
- data/county_district_edges.jsonl — 16,328 weighted edges. area_weight =
ST_Area(ST_Intersection(county, district))/ST_Area(county) over ST_MakeValid
Census TIGER 2024 geometries, overlaps <0.5% dropped. Uses area-intersection,
NOT centroid-in-polygon, so urban districts that carve through counties
(e.g. GA CD-5 / Atlanta across Clayton+DeKalb+Fulton) are captured, not
silently dropped. Per-county weights sum to ~1.0 per district type.
build.py:
- ~6,896 new district nodes: 435 CD (ACS demographics where available; sparse
for the 8 states missing from acs_cd) + 4,927 state-house + 1,897 state-senate
(geometry-only). GEOID/number-keyed, stable.
- county index.md gains a `districts:` block (frontmatter) + a ## Districts
section (body links, so link-integrity checks them).
- legislators + US House members gain `represents:` pointing at their district
node; edge stored once on the person, inverse left to the view.
- schemas/jurisdiction: classification enum + chamber/districts fields.
Honest gaps (logged, not hidden): ID + NH have no state-house geometry, so
their house districts get nodes (represents resolves) but no county edges;
CD nodes for acs_cd-missing states are demographically sparse.
Deterministic (byte-identical rebuild); validate.py passes 26,617 records,
link-integrity clean (every district/represents link resolves).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add `make board` and docs/board.md so the Board's rebuild-and-redeploy flow
is a documented step, not tribal knowledge. Covers why the county data is
inlined (self-contained Artifact / CSP), that build_viz.py injects it into
board.html, and that a live Artifact must be REPUBLISHED (editing the repo
file doesn't update a deployed Artifact). README links it in both the make
list and the docs index.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The page had no <title>, so browser tabs / the Artifact fell back to the
filename. build_viz.py's injection only rewrites the const lines, so the
title is preserved across regenerations.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Board is a self-contained Artifact, so its county data is INLINED
(const D / const CDETAIL) — the standalone county_*.json companions are not
read by it. build_viz.py was only writing those companions, so the rendered
Board kept showing the pre-crosswalk state (67 counties). Now build_viz.py
injects the fresh data straight into board.html's three marked const lines,
and the header stats read from an injected TOTALS object instead of being
hardcoded (so they can't go stale — the original 11,285 drift).
- scripts/build_viz.py — inject_board(): rewrite const D / CDETAIL / TOTALS
in board.html; load candidates + acs_cd for the totals
- viz/board.html — header driven by TOTALS; inlined data refreshed
(county drill-downs 67 → 1049 counties; e.g. Fulton GA now shows all 7
metro mayors)
Deterministic: board.html is byte-identical on rerun. Verified live —
header 13,329/2,494/3,131/363, Fulton/Bastrop drill-downs render nested
municipals.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The "OFFICEHOLDERS" stat was hardcoded to the old v2 Person count; v3 has
13,329. Counties/candidates/districts were unaffected. (Follow-up worth
doing: emit these header totals from build_viz.py so they can't go stale.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
build_viz.py was resolving officials to counties without the place→county
crosswalk, so only FL's 67 counties had rosters. Factor the resolver out of
build.py into a shared build.place_resolver() and use it in both, so the
Board and the tree agree by construction.
- scripts/build.py — extract place_resolver(); main() now calls it (tree
output byte-identical, refactor is behavior-preserving)
- scripts/build_viz.py — resolve via the shared resolver
- viz/county_data.json, viz/county_detail.json — regenerated
County drill-downs: 67 → 1049 counties with rosters; officials mapped
5184/5226 (42 county-unresolvable, tree-only). Deterministic.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pull Atlas's place→county crosswalk (Census TIGER 2024 places × county
geometries, 32,041 places) into the build as a committed raw input, and
use it to resolve municipal officeholders whose county was unknown.
- data/place_county_crosswalk.jsonl — new raw input (place_geoid → county_geoid)
- build.py — place-name+state → county_geoid → ACS county slug as a fallback
in county_slug(); city_slug() generalized to non-FL bare place labels
- data/sources/sources.yaml — provenance entry for the crosswalk
_unresolved municipals: 1919 → 58. The remainder are genuine: CT planning
regions (post-county), county-level rows mislabeled municipal upstream,
consolidated city-counties (null label), Wikidata-QID placeholder names,
and ambiguous same-name places — left unresolved rather than guessed.
Join key is county_geoid (5-digit FIPS); the directory slug is taken from
the ACS county node so municipals nest under the exact existing county dir.
Deterministic (byte-identical rebuild); validate.py passes 19,721 records.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-exported directly from Postgres (10.0.0.116), not Atlas's introspection,
which under-reported the roster (its v3 export had 11,473, missing the
restored Florida League of Cities municipal set). Live DB current tenures:
state 7,561 · municipal 4,009 · county 1,217 · federal 542.
- build.py now reads officeholders-v3.jsonl (was v2); dataset vintage 2026-07-04
- fixed one corrupt start_date at source-export (21021-12-03 -> 2021-12-03,
Lorraine Borowski, Mayor of Decorah IA)
- scripts/build_viz.py: committed, deterministic generator for the Board's
county_data.json / county_detail.json (previously built ad-hoc)
- generate_changelog.py: ignore files whose only change is the vintage stamp,
so the diff reflects government change, not re-export bookkeeping
Person files 11,285 -> 13,329. Non-FL municipal officials (1,903) are in the
tree but not yet county-mappable (place->county crosswalk still NULL).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Click any county to open a detail panel: its demographics, then the
actual officeholders in the mirror — grouped by county government and by
municipality, each with name and role — and a link to the county's files
on GitHub.
Richest for Florida, mirrored to the municipal level: e.g. St. Lucie
opens to 33 officeholders (18 county — commission, sheriff, tax collector,
school board — plus Fort Pierce, Port St. Lucie, and St. Lucie Village).
Counties without officeholders yet show their demographic node and a note.
Detail data (viz/county_detail.json, 181 KB) extracted from the entity
tree: 67 FL counties, 1,058 county + 2,124 municipal officials. Modal
closes on X, backdrop, or Esc. Verified in-browser: click opens the
panel, names render First-Last, municipality sections and GitHub links
resolve.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dropped the Coverage lens and its dark-unmapped framing. The Board is now
a pure demographic instrument: three lenses (median income, population,
poverty rate), every one coloring all 3,109 counties — no darkness, no
'not yet mapped', no fog-of-war copy. Rail shows Districts (363) instead
of 'counties lit'; the ledger describes the demographic lenses.
Also removed the load-in fade, which was flashing the map black on first
paint — it now renders fully colored immediately.
Verified in-browser: income (green) and poverty (amber) choropleths both
render full-country; lens switching and hover readout intact.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The county fills were technically correct but visually near-black: linear
min-max scaling crammed a right-skewed distribution into the dark end, so
the map read as empty. Fixes:
- Rank (percentile) coloring — spread the full palette evenly across
counties, the standard choropleth technique, so every lens shows rich
variation instead of a few bright outliers on black.
- Brighter per-lens ramps (income green, population teal, poverty amber).
- Coverage amber lifted so Florida's 67 lit counties are unmistakable
against the fog-of-war country.
- Default lens is now Median income, so the map opens full of color;
Coverage (the fog of war) is one click away.
Verified in-browser: full green income choropleth, Florida clearly lit in
coverage, hover readout prints each county's demographics + officeholders.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The map grew with the data. The old Board showed coverage at the state
level with a Florida drill-down; now that every US county is a demographic
node, the Board renders all 3,109 contiguous counties directly, with
switchable lenses:
Coverage — the true fog of war: 67 FL counties lit (officeholders
mirrored), the other 3,000+ dark on the frontier.
Population — ACS 2023 choropleth, 33 to 9.8M.
Median income — k to k.
Poverty rate — 1.4% to 48%.
Hover any county for its full readout (demographics + officeholder count).
Self-contained: inlined county geometry (duplicate-point-collapsed),
state-border overlay, hand-rolled projection, event-delegated hover for
3,109 paths, vanilla JS — no external requests. Verified: projection
places counties correctly, 3,099/3,109 join to ACS data.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The README described intent; the repo is now real. Rewrote it to reflect
what actually exists — 17,506 validated files across four entity types,
the deterministic pipeline, the commands — and added the /docs tree:
government-as-code.md the philosophy: git primitives -> government
data-model.md entity types, IDs, file format, the tree, determinism
sources.md where every fact comes from, and how current
roadmap.md done / next / later, honest about what isn't built
contributing.md the disciplines, and how to add a source
Plus data/sources/sources.yaml — the machine-readable source registry.
Every count, path, and source claim is grounded in the current tree, not
the aspirational brief. Internal links verified; validation still clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The diff is the product — now literally. generate_changelog.py reads a
git diff of the entity tree between any two refs and says, in plain
language, what changed in the government: entities added / modified /
removed, grouped by type and by jurisdiction, dated from the commit.
CHANGELOG.md is seeded from the real history so far:
- initial load: +11,285 people across 51 states
- institutional gap: +233 bodies, ~532 people enriched
- elections + demographics: +2,494 candidates, +3,494 jurisdictions
(TX +541, FL +396, CA +341 ...)
On an initial load every entity is an addition; on a re-sync of the same
source, only real government changes will surface — which is the whole
point. When nothing changed, it says so.
make changelog [BASE=.. HEAD=..]. No third-party deps.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The README claimed 'validated by JSON Schema' — now it is true.
/schemas holds a JSON Schema for each entity type (Person, Body,
Candidate, Jurisdiction): a stricter profile over OKF's permissive
base, tolerating unknown keys by design.
scripts/validate.py checks all 17,506 files with no third-party deps
(hand-rolled frontmatter parser + minimal schema engine):
1. OKF conformance — every file has frontmatter with a non-empty type
2. Schema conformance — required fields, property types, enums
3. Link integrity — internal /-rooted links resolve
Non-zero exit on failure, so it is a CI gate. Verified with a negative
test: it catches bad enums and dead links. All 17,506 files pass today.
Makefile ties it together: make build / validate / check.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two new entity types, built deterministically from the raw exports:
Candidate (2,494) — 2026 federal candidates as files under
us/states/<st>/candidates/, with office,
district, party, incumbent/challenger stance,
campaign committee, FEC id.
Jurisdiction (3,494) — demographic nodes carrying ACS 2023 data:
3,131 counties (deduped from 3,231 mixed-format
fips keys) + 363 congressional districts.
This completes the county skeleton nationwide: every US county is now a
browsable node with population, income, poverty, race, education and
housing — even where no officeholders are mapped yet. In Florida the
county index.md merges into the existing dir and reports its officeholder
count alongside demographics (St. Lucie: 33 officeholders + ACS profile).
build.py now reads seven raw inputs in one deterministic pass
(byte-identical on rerun). The mirror now answers: who holds power, who
runs this institution, who is running, and what each place is made of.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three new source datasets from Atlas, committed as-is before any build:
fec_candidates.jsonl 2,494 2026 federal candidates (officeholders.fec_data)
acs_county.jsonl 3,231 Census ACS 2023 by county (~100 dup keys to dedupe)
acs_cd.jsonl 363 Census ACS 2023 by congressional district
A new axis for the mirror: who is running (candidates) and the
demographics of each place (ACS). Keyed on fec_id / state+district /
county_fips — no person links yet. Raw first; the build into Candidate
and Jurisdiction entities follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The one radical view whose data is fully real today (brief §4.5).
Renders every officeholder in the mirror as coverage: teal is the
federal + state tier (the roof, every state), amber is county +
municipal depth (the foundation, so far only Florida). Click Florida
to descend into its 67 counties, shaded by local officeholder count.
Self-contained: inlined US state + FL county geometry, hand-rolled
lng/lat projection, vanilla JS — no external requests, no build deps.
Instrument aesthetic: dark ground, mono readout, breathing amber to
invite the drill-down. viz/coverage.json is generated from the tree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seat data answered 'who represents this place?' but not 'who runs
this institution?' — the Speaker of the House existed only as the rep
for LA-4. This adds the missing axis of institutional power.
New Body entities (233): the U.S. House, U.S. Senate, Executive Office,
49 committees, 181 subcommittees — each with its leadership.
Federal people (532/542) enriched with bioguide IDs, leadership roles,
and committee seats, reconciled from congress-legislators by name.
Mike Johnson is now Speaker of the House, not just LA-4.
Sources ingested directly into the repo (repo-canonical): Atlas
supplied bodies/leadership/committee_memberships via congress-legislators,
committed raw in data/. build.py supersedes convert_officeholders.py and
reads all four inputs in one deterministic pass (byte-identical on rerun).
The 10 unenriched federal records are a finding, not a bug: vacancies,
the President, and ~5 seats where Atlas's roster disagrees with the
authoritative current roster — model-vs-reality discrepancies to surface.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One record, one file. The jurisdiction tree is now real:
us/people/ 542 federal
us/states/<xx>/people/ 7,561 state
us/states/fl/counties/<c>/people/ 1,058 county
.../municipalities/<m>/people/ 2,124 municipal (67 FL counties)
Each file is OKF markdown + YAML frontmatter: fixed key order,
field-level source provenance, Atlas UUIDs for round-tripping,
deterministic paths and slugs. Converter passes the determinism
test: two runs, byte-identical tree.
Generated by scripts/convert_officeholders.py from
data/officeholders-v2.jsonl (unchanged).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The only surviving copy of the dataset after the DB loss on
10.0.0.116 — committed as-is, before any transformation.
Federal (536), state (7,560), county (1,057), municipal (2,118)
current officeholders. Source: Atlas via /depot/exports,
generated 2026-07-03.
Raw first, refined later: the conversion into structured entity
files will itself be a visible diff.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Government as an operating system, git as its missing changelog.
The mirror architecture, influence as a computable tool, a visual
grammar for power, and the game layer that lights the map.
The diff is the product.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>