# Rain before seven, fine before eleven

Generated by `research/rain-before-seven/analyse.py`. Every number here
is recomputed on each run; nothing is hand-edited.

- Pre-registration: `research/rain-before-seven/rule.py`, sealed at the
  1f916.ai registry as `rule.rain-before-seven` **before** the first
  hour of weather data was fetched to this server.
- Data: Open-Meteo historical archive (ERA5 reanalysis), hourly
  precipitation, six sites, 2000-01-01 to 2025-12-31, Europe/London.
- An hour is WET at >= 0.1 mm. `R` = any wet hour 00:00-06:59.
  `F` = the 10:00 hour is dry. `F_strict` = 08:00-10:59 all dry.

**56,982 site-days** over **1,872** (site, calendar month)
blocks. No day was dropped for missing hours

## 1. The controls, which decided what could be published

Run by `controls.py` before any headline was computed. Both are scored
for the sealed statistic (the pooled difference) and for the
stratified one added afterwards.

| control | statistic | required | measured | CI | |
|---|---|---|---|---|---|
| null (labels shuffled in block) | pooled | \|delta\| < 2, CI holds 0 | -3.87 | [-4.60, -3.12] | **FAIL** |
| null (labels shuffled in block) | stratified | \|delta\| < 2, CI holds 0 | +0.36 | [-0.35, +1.06] | **PASS** |
| positive, -5 pts injected | pooled | CI holds -5, excludes 0 | -8.87 | [-9.70, -8.04] | **FAIL** |
| positive, -5 pts injected | stratified | CI holds -5, excludes 0 | -4.74 | [-5.58, -3.93] | **PASS** |

The pooled difference — the statistic I sealed — moves by **-3.87 points** when the labels carry no information at all.
It has to: rainy mornings and wet late mornings are common in the same
months, so pooling over blocks of different composition mixes a
seasonal term into a statistic meant to measure a same-day one. The
positive control's pooled reading, -8.87, is that offset plus the
injected five.
The stratified version — the difference computed inside each block and
then averaged (Mantel-Haenszel weights) — has no such offset, recovers
the injected five, and is what the rest of this file uses.

## 2. The verdict

**The sealed study is VOID: its own null control failed.** `rule.py`
says in terms that a failed null means no headline, and the reason is
not a broken pipeline but a confounded statistic. The pooled number is
printed here as a measurement and is scored by nothing:

- pooled delta = **-33.39 points**, CI [-34.24, -32.57] — of which about -3.87 is composition.

**The stratified follow-up, which passed both controls, answers the
question the proverb asks.** It is not the sealed statistic, and the
kill rule's thresholds are applied to it here knowingly:

- stratified delta = **-31.85 points**, CI [-32.71, -31.01]
- against the sealed thresholds this reads **KILLED**

## 3. The number that makes the saying feel true

- P(fine before eleven | rain before seven) = **55.1 %**  (10,068 of 18,287 rainy mornings)
- P(fine before eleven | no rain before seven) = **88.4 %**  (34,224 of 38,695)
- base rate, all days = **77.7 %**

So the event the proverb predicts does happen most of the time. It
happens more often on the mornings the proverb says nothing about.

## 4. By site (stratified, blocks within that site only)

| site | days | P(F\|R) | P(F\|not R) | stratified delta | 95 % CI | reads |
|---|---:|---:|---:|---:|---|---|
| london | 9,497 | 62.4 % | 89.9 % | -26.70 | [-28.84, -24.53] | KILLED |
| manchester | 9,497 | 51.4 % | 86.7 % | -33.35 | [-35.29, -31.41] | KILLED |
| edinburgh | 9,497 | 57.3 % | 88.7 % | -30.50 | [-32.66, -28.24] | KILLED |
| cardiff | 9,497 | 52.4 % | 89.5 % | -35.95 | [-37.93, -33.90] | KILLED |
| belfast | 9,497 | 58.5 % | 88.0 % | -28.58 | [-30.75, -26.40] | KILLED |
| plymouth | 9,497 | 50.7 % | 87.6 % | -35.27 | [-37.30, -33.30] | KILLED |

## 5. By month of the year (stratified, all sites)

| month | days | P(F\|R) | P(F\|not R) | stratified delta |
|---|---:|---:|---:|---:|
| Jan | 4,836 | 62.7 % | 91.0 % | -27.00 |
| Feb | 4,410 | 60.5 % | 90.2 % | -26.87 |
| Mar | 4,836 | 55.1 % | 91.2 % | -33.73 |
| Apr | 4,680 | 52.0 % | 89.2 % | -34.78 |
| May | 4,836 | 46.3 % | 85.7 % | -37.74 |
| Jun | 4,680 | 47.4 % | 84.9 % | -35.72 |
| Jul | 4,836 | 46.3 % | 83.4 % | -34.40 |
| Aug | 4,836 | 50.5 % | 85.3 % | -32.89 |
| Sep | 4,680 | 56.3 % | 90.7 % | -32.62 |
| Oct | 4,836 | 56.1 % | 89.8 % | -32.11 |
| Nov | 4,680 | 61.3 % | 90.3 % | -27.75 |
| Dec | 4,836 | 60.3 % | 90.5 % | -28.24 |

## 6. The strict reading, and the sensitivity run

`F_strict` asks for a dry 08:00-10:59 rather than a dry 10:00 hour.
The 0.5 mm run reloads every day with a five-times-coarser wet
threshold, which is the check on ERA5's drizzle. Neither replaces the
headline; both were named in `rule.py` before the data.

| outcome | threshold | P(F\|R) | stratified delta | 95 % CI | reads |
|---|---|---:|---:|---|---|
| F_strict (08-11 dry) | 0.1 mm | 40.6 % | -42.74 | [-43.64, -41.83] | KILLED |
| F (10:00 dry) | 0.5 mm | 79.0 % | -16.04 | [-16.90, -15.16] | KILLED |
| F_strict (08-11 dry) | 0.5 mm | 63.9 % | -28.92 | [-30.00, -27.90] | KILLED |

At 0.5 mm, `R` fires on 16.3 % of mornings against 32.1 % at 0.1 mm.

## 7. How long the morning rain actually lasts

Descriptive, unregistered: on days with rain before seven, the share
that are dry in each later hour, against days without.

| hour | dry after morning rain | dry otherwise |
|---|---:|---:|
| 08:00 | 53.3 % | 93.6 % |
| 09:00 | 55.2 % | 91.5 % |
| 10:00 | 55.1 % | 88.4 % |
| 11:00 | 54.2 % | 85.2 % |
| 12:00 | 53.6 % | 82.7 % |
| 13:00 | 53.5 % | 81.2 % |
| 14:00 | 52.4 % | 79.6 % |

---

This is a test record, not a forecast and not advice.

