Commit Graph
4 Commits
Author SHA1 Message Date
jared 4ea0583d3a feat(per-capita): use per-year F-33 population in spending verbs
cog_spending(per_capita = TRUE) and cog_revenue(per_capita = TRUE) now
divide each year's amount by that gov-year's population from
gov_population_yearly (drawn from long.population) instead of a single
static ACS 2018-2022 value. Adds pop_source column with values
'census_f33' or 'unavailable'.
2026-04-29 16:36:22 -04:00
jared a778d790d8 fix: govid input ergonomics + clearer missing-govid message
Two UX fixes surfaced by first real-user use:

1. cog_spending / cog_revenue / cog_geographic_rollup now accept either
   a character vector OR a data.frame with a canonical_govid column
   (e.g. output of cog_gov_search() or cog_find_peers()). Shared
   .coerce_govid_input() helper in session.R. This lets the natural
   pipe work:

     cog_gov_search('MIAMI', state='FL', type='city') |>
       cog_spending(years=2022, category='Police')

   cog_peer_compare already accepted a data.frame for the peer arg;
   behavior there is unchanged.

2. .check_govids_in_scope() message reworded. The old text led with
   'v0.1 covers gov_types 0-3' which falsely implied the missing govids
   were scope-excluded types when the more common real cause is a typo
   or a guessed value. New message leads with typo + pre-2017 PID,
   mentions scope exclusion as one possibility, and points at
   cog_gov_search() as the recovery path.

Tests: 165 pass / 0 fail. check 0E/0W/0N.
2026-04-24 17:49:08 -04:00
jared 377eed1240 feat: cog_gov_search + cog_mirror + scope-aware verb behavior
Three pieces:

1. cog_gov_search: name/state/type search over canonical_fips_xwalk
   for resolving human-readable place names into canonical_govids.
   Accepts USPS abbrev ('FL') or FIPS int (12) for state; integer
   0-3 or name ('state','county','city','township') for type. Types
   4/5 emit an explanatory cli message and return an empty tibble
   (v0.1 corpus excludes them). USPS<->FIPS table hardcoded with
   50 states + DC + territories; FIPS 66 = GU (not GA).

2. cog_mirror: downloads manifest-listed files to a local directory
   with SHA-256 idempotency (files with matching hash return status
   'cached'). Supports HTTP and local-path fixture URLs. Round-trip
   test: mirror + re-open against the mirror + query Broward 2020
   returns identical results.

3. Scope-aware verbs: .check_govids_in_scope() helper in session.R
   queries canonical_fips_xwalk for the requested govids, emits a
   cli_inform listing any missing ones, and records the found/missing
   sets under provenance$scope. Wired into cog_spending (and
   transitively into cog_revenue, cog_geographic_rollup,
   cog_peer_compare via their cog_spending calls).

Also: dropped dbplyr from Imports (unused).

Tests: +29 (22 search + 12 mirror - 5 refactored) / 159 total pass.
devtools::check() now clean: 0E / 0W / 0N.
2026-04-24 11:38:32 -04:00
jared c682e6547d feat: cog_spending + cog_revenue + cog_explain
Three core query verbs over the spending_annotated / revenue_annotated
DuckDB views. Each verb accepts vector govid, vector years, optional
category filter, per_capita flag, and adjust_to_year for CPI-U
real-dollar conversion (bundled index).

Amounts are returned in full USD (SUM(amt) * 1000) so callers can
freely rescale to millions/billions. The $1,000s -> $USD conversion
is recorded in provenance$transformations$units_conversion.

Every result carries an attr(., "provenance") list matching
inst/schemas/provenance-v1.json. cog_explain() prints the structured
form via cli or returns the raw list for MCP/JSON consumers.

Also: .fetch_or_cache_manifest() now handles local fixture paths so
tests can point USCOGDATA_FIXTURE_URL at the pipeline publish_cache/
without a working HTTP server.

Tests: 80 pass / 0 fail. devtools::check() 0E/0W/2N (both notes
pre-existing / environmental).
2026-04-24 09:49:09 -04:00