Guard the roof classifier so party ceilings never classify as external roofs 🟩

Wires GuardedColumnClassifier(roof_party_ceiling_guard, <llm>) into the roof_type
column so a party-ceiling marker (another/same dwelling or premises above), with or
without a trailing depth, deterministically resolves to its party-ceiling member
(no overlay, ~0 heat loss) instead of the LLM occasionally reading it as a pitched
loft (#1376).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-01 09:41:45 +00:00
parent 0a9d835e66
commit 3987ca4667

View file

@ -14,6 +14,12 @@ from domain.epc.property_overrides.main_fuel_type import MainFuelType
from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType
from domain.epc.property_overrides.property_type import PropertyType
from domain.epc.property_overrides.roof_type import RoofType
from domain.epc.property_overrides.roof_party_ceiling_guard import (
roof_party_ceiling_guard,
)
from domain.data_transformation.guarded_column_classifier import (
GuardedColumnClassifier,
)
from domain.epc.property_overrides.water_heating_type import WaterHeatingType
from domain.epc.property_overrides.wall_type import WallType
from domain.epc.property_overrides.wall_type_construction_dates import (
@ -115,8 +121,13 @@ def _build_columns(
"roof_type": lambda src: ClassifiableColumn(
name="roof_type",
source_column=src,
classifier=ChatGptColumnClassifier(
chat_gpt, RoofType, RoofType.UNKNOWN
# A party ceiling ("another/same dwelling or premises above") has ~0
# heat loss and must never be classified as an external roof; the
# deterministic guard resolves those markers and the LLM handles the
# rest (#1376).
classifier=GuardedColumnClassifier(
guard=roof_party_ceiling_guard,
fallback=ChatGptColumnClassifier(chat_gpt, RoofType, RoofType.UNKNOWN),
),
repo=LandlordOverridesRepository[RoofType](
session, LandlordRoofTypeOverrideRow