Show per-geography household-record coverage on the populace overview#97
Show per-geography household-record coverage on the populace overview#97DTrim99 wants to merge 2 commits into
Conversation
Renders the geography_coverage section populace releases now publish in demographics.json (populace#358): unweighted household-record counts by state and congressional district. KPI row (districts, median records, districts under 50 with a district-ready / blocks-district-analysis badge, min state records) plus the thinnest districts when any fall under 50. Records are the sub-national resolution floor — the 2026-07 national-only release has 48 districts under 50 (median 114, min TX-08 at 25), which blocked congressional-district features with no dashboard visibility. Hidden for releases without the section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
left a comment
There was a problem hiding this comment.
Nice, focused addition — the "record counts are the resolution floor no calibration can rescue" framing is exactly right, and the card makes CD-readiness visible per release instead of by ad-hoc H5 inspection. Reviewed the data contract, the plumbing, backward-compat, and conventions. One thing I'd fix before merge (the stray lockfile); the rest is optional.
Verified
Consumes populace#358's output, doesn't recompute. The card reads the precomputed geography_coverage from demographics.json end-to-end: loadReleaseUncached fetches it → buildCalibration passes it through → latestPopulaceCalibrationSummary threads it to the summary → /api/populace exposes it and lists demographics in source_artifacts → typed in use-populace.ts. The component only sorts counts to pick the 10 thinnest for display; every number shown (n_geographies, household_records_median, n_under_50, household_records_min) comes straight from the artifact.
The type contract matches populace#358 field-for-field. I checked GeographyCoverageBlock against geography_coverage_payload in populace#358's demographics.py: unit, states/congressional_districts blocks, and {n_geographies, household_records_min/median/max, n_under_50, n_under_100, counts} all line up, and the consumer handles congressional_districts: null (the no-district-column case populace#358 tests). So the card will populate correctly once a release is built with that payload — no silent "—" from a name mismatch.
Backward-compatible. .catch(() => ({})) on the demographics.json fetch plus the null fallthrough means releases published before the section exists render nothing rather than breaking — consistent with the PR description.
Findings
1. Remove frontend/package-lock.json before merge. This repo is bun (bun.lock is the tracked lockfile on main, and the repo tooling actively rejects npm). package.json is unchanged in this PR, so no dependency was actually added — the lockfile looks like an accidental npm install, and it's 5,633 of the 5,739 added lines. A package-lock.json sitting next to bun.lock is a real hazard: Vercel or any npm-based tooling can resolve dependencies from it and drift from the bun-resolved tree. Suggest deleting it and adding package-lock.json to .gitignore.
2. Minor: text-red-600 is the one off-system color. Everything else uses semantic tokens (text-muted-foreground, border-border, the KpiCard tone system) — text-red-600 on the sub-floor chips is the only raw Tailwind palette value in the diff, and there's no prior use of it in the repo. text-destructive would keep it on the token system and adapt to dark mode consistently with the negative tone you're already using on the KPI above it.
3. Repo-level (not a blocker for this PR): there's no CI. gh pr checks reports "no checks reported" — the repo has no .github/workflows, so the "typecheck and next build pass" claim can't be enforced automatically. The frontend already has make typecheck (tsc --noEmit) and next build; a minimal Actions workflow running both on PRs would make that guarantee real going forward. (For this PR I verified the populace#358 contract by hand in lieu of CI — worth noting tsc wouldn't have caught a field-name mismatch anyway, since the payload crosses the boundary as JsonObject.)
Functionally this is ready once the lockfile is gone. Thanks for wiring the readiness signal in before it bites another dashboard.
The package-lock.json was an accidental npm install artifact in a bun repo (5.6k lines of the diff, and a real npm/bun resolution-drift hazard) — removed and gitignored. The sub-floor district chips move from raw text-red-600 to the text-destructive token, consistent with the KpiCard tone system. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Both findings addressed: the stray |
Companion to populace#358, which adds a
geography_coveragesection (unweighted household-record counts by state and congressional district) to each release'sdemographics.json.What it shows
A "Geography coverage" card on the populace overview:
district-ready/blocks district analysistone badge — zero is the readiness bar), and min records/state.TX-08: 25), red below the floor.Why
Record counts are the resolution floor no calibration can rescue. The current
national-onlyrelease has 48 districts under 50 records — which just blocked congressional-district features on the child-poverty dashboard, discovered only by ad-hoc H5 inspection. This makes CD-readiness visible per release, including on staging candidates before publish.Plumbing
loadReleasenow also fetchesdemographics.json(.catch(() => ({}))— releases without it, i.e. all current ones until populace#358 ships in a build, render nothing).geography_coveragethreaded throughbuildCalibration→latestPopulaceCalibrationSummary→/api/populace(also listed insource_artifacts) → typed inuse-populace.ts.Typecheck and
next buildpass.🤖 Generated with Claude Code