Repository navigation
Add Housing Benefit permitted-work earnings disregard - #2219
Conversation
a8d0b0b to
89368dc
Compare
108290a to
e70d955
Compare
89368dc to
a66b990
Compare
|
Parent-gated build hand-off. Head remains Tests for this child: 0 executed in this job; no claim is made about the current head's CI. Preserve Anthony's corrected disabled-worker earnings-disregard regression (£1,929.20) when updating the base. Draft status unchanged; no merge/readiness/closure action. Once #2225 lands, the pending commands are: git fetch origin main add-hb-permitted-work
git switch add-hb-permitted-work # create tracking branch if absent
git merge --no-ff origin/main
# Resolve, run focused foreground tests with -n 2 after load1 <=110 and
# os.statvfs available disk >=55 GB decimal; commit fixes and push once.
gh api -X PATCH repos/PolicyEngine/policyengine-uk/pulls/2219 -f base=mainOpen items: parent landing; merge/test/push/body refresh as needed; retarget; hub independent review. #2229 remains gated on this PR's landing. |
juaristi22
left a comment
There was a problem hiding this comment.
Reviewed at a66b990b52a468d2182d3154cbcbf8da66982b1a, limited to the permitted-work change over its stacked parent. No actionable findings from independent policy/source and code reviews.
The component replaces the selected ordinary disregard, preserves a higher lone-parent amount and caps the result at earnings. Its external pre-assessment contract matches the GB working-age rule and corresponding GB pension-age/NI provisions. It does not infer qualifying work or partner allocation from generic flags.
Validation:39 focused tests passed. An eligible claimed-HB integration raises the final award from£6477.90 to£10208.90 when the external£6000 assessment is supplied, exactly65% of the£5740 replacement difference; passport and cap effects were excluded. The documented upstream-assessment coverage limitation and stacked-parent merge order remain.
Brings in #2225 as merged (5086896, head 05246aa) and later main. This branch was stacked on #2225's e70d955, and no commit on main since then touches housing_benefit_applicable_income_disregard.py, so git merged it without a conflict. The merged file keeps main's #2225 logic (housing_benefit_special_earnings_disregard, with its eligibility routes and net-earnings cap) and applies this branch's permitted-work replacement on top of it, before the accommodation and additional amounts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…standard's docs Adds what #2225's delta review (section 6) said this PR owes now that #2225 has merged: - GB and NI pension-age YAML regressions where the special £20 comes from severe disablement allowance or blindness (derived by housing_benefit_special_earnings_disregard_eligible) and a pre-assessed permitted-work amount is above zero. Each pins the selected standard at £1,040 and the applied disregard at £4,160, not £5,200: SI 2006/214 Sch 4 para 5A(2) and SR 2006/406 Sch 5 para 5A(2) exclude para 5. - A lone parent at the permitted-work maximum, England and NI: the £183.50 reg 45(4) limit (16 x £11.44, rounded up) beats para 4's £25, so £9,542 is disregarded, capped at net earnings. - A permitted-work draw in the selected-standard Hypothesis property. It checks the selected standard ignores permitted work, and the applied disregard is min(net, permitted), or for a lone parent min(net, max(permitted, £1,300)), never stacked. - housing_benefit_special_earnings_disregard's documentation now says it is the amount before permitted work, which housing_benefit_applicable_income_disregard replaces. The formula is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hub hand-off: main merged, #2225's owed tests addedNew head:
No force-push or rebase. The PR is still a draft, and I made no review, merge or readiness change. The merge and its conflict resolutionThere was no textual conflict. This branch was stacked on #2225's What the merged formula now does:
Added tests (from #2225's delta review §6)The arithmetic is written into the YAML comments. The law is SI 2006/214 Sch 4 paras 5 and 5A and SR 2006/406 Sch 5 paras 5 and 5A, fetched from legislation.gov.uk today. The specified amount comes from ESA Regs 2008 reg 45(4) and (9A), SR 2008/280 reg 45(4) and (9A), and SI 1995/311 reg 17(4) and (10). For 2024-25 it is 16 × £11.44 (the model's adult minimum wage), rounded up to the next 50p: £183.50 a week. In each couple case, A does exempt work for £60 a week and B earns £100 a week from other work. Under para 5A(4), B's disregard is the smallest of £100, £183.50 − £60 and £20, which is £20. So the permitted amount is (£60 + £20) × 52 = £4,160, and net earnings are £8,320.
Test results (local, this head's tree;
|
| Run | Result |
|---|---|
housing_benefit_permitted_work.yaml |
37/37 passed (32 original + 5 new) |
HB applicable_income/ YAML directory |
182/182 passed |
13 test_housing_benefit_*/test_hb_* files + CTR pensioner-disregard properties, -n 2 -m "not microsimulation" |
161/161 passed, none skipped (20m29s) |
test_pension_age_and_working_age_schedules_agree + the extended selected-standard property, alone |
2/2 passed |
ruff format ., ruff check ., git diff --check |
clean |
I ran no microsimulation, dataset-loading test or full suite.
Mutation check. I applied each mutant to the formula's max_(…) term and restored the file afterwards (git diff on it is empty):
- Stacking (
permitted + standard): killed.- 27/37 YAML cases fail, including all four new SDA and blindness cases (£5,200 against £4,160).
- The property fails on an explicit example,
('single', 520, False, 500). - The lone-parent maximum cases don't kill this mutant, because net earnings cap them at the limit.
- Max with the special £20 (
max_(permitted, standard)): killed.- Only by Anthony's first case (£1,040 against £500) and by the property,
('single', 520, True, 500). - The new cases don't kill it, and that is expected. With lawful inputs the specified amount is at least £20 (reg 45(2), reg 17(2)), so replacement and max coincide for real cases.
- Only by Anthony's first case (£1,040 against £500) and by the property,
CI: run 40636400501 and siblings started on a67175429 and were pending when I posted this. Lint, Changes and Changelog fragments had passed. mergeable is MERGEABLE, and the merge state is BLOCKED while checks run.
Still owed
- CI. Test / Result and the Aggregate impact need to finish green on
a67175429. - The PR body's "Merge dependency" paragraph is stale. Add Housing Benefit special £20 earnings disregard #2225 merged on 25 Oct. I left it alone because I only updated the Validation paragraph. The base is already
main, so the retarget step in the 22 Oct comment is moot. - An independent review of this head, then a ruling on readiness. Draft status, merge and reviews are untouched.
- NI SDA case: the NI exempt-work limit is unverified. It is in SR 1995/41 reg 17(4). legislation.gov.uk's revised text of that regulation still lists unapplied amendments, so I didn't check £183.50 against it. That case's £4,160 is a supplied pre-assessed amount. The GB SDA case and both blindness cases rest on text I did fetch (SI 1995/311 reg 17; SI 2008/794 and SR 2008/280 reg 45).
- A model gap I noticed but did not change. At working age, the model takes the disability premium only from
is_disabled_for_benefits, but SI 2006/213 Sch 3 para 13(1)(a)(i) also lists SDA receipt. A working-age SDA recipient without that flag therefore misses the premium and the £20 route. With a positive permitted-work input, para 10A(2) makes the £20 irrelevant, but the premium gap stands. - Limit Housing Benefit childcare to qualifying charges and earnings residuals #2229 and Apply Housing Benefit accommodation disregards from their start date #2234 still need to merge this head. Limit Housing Benefit childcare to qualifying charges and earnings residuals #2229 is stacked on this branch. I didn't touch either.
- Axiom: the line still reads
TheAxiomFoundation/rulespec-uk#375 queued. The new cases' externally derived values (£4,160, £9,542) could join that issue's companion tests.
🤖 Generated with Claude Code
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in Notes
Moves flagged for reviewNone. Spending by benefit and service
Caseloads
Standard reform costings (change in gov_balance)
Standard reforms: change in each reform's target
Household net income by decileNo household's net income changes in any year. No change in any year: receipts by tax head; government balance, each component counted once; model totals; household income totals; population; poverty rates; people in poverty; inequality; mean household net income in each side's own deciles. Checks failing on both base and head (1)
Counted-once checkEach of 91 components was raised by £1 per unit in 2026-27, and every head of its totals was read household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
Resolve housing_benefit_applicable_income_disregard.py, where main's #2703 corrected the comment on the standard-disregard line this branch replaced. Keep the shared applied-standard call and move main's corrected paragraph citation into housing_benefit_applied_standard_earnings_disregard.py, where the special earnings disregard is now read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@anth-volk UK hub: the review's one P2 is fixed, and
#2229 and #2234 will need this head merged in once it lands. 🤖 Generated with Claude Code |
The worked arithmetic in the legal reproducer case had lost its spaces. Also name the pre-fix commit instead of "current head", as the round-2 review asked. Comments only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@anth-volk UK hub: enqueued at
🤖 Generated with Claude Code |
Fixes #2218.
Summary
Changes 11 files against main, adding one GBP input for an externally assessed annual HB permitted-work disregard. It replaces the ordinary standard, retains a higher lone-parent amount and is capped at net earnings. Additional and accommodation disregards remain separately conditional.
The approved C6 approach requires external assessment of qualifying status, exempt work, statutory earnings limits and partner allocations, rather than inference from gross earnings. There is no new ESA/eligibility engine or verified dataset mapping. Missing/zero input retains the ordinary-disregard approximation and may understate qualifying awards; variable documentation explains these limitations.
Government sources embedded in code: GB working-age Schedule 4 paragraph 10A, GB pension-age paragraph 5A, and the matching NI working-age and pension-age provisions.
Savings-credit-only correction
GB regulation 27(4) and NI regulation 25(4) permit only specified modifications to PC's assessed net income. The lone-parent/permitted-work adjustment therefore accounts for PC's existing earnings disregard; paragraph 9(1)'s additional disregard comes off in full.
Both HB calculations read a shared applied standard, preserving permitted-work replacement, the lone-parent proviso and the earnings cap. Subtracting it isolates paragraph 9 correctly, also correcting main's over-deduction for families on the special £20 route without permitted work.
Reproducer: policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml
Invariants
max(0, applied standard − PC earnings disregard).Validation and dependencies
Prior-head validation at
a67175429, after main6030cbc0b: permitted-work YAML 37/37; applicable-income directory 182/182; 13 HB Python files plus CTR pensioner earnings 161/161 (-n 2), without skips/failures. Age-agreement and selected-standard properties passed separately; Ruff formatting/lint andgit diff --checkwere clean.Current-head validation: savings-credit YAML 13/13 and permitted-work YAML 37/37 passed; all six Hypothesis properties implementing I1–I5 passed individually with
-kand-n 1; the existing selected-standard property passed separately. Ruff formatting/lint passed on all seven Python files changed by the PR, andgit diff --checkpassed. Scratch mutations intentionally failed: old ordinary subtraction produced 4 YAML failures/11 passes and failed I1/I2; removing the lone-parent arm produced 2 YAML failures/13 passes and failed I1. All working-source byte-identity guards passed. The fixed source passed all 15 extended YAML checks, including the reduced controls, in 43.50 s. No local full suite, microsimulation or dataset load.CI snapshot at 12:39 UTC: Fix Evidence passed at
f06c4ea82; an earlier duplicate was cancelled. No test or Aggregate impact run is visible for this head. Existing Aggregate comment6462145998links run40636400448at old heada67175429and is not credited to the new head. The 30-minute impact-wait limit passed while local mutation verification continued; no further CI wait.#2225's special standard merged on 25 October; this branch merged main at
a60062f0eand again at65da54d84(mergeac857c27a, which keeps the shared applied-standard call and moves #2703's corrected paragraph citation intohousing_benefit_applied_standard_earnings_disregard.py). Childcare and first-year accommodation changes (#2229, #2234) follow this replacement.axiom: TheAxiomFoundation/rulespec-uk#375 queued; TheAxiomFoundation/rulespec-uk#434 queued
Rulespec extension evidence, statutory outputs and companion tests were recorded by the UK hub on 24 October.
#375 queues the earnings/special/permitted-work extension; #434 separately queues the regulation 27 savings-credit pipeline. Corpus blockers and the subsequent signed-approval requirement are recorded; no encoder has been dispatched.