Slice S0380.122: tighten test_ventilation tolerances

17 hand-crafted ventilation tests had abs=0.001-0.01 tolerances that
masked the actual diff (always 0 or 1e-16 for these direct-arithmetic
formulas). Tightened to abs=1e-12 (essentially exact).

10 cohort cert pins (`LINE_8`/`LINE_10`/.../`LINE_25` against U985 PDF)
had mixed abs=0.0001-0.0005; standardised to abs=1e-4 (PDF 4-d.p.
display floor per [[feedback-e2e-validation-philosophy]]). The looser
0.0005 pins on (8), (16), (18), (21), (22b), (25) admitted up to half
a 4-d.p. unit of drift that the cascade isn't producing — actual
cascade diffs are ~5e-5 (one notch under display precision).

Test movement: all 26 tests pass at the new tolerances. Net pyright
change: 69 → 69.

Per [[feedback-zero-error-strict]] tolerance widening is forbidden;
this slice goes the other way — every pin tightened to its actual
precision floor.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-30 21:44:43 +00:00 committed by Jun-te Kim
parent 2dc6adb5b7
commit 07720e909e

View file

@ -42,7 +42,7 @@ def test_bare_masonry_detached_returns_baseline_line_16_of_0_65() -> None:
# Assert
assert isinstance(result, VentilationResult)
assert result.infiltration_rate_ach == pytest.approx(0.65, abs=0.01)
assert result.infiltration_rate_ach == pytest.approx(0.65, abs=1e-12)
def test_open_chimney_adds_80_per_volume_to_line_8_openings() -> None:
@ -60,8 +60,8 @@ def test_open_chimney_adds_80_per_volume_to_line_8_openings() -> None:
)
# Assert
assert result.openings_ach == pytest.approx(0.40, abs=0.005)
assert result.infiltration_rate_ach == pytest.approx(1.05, abs=0.01)
assert result.openings_ach == pytest.approx(0.40, abs=1e-12)
assert result.infiltration_rate_ach == pytest.approx(1.05, abs=1e-12)
def test_two_storey_dwelling_adds_0_1_via_line_10() -> None:
@ -77,8 +77,8 @@ def test_two_storey_dwelling_adds_0_1_via_line_10() -> None:
)
# Assert
assert result.additional_ach == pytest.approx(0.1, abs=0.001)
assert result.infiltration_rate_ach == pytest.approx(0.75, abs=0.01)
assert result.additional_ach == pytest.approx(0.1, abs=1e-12)
assert result.infiltration_rate_ach == pytest.approx(0.75, abs=1e-12)
def test_timber_frame_uses_line_11_structural_0_25_not_0_35() -> None:
@ -94,8 +94,8 @@ def test_timber_frame_uses_line_11_structural_0_25_not_0_35() -> None:
)
# Assert
assert result.structural_ach == pytest.approx(0.25, abs=0.001)
assert result.infiltration_rate_ach == pytest.approx(0.55, abs=0.01)
assert result.structural_ach == pytest.approx(0.25, abs=1e-12)
assert result.infiltration_rate_ach == pytest.approx(0.55, abs=1e-12)
def test_suspended_timber_floor_line_12_unsealed_vs_sealed() -> None:
@ -116,8 +116,8 @@ def test_suspended_timber_floor_line_12_unsealed_vs_sealed() -> None:
)
# Assert
assert unsealed.floor_ach == pytest.approx(0.2, abs=0.001)
assert sealed.floor_ach == pytest.approx(0.1, abs=0.001)
assert unsealed.floor_ach == pytest.approx(0.2, abs=1e-12)
assert sealed.floor_ach == pytest.approx(0.1, abs=1e-12)
def test_draught_lobby_present_zeros_line_13() -> None:
@ -131,7 +131,7 @@ def test_draught_lobby_present_zeros_line_13() -> None:
)
# Assert
assert result.draught_lobby_ach == pytest.approx(0.0, abs=0.001)
assert result.draught_lobby_ach == pytest.approx(0.0, abs=1e-12)
def test_window_draught_proofed_line_15_is_linear_in_pct() -> None:
@ -149,8 +149,8 @@ def test_window_draught_proofed_line_15_is_linear_in_pct() -> None:
)
# Assert
assert full.window_ach == pytest.approx(0.05, abs=0.005)
assert half.window_ach == pytest.approx(0.15, abs=0.005)
assert full.window_ach == pytest.approx(0.05, abs=1e-12)
assert half.window_ach == pytest.approx(0.15, abs=1e-12)
def test_openings_sum_each_table_2_1_rate_independently() -> None:
@ -167,7 +167,7 @@ def test_openings_sum_each_table_2_1_rate_independently() -> None:
)
# Assert
assert result.openings_ach == pytest.approx(0.825, abs=0.01)
assert result.openings_ach == pytest.approx(0.825, abs=1e-12)
def test_zero_or_negative_volume_raises_value_error() -> None:
@ -199,7 +199,7 @@ def test_pressure_test_ap50_uses_line_18a_formula() -> None:
)
# Assert
assert result.pressure_test_ach == pytest.approx(0.25, abs=0.001)
assert result.pressure_test_ach == pytest.approx(0.25, abs=1e-12)
def test_pressure_test_ap4_uses_line_18b_formula() -> None:
@ -214,7 +214,7 @@ def test_pressure_test_ap4_uses_line_18b_formula() -> None:
)
# Assert
assert result.pressure_test_ach == pytest.approx(0.263 * (4.0 ** 0.924), abs=0.001)
assert result.pressure_test_ach == pytest.approx(0.263 * (4.0 ** 0.924), abs=1e-12)
def test_shelter_factor_line_20_clamps_sides_to_0_4() -> None:
@ -303,8 +303,8 @@ def test_mvhr_24a_subtracts_efficiency_from_system_air_change() -> None:
for i in range(12):
delta_90 = mvhr_90.effective_monthly_ach[i] - mvhr_90.monthly_wind_adjusted_ach[i]
delta_0 = mvhr_0.effective_monthly_ach[i] - mvhr_0.monthly_wind_adjusted_ach[i]
assert delta_90 == pytest.approx(0.05, abs=0.001)
assert delta_0 == pytest.approx(0.5, abs=0.001)
assert delta_90 == pytest.approx(0.05, abs=1e-12)
assert delta_0 == pytest.approx(0.5, abs=1e-12)
def test_balanced_mv_24b_adds_full_system_ach_each_month() -> None:
@ -500,24 +500,25 @@ def test_section_2_matches_elmhurst_worksheet(fixture: ModuleType) -> None:
mv_kind=fixture.MV_KIND,
)
# Assert — line-by-line vs Elmhurst output.
assert result.openings_ach == pytest.approx(fixture.LINE_8_OPENINGS_ACH, abs=0.0005)
assert result.additional_ach == pytest.approx(fixture.LINE_10_ADDITIONAL_ACH, abs=0.0001)
assert result.structural_ach == pytest.approx(fixture.LINE_11_STRUCTURAL_ACH, abs=0.0001)
assert result.floor_ach == pytest.approx(fixture.LINE_12_FLOOR_ACH, abs=0.0001)
assert result.draught_lobby_ach == pytest.approx(fixture.LINE_13_DRAUGHT_LOBBY_ACH, abs=0.0001)
assert result.window_ach == pytest.approx(fixture.LINE_15_WINDOW_ACH, abs=0.0001)
assert result.infiltration_rate_ach == pytest.approx(fixture.LINE_16_INFILTRATION_RATE_ACH, abs=0.0005)
assert result.pressure_test_ach == pytest.approx(fixture.LINE_18_PRESSURE_TEST_ACH, abs=0.0005)
assert result.shelter_factor == pytest.approx(fixture.LINE_20_SHELTER_FACTOR, abs=0.0001)
assert result.shelter_adjusted_ach == pytest.approx(fixture.LINE_21_SHELTER_ADJUSTED_ACH, abs=0.0005)
# Assert — line-by-line vs Elmhurst output. All pins ride at abs=1e-4
# (PDF 4-d.p. display floor); cascade lands at ~5e-5 for monthly tuples.
assert result.openings_ach == pytest.approx(fixture.LINE_8_OPENINGS_ACH, abs=1e-4)
assert result.additional_ach == pytest.approx(fixture.LINE_10_ADDITIONAL_ACH, abs=1e-4)
assert result.structural_ach == pytest.approx(fixture.LINE_11_STRUCTURAL_ACH, abs=1e-4)
assert result.floor_ach == pytest.approx(fixture.LINE_12_FLOOR_ACH, abs=1e-4)
assert result.draught_lobby_ach == pytest.approx(fixture.LINE_13_DRAUGHT_LOBBY_ACH, abs=1e-4)
assert result.window_ach == pytest.approx(fixture.LINE_15_WINDOW_ACH, abs=1e-4)
assert result.infiltration_rate_ach == pytest.approx(fixture.LINE_16_INFILTRATION_RATE_ACH, abs=1e-4)
assert result.pressure_test_ach == pytest.approx(fixture.LINE_18_PRESSURE_TEST_ACH, abs=1e-4)
assert result.shelter_factor == pytest.approx(fixture.LINE_20_SHELTER_FACTOR, abs=1e-4)
assert result.shelter_adjusted_ach == pytest.approx(fixture.LINE_21_SHELTER_ADJUSTED_ACH, abs=1e-4)
# Monthly arrays — every month.
# Monthly arrays — every month at abs=1e-4 (PDF 4-d.p. display).
for i in range(12):
assert result.monthly_wind_speed_m_s[i] == pytest.approx(fixture.LINE_22_WIND_SPEED_M_S[i], abs=0.001)
assert result.monthly_wind_factor[i] == pytest.approx(fixture.LINE_22A_WIND_FACTOR[i], abs=0.001)
assert result.monthly_wind_adjusted_ach[i] == pytest.approx(fixture.LINE_22B_WIND_ADJUSTED_ACH[i], abs=0.0005)
assert result.effective_monthly_ach[i] == pytest.approx(fixture.LINE_25_EFFECTIVE_ACH[i], abs=0.0005)
assert result.monthly_wind_speed_m_s[i] == pytest.approx(fixture.LINE_22_WIND_SPEED_M_S[i], abs=1e-4)
assert result.monthly_wind_factor[i] == pytest.approx(fixture.LINE_22A_WIND_FACTOR[i], abs=1e-4)
assert result.monthly_wind_adjusted_ach[i] == pytest.approx(fixture.LINE_22B_WIND_ADJUSTED_ACH[i], abs=1e-4)
assert result.effective_monthly_ach[i] == pytest.approx(fixture.LINE_25_EFFECTIVE_ACH[i], abs=1e-4)
def test_table_u2_default_matches_worksheet_g86_to_r86() -> None: