Missouri Election

Polls close in 2 hours, 29 minutes, 7 pm Central, Nov 3

Decisions and corrections

Every judgment call behind the forecast, in the order it was made, each with a link of its own. Below the index: the log of corrections, then the decisions in full. Read from docs/DECISIONS.md when the site is built.

How the pieces fit together is on Methodology; how the model has been tested is on Evaluation.

Index by area

Every judgment call in the forecast, with the evidence behind it. Numbered so the methodology page and the site can cite them.

Seat model (30)

  • D-01 District lean = 2024 composite, not presidential alone (2026-11-01)
  • D-03 National shift for 2026: +3.3 points of share, t(5) scale 1.5 (2026-11-01)
  • D-04 Prior-residual carry 0.60 (0.75 for the same candidate pair) (2026-11-01)
  • D-05 Incumbency and slope pooled across 2022 and 2024 (2026-11-01)
  • D-06 Error structure (2026-11-01)
  • D-07 Uncontested seats fixed (2026-11-01)
  • D-08 Third-party candidates ignored in contested races (2026-11-01)
  • D-09 Not used: campaign finance, primary turnout, hand ratings (2026-11-01)
  • D-10 Vacant seats (2026-11-01)
  • D-11 Even-numbered Senate districts use geometric 2024 estimates (2026-11-01)
  • D-12 Lean composite reweighted toward the governor race (2026-11-01, v2)
  • D-13 Seat error grows with competitiveness (2026-11-01, v2)
  • D-14 No prediction market exists for the Missouri legislature (2026-11-01)
  • D-15 District-type shared error (2026-11-01, v2)
  • D-16 The 2026 shift is applied uniformly across district types (2026-11-01, v2)
  • D-17 Asymmetric incumbency in a wave year (2026-11-01, v2)
  • D-04 revised: residual carry depends on whether the incumbent returns (2026-11-01, v2)
  • D-18 Primary turnout ratio, small weight (2026-11-01, v2)
  • D-19 Education term (2026-11-01, v2)
  • D-20 Candidate quality (2026-11-01, v2 revision after lock)
  • D-21 One simulated election for both chambers (2026-11-01)
  • D-22 Seat distributions and 80% ranges come from the simulation (2026-11-01)
  • D-23 "Why this forecast": every forecast's centre exported as exact parts; labelling only (2026-11-01)
  • D-24 State Auditor: the 1-point incumbent adjustment and the 1.5-point candidate spread (2026-11-01)
  • D-25 District polls condition the seat model, jointly with MO-2 (2026-11-02)
  • D-26 Auditor polls inform the candidate effect; the SLU House generic ballot is a check, not an input (2026-11-02)
  • D-27 Late defensive committee money widens seat error outside the competitive set (2026-11-02)
  • D-28 Comparators are scored at their last version before polls close (2026-11-02)
  • D-29 Data checks of hand-set parameters; no value changes (2026-11-03)
  • D-31 Wave-year shared errors: regional and district-type sds 0.013 (2026-11-03; Daniel's ruling)

Congress (13)

  • D-C1 Congressional baseline: presidential lean plus the full national swing (2026-11-01)
  • D-C2 Incumbency 2.0 share for Wagner (2026-11-01)
  • D-C3 House effects, recency and poll error (2026-11-01)
  • D-C4 Markets at half the weight of one poll, shown beside (2026-11-01)
  • D-C5 MO-2's poll surprise conditions the legislative shared error (2026-11-01, revised)
  • D-C6 Nowcast contest USH2 and its link to the House seats inside MO-2 (2026-11-01)
  • D-C7 Only fresh, API-fetched market prices count (2026-11-01)
  • D-C8 D-C5's observation error grows as the MO-2 polls age (2026-11-01)
  • D-C6 (revised 2026-11-01) USH2 units, prior continuity and a support-only seat link
  • D-C9 MO-2 market prices without the overround; how the 44% is built (2026-11-01)
  • D-CAL1 Backtest writes per-seat probabilities and calibration bins to calibration.json (2026-11-01)
  • D-CAL2 Backtest calibration: no change to the 2026 seat model before certification (2026-11-01)
  • D-CAL2 superseded: the forecast changes before the election whenever the evidence says a value is wrong (2026-11-02, Daniel)

Measures (10)

  • D-M1 Ballot measures: poll error and undecided rule (2026-11-01)
  • D-M2 Fundamentals priors (2026-11-01)
  • D-M3 Markets as a check, not an input (2026-11-01)
  • D-M4 Undecideds split by who referred the measure (2026-11-01) [SUPERSEDED by D-M7]
  • D-M5 Amendment 3 prior from the 2024 vote (2026-11-01)
  • D-M6 Wider priors for unpolled referrals (2026-11-01)
  • D-M7 One shared undecided coefficient (2026-11-01; ruling 14; supersedes D-M4)
  • D-M8 Undecided split by referral type: citizen-petitioned measures 0.22 (2026-11-03; Daniel's ruling, supersedes part of D-M7's ruling 14)
  • D-M9 Amendment 3's undecided split 0.22: the abortion-measure record (2026-11-03; Daniel's ruling)
  • D-M10 Amendment 3's prior no longer counts the polls twice (2026-11-03; supersedes the poll half-step in D-M5)

Live and election night (10)

  • D-N1 Election-night nowcast calibration (2026-11-01)
  • D-N2 Election-night capture is automated; a contest is held until 5% is counted (2026-11-01)
  • D-N3 Live counts: counted votes are a floor, nothing is locked, complete only by hand (2026-11-01)
  • D-N4 Election night: one election for both chambers; seats gated at 5% (2026-11-01)
  • D-N5 Live nowcast: the reverse fraction guard and shared turnout uncertainty (2026-11-02)
  • D-V1 One vintage: the hourly run rebuilds the pre-returns nowcast; the build checks it (2026-11-01)
  • D-N6 Absentee batches, a replay-scored call tier, and the 2024 seat-call replay (2026-11-02)
  • D-N7 Model projections at 97.5%; complete district probability output (2026-11-03)
  • D-N8 Pre-election forecast frozen at poll close (2026-11-03)
  • D-N9 "We project" calls: one automatic tier, a persisted ledger with withdrawal (2026-11-03)

Data (3)

  • D-02 Daily Kos 2020-by-district file discarded (2026-11-01)
  • D-02 addendum: 2020 on current lines (2026-11-01)
  • D-H1 Hourly, publish-on-change forecast; status-only commits skip the deploy (2026-11-01)

Corrections

Published corrections to the site's figures, candidates, incumbents and results, newest first. Each entry gives the date, what was wrong, what it now says and which hourly version of the forecast first carried the fix.

2026-11-02 — Finance reporting periods and source attribution

The finance display previously used an October 22 cutoff and an October 27 source summary alongside later committee records. Per-record reporting periods, reported sources and collection dates from the raw finance tables are now retained and displayed. For example, House District 105's late HRCC record is through October 29 and cites MOScout October 30; it is not attributed to the October 27 report. Individual filing URLs were not supplied, and collection dates are not presented as independent verification dates.

The House District 94 record annotated as “>$100k” is displayed as “More than $100,000 (reported lower bound)”; its stored numeric amount is unchanged. All 43 candidate records and 78 committee records retain their financial quantities. This is a static-data/presentation correction, not a new forecast calculation: the published forecast generated at 2026-11-02 18:04:09 UTC is unchanged by this fix. The immutable archive retains the earlier file and the corrected metadata version separately.

From docs/CORRECTIONS.md. To report an error, use the Corrections link in the Sources box at the foot of a page.

The decisions

D-01 District lean = 2024 composite, not presidential alone (2026-11-01)

The lean is the mean of the Democratic two-party share in each district for president, governor and US Senate in 2024, computed from Secretary of State precinct results allocated to the 2022 district plans. In the 2022 and 2024 House fits the governor race alone predicted legislative results best (rmse 0.019-0.021), the presidential vote next (0.022-0.028), US Senate close behind; the composite is used because it is more robust to one race's candidate effects. Amendment 3 (2024 abortion vote) was tested and rejected: rmse 0.039-0.042.

D-02 Daily Kos 2020-by-district file discarded (2026-11-01)

The file is on the 2012-era map (e.g. HD 88 at Biden 65% vs the current HD 88 at Harris 42%). Correlation with 2024 leans only 0.965 and it predicts 2022 results far worse (rmse 0.062 vs 0.028). Only current-map data are used.

D-03 National shift for 2026: +3.3 points of share, t(5) scale 1.5 (2026-11-01)

The baseline relationship is the 2024 fit (intercept -0.8 share relative to the composite lean, in a national House environment of R+2.6). Late-October generic ballot averages sit at D+8.4 to D+9.1 (Silver Bulletin D+8.9 Oct 30, DDHQ D+8.7, RCP D+8.4); the implied national swing from 2024 is about +11.3 points of margin, +5.65 of two-party share. Missouri's House vote has historically moved less than the nation: in seats contested in consecutive cycles, the incumbency-adjusted swing was +2.4 share from 2016 to 2018 against a national +4.85 (elasticity 0.49) and -1.9 from 2018 to 2020 against -2.75 (elasticity 0.68). Using 0.58, the expected shift is 0.58 x 5.65 = +3.3 share. Cross-checks: state legislative specials in 2025-26 ran D+10 to D+12.5 in margin against Harris, which after the usual 1.5-4 point discount implies +3.5 to +4.5 share; Virginia and New Jersey 2025 ran about +4 share. The scale of 1.5 share covers generic-ballot error (about 1.5 margin points in recent cycles), elasticity uncertainty, and the limited Missouri record. Sensitivity (House expected Dem seats): shift 0 -> 52.7; +2.0 -> 56.4; +3.75 -> 59.8; +5.5 -> 63.4; +7.0 -> 66.4.

D-04 Prior-residual carry 0.60 (0.75 for the same candidate pair) (2026-11-01)

Seat residuals from the lean+incumbency fit correlate 0.675 between 2022 and 2024 (n=60 seats contested both years); the regression slope of the 2024 residual on the 2022 residual is 0.58 overall and 0.76 when both candidates are the same. Seats uncontested in 2024 use their 2022 residual decayed one further cycle.

D-05 Incumbency and slope pooled across 2022 and 2024 (2026-11-01)

Pooled OLS on contested House seats: slope on lean 0.99, incumbency +1.6 share (about 3 points of margin). This is smaller than textbook state-legislative incumbency advantages (which include scare-off and quality effects that the prior-residual term already captures). Senate uses the House coefficients (too few Senate races to fit on their own: 14 contested in 2024, with rmse 0.014 when the House-style fit is applied).

D-06 Error structure (2026-11-01)

Seat error: Student-t df 7, scale = out-of-sample rmse from the backtest (about 0.019 share), x1.25 for open seats, x1.5 for seats with no contested result under the current map. Regional error: normal, 0.75 share, seven regions assigned by district centroid (St Louis metro, KC metro, Springfield, Columbia, rural north, rural south, rural south-east). Statewide error: the D-03 prior itself (t5, 1.5). Residual kurtosis in the fits is mild (0.54), so df 7 is a modest fat-tail allowance.

D-07 Uncontested seats fixed (2026-11-01)

Seats with no major-party opponent on the Secretary of State certified list are fixed at the unopposed party. Libertarian-only or independent-only opposition is treated as uncontested (HD 73, 77, 83). HD 90 follows the SOS list (no Republican) over Ballotpedia; see the candidate NOTES.md. Write-ins ignored.

D-08 Third-party candidates ignored in contested races (2026-11-01)

Three-way races (SD 30 with a Libertarian, HD 2, 6, 127, 128 and others) are modelled on the two-party share. The Libertarian in SD 30 is noted on the seat page.

D-09 Not used: campaign finance, primary turnout, hand ratings (2026-11-01)

