# WhoVotedWhy
> Three records on US federal AI policy for the 119th Congress, per member and per candidate: how members vote when AI reaches a roll call, what they say in their own press releases, and who is spending to elect or defeat them. Every row links to the roll call, filing, or release it came from. No editorial position on AI regulation.
Built for people and for agents doing research. The HTML pages and the JSON below are generated from the same committed tables at the same commit, so a number on a page can be checked against its row, and the row against its filing.
## Start here
- [Data manifest](https://whovotedwhy.com/data/index.json): every table with row count, sha256, when it was last read from its source and whether that run completed, a JSON Schema URL, per-field provenance, the selection thresholds, and the coverage report. `schema_version` changes only when a field is renamed or removed.
- [Changes](https://whovotedwhy.com/data/changes.json): what each run added, removed, and changed per table, with dollar deltas, newest first.
- [Methodology](https://whovotedwhy.com/about): how bills and votes are selected, what the classifiers do and how well, what is not computed, how to report an error.
- [Sitemap](https://whovotedwhy.com/sitemap.xml): every page URL.
## Tables (JSON arrays, one object per row; schema at /data/schema/
.json)
- [politicians.json](https://whovotedwhy.com/data/politicians.json): everyone who has served in the 119th Congress. `id` is the Bioguide ID. `is_active` is false for members who have left; they keep their votes. `term_start`/`term_end` bound their service. `fec_candidate_ids` (OpenFEC) and `lis_id` (senate.gov XML) are the join keys to money and Senate votes. Source: unitedstates/congress-legislators, current and historical files.
- [bills.json](https://whovotedwhy.com/data/bills.json): bills classified as AI-relevant. `ai_relevance_score` (0 to 1, model judgement, not a probability), `ai_reasoning`, `topics`, `plain_summary` (model output) and `classifier` (which model, prompt hash, input hash, when). `status` and the dated milestones `reported_at`, `passed_house_at`, `passed_senate_at`, `became_law_at` come from the full action history. `recorded_votes` lists the floor roll calls Congress.gov associates with the bill; each must exist in roll_calls. `watchlisted: true` marks hand-curated inclusions. Rows with a score from 0.3 are stored; the site shows those from 0.5 (`thresholds` in the manifest).
- [roll_calls.json](https://whovotedwhy.com/data/roll_calls.json): one row per vote event. `kind` is `floor` (member positions available) or `committee` (tally only). `category` follows the unitedstates/congress taxonomy (passage, passage-suspension, amendment, cloture, motion-to-proceed, recommit, procedural, …). `ai_match` says why the vote is here: `bill` (on a tracked bill), `keyword` (the vote's own text mentions AI, which is how amendment votes on untracked bills are caught), `amendment` (an AI amendment to a tracked bill, or any amendment to a bill that is itself about AI). `positions_recorded` and `positions_unmatched` say how complete the roster is. `source_url` is the chamber's XML or the Congress.gov actions page.
- [votes.json](https://whovotedwhy.com/data/votes.json): one row per member per floor roll call. `position` is `yea`, `nay`, `present`, or `not_voting`. `bill_id` is null when the vote was on an amendment to an untracked bill.
- [statements.json](https://whovotedwhy.com/data/statements.json): official press releases that take a position on AI policy. `ai_stance` is toward government oversight of AI: `support` means favouring more rules or oversight, `oppose` fewer, `neutral`, `mixed`. `ai_relevance_score`, `ai_summary`, `ai_topics` and `classifier` are model output with provenance. `bill_refs` lists tracked bills the release cites, with `method` `number` (H.R. 5764) or `title` (exact bill title); `bill_ids` is the flat list. `content` is the first 2,000 characters; `url` is the member's own site. Source: Congress Press (thescoop.org/congress-press).
- [outside_spending.json](https://whovotedwhy.com/data/outside_spending.json): itemized FEC Schedule E independent expenditures by the super PACs in super_pacs.json, 2026 cycle. `support_oppose` is `S` or `O`. `is_notice` marks 24/48-hour notices, which periodic reports later restate, so do not sum these rows for a total. `filing_url` is the FEC PDF. `politician_id` is set when the candidate is a member of the 119th Congress. `amended_from` carries what an earlier version of the same transaction reported when the filer amended it; an amount of 0 with `amended_from` set is spending that was reported and then withdrawn, which FEC totals no longer count.
- [outside_spending_totals.json](https://whovotedwhy.com/data/outside_spending_totals.json): per-candidate, per-committee totals. `aggregation_method` is `fec_by_candidate` (FEC's own reconciled aggregate; use this) or `itemized_fallback` (summed here because that endpoint failed; approximate). Dollars to the cent.
- [network_funders.json](https://whovotedwhy.com/data/network_funders.json): who gives to each listed super PAC, from the PAC's own Schedule A receipts, aggregated by contributor. Where a PAC is funded by a nonprofit, the nonprofit is the contributor of record and the chain stops there; `funding_disclosure` in super_pacs.json says so per network.
- [committee_totals.json](https://whovotedwhy.com/data/committee_totals.json): each listed super PAC's Form 3X cycle totals through its last periodic report: `receipts`, `disbursements`, `transfers_out`, `cash_on_hand`, `coverage_end`. The bridge between what a PAC raised and what Schedule E ties to candidates; periodic reports lag itemized filings by up to a quarter.
- [electioneering.json](https://whovotedwhy.com/data/electioneering.json): FEC Form 9 electioneering communications by filers listed in super_pacs.json, the only filing a 501(c)(4) in these networks must make (a broadcast ad naming a candidate inside 60 days of a general or 30 of a primary). Empty until such filings exist.
- [donations.json](https://whovotedwhy.com/data/donations.json): itemized FEC Schedule A receipts to members' campaigns where the employer or contributing PAC resolves through employer_aliases.json. `donor_employer` is the free-text field verbatim; `employer_canonical` and `donor_category` (`employee`, `company_pac`, `investor`) are the resolution; `match_rule` names the query that found the row. Negative amounts are refunds. The FEC itemizes a contributor once their gifts to a committee pass $200 in aggregate.
- [scores.json](https://whovotedwhy.com/data/scores.json): per-member counts and sums. `said_did_pairs` lists bills the member both voted on and spoke about, with position, vote category, stance, and link method; no verdict is drawn and `consistency_score` is always null. `influence_score` and `conflict_index` are always null; they are not computed.
- [super_pacs.json](https://whovotedwhy.com/data/super_pacs.json): the reviewed registry of networks and committees, each with an evidence URL, review date, and what its funding disclosure can and cannot show.
- [excluded_committees.json](https://whovotedwhy.com/data/excluded_committees.json): super PACs seen spending in the same races and reviewed as not AI-industry money, each with what it is (`what`), an evidence URL, and a review date. Committees flagged by discovery but not yet reviewed are in the manifest's coverage report, not here.
- [candidate_positions.json](https://whovotedwhy.com/data/candidate_positions.json): for every non-member candidate with $1M or more of listed-network spending, their own words on AI: `quotes` verbatim from `source_url` (empty when the source says nothing about AI), `source_title`, `source_date`, `note`. No stance is assigned.
- [employer_aliases.json](https://whovotedwhy.com/data/employer_aliases.json): the alias rules: canonical name, category, the OpenFEC queries, the regexes a string must satisfy, and the exclusions.
- [watchlist.json](https://whovotedwhy.com/data/watchlist.json): the hand-curated bill list with a one-line reason each.
- [overrides.json](https://whovotedwhy.com/data/overrides.json): reviewed corrections applied on every build, with reason and evidence.
## Search index
[search.json](https://whovotedwhy.com/data/search.json): one flat row per member, tracked bill, roll call, statement, and non-member candidate with `type`, `url`, `title`, `subtitle`, and a lowercase `text` haystack. An agent can grep it instead of fetching every table.
## Per-entity documents (joined, one fetch)
- `https://whovotedwhy.com/data/politicians/{bioguide_id}.json`: the member with their votes (each carrying its roll call), statements, donations, outside-spending totals, and said/did pairs.
- `https://whovotedwhy.com/data/bills/{id}.json`: the bill with its sponsor, roll calls, citing statements, and Congress.gov URL.
- `https://whovotedwhy.com/data/votes/{id}.json`: the roll call with every member's position, name, party, and state.
- `https://whovotedwhy.com/data/candidates/{fec_candidate_id}.json`: a candidate, member or not, with per-committee totals, every itemized filing line, electioneering ads naming them, and `position` (their own words on AI, or null). The largest targets of AI money are challengers, so do not filter on `politician_id` when the question is about races.
Every document carries a `provenance` block with the commit and schema version. Each HTML page links to its JSON document.
## How to cite
Cite the primary record for the event (`source_url`, `filing_url`, or `url`) and this dataset's commit for what it added: the selection, the labels, and any total. Say which table a figure came from and the table's `seeded_at` from the manifest. Classifier fields (`ai_relevance_score`, `ai_reasoning`, `topics`, `plain_summary`, `ai_stance`, `ai_summary`, `ai_topics`) are model output; whether they have been measured against human labels is stated on the About page and in `/data/classifier_metrics.json` when it exists.
## Coverage and limits
- 119th Congress only (January 2025 onward). Every House roll call and Senate vote the chambers have taken is joined against the tracked bills on every run; the coverage block in the manifest gives the counts and any fetch failures.
- Votes on a bill that contains AI provisions (an NDAA) are on the list because the bill is tracked; the vote page says so. Amendment votes on such bills are included only when the amendment itself concerns AI.
- Bills are found by vocabulary match on titles and CRS summaries; a bill whose title and summary avoid AI terms is only present if watchlisted.
- Statements cover press releases, not floor speeches or hearings, from a three-month intake window per run; a release is classified once and never re-scored.
- Super PAC totals are spending by the listed committees only. The networks' nonprofits file no Schedule E; their spending is visible only as Form 9 electioneering inside the pre-election windows, and not at all for digital ads.
- Contributions match on the FEC's free-text employer field through the alias rules and undercount subsidiaries and spellings not yet in the list.
- No STOCK Act trades and no lobbying disclosures.
## Sources
Congress.gov API (bills, summaries, actions); House Clerk roll-call index and XML (clerk.house.gov/evs); senate.gov roll-call XML; OpenFEC (Schedule A, Schedule E, Form 9); Congress Press (member press releases); unitedstates/congress-legislators (member IDs, current and historical).