How Swim Hastings decides what to tell you
This document describes every rule the service uses, with the exact numbers.
It exists so that anyone can check our reasoning, disagree with it, and tell us
why. The rules are implemented in src/swimhastings/rules.py and the numbers
live in config/rules_config.yaml; if the code and this document ever
disagree, that is a bug and we want to hear about it. This file is published
as is at swimhastings.uk/heuristics/.
What this service is, and is not
Swim Hastings estimates when swimming at each beach along the Hastings and St Leonards frontage is more likely than usual to mean swimming in diluted sewage. It works entirely from public data: Southern Water's published storm overflow activity, Environment Agency rainfall and bathing-water data, tide predictions, and the rain forecast.
We do not test water quality. Nobody involved takes samples. A green verdict means "none of our data sources shows a problem", not "the water is clean". A red verdict means "the public data shows something we think you would want to know about", not "the water is proven contaminated". The Environment Agency's official classifications remain the only regulated assessment of these waters. Swim at your own judgment.
The numbers below are published, versioned guesses. They are informed by the general literature on bacterial die-off and by local knowledge of the frontage, but they have not been validated against water samples, because we have none. During the shadow period we compare our verdicts against Southern Water's beach warnings, the EA's forecasts, and reports from swimmers, and we tune the numbers in public, in this file's changelog.
The verdicts
- 🟢 no known issues — no rule fired.
- 🟡 caution — at least one rule fired at amber. Something in the data suggests an elevated risk.
- 🔴 avoid — at least one rule fired at red. There is an active or recent discharge affecting this zone.
When several rules fire, the worst one sets the colour and every reason is shown. Every alert and every status page entry lists the rules that fired, so you are never asked to trust a bare colour.
The zones and the outfall map
We divide the frontage into nine zones, west to east: Cooden Beach, Bexhill (Egerton Park to Galley Hill), Glyne Gap, Bulverhythe, St Leonards (Marina to Warrior Square), Hastings Pelham (pier to harbour arm), Rock-a-Nore, Fairlight and Covehurst Bay, and Pett Level with Cliff End. For each storm overflow outfall we recorded, by hand, which zones it discharges into directly and which zones a plume could plausibly reach while the tide is flooding (running broadly eastward along this coast) or ebbing (westward).
This mapping is local judgment, and we say so plainly: it is not a
hydrodynamic model. It is written down in config/beaches.yaml, one entry per
outfall, so anyone who knows this coast can challenge a specific line. The
outfall positions and identifiers come from Southern Water's published data;
the names are our own labels, because the public feed does not include names.
The feed does say which watercourse each outfall discharges into, and we
show that, verbatim and attributed, next to every outfall on the status page,
so that a local reader can test our mapping against it. Most overflows on
this coast are inland: they spill into a stream or drain, and reach a beach
only if that watercourse does. Where a watercourse drains is checked against
Ordnance Survey's flow-directed Open Rivers network
(scripts/trace_outfall_drainage.py, run over every outfall on 2026-09-05);
an overflow whose watercourse leaves the frontage, like the Pett Level marsh
sewers that reach the sea at Rye, carries no zones, and an inland overflow
carries the map of the sea outlet its water reaches, not of the beach
nearest its own position. That network knows seven outlets on this coast:
two Pevensey Levels sluices at Norman's Bay, the Combe Haven sluice at
Bulverhythe, the culverted town streams at Hastings, and the Ecclesbourne
and Fairlight glens.
The rules
R1 — active discharge into a zone → red
If Southern Water's data shows an outfall releasing right now, every zone that outfall discharges into directly goes red, and stays red until the release stops. This is the simplest and least arguable rule.
R2 — recent discharge → red, then amber, decaying over time
Contamination does not vanish when a release stops, so an ended release keeps a zone red for a while and then amber for a while longer. The windows are:
| Release length | Red after it ends | Amber until |
|---|---|---|
| longer than 1 hour | 24 hours | 48 hours after the end |
| 1 hour or shorter | 6 hours | 24 hours after the end |
For an inland overflow, "the end" is when the last of its water reaches the sea (see "Travel time" below).
Tides change how quickly the sea disperses a plume, so the windows are scaled by the tidal phase at evaluation time: on spring tides (stronger streams, faster dispersion) every window is multiplied by 0.75, and on neap tides by 1.25. Between the two, the windows apply as written.
These decay times are the most uncertain numbers in the system. Real die-off depends on sunlight, temperature, and sea state, none of which we currently model. We chose 24 and 48 hours because they bracket the advice most UK bathing-water bodies give after a discharge, and we expect to tune them. A short release puts much less into the water, so it is red for only the first 6 hours and caution for the rest of the day.
R3 — active discharge nearby, carried by the tide → amber, or red if long
If an outfall is releasing now and the current tide direction can carry the plume into a zone (per the hand-set map above), that zone goes amber. If the release has already been running for more than 3 hours, the zone goes red instead, on the reasoning that a long release puts enough into the water that adjacency stops being a comfort.
This rule needs tide data. When we have none, R3 does not fire at all, which is the less cautious direction; the status page says when we are running without tide data.
Travel time for inland overflows
Most overflows on this coast are not on the beach. They spill into a stream
some way inland, and the stream takes time to reach the sea: the Powdermill
Stream CSO at Battle is about 11 km of river from the Bulverhythe sluice,
the Cole Stream CSO at Cooden 2.5 km from the sluice its water reaches.
So for an inland outfall, rules R1 to R3 do not judge the release as the
feed reports it; they judge it shifted later by the time the water takes
to arrive. That time is the outfall's river distance (travel_km in
config/beaches.yaml, measured on Ordnance Survey's Open Rivers network)
divided by an assumed stream speed (travel_delay.stream_speed_km_h in
config/rules_config.yaml, 2 km/h). Until the first of the water is due,
the beach keeps whatever colour its other inputs give it and carries an
advisory note saying the release has happened, how far upstream, and when
to expect it. From then on R1 applies while water is still arriving, R2's
decay runs from when the last of it arrived, and R3's 3-hour escalation
clock starts when the water reaches the sea.
The speed is a published guess and deliberately a fast one: a small Wealden stream in spate runs at roughly half a metre a second. If the real water is slower than that, the beach goes red a little before it needs to, which is the right way to be wrong. Sea outfalls, and the one 300 m beach ditch at Bexhill, have no delay.
R4 — heavy rain but no reported discharge → amber
If any of the rain gauges in the catchments that drive local overflows records more than 10 mm in 6 hours, we treat the silence of the discharge feed as suspicious rather than reassuring, and every zone with no discharge signal of its own goes amber. Storm overflows exist to spill in exactly this weather, event monitors are not perfectly reliable, and reporting can lag. This rule is our answer to the known weaknesses of EDM (event duration monitoring) data.
R4 only fires when no discharge rule (R1, R2, R3) has already fired for the zone, because in that case the discharge data is evidently flowing and the rain adds nothing.
R5 — heavy rain forecast → advisory note only
If more than 15 mm of rain is forecast in the next 24 hours, every verdict carries a note saying overflows are likely and it is worth checking again before swimming. R5 never changes a colour; forecast rain is a reason to re-check, not evidence of contamination.
R6 — Environment Agency warnings → at least amber
Two EA signals each set a floor of amber for a designated bathing water: an active pollution risk forecast for the site, or a latest in-season sample exceeding our screening thresholds (E. coli above 500 or intestinal enterococci above 200 cfu/100 ml, which are the boundaries of the "good" class in the Bathing Water Regulations' coastal standards, used here as single-sample screening levels; the EA itself classifies annually, not per sample).
Only Hastings Pelham Beach, St Leonards and Bexhill are designated bathing waters, so only they can receive R6 input. Cooden, Glyne Gap, Bulverhythe, Rock-a-Nore, Fairlight and Pett Level are not sampled by the EA at all, which is itself worth knowing.
The verdict is decided by the two boolean signals alone, but the displayed reason carries the detail behind them: for a pollution risk warning, the EA's risk level and the forecast's expiry time, plus a reminder that this is the EA's daily rainfall/tide/wind prediction of reduced water quality and not a recorded storm overflow release (so no outfall will show a release when only R6 is active); for a poor sample, the sample date and the raw E. coli / intestinal enterococci counts. Each beach panel also links to the EA's own profile page for the site.
R7 — manual override
We can set a zone's verdict by hand, in either direction, and the verdict says a person set it and why. This exists for situations the rules cannot see, such as a pollution incident reported by another route. An override beats every other rule while it is active.
Staleness
The most dangerous failure for a service like this is a dead data feed silently showing a fresh-looking green. Freshness is checked per source, not just overall: each source that can raise a verdict has its own age limit (Southern Water discharge data 45 minutes, EA rainfall 45 minutes), and if any of them is over its limit — or has never delivered data at all, as on a fresh install — every verdict is flagged as delayed and the status page shows a warning banner naming the delayed source. A recent weather poll can never mask a dead discharge feed. When a Southern Water poll fails, the verdicts are still worked out again on schedule, so they pick up that flag once the 45 minutes pass, everywhere they are shown, including the Telegram and WhatsApp replies.
Southern Water's feed needs one more check, because it has no heartbeat. A row of its data changes only when that outfall starts or stops releasing, so when Southern Water's own pipeline stops upstream, the feed still answers our requests and looks exactly like a dry day: our polls succeed, and every beach would stay a current-looking green. That has happened. Southern Water's published release history, which records when each release appeared, shows the feed going silent and later catching up 48 times between April 2025 and October 2026. Most of those silences were in dry weather, when overflows rarely spill. Two were not: on 14 and 15 September 2025 the feed was silent for 31 hours while 29 releases at outfalls around Hastings went unreported, and on 23 October 2025 it was silent for nearly nine hours in a storm, with 17 more.
So the Southern Water feed also counts as delayed when it has reported no
overflow starting or stopping anywhere in its region, from Kent to Hampshire,
for 4 hours, although at least 8 mm of rain has fallen at one of our gauges
since then. Rain in the last hour is not counted, because a release takes
about that long to show up in the feed. Once the flag is raised it stays up
until the feed reports something new. As with any delayed source, every
verdict is flagged, the banner says why, and the operator is woken; no colour
is changed. We set the numbers by running the rule over that release history
and the EA's 15-minute rainfall at our three gauges: it would have flagged
both of those stalls (the first 19 hours in, when the rain came; the second
after 3.7 hours) and raised no other alarm in 18 months. The wettest silence
that was not a stall reached 6.2 mm. Silence on its own proves nothing: in
dry weather the feed has gone 53 hours without a release starting or stopping
anywhere while working normally, so a stall in dry weather is not caught.
The check is made only while our own requests are reaching the feed. If they
are failing, the feed is already flagged by its 45-minute limit, and the
silence is ours rather than Southern Water's, so we don't describe it as
theirs. The constants are staleness.southern_water_stall in
config/rules_config.yaml; scripts/measure_sw_stalls.py repeats the
measurement.
Southern Water's Rivers and Seas Watch service has a heartbeat of its own: a timestamp its pipeline rewrites every few minutes, whether or not it has anything new. It might catch a dry-weather stall, but it might not. In 16 of those 48 stalls the pipeline kept running and published old releases while the new ones waited. Through the first 20 hours of the September 2025 stall it published every 10 to 20 minutes. So a ticking heartbeat does not prove the feed current. From 14 October 2026 we record that heartbeat with every poll, to see whether it stops during a stall. It changes nothing until that has been measured.
A poll also fails when Southern Water's answer is too short to be the whole
feed. The data has one row per overflow: about 996 of them, 47 in and around
Hastings. An empty or half-loaded answer, which can happen while a dataset is
being republished, would make every overflow look quiet, and we would record a
successful poll. So an answer with fewer than 900 rows, or fewer than 40 near
Hastings, now counts as a failed poll. Only rows that carry a release start
are counted: an answer with every row present but no start times, as after a
renamed or emptied column, is just as unusable. None of it is used, the failure is
logged with the counts, and once 45 minutes pass without a good poll every
verdict is flagged as delayed, as with any feed we cannot read. Both floors
sit about a tenth below every count we have seen, so overflows added or
retired a few at a time never trip them. They are min_features and
min_features_in_bbox in config/sources.yaml. We also ask for the rows in a
fixed order, so that once the data passes 1,000 rows and arrives in pages, no
row can be skipped or repeated between pages.
The rainfall feed reads three gauges in one poll, and the EA's server answers slowly and unevenly. A poll counts as fresh when at least one gauge answers: a gauge that times out or errors is skipped for that poll and named in the poll log, and R4 reads whichever gauges did answer. Only a poll in which no gauge answers is a failed poll — that one still flags every verdict and wakes the operator.
EA bathing-water status is judged differently, because we cannot fetch it ourselves: the EA's bathing-water service refuses our server's requests, so that one source is relayed to us hourly from a machine on a home connection. How long ago we fetched it therefore measures that machine's uptime, not whether what we are showing is current. The EA's pollution risk forecast carries its own expiry — typically the following morning — so we treat the source as current while the forecast we hold is still inside it, and fall back to a one-day limit when we hold no usable expiry. A relay that stops for good is still caught: once the forecast we hold expires, the verdicts are flagged and the operator is alarmed as before.
Out of season that source cannot go stale at all. The EA issues pollution risk forecasts and takes samples only in the bathing season (15 May to 30 September), so from October to April there is nothing newer for the relay to bring, and a relay that has been off for weeks hides nothing. We treat 1 May to 1 October as the season, slightly wider than the official dates on both sides: the EA's last forecast of 2026 was issued on 1 October, and its pre-season samples are taken in early May. From 1 May the limits above apply again, with the warning banner and the operator alarm. Our own monitoring separately wakes the operator, and the status page also checks its own age in your browser, so a page our systems stopped regenerating warns you about itself.
The under-cliff walk verdict (cliff_walk)
A separate verdict, same discipline, different question: is there enough tide window to walk the foreshore under the cliffs from Rock-a-Nore past Fairlight Glen to Pett Level? People are cut off on this route every season and there are no exits between Ecclesbourne Glen and Pett Level.
The rule (src/swimhastings/cliffwalk.py, constants under cliff_walk in
config/rules_config.yaml): the route is treated as passable while the
predicted tide height at the Hastings station is below 3.0 m. From the
predicted high and low waters we compute the passable windows, then:
- 🔴 avoid — the predicted height is at or above the threshold now; the route is cut off.
- 🟡 caution — passable now, but the window closes in less than the 3 h we allow for the one-way walk plus a 1 h margin. Fine for the beach near an exit point; do not set out for Pett Level.
- 🟢 — the window outlasts the walk plus the margin.
Heights between high and low water are the same sinusoidal interpolation the status page uses — an approximation, and labelled as one. All three numbers are published guesses to be tuned against ground truth (the 3.0 m threshold in particular), and this verdict is about tide only: swell, surge and weather can close the route much earlier than the tide alone suggests. The verdict says so on every surface, and no verdict is ever shown from tide data more than 12 hours old — a missing verdict is shown as missing, never defaulted to green.
About Southern Water's own classifications
Southern Water publishes its own view of whether a release is affecting bathing waters. Where we have that classification we store it and can show it, always attributed. It never contributes to a verdict. Our reasons are structural: their classification methodology is not published in a form we can check, and an assessment of impact made by the party doing the discharging should be corroborated rather than inherited. Where we criticise their data we will do it specifically and with citations, not by assertion.
The release data itself (which outfall, when it started, when it stopped) is theirs, published under CC BY 4.0, and we depend on it gratefully. Two known limits of that feed: it reports only the most recent event per outfall, so two short releases in quick succession can appear to us as one; and while a release is in progress the feed's end-time field still shows the previous event, which we detect and treat as "still discharging".
Data sources and attribution
- Southern Water Storm Overflow Activity, © Southern Water, licensed under CC BY 4.0, via the Stream water data portal. Polled every 10 minutes.
- Environment Agency Bathing Water Quality API and flood-monitoring API (rainfall), Open Government Licence v3. Polled hourly and every 15 minutes respectively.
- Tide predictions from the UK Tidal API (Discovery tier). Contains ADMIRALTY ® tidal data: © Crown copyright and database right. The rules use only direction and phase; the status page additionally shows the next high or low water time and an estimated current height (a sinusoidal interpolation between low and high water — an approximation, and labelled as one). The licence permits showing this to you; it forbids us offering the data for bulk copying or re-publication, which we don't.
- Rain forecast from Open-Meteo. Polled every 6 hours.
- Sea and shore conditions (air and sea temperature, wind, modelled wave height) from Open-Meteo, polled hourly. These appear on the status page as comfort information only. They are not inputs to any rule: a flat, warm sea can still be contaminated, and we do not blur the two ideas.
Changelog
- 2026-10-20 (short releases). A release of 1 hour or less is now red
for 6 hours after it ends, then amber until 24 hours (new constant:
r2_decay.short_red_window_h). Before, it was red for the whole 24 hours with no amber stage. Three short releases from the Powdermill Stream overflow at Crowhurst, 5.5 km upstream (33 minutes on the evening of 18 October, then two of under a minute each on the 19th), kept Bulverhythe red for 49 hours on neap tides. Replayed under the new rule, the same releases give 16 hours of red and 33 of amber. Releases longer than an hour are unchanged. Release lengths under an hour are now given in minutes ("less than a minute", "33 min"), not as "0.0h". - 2026-10-14 (fixes after review). Four changes to the two entries below, none of which changes a colour:
- A failed Southern Water poll no longer stops the cycle. The verdicts are still worked out again, so the Telegram and WhatsApp replies flag them as delayed after 45 minutes, as the page and the app already did. Before, they kept the last verdict unflagged for as long as the polls failed.
- The stall check is made only while our own polls are succeeding. Our own outage in rain used to be described as Southern Water's feed going quiet.
- A short answer is judged on rows with a release start, so a full-sized answer with its start times missing counts as a failed poll too.
- The rows are requested in a fixed order (
orderByFieldsinconfig/sources.yaml), so pages can't skip or repeat rows. - 2026-10-14 (a short answer is a failed poll). A Southern Water poll
that returns fewer than 900 rows, or fewer than 40 in and around Hastings,
now counts as a failed poll ("Staleness" above;
min_featuresandmin_features_in_bboxinconfig/sources.yaml). Before this, an empty or half-loaded answer was recorded as a success with every overflow quiet, and with no rows the stall check below had no release times to read. The layer had 989 rows (47 near Hastings) on 25 July 2026 and 996 (47) on 14 October. No colours change, only freshness. Each poll also stores Southern Water's own pipeline heartbeat, which nothing reads yet, to measure whether it stops during a stall; the release history cannot tell us, and in 16 of its 48 stalls the pipeline was still running. - 2026-10-14 (Southern Water feed stalls). Southern Water's feed now
counts as delayed when it has reported no overflow starting or stopping
anywhere in its region for 4 hours, although 8 mm of rain has fallen at one
of our gauges since, not counting the last hour (new constants:
staleness.southern_water_stall; "Staleness" above). Its data has no heartbeat, so a pipeline that had stopped upstream used to look like a dry day: our polls succeeded and the beaches stayed green. Measured against Southern Water's published release history (April 2025 to October 2026) and the EA's 15-minute rainfall at our three gauges, the rule flags the two stalls that hid local releases in rain and raises no other alarm. Each Southern Water poll now records the newest release start or stop in the whole feed, which is what the rule reads. No colours change, only freshness. Also corrected "The zones and the outfall map", which still described five zones: there are nine, Cooden to Pett Level, and R6's list of beaches the EA does not sample now names all six. - 2026-10-02 (EA data out of season). EA bathing-water status no longer
counts as delayed between 2 October and 30 April (
staleness.ea_bwq_seasoninconfig/rules_config.yaml; "Staleness" above). The EA publishes no forecasts or samples then, so the relay that brings them has nothing to deliver, and its silence used to flag every verdict after a day. Nothing changes from 1 May to 1 October. R6 itself is unchanged: the last season's signals still apply as held. - 2026-09-05 (travel time). Inland overflows now carry their river
distance to the sea, and rules R1 to R3 see their releases shifted later
by that distance at an assumed 2 km/h (new "Travel time for inland
overflows" section above;
travel_kmper outfall inconfig/beaches.yaml,travel_delay.stream_speed_km_hinconfig/rules_config.yaml). Before this, a release at Battle turned Bulverhythe red the moment the feed reported it, though the water was five or six hours from the beach; the audit below made that gap explicit for eight outfalls, and it goes both ways, since the decay after a release also started too early. While the water is on its way the beach now carries an advisory note with the expected arrival instead of a colour. Sea outfalls are unchanged. - 2026-09-05 (outfall map audit). After the Pett Level correction we
traced every one of the 47 outfalls in the feed through OS Open Rivers,
not just the six on that marsh, asking of each inland overflow: where
does its watercourse reach the sea? Three lines of the map were wrong.
Two Powdermill Stream CSOs (SWS00031 at Battle, SWS00490 at Crowhurst)
had been filed under "Brede catchment, drains to Rye"; that is the
Sedlescombe stream of the same name. Battle's Powdermill Stream is Combe
Haven water and reaches the sea at Bulverhythe, so both now carry the
same map as the Watermill Stream CSO beside them (local to Bulverhythe,
Glyne Gap on the ebb). This is the opposite error to Pett Level: a
release there would have produced no verdict at all. The Cole Stream CSO
at Cooden (SWS00546) was mapped as discharging directly into Cooden; the
stream in fact runs west behind the beach into the East Stream and
reaches the sea through the Pevensey Levels sluice 1.5 km west, the
same outlet as the two Levels CSOs, so it now carries their flood-only
map. And the lower Combe Haven valley CSO (SWS00978) was mapped as local
to Glyne Gap as well as Bulverhythe; there is no outlet at Glyne Gap,
the river reaches the sea at the Bulverhythe sluice, so Glyne Gap moves
to the ebb adjacency, the map the Bulverhythe beach outfall at that
sluice already had. The remaining 44 lines held, including every
drains-to-Rye entry. One line OS could not settle either way: the
"Pigeon Cove Gill" outfall on the ridge above Ore (SWS00713), where the
network has no gill by that name; it stays local to Fairlight on
Southern Water's word that it discharges to a coastal gill. None of the
three corrected outfalls has released since June 2026, so no published
verdict was affected. Every outfall now carries Southern Water's
receiving-water field in
config/beaches.yaml, and the trace script covers the whole map. No rule thresholds changed. - 2026-09-05 (rainfall poll). A rainfall poll now succeeds when at least one of the three
EA gauges answers (
sources/ea_rainfall.py). Before, one gauge past its 90-second timeout failed the whole poll, and three misses in a row — the EA host is routinely slow — flagged every verdict as delayed while the other gauges' fresh readings went unread. On the morning of 5 September the page carried the delayed banner over nine green beaches for the rainfall feed alone. A poll in which no gauge answers still fails, still alarms the operator and still flags the verdicts; a gauge that is skipped is named in the poll log with its error. No thresholds changed. - 2026-09-04 (labels, receiving water). Follow-up to the entry below. The same Pett Level resident pointed out that no sewage outfall exists at Cliff End, and they were right about our label too: the outfall we had called "Cliff End outfall" (SWS00659) sits 1.7 km inland at Pett village. Southern Water's receiving-water field, which the poller had been discarding, says it discharges to the English Channel, so it reaches the sea by pipe rather than at Cliff End. It is renamed accordingly. That field is now stored with every release and shown, attributed, next to every outfall on the status page, so a local reader can test any line of our map against it. No mapping or verdict logic changed.
- 2026-09-02 (outfall map). Pett Level lost five outfalls. The Pannel
Sewer CSO and the four Marsham Sewer tributary CSOs on the Pett Level
marsh had been mapped as discharging "directly" into Pett Level, on the
cautious assumption that the marsh drains to the sea at Cliff End. A
local swimmer challenged that, and Ordnance Survey's Open Rivers network
(a flow-directed map of every watercourse) confirms it: both sewers run
east into the Royal Military Canal and reach the sea through the River
Brede at Rye, about 7 km from Cliff End, with no watercourse outlet to
the sea within 3 km of Pett Level. Those five CSOs now have no zones, so
a release there produces no verdict on our frontage (
config/beaches.yaml; the check isscripts/trace_outfall_drainage.py). Only the Cliff End sea outfall (SWS00659) still drives Pett Level. In late August the old mapping had turned Pett Level red four times for releases that went to Rye; those were false alarms and we said so to the person who asked. No rule thresholds changed. - 2026-08-31. EA bathing-water freshness now follows the forecast's own
expiry rather than a 3-hour fetch limit (
stalenessinconfig/rules_config.yaml; fallback raised to 24 hours for when no expiry is on file). That source reaches us by an hourly relay from a home machine, so the old limit measured that machine's uptime: when it slept overnight, the morning's verdicts were all flagged as delayed even though the bathing-water forecast on the page was the current one, valid until 08:29 that morning. Nothing about the verdicts themselves changed — the same inputs still produce the same colours — but a warning that fired every night for a feed that was not actually out of date was training readers to ignore the one channel that has to stay trustworthy. A genuinely dead relay still flags the verdicts and wakes the operator, once what we hold expires. - 2026-08-19 (display fix). Release start/end times in R1/R2 reasons were printed in UTC, reading an hour early during British Summer Time (the status page's events table was already UK-local, so the same event showed two different times). Reason times are now UK local everywhere. No verdict logic or thresholds changed.
- 2026-08-19. R6's displayed reasons now carry the evidence behind the booleans: risk level and expiry for a pollution risk warning (with an explicit note that it is a forecast, not a recorded release), sample date and bacterial counts for a poor sample. Both reasons can now appear together when both signals are active (previously the warning suppressed the sample text). No thresholds or verdict logic changed — the same inputs still produce the same colours.
- v1.1 (August 2026). Staleness tightened after an external code audit:
freshness is now judged per source rather than by the newest poll from any
source, so a dead Southern Water feed flags every verdict as delayed even
while weather polls succeed (new constants:
staleness.verdict_sources_max_age_min). "No data yet" now counts as stale rather than fresh. No thresholds for the discharge/rain/decay rules changed. - 2026-08-01. Added the under-cliff walk verdict (
cliff_walk: passable below 3.0 m, 3 h walk + 1 h margin, 12 h data-age limit). New surface, no change to the swim rules R1–R7. - v1 (July 2026). Initial public rule set, R1 to R7 as above. All constants are first guesses awaiting the two-week shadow period; expect this file to change and to say so.
Contains data from Southern Water Storm Overflow Activity, © Southern Water, licensed under CC BY 4.0; Environment Agency data under the Open Government Licence v3; forecast and conditions by Open-Meteo. Contains ADMIRALTY ® tidal data: © Crown copyright and database right. This service reports and interprets that public data; it does not measure water quality. Privacy.