Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/test_outcome_allowlist.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@ why = "Microsimulation tests need the private dataset. Runs without its credenti
[[allow]]
nodeid = "policyengine_uk/tests/test_dwp_published_rates.py::test_projection_continues_from_last_published_rate[[]*"
outcome = "skipped"
reason = '^(not uprated|series ends before 2026-27|Universal Credit Act 2025 ss\.1 and 3 depart from CPI uprating)$'
why = "The test is parametrised over every DWP rate parameter and skips those it does not apply to: parameters with no uprating, series that end before 2026-27, and the five the Universal Credit Act 2025 ss.1 and 3 set apart from CPI uprating (the four UC standard allowances and the LCWRA element, #1925). 66 cases on 12 October 2026."
reason = '^(not uprated|series ends before 2026-27|Universal Credit Act 2025 s\.1 departs from CPI uprating)$'
why = "The test is parametrised over every DWP rate parameter and skips those it does not apply to: parameters with no uprating, series that end before 2026-27, and the four UC standard allowances, whose minimum the Universal Credit Act 2025 s.1 sets above CPI uprating (#1925). The LCWRA element, frozen by s.3, is checked against its own uprating index (#2284). 64 cases on 12 October 2026."
1 change: 1 addition & 0 deletions changelog.d/uc-lcwra-s3-freeze.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Hold the Universal Credit LCWRA element at £217.26 a month for 2026-27 to 2029-30, as Universal Credit Act 2025 s. 3 freezes it, and uprate it from that amount by the benefit uprating index from 2030-31. It was CPI-uprated from 2027-28. The freeze is `gov.dwp.universal_credit.rebalancing.health_element_freeze` and applies while the rebalancing reforms are active. The amount the rebalancing scenario pays new claimants (`rebalancing.new_claimant_health_element`) follows the same path, so lifting the freeze reaches them.
37 changes: 36 additions & 1 deletion docs/book/policy/uc-rebalancing.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ The reforms combine a higher standard allowance, protected awards for existing h

From April 2026, new Universal Credit claimants who qualify for the Limited Capability for Work-Related Activity (LCWRA) element receive a fixed monthly amount of £217.26.

Universal Credit Act 2025 s. 3 freezes the element for 2026-27 to 2029-30: it disapplies the annual up-rating in Social Security Administration Act 1992 s. 150(1) and (2) in the tax years ending 5 April 2026 to 5 April 2029, and an up-rating order takes effect from the tax year after the one in which it is made. The new-claimant amount therefore stays at £217.26 a month to 2029-30. From 2030-31 it is uprated from £217.26 by the benefit uprating index, one year's growth at a time. It never falls, because s. 150(2) provides only for increases; other Universal Credit amounts follow the benefit uprating index directly, which gives the same result whenever the index rises.

Two parameters hold this amount, and both are uprated by `gov.dwp.universal_credit.elements.disabled.uprating`, so they follow the same path:

- `gov.dwp.universal_credit.elements.disabled.amount` is the LCWRA element the `uc_LCWRA_element` formula pays. A simulation uses it from 2030-31, and whenever the rebalancing reforms are inactive.
- `gov.dwp.universal_credit.rebalancing.new_claimant_health_element` is the amount the rebalancing scenario pays new claimants for 2026-27 to 2029-30.

A change to the freeze or to the benefit uprating index moves both. A reform to either amount itself does not change the other.

`rebalancing/create_health_element_uprating.py` builds the index when parameters are processed: the benefit uprating index, held flat in each year in which `rebalancing.health_element_freeze` and `rebalancing.active` are both true.

