Repository navigation
Conversation
… wage Reg. 8(1) of the ICA Regulations 1976 states the limit as a fixed sum. From April 2025 the Government sets it at 16 times the hourly national living wage, rounded up to the nearest pound, "from April 2025 and in future years" (Explanatory Memorandum to SI 2025/352, para. 5.6; SI 2026/218 EM para. 5.3). The parameter had no projection, so every year after April 2026 held £204. Keep each legislated amount and derive later years with the repo's extend_after_last_stated projection step, from the national living wage in force on 30 April and a new hours parameter (16). A projected year never lowers the limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each projected year is now ceil(hours x NLW) alone. The floor had no source, never bound under current law, and under a reform made an hours cut inert and a one-year change permanent. Tests cover reforms that lower the limit, the band the rule reads and the baseline copy. The rounding example is corrected: 1,325 x 0.01 is exactly 13.25; 20 x (1,020 x 0.01) is 204.00000000000003. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e211c32 to
c3aab5b
Compare
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 30 (thresholds in Notes
Moves flagged for review
Receipts by tax head
Spending by benefit and service
Caseloads
Government balance, each component counted once
Model totals
Household income totals
Poverty rates
People in poverty
Inequality
Mean household net income in each side's own deciles
Standard reform costings (change in gov_balance)
Standard reforms: change in each reform's target
Household net income by decileMean change in household net income per household, and as a share of the decile's base income; households stay in the base run's deciles.
No change in any year: population. Checks failing on both base and head (1)
Counted-once checkEach of 91 components was raised by £1 per unit in 2026-27, and every head of its totals was read household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
juaristi22
left a comment
There was a problem hiding this comment.
Review status: PARTIAL
Review severity: COMMENT
Confirmed critical findings: 0
Reviewed head: c3aab5bc822876909fa13611b3f2abac7b9567e3, against merge base 8ba8bd694c0ec6c3b4f45a4d5a1a8936c7e44e4b. This covers all 14 changed paths, including the current stacked Carer’s Allowance changes from #2699.
The independent code and policy/source reviews found no confirmed defect in the changed behavior. The remaining material gap is execution: I did not collect or run the UK tests locally. At 20:25 UTC, this exact head has YAML, all six Python shards and Aggregate in progress, with Test / Result not yet observed. Completed matching-head hosted tests can resolve that gap; this review does not require a duplicate local run.
The source and static checks support these conclusions:
- The stated wage rates and age thresholds are preserved. All 94 dated non-apprentice records, 18 apprentice records and 10 CA limit records match the base. Uprating metadata applies to wage amounts, and the test source checks that a later explicitly stated rate takes precedence before projection continues.
- The LPC remit uses two-thirds of median hourly earnings as a key reference point, alongside other considerations. Using previous May–July mean earnings growth for adult, youth and apprentice rates is a disclosed projection assumption. The ONS May–July 2026 observation is 3.9%; independent decimal arithmetic gives £12.71 × 1.039 = £13.20569, rounded to £13.21. This does not establish a legislated April 2027 rate.
- At an assumed £13.21 hourly rate, the inspected rules give ESA’s £211.50 weekly permitted-work limit, UC’s £915 monthly / £10,980 annual benefit-cap earnings threshold, and CA’s £212 weekly limit. The ESA and UC executable formulas are unchanged; their newly reached values were checked by source interpretation and independent arithmetic.
- The current CA helper uses the year’s hours × NLW rule alone. The new tests cover lower-hours/wage reforms, bounded-year recovery and baseline isolation. The positive final-CA boundary test and the affected UC, ESA, MIF and childcare paths were read and traced statically; their model execution remains unverified here.
Fourteen official source originals and their text derivatives were checked: six reused after checksum validation and eight acquired for this review. Key sources are LPC remit 2026, NMW regulation 4, regulation 4A, ONS KAC3, October 2026 earnings bulletin, ESA regulation 45, UC regulation 6, UC regulation 82, and the CA uprating memoranda (2025, physical page 2, §5.6; 2026, physical page 2, §5.3).
No critical, should-address or optional findings were confirmed. Overall PARTIAL because the matching-head execution gap remains open. This is a review of changed behavior and affected dependencies; it does not certify every historical rule or private population impact.
Uprating holds £14.45 as 14.450000000000001; exact arithmetic on that float makes 20 hours £290 rather than the model's (correct) £289. Also qualify the £204 floor on the hours, as the test's invariant 4 does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gov.hmrc.minimum_wage.non_apprentice and .apprentice ended at April 2026 with no projection, so every rule that reads them froze: the UC benefit cap earnings exception, the minimum income floor, ESA permitted work, the childcare earnings tests and, from #2699, the Carer's Allowance earnings limit. Uprate each bracket amount (not the age thresholds) and the apprentice rate by gov.economic_assumptions.indices.earnings_uprating, the May-July AWE growth of the year before, never negative, rounded to the nearest penny. May-July 2026 growth was 3.9%, so April 2027 is £12.71 x 1.039 = £13.21. Rates set later take precedence and the projection continues from them. The bracket amounts move under `values:` to carry the uprating metadata, so most of the non_apprentice.yaml diff is indentation (git diff -w). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c3aab5b to
96525e9
Compare
- YAML: rounding is applied once from the last rate set; the younger bands' fixed ratio to the national living wage is an assumption (the Government is committed to aligning the 18 to 20 rate); a reform's rate is not projected, so an open-ended reform now holds flat against a rising baseline (also in the changelog). - Docs that listed the index's users or said minimum wage rates only enter through reforms. - Tests: each band from its own last rate set; minimum_wage for every age band; a later rate of £13.50 (distinguishable from the projection); the reform behaviour; the CA YAML cases keep only 2027-28, which rests on published earnings, not OBR forecasts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@vahid-ahmadi I'd like your sign-off on the earnings index this projects the minimum wage by, since #2537 came from your review of #2536. The description has a section, "The index, for maintainer sign-off".
The LPC's central estimate for April 2027 was £13.18. Once today's Budget sets April 2027 and it's added, the two indices stay within 4p of each other through April 2030. Either is a one-line change per bracket, so tell me which you'd prefer. |
The Low Pay Commission remit quote no longer adds "for workers aged 21 and over", which the remit doesn't say. The YAML now says the index is dated 1 January, that annual figures read 30 April, and that the indices end in 2039. The younger bands keep their ratio to the national living wage only to the penny. The nowcasting doc's age-band row now names the rules that read a person's band rate, and the README's minimum wage sentence moves out of the Pension Credit paragraph. The reform test's docstring says its open-ended case documents behaviour rather than testing projection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
An independent review approved 15052a7 with one should-fix and six nits. 6cea6ac answers them, and a re-review of that commit is queued.
@vahid-ahmadi, the 1.5% long-run gap is the new information for the index choice. |
The module docstring said "the series" runs to one year past the statutory inputs, which reads as the index; the yearly series does, but the index stops in 2039 like the others. The nowcasting doc no longer calls the long-run wage floor the same as one growing with average earnings: the projection runs about a year behind them and holds flat from 2040. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22
left a comment
There was a problem hiding this comment.
Review status: COMPLETE
Review severity: APPROVE
Confirmed critical findings: 0
Reviewed 58da01cc384de7547d06033301bcd751805f72a9 against merge base 3c1962100ee9dd7521715af7da553f42695ea227. Since the previous reviewed commit is no longer an ancestor, this is a fresh review of the 12 remaining changed paths after #2699 merged.
The independent code and policy/source reviews found no confirmed defect. The previous execution gap is resolved for this head: the hosted source test suite has successful YAML, all six Python shards and Test / Result checks. The workflow collects all tests, partitions Python node IDs and audits their outcomes. Local UK tests were not run. This is head-associated PR workflow evidence, not a standalone-head or later-main execution certificate.
All 89 dated non-apprentice amounts, five threshold records and 18 apprentice amounts, including their dated references, match the base. Uprating applies to amounts. The tests cover later stated-rate precedence, rounding once from the last stated rate, bounded-year recovery, the disclosed flat open-ended reform behavior, and the affected ESA/UC/CA thresholds and relevant final-benefit paths.
The previous May–July mean-earnings index and common growth for younger/apprentice bands are disclosed projection assumptions. The LPC remit uses median hourly earnings as a key reference point; it does not mandate this forecast formula. The ONS KAC3 observation supports the 3.9% input and £12.71 × 1.039 → £13.21 projection, not a legislated April 2027 rate. Jan 1 projection dates, Apr 30 fiscal-year sampling, the 2039 index horizon, flat path from 2040 and roughly 1.5% long-run difference from same-year OBR earnings growth are disclosed.
Vahid's sign-off on the index choice remains pending. This approval assesses the implementation and disclosure of the chosen assumption; it does not settle that maintainer decision. The consultation-letter £13.18 comparison, private aggregate figures and reports of other independent reviews were not independently verified here. Fourteen cached official originals and their text derivatives passed integrity checks; no new source requests were made.
CI precision: the raw packet is 22 successful checks and two cancelled Fix evidence checks, with a raw FAILURE rollup. A later Fix evidence check completed successfully at 08:08:31 UTC, after the last cancellation at 08:08:03. I am not calling every raw check green or attributing the cancellations to a cause.
Budget 2026 paragraph 6.128: from 1 April 2027 the national living wage is £13.21, the 18 to 20 rate £11.27, and the 16 to 17 and apprentice rates £8.31, each up 3.9%. They are dated values citing the Budget until the amending S.I. is made, and the projection now starts from them. The index's April 2027 rise is also 3.9% (May-July 2026 earnings), so projecting the April 2026 rates gave these to the penny; a test keeps that as a one-year backtest. test_minimum_wage_rates checks the files and the model against an ANNOUNCED_RATES table, and every dated value must be a commencement or announced date. The precedence test moves to a rate set for April 2028, and no test hard-codes a projected value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22
left a comment
There was a problem hiding this comment.
Incremental review of 58da01cc3..1c17f28b3: PARTIAL, with no confirmed critical or should-address findings.
The official Budget document confirms the announced 1 April 2027 rates: £13.21 for ages 21+, £11.27 for ages 18–20, and £8.31 for ages 16–17 and eligible apprentices. The new explicit anchor, subsequent projection and rounding are coherent on static inspection. The separate announced-rate tests preserve the distinction from historical rates backed by regulations. Later projections remain assumptions, and the maintainer's index choice remains open.
Remaining validation: this exact commit's YAML tests passed, but all six Python shards are still running and Test / Result has not appeared in the fresh metadata. Local country/Core tests were NOT RUN. The previous approval and passing tests apply to 58da01cc3; they do not qualify this new commit. The raw cancelled Fix record is retained alongside later successful Fix checks, without attributing a cause.
Optional wording clarification: the axiom: n/a explanation could mention the new Budget-announced anchor as well as projection. This review does not certify parity, private aggregate impacts or adoption.
The OBR forecasts the national living wage itself (EFO October 2026, detailed economy tables, Table 1.13), and HM Treasury costed the Budget 2026 Carer's Allowance taper on those projections. Add gov.economic_assumptions.yoy_growth.obr.national_living_wage: growth in the rates set to 2027, the OBR's estimates for 2028 to 2031 (£13.51, £13.85, £14.23, £14.62), then average_earnings growth. Project the minimum wage rates by its index instead of earnings_uprating. Tests check the series against the published table to the penny and its long-run years against average_earnings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22
left a comment
There was a problem hiding this comment.
Incremental review of 1c17f28b3..8742d96ac: PARTIAL, with no confirmed critical or should-address findings.
I checked the new series against the official October 2026 OBR economy workbook, Table 1.13. The years, hourly units, raw rates and all eleven six-decimal growth ratios match the new test table and series. The projection reproduces £13.51, £13.85, £14.23 and £14.62 for 2028–2031 on static inspection. Treasury's policy costings, physical page 16 also support using OBR wage projections as the taper's costing premise. These are forecasts, rather than enacted future wage rates.
The transition after 2031 to average earnings, common growth for younger/apprentice bands, mixed forecast vintages and the 2039 index horizon remain disclosed assumptions. Maintainer sign-off on index choice remains open. Static tracing found no defect in the index composition, later stated-rate precedence or the linked CA/ESA/UC rounding rules.
Remaining validation: this exact commit's YAML tests passed at 16:09:12 UTC. All six Python shards are still running, and Test / Result has not appeared. Local country/Core imports and tests were NOT RUN. The earlier reviews and CI remain tied to their original commits. The cancelled Fix record is retained alongside a later successful Fix check, without attributing a cause. Private aggregate impacts and adoption are not certified here.
Optional wording: the PR title still names May–July earnings growth, while the selected forecast index has changed.
|
Hand-off to the UK hub at 8742d96. HOLD: do not land until @vahid-ahmadi signs off on the index, or Max rules "go" on d2129.
|
Fixes #2537. Builds on #2699, which merged on 28 October, so the diff against main is this PR's own six commits: 96525e9 (the projection), 15052a7, 6cea6ac and 58da01c (review fixes), 1c17f28 (the April 2027 rates Budget 2026 announced) and 8742d96 (the OBR's forecast of the national living wage as the projection's index).
What and why
gov.hmrc.minimum_wage.non_apprenticeandgov.hmrc.minimum_wage.apprenticeend at the April 2026 rates (S.I. 2026/357) and had no projection. Every later year read £12.71 for the national living wage, while the model's earnings grow with the OBR forecast. So every rule that reads these rates froze from 2026-27:The change
The age thresholds don't move. Each bracket amount and the apprentice rate now carry:
values:so they can carry the metadata. Most of thenon_apprentice.yamldiff is indentation; review withgit diff -w. The files' comments say the later years are a projection, not law.The index: the OBR's own forecast of the national living wage
The OBR forecasts the national living wage itself, in Table 1.13 of the October 2026 EFO's detailed economy tables. Its note says the rate "has been set by the Government up until 2027" and that later figures "are OBR estimates consistent with the rest of our economy forecast". HM Treasury's Budget 2026 policy costings say the Carer's Allowance taper's cost uses "OBR projections for increases in the National Living Wage".
The new series
gov.economic_assumptions.yoy_growth.obr.national_living_wagehas three parts:average_earningsgrowth, year for year. The Low Pay Commission remit 2026 says two-thirds of median hourly earnings "should continue to be the key reference point for future rates".On the vintage and upkeep:
utils/import_obr_forecasts.pydoesn't read Table 1.13, whose years run across a row rather than down a column. So the series is updated by hand with each EFO, and the README and the YAML say so. Read the OBR's national living wage forecast (EFO Table 1.13) in import_obr_forecasts #2721 is to teach the importer to read it.test_minimum_wage_projection.pyholds the table. It fails if the series stops reproducing it, or if the years after 2031 stop matchingaverage_earnings.What this changes for reforms. A rate a reform sets is not projected forward, as with every other uprated parameter (
utils/dated_reforms.py).test_a_reform_rate_is_not_projectedchecks both cases:{"2027": 13.50}) leaves later years on the baseline's path."2027-04-06.2100-12-31", orReform.from_dictwith a bare year) holds its rate flat.Before this PR the baseline was flat, so an open-ended reform was a uniform rise. Now it is a rise until the baseline passes it and a cut after: £13.50 from April 2027 is below the baseline's £13.51 from April 2028. The changelog says so.
The younger bands are an assumption. The OBR forecasts only the national living wage, and the remit's reference point is for that rate. The other rates have no such anchor, so the projection grows each by the same index, which keeps its April 2027 ratio to the national living wage to the penny. The remit also says the Government "remains committed to" aligning the 18 to 20 rate with the national living wage, at a pace the LPC sets. This PR doesn't model that, and the YAML says so.
The April 2027 rates (Budget 2026)
Budget 2026 (28 October, paragraph 6.128) raised every rate by 3.9% from 1 April 2027:
test_minimum_wage_rates.pygets anANNOUNCED_RATEStable. It checks the files and the model against the Budget's rates, and the date check now covers every dated value. Move the row toRATES_FROM_COMMENCEMENTonce the S.I. is made.For maintainer sign-off: which index
No index is a rule. Each April's rate is set by an S.I. after a Low Pay Commission recommendation. Three candidates are in the repo, and switching is a one-line change per bracket:
obr.national_living_wage(this PR): the OBR's estimates to 2031, then average earnings. These are the figures the Budget costed the taper on.earnings_uprating(this PR's earlier commits): May to July growth in average weekly earnings in the year before, as projected for the Pension Credit guarantee (SSAA 1992 s. 150A). In effect it isaverage_earningslagged a year.obr.average_earnings(The national living wage parameter ends at April 2026, so every rule that reads it freezes #2537's proposal): calendar-year growth of the same year.All three give the same rates to 2027, since those are set. From the announced £13.21:
earnings_upratingaverage_earningsearnings_uprating/average_earnings)average_earningsgrow alike, so the 2031 gap of 0.3% stays.earnings_upratingruns a year behind and ends about 1.7% lower.The Budget-day dashboard and the Carer's Allowance taper. The taper takes effect in 2030-31.
obr.average_earningsfrom 2027 (October 2026 forecast), without rounding. That gave £226.50 and £232.39.@vahid-ahmadi: #2537 came from your review of #2536, so the index choice is yours to sign off.
Projected national living wage and the rules that read it
Read from the built parameter tree on this branch. The dependent columns follow each rule's arithmetic, and the "Rise" column is the series' growth that April. The index ends in 2039, so the national living wage holds at £19.69 from 2040.
Invariants
Stated in
test_minimum_wage_projection.pyand executed:test_minimum_wage_rates.py, and now hold over projected years too.minimum_wage, for one person in each age band;esa_exempt_work_higher_earnings_limit;uc_benefit_cap_earnings_exception_threshold;average_earnings: the same years and the same values.Tests that pinned April 2026 rates in later years
test_esa_permitted_work_nlw_reforms.pypinned the 2027-28 baseline permitted work limit at £203.50 (16 × £12.71). With this PR, 2027-28's baseline is £211.50, and at 2027 the test's £13.18 reform no longer moved anyone. It now uses 2026-27, a year whose rate is set. Every other quantity it reads is identical in the two years, and the test's numbers hold whatever the projection gives:The reform-in-a-projected-year path is still covered by
test_legacy_benefit_parameters.py. No other test pinned April 2026 rates.carers_allowance_earnings_limit_projection.yamlkeeps only 2027-28, which rests on the announced £13.21. Later years rest on OBR forecasts, so they are tested in Python against whatever the model's wage is. Only invariant 7 holds the OBR's estimates, so an EFO update changes that test's table, the series and this description's tables.Aggregate impact
These figures are from the Aggregate impact job at 8742d96 against main (run), on certified data (enhanced FRS 2024-25, policyengine-uk-data 1.58.1). The job ran on 8742d96 merged into main at 6360988. Nothing changes before 2027-28.
Against the earlier
earnings_upratingprojection (run at 58da01cc3, on an earlier main), the figures move the same way as the national living wage:Each line traces to a rule that reads the minimum wage:
universal_childcare_entitlementgives them only within the working-parent hours (existing modelling, not changed here).is_scp_eligible).Lines not in the table:
social_security_income.Distributional results and checks:
The job flags 30 moves for review; a flag does not fail the job.
Reproducer: policyengine_uk/tests/test_minimum_wage_projection.py::test_the_series_reproduces_the_obr_table
axiom: n/a: projects minimum wage rates after the last rate set, from the April 2027 rates Budget 2026 announced; no legislated amount changes
🤖 Generated with Claude Code