# Holborn & St Pancras by-election: what we said, what happened

**Contest:** Holborn & St Pancras, Thursday 8 October 2026. **Forecast of record:** vintage `holborn-stp-by2026-v0.2`, formed 16 September 2026, frozen under Addendum 4. **Scored:** 11 October 2026, scoring version `by-elections-2026-10-08`.

> Bracketed fields are filled by CC from the INF-151 artifacts only (scored `calibration_ledger` row, `calibration_residuals`, `by_election_results`, `by_election_result_parties`). No other edits to this text; wording changes go back to Chat.

## In one paragraph

We said Labour would hold the seat with a lead of 23 points over Zack Polanski, 80% interval 16.6 to 29.2, and put the probability of a Labour hold above 0.99 while flagging that number as too confident for a by-election. Labour held the seat. Sagal Abdi-Wali won by 12.4 points. The winner and the runner-up were right. The margin was outside our 80% band, and so were five of the seven party lines we simulated. The forecast was right about the result and wrong about the shape of it. This document says where, by how much, and what changes.

## The result

| Candidate | Description | Votes | Share |
| -- | -- | -- | -- |
| Abdi-Wali | Labour Party | 12,292 | 45.17 |
| Polanski | Green Party | 8,928 | 32.81 |
| Cameron | Conservative Party | 1,922 | 7.06 |
| Newman | Reform UK | 1,612 | 5.92 |
| Stillman | Liberal Democrats | 924 | 3.40 |
| Johnson | Restore Britain | 692 | 2.54 |
| Galloway | Workers Party of Britain | 314 | 1.15 |
| Kapoor | Rejoin EU | 236 | 0.87 |
| Brunch | Official Monster Raving Loony Party | 87 | 0.32 |
| Spiby-Vann | Christian Peoples Alliance | 63 | 0.23 |
| Fischer | Climate Party | 51 | 0.19 |
| Walker | UK Independence Party | 51 | 0.19 |
| Pipaliya | UK VOICE | 23 | 0.08 |
| Darwood | Independent | 7 | 0.03 |
| Silberman | Communist League | 9 | 0.03 |

Labour majority 3,364 (12.36 points). Valid votes 27,211; 108 rejected; turnout 38.76%. Source: Camden Council declaration, transcribed with its page hash into the repository (`backtrack/hd/holborn/scoring/declared_result_2026-10-08.json`).

## Forecast against result

Run B of the v0.2 vintage, the headline. Error is forecast minus actual, in points of valid vote.

| Line | Forecast mean | 80% interval | Actual | Error | Inside band |
| -- | -- | -- | -- | -- | -- |
| Labour (Abdi-Wali) | 47.00 | [43.06, 50.85] | 45.17 | +1.83 | yes |
| Green (Polanski) | 24.01 | [20.94, 27.25] | 32.81 | −8.80 | no |
| Reform (Newman) | 15.73 | [14.55, 16.97] | 5.92 | +9.81 | no |
| Conservative (Cameron) | 3.50 | [3.24, 3.78] | 7.06 | −3.56 | no |
| Liberal Democrat (Stillman) | 4.78 | [4.42, 5.15] | 3.40 | +1.38 | no |
| Workers (Galloway) | 4.29 | [0.37, 7.88] | 1.15 | +3.14 | yes |
| Restore (Johnson) | 0.00 (null line) | — | 2.54 | −2.54 | — |
| Margin, Labour − runner-up | 22.98 | [16.58, 29.15] | 12.36 | +10.62 | no |
| Turnout (reporting only) | 38 | [28, 48] | 38.76 | — | yes |

Winner: Labour, forecast probability 1.0000 (flagged near-degenerate at publication). Runner-up: Green, forecast probability 1.000. Margin bucket: canter (≥ 10 points), forecast 0.994, realised at 12.36.

## What the scores say

* Winner identity: correct. Log loss 0.0000. The probability was published as >0.99 with the §6.2 flag; it is scored as recorded, not as we would now set it.
* Runner-up identity: correct.
* Margin: central 22.98, actual 12.36, error +10.62. The result lies 4.2 points below the lower 80% bound. Interval score (Winkler, α = 0.2): 54.744.
* Coverage: 2 of 8 simulated lines inside their 80% bands (Labour and Workers).
* Turnout: prior 38 [28, 48], actual 38.76. The prior moved no share; it was reporting only.

## Where the error came from

In order of size.

**1. The challenger line.** The Green line was 24.0 against 32.8. The term that carries by-election consolidation behind a challenger (spec §2(d)) was pre-registered at N(+10.9, 8.9) from the June contests. Addendum 3 (16 September) cut its coefficient to one third for this field: halved because the block it drew from had been split by Andrew Feinstein's withdrawal, then two thirds of the remainder to the focal line. On the carved Green base of 19.9 the full prior puts the line at about 31; with the Green national movement added, about 35. That is arithmetic on the base lines, not a simulation run. The damping was a ruling made blind, before any number was computed, and it cost about seven points. The run we recorded as a diagnostic — run C, which applies the national delta to the focal line as well — put Labour at 45.1 against 45.2 and the margin at 18.0 with a band [11.8, 23.9] that contains the result. We flagged that convention at v0.2 as a possible double count. It was not.