Existing recipients are treated differently. Universal Credit Regulations 2013 reg. 36 gives one amount, the protected LCWRA amount, to every pre-2026 claimant, severe conditions criteria claimant or terminally ill claimant, whatever their age or couple status. For 2026-27 it is £429.80 a month ([SI 2026/113](https://www.legislation.gov.uk/uksi/2026/113/made) reg. 3(3)(b)), stored in `gov.dwp.universal_credit.rebalancing.protected_health_element`.

For a tax year without a legislated amount, the model uses the lowest amount the Universal Credit Act 2025 s. 4 duty allows. For every standard allowance amount, the protected amount plus that allowance must be at least the previous year's sum, increased by the relevant CPI percentage: the CPI 12-month rate in the September before the tax year, never below 0% (s. 4(4)(a)). The model reads that rate from `gov.economic_assumptions.statutory_uprating_inputs.cpi_september`. Section 3 switches off the element's ordinary uprating, so the amount otherwise stays where it was. Run from the 2025-26 amounts at the 3.8% September 2025 CPI rate, this rule gives the legislated £429.80.
Expand Down Expand Up @@ -48,7 +59,7 @@ These uplifts are applied to the CPI-uprated standard allowance for each year. I
The reforms are implemented through parameters, scenario modifiers, and scenarios that work together to enable policy analysis.
```

- **Parameters**: YAML files define the reform's activation status, the health element amounts for new claimants and for protected (pre-2026) claimants, and the standard allowance uplift rates.
- **Parameters**: YAML files define the reform's activation status, the health element amounts for new claimants and for protected (pre-2026) claimants, the health element freeze, and the standard allowance uplift rates.
- **Scenario modifier**: The `add_universal_credit_reform` function applies the protected existing-claimant health-element path during microsimulation.
- **Scenario**: The `universal_credit_july_2025_reform` scenario enables the reforms in policy analysis.

Expand Down Expand Up @@ -110,10 +121,34 @@ scenario = Scenario(
sim = Simulation(scenario=scenario)
```

### Lifting the health element freeze

```python
from policyengine_uk import Simulation, Scenario

# Uprate the LCWRA element by CPI from 2028-29 instead of freezing it.
# A bare year names the fiscal year from 6 April.
scenario = Scenario(
parameter_changes={
"gov.dwp.universal_credit.rebalancing.health_element_freeze": {
"2028": False,
"2029": False,
}
}
)

sim = Simulation(scenario=scenario)
```

New claimants then get the uprated amount in 2028-29 and 2029-30, and every later year starts from that higher amount. The protected amount for existing claimants does not change; it follows the s. 4 floor.

The freeze reaches the element through parameter processing. A `Scenario(parameter_changes=...)` change and a `reform=` dictionary keyed by year (`reform={"gov.dwp.universal_credit.rebalancing.health_element_freeze": {"2028": False, "2029": False}}`) both re-run it, before the rebalancing scenario sets the 2026-27 to 2029-30 health elements. A `reform=` key naming a single day edits the annualised parameter on that day only and does not.

## Legislative reference

The reforms are based on the Universal Credit Bill and its impact assessment:

- https://www.legislation.gov.uk/ukpga/2025/22/section/3
- https://bills.parliament.uk/publications/62123/documents/6889
- https://bills.parliament.uk/publications/62124/documents/6892
- https://assets.publishing.service.gov.uk/media/689ca49e1c63de6de5bb1298/withdrawn-universal-credit-bill-uc-rebalancing-impact-assessment.pdf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
description: Limited capability for work-related activity element amount under the Universal Credit.
description: Limited capability for work and work-related activity (LCWRA) element amount under Universal Credit. From April 2026 this is the amount for claimants other than pre-2026, severe conditions criteria or terminally ill claimants, which Universal Credit Act 2025 s. 3 freezes for 2026-27 to 2029-30.
values:
2016-04-10: 315.6
2017-04-10: 318.76
Expand All @@ -14,10 +14,16 @@ values:
metadata:
period: month
label: Universal Credit disability element amount
uprating: gov.benefit_uprating_cpi
# Benefit uprating CPI, held for 2026-27 to 2029-30 (Universal Credit Act
# 2025 s. 3); built by rebalancing/create_health_element_uprating.py.
uprating: gov.dwp.universal_credit.elements.disabled.uprating
unit: currency-GBP
reference:
- title: The Universal Credit Regulations 2013 reg. 27 (LCWRA element), amounts in reg. 36
href: https://www.legislation.gov.uk/uksi/2013/376/regulation/36
- title: Universal Credit Act 2025 s. 2 (2026-27 amount)
href: https://www.legislation.gov.uk/ukpga/2025/22/section/2
- title: Universal Credit Act 2025 s. 3 (freeze for 2026-27 to 2029-30)
href: https://www.legislation.gov.uk/ukpga/2025/22/section/3
- title: Benefit and pension rates 2026 to 2027
href: https://www.gov.uk/government/publications/benefit-and-pension-rates-2026-to-2027/proposed-benefit-and-pension-rates-2026-to-2027
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
"""Build the uprating index for the Universal Credit LCWRA element.

Universal Credit Act 2025 s. 3(1):

Subsections (1) and (2) of section 150 of the Social Security
Administration Act 1992 (annual up-rating of benefits) do not apply, in
the tax years ending with 5 April 2026, 5 April 2027, 5 April 2028 and
5 April 2029, to the LCWRA element or the LCW element.

SSAA 1992 s. 150(1) has the Secretary of State review the Universal Credit
amounts (s. 150(1)(n)) in each tax year, and s. 150(2) provides for an
up-rating order where prices have risen; for these amounts the increase is
at the Secretary of State's discretion (s. 150(2)(b)), as s. 150(3) does not
list them. An order brings its changes into force in the week beginning with
the first Monday of the tax year after the one in which it is made
(s. 150(10)(a)(i)), for Universal Credit from the first assessment period
beginning on or after that day (s. 150(10ZA) and (10ZB)). The four
disapplied reviews, in 2025-26 to 2028-29, are therefore those that would
have uprated the rates for 2026-27 to 2029-30, the years named in the
section's heading. The review in 2029-30 is not disapplied, so the element
can rise again from April 2030.

``elements/disabled/amount.yaml`` holds the 2026-27 amount set by s. 2
(£217.26 a month) and is uprated by the index built here,
``gov.dwp.universal_credit.elements.disabled.uprating``. The index moves
with ``gov.benefit_uprating_cpi``, the model's benefit uprating index, as
uprating will extend it (including any reform to it), except in a tax year
in which ``rebalancing.health_element_freeze`` and ``rebalancing.active`` are
both true, when it stays at the previous year's value. It never falls, as
s. 150(2) provides only for increases. Uprating an amount by it therefore
holds the amount through the frozen years and then raises it by each later
year's increase in the benefit index, from the frozen amount rather than
with the frozen years' increases added back.

``rebalancing/new_claimant_health_element.yaml``, the copy of the s. 2 amount
that ``scenarios/uc_reform.py`` pays new claimants for 2026-27 to 2029-30, is
uprated by the same index, so a simulation sees the same path as the element
amount when the freeze or the CPI forecast changes. A reform to one of the two
amounts does not move the other.

The pre-2026 (protected) amount of the element is also frozen by s. 3 and
raised under s. 4; ``scenarios/uc_reform.py`` sets it for 2026-27 to
2029-30. The LCW element is not modelled.

Other Universal Credit amounts are uprated by ``gov.benefit_uprating_cpi``
directly and would fall with it; the two agree whenever the index rises.

This runs with the other generated series before uprating (see
``process_parameter_tree``). A reform written onto the statutory timeline
re-runs that processing (``policyengine_uk.utils.dated_reforms``): a
``Scenario(parameter_changes=...)`` change, or a ``reform=`` dict entry keyed
by a year or a ``start.stop`` range. So a change to the freeze, to
``rebalancing.active``, to the benefit index or the forecasts behind it, or to
an amount itself reaches the element, which is then held or uprated from the
changed value. A ``reform=`` dict key naming a single day still edits the
annualised parameter on that day only and does not re-run uprating.
"""

from typing import Dict

from policyengine_core.parameters import Parameter, ParameterNode, get_parameter

from policyengine_uk.parameters.gov.hmrc.create_threshold_indexation import (
first_tax_year,
)

INDEX_NAME = "gov.dwp.universal_credit.elements.disabled.uprating"
BENEFIT_INDEX_NAME = "gov.benefit_uprating_cpi"
# Fiscal-year conversion reads each tax year's value at 30 April.
FISCAL_YEAR_SAMPLE_MONTH_DAY = "04-30"
# Index values are keyed to 1 January, as core uprating keys its values.
INDEX_VALUE_MONTH_DAY = "01-01"


def tax_year_instant(year: int) -> str:
"""Date at which parameters are read for the tax year from April
``year``."""
return f"{year}-{FISCAL_YEAR_SAMPLE_MONTH_DAY}"


def latest_instant(parameter: Parameter) -> str:
return max(value.instant_str for value in parameter.values_list)


def uprating_parameter_name(parameter: Parameter):
"""Name of the parameter that uprates ``parameter``, or None."""
meta = parameter.metadata.get("uprating")
if meta is None:
return None
if isinstance(meta, str):
return meta
if set(meta) != {"parameter"}:
raise NotImplementedError(
f"{parameter.name} is uprated with options {sorted(meta)}; the "
"Universal Credit health element uprating reads it only as a "
"plain uprating index."
)
return meta["parameter"]


def projected_value(parameter: Parameter, parameters: ParameterNode, at: str):
"""``parameter`` at ``at`` as core uprating will extend it.

Core uprating starts from the latest stated value and adds, for each
value of the uprating index dated after it, that value times the index's
change since the latest stated date. Read before uprating runs, the
parameter itself holds only its stated values.
"""
last = latest_instant(parameter)
uprater_name = uprating_parameter_name(parameter)
if at <= last or uprater_name is None:
return parameter(at)
uprater = get_parameter(parameters, uprater_name)
if uprating_parameter_name(uprater) is not None:
raise NotImplementedError(
f"{uprater.name}, which uprates {parameter.name}, is itself "
"uprated; the Universal Credit health element uprating reads "
"only a fully stated index."
)
projected = [
value.instant_str
for value in uprater.values_list
if last < value.instant_str <= at
]
if not projected:
return parameter(at)
# Core's order: the index ratio first, then the amount.
return parameter(last) * (uprater(max(projected)) / uprater(last))


def index_years(parameters: ParameterNode) -> range:
"""Tax years in which the benefit index, once uprated, can change: from the
first year of its own values or its uprater's to the first tax year whose
30 April sample sees the last of them. A value dated after 30 April, such
as the one a one-year reform restores, first reaches the next tax year."""
benefit_index = get_parameter(parameters, BENEFIT_INDEX_NAME)
instants = [value.instant_str for value in benefit_index.values_list]
uprater_name = uprating_parameter_name(benefit_index)
if uprater_name is not None:
uprater = get_parameter(parameters, uprater_name)
instants += [value.instant_str for value in uprater.values_list]
first = min(int(instant[:4]) for instant in instants)
last = max(first_tax_year(instant) for instant in instants)
return range(first, last + 1)


def is_frozen(rebalancing: ParameterNode, year: int) -> bool:
"""Whether the element keeps the previous year's amount in the tax year
from April ``year``. A year before either parameter starts is not."""
instant = tax_year_instant(year)
return bool(rebalancing.health_element_freeze(instant)) and bool(
rebalancing.active(instant)
)


def health_element_index_values(parameters: ParameterNode) -> Dict[str, float]:
"""The uprating index, keyed to 1 January of each year."""
benefit_index = get_parameter(parameters, BENEFIT_INDEX_NAME)
rebalancing = parameters.gov.dwp.universal_credit.rebalancing
values = {}
index = 1.0
previous = None
for year in index_years(parameters):
current = projected_value(benefit_index, parameters, tax_year_instant(year))
if current is None:
continue
if previous is not None and not is_frozen(rebalancing, year):
index *= max(1.0, current / previous)
previous = current
values[f"{year}-{INDEX_VALUE_MONTH_DAY}"] = index
return values


def add_uc_health_element_uprating(parameters: ParameterNode) -> ParameterNode:
"""Add ``gov.dwp.universal_credit.elements.disabled.uprating``.

Runs after ``create_economic_assumption_indices``, which builds the index
that extends ``gov.benefit_uprating_cpi``.
"""
parameters.gov.dwp.universal_credit.elements.disabled.add_child(
"uprating",
Parameter(
INDEX_NAME,
data={
"description": (
"Uprating index for the Universal Credit LCWRA element: "
"the benefit uprating index, held flat in the tax years "
"for which the Universal Credit Act 2025 freezes the "
"element and never falling. It is built when parameters "
"are processed; to change it, change "
"gov.dwp.universal_credit.rebalancing."
"health_element_freeze or the benefit uprating index."
),
"values": health_element_index_values(parameters),
"metadata": {
"unit": "/1",
"label": "Universal Credit health element uprating index",
"reference": [
{
"title": "Universal Credit Act 2025 s. 3",
"href": "https://www.legislation.gov.uk/ukpga/2025/22/section/3",
},
{
"title": "Social Security Administration Act 1992 s. 150",
"href": "https://www.legislation.gov.uk/ukpga/1992/5/section/150",
},
],
},
},
),
)
return parameters
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
description: >-
While this parameter is true, the Universal Credit limited capability for work and work-related activity (LCWRA) element keeps its amount from the previous tax year instead of being uprated, unless an amount is stated for the year (as Universal Credit Act 2025 s. 2 states £217.26 for 2026-27). Universal Credit Act 2025 s. 3(1) disapplies the annual up-rating review and order in Social Security Administration Act 1992 s. 150(1) and (2) for the element in the tax years ending 5 April 2026 to 5 April 2029. An up-rating order changes rates from the tax year after the one in which it is made (s. 150(10)), so the frozen rates are those for 2026-27 to 2029-30, the years named in the section's heading. A year here is the tax year whose rates it governs, from 6 April. The freeze applies only while the rebalancing reforms are active.
values:
2015-01-01: false
2026-04-06:
value: true
metadata:
reference:
- title: Universal Credit Act 2025 s. 3(1)
href: https://www.legislation.gov.uk/ukpga/2025/22/section/3
2030-04-06:
value: false
metadata:
reference:
- title: Universal Credit Act 2025 s. 3(1) (disapplication ends with the tax year ending 5 April 2029)
href: https://www.legislation.gov.uk/ukpga/2025/22/section/3
metadata:
unit: bool
label: Universal Credit health element uprating freeze
reference:
- title: Universal Credit Act 2025 s. 3
href: https://www.legislation.gov.uk/ukpga/2025/22/section/3
- title: Social Security Administration Act 1992 s. 150(1), (2) and (10)
href: https://www.legislation.gov.uk/ukpga/1992/5/section/150
Loading
Loading