Repository navigation
Conversation
Universal Credit Act 2025 s. 3(1) disapplies SSAA 1992 s. 150(1) and (2) for the LCWRA and LCW elements in the tax years ending 5 April 2026 to 5 April 2029. An up-rating order takes effect from the tax year after it is made (s. 150(10)), so the rates for 2026-27 to 2029-30 are not uprated. The element was uprated by gov.benefit_uprating_cpi, giving £222.26 for 2027-28. It is now uprated by gov.dwp.universal_credit.elements.disabled. uprating, which a process_parameters builder makes from the benefit index (as uprating extends it), held flat while rebalancing.health_element_freeze and rebalancing.active are true, and never falling. Refs #2280. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Examples for 2026-27 to 2030-31; a differential against the processed benefit index; reforms (freeze or rebalancing off, one year unfrozen, a changed amount, a reform dict); and Hypothesis properties: frozen years hold for any CPI path, later years grow with the benefit index and never fall, any freeze/active schedule holds exactly its years, and a reformed amount is held or uprated from its value. YAML cases pin 2027-28 to 2029-30 at £2,607.12 a year. Mutation check: main's uprating fails 8 pytest and 3 YAML cases; dropping the no-fall floor fails 3 properties; ignoring rebalancing.active fails 2. Refs #2280. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #2280. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/book/policy/uc-rebalancing.md
This was referenced Oct 10, 2026
Review finding: for 2026-27 to 2029-30 the rebalancing scenario pays new claimants rebalancing.new_claimant_health_element, a flat £217.26, so lifting the freeze changed elements.disabled.amount but no simulated award in those years. new_claimant_health_element is now uprated by gov.dwp.universal_credit.elements.disabled.uprating as well. The two amounts follow one path under any freeze schedule or CPI forecast, and a lifted freeze reaches a simulated new claimant (£221.60 in 2028-29 with the freeze lifted from that year). Baseline amounts do not change. Tests: the one-path invariant on the baseline, under freeze and CPI reforms, and in the tree properties; a simulation test with a forced new claimant. Without the uprating line 5 tests fail. Docs: say which parameter a simulation reads in which years, apply the example before the data load, and note the no-fall floor is this element's only. The index's description says how to change it. Refs #2280. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…year Review round 2: the uprating index stopped at the calendar year of the last benefit-index (or lagged CPI) entry. A value dated after 30 April first reaches the next tax year's 30 April sample, so that year's change was lost. Reproduced on the full pipeline: a one-year change to the benefit index from 1 June 2038 restores the stated value on 1 June 2039; the processed index doubles from 2039-40 to 2040-41, but the element stayed at £217.26 instead of £434.52. index_years now runs to the first tax year whose 30 April sample sees the last entry, using create_threshold_indexation.first_tax_year. Baseline amounts do not change. Tests: the reviewer's case on the full pipeline (both amounts, against the independent recursion), and a property with up to three benefit-index values at any date, including after 30 April and past the last uprating entry. Reverting the fix fails both. Also from the review: the docs say a reform to either amount does not move the other, and a test comment describes core's latest-stated-value rule rather than calling it the statutory path. Refs #2280. 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 #2280.
What was wrong
gov.dwp.universal_credit.elements.disabled.amount, the LCWRA element (£217.26 a month from April 2026), was uprated bygov.benefit_uprating_cpi. The model therefore projected £222.26 for 2027-28, £226.70 for 2028-29, £231.24 for 2029-30 and £235.86 for 2030-31. The Universal Credit Act 2025 freezes the element for 2026-27 to 2029-30.The law
Universal Credit Act 2025 s. 3(1):
The disapplied years are the years in which the review is made, not the years whose rates are frozen:
DWP's 2026-27 rates confirm the first year. The LCW element stayed at £158.76, while the lower disabled child addition, also £158.76 in 2025-26, rose to £164.79 (3.8%).
The review in 2029-30 is not disapplied, so the element can rise again from April 2030. s. 150(3), which lists the sums that must rise at least with prices, does not include the Universal Credit amounts, so the 2030-31 increase is discretionary under s. 150(2)(b). The model assumes it follows the benefit uprating index, as for every other UC amount. s. 150(2) provides only for increases, so the element never falls.
The report that started this (on #1925) said the freeze runs "through the tax year ending 5 April 2029", meaning no CPI uprating in 2027-28 or 2028-29. Read with s. 150(10), it runs a year longer: 2029-30 is frozen too.
Scope
universal_credit_july_2025_reformapplies for 2026-27 to 2029-30 (Pay pre-2026 UC health element claimants the legislated protected amount #2248, merged). This PR does not change that.Changes
rebalancing/health_element_freeze.yaml(new, bool): true for the rates of 2026-27 to 2029-30, keyed from 6 April 2026 and false from 6 April 2030. Each value cites s. 3(1).rebalancing/create_health_element_uprating.py(new) runs inprocess_parameters, after the economic assumption indices and threshold indexation and before uprating. It buildsgov.dwp.universal_credit.elements.disabled.uprating. That index isgov.benefit_uprating_cpias uprating will extend it, with any reform to it included and each year read at the 30 April sampling date. It stays flat in each year wherehealth_element_freezeandrebalancing.activeare both true, and it never falls.elements/disabled/amount.yamlis uprated by that index. Its description now names the new-claimant row and the freeze, and it cites ss. 2 and 3.rebalancing/new_claimant_health_element.yamlis uprated by the same index. For 2026-27 to 2029-30,universal_credit_july_2025_reformpays new claimants this second copy of the s. 2 amount, which was a flat £217.26. Without this change, lifting the freeze would have moved the parameter but no simulated award in those years (review round 1). The two amounts now follow one path.uc-rebalancing.mdexplains the freeze, says which of the two parameters a simulation reads in which years, and gives an example of lifting the freeze.The result. The element is £217.26 a month for 2026-27 to 2029-30. From 2030-31 it rises by one year's benefit-index growth at a time, from £217.26 rather than from a CPI path that also counts the frozen years: £221.60 for 2030-31, against £235.86 on
main.Reforms
Scenario(parameter_changes=...)re-runs parameter processing, so changes to any of these reach the element:rebalancing.active(false means no freeze, matching Apply the Universal Credit Act 2025 standard allowance uplifts to 2029-30 #2242's reading ofactive);reform=dict changes the year it names.applied_before_data_load=True, because the reform modifier sets those awards when the simulation is built (UC rebalancing reforms don't take effect unless the Scenario applies before the data load #2252).Design notes
create_threshold_indexation.py: it runs inprocess_parameters, reads at the 30 April sampling date and keys its index values to 1 January.create_standard_allowance_uprating.pyfor the "index the amount'supratingmetadata points to" pattern.projected_valuemirrors core's non-cadence uprating exactly. It raisesNotImplementedErrorif the benefit index's uprating ever gains options, or its uprater gains its own uprating, so a change there fails loudly.Review
Independent reviews on Subfleet, read-only:
model-structure.md.Files:
~/reviews/uk-lcwra-s3-freeze/review-r{1,2,3}.mdand the responses beside them.Invariants
health_element_freezeandrebalancing.activeare both true (2026-27 to 2029-30 in law), the amount equals the previous year's, for any CPI path.parameters.govand the unconvertedparameters.baseline. This holds also when a benefit-index value is dated after 30 April: it reaches the next tax year (review round 2).rebalancing.new_claimant_health_elementequalselements.disabled.amountin every year from 2026-27, under any freeze schedule or CPI path. So a lifted freeze reaches a simulated new claimant.Tests
policyengine_uk/tests/test_uc_health_element_freeze.py(21 tests):main's four-year path. A household with LCWRA gets 12 × the 2030-31 amount.activeoff: CPI uprating from 2027-28,main's path;reform=dict.Scenario(applied_before_data_load=True)). Frozen years stay at £217.26, and later years follow invariant 2.uprate_parameters(200 examples each):uc_LCWRA_element.yaml: 2027, 2028 and 2029 cases at £2,607.12 a year (12 × £217.26).Mutation check. Each of these fails tests:
main's uprating (gov.benefit_uprating_cpi): 8 pytest cases and the 3 new YAML cases.rebalancing.active: 2 tests.new_claimant_health_element: 5 tests.Local runs (one process each, fresh
--basetemp):main4d80b29 merged): the new file withtest_uc_rebalancing.py,test_no_economic_assumptions.py,test_fiscal_year_parameters.pyandtest_threshold_indexation.py: 141 passed, 1 xpassed. UC YAML policy tests: 417 passed.mainand before the review fix: the new file withtest_uc_rebalancing.py,test_parameter_metadata.py,test_build_metadata.py,test_fiscal_year_parameters.py,test_no_economic_assumptions.py,test_threshold_indexation.py,test_lagged_series.pyandcode_health/test_cached_arrays_not_written_in_place.py: 225 passed, 1 skipped, 1 xpassed.test_parameter_metadata.py,test_build_metadata.py,test_fiscal_year_parameters.py,test_no_economic_assumptions.py,test_threshold_indexation.py,test_lagged_series.pyandcode_health/test_cached_arrays_not_written_in_place.py: 204 passed, 1 skipped, 1 xpassed. UC YAML policy tests (tests/policy/baseline/finance/benefit/family/universal_credit): 417 passed.Impact
Two full microsimulation runs on
enhanced_frs_2024_25.h5@1.58.0:mainat 9475c95 and this branch at f68400f, for 2026-27 to 2030-31. Nothing is scaled. £bn, branch minusmain.universal_credituc_LCWRA_element(every benefit unit with LCWRA)gov_balancehousehold_net_income2026-27 to 2029-30: nothing changes, in any household or benefit unit (the largest change in any of the four variables is exactly 0). In those years
universal_credit_july_2025_reformsets every claimant's element: new claimants fromrebalancing.new_claimant_health_element, which was already a flat £217.26, and protected claimants from the s. 4 floor. So simulated awards already had the freeze. What was wrong before 2030-31 was the parameter itself, which is what a calculation without the modifier reads (the YAML test runner, orrebalancing.activefalse) and what the parameter listing shows.2030-31: the element is £221.60 a month, not £235.86, which is £14.25 a month or £171.05 a year lower for each claimant with LCWRA.
uc_LCWRA_elementis computed for every benefit unit with LCWRA, on Universal Credit or not (6.64m), so it moves by more than Universal Credit does.Read the 2030-31 figures with #2282 in mind. From 2030-31 the model pays
elements.disabled.amountto every LCWRA claimant, including protected claimants who keep a much higher amount in law. Onmain,uc_LCWRA_elementfalls from £32.3bn in 2029-30 to £20.1bn in 2030-31 for that reason; here it falls to £18.8bn. This PR corrects the amount new claimants get in 2030-31. Its effect is spread over all claimants only because of #2282. Once #2282 is fixed it will apply to new claimants alone, and the national figure needs a new run then.Overlaps
tax_benefit_system.py, where both add a builder call inprocess_parameters, anduc-rebalancing.md. Tested on a local merge of this branch (b30bc54) with Apply the Universal Credit Act 2025 standard allowance uplifts to 2029-30 #2242 (2248c19), keeping both builder calls:test_uc_health_element_freeze.py,test_uc_standard_allowance_uplift.py,test_uc_rebalancing.py,test_no_economic_assumptions.pyandtest_parameter_metadata.pygive 45 passed. On that merge the element is £217.26 for 2026-27 to 2029-30 while the single 25+ standard allowance rises from £424.90 to £438.07, £450.73 and £463.28. The s. 4 floor reads the standard allowance and September CPI, not this element's index, so the two changes do not interact before 2030-31.mainis merged in. Its floor already keeps the protected amount from falling, which is consistent with s. 3.uc_reform.pyonly; no overlap.elements.disabled.amountbecause of s. 3. With this PR, the projection continues from the 2026-27 rate by this element's own uprating index, so the skip can go. Checked on a local merge of this branch (f68400f) and Set DWP benefit rates to the announced amounts, not CPI projections #1925 (e1bf98b) withelements.disabled.amountremoved fromUC_ACT_2025_EXCEPTIONS: its differential, fixed-start and continuity tests pass for this parameter and forrebalancing.new_claimant_health_element, which its fixture also covers and which is now uprated (49 passed; only the four standard allowance amounts still skip, for s. 1). Whichever PR merges second should drop that line; I have left a note on Set DWP benefit rates to the announced amounts, not CPI projections #1925.benefit-uprating-september-cpi(unowned) moves benefits to September CPI. If it changes the index that UC amounts use,BENEFIT_INDEX_NAMEin the new builder should follow, so that the freeze holds whichever CPI measure is used.Follow-ups (not in this PR)
elements.disabled.amount. Onmaina protected household goes from £457.15 a month in 2029-30 to £235.86 in 2030-31; with this PR, to £221.60. This PR corrects the new-claimant amount but does not restore the protected amount. That is why the 2030-31 impact above reaches every claimant.rebalancing.activefalse, everyone gets the Act's £217.26.rebalancing.new_claimant_health_element, notelements.disabled.amount. This PR makes the two follow one path, but a reform to one still does not move the other. Paying the element from one parameter in the formula is UC rebalancing reforms don't take effect unless the Scenario applies before the data load #2252's proposal.axiom: TheAxiomFoundation/rulespec-uk#367 queued (UC Act 2025 s. 3, labelled
pe-parity; s. 3 companion cases added there). The encoder path is blocked:uk/statute/ukpga/2025/22/3is not in the served corpus (404 on 2026-10-10). rulespec-ukuk/regulations/uksi/2013/376/36.yamllcwra_ordinary_claimant_amountis 217.26 with no later version, which agrees for the frozen years.🤖 Generated with Claude Code