**2. The locals.** The May 2026 Camden result (Labour 32.8, Green 27.1, Camden People's Alliance 3.2, borough-wide) was a better prior for the challenger than the 2024 result plus swing. The spec gave the locals no weight. On 17 September we recorded the gap between our conditional (0.998) and the market (about 0.70) as a difference in what was being modelled, not an error in the price: the market priced direct Labour-to-Green switching, which the model has no term for. The result says that channel was real and about eight points wide.

**3. The swing convention on small lines.** Addendum 1 applied each party's national movement since 2024 as a uniform additive shift on the non-focal lines (run B, the headline). The vintage document flagged this as a known limitation for Reform, whose +8.7-point national rise was added to a 6.1-point local base. Run B had Reform at 15.7 and the Conservatives at 3.5. The result was 5.9 and 7.1. The comparator run A, which moved only the Labour line, had 7.1 and 8.3 — within 1.3 points of both. Across the four by-elections we have scored this parliament (Makerfield, Aberdeen South, Arbroath, Holborn) we have now understated the Conservative line and overstated the Reform line in every one.

**4. The carve.** Feinstein's 2024 vote (18.9) was split on his endorsement: 60% retained, two parts to Polanski and one to George Galloway. Galloway took 1.2. The block went to Polanski, or stayed at home, almost whole. A candidate with no local line and no local organisation gets about one point; the carve gave him four.

**5. Null lines.** Restore Britain was given an explicit zero: no 2024 line, no national series. It took 2.5, having taken 6.8 in Makerfield four months earlier.

**6. Spread.** Two of eight simulated lines inside their 80% bands. The flag on P(hold) said the model's spread was too narrow for a by-election. It is too narrow on every line, not only on the headline.

## What held

* Winner, runner-up and margin bucket.
* Labour's own share: 47.0 [43.1, 50.9] against 45.2.
* Turnout: 38 [28, 48] against 38.8.
* Publishing margin-led, with P(hold) flagged rather than adjusted. The flag was the right call; so was leaving the number alone.
* The vintage was pinned before polling, and the forecast file and its sha256 are unchanged from 17 September. See the freeze note below for what was not done in time.

## The market, read afterwards

Betfair prices are recorded for comparison only and never enter the model. The first capture, on 3 September, had Labour last traded at 1.40 — about 70% with the book's margin removed. On 6 October the recorded figure was 94%. On polling-day morning it was 93% (midpoint basis). The last price before polls closed was 1.03. The market settled Labour at 02:14 UTC on 9 October, with £264,839 matched across 8,856 captures.

On the probability, the market was better calibrated than we were: 0.93 is closer to a fair reading of a 12-point hold than 1.00. On direction, the model was right from 1 September and the market moved more than 20 points toward it. We record both and claim neither as skill. This is one contest, and the market's move coincided with Labour's national recovery and the Greens' difficult final week. The market priced a channel we lacked; we were overconfident on a direction that turned out right.

## A synthetic instrument, scored

Before the cut-off we pre-registered a synthetic polling instrument on this contest, recorded and not used. It is not a poll and we do not publish it as one. It places language-model respondents on a 240-cell frame of the constituency (age, sex, qualification, 2024 vote), raked from the census and the 2024 result, and aggregates their answers. Four arms: two on a local 14-billion-parameter model, two on an API model, each with and without a context pack of national polling and local facts dated 30 September. Snapshots were hashed and committed on 30 September (local) and 2 October (API), before the 7 October cut-off. Spec `HOLBORN_SILICON_SHADOW_SPEC.md` v0.1, frozen blind.

Scores against the declaration, with the forecast of record for comparison:

| Arm | Labour | Green | Con | Reform | Lib Dem | Margin (actual 12.4) | MAE, 15 lines | Runner-up |
| -- | -- | -- | -- | -- | -- | -- | -- | -- |
| Forecast of record (v0.2) | 47.0 | 24.0 | 3.5 | 15.7 | 4.8 | 23.0 (+10.6) | 2.18 | correct |
| API, with context | 37.4 | 21.5 | 4.3 | 8.8 | 13.5 | 16.0 (+3.6) | 3.11 | correct |
| API, no context | 35.6 | 18.2 | 5.7 | 7.6 | 19.2 | 16.5 (+4.1) | 3.60 | wrong |
| Local, with context | 43.4 | 5.6 | 10.4 | 11.1 | 5.7 | 32.3 (+19.9) | 3.90 | wrong |
| Local, no context | 46.2 | 5.6 | 14.4 | 3.1 | 6.2 | 31.9 (+19.5) | 4.07 | wrong |
| Actual | 45.2 | 32.8 | 7.1 | 5.9 | 3.4 | 12.4 | — | Green |

**Reading.** Every arm called the winner. The API arms beat the forecast of record on the margin and lost on the lines: they placed Labour eight to ten points low and the Liberal Democrats ten to sixteen points high, and the errors cancelled. A margin that is right for the wrong reasons is not skill. The local arms put Polanski at 5.6 against 32.8 and are unusable on a challenger line. The context pack moved the API arm three points toward the result on Polanski and six points toward it on the Liberal Democrats. Cost of the four arms: £1.64 in API calls and about three pence of electricity.

**Known limitations of this run.** Listed so a reader can see what it tests and what it does not.

* A first instrument, specified blind, with no scored event to calibrate against.
* The frame has four axes. It has no tenure, ethnicity, religion or ward, and no turnout-propensity weighting beyond a single turnout item. A proper post-stratification frame is the programme's next build.
* The local model is a 14-billion-parameter model at 4-bit quantisation, the largest the hardware runs. About 78% of its cells returned an identical answer distribution: it did not distinguish one respondent from another. That is a known failure of small models, and the flag that catches it fired as designed.
* The API model is a small, fast variant with reasoning off. Four of 720 cells in the context arm were lost to rate limits.
* The context pack predates the final week, including the Green conference motion of 4 October, and no constituency poll existed to anchor it.
* No pollster house-effect correction is stored for this instrument, so none was applied.

The programme's value bar is to beat an MRP on the same anchor and a swing model on a real election, with an ablation arm on every run. One event cannot pass or fail it. The next scored event sets the verdict; these results go into it as recorded.

## The freeze

Addendum 4 set the scored vintage as the last at or before 12:00 UK on 7 October, with its snapshot hash committed before 07:00 UK on 8 October. The vintage was pinned in the database at 12:13 UTC on 7 October and the branch carrying the pin was pushed at 12:20 UTC. The hash itself was not committed before polling: the hashing step could not canonicalise the row's candidate object and stopped for a ruling while the decider was away. The hash was committed after the result, under a ruling of 10 October that scores against it and records the gap here. The pre-result evidence is the database pin and the branch push; the committed forecast document and its sha256 (`f2683aff…`) are unchanged from 17 September. We state this because the point of pre-registration is that readers can check it, and on this contest the check is weaker than it should be.

## What changes

These are intentions, recorded now. Each lands as a dated addendum or a new spec before it is used, and never during a contest.

1. The focal line carries the national delta (run C's convention), and the consolidation prior is applied undamped for a party-leader challenger.
2. A locals-derived prior for the challenger line where the most recent locals show the challenger second across the seat.
3. Non-focal lines move multiplicatively or on the logit scale, with a regional delta where one exists, not a GB additive shift.
4. Differential turnout enters the shares; the turnout prior itself stays.
5. No null lines for a party with a declared result in any by-election this parliament.
6. The freeze path is rehearsed end-to-end on a synthetic row before the decider is unavailable, as the poll path was.

## Provenance

* Forecast of record: `freeze/holborn-stp-by2026-v0.2`, `byelection_forecasts` row 18, 500,000 draws, seed 20260901, nowcast-v2.7 read. Document sha256 `f2683affe96b4a570c70c6f863bbc0c074f28eba6b73998e89375ba6391f87c5`.
* Spec lineage: `freeze/holborn-stp-by2026-spec-v0.1` → `-ad1` → `-ad2` → `-ad3` → `-ad4` → `-ad5`.
* Declaration: Camden Council returning officer's page; transcript with page sha256 in `backtrack/hd/holborn/scoring/declared_result_2026-10-08.json`.
* Scored ledger row: `contest_id = holborn-and-st-pancras-2026-10-08`, `scoring_version = by-elections-2026-10-08`, row id 45; residuals in `calibration_residuals`.
* Market series: Betfair market 1.261869476, recorder captures 3 September to 9 October 2026, delay-key prices.
* Synthetic instrument: `HOLBORN_SILICON_SHADOW_SPEC.md` v0.1, tag `freeze/holborn-silicon-shadow-v0.1`; snapshots and md5 sidecars under `backtrack/hd/holborn/`; scoring record `backtrack/hd/holborn/scoring/scoring_2026-10-09.{json,md}`; `calibration_ledger` rows 40–43, `scoring_version = silicon-shadow-v0.1`, contest type `silicon_shadow`. Recorded, not used.

---

## Appendix — copy for the /by-elections index (CC pastes verbatim)

**Scored-forecasts line, append:** `Holborn & St Pancras ✓ (Lab >0.99 — margin band missed)`

**"What the by-elections tell us", append after the June paragraph:**

Holborn & St Pancras (8 October 2026) was the first routine vacancy in a safe Labour seat with a challenger from the left. Labour held by 12.4 points. We had the winner and the runner-up right, the margin 10.6 points too wide, and the Conservative line understated for the fourth contest in four. The post-mortem is on the Holborn page.

**Summary table, new column "Holborn":** turnout 38.8% · Con vote share 7.1% · Lab–Reform gap +39.3pp.

**Results block (same shape as Makerfield):** Labour hold — majority 3,364 (12.4%) · turnout 38.76% · rows from `by_election_result_parties`.
