Model/backend/documents_parser
Khalim Conn-Kowlessar a5eda92a90 Slice S0380.172: Heat-network heat-source-eff CO2/PE factor scaling
Closes the CO2 / PE residuals for CH1 (boiler community heating, SAP
code 301) and CH3 (HP community heating, SAP code 304) via SAP 10.2
Table 4a (PDF p.164) heat-network heat-source efficiency:

  "Boilers (RdSAP)"     → 80%   → code 301
  "Heat pump (RdSAP)"   → 300%  → code 304

Spec block 13a (PDF p.153) (467) "PE associated with heat source 2"
= [(307b)+(310b)] × 100 / (467b) — i.e. fuel input = network_input ×
100 / heat_source_eff before applying Table 12 PE factor. Block 12b
(367) mirrors for CO2. The cascade meters network_input directly
(eff = 1/DLF for the cost path via Table 12 heat-network rate), so
PE / CO2 factors are scaled by 1/heat_source_eff at lookup time —
mathematically equivalent to spec's (network_input / eff) × factor.

Three changes:

1. New `_HEAT_NETWORK_HEAT_SOURCE_EFFICIENCY: Final[dict[int, float]]`
   keyed on SAP code: 301 → 0.80, 304 → 3.00. SAP 302 (CHP+boilers)
   is omitted — the 35%/65% split + displaced-electricity credit per
   spec block 13b (464)/(466)/(364)/(366) needs the .171 follow-up.

2. New `_heat_network_heat_source_efficiency_scaling(main)` helper
   returning 1.0 for non-heat-network mains + SAP 302, and
   1/heat_source_eff for SAP 301 / 304.

3. Wired into `_main_heating_co2_factor_kg_per_kwh` and
   `_main_heating_primary_factor` non-electric branches (heat
   networks are non-electric per `_is_electric_main`). Both functions
   return `Table_12_factor × scaling` so the cascade's
   `network_input × scaled_factor` lands on the spec
   `(network_input / eff) × Table_12_factor`.

Closures vs pre-S0380.172 residuals (heating-systems corpus block 11b):

  variant            ΔCO2          ΔPE        notes
  CH1 (Boilers/Gas)  -787→-126    -3827→-967  ~75-84% closure
  CH2 (CHP/Gas)      unchanged     unchanged   excluded — SAP 302
  CH3 (HP/Elec)      +1614→+473  +11879→+1749 ~71-85% closure
  CH4 (CHP/Oil)      unchanged     unchanged   excluded — SAP 302
  CH6 (CHP/Coal)     unchanged     unchanged   excluded — SAP 302

Cost + SAP unchanged on all 5 (heat-network rate × network_input via
Table 12 is correct regardless of heat-source efficiency).

Residual CH1 / CH3 gap drivers (follow-up scope):
- WHC=901 HW path: cascade reads cert-lodged "Mains gas" as HW fuel
  on community-heating certs; should fall through to main fuel for
  the heat-network so the scaling applies on HW side too.
- Elmhurst 0.8523 multiplier on heat-network energy column (worksheet
  (467) energy = spec_formula × 0.8523 uniformly across non-CHP
  heat-network rows; mechanism not yet identified — spec divergence
  candidate for SAP_CALCULATOR.md §8).

Cohort no-regression verified: 9 ASHP + 38 cohort-2 golden fixtures
pass unchanged; the 41-variant heating-systems corpus has identical
residuals for non-heat-network certs. The 2 closed CH variants are
re-pinned at their new sub-1000 magnitudes.

Test baseline at HEAD: 926 pass + 1 skipped (was 926 + 1 at
predecessor a4b5f4e7; pin updates net to 0). Pyright net-zero on
affected files (cert_to_inputs.py, test_heating_systems_corpus.py):
32 → 32.

Per [[feedback-spec-citation-in-commits]] the dispatch table cites
SAP 10.2 Table 4a (PDF p.164) verbatim row labels.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 15:40:25 +00:00
..
handler address JTK review comments 2026-04-20 15:11:17 +00:00
tests Slice S0380.172: Heat-network heat-source-eff CO2/PE factor scaling 2026-06-04 15:40:25 +00:00
__init__.py Map to RdSapSiteNotes from site notes JSON 🟥 2026-04-16 13:54:03 +00:00
db_writer.py include updating epc_property_data to pashub to ara workflow 2026-04-29 09:55:14 +00:00
elmhurst_extractor.py Slice S0380.170: Community heating mapper unblock (Table 12 dispatch) 2026-06-04 15:40:25 +00:00
extractor.py Handle wall thickness "Unmeasurable" 🟩 2026-04-30 16:41:16 +00:00
local_runner.py update local runner to work for elmhurst 2026-04-24 14:01:36 +00:00
parser.py load ecmk site notes to db 2026-04-29 11:20:47 +00:00
pdf.py update local runner to work for elmhurst 2026-04-24 14:01:36 +00:00