Commit Graph

5 Commits

Author SHA1 Message Date
Fabio 662ccecb26 Board: surface the newly-nested municipals in county drill-downs
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>
2026-07-04 20:36:42 -04:00
Fabio 199d8b37d3 Municipals: nest 1,823 city officeholders under their real counties
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>
2026-07-04 20:23:57 -04:00
Fabio 7a2cc64362 Sync: officeholders v3 — fresh export from live Atlas DB (13,329 tenures)
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>
2026-07-04 18:56:37 -04:00
Fabio 5b0712c31f Add elections + demographics layer: candidates and jurisdictions
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>
2026-07-03 23:35:00 -04:00
Fabio d6874ca8a6 Close the institutional gap: bodies, committees, leadership
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>
2026-07-03 20:51:07 -04:00