Holborn & St Pancras by-election (8 October 2026)
Vintage holborn-stp-by2026-v0.2 · as of 16 September 2026 · polling day 8 October 2026 · status frozen
Labour leads by 23.0 points; 80% interval 16.6 to 29.2.
Lab - runner-up, pp of valid vote (single field, run B headline)
Forecast shares — every line on the register
single SOPN field (15 candidates: 8 simulated lines + 7 explicit zero lines); values = run B (headline) of the Ad1.3 protocol
| Candidate | Ballot description | Mean | 80% interval | P(win) |
|---|---|---|---|---|
| Abdi-Wali | Labour Party | 47.0 | [43.1, 50.9] | >0.99 |
| Polanski | Green Party | 24.0 | [20.9, 27.3] | 0.00 |
| Newman | Reform UK | 15.7 | [14.6, 17.0] | — |
| Stillman | Liberal Democrats | 4.8 | [4.4, 5.2] | — |
| Galloway | Workers Party of Britain | 4.3 | [0.4, 7.9] | 0.00 |
| Cameron | Conservative Party | 3.5 | [3.2, 3.8] | — |
| Brunch | Official Monster Raving Loony Party | 0.5 | [0.4, 0.5] | — |
| Walker | UK Independence Party | 0.2 | [0.2, 0.2] | — |
| Darwood | Independent (no description) | 0.0 | — | 0.00 |
| Fischer | Climate Party | 0.0 | — | 0.00 |
| Johnson | Restore Britain | 0.0 | — | 0.00 |
| Kapoor | Rejoin EU | 0.0 | — | 0.00 |
| Pipaliya | UK VOICE | 0.0 | — | 0.00 |
| Silberman | Communist League | 0.0 | — | 0.00 |
| Spiby-Vann | Christian Peoples Alliance | 0.0 | — | 0.00 |
Explicit-zero lines: Ad3.7 null treatment - explicit 0.0 forecast so s6.1 per-candidate scoring covers all 15
Probability of a Labour hold
Probability of a Labour hold: above 0.99 under the model’s spread. That spread is too narrow for a by-election; the number is near-degenerate, is recorded as such in the calibration ledger, and is published rather than adjusted.
Where the forecast stands
- Constituency polls used: none published as of 8 October 2026.
- Register: collapsed at SOPN on 15 September 2026 — the sole collapse trigger. 15 candidates.
- Polanski is the sole focal challenger; Galloway stands on a line carved from the 2024 Feinstein block (Ad.3).
- National-swing term: per-party on non-focal lines from v0.2; the focal line moves only through the consolidation term (Ad.1).
- Final freeze: the last vintage at or before 12:00 UK on Wednesday 7 October is the scored forecast (Ad.4).
The recorded market
Betfair prices are recorded for a post-hoc comparison only — they are never a model input. Latest recorded: 96% Labour hold (8 October 2026 at 19:13).
How to read this
This is a pre-registered forecast: the structure and priors were frozen before any number was computed, and every change since is a dated addendum that removes nothing. It is scored at declaration against the frozen vintage, on the record, whatever the result.
Vintage history
| Vintage | Date | Tag | Role |
|---|---|---|---|
| v0.1 | 1 September 2026 | freeze/holborn-stp-by2026-v0.1 | prior-only branch mixture (PARTIAL headline) |
| v0.2 | 16 September 2026 | freeze/holborn-stp-by2026-v0.2 | single field, run B headline — the forecast of record |
The lineage is append-only: a new vintage is a new row, and this page always renders the newest row of record — no frontend change is needed when one lands.
Provenance
- Spec lineage:
freeze/holborn-stp-by2026-spec-v0.1→freeze/holborn-stp-by2026-spec-v0.1-ad1→freeze/holborn-stp-by2026-spec-v0.1-ad2→freeze/holborn-stp-by2026-spec-v0.1-ad3→freeze/holborn-stp-by2026-spec-v0.1-ad4→freeze/holborn-stp-by2026-spec-v0.1-ad5 - Vintage:
freeze/holborn-stp-by2026-v0.2· forecast row id 18 · 500,000 draws · seed 20260901 · common random numbers across vintages · headline run per Ad1.3 - Nowcast read: nowcast-v2.7 (model_registry is_current; Ad1.5)
- The frozen document: raw markdown (served byte-identical to the committed file) · the committed file on GitHub · sha256
f2683affe96b4a570c70c6f863bbc0c074f28eba6b73998e89375ba6391f87c5
The frozen vintage document, verbatim
forecasts/byelections/holborn-and-st-pancras-2026-10-08-v0.2.md — reproduced without alteration.
# Holborn & St Pancras by-2026 — v0.2 vintage (SOPN-collapse, prior-only) — 2026-09-16 **Version tag:** `holborn-stp-by2026-v0.2` · **Formed:** 2026-09-16 (INF-48 session) **Governing spec:** `HOLBORN_STP_BY2026_SPEC.md` v0.1 + Ad.1 + Ad.2 + **Ad.3**, tag `freeze/holborn-stp-by2026-spec-v0.1-ad3` (merge `1da8704`, blob `4f64412c`) — Ad.3 committed and tagged **before** this engine pass (ruling condition (i)); implemented exactly as written. **Engine:** `analysis/holborn_stp/holborn_stp_v02_model.py` · seed **20260901** (dated-seed convention, unchanged from v0.1) · **500,000 draws** · CRN — v0.1's term streams (a, c, k) drawn in v0.1's exact order, **one new stream g appended** (Workers entry variance, Ad3.8); stream identity with v0.1 asserted in-engine, and the v0.1 engine re-run before this pass reproduced `holborn_stp_v01_results.json` byte-identically. Run differences are structural, never sampling noise. **Election date:** 2026-10-08 (Ad.2; rows from Ad.2 onward carry the real date). **Prior-only:** the §5 gate is unfired — `constituency_polls` (id 290) = 0 rows, checked 2026-09-16; no published VI poll known (Ad.3 pre-registration statement). **Market-blind:** no price, odds, or implied probability entered any input path. **Results of record:** this file + `holborn_stp_v02_results.json`. Byte custody: directory is scoped `* -text`. --- ## Register collapsed — residual R realised; headline no longer PARTIAL SOPN published 2026-09-15 (Camden Council; 15 candidates; Feinstein not on the paper). The field falls to **R** per the 2026-09-16 STOP report; the 2026-09-16 ruling (Ad.3) defines its treatment. All subsequent vintages are **single-field** on the SOPN set. The v0.1 PARTIAL label is resolved: the residual is no longer an unsimulated branch — it is the field. --- ## 1. Inputs of record **Field (Ad3.1/Ad3.7):** 8 simulated lines — Lab, Green (Polanski, **focal**), **Workers (Galloway, carved)**, Con, Reform, LD, OMRLP, UKIP; **7 explicit zero lines** — Climate, Rejoin EU, UK VOICE, Communist League, CPA, Restore Britain, Darwood (Ind); exits to abstention — Feinstein remainder (0.4 of block), Islam (Ind), SEP, Kumar (Ind), Smith (Ind). **Carve (Ad3.4):** Feinstein block 18.94 pp (7,312 votes) → retention 0.6 = 11.37 pp (4,387.2), split **2:1 Polanski:Galloway** on the endorsement: Polanski transfer **7.58 pp** (2,924.8) onto the Green line; Workers line **3.79 pp** (1,462.4). Remainder 7.58 pp exits per §2(ii). Renormalised bases: Lab 54.08 · Green 19.92 · Workers 4.19 · Con 7.95 · Reform 6.79 · LD 6.40 · OMRLP 0.46 · UKIP 0.21. **Terms (spec §2 + Ad.3), single field:** | Term | Value | Applied to | |---|---|---| | (a) vacancy | N(−1.5, 2.0) pp | Lab, all runs | | (b) national swing | per-run delta map below (uniform additive, Am.A1/Ad1.1) | see runs | | (c) succession bounce | N(+3.0, 4.0) pp | Lab, all runs | | (d) consolidation | N(+10.9, 8.9) pp floored at 0, **coefficient 1/3** (damped ×0.5, focal's 2/3 share — Ad3.5) | Green (Polanski), sole focal | | Workers entry | N(0, 3.0) pp on the carved base, line truncated at 0 (Ad3.4) | Workers only | | (e) turnout | central 38, 80% [28, 48] — **reporting only** | share-neutral | **Nowcast vintage (2026-09-16, SNAPSHOT, strict `<`, nowcast-v2.7 per Ad1.5 — `model_registry` is_current verified; n=26, oldest 2026-06-29, house effects off)** vs GE-2024 GB baselines: | Party | Nowcast | GE24 GB | Δ (pp) | Run A | Run B | Run C | |---|---:|---:|---:|---|---|---| | Lab | 25.6 | 34.7 | **−9.1** | applied | applied | applied | | Con | 19.9 | 24.4 | −4.5 | — | applied | applied | | Reform | 23.4 | 14.7 | +8.7 | — | applied | applied | | LD | 10.8 | 12.5 | −1.7 | — | applied | applied | | Green | 11.1 | 6.9 | +4.2 | — | — (focal, (d)-only) | applied (diagnostic) | | SNP | 2.8 | 2.6 | +0.2 | — | — (no line) | — (no line) | Workers, OMRLP, UKIP: no nowcast series — no (b) delta in any run (Ad3.6). Zero (b)-floor events in all runs. Workers truncation clipped 8.1% of draws (the ruled truncation at 0, not an Ad1.1 floor event). **Mechanics:** restrict + carve → renormalise → apply pp terms → clip at 0 → renormalise (spec §2 (i)–(iv)). **Canter boundary unchanged: margin ≥ +10 pp.** --- ## 2. Run outputs (Ad1.3 protocol, focal = Polanski) *One MC pass per run; the three runs share the CRN streams and differ only in the term-(b) delta map. Run B is the headline regardless of what C shows (Ad1.3).* ### Run A — comparator: Lab-only (b), frozen §2(b) as v0.1 · P(Lab hold) **1.0000** | Line | Mean | 80% | P(win) | |---|---:|---|---:| | Lab | 48.22 | [44.19, 52.16] | 1.0000 | | Green (Polanski, focal) | 24.64 | [21.48, 27.96] | 0.0000 | | Workers (Galloway) | 4.40 | [0.38, 8.08] | 0 | | Con | 8.29 | [7.65, 8.96] | 0 | | Reform | 7.08 | [6.53, 7.65] | 0 | | LD | 6.67 | [6.16, 7.21] | 0 | | OMRLP · UKIP | 0.48 · 0.22 | | 0 | Margin 23.58 [17.02, 29.90] · canter 0.9948 · runner-up Green 1.000 ### Run B — **HEADLINE**: Ad1.1 per-party on non-focal lines · P(Lab hold) **1.0000** | Line | Mean | 80% | P(win) | |---|---:|---|---:| | Lab | 47.00 | [43.06, 50.85] | 1.0000 | | Green (Polanski, focal, (d)-only) | 24.01 | [20.94, 27.25] | 0.0000 | | Workers (Galloway) | 4.29 | [0.37, 7.88] | 0 | | Con | 3.50 | [3.24, 3.78] | 0 | | Reform | 15.73 | [14.55, 16.97] | 0 | | LD | 4.78 | [4.42, 5.15] | 0 | | OMRLP · UKIP | 0.47 · 0.22 | | 0 | Margin 22.98 [16.58, 29.15] · canter 0.9941 · runner-up Green 1.000 *(Reform's +8.7 delta on a 6.14-pp base is the Ad1.7 known limitation — recorded, not adjusted.)* ### Run C — diagnostic: per-party including the focal line · P(Lab hold) **0.9998** Lab 45.08 [41.27, 48.80] · Green 27.12 [24.15, 30.24] (P(win) 0.0002) · Workers 4.11 [0.35, 7.57] · Con 3.36 [3.12, 3.61] · Reform 15.09 [14.00, 16.23] · LD 4.58 [4.25, 4.93] · margin 17.95 [11.75, 23.94] · canter 0.9475. --- ## 3. Headline (run B — single field, NOT PARTIAL) | Quantity | Value | |---|---| | **P(Labour hold)** | **1.0000** (4 dp; near-degenerate, flagged per §6.2 — P(upset) < 5×10⁻⁵) | | P(canter: margin ≥ 10) | 0.9941 | | P(contested hold: 0 < margin < 10) | 0.0059 | | P(upset: challenger wins) | 0.0000 (4 dp) | | Lab share | 47.00, 80% [43.06, 50.85] | | Margin (Lab − runner-up) | 22.98, 80% [16.58, 29.15] | | Runner-up | Green (Polanski), 1.000 | --- ## 4. Decomposition (Ad1.3/Ad3.8) vs v0.1 PARTIAL headline of record | Effect | Definition | ΔP(hold) | ΔLab mean | ΔMargin | ΔP(canter) | |---|---|---:|---:|---:|---:| | **Candidate-set effect** | A(v0.2) − v0.1 (R-carve sits inside this effect) | **+0.0535** | +3.47 | +4.30 | +0.2116 | | **Convention effect** | B − A (Ad1.1 alone) | 0.0000 | −1.22 | −0.60 | −0.0007 | | **Focal-line sensitivity** | C − B (diagnostic; cannot change Ad1.1 in-arc) | −0.0002 | −1.92 | −5.03 | −0.0466 | The v0.1 → v0.2 move is almost entirely the candidate-set collapse: the hinge branch **B2 (Feinstein stands without Polanski, 0.38 weight, the only branch whose 80% margin interval crossed zero) did not realise**. The Ad1.1 convention costs Labour 1.22 pp of mean share and nothing measurable in win probability. The double-count question (C − B): applying the focal's national delta on top of (d) would move the margin −5.03 pp and P(canter) −0.0466 — recorded as an Ad1.3 finding for the post-mortem, not a re-ruling. --- ## 5. Sensitivity lines (Ad3.5 — base-line arithmetic only, no MC pass; reported, not adopted) | Split Polanski:Galloway | Transfer (pp 2024) | Workers carve (pp 2024) | Green base (renorm) | Workers base (renorm) | |---|---:|---:|---:|---:| | **2:1 (adopted)** | 7.58 | 3.79 | 19.92 | 4.19 | | 1:1 (bracket) | 5.68 | 5.68 | 17.82 | 6.28 | | 3:1 (bracket) | 8.52 | 2.84 | 20.96 | 3.14 | The (d) coefficient would move with the ratio under the same mechanic; it is not recomputed (Ad3.5). --- ## 6. CRN proof + turnout Streams sha256/16: a `e6eae8fa4db4f093` · c `629d947102a5f0be` · k `bdc72985e4cd42df` · **g `824894b907fab0a3` (appended)**. In-engine assertion: a/c/k byte-identical to a fresh generator run of v0.1's draw sequence; v0.1 engine re-run 2026-09-16 reproduced its tracked JSON byte-identically (git diff empty). Run A thereby reproduces v0.1's Lab-only draws at stream level (Ad3.8). Turnout: reporting prior 38% [28, 48] of electorate; conditional map **degenerate at this vintage** (share-neutral §2(e)); stated, not silently skipped. --- ## 7. Row of record + revision protocol `byelection_forecasts` row, model_version `holborn-stp-by2026-v0.2`, status `live`, `frozen` FALSE, `election_date = 2026-10-08` (Ad.2 — no pre-writ sentinel). Insert migration `supabase/migrations/20260916170000_holborn_stp_by2026_v02_vintage.sql`, applied at/after merge under merge-and-report with a rolled-back trial insert first. Annotated vintage tag `freeze/holborn-stp-by2026-v0.2` on the merge commit (Clacton vintage-tag naming). The v0.1 row (id 16) is untouched — append-only. Revisions per spec: weekly vintage refresh owned by the weekly check; first constituency poll → §4 protocol (the §5 gate has then run; v0.3 pre-poll freeze per Ad1.3 runs B only); all appends, never edits.