| 1 | # Docket - Neutrality Doctrine (enforceable) |
| 2 | |
| 3 | Neutrality is the product. This file turns "be non-partisan" into **engineering constraints, lint rules, and tests** that ship in the codebase. Every PR is checked against it. |
| 4 | |
| 5 | --- |
| 6 | |
| 7 | ## The 5 hard rules |
| 8 | |
| 9 | ### 1. Government-source-only |
| 10 | Every user-facing fact MUST carry a `sourceUrl` pointing to an official government domain. No exceptions, no secondhand sources. |
| 11 | - **Allowed source hosts:** `congress.gov`, `api.congress.gov`, `govinfo.gov`, `usaspending.gov`, `fiscaldata.treasury.gov`, `cbo.gov`, `gpo.gov`, `clerk.house.gov`, `senate.gov`, `*.gov`, and OpenStates' official-record links (which point to state `.gov` legislatures). |
| 12 | - **Enforcement:** `Fact` / `Action` types REQUIRE a non-null `sourceUrl`; a test rejects any record whose host is not in the allowlist. No card renders without a visible "Source" link. |
| 13 | |
| 14 | ### 2. No adjectives |
| 15 | Generated/display text contains **no qualitative modifiers**. Numbers, status, dates, names only. |
| 16 | - **Banned-words lint** (`lint/neutrality.ts`) - fails the build if any appear in generated copy, summaries, or push text: |
| 17 | `slashed, gutted, slammed, blasted, massive, tiny, huge, sweeping, radical, extreme, controversial, popular, unpopular, landmark, historic, devastating, crippling, generous, stingy, bloated, wasteful, common-sense, partisan, bipartisan(as praise), key, crucial, vital, narrowly, barely, overwhelmingly, finally, surprisingly` |
| 18 | (List lives in code; extend over time.) |
| 19 | - "Reduced by $X" / "added $Y" - yes. "Cut" / "slashed" - no. |
| 20 | |
| 21 | ### 3. Surface by official action, never by virality |
| 22 | Feed ranking = **(a) date of official legislative/spending action → (b) dollar magnitude → (c) people affected (per CBO/agency estimate)**. |
| 23 | - **Forbidden inputs to ranking:** news mention counts, social shares, click engagement, "trending," editorial pinning. |
| 24 | - **Enforcement:** the ranking function takes ONLY `{actionDate, dollarAmount, affectedEstimate, actionType}`. A test asserts no engagement/news field is referenced. Topic selection is proportional to official-action volume + dollar magnitude, not editorial judgment. |
| 25 | |
| 26 | ### 4. No comment sections, ever |
| 27 | No free-text user comments on bills, votes, or spending - anywhere. The single largest bias-injection surface. |
| 28 | - Permitted engagement: a single **"Was this summary clear?" yes/no** on summary *clarity* (never on the bill's merit). No reactions, votes, ratings, or emoji on legislation itself. |
| 29 | - No social-share buttons on individual bills (sharing imports outside political discourse). Share-as-image (factual card) only, later. |
| 30 | |
| 31 | ### 5. LLM summaries = extraction templates, not free-form |
| 32 | When prose summaries land (Phase 2+; MVP is structured-fields-only), they are produced by **field extraction into a fixed template**, not open-ended generation. |
| 33 | - Template: (1) official title + number, (2) sponsor name/party/state - factual, uncharacterized, (3) what the text authorizes (extracted clauses, plain language), (4) CBO score if any (dollar figure only), (5) current status. |
| 34 | - Every summary passes the banned-words lint + a **Polarization-Index check** before publish (generate D-leaning and R-leaning variants, assert the default sits statistically between them). High-salience bills (100+ media mentions) get human review before push. |
| 35 | - LLM runs locally for drafting; extraction is preferred over generation wherever a field can be pulled deterministically. |
| 36 | |
| 37 | --- |
| 38 | |
| 39 | ## Visualization neutrality |
| 40 | - Party affiliation and vote splits ARE factual data and may be shown - but with **muted, equal-weight tones** (`--dk-party-d/r/i`, `--dk-yea/nay`). Never saturated red-vs-blue. Equal saturation, equal area, alphabetical or by-count order (not party order). |
| 41 | - Default sort of any member/vote list: **by vote, then alphabetical** - not grouped by party (grouping primes partisan reading). |
| 42 | |
| 43 | ## Trust surfaces (must ship) |
| 44 | - **/how-we-pick** - plain explanation of the ranking algorithm (rule #3), public. |
| 45 | - **/who-pays** - funding/ownership transparency. |
| 46 | - **Source link on every fact** (rule #1). |
| 47 | - No political-campaign or advocacy ads, ever. |
| 48 | |
| 49 | ## Standing risks (monitor, not one-time) |
| 50 | 1. **LLM bias drift** - re-run the Polarization-Index suite on every model change; it's CI, not a launch checklist item. |
| 51 | 2. **Topic-selection soft bias** - audit feed composition periodically against official-action volume; if it skews, the ranking inputs are wrong, not the world. |
| 52 | 3. **Partisan co-option** - bipartisan advisory board + dual-side launch outreach; track which communities adopt. |
| 53 | |
| 54 | ## CI gate (definition of done for any user-facing text feature) |
| 55 | - [ ] banned-words lint passes |
| 56 | - [ ] every fact has an allowlisted `sourceUrl` |
| 57 | - [ ] ranking references only the 4 permitted fields |
| 58 | - [ ] no comment/reaction-on-bill component present |
| 59 | - [ ] (Phase 2+) Polarization-Index check passes on sample summaries |