Default a solid-fuel room heater's natural fuel to house coal 🟩

Solid fuel is ambiguous across coal/wood/smokeless/pellets, so the overlay
defaults to house coal (33, the most common) when no main_fuel override is
given; a specific solid-fuel override still wins by last-wins composition.
Updates the ADR-0041 natural-fuel amendment accordingly (every archetype drags
a natural fuel; solid defaults to coal).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-30 16:55:57 +00:00
parent 390df5a6bd
commit 56aaace5b1
2 changed files with 16 additions and 9 deletions

View file

@ -108,13 +108,15 @@ A room-heater / direct-acting archetype names a *system*, not its fuel — and f
arrives as its own composable `main_fuel` override. Two rules keep the system
self-coherent without coupling the two overlays:
- **The heating overlay drags a natural fuel only where the archetype is
unambiguous** — electric room heaters / direct-acting / storage are
unambiguously electricity (RdSAP `main_fuel` code 29), a gas boiler is mains
gas (26). A **solid / oil room heater is fuel-ambiguous** (coal vs wood vs
smokeless), so it drags **no** natural fuel and relies on the `main_fuel`
override; dragging a guessed coal-vs-wood code would be *more* wrong (very
different carbon).
- **Every archetype drags a natural fuel so the system self-coheres without a
`main_fuel` override.** Where the fuel is unambiguous it is exact — electric
room heaters / direct-acting / storage → electricity (RdSAP `main_fuel` 29), a
gas boiler → mains gas (26), an oil room heater → oil (28). **Solid fuel is
ambiguous** (coal / anthracite / smokeless / dual fuel / wood logs / pellets),
so it **defaults to house coal (33)** — the most common solid fuel — which a
specific `main_fuel` override then refines. (The `main_fuel` override's own
vocabulary must grow to carry the full solid-fuel list — a parallel taxonomy
gap, same shape as this one.)
- **A present `main_fuel` override wins** by the applicator's last-wins
composition (`apply_simulations` setattrs non-`None` fields in order), so the
`main_fuel` overlay is applied **after** the heating overlay. The agreeing

View file

@ -84,9 +84,12 @@ _SOLID_FUEL_ROOM_HEATER_CODES = frozenset(range(631, 637))
# that lodged a different fuel. A later `main_fuel` override still wins (last-wins
# composition); a contradicting landlord fuel is logged, not silently overridden.
# Electric room heaters (Table 4a 691-701) are unambiguously electricity (RdSAP
# main_fuel code 29). Solid/oil room heaters are fuel-ambiguous (coal vs wood vs
# smokeless), so they drag no natural fuel and rely on the `main_fuel` override.
# main_fuel code 29). Solid fuel is ambiguous (coal / anthracite / smokeless /
# dual fuel / wood logs / pellets), so it defaults to house coal (33) — the most
# common solid fuel — when the landlord gives no `main_fuel` override; a specific
# solid-fuel override still wins by last-wins composition.
_ELECTRICITY_FUEL = 29
_HOUSE_COAL_FUEL = 33
_ELECTRIC_ROOM_HEATER_CODES = frozenset(range(691, 702))
# SAP Table 4c full boiler-control code: programmer + room thermostat + TRVs. The
@ -171,6 +174,8 @@ def _natural_fuel_for(code: int) -> Optional[int]:
present `main_fuel` override wins by last-wins composition."""
if code in _ELECTRIC_ROOM_HEATER_CODES:
return _ELECTRICITY_FUEL
if code in _SOLID_FUEL_ROOM_HEATER_CODES:
return _HOUSE_COAL_FUEL
return None