Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| -- Verification queries for the priority-states scrape batches. | |
| -- | |
| -- Run via psql against Neon dev (NEON_DATABASE_URL_DEV): | |
| -- ./packages/hosting/scripts/neon/psql_resolved.sh -f scripts/datasources/jurisdiction_pilot/verify.sql | |
| -- Or pass a specific batch: | |
| -- psql "$NEON_DATABASE_URL_DEV" \ | |
| -- -v batch="'<batch-uuid>'" \ | |
| -- -f scripts/datasources/jurisdiction_pilot/verify.sql | |
| \if :{?batch} | |
| \else | |
| \set batch (SELECT scrape_batch_id::text FROM ( \ | |
| SELECT scrape_batch_id, MAX(loaded_at) AS t FROM bronze.bronze_contacts_scraped GROUP BY 1 \ | |
| UNION ALL \ | |
| SELECT scrape_batch_id, MAX(loaded_at) AS t FROM intermediate.int_events_channels_candidates GROUP BY 1 \ | |
| ) x ORDER BY t DESC LIMIT 1) | |
| \endif | |
| \echo | |
| \echo === Batch in scope === | |
| SELECT :batch::uuid AS batch_id; | |
| \echo | |
| \echo === Contacts per state === | |
| SELECT | |
| state_code, | |
| COUNT(DISTINCT jurisdiction_id) AS jurisdictions_with_contacts, | |
| COUNT(*) AS contact_rows, | |
| SUM((raw_row->>'is_mayor')::boolean::int) AS mayor_rows, | |
| SUM(CASE WHEN email IS NOT NULL THEN 1 END) AS rows_with_email, | |
| SUM(CASE WHEN phone IS NOT NULL THEN 1 END) AS rows_with_phone | |
| FROM bronze.bronze_contacts_scraped | |
| WHERE scrape_batch_id = :batch::uuid | |
| GROUP BY state_code | |
| ORDER BY state_code; | |
| \echo | |
| \echo === YouTube: candidates vs verified (this batch) === | |
| SELECT | |
| 'candidates' AS layer, | |
| state_code, | |
| COUNT(DISTINCT jurisdiction_id) AS jurisdictions, | |
| COUNT(*) AS channel_rows, | |
| COUNT(*) FILTER (WHERE is_verified) AS verified_flagged, | |
| COUNT(*) FILTER (WHERE NOT is_verified) AS rejected, | |
| COUNT(DISTINCT rejection_reason) AS distinct_rejection_reasons | |
| FROM intermediate.int_events_channels_candidates | |
| WHERE scrape_batch_id = :batch::uuid | |
| GROUP BY state_code | |
| UNION ALL | |
| SELECT | |
| 'verified_canonical' AS layer, | |
| state_code, | |
| COUNT(DISTINCT jurisdiction_id), | |
| COUNT(*), | |
| COUNT(*) FILTER (WHERE is_primary), | |
| NULL::bigint, | |
| NULL::bigint | |
| FROM intermediate.int_events_channels | |
| WHERE scrape_batch_id = :batch::uuid | |
| GROUP BY state_code | |
| ORDER BY layer, state_code; | |
| \echo | |
| \echo === Rejected candidate reasons (top) === | |
| SELECT | |
| COALESCE(rejection_reason, '(verified)') AS reason, | |
| COUNT(*) AS n | |
| FROM intermediate.int_events_channels_candidates | |
| WHERE scrape_batch_id = :batch::uuid | |
| GROUP BY 1 | |
| ORDER BY n DESC | |
| LIMIT 20; | |
| \echo | |
| \echo === Verified YouTube channel purpose breakdown === | |
| SELECT | |
| COALESCE(channel_purpose, 'unknown') AS channel_purpose, | |
| COUNT(*) AS rows, | |
| COUNT(*) FILTER (WHERE is_primary) AS primary_rows | |
| FROM intermediate.int_events_channels | |
| GROUP BY 1 | |
| ORDER BY rows DESC; | |
| \echo | |
| \echo === Non-meeting channels still in verified (should review) === | |
| SELECT jurisdiction_id, channel_title, channel_purpose, official_meeting_confidence | |
| FROM intermediate.int_events_channels | |
| WHERE channel_purpose IN ('county-general', 'municipality-general', 'tv-public', 'unknown') | |
| ORDER BY channel_purpose, jurisdiction_id | |
| LIMIT 30; | |
| \echo | |
| \echo === Verified YouTube metadata coverage === | |
| SELECT | |
| COUNT(*) AS rows, | |
| COUNT(*) FILTER (WHERE channel_description IS NOT NULL AND BTRIM(channel_description) <> '') AS has_description, | |
| COUNT(*) FILTER (WHERE subscriber_count IS NOT NULL) AS has_subscribers, | |
| COUNT(*) FILTER (WHERE video_count IS NOT NULL) AS has_video_count, | |
| COUNT(*) FILTER (WHERE latest_upload IS NOT NULL AND BTRIM(latest_upload) <> '') AS has_latest_upload, | |
| COUNT(*) FILTER (WHERE jsonb_array_length(jurisdiction_website_back_links) > 0) AS has_back_links | |
| FROM intermediate.int_events_channels; | |
| \echo | |
| \echo === City channels incorrectly on counties (should be 0 verified) === | |
| SELECT | |
| y.jurisdiction_id AS county_id, | |
| j.name AS county_name, | |
| y.channel_title, | |
| y.youtube_channel_url | |
| FROM intermediate.int_events_channels y | |
| JOIN intermediate.int_jurisdictions j ON j.jurisdiction_id = y.jurisdiction_id | |
| WHERE y.jurisdiction_type = 'county' | |
| AND ( | |
| LOWER(BTRIM(COALESCE(y.channel_title, ''))) ~ '^city of ' | |
| OR POSITION('cityof' IN LOWER(y.youtube_channel_url)) > 0 | |
| ) | |
| ORDER BY y.state_code, y.jurisdiction_id | |
| LIMIT 25; | |
| \echo | |
| \echo === YouTube metadata quality (junk titles / missing description / back-links) === | |
| SELECT | |
| 'verified' AS layer, | |
| COUNT(*) AS rows, | |
| COUNT(*) FILTER ( | |
| WHERE LOWER(BTRIM(channel_title)) IN ('home','videos','shorts','live','playlists','community','about') | |
| ) AS junk_tab_titles, | |
| COUNT(*) FILTER ( | |
| WHERE channel_description IS NULL OR BTRIM(channel_description) = '' | |
| ) AS missing_description, | |
| COUNT(*) FILTER ( | |
| WHERE jsonb_array_length(jurisdiction_website_back_links) > 0 | |
| ) AS has_jurisdiction_back_links | |
| FROM intermediate.int_events_channels | |
| UNION ALL | |
| SELECT | |
| 'candidates', | |
| COUNT(*), | |
| COUNT(*) FILTER ( | |
| WHERE LOWER(BTRIM(channel_title)) IN ('home','videos','shorts','live','playlists','community','about') | |
| ), | |
| COUNT(*) FILTER ( | |
| WHERE channel_description IS NULL OR BTRIM(channel_description) = '' | |
| ), | |
| COUNT(*) FILTER ( | |
| WHERE jsonb_array_length(jurisdiction_website_back_links) > 0 | |
| ) | |
| FROM intermediate.int_events_channels_candidates; | |
| \echo | |
| \echo === Rows with junk tab titles (sample) === | |
| SELECT | |
| 'verified' AS layer, | |
| jurisdiction_id, | |
| channel_title, | |
| LEFT(channel_description, 80) AS description_preview, | |
| jurisdiction_website_back_links, | |
| youtube_channel_url | |
| FROM intermediate.int_events_channels | |
| WHERE LOWER(BTRIM(channel_title)) IN ('home','videos','shorts','live','playlists','community','about') | |
| UNION ALL | |
| SELECT | |
| 'candidates', | |
| jurisdiction_id, | |
| channel_title, | |
| LEFT(channel_description, 80), | |
| jurisdiction_website_back_links, | |
| youtube_channel_url | |
| FROM intermediate.int_events_channels_candidates | |
| WHERE LOWER(BTRIM(channel_title)) IN ('home','videos','shorts','live','playlists','community','about') | |
| ORDER BY layer, jurisdiction_id | |
| LIMIT 25; | |
| \echo | |
| \echo === Verified canonical channels (GA counties sample) === | |
| SELECT | |
| y.jurisdiction_id, | |
| y.jurisdiction_type, | |
| j.name, | |
| y.channel_title, | |
| y.youtube_channel_url, | |
| y.official_meeting_confidence, | |
| y.source, | |
| y.is_primary, | |
| y.back_links_to_jurisdiction_website, | |
| y.jurisdiction_website_back_links | |
| FROM intermediate.int_events_channels y | |
| JOIN intermediate.int_jurisdictions j USING (jurisdiction_id) | |
| WHERE j.state_code = 'GA' | |
| AND y.jurisdiction_type = 'county' | |
| ORDER BY y.jurisdiction_id, y.is_primary DESC, y.official_meeting_confidence DESC NULLS LAST | |
| LIMIT 30; | |
| \echo | |
| \echo === Noise still in candidates only (pattern_match rejects) === | |
| SELECT | |
| c.jurisdiction_id, | |
| c.jurisdiction_type, | |
| j.name, | |
| c.channel_title, | |
| c.youtube_channel_url, | |
| c.official_meeting_confidence, | |
| c.rejection_reason | |
| FROM intermediate.int_events_channels_candidates c | |
| JOIN intermediate.int_jurisdictions j USING (jurisdiction_id) | |
| WHERE c.scrape_batch_id = :batch::uuid | |
| AND NOT c.is_verified | |
| ORDER BY c.jurisdiction_id | |
| LIMIT 30; | |
| \echo | |
| \echo === Mayor-flagged contacts (top 50) === | |
| SELECT | |
| state_code, | |
| jurisdiction_id, | |
| person_name, | |
| title_or_role, | |
| email, | |
| phone, | |
| source_page_url | |
| FROM bronze.bronze_contacts_scraped | |
| WHERE scrape_batch_id = :batch::uuid | |
| AND (raw_row->>'is_mayor')::boolean = TRUE | |
| ORDER BY state_code, jurisdiction_id | |
| LIMIT 50; | |
| \echo | |
| \echo === Coverage gap: jurisdictions with website but NO verified YouTube === | |
| WITH targets AS ( | |
| SELECT DISTINCT ON (jurisdiction_id) | |
| jurisdiction_id, | |
| state_code, | |
| COALESCE(NULLIF(btrim(j.name), ''), jurisdiction_id) AS name, | |
| btrim(website_url) AS website_url | |
| FROM intermediate.int_jurisdiction_websites w | |
| LEFT JOIN intermediate.int_jurisdictions j USING (jurisdiction_id) | |
| WHERE w.state_code IN ('AL','GA','IN','MA','WA','WI') | |
| AND w.jurisdiction_category IN ('municipality','county') | |
| AND w.website_url IS NOT NULL AND btrim(w.website_url) <> '' | |
| ORDER BY jurisdiction_id, w.website_record_key | |
| ), | |
| verified AS ( | |
| SELECT DISTINCT jurisdiction_id FROM intermediate.int_events_channels | |
| ) | |
| SELECT t.state_code, t.jurisdiction_id, t.name, t.website_url | |
| FROM targets t | |
| LEFT JOIN verified v USING (jurisdiction_id) | |
| WHERE v.jurisdiction_id IS NULL | |
| ORDER BY t.state_code, t.jurisdiction_id | |
| LIMIT 50; | |
| \echo | |
| \echo === Checkpoint file === | |
| \echo (See data/bronze/jurisdiction_pilot_progress/<batch>.jsonl) | |