Skip to content

Use the Housing Benefit pension deduction parameter consistently - #2497

Merged
juaristi22 merged 1 commit into
mainfrom
fix-140-hb-pension-deduction-parameter
Oct 20, 2026
Merged

juaristi22 merged 1 commit into
mainfrom
fix-140-hb-pension-deduction-parameter

Conversation

@juaristi22

@juaristi22 juaristi22 commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Changing the Housing Benefit pension-contribution deduction rate updates net earnings but leaves the applicable-income deduction at 50%. Use the existing parameter in applicable income so final awards respond consistently; the default 50% calculation stays unchanged.

The new 2025 council-tenant regression has £12,000 earnings, £2,000 pension contributions and £10,000 rent. Under a 25% deduction-rate reform, Housing Benefit should be £5,805.29 instead of the default £6,130.29. The original calculation kept the default payment.

Refs #140 (the Housing Benefit follow-up). The JSA work remains open. Contribution bases, claimant masks, floors and eligibility rules are preserved.

Reproducer: policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income.yaml

Validation: policyengine-core test policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit -c policyengine_uk — 259 cases passed, including the four new rate/control cases. make format and Ruff lint passed. Local runtime: Python 3.13.14 / PolicyEngine Core 3.32.27.

Impact (UK hub, 2026-10-19): none.

  • The run: the repo's Aggregate impact workflow on the certified dataset, run 39316709366, compares main e2ea32893 with main merged with this head (5b063b5bb), on policyengine-uk-data 1.58.1, fiscal years 2025-26 to 2031-32.
  • The result: no aggregate changes in any year, and no household's net income changes. That covers receipts, spending, caseloads, poverty, inequality and deciles. No check is broken; one check (VAT never negative) fails on both sides, as it does on main.
  • Why: the parameter is 0.5 at every date, so current law can't move; only reforms of the rate respond.

axiom: needed

Encoded parity for the changed pension-deduction parameter response remains unverified. No encoder was invoked.

@juaristi22
juaristi22 marked this pull request as ready for review October 18, 2026 09:25

@vahid-ahmadi vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks right, fine to approve.

@juaristi22, this replaces the hard-coded 0.5 in HB applicable income with the existing means_test.pension_contribution_deduction_rate that housing_benefit_net_earnings already uses. So both now follow HB Regs 2006 reg 36(3)(c) ("one-half"), and a reform moves both. The default result is unchanged. I hand-checked the default case. 12,000 − 0.5 × 2,000 − 260 = 10,740, and 10,000 − 0.65 × (10,740 − 4,786.60) = £6,130.29. The 25% case gives 11,240 and £5,805.29.

  1. nit: the same hard-coded half-pension deduction remains in income_support_applicable_income.py:39, council_tax_reduction_applicable_income.py:116 and carers_allowance_earnings.py:106. Each comes from different regulations, so it is right to leave them out of this PR. They would fit as follow-ups under #140 alongside the JSA one.
  2. nit: housing_benefit_applicable_income.py:93-101 still rebuilds a net-earnings-like figure itself instead of reading housing_benefit_net_earnings. This PR makes the two consistent on the rate, but the duplication is where the inconsistency came from. Worth a follow-up issue.

What I checked

  • Read the full diff and issue #140, and the parameter's references (SI 2006/213 reg 36 and 38, SI 2006/214 reg 36 and 39).
  • policyengine-core test housing_benefit_applicable_income.yaml: 9 passed. All of tests/policy/baseline/finance/benefit/family/housing_benefit: 259 passed.
  • Reverted the formula change. The new reform cases then fail 3 of 9, and the default case still passes, as expected.
  • ruff check and ruff format --check on the changed file: clean.
  • Hosted CI on this head: all green.

🤖 Generated with Claude Code

@vahid-ahmadi vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving, per my review above. The shoulds and nits can follow.

@MaxGhenis

Copy link
Copy Markdown
Collaborator

UK hub audit (session local_8e19f9d5, Opus 5.5), for Max's d1728 (2026-10-19), under which the hub merges #2458, #2497 and #2147 on its gates, after correcting each body's axiom: line to a value the parity rule accepts. The author (@juaristi22) had already enqueued it at 16:43:59Z on 2026-10-19, on head e9a2334bcf3546a98db8ce129a5ae355b5ab3bb4, which is the head the reviews cover. The hub verified the gates, fixed the axiom: line, added the impact and did not enqueue again.

  • Reviews:
    • @vahid-ahmadi APPROVED at e9a2334bc (2026-10-18).
    • An independent in-session Opus 5.5 review (code reading; it ran no tests) gave APPROVE WITH NITS at e9a2334bc. It confirmed that the parameter is 0.5 at every date and that nothing else sets it, that there is no double deduction, and that the one-half rate is the same in HB Regs 2006 regs 36 and 38 and HB (SPC) regs 36 and 39. It also recomputed all four YAML cases.
    • Its nits (non-blocking): add the regulation references to housing_benefit_applicable_income's reference, and name the parameter in housing_benefit_net_earnings' documentation.
    • Its follow-up: CTR applicable income and Income Support still hard-code 0.5. That is a separate task.
  • Impact: none, from Aggregate impact run 39316709366 (main e2ea32893 against main merged with this head, certified uk-data 1.58.1, 2025-26 to 2031-32).
  • axiom: line: n/a: infrastructure (parameter wiring), per the review. rulespec-uk has no module for these regulations, and the law's rate is unchanged.
  • Checks: every check passed at the head, and the merge queue re-tested against current main.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants