<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# What has not been tested

This page lists, in one place, every claim this repository makes that has not been
checked. For each it gives:

* what was checked instead;
* what would close the gap;
* where the gap is noted alongside the code.

A claim that is tested only on the simulated farm is marked as such, because a simulator
never satisfies §9.2. When an item is checked, move it to the end with the date and a
link to the evidence; do not delete it.

## Needs hardware or a farm

| Not tested | Checked instead | What would check it | Noted in |
| --- | --- | --- | --- |
| **Sending and receiving SMS through a real modem**: `mmcli` creating, sending and deleting a message; reading replies; a long Spanish text arriving as one joined message; the sender's number in the format a real network gives it | The commands and their JSON as ModemManager 1.23's source defines them (`cli/mmcli-output.c`, `cli/mmcli-modem-messaging.c`), against a fake that answers the same way | A modem ModemManager supports, with a SIM, on the gateway: send to a phone and reply to it (Q29's first step) | [modules/notify](../modules/notify/README.md) |
| **ModemManager letting the notifier's service user send**, which polkit decides | Nothing | The same modem, with the notifier running as its own systemd service rather than as a person | [modules/notify](../modules/notify/README.md), [deploy/systemd](../deploy/systemd/README.md) |
| **An OpenSprinkler controller's messages**, read by the MQTT bridge's profile | The topics and payloads as its firmware formats them (`services/notifier.cpp`, `services/mqtt.cpp`), read from its source; an emulator sending the same | A controller on the farm's MQTT broker, a zone run by hand, and the log read back | [sdk/mqtt_bridge.py](../sdk/mqtt_bridge.py), [notes/irrigation-projects](notes/irrigation-projects.md) |
| **The zone flow check on a real zone**: the usual flow a meter's runs teach it, and a clogged or broken head said from them; with a gauge, each run taken to one pressure | 300 simulated seasons, the supply pressure wandering ±10% and the meter ±2%, the gauge within 1% (`zoneflow.drill`); head flows from Rain Bird's charts, not measured heads | A pulse meter on an OpenSprinkler, one zone run through a season with a nozzle capped and a head removed on known days, the alerts read back | [modules/zoneflow](../modules/zoneflow/README.md), [notes/water-meters](notes/water-meters.md) |
| **A weather station heard off the air by `rtl_433`**, through the bridge's `rtl_433` profile | The decoder's field names and MQTT topics as its source and documentation give them (`src/devices/fineoffset.c`, `docs/OPERATION.md`), against an emulated event | An RTL2832 dongle on the gateway, a Fine Offset station in range, `rtl_433 -M time:unix -F mqtt`, and the log read back | [sdk/mqtt_bridge.py](../sdk/mqtt_bridge.py), [notes/weather-stations](notes/weather-stations.md) |
| **An ATMOS 41 Gen 2 on a real RS-485 line**, through the Modbus collector | Its register map, serial settings and burst-read rule from METER's Integrator Guide (rev. 05), against a fake station answering RTU frames over a pseudo-terminal | A Modbus-enabled ATMOS 41 Gen 2, a USB RS-485 adapter on the gateway, a day of polls read back beside the station's own logger | [sdk/modbus_collector.py](../sdk/modbus_collector.py) |
| **A Tempest, a WeatherLink Live and an Ecowitt gateway on a farm's network**, through the station adapters | Each maker's documented messages (WeatherFlow's UDP reference v171, Davis's local API reference, Home Assistant's Ecowitt library's field names) over real sockets on loopback | Each station on a LAN with the adapter, a day of readings read back beside the maker's own app | [sdk/station_adapters.py](../sdk/station_adapters.py) |
| **A real radio and a real device driver** (build step 7) | Meshtastic chosen on paper (Q6); a Modbus RTU driver over a pseudo-terminal; a real station's feed (McAllister Farm's SCAN station) through layer zero every six hours | One Meshtastic node with one sensor, through a season | [README](../README.md) |
| **A growing season on a real farm** (§9.2), which every reliability claim waits on | The simulated farm, Harrow Bend, and recorded seasons from public stations | The pilot (Q1): two sites, decided by February 2027 to install before spring | [README](../README.md), [Q1](spec/open-questions.md) |
| **The depth check under a cover**: whether real mulch, sod or plastic damp a probe's daily wave as the simulator's mulch does, and whether peers under the same recorded cover calibrate it | The simulator's mulch, five centimetres of wood-chip diffusivity: unrecorded, a probe at 10 cm read as 19.3 cm and was flagged moved; recorded, it read true against mulched peers | Probes at two or three depths under mulch and under bare soil in one field, a week of temperatures | [sdk/siting.py](../sdk/siting.py) |
| **The thresholds**: a trough's empty, low and refill marks; the soil advisory's readily available water; the frost watch's 0 °C | Simulated troughs; one recorded summer for the soil advisory (2013); one frost season (2025–26) | A season of a real farm's troughs and beds, with the farmer saying which alerts were right | [§15](spec/v0.1.md), [modules/water](../modules/water/README.md), [modules/soilwater](../modules/soilwater/README.md) |
| **A real ensemble forecast at the farm** | A simulated ensemble on thirty recorded springs: its chance of frost beat a single forecast's margin at every setting. Its error and spread are the simulator's own | A season of ECMWF's open ensemble or NOAA's GEFS collected for McAllister Farm and scored against the SCAN station | [notes/forecasts.md](notes/forecasts.md#ensembles-a-chance-in-place-of-a-margin-q26) |
| **The watering check on a real bed**: whether half the expected rise is the right line for a real drip line, soil and probe depth | Two recorded summers through the simulated bed, with waterings blocked on purpose: every blocked one caught; on the simulator of 2026-10-16, one watering of 61 in 2012 rose only 0.47 of its expected rise and was wrongly flagged (on the simulator before, it came within 0.05 of the line) | A season of a real bed's waterings, with the farmer noting the ones that did not arrive | [modules/soilwater](../modules/soilwater/README.md#did-the-water-arrive) |
| **Field capacity learned from a bed's own probes, and the layered-soil note**, by the upper quartile of the drain-downs | The simulator's yard, sandy topsoil over compacted clay with assumed values, on two recorded summers. On the survey's values one topsoil probe drowned it, and learning cut the water by three fifths. With a probe in each layer, learning alone did not help; each layer's values did. On the simulator of 2026-10-16 a lawn by one probe, learning by the median, was short in every summer of 30; by the upper quartile, with the other changes of that day, in 1 or 2. The shape of each drain-down, and the probe's noise, are the simulator's | A yard or raised bed with probes at two depths through a season of waterings and rain, and a soil test of each layer to set beside what was learned | [modules/soilwater](../modules/soilwater/README.md#the-beds-own-soil) |
| **The lawn add-ons' scores**: what a rain sensor, a soil sensor at a given set point, weather-based adjustment, cycle and soak and rotary nozzles do for a real lawn's water and health | Thirty recorded summers through the simulator's lawn, on an assumed silt loam and an assumed layered yard, with turf that grows no roots and heads that water evenly; beside published plot and home studies from Florida, on bermudagrass | A season of a real lawn's zones, metered, with a probe and the turf's condition recorded | [notes/lawn-sprinklers](notes/lawn-sprinklers.md) |
| **The clear-sky check on a farm's own station**: its margins on a cheap station's light sensor, and on readings of a moment rather than hourly means | A reference station's calibrated pyranometer (NOAA's Crossville, Tennessee, 2022–2024), with clock, unit and gain faults put in by hand | A season of a farm station's sunshine beside a pyranometer | [notes/weather-stations](notes/weather-stations.md) |
| **The checks' thresholds on a cheap capacitive probe**, and the soil-sensor recommendations | Two networks of Stevens Hydra Probes scored against ISMN's flags (SCAN and NOAA's USCRN, in and around Tennessee); a probe's bias put into the simulated bed | Two cheap probes and a calibrated one in one bed through a season, the checks' flags read against the calibrated probe | [notes/soil-sensors](notes/soil-sensors.md) |
| **Advice by the weather for a bed with no probe**, and its margin, the crop's use counted a fifth above FAO-56's estimate (`WEATHER_MARGIN`) | Thirty recorded summers through the virtual beds, the station's readings drawn from the same recorded weather and the beds' water loss a different formula from the balance's, about a fifth more than it counts: no bed whose crop is named short with the margin, 21 summers of 30 short without it on the backtest bed; where the balance was not low, a sixth to a quarter more water. How far a real station's balance is from a real bed, and which way, is not known | A season of a bed with a station and a probe both, the probe kept out of the advice and read against it | [modules/soilwater](../modules/soilwater/README.md#by-the-weather-with-no-probe) |
| **A probe in one bed correcting the weather balance of another**: whether the rate a real probe sees its bed dry carries to a bed nearby; never below the margin | Thirty recorded summers through two virtual beds of one soil and crop, one probe-led and one advised by the corrected balance, with the probe true, 0.05 high and 0.05 low (`weather_backtest(reference=True)`): on the simulator of 2026-10-16 the reference seldom read faster than the margin, and corrected little. A day that began wetter than field capacity counted drainage as the crop's use, and is left out since 2026-10-17. Through the 2012 drought, taken below the margin, its rate left a bed short 33 hours: the balance, stepped once a day, needed the margin even at a true rate | Two beds of one crop on one station, each with a probe; one bed advised by the corrected balance with its own probe kept out of the advice and read against it | [modules/soilwater](../modules/soilwater/README.md#a-probe-nearby-corrects-the-balance) |
| **Sowing advice from a bed's soil temperature**: whether a seed sown when the advisory says "good" comes up, and in about the days it says | Harrington's constant-temperature tables (1954) read into the advice, and a simulated soil swinging each day; nothing sown | A season of sowings in a bed with a probe at 5 cm, the date each crop came up counted against the advice's days | [modules/sowing](../modules/sowing/README.md) |
| **Watering a day early when a bed would be short by tomorrow, and a second look at 13:00**: whether a real shallow bed's next-day drying is what its last day's was | Thirty recorded summers on two simulated beds (on the earlier soil, the yard short in 4 summers instead of 18, for 7% more water). On the simulator of 2026-10-16 the yard is short in 19 to 22 summers even so, and in 4 to 7 watered at a fifth of its water gone | A season of a shallow bed with its probe, the hours past half its water counted | [modules/soilwater](../modules/soilwater/README.md#the-beds-own-soil) |
| **A crop that grows: FAO-56's crop coefficient and roots through the season**, the 2025 revision's coefficients and roots for 20 crops (lawns still the 1998 edition's), a probe at the roots' front left out, and the young crop's refill point (`Bed.young_fraction`) | Thirty summers of tomatoes and lettuce sown on 1 May, the virtual crop growing by the same curve the advice is told, three draws. On the simulator of 2026-10-16: by the weather, never short; by probes at 10 and 30 cm, short in 5 to 8 summers (tomatoes) and 8 to 15 (lettuce), the hours in the days after the initial stage ends, roots still 15 cm; not knowing the crop, short in two summers of three by probes. On the soil of 2026-10-15, never short | A season of a sown crop with probes at three depths, its roots dug at mid-season and its stages dated, beside the curve | [modules/soilwater](../modules/soilwater/README.md#a-crop-that-grows) |
| **Roots that stop: the rooting limit and the probes' root signs**, the 0.002-a-day level line, the 0.02 under field capacity that counts as roots, the 15 cm the curve must be past a probe, and a stop held on 3 mornings of 7 | Thirty summers of tomatoes in the simulator's silt loam with the roots stopped at 30 cm, probes at 10, 30 and 60 cm, three draws. On the soil before 2026-10-15 the curve alone was short in 29 summers and the signs cut that by more than 99%. On the simulator of 2026-10-16, over a dense pan, the curve alone was short in 10 to 18 summers, the signs 9 to 12, the rooting limit set 6 to 9; but with roots densest at the top the signs see a stop on 74 to 87 of 145 mornings with or without a pan. Whether they earn their place over a real pan is not known | A bed over a known pan or a raised bed's floor, with probes above and below it through a season, and the roots dug at mid-season | [modules/soilwater](../modules/soilwater/README.md#roots-that-stop), [notes/root-depth](notes/root-depth.md) |
| **A range of roots: watering timed by the shallow end, refilled to the deep**, for a stop and for plantings at different stages side by side (`Bed.plantings`), and probes named for their planting | Thirty summers, three draws: tomatoes with lettuce sown among them six weeks later, each in its own patch watered alike. On the simulator of 2026-10-16, whose bare patch dries at its surface: told the tomatoes alone, the lettuce was short in 22 summers by the weather and 22 to 24 by probes; told both, never by the weather and 2 to 5 by probes. An unnamed probe in the lettuce's patch, which on the simulator before left the tomatoes short in 6 to 8 summers, now misleads little | A bed of two plantings weeks apart, a probe among each, through a season, the young plants' state recorded | [modules/soilwater](../modules/soilwater/README.md#plantings-at-different-stages) |
| **A crop's clock by the season's warmth**: the 2025 revision's thresholds (Table 6.10) and field-observed degree-days for 10 crops (Table 6.11), and for the other 10 the 1998 days taken as right for the farm's normal year | Thirty summers on the virtual farm whose crop goes through its curve by the same degree-days: about the same water on average, −13% to +9% in single years, never short either way; the virtual crop follows the clock by construction. The revision's degree-days are field observations elsewhere, for cultivars it does not name | A season's crop dated at its stages (full cover, first harvest) beside the clock's days and the calendar's | [modules/soilwater](../modules/soilwater/README.md#by-the-seasons-warmth) |
| **A bed under cover**: `Bed.rain_share`, and a covered bed seen by its probes through three storms of 15 mm while its valve stayed shut | Thirty summers of the backtest bed under a tunnel with the open sky's forecasts, three draws: told, short in at most 2 summers for an hour, and never held for rain; not told, 0 to 3 summers for up to 55 hours; learning, held on a quarter to a third fewer mornings; an open bed never taken for covered. The simulator's rain falls in one spell a day | A tunnel bed and an open one on one farm, with a rain gauge and valves that report, through a season | [modules/soilwater](../modules/soilwater/README.md#hot-days-and-beds-under-cover) |
| **A lawn's crop coefficient: 1998's 0.95 or the 2025 revision's 0.70** (`turf_cool` the default, `turf_lawn` the revision's) | Thirty summers by the weather on the lawn drill's two soils, three draws: told the revision's, a third less water, and if the lawn truly uses 1998's, on the simulator of 2026-10-16 the yard's lawn is short in 27 or 28 summers (on the soil of 2026-10-15, in 3); by a probe, no difference. Which is true of a real lawn is not known here | A lawn with a probed bed nearby as its reference through a season, its learned rate set beside both values, and the grass's state recorded | [modules/soilwater](../modules/soilwater/README.md#a-crop-that-grows), [notes/lawn-sprinklers](notes/lawn-sprinklers.md) |
| **The backtests' soil moving water below field capacity as a real one does** (since 2026-10-15): van Genuchten's curve through each horizon's saturation, field capacity at 33 kPa and wilting point at 1500 kPa, Rosetta3's residual water and `L` (since 2026-10-16; before, none and 0.5), Mualem's conductivity from its saturated one, Darcy's law between layers at the two conductivities' geometric mean | HYDRUS-1D on the same soils, within 0.0002 to 0.002 of water content while water spread and rose and 0.002 to 0.012 while a watering soaked in (an outside benchmark, through phydrus); the curve and its slope against their own numbers, Darcy's flux against one worked by hand, water moving by suction not by how wet a soil looks (sand over clay), no step overshooting, every millimetre kept. The lawn that found it, short in 13 summers of 30 when no water moved, was short in 1 to 8; with the residual at half the wilting point the big results held and that lawn went short in 8. Carsel and Parrish's class-mean silt loam, not this soil's own curve | A real bed's probes at two depths through the days after a light watering, to see how fast and how far the water below field capacity moves; and a soil's measured curve and conductivity in place of the fit | [modules/soilwater](../modules/soilwater/README.md#water-below-field-capacity), [sim/physics.py](../sim/physics.py) |
| **The backtests' crop using its water as FAO-56's does** (since 2026-10-16): its whole use to its `p` (`Ks`), roots drawing most from the top in a line to none at their depth (Prasad 1988), the soil's surface drying by the dual coefficient, a mown lawn covering 0.95 of its ground, a dense pan as an option | Against USCRN's Crossville probes under grass: hourly correlation 0.85 to 0.96, rain-free drying at 0.74 of the probes' rate at 5 cm, 0.85 at 10 and 1.26 at 20; the lawn's use 0.96 of the reference ET, FAO-56's being 0.95. Every table run again on it, three draws. The roots' depth and shape under a real crop are assumed | A bed's probes at three depths through rain-free spells, its roots dug, and its water use set beside the station's reference ET | [modules/soilwater](../modules/soilwater/README.md#the-crops-water-use-and-the-soils-surface), [notes/soil-models](notes/soil-models.md), [sim/physics.py](../sim/physics.py) |
| **A probe out of the soil, told by reading drier than its soil can be** (`soil_floor`: half the wilting point in the top 15 cm, FAO-56 Rev.1 Eq. 7.5, the wilting point below, less 0.03) | Readings made up in the tests: a probe at 20 cm reading 2% in a silt loam, at 10 cm reading 4% (dry topsoil, read) and 2% (air), a second probe still in the soil, the weather carrying the bed from the last reading in it, and sand, where it cannot tell | A probe pulled out of a bed and one left with an air gap beside it, each reading through a dry week; and a summer's readings of probes in dry topsoil, to see the floor never trip on soil | [modules/soilwater](../modules/soilwater/README.md#a-probe-out-of-the-soil) |
| **openSenseMap's soil probes as a test source**, and the reader's units | Six hours of one SMT50 station and one LSE01's metadata (fixture), and a live run on 2026-10-13: every reading passed the checks, including an LSE01 reading 2% soil water | A season of several stations' series read, with their keepers asked where and how deep their probes are | [notes/test-data-sources](notes/test-data-sources.md) |
| **Field capacity read off a tension sensor beside a probe**, and the Watermark's calibration | A van Genuchten silt loam's curve, exact and with noise; Shock et al.'s equation by hand | A Watermark and a probe at one depth through a season, and the value read off set beside a laboratory's 33 kPa water content for a core from that depth | [modules/soilwater](../modules/soilwater/README.md#the-beds-own-soil), [sdk/tension.py](../sdk/tension.py) |
| **What measuring more would buy**: an anemometer at the station, the crop's use measured, a tension sensor beside each probe | Simulated only: the trials on the virtual farm, McAllister and Davis 1991 to 2025, then the sealed Bushland and Tifton, each against the same bed measuring nothing more; the virtual soil's field capacity is its water at 33 kPa, so its tension sensor is out only by its own error | Beds side by side on one farm, one advised with the measure and one without, through a season, the water given and the crop's yield or stress set beside each other | [modules/soilwater](../modules/soilwater/README.md#what-measuring-more-would-buy) |
| **The backtests' crop making up for a dry top, and running short sooner on a hot day** (since 2026-10-18): Jarvis's compensated uptake, each farm's crop as far as a compensation drawn between 0.5 and 1 lets it; FAO-56's `p + 0.04 (5 − ETc)` | The equations by unit test (`sim/test_physics.py`); the compensation's range assumed, not measured | A crop's uptake by depth under a dry top, from a profile probe beside a weighing lysimeter or sap flow, through a dry spell | [modules/soilwater](../modules/soilwater/README.md), [sim/physics.py](../sim/physics.py) |
| **The simulator's water near field capacity and below the roots**: a cubic rule for drainage above field capacity, not Mualem's conductivity; a soil at field capacity that never drains further; the soil under the roots a store at field capacity, 60 to 86 mm a tomato season rising to them; rain soaking in at 2.5 mm an hour, none caught by the canopy; watering perfectly even; every season starting full | The season's water balanced to 1e-11 mm; HYDRUS-1D on three 72-hour cases without roots (found by the audit of 2026-10-18, not changed) | HYDRUS-1D through a whole season, free drainage, roots and evaporation, beside the simulator | [sim/physics.py](../sim/physics.py), [notes/soil-models](notes/soil-models.md) |
| **A farm's station and forecasts in the backtests** (since 2026-10-18): each farm's station off by half a degree, three points of humidity, a twentieth of its sunshine and a fifth of its wind; a rain day in four missed whole at a day's lead, a dry day in twelve forecast a spell | Round values, assumed | A farm's station beside a reference station through a season; a season of the farm's forecasts scored against its gauge (`sdk/forecast.py`) | [modules/soilwater/backtest.py](../modules/soilwater/backtest.py) |
| **What the soil advice cannot see**: the soil above the shallowest probe, read as that probe reads; a dead or misreporting rain gauge; the refill reaching past the deepest probe to the roots' depth by assumption; a crop's days counted in UTC, a day off east of it | Found by the audit of 2026-10-18 on hand-built beds and the simulator; not changed | A probe at 3 to 5 cm beside the others through a hot summer; a gauge set beside the station's neighbours; a profile probe below the deepest | [modules/soilwater](../modules/soilwater/README.md) |
| **The soak test**: whether the litres it asks for wet a real bed past field capacity down to its probes, and what it reports is the bed's field capacity | Readings made to rise and drain as a soak's would | A soak test on a bed with probes at two depths, beside the field capacity learned from a season's rains | [modules/soilwater](../modules/soilwater/README.md#a-soak-test-field-capacity-on-the-day) |
| **Salt from a probe's bulk conductivity**: Hilhorst's pore water, through Topp's permittivity, to a saturated paste's extract | METER's worked example and Hilhorst by hand, on readings made to fit; Maas and Grattan's tolerances read in | A tunnel bed's probe through a season, its estimates set beside a laboratory's saturated-paste ECe on cores taken beside it | [modules/salinity](../modules/salinity/README.md) |
| **The twin's soil started from probes in the tunnel** | The layers set from readings, by unit test; one GreenLight night three ways, the low moving 0.18 °C for 3 °C of soil | A tunnel with soil probes at two depths through a winter, the twin's lows with and without them set beside the tunnel's own air sensor | [modules/twin](../modules/twin/README.md) |
| **GreenLight's tunnel against a real tunnel**: the covered-crop frost watch's "inside low", and the twin-against-sensor check's idea of how far apart a model and a thermometer usually sit | GreenLight against the virtual farm's tunnel; the watch on forecasts against the twin run on the weather that came, and the check against a second model with faults put in. The "truth" inside is a model each time, and the twin runs about 1.1 °C warm on forecasts | A tunnel's inside and outside air logged on clear spring nights, with its film type written down | [modules/twin](../modules/twin/README.md), [Q28](spec/open-questions.md) |

## Needs root, a phone or the open internet

| Not tested | Checked instead | What would check it | Noted in |
| --- | --- | --- | --- |
| **The sandbox's filesystem protections** (`ProtectSystem`, `ProtectHome`) | Runs under a *user* systemd manager, which skips mount-namespace options without saying so | `systemd-run -p ProtectSystem=strict … touch /usr/x` under the system manager, on the gateway | [deploy/systemd](../deploy/systemd/README.md) |
| **Dropping capabilities** (`CapabilityBoundingSet=`) | Nothing: a user manager is refused it. The notifier's live run on 2026-10-11 had to leave it out | The unit started by the system manager, then `grep Cap /proc/<pid>/status` | [deploy/systemd](../deploy/systemd/README.md) |
| **Push reaching a real phone**: the ntfy app showing the alert, and its "I'm on it" button sending the acknowledgement | A real ntfy server (v2.11.0), open and locked down. The button was pressed by making the exact request its action describes. Per ntfy's documentation, an iPhone gets instant notifications from a self-hosted server only when that server relays through ntfy.sh (`upstream-base-url`); not tried | The ntfy app on an Android phone and an iPhone, subscribed to a test topic on the server the pilot will use | [modules/notify](../modules/notify/README.md) |
| **The data service facing the internet** | Real sockets on this machine: tokens, grants, TLS with a generated certificate, rate limits, timeouts | Someone outside trying to break it | [README](../README.md), [server](../server/README.md) |

## Needs a person

| Not tested | Checked instead | What would check it | Noted in |
| --- | --- | --- | --- |
| **Every Spanish string**: messages, the board, the advisor. The notifier's lists of yes and no words matter most, because they decide whether a reply stops an alert climbing | `make packs`: every key present, every field matching English | A native-speaking agronomist's review, and the yes and no lists tried on the people who will text back | [LANGUAGE_PACKS](LANGUAGE_PACKS.md), each module's README |
| **The advisor's crops without a model**: chill and bloom for blueberries, heat at fruit set in any crop but tomato, oats, and the 255 plants with neither source | The 28 crops with a crop model, and 625 fruit cultivars for chill | Sources for them, or a grower's records | [site-match-tennessee](../modules/advise/notes/site-match-tennessee.md#not-checked-yet) |

## Smaller gaps in the tests

None open at the moment.

## Checked since this list began

| Checked | How | Evidence |
| --- | --- | --- |
| **The farm page served with TLS** (2026-10-11) | A generated certificate: the pages over TLS, nothing over plain HTTP, an untrusted certificate refused, and a client that stalls its handshake stalling only itself | [modules/board/test_board.py](../modules/board/test_board.py), `TestTls` |
| **The module host and the other writers of the farm's log** (2026-10-11) | The notes said the host "runs inside the gateway", but no gateway process exists (it waits on the radio, build step 7). The real gap was worse: the host never read what other processes appended, so a revocation made at the command line was not seen until a restart, nor a new grant, nor a reading from the ingest. It now reads the file back every two seconds; tests show each counts, and fail on the old host. Found on the way: the first event after a power cut was glued to the cut line and lost; it now starts a fresh line | [sdk/test_modhost.py](../sdk/test_modhost.py) `TestOtherWritersOfTheLog`, [sdk/test_log.py](../sdk/test_log.py) `TestOtherWritersOfOneFile`, `test_the_first_event_after_a_power_cut_is_not_lost` |
| **Quiet hours across a change of hour, and a notifier that runs for a year** (2026-10-11) | The autumn change in Tennessee: a frost watch held overnight goes out at 6 am by the farm's clock both sides of it, which a fixed offset would get wrong by an hour. A year of daily alerts leaves about a week of them in the notifier's memory, and every alert and clear still went out | [modules/notify/test_notify.py](../modules/notify/test_notify.py): `test_quiet_hours_keep_the_farm_s_clock_across_the_change_of_hour`, `test_a_year_of_alerts_is_not_a_year_of_memory` |
