# Frozen Analysis Specification v1
**Issued 2026-08-22. Binds `PREDICTIONS_v2_2026-08-22.md`. Hashed and published; corrections go to v2 with a changelog, never edited in place.**

---

## Why this document exists

A reviewer's verdict on the register was that it *"pre-registers the answers without pre-registering the questions."* Thresholds were frozen; the quantities they applied to were still choosable in October. That converts pre-registration from a constraint into a credential.

This document closes that. Every prediction gets a population, a unit, exact variable definitions, an estimator, a test, covariates, exclusions, a missing-data rule, and **a total scoring map — every possible outcome assigned to hit, miss, or unscoreable, with no residual region.**

Everything below describes **what the code actually does**, verified against `scripts/build.py` and `scripts/style_analysis.py`, not what it was intended to do.

---

## §0 Definitions binding all predictions

**Universe.** 59 US House districts, fixed in `scripts/build.py` as a literal table with 2024 House margin, 2024 presidential margin, and tier. Selection rule: 2024 House margin ≤ 10 points **OR** 2024 presidential margin ≤ 10 points, drawn from the Cook Political Report competitive list (ratings as of 2026-08-13, retrieved via 270toWin 2026-08-20). **Tier A** = presidential margin ≤ 5; **Tier B** = 5.1–10. Redistricted states (CA, OH, TX, UT, NC, FL, LA, MO, TN) use post-redistricting presidential estimates; their pre-2026 House margins are marked NA and are not comparable. **This list is frozen and published in full. It is the single most politically loaded choice in the project and it is not revisable.**

**Roster.** 115 candidates, in `scripts/nominees.py`. Party composition **57 D / 57 R / 1 IND** — the baseline C2 is scored against.

**Tenure.** Cumulative elected House + Senate service in years through 2026-11-03, in `AGE_TENURE`. Challengers and open-seat non-members are **0.0**.

**Incumbent.** Tenure > 0. Under the frozen roster, n ≈ 59 incumbents, ≈ 56 challengers/open-seat.

**Corporate/trade PAC receipts.** From FEC bulk `itpas2.txt`, summing `transaction_amt` where transaction type ∈ **{24K, 24Z, 24R, 24C, 24F}** and the filing committee's bucket is Corporate PAC or Trade assoc PAC. Memo entries (`memo_cd == "X"`) are **excluded** to prevent double-counting. Independent expenditures (24E for; 24A/24N against) are tracked separately and are **not** in this sum.

**Committee bucket**, from `cm.txt`, applied in this order — order matters and is frozen:
1. `dsgn == "D"` → Leadership PAC *(takes priority; never counted as corporate)*
2. `cmte_tp ∈ {Y, X, Z}` → Party committee
3. `org_tp ∈ {C, W}` → **Corporate PAC**
4. `org_tp == "T"` → **Trade assoc PAC**
5. `org_tp == "L"` → Labor · `"M"` → Membership · `"V"` → Cooperative
6. otherwise → Other/unclassified

**Corporate/trade PAC share of receipts** = `100 × (Corporate PAC + Trade assoc PAC) / total_receipts`, where `total_receipts` is FEC `weball26.txt` column 5 (total receipts, cycle-to-date). Not itemised-only. Not contributions-only.

**Viability filter.** A candidate committee is excluded if receipts < $25,000 **and** disbursements < $25,000. Applied identically in October.

**Reading grade.** Flesch-Kincaid, as implemented in `scripts/style_analysis.py`. The frozen feature set and corpus minimums are in `STYLE_PROTOCOL.md` (v0.1 frozen, changelogs v0.2–v0.6).

**Register cells.** `release` (release body) · `quote` (written attributed quotation) · `spoken` (interview/gaggle, excluded from written comparisons) · `post` (social).

**Scoring date: 2026-10-31.** Data vintage: the FEC Q3 bulk files as published at the October refresh, downloaded once, on a date recorded in the Source Log.

**Rounding.** All test statistics rounded to 2 decimals **before** comparison to a threshold. A value landing exactly on a boundary counts as **satisfying** the claim.

---

## §1 The money predictions

### A1a — PRIMARY
- **Population:** incumbents only (tenure > 0) in the 59 frozen districts, passing the viability filter.
- **Unit:** candidate.
- **Y:** corporate/trade PAC share of receipts, per §0. **X:** tenure in years.
- **Estimator:** Pearson r. **Also reported, not scored:** Spearman ρ (the outcome is bounded, skewed and zero-inflated), and a bootstrap 95% CI.
- **Covariates:** none — this is a bivariate claim.
- **Exclusions:** viability filter only. No outlier removal, ever, under any justification.
- **Missing data:** a candidate with no FEC committee is excluded and **counted in a published excluded-list**; if exclusions exceed 10% of incumbents the prediction is scored **MISS**, not unscoreable.
- **Scoring map:** `r ≥ 0.60` → **HIT**. `r < 0.60` → **MISS**. No other outcome exists.

