Multi-government aggregates disclose no reporting coverage: add the coverage argument and always-on coverage metadata #13
Closed
opened 2026-07-29 00:05:28 -04:00 by jared
·
0 comments
No Branch/Tag Specified
main
ci/mirror-canonical-tags
chore/release-47-badges-mirror-pr
docs/readme-perf-remeasure-56
feat/pagination-search-balances-57
feat/duckdb-threads-60
feat/cohort-predicates-58
fix/windows-backslash-paths
ci/mirror-to-github
ci/github-actions-matrix
feat/public-release-0.3.0
chore/fixture-sb203
ci/apt-https
fix/pushdown-pagination
feat/all-categories-37
fix/partial-coverage-signposting-9
fix/schema-v7
fix/cog-categories-balance-subtype
feat/cog-balances-25
feat/revenue-concepts-12
feat/expenditure-concepts-11
feat/coverage-disclosure-13
feat/complete-argument-18
fix/kodor-batch-14-15-16
fix/all-scoped-series-breaks-19
fix/regen-fixture-corpus-18
test/walkthrough-findings
feat/expenditure-concept
fix/3-url-trailing-slash
feat/phase-r3-signposting
fix/fixture-option-b-aggregates
feat/phase-r2-harmonization
feat/phase-r1-forward
feat/cog-gov-search-basket-mode
v0.4.0
Labels
Clear labels
kodor
kodor/feature-proposal
kodor/fix
kodor/needs-review
kodor/triaged
madison-walkthrough
severity/high
severity/low
severity/medium
south-guide
verdict/defect
verdict/definitional
kodor
kodor/feature-proposal
kodor/fix
kodor/needs-review
kodor/triaged
Kodor should process this issue
Kodor has written a feature proposal
Kodor should implement a fix (assigned to Kodor)
Kodor's work or failure needs Jared's review
Kodor has already triaged this issue (skip)
Surfaced while building the client-facing Southern API guide
needs
human
Cannot move without a person -- a decision, a check an agent cannot make, something outside the repo
origin
client
Came from a client ask
origin
obligation
Created by a change elsewhere
origin
review
Came from human review
origin
roborev
Promoted from a roborev finding
type
chore
Maintenance with no behaviour change
type
debt
Owed work -- docs, tests, cleanup a change obligated
type
decision
Needs a decision before work can proceed
type
defect
Something is wrong
type
feature
New capability
ws
api
Query verbs and results
ws
corpus
Corpus, mirror, provenance
ws
docs
Vignettes and guides
Assign a task to kodor
Kodor thinks this needs a feature.
Kodor should fix this
Kodor thinks the user is ready to review this.
Kodor is done with this issue.
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Civilytics/uscogdata#13
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Filed from the Madison walkthrough audit (
cog_explorer/docs/walkthroughs/FINDINGS.md, 2026-07-28). Verdict: definitional — the verbs do exactly what "sum/match what's there" should do; the gap is that the return value never says what "there" was.Root cause
The Census of Governments is a complete census only in years ending in 2 and 7. In every other year it is a sample, and the sample size varies enormously. Neither
cog_geographic_rollup()norcog_peer_compare()/cog_find_peers()has any concept of "the universe": each sums or labels whichevercanonical_govids happen to have rows in the requested years and returns that with no column, flag, orprovenanceentry distinguishing "every government reported" from "5% of governments reported."Both findings are one problem seen from two verbs, and the owner has settled one design that resolves both.
Findings resolved
cog_geographic_rollup()(and any multi-government aggregate built the same way) silently sums whichever governments reported that year, with no signal that the reporting universe varies 5.1%-99.5% year to yearcog_find_peers()fixes peer-cohort membership at a singlecohort_year, but nothing incog_peer_compare()'s return says how many of those peers actually reported in the years requested — for a small city's cohort, that can collapse to 3 of 15Reproduction (verbatim from FINDINGS.md, verified against the live corpus)
F-020
F-023
Both reproduce on the bundled fixture corpus (2011/2012/2019/2020), which is what the test asserts against: Wisconsin's 608-city universe rolls up 597 governments in FY2012 (a census year) but only 152 / 112 / 114 in FY2011 / FY2019 / FY2020; and Chilton's 15-peer cohort taken at FY2012 reports 15 of 15 in FY2012 and 3 of 15 in FY2019 and FY2020.
Why it matters
A caller who does not independently know the Census of Governments survey calendar has no way to learn from the return value alone that a given year's "statewide total" rests on a fraction of the actual governments. 43 of 55 years (78%) are sample years. The cleanest illustration: FY2002 (census, 591 govs, Madison's share 5.89%) to FY2003 (sample, 31 govs) — Madison's own total is essentially flat (+0.6%) while its apparent share more than doubles to 13.1% on the denominator collapse alone. The peer side is arguably worse exposure: the reassurance a Madison-scale user gets from a stable-looking peer band is not a property of
cog_peer_compare()— it is a property of Madison being large. Governments matched to a small target sit in exactly the population band most exposed to the sample cycle, and building a peer comparison for one's own small city is, if anything, a more common use of this package than a full geographic rollup.The machinery to say so already half-exists:
cog_geographic_rollup()'s provenance recordsexcluded_govidsfor the population case — a far smaller effect than the 5%-to-99% coverage swing that has no analog at all.The agreed design (settled 2026-07-28 by the project owner — not open for re-litigation)
A
coverageargument oncog_geographic_rollup(),cog_peer_compare()/cog_find_peers(), and theircog-apiequivalents:coverage = "all"— every unit that reported that year. Today's behaviour, and the default, kept for backward compatibility so nothing currently calling these verbs breaks.coverage = "census"— restrict to census years only (years ending in 2 or 7).coverage = "consistent"— restrict to units reporting in every requested year, producing a balanced panel.Independent of which mode is chosen, every result carries always-on coverage metadata —
n_units_reporting,n_units_expected,is_census_year— so that even the default"all"mode can no longer mislead silently.Motivating principle, stated by the owner: using these verbs correctly must not require the user to know that the Census of Governments is a complete census only in years ending in 2 and 7 — that fact about survey design belongs in the tooling, not in the analyst's head.
Definition of done
coverage = c("all", "census", "consistent")implemented oncog_geographic_rollup(),cog_find_peers(), andcog_peer_compare(), defaulting to"all".n_units_reporting,n_units_expected, andis_census_year, regardless of mode — reachable programmatically, not only viacog_explain().CENSUS_YEARSalone is not a fully reliable proxy for complete coverage: FY1967 reports only 97 of Wisconsin's 608 type-2 governments (16.0%), a nationwide pattern for that vintage (type-2 nationwide: 3,765 reporting in 1967 vs. 18,517 in 1972).is_census_yearmust be a statement about the survey calendar;n_units_reportingis what actually tells the truth.tests/testthat/test-coverage-disclosure.R→test_that("multi-government aggregates disclose reporting coverage on every result", ...). Against the fixture it asserts a Wisconsin all-cities rollup reportsn_units_expected == 608in every year withn_units_reportingof 597 (FY2012,is_census_year == TRUE) and 112 (FY2019,is_census_year == FALSE); that Chilton's FY2012 15-peer cohort reportsn_units_reporting == 3for FY2019; and thatcoverage = "consistent"returns only units present in every requested year. Remove theskip()on line 1 of the test body to activate.Cross-reference
cog-apicarries the same gap on its own surface, with an extra defect:provenance.scope.govids_missing— the field that looks built to answer exactly this — reports[]for a cohort member that contributed no rows. Tracked there as finding F-032.Severity: high. Verdict: definitional.