diff --git a/docs/adr/0045-gas-cpsu-dumping-ground-splits-into-solid-fuel-and-electric-boiler-archetypes.md b/docs/adr/0045-gas-cpsu-dumping-ground-splits-into-solid-fuel-and-electric-boiler-archetypes.md index 49117b477..da1bdad85 100644 --- a/docs/adr/0045-gas-cpsu-dumping-ground-splits-into-solid-fuel-and-electric-boiler-archetypes.md +++ b/docs/adr/0045-gas-cpsu-dumping-ground-splits-into-solid-fuel-and-electric-boiler-archetypes.md @@ -49,28 +49,41 @@ Add the missing archetypes and reclassify the bucket. No calculator change. `"Solid fuel room heater, open fire with back boiler"` → 632, `"Solid fuel room heater, closed with boiler"` → 634. Companions drag from the code (already-covered 631–636 set) — no overlay-logic change. -2. **`"Electric boiler"` → SAP 191**, dragging **electricity (29)** via - `_natural_fuel_for` — an electric boiler is unambiguously electric (ADR-0041 - "direct-acting/storage → electricity"), and this also closes the pre-existing - gap where 191 dragged no fuel. Meter stays Single, control None (191 is neither - a storage nor a wet-boiler-control system). -3. **Deterministic `main_heating_guard` + reclassify**, TEXT-first / - pgEnum-deferred. The guard resolves the structured phrasings by description - alone: `"…open fire … back boiler"` → 632 (tested before the bare `"open fire"` - → 631), `"…closed … with boiler"` → 634, and `"Boiler: NA"` → - `"Electric boiler"` (the NA type is the electric signal). `scripts/ - reclassify_gas_cpsu.py` reuses the guard as its decision function and defers the - four new `main_heating_system` pgEnum-cache values. +2. **`"Electric boiler"` → SAP 191** and **`"Electric CPSU"` → SAP 192**, both + dragging **electricity (29)** via `_natural_fuel_for` — electric boilers are + unambiguously electric (ADR-0041 "direct-acting/storage → electricity"), also + closing the pre-existing gap where 191/192 dragged no fuel. 191 stays on a + Single meter; 192 (electric CPSU) is already in `_ASSUMED_DUAL_METER_CODES`, so + it drags an off-peak Dual meter (§12 Rule 1, 10-hour). +3. **Deterministic `main_heating_guard` for the description-determined cases + + reclassify**, TEXT-first / pgEnum-deferred. The guard resolves the structured + phrasings by description alone: `"…open fire … back boiler"` → 632 (tested + before the bare `"open fire"` → 631), `"…closed … with boiler"` → 634, and + `"Boiler: NA"` → `"Electric boiler"` (the NA type is the electric + signal). `scripts/reclassify_main_heating.py` reuses the guard as its decision + function. +4. **Electric CPSU is fuel-determined, not description-determined.** `"Boiler: A/C + rated CPSU"` is identical bar the efficiency band, so the electric/gas split + cannot be read from the description — the guard cannot see it. The reclassify + therefore resolves it with a **fuel-aware, per-property** step (`electric_cpsu_ + for(description, main_fuel)`): a CPSU boiler whose property carries a + `main_fuel = electricity` override → `"Electric CPSU"` (192); a gas / unknown + fuel stays Gas CPSU (120). Only the **TEXT** layer is updated for it — the + description-keyed classifier cache cannot represent a fuel-dependent value. The + **live** guard stays fuel-blind, so a new electric-CPSU intake (rare — 1 row in + the corpus) falls to the LLM rather than being silently mis-guarded. ## Consequences -- ~95 rows leave the Gas CPSU garbage drawer for faithful archetypes: 37 solid - fuel scored as solid fuel (not mains gas), 58 electric boilers scored as electric - (not a mains-gas CPSU). Correct Rebaselining (ADR-0039). -- **FE-owned pgEnum additions (Dan):** four new `main_heating_system` values — +- 96 rows leave the Gas CPSU garbage drawer for faithful archetypes: 37 solid + fuel scored as solid fuel (not mains gas), 58 electric boilers + 1 electric CPSU + scored as electric (not a mains-gas CPSU); the 1 genuine gas CPSU stays on 120. + Correct Rebaselining (ADR-0039). +- **FE-owned pgEnum additions (Dan):** five new `main_heating_system` values — `"Solid fuel room heater, open fire"`, `"Solid fuel room heater, open fire with back boiler"`, `"Solid fuel room heater, closed with boiler"`, `"Electric - boiler"`. TEXT read path fixed on merge; cache writes defer to the migration. + boiler"`, `"Electric CPSU"`. TEXT read path fixed on merge; cache writes defer to + the migration. - Extends [ADR-0041](0041-landlord-heating-classification-targets-a-complete-modellable-taxonomy.md) (complete taxonomy — retiring the Gas CPSU garbage drawer it named) and [ADR-0035](0035-coherent-heating-system-synthesis.md) (companions drag from the @@ -78,12 +91,6 @@ Add the missing archetypes and reclassify the bucket. No calculator change. ### Out of scope -- **Electric CPSU (SAP 192), the 1 `"Boiler: A rated CPSU"` row.** Its description - is identical to the genuine gas `"Boiler: C rated CPSU"` bar the efficiency - band — the electric/gas split is **fuel-determined**, which a pure-string guard - cannot see. Rather than break the guard = reclassify-decision-function symmetry - for one row, this is deferred to a small fuel-aware follow-up; the gas CPSU row - stays correctly on 120. - **Whether "NA" ever denotes a non-electric boiler.** It is 100% electric in the corpus and the guard treats it as electric; a future non-electric "NA" would be a re-open signal, not a silent mis-map (the fuel override would disagree).