### A1b — SECONDARY
- **Population:** all 115, viability filter applied. Labelled in publication as containing the challenger/incumbent contrast.
- **Estimator:** Pearson r pooled; plus Pearson r computed **within each party separately** for the sign test.
- **Scoring map:** HIT iff `0.70 ≤ r_pooled ≤ 0.90` **AND** `r_DEM > 0` **AND** `r_REP > 0`. Any other outcome → **MISS**. *(All three conjuncts scored — v1's falsifier tested only two.)*

### A2
- **Population:** incumbents in **all 435 districts**, same viability filter, same variable definitions.
- **Estimator:** Fisher z of the all-435 incumbents-only Pearson r, minus Fisher z of the A1a battleground incumbents-only r **computed on the same October vintage**. *(Referent fixed: A1a's October value, not the June figure and not the pooled figure.)*
- **Scoring map:** `|Δz| ≤ 0.20` → **HIT**. `|Δz| > 0.20` → **MISS**.
- **Declared:** the two samples are nested, so this is not a two-independent-sample comparison and no p-value is claimed.

### A3
- **Population:** incumbents only.
- **Covariate:** binary — committee chair **or** ranking member of any standing committee as of the October roster, from official committee membership pages (Tier 1). Subcommittee chairs do **not** count. The coded list is published.
- **Estimator:** partial Pearson correlation of tenure with corporate/trade share, controlling for that binary.
- **Scoring map:** `partial r ≥ 0.50` → **HIT**, else **MISS**.
- **Declared limitation, in advance:** one binary control is not an identification strategy. Majority-party status, committee assignment, seat safety, district industry mix and total receipts are **uncontrolled**. This tests only whether gavels alone account for the association. No causal claim is made or will be made from it.

### A4
- **Population:** incumbents in the **2024** competitive-district set, built by re-running `build.py` against `weball24 / cm24 / pas224 / cn24 / ccl24`. The 2024 district list is fixed from Cook's final 2024 House ratings and **published before the rebuild is run**.
- **Scoring map:** `0.50 ≤ r ≤ 0.85` → **HIT**, else **MISS**.
- **Declared:** largely the same members appear in both cycles, so this is not an independent replication and will not be described as one.

---

## §2 The writing predictions

### Scoreability floor — binds B1, B2, B3, B4
The B-block is scoreable only if **≥ 90 of 115 candidates yield ≥ 5 collectable social posts each** under the frozen protocol. **Failing the floor scores every B prediction as MISS, not unscoreable.** Attrition is exactly what C1 and C2 predict; letting it delete predictions would let the denominator be selected on a variable correlated with the outcome.

### B1
- **Population:** candidates whose written-official and social cells both meet the frozen minimums.
- **Groups:** "professional media background" = pre-candidacy paid employment in broadcast, journalism or on-air media, coded from the frozen occupation rubric (§H of `EVIDENTIARY_STANDARD_v1.md`). **The group assignment is published before October.**
- **Estimator:** difference in mean social-register FK grade. **Tests:** two-sided Welch t-test; **and** TOST equivalence, margin **1.0 reading grades**, α = 0.05.
- **Scoring map:** HIT iff two-sided `p > 0.05` **AND** equivalence established at margin 1.0. **MISS** if two-sided `p ≤ 0.05` in either direction, **or** equivalence not established.

### B2
- **Population:** the **first 100** written attributed quotations collected in the sweep, ordered by district code then candidate surname — **the ordering is fixed here so the sample cannot be chosen later.**
- **Measure:** third-person self-reference, per the frozen `selfnames` matching in `style_analysis.py`.
- **Scoring map:** **any single instance in any quotation, of any length** → **MISS**. Zero instances across all 100 → **HIT**. *(v1 scored a rate, which one violation only tripped if the quote ran under 334 words.)*
- **Declared:** a black-box Beta(1,1) posterior on 23-for-23 gives only **19%** for 100 more. The stated 70% departs from that on the mechanistic ground that press releases quote their principal in the first person by construction. **A miss falsifies the mechanism, not merely the number.**

### B3
- **Population:** candidates with a computable written-quote → social gap and an established age.
- **Estimator:** Mann-Whitney U on the under-55 vs 55-and-over split; **plus** leave-one-out removing the oldest subject; **plus** TOST, margin **1.5 reading grades**.
- **Scoring map:** **MISS** iff `p ≤ 0.05` two-sided **AND** the split survives removal of the oldest subject. Every other outcome → **HIT**.

### B4
- **Estimator:** median written-quote → social FK gap for national office-holders (benchmark file) vs candidates.
- **Scoring map:** HIT iff office-holder median ≥ 3.5 **AND** candidate median ≤ 2.5. Else **MISS**.
- **Declared:** n = 4 office-holders at registration. Underpowered and labelled as such.

---

## §3 Collection

### C1
- **Estimator:** count of the 115 with no social cell meeting the frozen minimum, divided by 115.
- **Scoring map:** `≥ 15%` → **HIT**, `< 15%` → **MISS**.
- **Published with the result:** the per-candidate reason for each failure (platform block, insufficient volume, no account located).

### C2
- **Baseline, fixed today:** roster is **57 D / 57 R / 1 IND**. The independent is excluded from this test.
- **Estimator:** odds ratio of meeting the social minimum, Democrat vs Republican, on the 2×2 table. Fisher exact two-sided p reported but **not** part of the scoring rule.
- **Scoring map:** `OR ≥ 1.30` → **HIT**. `OR < 1.30`, or OR < 1 → **MISS**.

---

## §4 Roster, ages, scoring

### D1
- **Materially changed** = any of: withdrawal, replacement nominee, party switch, campaign suspension, death, or disqualification, affecting a named candidate on the frozen roster, evidenced at Tier 1 or Tier 2 and dated between 2026-08-22 and 2026-11-03.
- **Scoring map:** `≥ 2 districts` → **HIT**, `≤ 1` → **MISS**.

### E1
- **Establishable** = an age meeting rule **G4** of `EVIDENTIARY_STANDARD_v1.1.md` (stated, identified, editorial, not partisan-origin).
- **Scoring map:** 2, 3 or 4 of the seven → **HIT**. 0, 1, 5, 6 or 7 → **MISS**.

### E2 — the only prediction with an unscoreable branch
- **Scoring map:** resolves to the older value → **HIT**. Resolves to the younger → **MISS**. **Does not resolve by 2026-10-31 → UNSCOREABLE**, and excluded from the Brier calculation.
- **Declared:** 57% assumes uniform birth dates. US births are seasonal by roughly ±5–8%, moving the true figure into **53–61%**.

### E3
- **Scoring map:** 0 or 1 of the four resolve → **HIT**. 2, 3 or 4 → **MISS**.

### F1
- **Scoring map:** the October publication contains ≥ 1 item explicitly labelled **RETRACTED** or **DOWNGRADED** referencing a claim published before 2026-09-01 → **HIT**. No such labelled item → **MISS**.
- **Declared conflict:** this outcome is partly under the author's control. It is scored on the published artifact rather than on judgment, which is the most externally checkable form available, but it is not a clean forecast.

### F2 — COMMITMENT, NOT SCORED
Publish, for the scored set: **Brier score**; **log-odds calibration shift â** with its 95% CI; and the **Murphy decomposition** (reliability / resolution / uncertainty). No threshold attached — attaching one is what created v1's paradox.

### F2′
- **Estimator:** â from the one-parameter recalibration model `logit(p_true) = logit(p_stated) + a`, fitted by maximum likelihood over the scored set, E2 excluded if unscoreable.
- **Scoring map:** `â < 0` → **HIT**. `â ≥ 0` → **MISS**.

### G1
- **Population:** incumbents and challengers across the extension set, same veteran coding as §F of the evidentiary standard (documented service; "Unclear" excluded and counted).
- **Estimator:** Fisher exact, two-sided, on the 2×2 of veteran status by party.
- **Scoring map:** `p > 0.05` → **HIT**, `p ≤ 0.05` → **MISS**.
- **Basis at registration:** 17/57 R vs 10/57 D, **p = 0.186, OR = 2.00**.

### G2
- **Any recorded legal matter** = the legal column is not "None found" (Conviction, Charge filed, Settlement, or Civil judgment).
- **Estimator:** Fisher exact, two-sided, by party.
- **Scoring map:** `p > 0.05` → **HIT**, `p ≤ 0.05` → **MISS**.
- **Basis at registration:** 5/57 R vs 7/57 D, **p = 0.762, OR = 0.69**.

---

## §5 Adjudication

1. **Every prediction above has a total scoring map.** No outcome requires judgment. If one is found that does, that is a **defect in this document** and is logged as such in the Source Log — it is not resolved by the author's discretion.
2. **Scoring runs on 2026-10-31**, on data downloaded once, on a date recorded in the log.
3. **Every input is published with the result** — the excluded-candidate lists, the media-background group assignment, the committee-chair coding, the per-candidate collection-failure reasons — so a third party can recompute every number.
4. **Disputes:** any reader may submit a challenge with the recomputation attached. Sustained challenges are published as errata beside the original, never as edits.
5. **No prediction is withdrawn after 2026-08-22.** The only permitted post-registration status is HIT, MISS, or the single specified UNSCOREABLE branch in E2.

---

*Analysis Specification v1, issued 2026-08-22, binding `PREDICTIONS_v2_2026-08-22.md`. Verified against `scripts/build.py` and `scripts/style_analysis.py` as they stand at this date.*