No machine-readable finance data exists for 2026 (MEC is interactive-only; Transparency USA does not cover Missouri; MEC stays unscrapeable, but Missouri Scout's transcription of the 8-day reports is on file and D-27 uses it, for error width only, never for a mean). Primary-vote ratios (KCUR's signal) could not be validated against a past cycle without 2024 primary data. External ratings (State Navigate, DLCC and HRCC targets, Missouri Times) are shown as comparisons, not fed into the model, so the scorecard can compare them fairly.

D-10 Vacant seats (2026-11-01)

Eight House seats and SD 10 are vacant going in. They are treated as open seats whose "held by" party is the last holder's party for the flip count.

D-11 Even-numbered Senate districts use geometric 2024 estimates (2026-11-01)

The 17 Senate seats on the 2026 ballot had no 2024 Senate contest, so no precinct is tagged with its Senate district in the 2024 results. Their 2024 leans are estimated by block-weighting the New York Times 2024 precinct polygons into House-by-Senate pieces, with the governor, US Senate and Amendment 3 numbers shifted from the parent House district by each piece's presidential deviation. Validated on the 17 odd districts, where the direct answer is known: maximum presidential-margin error 0.69 points. Senate seat error is nonetheless given the no-history multiplier where the seat lacks a contested result under this map.

D-02 addendum: 2020 on current lines (2026-11-01)

The lean agent rebuilt 2020 presidential results on the 2022 districts from VEST precincts (block-population weighted). They correlate 0.9985 with the 2024 leans and predict 2022 results as well as 2024 does. They are kept as a cross-check and shown on district pages; the composite lean stays 2024-only (D-01) to keep the lean on the same electorate as the backtest. HD 136 (Springfield) is the most method-sensitive competitive seat: D+4.8 by our allocation, D+7.1 by the NYT polygons, R+3.2 by OnPoint; its Democratic incumbent's 2024 result is consistent with our figure.

D-12 Lean composite reweighted toward the governor race (2026-11-01, v2)

Out-of-sample (fit one cycle, predict the other, with residual carry) rmse by baseline: presidential alone 0.023/0.027; US Senate alone 0.023/0.024; equal composite 0.020/0.022; governor alone 0.019/0.020; governor 0.5 / presidential 0.25 / Senate 0.25: 0.019/0.021. The 2024 governor race (Kehoe v Quade, the House Minority Leader) behaves most like a legislative race. The 0.5/0.25/0.25 blend is adopted over governor-alone to limit any one candidate's home-region effect (Quade is from Springfield). Backtest with the new lean: 107/110 and 65/69 seats, Brier 0.024 and 0.030 (oracle intercept).

D-13 Seat error grows with competitiveness (2026-11-01, v2)

2024 residual sd by distance from even: within 5 points 0.024 (n=26), 5-10 points 0.022 (12), 10-20 points 0.016 (21), beyond 0.014 (51). Competitive seats draw money and effort that move results. The seat error scale is now 1.30x the backtest rmse at an even lean, 1.20x at 5 points, 0.90x at 10, 0.75x at 20 or more. Regional random effects were tested and found insignificant in 2022 and 2024 (ANOVA p 0.86), so the regional error stays small (0.75 share) and exists to carry wave-year correlation the two calm cycles cannot show.

D-14 No prediction market exists for the Missouri legislature (2026-11-01)

Searched Kalshi and Polymarket: markets exist on Missouri Amendment 3 and the congressional-map referendum, none on legislative seats or supermajorities. Nothing to incorporate or benchmark against.

D-15 District-type shared error (2026-11-01, v2)

Since D-21 the type, regional and statewide errors are drawn once and shared by both chambers. A wave year moves similar districts together in ways two calm cycles cannot reveal. Districts are typed by region and ballot density (per-chamber quantiles): urban core (metro, dense, lean above 60% D), inner suburban, suburban, exurban, rural. Each type gets a shared normal error of 0.75 share per simulation, on top of the regional and statewide errors. The seat-level sd is unchanged.

D-16 The 2026 shift is applied uniformly across district types (2026-11-01, v2)

Tested whether Missouri swings differentially by district type. The 2020 to 2024 presidential swing by current House district had zero correlation with the district's lean (slope -0.0001) and differed little by type (rural -1.1 share, suburban -0.6, inner suburban +0.1, urban core -0.8). The 2022-to-2024 change in legislative residuals was also unrelated to lean, Amendment 3 vote or ticket-splitting (correlations 0.02-0.12, n=60). Pending the Virginia and New Jersey 2025 evidence, the shift is uniform; any type-dependence is carried as the D-15 shared error rather than as a mean adjustment.

D-17 Asymmetric incumbency in a wave year (2026-11-01, v2)

Virginia 2025, contested House of Delegates seats, swing from Harris 2024 regressed on lean and incumbency: open seats +2.0 share, Republican incumbents +1.0, Democratic incumbents +4.9. Relative to open seats, the wave party's incumbents gained 2.9 and the other side's incumbents held only 1.0, against Missouri's symmetric calm-year estimate of 1.6 either way. New Jersey's multi-member districts give no clean estimate. The 2026 incumbency effect blends the two at half weight: Democratic incumbents +2.25 share, Republican incumbents 1.3. Net effect on the House expectation: about +0.3 Democratic seats. Logged as the first judgment call that rests on another state's evidence; it will be re-examined against the Missouri result.

D-04 revised: residual carry depends on whether the incumbent returns (2026-11-01, v2)

The literature (Fowler and Hall 2014; Split Ticket) says an incumbent keeps about half of their overperformance when they run again and that "partisan incumbency" is near zero. Missouri 2022 to 2024 agrees in part: slope of the 2024 residual on the 2022 residual is 0.72 when the same incumbent returned (n=16), 0.36 when the 2022 incumbent had gone (n=20), 0.43 when neither year had an incumbent (n=24). The district-level component that survives a retirement is real here (local party strength, lean measurement), so open seats are not zeroed. New carries: same candidate pair 0.75, incumbent returning 0.65, previous incumbent gone 0.40. Name matching now ignores punctuation and middle initials (two 2024 incumbents had been mis-flagged as gone).

D-18 Primary turnout ratio, small weight (2026-11-01, v2)

The August 2024 primary's Democratic share of major-party primary votes, minus the district lean, correlated 0.21 with the 2024 general residual across 110 contested House seats (0.15 in the 36 competitive ones); regression slope 0.055 share per unit. One cycle of validation only, so it enters at about half that weight (0.03), de-meaned within the year (the August 2026 primary ran unusually Democratic statewide because of Amendments 4 and 5), and clipped at plus or minus 15 points of ratio. Maximum effect on any seat: about 0.45 share.

D-19 Education term (2026-11-01, v2)

Adding the district's bachelor's-degree share (ACS 2023 five-year, 2022 districts) to the fit improves out-of-sample rmse in both directions (0.0194/0.0209 to 0.0191/0.0196). Pooled coefficient -0.043 share per unit of bachelor's share: a district 20 points above the state mean votes about 0.9 share less Democratic for the legislature than its 2024 lean implies. The pattern is the familiar one of educated suburbs splitting tickets toward down-ballot Republicans. Income is collinear and adds nothing further. Race, age and homeownership showed no relationship to residuals.

D-20 Candidate quality (2026-11-01, v2 revision after lock)

Both candidates in 36 competitive races were scored 0-3 for prior office (0 none; 1 school board, small council or a prior serious run for the seat; 2 county office, mayor or former legislator; 3 sitting legislator). Incumbents are excluded from the term because incumbency is modelled separately; the difference in non-incumbent scores enters at 0.8 share per point (Klarner: former legislator +3 share; FiftyPlusOne: about 0.65 share per experience step), capped at 2 points. It changes only eight races, none by more than 1.6 share: HD 10, 30, 34, 38, 104, 110, 135 and SD 34 (sitting Rep. Mike Jones against a school-board member). Sources and notes: data/raw/quality/. The seat forecast was re-locked with this term; the earlier lock (same evening, without it) is in git history, commit 9ea3e8c.

D-M1 Ballot measures: poll error and undecided rule (2026-11-01)

Missouri's own record, 16 measures 2014-2024 with a poll in the final six weeks: polls overstated the yes share by 3.9 points on average with an rmse of 9.3; the median share of undecideds that ended up voting yes was 0.23 (0.40 on legislative referrals, negative on initiatives). Rule adopted: 30% of undecideds to yes on every measure (residual mean error -0.5, rmse 8.1), poll_error_sd 0.08, t5. Poll averages are shrunk about halfway toward a fundamentals prior (prior_weight 40) because two or three polls with 14-33% undecided do not pin a Missouri measure. Sources: data/raw/measures/history_polls.csv.

D-M2 Fundamentals priors (2026-11-01)

Amendment 3 (repeal): prior 0.47 from the 2024 result (48.4% for the restrictive side) moved toward No by the expected more-Democratic electorate and a 3:1 money deficit, back toward Yes by the minors' gender-care provision (67-73% support alone). Amendment 6: 0.56 (initiative-rights measures with union money and no opposition; August 2026 voters rejected the legislature's Amendment 4 by 80-20). Amendment 7: 0.42 (no campaign, a tax idea voters rejected in August as Amendment 5, 83-17). Amendment 8: 0.58 (uncontroversial referral; such measures passed 77-82% in August). Proposition A: 0.43 (no yes campaign, $11M against, status quo is No). Turnout links: a more Democratic electorate moves Amendment 3 and Proposition A toward No (-0.8 per unit of shift), Amendment 6 toward Yes (+0.6). All measures share one common error (sd 0.02) plus the seat model's statewide shift.

D-M3 Markets as a check, not an input (2026-11-01)

Kalshi Amendment 3 last trade 0.42 (bid 0.36) on Nov 1; Polymarket 0.38; Polymarket Proposition A 0.335 on negligible volume. The model gives 0.35 and 0.24. Shown beside the forecast; not blended in.

D-M4 Undecideds split by who referred the measure (2026-11-01) [SUPERSEDED by D-M7]

In 23 final-window Missouri polls since 2014, undecideds broke toward yes on legislative referrals (median 0.52 of undecideds) and polls overstated yes on citizen measures by 6 points. Rule: 0.40 to yes on legislative referrals, 0.15 on initiatives and referendums. Historical rmse 8.3 -> 7.8 points (6.4 -> 6.1 excluding 2020). Replaces the flat 0.30 of D-M1.

D-M5 Amendment 3 prior from the 2024 vote (2026-11-01)

2024 keep-rights share by House district = 0.196 + 0.784 x Harris share (vote-weighted). Applying the seat model's electorate shift (+3.3 share, t5 scale 1.5) gives repeal 45.8% (80% range 44.1-47.5) before any effect of the minors' gender-care provision. The August and October polls sit about 4 points above that; the prior is 0.478, adding half of the poll-implied effect, sd 0.05. Precedent for an upside surprise: 2020 Amendment 3, a legislative referral leading with a popular provision, polled 29-56 and passed with 51%.

D-M6 Wider priors for unpolled referrals (2026-11-01)

Amendments 7 and 8 have no public poll. Missouri legislative constitutional referrals since 2014 have a yes-share sd of 16 points (22 measures). prior_sd raised from 0.08 to 0.12.

D-N1 Election-night nowcast calibration (2026-11-01)

County deviation sd 3.7 share points around the regional swing (initially 1.8; the replay showed the narrower value covered only 33-64% of outcomes in its 80% intervals), early-batch sd 5 points at half counted, regional sd 1.2, urban-rural tilt sd 0.25 of the baseline deviation. Size-dependent county noise was tested and worsened coverage. Result on 210 replayed nights: 80% coverage 73-88%, average miss 1.0 point at 10% counted falling to 0.2 at 90%, eventual winner favoured at every checkpoint. Details in docs/ELECTION-NIGHT.md.

D-H1 Hourly, publish-on-change forecast; status-only commits skip the deploy (2026-11-01)

