PolicyEngine / PolicyEngine/policyengine-scorecard
Forcing take-up ON zeroes housing_benefit_pensioners — the fullpart denominator is unusable until this is resolved
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- Avg merge
- 6d 12h
- Merged PRs (30d)
- 32
Description
Found by the first real UK compute run (#127, toward #76), on the certified populace-uk-2023-dd68c73-4aa4b14-20260619T023711Z artifact at policyengine-uk 2.89.2.
What happened
compute_uk_counterparts.py runs two sims: baseline (calibrated take-up) and fullpart (take-up forced on, to give the entitled-population denominators the DWP take-up counterparts need). The pipeline's own invariant then aborted:
forcing take-up ON made these values FALL, which is impossible for a
take-up denominator and is how a receipt-gated benefit reads as healthy:
housing_benefit_pensioners recipient_count 380,069.49 -> 0.0
housing_benefit_pensioners benefit_spending £2,623,951,195.87 -> 0.0
Do not publish this run.
14 of 30 take-up-sensitive values rose as expected. This one didn't just fail to rise — it went to exactly zero.
Why it matters
The whole point of the fullpart run is to produce entitled denominators so a take-up rate can be computed as recipients / entitled. A denominator of zero does not produce a wrong rate; it produces an undefined one. And the failure mode the guard names is the dangerous version: if this had been left unchecked, a receipt-gated benefit would read as healthy rather than broken.
So no UK take-up counterpart involving pensioner housing benefit can be published until this is understood.
Likely mechanism (hypothesis, not verified)
Forcing would_claim_* / claims_all_entitled_benefits on plausibly migrates pensioner households onto Universal Credit, so the legacy pensioner housing-benefit population empties. If so the zero is arithmetically correct for the world the override creates — and the problem is that the override creates the wrong counterfactual for this benefit, not that the engine miscomputes.
That would make it a question about what fullpart should mean for legacy/UC-overlapping benefits, not a bug to patch. Note the other legacy benefits in the same run (jsa, esa_income, housing_benefit_pensioners) all show 0/1 — they did not rise either. universal_credit shows 1/1. That pattern is consistent with the migration hypothesis and is the first thing to check.
What needs deciding
- Confirm or reject the migration hypothesis by inspecting which override flags are set for pensioner HB and where the population goes.
- Decide the contract: does
fullpartforce take-up per benefit (holding legacy/UC routing fixed), or does it force the whole entitlement cascade? The current override does something closer to the latter, and the take-up denominators need the former. - Whichever way, keep the guard. It did its job — this is the run it existed for.
Not blocked on
#127 (the compute route) is independent and honest about this: it publishes nothing, and data/pe/ carries no UK artifact. UK coverage stays at 14 results.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with compute_uk_counterparts.py and the certified UK artifact from the first compute run. Inspect which override flags apply to pensioner housing benefit and where affected households move, then compare the legacy benefits with universal_credit. Done means the migration hypothesis is confirmed or rejected, the fullpart contract is decided, and the existing guard remains in place.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 38/100