Repository navigation
Conversation
W1's population_uc_standard_allowance_plus_10 required that no universal_credit amount fall when every standard allowance rises 10%. universal_credit is the amount paid, net of deductions. Under the benefit cap (Universal Credit Regulations 2013, SI 2013/376, reg 81) a capped award stays flat, and deductions are taken from the award as percentages of the standard allowance (Claims and Payments Regulations 2013, SI 2013/380, Sch 6), so a capped claimant with deductions is paid less. policyengine-uk 2.130.1 applies deductions to simulations built from data (#1905), so one benefit unit in the 1,000-household subsample shows exactly that; 2.126.12 applied none below 1e6 benefit-unit weight, so the subsample never had deductions. The check now asserts what the law makes invariant: - no award before deductions (universal_credit_pre_benefit_cap less benefit_cap_reduction) falls; - no payment falls by more than its deductions rise; - no deductions rise by more than the standard allowance; plus, as before, exact 10% scaling and at least one higher payment. The verdict is a pure function, uc_allowance_verdict, with a test for the lawful capped case and one for each unlawful movement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UK hub pointed out that "deductions rise by no more than the standard allowance" holds only while uc_deduction_rate <= 1: policyengine-uk 2.130.1 adds the latent excess above the deductions cap (deductions the cap does not limit) with no bound of its own. The check now requires that no unit's deduction rate changes under the reform (the rate does not depend on the allowance) and that its deductions rise by no more than that rate times the allowance rise, which is tighter for ordinary rates and still correct above 1. Tests cover a rate above 1 and a changed rate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UK hub's independent legal check (AGREE_WITH_CHANGES) confirms the invariants as model invariants: Universal Credit counts towards the cap before any deduction (SI 2013/376 reg 80(2)); in law a sanctioned capped award can fall (regs 110, 111), which the model, applying no sanctions, cannot show; advances are recovered as fixed amounts (SI 2013/383 reg 10), so the model's deduction rise is an upper bound (policyengine-uk#2410). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round-1 review of #614 and the full contract run on policyengine-uk 2.130.1 show that the deduction-rate assertions encoded the model's formula, not the law, and fail lawful cases: - deductions start with a new award (56 units on the full 1.58.1 file whose rate goes from 0 because their baseline award was nil); - the one-penny minimum payable binds (53 units); - in law advances are fixed amounts (SI 2013/383 reg 10), so no allowance-proportional bound is an invariant of both law and model. The check now requires: - no award before deductions falls by more than a penny (float32 rounding in these sums is a few thousandths of a pound; the round-1 review found the two "falling awards" on 2.126.12 were 0.0039 a year); - each payment moves by its award's change less its deductions' change, to the penny (signed, so a missing deduction release is caught); - exact 10% scaling and at least one higher payment, as before. How much deductions rise is documented as unchecked here. On the full 1.58.1 file both 2.126.12 and 2.130.1 hold; tests pin the penny boundary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#612's population stub raised universal_credit under the UC allowance reform but not universal_credit_pre_benefit_cap, so on this branch the payment no longer equalled the award less deductions and #614's accounting assertion rightly failed three coverage tests. The stub now raises the award with the payment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round-2 review of #614: - Medium: deductions may not reduce the amount payable below a penny an assessment period (SI 2013/380 Sch 6 para 3(1)(a)). The check now requires every payment, in both runs, to be at least the lesser of its award and 12p a year, so deductions that take a whole award fail. - Medium: every value the check reads must be finite in both runs; a NaN deduction, cap reduction or award no longer passes the comparisons. - Low: the award-decline case lowers the award and its payment together, so only the award condition catches it; new tests cover errors that cancel across units, the penny boundary on gains, the 10% scaling tolerance and a payment left at exactly the floor. Removing any one of the four conditions fails a test. - Low: the population stub has no cap reduction or deductions, so its payments equal its awards at every level. - #612 review Low: assertion ids are tested on extraction-error, pending and unsupported rows too. On the full 1.58.1 file with policyengine-uk 2.130.1 the check holds: 0 award falls, 0 accounting breaks, 0 payments below the floor, 0 non-finite values. All 66 runner tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #613
Stacked on #612. These files belong to workstream W1 (the UK Budget reform contract:
budget_reform_population.py). W1's session is idle, so W4 opens this change by the coordinator's ruling. Unlike #612, this changes a verdict. It is a declared change citing the regulations, not an exemption. Hold: this merges only after the UK hub's legal check (done: AGREE_WITH_CHANGES) and this PR's independent review both agree.What changes
population_uc_standard_allowance_plus_10used to require that nouniversal_creditamount fall when every UC standard allowance rises 10% for 2027-28.universal_creditis the amount paid, net of deductions, and the law lets the amount paid fall. The old assertion was therefore blind to the award and wrong for capped claimants with deductions.It is replaced by two assertions that hold for every benefit unit:
universal_credit_pre_benefit_capminusbenefit_cap_reduction. The benefit cap reduces the award by the excess of welfare benefits over the cap (Universal Credit Regulations 2013, SI 2013/376, reg 81), counting Universal Credit before any deduction (reg 80(2)), so a capped award stays flat.As before, the allowance must scale by exactly 10% and at least one payment must rise.
Not checked here: how much deductions rise. An earlier commit on this branch bounded that by the deduction rate times the allowance rise. That bound encoded the model's formula, not the law, and it failed lawful cases on the full 1.58.1 file:
In law, advances are also fixed amounts (SI 2013/383 reg 10), while the model scales every deduction type with the allowance (policyengine-uk#2410). So no allowance-proportional bound holds for both law and model.
Why a penny. These amounts are float32 annual pounds, and their sums round by a few thousandths of a pound. The review found the largest award "decline" on 2.126.12 was £0.0039 a year.
The verdict is a pure function,
uc_allowance_verdict. Tests cover:Why now
policyengine-uk 2.130.1 fails the old check on one benefit unit in the seeded 1,000-household subsample: a capped award whose deductions rise. 2.126.12 passed only because its
uc_deduction_random_drawapplies no deductions when benefit-unit weight sums below 1e6, as the subsample does. policyengine-uk #1905 changed that gate tobuilt_from_data.The full published uk-data 1.58.1 file, with every standard allowance +10% for 2027-28 (counts only):
A correction: an earlier version of this description said 2.126.12 had two falling awards, fixed by policyengine-uk #2076. Those were float32 rounding of £0.0039 a year at most. Neither version has a real award decline.
Legal check
An independent check by the UK hub, run by an Opus 5.5 reviewer, returned AGREE_WITH_CHANGES (
~/reviews/uk-hub/reviews/uc-cap-deductions-ruling/review-opus.md):Invariants
axiom: n/a: test-contract invariant; no policy encoding changes
🤖 Generated with Claude Code