The forecast is no longer locked. .github/workflows/forecast-hourly.yml runs model/run_hourly.py at minute 7 of every hour until 2026-11-20 (afterwards only on manual dispatch). The seat pipeline (100,000 runs) and the measures forecast run; a rounded summary (chamber p_rep_super to 3 dp, expected Republican seats to 1 dp, Democratic p10/p90, every seat p_dem to 3 dp as a digest, every measure p_pass to 3 dp) is compared with the last entry of data/forecast/forecast_history.json. Unchanged: the previous output files are restored byte for byte (float noise differs across machines) and only data/forecast/status.json {checked_at, last_changed, runs_since_change} moves. Changed: new outputs kept and a history entry appended. The final field is gone from forecast_2026.json. Guard: once data/live/nowcast.json status is counting, neither model re-runs (election night belongs to the nowcast). Deploy cost: pushing to the default branch deploys on Vercel, so site/vercel.json has an ignoreCommand that skips the build when the only file changed in the commit is data/forecast/status.json. Chosen over throttling status commits because the checked-at stamp stays honest in git and a skipped build costs nothing. Consequence: the site shows "Updated <last change>, checked hourly" and not the checked-at time, because that stamp would lag between deploys. The scoring rule scores the last forecast published before polls close at 7 pm CT, plus the full history.

D-C1 Congressional baseline: presidential lean plus the full national swing (2026-11-01)

MO-2 fundamentals = national generic-ballot two-party share (0.5 + margin/2; D+8.2 on 2026-11-01 gives 0.541) + (district 2024 presidential two-party lean on current lines, 0.4599 from data/raw/congress/scripts/build_overlap.py, minus the national 2024 presidential two-party share, 0.4924 = Harris 75.02M / (Harris + Trump 77.30M)) at elasticity 1.0, not the legislative 0.58. The reported swing (0.054) is the generic share minus the 2024 national House share 0.487. Departure from PLAN 2.4: the plan used a relative lean of -0.023 (implying a national baseline of 0.485, which matches no published figure); the computed -0.033 is used and lowers fundamentals from about 0.50 to 0.483. Parameter: national_pres_2024_dem_share in data/congress/inputs.json.

D-C2 Incumbency 2.0 share for Wagner (2026-11-01)

2.4 measured in 2024 (2024 House 0.438 against presidential 0.460 on the same lines), 1.7 in the House literature, 2.0 chosen for wave compression; incumbency_share 0.020. Money term: 0.5 share points per log unit of the spending ratio, capped at 1.0: ln(1.94/5.67) x 0.005 = -0.0054 (FEC through 2026-10-14).

D-C3 House effects, recency and poll error (2026-11-01)

Partisan-sponsored polls (D: PPP for House Majority PAC, FM3; R: Remington) are moved 3 margin points (1.5 share) toward the other side, partisan_margin_shift 3.0. Weight = 0.5^(age/21 days) x sqrt(n/400); FM3 (May) falls to under 0.01. Poll-error sd 3.3 share (poll_error_sd), fundamentals sd 4.0 (fundamentals_sd) weighted as one fresh 400-person poll (fundamentals_weight 1.0); the centre is the weighted blend and its sd moves from 4.0 toward 3.3 with the evidence share. Error: shared national draw (sd 0.75 share = 1.5 margin points of generic-ballot error, seed 20261103 and t5 as in pipeline.py) plus a district t5 draw; both t5 draws are rescaled to unit variance so the stated sds are the actual sds. Exact sharing of the seat model's array is pending the lead.

D-C4 Markets at half the weight of one poll, shown beside (2026-11-01)

Superseded in part by D-C7 (2026-11-01): the weight and mapping stand; which prices count changed. market_weight 0.5 (one fresh 400-person poll counts 1.0). A market probability is mapped to a share as 0.5 + 0.04 x z(p) (market_sd). Rows with used = 1 in markets.csv are averaged (Kalshi 0.33, Polymarket 0.37, the latter unverified, giving 0.35). Set market_weight to 0 if prices look thin; the market is then only displayed.

D-C5 MO-2's poll surprise conditions the legislative shared error (2026-11-01, revised)

Observation sd amended by D-C8 (grows as the polls age). Supersedes the earlier D-C5 ("shown, not fed back, before the election"); Daniel approved feeding it back now ("we always want the model to be the very best it can be").

  • Signal: z = MO-2's house-adjusted poll average minus its congressional fundamentals (congress.environment_signal), 0.505 - 0.483 = +0.022 on 2026-11-01. The generic ballot, Wagner's incumbency and the money term are netted out.
  • Observation: 0.58 z (the D-03 legislative elasticity) observes the seat model's shared error for the House seats in MO-2, e_state + sum a_r e_region + sum a_t e_type, with loadings a = MO-2's presidential vote by region and district type. Noise sd 0.58 x 0.051: one poll's error (district polls miss together, so four are not divided down) combined with the district part of the fundamentals error. Gaussian conditioning; the t5 statewide term enters at its variance; posterior variances are left at their priors (conservative). Parameter mo2_feedback_weight 1.0 (0 turns it off), mo2_legis_elasticity 0.58.
  • Result: +0.0036 statewide, +0.00045 St. Louis region, +0.0003 inner suburbs. House P(R two-thirds) 0.133 -> 0.099; Senate 0.571 -> 0.521; 21 seats move more than 1 point (HD 94, 96, 101, 104-106 about +5).
  • Sensitivities (adversarial review): under PLAN 2.4's baseline (D-C1 alternative) z is about 0.005 and the statewide update +0.0008, so most of the effect rests on D-C1. Reading 0.58 as Missouri's own elasticity (z against 0.58-elasticity fundamentals, used at 1.0) gives +0.0052; obs_sd 0.035-0.07 gives +0.0056 to +0.0023. Two of the four polls are partisan (about two-thirds of the poll weight); Emerson alone gives +0.0070. The chosen reading is the more conservative of the two elasticity readings.
  • Not backtested: no MO-2 (or other district) polls from 2022 or 2024 are in the data. Scored after the results.
  • Counted once: the nowcast's statewide prior is shift_mean + this update (nowcast.prior_shift), so returns update it rather than adding to it; congress.seats_check compares the polls with seat means before the update.

D-C6 Nowcast contest USH2 and its link to the House seats inside MO-2 (2026-11-01)

USH2 (label "U.S. Representative, District 2", D Wellman / R Wagner, ENR title "U.S. Representative - District 2") is a partisan contest like AUD with four county rows read from data/processed/county_cd_baselines.csv (CD 2): Franklin, Warren, St. Louis County (part), St. Charles (part). Baseline per county = 2024 Dem two-party US House share in that row (Franklin 0.276, St. Charles 0.363, St. Louis 0.489, Warren 0.248) plus the expected movement 0.0567, which is the MO-2 forecast's dem_share_mean (0.4949, data/forecast/congress_2026.json) less the 2024 MO-2 Dem two-party share from the same table (0.4382); result level 0.494. Prior sd 0.0319 from the forecast's 80% range ((p90 - p10) / 2.563). Expected-vote weights are the 2024 US House votes in those rows (all candidates: 53,857, 58,554, 302,767, 13,214). All four rows sit in the stl region, so the contest's region swing is one number. The 5% gate applies to USH2's own expected vote: below it the contest is awaiting and nothing flows to the seats. ENR reading is optional: if the title is absent the capture only warns. Seat link: USH2's projected share less its baseline (the swing) is one more observation of the St. Louis-area swing. Each House seat inside MO-2 blends it with the swing it already carries (the auditor-informed seat shift): seat mean += ush2_seat_weight (0.5, CAL) x w x (USH2 swing - existing seat shift), w = the seat's share of presidential votes inside CD 2 (hd_cd_overlap.csv share_of_hd). Seats outside MO-2 (w = 0) and called seats are untouched; the engine is not restructured (the shift is applied to the seat means before the simulation). No pipeline.py change. Output: ush2_link, legislature.ush2_seats. Not calibrated: nowcast_replay has no US House case; the weight is a judgment, to be scored after the results.

D-N2 Election-night capture is automated; a contest is held until 5% is counted (2026-11-01)

