# 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.
