๐Ÿ“ Methodology

How VoteClarity Scores Alignment

A plain-language walkthrough of how an alignment score is computed, why some votes show up in your /alerts inbox and others don't, and what the score-delta threshold means for the alerts you receive.

1. What the alignment score is

An alignment score is a single percentage that tells you how often a representative votes the same way as the progressive majority on the policy issues you care about โ€” across all the roll-call votes on those issues that we have on record.

For each issue you select on /app, VoteClarity counts every roll call that has been tagged to that issue, then asks two questions of each one: which way did the Democratic majority vote? (the "progressive direction" for that vote) and did the rep vote that same way? A simple average across the issues you picked โ€” with non-voting and tie votes excluded โ€” becomes the % you see on a /rep profile.

The per-issue formula, in plain language:

Issue % = count(aligned_yields_to_majority_dir) รท count(partisan_yields_on_tagged_issue) ร— 100

Tie votes (a 50/50 split in the Democratic caucus) are excluded from both the numerator and denominator โ€” the same skip rule the /alerts flag detection uses. A rep whose party abstain in unison isn't "half-aligned" โ€” that vote simply doesn't carry a directional signal, so it doesn't move the score.

The overall score you see at the top of a /rep profile is the average across the 10 issues you picked (or fewer, if some issues had zero tagged votes on the floor for that rep). When nothing has been tagged yet, the page degrades to โ€“ ("no data") rather than inventing a score out of thin air.

2. How a rep vote is mapped

For every roll call in the Senate and House, VoteClarity pulls the Yea/Nay position each member recorded, then determines which way the Democratic majority of that chamber voted on the same roll. Tally that against the rep's vote โ€” did they vote with the Democratic majority's direction, or against it?

That mapping boils down to three steps per vote:

That same SQL is what powers the per-issue score circles on every /rep profile and the row-level rep cards on /districts; the methodology here is identical.

3. Issue weights and your weighted lean

When you take the quiz on /app or subscribe to the digest, you mark each issue on a 1โ€“5 scale and pick a direction: progressive or conservative. Those answers are stored as { slug, weight, lean } rows inside subscribers.issue_prefs (a JSONB column). The weight is a 0โ€“1 number โ€” the higher you rated it, the more a single rep miss will move your alert signal for that issue.

For each roll call, the alignment check for you (not the aggregate score) considers only the issues you actually picked. A representative's contribution to a weighted delta on one tagged issue is computed as:

Per-issue delta = โˆ’weight when the rep's vote opposes your lean, or 0 when it agrees.

If you marked healthcare at weight 0.8 and your rep votes against the progressive direction on a healthcare bill, the per-issue delta for that vote is โˆ’0.8. If you marked tech & privacy at weight 0.2 and the same rep misses on that one, the delta is only โˆ’0.2 โ€” the issue matters less to you, so the mismatch is smaller.

That's why two voters with different priorities can subscribe to the same rep and receive very different /alerts feeds โ€” same votes, different signal strength.

4. The score-delta threshold

VoteClarity only fires an /alerts flag when the weighted mismatch passes a minimum bar โ€” we don't want every tiny mismatch on a low-priority issue to fill your inbox. The relevant constant lives in the detector that decides whether a flag is created:

ALERT_DELTA_THRESHOLD = 0.40

In plain language: we only flag a vote if the weighted mismatch is at least 0.40 in absolute value. The detection rule, represented as a formula:

shouldAlert = |delta| ≥ 0.40, where delta is โˆ’|weight| on a mismatch and 0 on agreement.

What this means in practice:

The 0.40 cutoff is conservative on purpose. A first-time voter will typically rate 5โ€“10 issues; we want alerts to highlight the misses that genuinely matter, not the full set of partisan floor votes. You can always lower your ratings to make a given issue less trigger-happy, or raise them to make it more reactive.

The threshold lives in alerts/detector.js as the exported constant ALERT_DELTA_THRESHOLD = 0.4, and is passed explicitly to computeScoreDelta({...}) at each flag-evaluation call in alerts/service.js. There is no hidden second filter on top of it.

5. What fires a /alerts flag

All five of these conditions must hold for a single roll call to land in your inbox:

If you see a flag in your inbox, every one of those boxes has been ticked.

6. Where the data comes from

Everything VoteClarity scores comes from two primary sources:

The /rep profile SQL and the /alerts detector query the same member_vote_positions, roll_call_votes, and vote_issue_tags tables, so a number on your profile is computed from exactly the same source data as a flag in your inbox. There is no per-page re-summarization โ€” one pipeline, one explanation.

One thing to keep in mind: because tagging is keyword-first with LLM fallback, a small share of votes may still be untagged. Those votes never enter into the alignment % or the alert signal. As the LLM pass catches up, they're backfilled into the same tables without changing the math โ€” they simply start contributing once a tag arrives.

Browse voting records by issue

Each issue page shows the top 5 most-aligned and most-opposed active members of Congress for that category, with per-vote counts and links to their full voting profiles.