Returns are read by scripts/live/capture.mjs (Chromium, because enr.sos.mo.gov is behind Cloudflare) every 10 minutes, validated, and pushed with the nowcast; the manual path in docs/ELECTION-NIGHT.md remains the fallback. Copied from israelielection.org's election night: (1) a capture that fails any check (unknown county, votes that fell, a fraction outside 0..1, rows not adding to the page's own total, counties not adding to the statewide page, a missing contest, a page for another election) writes nothing and is logged with a distinct reason; (2) a keep-alive restarts the loop after a crash or reboot; (3) no projection from a tiny count: below min_coverage = 5% of the expected statewide vote, nowcast.json marks the contest awaiting and carries the pre-election chance and range, and the seat shift stays at its prior (Israel's projection at 0.1% counted was badly wrong). The threshold is the one israelielection.org uses; our own replay shows 1.0 point average miss at 10% counted, so 5% is a floor, not a promise. Two defects found while rehearsing and fixed in model/nowcast.py: a file mixing district rows (with reported_frac) and county rows (with precincts) made every county read as half counted; and a district counted to 100% within half a point of tied divided by zero and stopped the whole run.

D-C7 Only fresh, API-fetched market prices count (2026-11-01)

Daniel's ruling 9 (Codex review, "Unverified market prices"). Supersedes the price selection in D-C4; its weight (0.5) and mapping (0.5 + 0.04 z(p)) stand. model/markets_fetch.py reads two free public APIs with no key, every hourly run before the forecast (run_hourly.py; 10 s timeout per request, every failure logged and skipped, never fatal): Kalshi KXHOUSERACE-MO02-26-D (api.elections.kalshi.com/trade-api/v2; yes if the member sworn in for MO-02 in 2027 is a Democrat) and Polymarket "Will the Democratic Party win the MO-02 House seat?" (gamma-api.polymarket.com, event mo-02-house-election-winner). Both price "a Democrat wins MO-2" = Wellman, contract mo2_dem_wins. Price = bid/ask midpoint when the spread is at most 0.05; otherwise the platform is skipped that hour (the last trade can be hours old; review 2026-11-01). Each fetch appends a row to data/raw/congress/markets.csv with as_of = fetch time (UTC ISO), source = api, the API URL and a contract note. congress.market_rows counts a row only if source = api, contract = market_contract, used = 1, it is the platform's latest API row and it is at most market_max_age_hours (36) old; the counted platforms are averaged. Otherwise the market weight is 0 and the prices are shown, not counted. The three hand rows (an undated search snippet, an earlier guess-dated snapshot, the unverified Polymarket figure) are now used = 0, source = hand, display only. First fetch 2026-11-01 17:29 UTC: Kalshi 0.365, Polymarket 0.395 (mean 0.38, against the old hand mean 0.35). Codex's caveat stands: a market is not an independent observation of the vote; the blend is to be scored against a no-market benchmark (Milestone 1).

D-C8 D-C5's observation error grows as the MO-2 polls age (2026-11-01)

Daniel's ruling 10 (Codex: "MO2 feedback does not lose strength"). The MO-2 forecast's own poll weights, 0.5^(age/21 days) x sqrt(n/400), are precisions in units of one fresh 400-person poll (the fundamentals count 1.0 in the same unit). Their sum W is the polls' effective weight. Poll part of the observation sd = 0.033 / sqrt(min(W, 1)): at one fresh poll or more it stays one poll's error (district polls miss together, D-C5), below it the variance is divided by W. Combined with the district part of the fundamentals error as before. W = 1.66 on 2026-11-01 and 1.55 on 2026-11-03, so obs_sd stays 0.0513 and the published update is unchanged before the election; W falls below 1 on 2026-11-17 (obs_sd 0.0527 on 11-20) and to 0.085 on 2027-01-30 (obs_sd 0.120, the statewide update falls accordingly). The surprise z itself is a normalised average and does not age; only its weight does. The cap at one poll is the D-C5 judgment, not estimated.

Amended 2026-11-02 (whole-branch review of D-25 to D-28): the default aging clock is the UTC date capped at election day, `congress.model_today()`, used by the MO-2 polls, the district polls and the Auditor polls alike and computed once per run. The UTC date turns at 6 pm Central on Nov 3 while the polls are open; a late hourly run would otherwise re-age the polls and republish after they close. Explicit dates are not capped, so post-election scoring ages as this decision says.

D-21 One simulated election for both chambers (2026-11-01)

Daniel's ruling 13 (Codex PLAN, "The headline requires joint predictions"). pipeline.py draws the statewide t5 error, one normal error per region and one per district type once per simulation (simulate.shared_shocks) and passes the same vectors to the House and Senate simulations (simulate(..., state_shift=, region_shift=, type_shift=), keyed by region and type name; callers that pass none, such as nowcast.py, keep the old behaviour and random stream). Seat errors stay independent. New output joint in forecast_2026.json: P(Republican two-thirds in both chambers / House only / Senate only / neither). 2026-11-01, 100,000 runs: both 0.089, House only 0.010, Senate only 0.431, neither 0.470 (independent draws gave both 0.051). Marginals unchanged within Monte Carlo noise (House 0.0993 -> 0.0991, Senate 0.5208 -> 0.5206). Sharing the full statewide, regional and type error is the strongest dependence the model's error structure allows; whether the chambers share all of it is not estimated (Codex: "without establishing which dependence strength is empirically correct"). joint_shock False restores separate draws. MO-2 and the measures are not yet in the same draw (Milestone 2).

D-M7 One shared undecided coefficient (2026-11-01; ruling 14; supersedes D-M4)

The referral-specific split (0.40 legislative, 0.15 initiative/referendum) is replaced by one coefficient for every measure, fitted by least squares constrained to 0..1 on the latest complete final-six-week poll per contest (17 contests, 7 election dates, history_polls.csv): 0.3925. Reproduce with python model/measures.py --fit; the value lives in data/measures/inputs.json (undecided_to_yes). Leave-one-election-date-out RMSE (refit on the other dates, score the held-out ones): 8.28 points for the shared coefficient against 8.77 for the referral split, so the extra degree of freedom did not earn its place; D-M4's 8.3 to 7.8 was in-sample. The coefficient is an empirical poll-to-result correction, not a measured share of undecideds who voted yes: the implied ratio (result - poll yes)/undecided lies outside 0..1 in 8 of 21 complete rows, and sampling error, switching by decided respondents, turnout, wording and campaigning all enter it. Effect: initiative and referendum measures with polls (A6, Prop A) move up about 3 points, since they were using 0.15; unpolled measures and A3 are unchanged in effect. Priors, poll error and everything else are untouched. Small local history; a fuller poll-to-final error model is deferred (audit M1).

D-N3 Live counts: counted votes are a floor, nothing is locked, complete only by hand (2026-11-01)

Rulings 5-8 (Daniel, 2026-11-01) on the Codex accuracy review (docs/research/2026-11-01-accuracy-review/WORK-ORDER-01.md).

  • Conservation. In every draw a reported unit (county, or district for HD-/SD- rows) ends with a + q_p R_p + q_L L votes for option a and b + (1 - q_p) R_p + (1 - q_L) L for option b: counted votes plus nonnegative additions, so neither side can end below its count (the review's 900-50 fixture at 95% had 554 and 217 violating draws; now 0). R_p = n (1 - f) / f x lognormal(0, 0.15): the old total noise (0.15 (1 - f) on the log total) restated on the remainder, where it is the same 15% relative spread but cannot go negative. q_p is the remainder's share implied by the unit's latent final share (the replay-calibrated tau / sigma_b posterior, D-N1), bounded to [0, 1]; this keeps D-N1's calibration and only truncates impossible draws. The latent share of a reported unit is no longer clipped to 1-99%, so a 100-0 county cannot acquire votes for the other side by clipping. Statewide pre-election parameters are unchanged.
  • Near-final, not exact (ruling 6). Every reported unit not flagged complete carries a leftover L = n x lognormal(log 0.02, 0.6) (median 2% of counted, 80% between about 0.9% and 4.3%) whose share is the latent share plus N(0, 0.10), clipped to [0, 1]. Why 2%: Missouri absentee ballots must arrive by the close of polls, so the true post-election-night remainder is provisional and military/overseas ballots, which is small; but the reported fraction is precinct completion (the capture sends precincts reported / total), and a county can show every precinct in while an absentee or central-count batch is still out. 2% with a long right tail covers that mismatch; it is a judgment, deliberately on the wide side, to be scored after the results. Consequence: a 5001-4999 district at 100% precincts reads about 53% D, not certain either way.
  • Complete (ruling 6). A hand-entered complete column (1/true) on a contest+county row or a district row makes that unit exact: final = counted, no remainder, no leftover, and for a district no state, region, type or seat noise for that seat. A unit is complete only if every one of its option rows carries the flag; a partial flag, or a flag on zero votes, is ignored with a WARNING (unknown missing returns are not zero votes). Revised counts simply replace the rows; the flag stays with the rows. A complete exact tie is a coin flip in the chamber draws (p = 0.5), listed in legislature.ties, never projected. A contest is complete when all its counties are; its p_a_wins counts an exact tie as half and it sets tie.
  • No fixed winners from counts (ruling 5). The 98%-counted / 0.5-point rule is gone (at 98% and 50.6% D the D candidate can finish on 49.588%). Seats with returns stay probabilistic in every draw. Fixed winners from the forecast file (uncontested seats) are unchanged.
  • Projected winner (ruling 8). CAL["projected_threshold"] 0.95. Contests: projected_winner = option_a / option_b at >= 95% and not awaiting, else null. Legislature: projected replaces called, a list of {chamber, district, winner, p_win (4 dp), share (counted D two-party share, 4 dp), pct_counted, complete} for seats with returns at >= 95%. It can come off again.
  • Unknown reporting fraction (ruling 7). The silent 0.5 default is gone. A unit with votes and no (or a zero) fraction gets f = counted / expected two-way votes, clipped to [0.05, 0.95] (never complete by inference), with a wider remainder (log-sd 0.5) and a WARNING naming the rows. Expected: the county's expected_2026 (statewide contests), the USH2 two-party expected total (D-C6), or for a district 2024 presidential votes x the statewide midterm drop-off. County rows in nowcast.json carry frac_source (reported_frac | precincts | inferred | complete); returns may label their own fraction with a frac_source column. Precinct completion remains a proxy for the vote fraction.
  • Mechanics. The live chamber draws (nowcast.seat_draws) reproduce simulate.simulate's draws call for call (a test checks the wins are identical), so with no district returns the live chambers equal the published forecast to Monte Carlo error (House 0.0988 vs 0.0993, Senate 0.5232 vs 0.5208 at 20,000 draws). A seat with returns uses its own draw's shared part (state + region + type), shrunk toward the counted share as for counties; its returns noise comes from a separate stream so entering one district never reshuffles another seat's draws.
  • Known limit (open): D-N1's sigma_b (5 points at half counted, falling as sqrt(1 - f)) implies that near completion the last few percent can differ sharply from the rest; at 98% counted and 50.6% D the seat reads about 76% D. That is the calibrated model's own uncertainty, not a lock, and it is conservative if precinct completion overstates vote completion.

D-C6 (revised 2026-11-01) USH2 units, prior continuity and a support-only seat link

Supersedes the expected-vote, prior-sd and swing paragraphs of D-C6 above; the contest, rows and weight 0.5 are unchanged.

  • Units (Codex units finding; lead GATE in docs/planning/2026-11-01-accuracy-impl/STATE.md). Expected totals are two-party (D+R) 2024 US House votes in the CD-2 county parts (415,500) times each county's midterm drop-off, the same drop-off as the statewide expected_2026 (expected / 2024 presidential total): 364,376 expected two-party votes. The 2024 reference share is the expected-weighted county share, so the weighted county baseline equals the published MO-2 mean exactly (0.4949; before, 0.4943 against 0.4949). The 5% gate's denominator is declared in nowcast.json as coverage_basis.
  • Prior continuity (ruling 11). With no returns or below the gate the USH2 headline is the published distribution itself: ush2_prior_draws re-creates congress.py's draws from the published blend (centre, national and district sd), seed, runs and t5 (P(D) 0.4306, 80% range 45.40-53.58 against published 0.4306, 45.41-53.58; before, 0.4450 and 43.82-55.02). Once returns pass the gate the county decomposition aggregates back to the published sd rather than adding to it: the common swing gets sd_S^2 = sd^2 - (sum w^2 tau^2 + rho^2), giving sd_S 0.0115 (sd 0.0319 from the 80% range), and USH2 county turnout is not drawn (turnout_sd 0); with no returns that decomposition's sd is 0.0318. Consequence: with four rows and St. Louis at 71% of the expected vote, most of the district's prior uncertainty sits in the county terms, so St. Charles or Franklin reporting moves the St. Louis part less than before.
  • Seat link (ruling 12). The swing passed to the House seats is the within-county support change at FIXED expected two-party weights: sum_c w_c (projected county share_c - baseline_c), regions.stl.support_swing. A pure turnout-mix change (St. Louis part at 75% turnout, every county's share at baseline) moves the district total by 1.1 points but gives a support swing of 0.00003 (before, -1.10 points passed to the seats); a 3-point St. Louis share change gives +0.0213 (w = 0.711). Turnout composition still counts for USH2's own projection. The transfer is a point estimate: the USH2 posterior's uncertainty is not propagated into the seat draws (seat sds unchanged), and this is not a joint posterior; a coherent joint update (shared environment conditioned on USH2 and auditor counts with candidate effects) is later work. Weight 0.5 stays a judgment, unscored.

D-N4 Election night: one election for both chambers; seats gated at 5% (2026-11-01)

The live legislature draws the regional and district-type shocks once and shares them across House and Senate (as D-21 does before the election) and reports legislature.joint (both / house_only / senate_only / neither, as P(R keeps)). With no returns it reproduces the published joint block within Monte Carlo error (0.0905 vs 0.0893 both). A seat is listed as a projected winner only once at least 5% of its own count is in (D-N2's gate) or it is flagged complete; on the synthetic replay 13 safe seats were otherwise projected at 2.5% counted. District rows from the ENR capture now carry frac_source=precincts, since their fraction is precincts reporting, not ballots counted. Review fixes (2026-11-01): a stated fraction that implies a final count above 1.5x expected (absentees in before precincts: 1 of 600 precincts with half the vote counted) is not trusted and the fraction is inferred instead, with a WARNING; the same for districts. An inferred district is gated on its unclipped counted / expected share. Each seat's returns noise has its own stream seeded by (seed, chamber, district), and the legislature its own stream, so entering one count never reshuffles another seat or the chamber odds. capture.mjs copies every Python WARNING line into the cycle log.

D-N5 Live nowcast: the reverse fraction guard and shared turnout uncertainty (2026-11-02)

Two model changes (PLAN 2026-11-01-model-improvements, section 2 items 2 and 3); figures in docs/planning/2026-11-01-model-improvements/B-before-after.md.

  1. implied_min 0.5. D-N4's guard distrusted a stated reporting fraction only when it implied too many votes. The reverse, precincts mostly in but votes far below expectation (large precincts, an absentee batch outstanding; the ENR fraction is precincts reported / total), was taken at face value, so a county or seat projected from its early batches. Now a fraction implying a final count (counted / f) below 0.5 x expected is inferred like the too-many case: wide remainder (frac_sd_inferred 0.5), frac_source "inferred" (the site's "est. vote"), a WARNING naming the unit. County rows and districts. Effect: none on a clean night, and none on the corrected synthetic fixture (the earlier 13-to-8 and Senate 0.33 figures came from a fixture giving every district 9,000 x f votes). implied_min is 0.4, not 0.5: a fully counted low-turnout urban district runs about 0.58 of expected. Cost: a unit truly 40% below expected turnout is widened, not mistaken.
  2. Shared turnout draws. Unreported county totals were expected x a deterministic regional factor (learned from counties at least half counted) x independent county noise, so the regional turnout mix looked known and the factor ignored its own uncertainty (Codex TURNOUT-ADDENDUM). Now one log-turnout draw per region (sd 0.08 x sqrt(3/(k+3)), k = counties informing that region's factor) and one statewide (0.05 x sqrt(3/(k_all+3))) multiply the uncounted totals only; counted votes are untouched (D-N3 floor, tested). Own random stream, so no other draw moves. Off for USH2 (its sd is already decomposed to the published one). Validation: nowcast_replay.py, now with a rescale=False variant that keeps real county totals (the standard replay rescales them to the expected sum, hiding turnout error): 80% coverage at 10-50% counted does not fall in either (0.884 to 0.896 and 0.859 to 0.884 at 10%), mean miss unchanged. Counted-share projections do not move; intervals widen slightly early. Adversarial review (2026-11-02): no bug found; counted-vote conservation, the separate random stream and the shrinkage at k = 0 checked. Risks accepted: (a) a unit at 100% of precincts with under 0.4 of the expected vote is also inferred (not exempted: it is not near-final), so it is widened, not fixed; (b) inferred units leave the regional-factor pool, so a region truly under half of expected turnout is not learned from them, only widened (the shared draw now covers that uncertainty); (c) a hand reported_frac is distrusted by the same rule; (d) the shared draws are zero with nothing counted, so the no-returns prior is exact. Also from review: an awaiting measure now shows the published p, mean, p10 and p90 exactly (it was a re-run, A8 0.7165 vs 0.7306 published). Fixed from the review: no second WARNING for a unit already inferred.

D-V1 One vintage: the hourly run rebuilds the pre-returns nowcast; the build checks it (2026-11-01)

The home page and /live showed three vintages (forecast file, an older nowcast, and a live Auditor row). Every published file now carries vintage {generated, forecast_generated, inputs_as_of} (metadata only, no numeric change). model/run_hourly.py rebuilds a pre-returns data/live/nowcast.json whenever it was not built from the published forecast, in the same commit (forecast-hourly.yml commits it), and never touches a counting one. site/scripts/sync-data.mjs fails the build when a pre-returns nowcast disagrees with the forecast (0.0015) and only warns when counting. Before returns /live shows the forecast's figures and timestamp; the nowcast's own time appears once counting starts.

D-22 Seat distributions and 80% ranges come from the simulation (2026-11-01)

The district page used to draw a Student-t curve (7 df, scale = the seat error sd_seat) and an 80% range of mean +/- 1.2816 sd_seat. Neither includes the shared statewide (t5, 0.015), regional or district-type errors that p_dem does, so the curve and p_dem disagreed (HD31: curve about 15% D against 22.2%; HD100: 85.7% against 78.8%) and ranges were about 50% too narrow. simulate() now hands back the share matrix it already builds (share_out; no extra random draw, so every p_dem, chamber and joint figure is bit-identical, checked by diffing a 100,000-run, seed 20261103 pipeline run before and after). pipeline.py writes p10, p50, p90 per seat into seats_2026_forecast.csv and a 1-point histogram (100 bins over [0, 1], counts of simulations, shares outside [0, 1] pooled in the end bins) per contested seat into data/forecast/seat_hist_2026.json. The 50% line is a bin edge, so the mass above it is exactly the p_dem count. The district page plots that histogram (each bin edge takes the mean of its two neighbouring bins; no other smoothing) and the history chart's 80% bar is p10 to p90. The t-approximation and mean +/- 1.2816 sd remain only as a fallback when those fields are missing. The fine print that called the curve an approximation is removed where the histogram is used (it stays on the fallback, where it is true). Fixed-winner and uncontested seats have no histogram. Live (election-night) seat views do not use these fields.

D-C9 MO-2 market prices without the overround; how the 44% is built (2026-11-01)

Kalshi's two MO-02 contracts were priced 0.365 (Democrat) and 0.615 (Republican), summing to 0.98; Polymarket's sum to about 1.00. Reading only the Democratic midpoint treats the book's overround or underround as probability. model/markets_fetch.py now records P(Dem) = p_D / (p_D + p_R) when both sides have a tight book and their sum is within 0.9-1.1, else the raw p_D, and keeps the raw midpoint in the row's note. Effect on the 21:10 UTC inputs: Kalshi 0.365 -> 0.372, counted market 0.390 -> 0.394, MO-2 P(D) 43.9% -> 44.0%.

Why the forecast says 44% while some outside forecasts call the race even (review in docs/planning/2026-11-01-model-improvements/PLAN.md, section 1): the expected Wellman two-party share is 49.6%, close to even. The market blend at weight 0.5 contributes about 1.8 points of probability (45.7% with no market weight, 43.9% at 0.5). The main reason the chance sits below 50% is the fundamentals, 48.3% (2024 presidential lean moved by the national swing, Wagner's 2.0-point incumbency edge, money). No parameter was changed to approach another forecaster's number; the evidence that could justify a change is a congressional panel in the backtest, planned after certification.

D-CAL1 Backtest writes per-seat probabilities and calibration bins to calibration.json (2026-11-01)

The public evaluation page needs calibration by probability bin; scores.json only had per-year scores. model/backtest/run.py now also writes data/backtest/calibration.json: per model, every held-out contested seat's predicted Democratic win probability and outcome, and 10 equal-width bins (count, mean predicted, observed frequency, Wilson 95% and 80% intervals, few_seats when n < 10) pooled, by chamber, by year, and by year and chamber. A separate file, not a new key, so scores.json stays byte-identical (checked with cmp) and its consumers are unaffected. The probabilities are the very ones Brier and log loss use, captured read-only: no model change, no extra RNG draws, no change to the 2026 forecast. Wilson, not Wald, because bins hold 0 or 100% observed frequencies; intervals treat seats as independent although a year's seats share a statewide shift, so they are optimistic (stated in the file). Bins under 10 seats are flagged, not merged. Runtime about 4 s. First finding: pooled over 2018-2024, Democrats won less often than predicted in the 0.1-0.5 bins (0.4-0.5: 43% predicted, 17% observed) and more often in 0.6-0.8; reported, no recalibration made on four elections.

D-CAL2 Backtest calibration: no change to the 2026 seat model before certification (2026-11-01)

The D-CAL1 export showed baseline A's middle seats going decisively one way more often than predicted. Analysis (docs/planning/2026-11-01-model-improvements/CALIBRATION-ANALYSIS.md): the pattern survives removing each year's statewide error, sits in 2018 and 2020 on the old map, and is concentrated in seats with no lean or past result; on the current map (2022, 2024) the middle seats are close to calibrated. The 2026 model's seat scale (0.0174) is already measured out of sample with the year shift removed, and its competitive-seat sd (about 0.03) is a third to half of baseline A's. Variants of the seat scale barely move the headline chances (House P(R two-thirds) 0.099 published, 0.098 at x0.845); the headline is driven by the statewide error, which the backtest cannot estimate from four elections. Decision: no change before certification. After it: add 2026 to the backtest; settle whether D-06's scale should be the t(7) scale or the sd (simulate.py draws t(7) x scale, about 1.18x wider than the measured error); re-check the open-seat (x1.25) and no-history (x1.5) multipliers. /evaluation shows baseline A's calibration with a caveat that it is not the published forecast.

D-23 "Why this forecast": every forecast's centre exported as exact parts; labelling only (2026-11-01)

The site is to explain each forecast in plain words, and every sentence must map to a number the model used (docs/planning/2026-11-01-why/SPEC.md). The site could not rebuild the parts itself: the seats CSV dropped carry, incumbency, education, primary, quality and MO-2 terms, and rounded the rest to 4 dp. The model now exports them, computed from arrays it already has, with no new random draws and no change to any published number:

  • Seats (seats_2026_forecast.csv, new columns after the old ones, 6 dp): L_comp_exact plus contrib_baseline (2024 intercept + (slope - 1)(L - 0.5)), contrib_national (shift_mean), contrib_mo2_state, contrib_mo2_local (D-C5), contrib_incumbency (D-17), contrib_prior_result (carry x past error), contrib_education (D-19), contrib_primary (D-18), contrib_quality (D-20) sum to mean_exact (the published mean unrounded) within 1e-9 in memory and 6e-6 in the file. Also resid_year (2024, 2022 or none), carry_reason, carry_effective (the carry, times 0.65 on the 2022 fallback), the seat-error multipliers sd_rel, sd_open_mult, sd_nohist_mult, and dtype. The old 35 columns keep their 4-dp rounding and text.
  • Chambers (forecast_2026.json chambers.*.why): seats with a fixed winner, very likely (chance above 95% or below 5%) and in play; seats needed; Senate holdovers; the runs in which Republicans keep two-thirds; and the mean statewide swing draw in those runs and in the rest (House today -2.9 and +0.3 pts; Senate -0.8 and +0.9).
  • Measures (measures_2026.json measures[].why): k x poll yes + k x 0.3925 x undecided + (1 - k) x starting estimate = centre, the weights, each poll's share of the weight, and the spread's pieces. sd_own, common_error_sd and turnout_term_sd are the scale parameters of t(5) draws, not standard deviations: each draw's sd is about 1.29 times the figure (sqrt(5/3)), so a reader sentence must call them scales or convert them.
  • MO-2 (congress_2026.json districts[].why): fundamentals as national generic-ballot term + district vs nation + incumbency + money, and the blend's weights, values and parts (sum = centre).
  • State Auditor (data/live/nowcast.json contests.AUD.why, pre-election metadata, see D-24). Seats with a fixed winner (D-07) have no contest, so the site must show no parts for them even though the columns are filled; carry_reason reads "same_pair" on some fixed-winner seats (14 today), a pre-existing quirk of the same-candidates match. A chance from the simulation is not additive and is not decomposed (SPEC rule 2). Proof that nothing published moved: the full pipeline before and after the change, same seed and inputs, gives identical pre-existing fields in every output (docs/planning/2026-11-01-why/compare_outputs.py; model/test_why.py). The one text change is the A3 notes in data/measures/inputs.json, which still carried a stale "Prior 0.47 ... (repeal baseline ~48.4%)" sentence contradicting the 0.478 starting estimate (D-M5); that sentence's label and stale figure were removed (SPEC section 10.2).

D-24 State Auditor: the 1-point incumbent adjustment and the 1.5-point candidate spread (2026-11-01)

Documentation of an existing choice; no number changes. The Auditor's pre-election level (model/nowcast.py) is the expected-turnout-weighted 2024 Democratic down-ballot share (Secretary of State, Treasurer, Attorney General, Lieutenant Governor), plus the seat model's statewide shift (D-03 shift_mean plus D-C5's statewide MO-2 update), minus 1 point for the Republican incumbent's (Fitzpatrick's) money and name. Its spread combines the statewide-shift sd (1.5 pts) with a candidate-effect sd of 1.5 pts: hypot(0.015, 0.015) = 2.1 pts. Both are judgment, not estimates: there are no Auditor polls, and until now the only record of either number was a code comment. They are now named constants (AUD_INCUMBENT_PENALTY, AUD_CANDIDATE_SD), the latter also in the election-night update that turns the Auditor's returns into the legislative statewide swing (its observation and prior variances), and exported in contests.AUD.why; they are not re-estimated before the election. Amended by D-26 (2026-11-02): the two numbers are now the prior of the candidate effect, which the two published Auditor polls update; the level and both uses of the candidate sd take its posterior (see D-26).

D-25 District polls condition the seat model, jointly with MO-2 (2026-11-02)

Signal. Two Senate-district polls are on file (data/raw/polls/legislative_polls_2026.csv, each row with source_url and fetched): SD 8, Remington Research Group for Missouri Scout, Sep 30-Oct 1, n=596 LV, Ingle (D) 48, Patterson (R) 45; SD 30, Remington for Missouri Scout, Oct 7-8, n=517 LV, Fogle (D) 47, Stinnett (R) 45. Each is a two-party Democratic share (0.5161, 0.5109), moved toward the Democrat by the congressional model's partisan_margin_shift (3 margin points = 1.5 share) because the sponsor is Republican-leaning (congress.adjust_polls, same rule as MO-2's polls), so 0.5311 and 0.5259. Observation. z = adj_dem_share - the seat's mean before any feedback (both Democratic two-party shares; positive = the poll is more Democratic than the model). z observes the seat's whole error: loading 1 on the statewide error, 1 on its region (SD 8 kc_metro, SD 30 springfield), 1 on its district type (both suburban_inner) and 1 on its own seat error. Today z = +0.029 (SD 8) and +0.008 (SD 30). Noise. poll_obs_sd(weight, district_poll_error_sd) = 0.04 / sqrt(min(weight, 1)), with weight = 0.5 * (age_days / 21) sqrt(n / 400) (D-C8's aging rule, constants read from data/congress/inputs.json). 0.04 is judgment: one legislative-district poll's error, larger than the congressional 0.033 because legislative polling is thinner and the pollster's record at this level is unknown. On Nov 2 the weights are 0.42 and 0.50, so the observation sds are 0.061 and 0.057. Joint update. pipeline.shared_observations replaces D-C5's single update with one Gaussian update of the latent errors [state, regions, types, polled seats] on all observations at once (MO-2's surprise, as in D-C5, with its loadings 1, a_r, a_t on lamz and noise (lamobs_sd)^2; and each poll). Prior variances are the simulated ones: state shift_scale^25/3 (t5), region and type 0.0075^2, a polled seat its final sd_seat^27/5 (t7; sd_seat after the open-seat and no-history multipliers). Posterior mean = Sigma H' (H Sigma H' + R)^-1 y; the variances stay at their priors in the simulation (conservative, as in D-C5). Because both sources inform the same statewide error, the joint statewide shift (+0.50 pts) is less than MO-2 alone (+0.36) plus the polls alone (+0.25): nothing is counted twice. SD 8 and SD 30 are not in CD 2, so the two sources overlap only through the statewide and suburban_inner terms. Seat parts (D-23): contrib_mo2_state/local stay MO-2 alone; contrib_poll_shared is the joint shared shift minus MO-2's; contrib_poll_seat is the polled seat's own part (SD 8 +0.49 pts, SD 30 +0.07). nowcast.prior_shift = shift_mean + MO-2's state + the polls' state part (+0.14 pts), so election night does not count the polls again; the Auditor's why gains polls_state. Switches. district_poll_weight (1.0; divides each poll's variance; 0 turns the polls off) and mo2_feedback_weight (unchanged). With both 0, or with the polls at 0, the seats CSV is identical in every pre-existing column to the pre-change pipeline (same seed, inputs and day); three columns are added (poll_shift, contrib_poll_shared, contrib_poll_seat) and the column order changes. district_poll_today pins the aging date for tests. Result (100,000 runs, Nov 2). House P(R two-thirds) 0.0991 -> 0.0872, expected D seats 59.53 -> 59.84; Senate P(R two-thirds) 0.5206 -> 0.4582, expected D seats 11.39 -> 11.50. SD 8 p_dem 0.570 -> 0.644, SD 30 0.719 -> 0.740; 14 House seats move by 1-2.3 points (all toward the Democrat, through the statewide term and their own region and type terms: kc_metro for HD 12 and HD 17, springfield for HD 133; suburban and suburban_inner). Not backtested: there are no district polls from earlier cycles; scored after the results like D-C5. docs/planning/2026-11-02-new-sources/A-before-after.md. Sensitivities (Senate P(R two-thirds); House; SD 8 p_dem; SD 30 p_dem): poll error sd 0.03: 0.433; 0.082; 0.676; 0.747. 0.06: 0.487; 0.092; 0.609; 0.731. Partisan shift 0: 0.519; 0.100; 0.592; 0.693 (unadjusted, SD 30's poll is slightly less Democratic than the model). Twice (6 margin points): 0.399; 0.076; 0.692; 0.782. SD 8 alone: 0.464; 0.088; 0.642; 0.731. SD 30 alone: 0.512; 0.097; 0.573; 0.731. Polls without MO-2: 0.486; 0.107; 0.622; 0.722.

D-26 Auditor polls inform the candidate effect; the SLU House generic ballot is a check, not an input (2026-11-02)

Signals. Two State Auditor polls (data/raw/polls/auditor_polls_2026.csv, each row with source_url and fetched): SLU/YouGov, Aug 13-24, Fitzpatrick (R) 45, Wilson (D) 43, unsure 12, nonpartisan; Remington Research Group for Missouri Scout, Oct 14-15, n=684 LV, Fitzpatrick 47, Wilson 40, Coffell (L) 2, undecided 11, Republican-leaning sponsor. And the SLU/YouGov microdata (STLU0016, 900 likely voters, design effect 1.25, n_eff 720; provenance in data/raw/polls/NOTES.md), whose weighted Missouri House item (POLS026) is D 43.5 / R 48.5 / other 1.9 / unsure 6.1 (model/slu_toplines.py; the US House item POLS025 is 43.6 / 48.1; both round to the published 44 / 48). Auditor polls: an input to the candidate effect only. Each poll is Wilson's two-party share (the model's Democratic-share convention), the Remington one moved 1.5 points toward the Democrat (partisan_margin_shift, as for every R-sponsored poll), aged and sized by the D-C8 rule, so 0.4886 (SLU) and 0.4748 (Remington). The SLU Auditor item was asked of 449 of the 900 (451 rows coded 9, not asked), so its weight uses n_eff 449 / 1.25 = 359, not the poll's 720. Model: y_i = base + shift + c + e_i, with base the 2024 down-ballot share, c the candidate effect (Fitzpatrick's personal vote) with D-24's prior N(-0.01, 0.015^2), e_i ~ N(0, poll_obs_sd(w_i, 0.04)^2) and the statewide shift ~ N(prior_shift, shift_scale^2) marginalised, not updated: the shift stays the seat model's (D-03, D-C5, D-25), and an Auditor poll cannot tell the statewide mood from Fitzpatrick's own pull. Because both polls share the shift, their errors are correlated: one 2x2 covariance shift_sd^2 11' + diag(e_i^2), so no number of polls can make the data precision on c exceed 1 / shift_sd^2. 0.04 is the D-25 district-poll figure (one down-ballot poll's error; above the congressional 0.033). The posterior sd has a floor of 0.01: two polls of a low-information race do not make the candidate effect more certain than 1 point (today's posterior, 1.43, is above it). The polls are aged to the forecast run's own poll date (`shared_observations.today`), so the Auditor level moves only with the forecast it is read with. The level becomes base + prior_shift + c_post_mean and the spread hypot(shift_scale, c_post_sd); the election-night link that turns the Auditor's returns into the seat shift uses c_post_sd in both its observation and its removed-prior variance (so returns still update the prior, never add to it). Exports: contests.AUD.why.polls, why.candidate_effect = {prior, posterior}, why.polls_candidate (the polls' part, c_post_mean + 0.01; incumbent_adj keeps its meaning, the prior's -0.01, and the parts still sum to level_exact) and why.candidate_sd (now the posterior sd). `AUD_POLL_WEIGHT` (1.0) scales each poll's precision; 0 restores D-24 exactly. Not backtested (no Auditor polls from earlier cycles); the c-shift correlation the polls induce is dropped when c's marginal is used on election night. Result (Nov 2). Weights 0.094 (SLU, 70 days) and 0.722 (Remington, 18 days); obs sds 0.130 and 0.047. Candidate effect -1.00 +- 1.50 -> -0.54 +- 1.43 pts. Auditor expected Democratic share 42.7% -> 43.1%, 10th-90th 39.6-45.7 -> 40.1-46.1, sd 2.12 -> 2.07 pts, P(Wilson) 0.11% -> 0.15%. No seat, chamber or seat-shift figure moves; the 2016-2024 nowcast replay is byte-identical. SLU House generic ballot: a check, published, not applied. `pipeline.statewide_check` writes forecast JSON `checks.generic_house`: slu_2pv = D / (D + R) of POLS026 = 0.4733 against the model's implied statewide House share (sum of pres_total_d mean_d over the 163 House seats / sum of pres_total_d, means after D-25) = 0.4406, z = +3.3 pts; weight 0.133 by D-C8 (field end Aug 24, n_eff 720), obs_sd poll_obs_sd(0.133, 0.03) = 0.082 (generic_check_error_sd). It is not applied: at 70 days old it would move the statewide shift by under 0.2 points (prior variance shift_scale^2 * 5/3), a generic ballot asks about a party and not the candidates on each ballot (163 seats, many uncontested), and the vote-weighted mean of seat means is not the statewide two-party House vote. Published the way congress.seats_check is, as a comparison readers can see (applied: false).

D-27 Late defensive committee money widens seat error outside the competitive set (2026-11-02)

Decision. A seat that is not in the researched competitive set (data/raw/quality/candidates_2026.csv, 36 seats) but whose defending party's committees spent at least $20,000 in the Missouri Ethics Commission 8-day reports (Oct 1-22, as transcribed by Missouri Scout on Oct 27) gets its seat error sd_seat multiplied by 1.25 (defence_spend_mult; defence_spend_min = 20000; defence_spend_mult 0 turns it off). The seat frame carries defence_widened (True for those seats). The defending party is the seat's last_party; spending is the sum of 8-day committee rows on that side (HRCC for Republicans; Will of the People + MO Democratic State Committee, SDCC and Missouri Senate Campaign Committee for Democrats). Rows whose amount is not a number are skipped (none in the 8-day rows on file). Why. A party committee spending real money to defend a seat it was not expected to lose is information about risk the lean and quality terms do not carry. We have no way to turn dollars into a direction we could defend, so the money changes how sure we are, not which way the seat leans: the mean is untouched (asserted in model/test_defence_spend.py, mean identical with the multiplier at 1.0 and 1.25). Effect. One seat qualifies: HD 14 (Democratic-held; Democratic committees $20,248). Its chance of a Democratic win moves from 99.42% to 98.82%; no other seat moves by more than 0.1 point; the House chance of a Republican two-thirds moves from 8.72% to 8.78%, expected Democratic House seats 59.84 both before and after, Senate unchanged. The effect is small because every seat with large committee spending is already in the competitive set. The multiplier is a judgment, not a fitted value; it is not backtested (no 2022 or 2024 8-day spending file is on file). Publication. The same inputs are published as data/forecast/finance.json (candidate raised, spent, cash on hand, and every committee row with its own period string; 24-hour and late-spend rows are context, never summed with the 8-day rows) by model/build_comparators.py.

D-28 Comparators are scored at their last version before polls close (2026-11-02)

Decision. The comparison forecasters are published as data in data/forecast/comparators.json, built by model/build_comparators.py from files on record (static input, never touched by the hourly run): State Navigate at its Nov 2 version (replacing Oct 31), On Point Politics as of Nov 1 (rated seats only: 22 House, 3 Senate; its Safe seats have no label and only a band, so the scorecard scores On Point on the seats it rates), and Missouri Scout's calls kept in ratings.csv (House D+7 with named flips, Senate D+2, and the House Power Rankings) as a columnist's calls shown beside the forecast, not scored with Brier. Rule. Every comparator is scored at its last version published before polls close at 7 pm CT on election day, the same rule the scorecard applies to our own forecast. A comparator that updates again before polls close replaces the one on file; one that stops updating is scored at its last version. On Point's win probability in the file is the leading party's chance (1 minus the Democratic figure where Republicans lead); flip means the leading party differs from the last winner's party. No model change. No forecast number moves; this is labelling and data only. Each row carries a source_url and fetched date in the raw files.

D-N6 Absentee batches, a replay-scored call tier, and the 2024 seat-call replay (2026-11-02)

Lead's goal for Nov 3: call seats correctly, and earlier. Code: model/nowcast.py (CAL keys marked D-N6), model/call_replay.py; tests model/test_batches.py.

  1. Evidence. OpenElections 2024 precinct file (data/raw/returns_2024/house_precincts_2024.csv, built by model/build_precincts_2024.py; State House D and R rows; district sums checked against the certified totals in history_seats.csv; sources in its NOTES.md). 107 of 116 jurisdictions report absentee / central-count votes as their own line. Across the 79 contested House districts with both an absentee line and election-day precincts, the absentee batch was a median 30% of the two-party vote (sd 9 points) and ran a median 4.3 points more Democratic than the election-day votes (sd 4.0; 25th-75th 2.5 to 6.2; positive in every competitive district). Within a district the election-day precincts' shares have a vote-weighted sd of 0.048 (median over districts; median 15 precincts, median 820 votes per precinct). The live model (D-N1) centred the early batch at zero bias, so in the replay of the 2024 House below a competitive seat's final (never withdrawn) projection came at a median 94.8% of its vote counted.
  2. Mechanism.
  3. Recording (record_batch, data/live/batches.json; key "A3|Boone" for a contest's county, "HD-17|" for a district; value {a, b, f, at}). A unit's post with votes and no precinct reported (fraction missing or 0) is its absentee batch, and is replaced by each later post while still no precinct is in (a second central-count batch is still absentee). A post with precincts in whose count is far above its stated fraction (n > implied_max x f x expected, 1.5: absentee listed as one precinct, or in before the precincts) is recorded if the unit has no batch on file, and not replaced after. A count below the recorded batch (a revision or a bad capture) drops the record. update_batches checks every county of every contest and every district on each run; complete units are skipped.
  4. Families (batch_family): one partisan lean shared by AUD, USH2 and every HD-/SD- district; one lean per measure.
  5. Lean (batch_leans). Per family, prior N(mu0, 0.03^2), mu0 = +0.03 (toward the Democrat) partisan, 0 for a measure's yes side. A unit informs once it has >= 1,000 election-day votes (counted minus batch) and >= 25% of its precincts; its d = batch share - election-day share has variance unit_sd^2 (0.04^2) + precinct_sd^2 (0.12^2) x 850 / n_E + (0.08 (1 - f))^2: its own lean, a few precincts' sampling noise, and the first precincts' unrepresentative order. Precision-weighted posterior; its sd never below 0.015 (the early units are biased, not only noisy).
  6. Observation (batch_observation). Final share = f_v x counted share + (1 - f_v) x remainder share. The remainder share precision-weights the counted election-day share (variance precinct_sd^2 (1/k_E + 1/k_R) + (0.10 (1 - f_E))^2, precincts counted from K = max(3, estimated final / 850), k_E capped at election-day votes / 850 so split precincts of a few votes carry no weight) with the batch share minus the family lean (variance lean sd^2 + unit_sd^2); with no election-day votes it is the batch estimate alone. The election-day total is the precinct-implied total (n_E / f_E) blended with the expectation (expected minus batch) by f_E, and is trusted only when f_E >= 0.2, the stated fraction is not below the one recorded with the batch, and the implied total is within [implied_min, implied_max] (0.4, 1.5) of the expectation; otherwise the expectation alone, source "inferred". The vote fraction f_v = counted / (batch + election-day total) (clipped to 5-95% when inferred) replaces the precinct fraction, (1 - f_v)^2 x the remainder share's variance replaces early_batch_var, and the gate is f_v ("batch") or counted / expected ("inferred").
  7. Where used. County rows: attach_batch_obs adds the estimate, and nowcast_contest uses it in place of the counted share and early-batch term and skips the D-N4/D-N5 guards for those rows. Seats: district_returns and seat_wins (remainder log-sd frac_sd 0.15 for "batch", frac_sd_inferred 0.5 for "inferred"). Those rows carry frac_source "batch" ("votes NN%" on the site).
  8. Output. nowcast.json batches {recorded, informing, leans per family (mean, sd, prior_mean, prior_sd, n_units, n_batches), rule}; county rows and legislature.batches carry {abs_share, abs_frac, eday_share, est_share, est_sd}.
  9. Switch. batch_aware=False turns all of it off: nothing recorded, no file written, the D-N1 observation stands. Without a recorded batch nothing changes (test_no_batch_means_no_change; a frozen fixture confirmed legislature() output identical after seat_wins was extracted for the replay). early_batch_var also has a batch_form "linear" option; CAL does not set it, so D-N1's form stands, and the replay pins it.
  10. Call tier. Each legislature.projected entry carries called: true when the seat is complete, or at >= 99% (call_threshold) with >= 15% of its vote counted (call_gate, on the seat's gate: f_v for a batch seat, counted / expected when inferred, else the precinct fraction). "Projected winner" stays at 95% (ruling 8, unchanged). Seats only; contests have no called tier.
  11. Scoring (model/call_replay.py, data/forecast/call_replay.json). The 2024 House through seat_wins, the code election night runs: 40 nights x 110 contested seats = 4,400 seat-nights; the 18 seats decided within 5 points give 720 competitive seat-nights. Prior: the backtest's production reproduction for 2024 (model/backtest/prod_repro.py). Truth: the real precinct returns. Reporting order simulated: a county's absentee batch first 75% of the time (else at a random point in its count), listed as one of the precincts half the time; R-leaning precincts first (tilt 0.6 z-score) half the nights; counties at different paces; the expected vote the guards and gate use has a 10% log error. "Prior" draws the statewide shift from the forecast's prior; "informed" centres it on the realised 2024 shift (sd 0.008), as the Auditor count would. The batch form learns its lean with batch_leans from CAL's prior (0.03), not the 2024 value. Wrong = a projected winner who lost; reversal = a projection withdrawn; final call = the share counted from which the right call held to the end.

| Environment | Form, threshold / gate | Wrong calls | Reversals | Competitive final call, median share counted | Competitive seats called by 50% / 75% / 90% counted | |---|---|---|---|---|---| | prior | current 95% / 5% | 13 | 231 | 0.948 | 10% / 22% / 38% | | prior | current 99% / 5% | 1 | 224 | 1.000 | 1% / 5% / 20% | | prior | batch 95% / 5% | 22 | 143 | 0.652 | 33% / 56% / 72% | | prior | batch 97.5% / 15% | 9 | 145 | 0.680 | 27% / 51% / 66% | | prior | batch 99% / 15% | 4 | 137 | 0.735 | 21% / 46% / 61% | | informed | current 95% / 5% | 8 | 238 | 0.948 | 14% / 26% / 41% | | informed | current 99% / 5% | 2 | 236 | 1.000 | 4% / 7% / 24% | | informed | batch 95% / 5% | 23 | 160 | 0.671 | 34% / 55% / 70% | | informed | batch 97.5% / 15% | 11 | 149 | 0.704 | 28% / 50% / 64% | | informed | batch 99% / 15% | 7 | 157 | 0.741 | 22% / 46% / 60% |

Seats that drew wrong calls under batch 99% / 15%: HD-47 and HD-98 (prior); HD-15, 38, 132 and 136 (informed). All were decided within 4.5 points (HD-47 54.5% D; the others 51.0-53.0%); the lead's reading is that their R-leaning precincts posted first (the replay file does not record each night's order). HD-47 and HD-132 are heterogeneous (within-district sd 0.15 and 0.10, against the 0.048 median); HD-15 and HD-38 are not (0.03). Calibration: at 25-75% counted, seats at >= 95% confidence went the stated way 99.8-99.9% of the time in the batch form and 99.97-100% in the current form, in both environments. Not scored: county rows (measures, Auditor, USH2); only House seats are replayed.

  1. Judgment and limits.
  2. The lean prior 0.03 is a judgment, below 2024's 4.3 because 2024 was a presidential year and no 2022 precinct file was available; on the night the learned lean, not the prior, carries the weight once units inform.
  3. The posting order is assumed, not observed; the replay's rural-first tilt (0.6 z-score, half the nights) is the lead's guess. That is why the ordering-drift terms (0.10 on the remainder, 0.08 on the lean) are wide and precinct_sd is 0.12, not the measured 0.048 (the replay's remainder-minus-counted share runs 0.055-0.065 sd mid-count, D-leaning on rural-first nights).
  4. Split precincts: a precinct of a few votes is not a precinct's worth of evidence (the k_E cap); a unit whose first precincts are tiny is sized from the expectation ("inferred") until a fifth of its precincts are in and the implied total is plausible.
  5. St. Louis County, Clay, Kansas City, St. Louis City, Boone and four small counties report no absentee line in the 2024 file; the replay carved a synthetic batch out of their precincts with the measured size and lean. Election night will show whatever ENR shows: a batch posted before any precinct is recorded; absentee votes inside precinct counts are not, and D-N1 stands there.
  6. The cost of the batch model is more wrong projections at the 95% tier (22 vs 13 per 4,400 seat-nights, prior; 23 vs 8, informed), against about 40% fewer reversals (143 vs 231) and far earlier calls (33% of competitive seats by half counted vs 10%). The lead keeps 95% for "Projected" and adds "Called" at 99% / 15%: 4-7 wrong per 4,400 against 1-2 for the old form at 99%, whose median competitive final call came only at the complete count (20-24% by 90% counted).
  7. Open: whether "Projected" should move to 97.5% (9-11 wrong); a measure's absentee lean is learned from scratch each night (prior 0, no history); Kansas City's rows (ENR may list Kansas City inside Jackson, Clay and Platte, so a county's batch may mix in Kansas City's).

D-CAL2 superseded: the forecast changes before the election whenever the evidence says a value is wrong (2026-11-02, Daniel)

Ruling, evening of Nov 2: everything that improves the forecast is changed before the Nov 3 6:55 p.m. pre-close snapshot, and whatever can be made dynamic (new information moves it automatically) is, provided it is signal and not noise. The bar for a change is "the evidence says the current value is wrong", not "a different value is defensible". D-CAL2's rule (no change to the 2026 seat model before certification) no longer applies; the forecast history (data/forecast/archive) records every version, so the scorecard can score pre- and post-ruling versions separately. Studies run under the ruling on Nov 2-3: docs/research/2026-11-03-outside-polls (no change to D-03), docs/research/2026-11-03-hand-set-parameters (D-29 below), docs/research/2026-11-03-outside-the-box (in progress).

D-29 Data checks of hand-set parameters; no value changes (2026-11-03)

Under the ruling above, every hand-set parameter was checked against Missouri data (docs/research/2026-11-03-hand-set-parameters, scripts in that directory). No value clears the bar; the data basis is recorded here.

  • Incumbency asymmetry is present in Missouri's calm years too (2022+2024 cross-section D +1.94 +- 0.44, R +0.97 +- 0.32 share; Gelman-King 2016-24 D +2.9 +- 1.0, R +1.2 +- 0.6), within 0.2 points of D-17's blended D 2.11 / R 1.17, so D-17 now rests on Missouri as well as Virginia evidence; refitting it does not lower out-of-sample rmse.
  • Out-of-sample carry grid optimum x0.75-1.0 of D-04's carries; open-seat multiplier about 1.1 (range 0.8-1.5) against 1.25; no-history 1.0-1.6 against 1.5; regional and district-type shared sds 0.0087 / 0.0082 (four-cycle RMS) against 0.0075, and 0.013 in the 2018 wave.
  • The Auditor incumbent edge is 1.2 points in the 2024 same-ballot contrast against D-24's 1.0, with office-to-office sd 1.3 against 1.5. The measures' t5 x 0.08 scores better than an sd-matched t5 on the 17-contest history; the undecided coefficient 0.3925 reproduces.
  • D-13's competitiveness gradient is not found in any of four out-of-sample tests; because the replacement level is not identified (calm years too wide, the 2018 wave 2.5-3x more dispersed), it is re-estimated after certification together with D-06's t7-versus-sd scale. No seat-model parameter on its plausible range moves the House supermajority chance by more than 2 points or the Senate's by more than 3.3; the headline belongs to the statewide shift (D-03).
  • Documentation correction to D-03: "scale 1.5" is the t5 scale; the simulated sd of the shift is 0.015 x sqrt(5/3) = 1.94 share points (docs/research/2026-11-03-outside-polls).
  • Post-election refit, in order: D-13's profile and the seat-error level; sd_region / sd_type in a wave year; D-20's candidate-quality coefficient (estimable by coding 2022 and 2024 challengers). D-N3's 2% leftover is measured from the 2026 capture archive against the certified canvass.

D-M8 Undecided split by referral type: citizen-petitioned measures 0.22 (2026-11-03; Daniel's ruling, supersedes part of D-M7's ruling 14)

Evidence: 68 statewide measures 2014-2025 with final-month polls and results (51 other states, Missouri's 17; docs/research/2026-11-03-outside-the-box/measure-poll-error, contests.csv with a source per row). The result fell short of the two-way poll in 79% of contests and in 86% of citizen initiatives (status-quo bias). The model's own undecided estimator gives 0.22 pooled (80% contest bootstrap 0.125-0.302, excluding D-M7's 0.3925), 0.121 on citizen-petitioned measures (n = 44), 0.36 on legislative referrals, and 0.224 on Missouri's own six initiatives. Rule: initiatives and veto referendums (A6, Prop A) use undecided_to_yes 0.22 (data/measures/inputs.json per-measure override, read in measures.run and measure_why); legislative referrals (A3, A7, A8) keep the shared 0.3925; poll_error_sd 0.08, priors and prior_weight unchanged; --fit still fits the shared value. 0.22 rather than 0.121 because A6 carries 29% undecided, beyond the record's range, and 0.22 is the median split among high-undecided initiatives. Effect at 100,000 runs: A6 p_pass 0.785 to 0.702 (mean 0.569 to 0.545), Prop A 0.288 to 0.202 (0.452 to 0.427); A3, A7, A8 identical (fixed seed). Caveat on record: scored on Missouri's own contests alone, leave-one-date-out, the split ties D-M7 (rmse 8.29 against 8.28); the change rests on the national record, and the scorecard will say whether it earned its keep. No favourite changes; the site's recommendations are unaffected.

D-M9 Amendment 3's undecided split 0.22: the abortion-measure record (2026-11-03; Daniel's ruling)

Daniel asked for the A3 and A6 forecasts to be improved in particular (docs/research/2026-11-03-a3-a6). A6 needs nothing beyond D-M8: held out on 44 citizen-petitioned measures, 0.22 scores 5.80 against 6.61 for 0.3925, and fits that let the split depend on the undecided share give 0.25-0.27 at A6's 28.8% undecided, so neither 0.121 nor a higher value is supported. A3 is a legislative referral, which D-M8 left at the shared 0.3925; but it is an abortion measure whose Yes is the change and whose status quo is the rights amendment. On the 14 abortion measures of 2022-2024 with final-month polls, the status quo beat its poll in 12; where the change side was restrictive (Kansas 2022, Colorado Prop 115) it underran by 11.4 and 4.3 points; the fitted undecided coefficient on abortion measures is 0.087 (80% bootstrap 0-0.215, excluding 0.3925); held out one at a time, 0.3925 has rmse 5.01 and overstates the change side by 3.2 points, 0.22 has 4.22. Abortion measures referred by legislatures fit 0.00 (n 4). Rule: A3 carries undecided_to_yes 0.22 (per-measure override); A7 and A8 keep the shared 0.3925. The prior (D-M5), poll_error_sd and the polls are unchanged; the 2024 vote reweighted to any plausible 2026 electorate moves keep-rights by at most 0.3 points, so the prior's base stands. Effect at 100,000 runs: A3 p_pass 0.399 to 0.345 (mean 0.481 to 0.470, 80% range 0.376-0.586 to 0.365-0.575). Risks on record: the 2020 Missouri Amendment 3 bundling surprise (polled 29-56, passed 51) is upside risk for a bundled measure, weakened by a ballot title that leads with "Repeal"; if undecideds broke like Missouri's referrals (0.53) A3 would be 0.442. Held for after the election: D-M5's prior counts the polls twice (a corrected prior would give about 0.30), and the abortion-only coefficient 0.087 (0.30). The site's recommendation (No on 3) is editorial and unaffected; the forecast moved on evidence, not on the recommendation.

D-31 Wave-year shared errors: regional and district-type sds 0.013 (2026-11-03; Daniel's ruling)

D-06 and D-15 set the regional and district-type shared error sds at 0.0075 each, calibrated on the calm 2022 and 2024 cycles. The hand-set parameter audit (docs/research/2026-11-03-hand-set-parameters, E7, E8) measured them by cycle on out-of-sample errors: region 0.013 (2018), 0.010 (2020), 0.003 (2022), 0.003 (2024); type 0.014, 0.009, 0.002, 0.001; four-cycle RMS 0.0087 / 0.0082; and seat swings in 2016-18 were 0.049 sd against 0.015 in 2022-24. 2026 is a wave year by every pre-election measure (generic ballot D+8 to D+9, docs/research/2026-11-03-outside-polls), so the calm-year value understates how far seats move together. Ruling: sd_region = sd_type = 0.013, the 2018 level (n = 1 wave year; the honest-uncertainty principle, PRODUCT.md 3, over a single-cycle estimate's precision). No point estimate moves; the distributions widen. Effect at 20,000 runs: House P(R keeps two-thirds) 0.0885 to 0.1066 (Democrats end it: 91% to 89%), Senate 0.4587 to 0.4553, House Democratic seats 59.8 (55-65) to 60.0 (54-66), joint both-chambers 0.078 to 0.094, seats within 5-95% 21 to 25. The live model reads these sds from the published forecast file, so election night follows once the hourly run republishes. Re-estimated after certification with 2026 added (D-29's refit list).

D-M10 Amendment 3's prior no longer counts the polls twice (2026-11-03; supersedes the poll half-step in D-M5)

D-M5 built A3's prior (0.478, sd 0.05; Yes = repeal) from the 2024 vote moved by D-03's shift (repeal 45.8%) plus half of the 3.9-point gap up to the August SLU and October Remington polls (+1.95). Those two polls carry 99.5% of A3's poll weight and enter the likelihood as polls, so they set about 74% of the forecast's centre, not the 47% the "why" panel showed (docs/research/2026-11-03-a3-prior, arithmetic reproduced). Corrected prior: mean 0.457, the 2024 vote reweighted to the expected 2026 electorate (keep-rights 51.70%) moved by the same 0.784 x 3.3 shift, with no poll-based step; sd 0.06, because the one re-vote of the same question on record (Missouri's 2018 Amendment 1 at 62.0% keep, the 2020 bundled legislative repeal at 49.0%) moved 13.0 points in two years, 8.9 net of partisanship. D-M9's 0.22 split stands. Effect at 100,000 runs: A3 p_pass 0.345 to 0.304, mean 0.470 to 0.459, 80% range 0.365-0.575 to 0.348-0.570; no other measure's prior was built from its polls, so none changes; no favourite changes.

D-N7 Model projections at 97.5%; complete district probability output (2026-11-03)

Decision. Daniel requested a 97.5% model-call threshold during homepage alignment. CAL["projected_threshold"] is now 0.975 for statewide contests, MO-2 and legislative seats. Projection eligibility still requires the existing returns/coverage gate; the comparison uses unrounded probability. The frontend requires an explicit producer projection and sufficient probability/evidence, including when reading older 95%-policy snapshots. Legacy call records without probability/evidence do not qualify as current-policy projections. This changes projection labels, not the underlying simulation probabilities.

Communication. Calls are labeled Missouri Election model projections and may be withdrawn with later returns. The homepage's list is current state, not a persisted first-call chronology; its times are model-run times. Aggregate chamber and joint needles remain probabilities without a formal call state. The threshold is a policy choice, not an empirical error-rate guarantee.

Data contract. legislature.seat_estimates adds every modeled district's probability, whether its own returns have arrived, counted fraction, fraction provenance and complete flag. It uses the existing simulation draws, adds no random draws, and leaves the legacy filtered doubt list intact. This prevents a needle from reverting to the prior when a high-confidence race leaves that list. Older feeds without a usable district value show it unavailable.

Verification. Focused probability-boundary, coverage, tie, legacy-feed, provenance and full-district-output regressions accompany this change. The release return in docs/planning/2026-11-03-election-night-home/STATE.md records integration results and deployment status.

D-N8 Pre-election forecast frozen at poll close (2026-11-03)

Ruling (Daniel, 2026-11-03). From 6:50 pm Central on November 3 the scheduled hourly forecast job no longer runs. Each live capture cycle reloads data/forecast from the deploy branch before running the nowcast, and the hourly job fetches prediction-market prices into the MO-2 forecast; after polls close those prices react to the same returns the nowcast counts, which would count them twice in MO-2 and the House seats inside it. A fresh run is dispatched by hand at about 6:30 pm so the 6:55 pm pre-close snapshot carries the latest inputs. A manual dispatch still runs (deliberate corrections only). The nowcast's pre-election starting point all night is therefore the forecast published at the freeze, identical to the pre-close snapshot.

Not adopted tonight. An eastern-states signal (docs/research/2026-11-02-east-coast-signal) was weighed and dropped for election night: its effect lasts only until Missouri's own returns arrive, and it would have needed untested live scrapers. Tonight's eastern returns are to be archived as a second test night.

D-N9 "We project" calls: one automatic tier, a persisted ledger with withdrawal (2026-11-03)

Ruling (Daniel, 2026-11-03). Calls are fully automatic and carry the prefix "We project". The races are the five measures (A3, A6, A7, A8, PROPA), MO-2 (USH2), State Auditor (AUD), the House and Senate supermajority outcome, and every modeled legislative seat (docs/planning/2026-11-03-called-cards/SPEC.md).

Lead rulings. The called tier is the same everywhere: the leading outcome's unrounded probability is at least CAL["call_threshold"] (0.99) with at least CAL["call_gate"] (0.15) of the gate quantity counted, or the race is complete (an exact tie is never called). Statewide contests and MO-2 gate on pct_counted and are never called while awaiting. Seats reuse the existing per-seat called rule (D-N6, D-N7: projected, then 99% with 15% of the district's evidence gate, or complete). The supermajority is called "keep" when p_rep_supermajority >= 0.99 and "lose" when it is <= 0.01, gated on the share of the chamber's contested seats' expected vote (2024 presidential votes x the midterm drop-off) counted. Withdrawal uses hysteresis: a called race is withdrawn when its called outcome's probability falls below projected_threshold (0.975), which includes a winner flip; it may be called again later as a new ledger entry.

Data contract. model/nowcast.py keeps the ledger in <live dir>/calls.json beside batches.json (same lifecycle: it survives runner restarts, and MOLEG_LIVE_DIR isolates rehearsals and replays). It is gitignored. Each run with a returns file evaluates every eligible race, appends new calls stamped with the run's generated time, updates current_p, and records withdrawals; a run without a returns file reports the ledger unchanged. The snapshot carries calls (ordered by called_at) and calls_rule. The calls are metadata over the existing draws: they add no random draws and change no probability, share or seat count; every pre-existing nowcast figure is byte-identical (checked on the synthetic replay, all stages).

From docs/DECISIONS.md, rendered as written. Entries marked superseded or revised stay in the log; the later entry governs.