Repository navigation
Keep the protected UC LCWRA amount from 2030-31 - #2428
Conversation
The rebalancing scenario set the UC health element only for 2026-27 to 2029-30. From 2030-31 every LCWRA claimant fell to the new-claimant amount, a protected claimant from £457.15 to £235.86 a month. Universal Credit Act 2025 s. 2 relabels the reg. 36 rows for good; s. 3 disapplies the SSAA 1992 s. 150 up-rating only in the tax years ending 5 April 2026 to 5 April 2029; s. 4's floor covers only 2026-27 to 2029-30. So both amounts continue and are uprated again from 2030-31. - The scenario now sets the element to the end of the data's projection (PROJECTION_END_YEAR, 2032). - A protected amount with no stated value takes the s. 4 floor to 2029-30 and, from 2030-31, the year before's amount uprated by elements.disabled.uprating, the index the new-claimant amount follows. - The new-claimant share is the parameter rebalancing.new_claimant_share: WPI Economics' 2026-27 to 2029-30 shares, held at 22% after, a stated assumption. Tests: no drop from 2029-30 to 2030-31 for a protected or new claimant; the protected amount's path from 2030-31; a 2030-31 reform to either amount moves Universal Credit; the element never falls for any CPI path and Universal Credit never falls for non-negative CPI; the draw reads the share in every year it sets. Ending the loop at 2029 fails 5 tests; keeping the s. 4 floor after 2029 fails 1. Fixes #2282. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…amount - uc_reform.REBALANCING_YEARS: the tax years in which the rebalancing scenario sets the element (2026 to PROJECTION_END_YEAR), one public name other code can read (the UK hub's guard for elements.disabled.amount reforms). - The non-negative-CPI property also checks that the protected amount is never below the new-claimant amount in any year (UK hub's spec on #2282). - Two of #2284's tests assumed the formula decides 2030-31 awards. With the scenario setting 2030-31, a household without a stated claim status gets the protected amount, so they now state a new claimant, and the reform-dict test changes new_claimant_health_element, the amount the scenario pays. Refs #2282. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- #2284 review round 7: a reform can name the generated index directly. It is a calendar-year series written just after the builder and before uprating, so it replaces the freeze and the no-fall floor for the years it names. The builder docstring, the index's description and the docs say so, and a test checks it for "2028" and "2028-01-01". - #2428 review round 1: the scenario sets the element to 2032-33, so the formula decides from 2033-34; the docs and the new-claimant amount's description said 2032-33 and 2029-30. Refs #2282. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Hand-off to the UK hub (session local_51f6a5a6-ef54-422b-aa89-8a8130a675ef).
axiom: TheAxiomFoundation/rulespec-uk#367 queued (UC Act 2025 ss. 3 and 4, |
The dataframe export test and two rebalancing tests hard-coded 2026 to 2029, so the protected LCWRA amount running on to 2030-31 (#2428) failed CI. They now read REBALANCING_YEARS, the scenario's own range. Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Hand-off: test years derived from Head: Fix. Results at
Audit of hard-coded rebalancing years.
Status. CI is pending at this head (Test Python 1-4, YAML, docs, fix evidence). |
|
Landed by the UK hub (merge queue, pinned to head
|
…into uc-hb-split-shared-cap-lha-rules No conflicts. Main's two edits to files this PR also changes (test_benefit_cap_specified_benefits_properties.py: REBALANCED_YEARS from REBALANCING_YEARS; test_legacy_award_readers_properties.py: comment) merged automatically. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #2282.
Reproducer: policyengine_uk/tests/test_uc_health_element_after_freeze.py::test_protected_amount_is_uprated_by_the_element_index_from_2030_31
Builds on #2284 (the UC Act 2025 s. 3 freeze, merged as 0f20450), which adds the uprating index this PR uses. Retargeted to
main.What was wrong
universal_credit_july_2025_reform(scenarios/uc_reform.py) set the health element only for 2026-27 to 2029-30 (range(2026, 2030)). From 2030-31 theuc_LCWRA_elementformula paid every LCWRA claimantelements.disabled.amount, the new-claimant amount, including pre-2026, severe conditions criteria and terminally ill claimants. Onmaina protected claimant went from £457.15 a month in 2029-30 to £235.86 in 2030-31.The law
So both amounts continue from 2030-31 and are uprated under s. 150. For UC amounts that uprating is discretionary (s. 150(2)(b); s. 150(3) does not list them); the model assumes it follows the benefit uprating index, as for every other UC amount.
Changes
scenarios/uc_reform.pyPROJECTION_END_YEAR(2032), not to 2029-30.gov.economic_assumptions.indices.uc_health_element, the index the new-claimant amount follows (Freeze the UC LCWRA element for 2026-27 to 2029-30 (UC Act 2025 s. 3) #2284). The index is the benefit uprating index, held in any year the freeze is in force, and never falls.REBALANCING_YEARS(2026 toPROJECTION_END_YEAR), for other code to read (the UK hub's guard forelements.disabled.amountreforms).rebalancing/new_claimant_share.yaml(new): 11%, 13%, 16% and 22% for 2026-27 to 2029-30, WPI Economics' estimates for the Trussell Trust (the values that were in the code), held at 22% from 2030-31. That hold is an assumption, not a source: the share keeps rising as the caseload turns over, so holding it understates new claimants and overstates protected amounts from 2030-31. I could not find the WPI publication online, so the parameter cites the Act rather than a link.protected_health_element.yaml: the description gives the post-2029 rule.uc-rebalancing.mdexplains the post-2029 amounts and the share.Still not covered: from 2033-34, after the data's projection, the scenario no longer sets the element and the formula pays every claimant the new-claimant amount. Removing that limit means computing the element in the formula from the claim status and the parameters, which is #2252's proposal.
Invariants
main's dated reforms define for an uprated parameter. The draw reads the share in every year it sets.Tests
policyengine_uk/tests/test_uc_health_element_after_freeze.py:new_claimant_health_element, the amount the scenario pays;new_claimant_sharein every year to 2031-32, and a reform to it for 2031-32 changes that year's status.Mutation check. Ending the scenario's loop at 2029 fails 5 tests; keeping the s. 4 floor after 2029-30 fails 1.
Local runs at 727085c (
mainmerged): this file,test_uc_health_element_freeze.py,test_uc_rebalancing.py,test_dwp_published_rates.py,code_health/test_cached_arrays_not_written_in_place.pyandtest_process_time_reforms.py::test_generated_parameters_are_the_series_processing_builds: 1380 passed, 64 skipped; UC YAML policy tests: 482 passed. Earlier, at b6f3f3f: this file,test_uc_health_element_freeze.py,test_uc_rebalancing.py,code_health/test_cached_arrays_not_written_in_place.pyandtest_process_time_reforms.py::test_generated_parameters_are_the_series_processing_builds: 84 passed. The impact runs were at 577f549; later commits rename and test, and move the index without changing its values.Impact
Three full microsimulation runs on
enhanced_frs_2024_25.h5@1.58.1, 2029-30 to 2032-33, nothing scaled:main(1a31ef1), #2284 (f1a495d) and this branch (577f549). £bn a year.universal_credit, this PR minus #2284uc_LCWRA_element, this PR minus #2284gov_balance, this PR minus #2284household_net_income, this PR minus #2284universal_credit, this PR minusmainhousehold_net_income, this PR minusmainuc_LCWRA_elementtotal goes back to its 2029-30 level and rises with it (£31.9bn in 2029-30; £32.7bn, £33.5bn and £34.3bn after), instead of falling to £18.7bn on Freeze the UC LCWRA element for 2026-27 to 2029-30 (UC Act 2025 s. 3) #2284 and £19.9bn onmain.uc_LCWRA_elementcovers every benefit unit with LCWRA (6.55m in 2030-31), on Universal Credit or not, so it moves by more than Universal Credit does.main, 2030-31: 1.75m households gain £4.77bn and 0.55m lose £174m (£318 each). The difference from the Freeze the UC LCWRA element for 2026-27 to 2029-30 (UC Act 2025 s. 3) #2284 comparison is Freeze the UC LCWRA element for 2026-27 to 2029-30 (UC Act 2025 s. 3) #2284's freeze:mainuprates the new-claimant amount through 2026-29.Protected and new claimants (benefit units with LCWRA, millions; 22% flat): 5.18 protected and 1.34 new in 2029-30; 5.21 and 1.35 in 2030-31; 5.23 and 1.35 in 2031-32; 5.25 and 1.36 in 2032-33.
Sensitivity: a rising new-claimant share
d1595 asks whether to hold the share at 22% or let it rise. This is a fourth real run of this branch with the share on the 2026-29 least-squares trend (11%, 13%, 16%, 22% rise 3.6 points a year): 24.5%, 28.1% and 31.7% for 2030-31 to 2032-33, set through
Scenario(parameter_changes=...)onrebalancing.new_claimant_share. Either path is a one-line change to that parameter.universal_credit, 22% flat minus #2284universal_credit, rising minus #2284uc_LCWRA_element, 22% flat minus #2284uc_LCWRA_element, rising minus #2284universal_credit, rising minus 22% flatuniversal_credit, rising minusmainmain: households gainingmain: households losingThe weighted share of LCWRA benefit units drawn as new claimants sits below the parameter (23.6% against 24.5% in 2030-31; 20.5% against 22% in 2029-30). The seeded draw is independent of LCWRA status, so the gap is sampling variation in the weighted data, the same on
main.Outputs:
~/reviews/uk-lcwra-s3-freeze/impact2282/results/(compare.txt,compare_rising.txtand the four runs' arrays).Review
~/reviews/uk-lcwra-s3-freeze/review-2428-r1.md.mainis merged).mainafter Freeze the UC LCWRA element for 2026-27 to 2029-30 (UC Act 2025 s. 3) #2284 landed): approve the PR as a whole. The diff againstmainis byte-identical to the approved change plus the docstring fix. File:review-2428-r3.md.Overlaps
rebalancing.activefalse gives everyone the Act's £217.26): unchanged here.axiom: TheAxiomFoundation/rulespec-uk#367 queued (UC Act 2025 ss. 3 and 4, labelled
pe-parity; s. 3 companion cases added there for #2284). rulespec-ukuk/regulations/uksi/2013/376/36.yamllcwra_protected_claimant_amountholds 429.80 with no later version; the post-2029 s. 150 uprating is the s. 150 module #367 queues.Test-year fix (a66d1ad)
CI failed
test_dataframe_dataset.py::test_an_export_names_the_people_in_each_year_the_rebalancing_recordsat 727085c: it hard-coded the rebalancing years as 2026 to 2029, but the scenario now runs toREBALANCING_YEARS(2026 to 2032). The test now derives its expected columns from that constant. Two tests with the same hard-coded years are changed the same way (test_benefit_cap_specified_benefits_properties.py,test_uc_rebalancing.py). Test files only; no source, data or parameter changes.Test results at a66d1ad (
-n 4, test fixtures only, no microdata):test_dataframe_dataset.py: 78 passed. The same test fails at 727085c with the CI message.test_benefit_cap_specified_benefits_properties.py: 26 passed.test_uc_rebalancing.py: 17 passed.test_section_4_floor_treats_a_cpi_fall_as_zerohit a Hypothesistoo_slowhealth check under host load in the full-file run; run alone it passes.uvx ruff format --check .: 1721 files already formatted;ruff checkon the three files passes.Review of this head is pending with the UK hub. The author of this change did not review it.
🤖 Generated with Claude Code