Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
1b02f9f
Merge remote-tracking branch 'origin/ca-earnings-limit-float32-test' …
MaxGhenis Oct 20, 2026
0acc9f7
Count Carer's Allowance earnings-limit pence exactly
MaxGhenis Oct 20, 2026
ab644ac
Pin #2541's boundary cases as explicit examples in the property tests
MaxGhenis Oct 20, 2026
71d35f5
Take CA earnings to the nearest half penny before the limit test
MaxGhenis Oct 21, 2026
0c06105
Merge remote-tracking branch 'origin/ca-earnings-limit-float32-test' …
MaxGhenis Oct 21, 2026
0bd3a2b
Merge remote-tracking branch 'origin/main' into fix/2541-ca-earnings-…
MaxGhenis Oct 21, 2026
a67d545
Bound the exactness claim in the CA earnings-limit comment
MaxGhenis Oct 21, 2026
5eb7e5a
Apply reg. 5 to each step of CA net earnings, in whole pence
MaxGhenis Oct 27, 2026
32f1639
Merge remote-tracking branch 'origin/main' into fix/2541-ca-earnings-…
MaxGhenis Oct 27, 2026
d4b8cb2
Work out Class 1 exactly and read entered pension totals for CA earnings
MaxGhenis Oct 28, 2026
8f1df68
Pin two pension programmes summed in whole pence (CA Case 32)
MaxGhenis Oct 28, 2026
6e8a53f
Read model sums in whole pence; deduct entered Class 1 as stored
MaxGhenis Oct 28, 2026
9cf7fd7
Test the sums reader where wrong-rule swaps survived
MaxGhenis Oct 28, 2026
6e1179d
Sum Class 1 months exactly; gate the exact path on how core calculates
MaxGhenis Oct 28, 2026
a51dd97
Changelog: Class 1 entered is deducted as entered, months summed exactly
MaxGhenis Oct 28, 2026
ea3f7d3
Pin Class 1 entered for the year in whole pence (CA Case 37)
MaxGhenis Oct 28, 2026
2502953
Say the sums test checks the model's definitions, not sick pay's trea…
MaxGhenis Oct 28, 2026
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
1 change: 1 addition & 0 deletions changelog.d/2541.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed the Carer's Allowance earnings limit treating earnings a penny a week over the 2020-21 to 2024-25 limits (£128, £132, £139 and £151) as within them. Net earnings now apply the Computation of Earnings Regulations' rounding to each step: pay and profit are taken down to a whole penny and each calculated deduction (notional tax, Class 4 and half of pension contributions) up to one; the model's PAYE and Class 1, which in law are the amounts actually deducted, are rounded up too. Earnings are worked in double precision from the whole pence each amount was entered as, and a sum the model forms (pay, pension contributions, NI income) is the exact sum of its parts. Class 1 is worked out again from its formula where the model calculated it with that formula; entered as an input (for the year or month by month), or calculated under a reform, it is deducted as entered or calculated, its months summed exactly, so £1.20 entered is £1.20 deducted. The limit test reads the whole pence back exactly, so float32 rounding no longer decides it. Pension contributions entered as a total still reduce earnings. The Scottish Carer Support Payment, which reads the same earnings, is judged exactly at its limit too.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
# are gross pay less income tax, primary Class 1 contributions and half of
# pension contributions (Computation of Earnings Regulations 1996 reg.
# 10(4)), and trading profit less a notional basic-rate tax and main-rate
# Class 4 (regs. 13(4) and 14). A fraction of a penny is disregarded (reg. 5).
# Class 4 (regs. 13(4) and 14). A fraction of a penny counts in the
# claimant's favour (reg. 5): disregarded in earnings, a penny in a deduction.
# 2026-27: personal allowance and NI primary threshold £12,570, employee
# Class 1 main rate 8%, Class 4 lower profits limit £12,570 at 6%, basic rate
# 20%. Carer's Allowance £86.45 a week.
Expand Down Expand Up @@ -321,3 +322,302 @@
carers_allowance_earnings: 10_518.20
is_gainfully_employed_for_carers_allowance: false
carers_allowance_pre_overlap: 86.45 * 52

- name: Case 21, in 2024-25 a penny a year short of £151.01 a week is within the limit.
period: 2024
absolute_error_margin: 0.01
input:
age: 45
employment_income: 7_852.51
care_hours: 40
country: ENGLAND
output:
# 7,852.51 / 52 = £151.0098, which counts as £151.00 (reg. 5).
carers_allowance_earnings: 7_852.51
is_gainfully_employed_for_carers_allowance: false
carers_allowance: 81.90 * 52

- name: Case 22, in 2024-25 a whole penny over £151 is over the limit.
period: 2024
absolute_error_margin: 0.01
input:
age: 45
employment_income: 7_852.52
care_hours: 40
country: ENGLAND
output:
# 7,852.52 / 52 = £151.01. Float32 holds 7,852.52 as 7,852.52001953125;
# counting pence in float32 used to give £151.00 (#2541).
carers_allowance_earnings: 7_852.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 23, in 2024-25 the half penny of half an odd-pence pension contribution counts as a penny off earnings.
period: 2024
absolute_error_margin: 0.01
input:
age: 45
employment_income: 7_852.52
employee_pension_contributions: 0.01
care_hours: 40
country: ENGLAND
output:
# Half of 0.01 is 0.005. Counting the half penny of the deduction as a
# penny favours the claimant (reg. 5), so earnings are 7,852.51, or
# £151.0098 a week, which counts as £151.00.
carers_allowance_earnings: 7_852.51
is_gainfully_employed_for_carers_allowance: false
carers_allowance: 81.90 * 52

- name: Case 24, in 2024-25 a penny more pay with the same contribution is over the limit.
period: 2024
absolute_error_margin: 0.01
input:
age: 45
employment_income: 7_852.53
employee_pension_contributions: 0.01
care_hours: 40
country: ENGLAND
output:
# 7,852.53 less 0.01 (the half penny counted as a penny) is 7,852.52, or
# £151.01 a week.
carers_allowance_earnings: 7_852.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 25, a fraction of a penny in each self-employed deduction counts as a penny.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
self_employment_income: 14_000.01
personal_pension_contributions: 6_039.38
care_hours: 40
country: ENGLAND
output:
# Notional tax 20% x 1,430.01 = 286.002 and Class 4 6% x 1,430.01 =
# 85.8006 count as 286.01 and 85.81 (reg. 5), and half the premium is
# 3,019.69: 14,000.01 - 286.01 - 85.81 - 3,019.69 = 10,608.50, or £204.00
# a week, within the limit. Unrounded, earnings are 10,608.5174; the
# nearest half penny of that is 10,608.52, £204.01 a week, which would
# have ended entitlement (juaristi22's review of #2543).
carers_allowance_earnings: 10_608.50
is_gainfully_employed_for_carers_allowance: false
carers_allowance: 86.45 * 52

- name: Case 26, in 2026-27 a whole penny of Class 1 counts as that penny, not two.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income: 14_764.46
employee_pension_contributions: 7_960.76
care_hours: 40
country: ENGLAND
output:
# Class 1 is 8% x (14,764.46 - 52 x 241.73) = 175.56 exactly; the model's
# float32 sum of twelve months holds it as 175.5600128, which rounded up
# would be 175.57. Pay less the contribution is 6,803.70, under the
# personal allowance, so no PAYE, and half the contribution is 3,980.38:
# 14,764.46 - 175.56 - 3,980.38 = 10,608.52, or £204.01 a week, over the
# limit.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 27, in 2025-26 the same Class 1 of £175.56 leaves a penny a week over £196.
period: 2025
absolute_error_margin: 0.001
input:
age: 45
employment_income: 14_764.46
employee_pension_contributions: 8_792.76
care_hours: 40
country: ENGLAND
output:
# 14,764.46 - 175.56 - 4,396.38 = 10,192.52, or £196.01 a week.
carers_allowance_earnings: 10_192.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 28, in 2024-25 Class 1 of £43.80 leaves a penny a week over £151.
period: 2024
absolute_error_margin: 0.001
input:
age: 45
employment_income: 13_117.46
employee_pension_contributions: 10_442.27
care_hours: 40
country: ENGLAND
output:
# Class 1 is 8% x (13,117.46 - 12,569.96) = 43.80, stored as 43.800003.
# Half the contribution is 5,221.135, which counts as 5,221.14 (reg. 5):
# 13,117.46 - 43.80 - 5,221.14 = 7,852.52, or £151.01 a week.
carers_allowance_earnings: 7_852.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 29, pension contributions entered as a total still come off earnings.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income: 11_000
pension_contributions: 1_000
care_hours: 40
country: ENGLAND
output:
# 11,000 - 1,000 / 2 = 10,500, or £201.92 a week, within the limit.
carers_allowance_earnings: 10_500
is_gainfully_employed_for_carers_allowance: false
carers_allowance: 86.45 * 52

- name: Case 30, in 2026-27 £12,570.50 of profit with a £3,923.70 premium is a penny a week over the limit.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
self_employment_income: 12_570.50
personal_pension_contributions: 3_923.70
care_hours: 40
country: ENGLAND
output:
# Notional tax 20% x 0.50 = 0.10 and Class 4 6% x 0.50 = 0.03:
# 12,570.50 - 0.10 - 0.03 - 1,961.85 = 10,608.52, £204.01 a week.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 31, a penny more profit can leave a penny less in earnings, as reg. 5 intends.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
self_employment_income: 12_570.51
personal_pension_contributions: 3_923.70
care_hours: 40
country: ENGLAND
output:
# Notional tax 0.102 and Class 4 0.0306 each count as a penny more (0.11
# and 0.04), so the extra penny of profit adds two pennies of deductions:
# 12,570.51 - 0.11 - 0.04 - 1,961.85 = 10,608.51, £204.00 a week, within.
carers_allowance_earnings: 10_608.51
is_gainfully_employed_for_carers_allowance: false
carers_allowance: 86.45 * 52

- name: Case 32, two pension programmes are summed in whole pence, not as float32 adds them.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income: 12_229.84
employee_pension_contributions: 1_807.49
personal_pension_contributions: 1_435.15
care_hours: 40
country: ENGLAND
output:
# The contributions total 3,242.64, which pension_contributions holds as
# 3,242.64013671875: more than half a float32 step out, so read alone it
# would be 3,242.6401367 and half of it would count as 1,621.33. Summed
# in whole pence, half is 1,621.32. Pay is under the primary threshold,
# and pay less the employee contribution under the personal allowance:
# 12,229.84 - 1,621.32 = 10,608.52, or £204.01 a week, over the limit.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 33, Class 1 entered as nil is deducted as nil, not as the formula would work it.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income: 12_569.97
employee_pension_contributions: 3_922.90
ni_class_1_employee: 0
care_hours: 40
country: ENGLAND
output:
# The model's formula would charge 8% of the penny over its £12,569.96
# primary threshold, 0.0008, counted as a penny. Entered as nil, nil is
# what was deducted (reg. 10(4)(a)): 12,569.97 - 3,922.90 / 2 = 10,608.52,
# or £204.01 a week, over the limit.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 34, a pension total the model sums from two inputs is read in whole pence.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income_before_lsr: 10_608.96
salary_sacrifice_returned_to_income: 0.20
employee_pension_contributions_reported: 1.08
care_hours: 40
country: ENGLAND
output:
# Pay is 10,608.96 + 0.20 = 10,609.16; employee contributions are
# 1.08 + 0.20 = 1.28, which float32 adds to 1.28000009, so that half of
# it read alone would count as 0.65. Summed in whole pence, half is 0.64:
# 10,609.16 - 0.64 = 10,608.52, or £204.01 a week, over the limit.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 35, pay the model sums from two inputs is read in whole pence.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income_before_lsr: 10_276.42
salary_sacrifice_returned_to_income: 1_415.69
employee_pension_contributions_reported: 751.49
care_hours: 40
country: ENGLAND
output:
# Pay is 10,276.42 + 1,415.69 = 11,692.11, which float32 adds to
# 11,692.109375: more than half a float32 step out, so read alone it would
# count as 11,692.10. Contributions are 751.49 + 1,415.69 = 2,167.18, half
# 1,083.59. Pay is under the primary threshold and pay less contributions
# under the personal allowance: 11,692.11 - 1,083.59 = 10,608.52, or
# £204.01 a week, over the limit.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 36, pay and pension both summed by the model are read in whole pence.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income_before_lsr: 10_794.69
salary_sacrifice_returned_to_income: 1_435.15
employee_pension_contributions_reported: 1_807.49
care_hours: 40
country: ENGLAND
output:
# Pay is 10,794.69 + 1,435.15 = 12,229.84 (float32: 12,229.8408203125)
# and contributions 1,807.49 + 1,435.15 = 3,242.64 (3,242.64013671875),
# each more than half a float32 step out of its pence. Summed in whole
# pence: 12,229.84 - 3,242.64 / 2 = 10,608.52, or £204.01 a week, over.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0

- name: Case 37, Class 1 entered for the year in whole pence is deducted in whole pence.
period: 2026
absolute_error_margin: 0.001
input:
age: 45
employment_income: 10_609.72
ni_class_1_employee: 1.20
care_hours: 40
country: ENGLAND
output:
# The model divides the year's 1.20 among the months in float32 and
# sums them to 1.2000002, which rounded up would deduct 1.21. The Class
# 1 deducted is the 1.20 entered (reg. 10(4)(a)): 10,609.72 - 1.20 =
# 10,608.52, or £204.01 a week, over the limit.
carers_allowance_earnings: 10_608.52
is_gainfully_employed_for_carers_allowance: true
carers_allowance: 0
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,33 @@
output:
carers_allowance_earnings: 6146.6
carer_support_payment_pre_overlap: 0

- name: Each self-employed deduction rounded up a penny leaves earnings within the limit
period: 2026
absolute_error_margin: 0.001
input:
age: 45
self_employment_income: 12576.76
personal_pension_contributions: 3932.96
care_hours: 40
country: SCOTLAND
output:
# Sch2para4: notional tax 20% x 6.76 = 1.352 and Class 4 6% x 6.76 =
# 0.4056 count as 1.36 and 0.41; half the premium is 1,966.48:
# 12,576.76 - 1.36 - 0.41 - 1,966.48 = 10,608.51, or 204.00 a week.
carers_allowance_earnings: 10608.51
carer_support_payment_pre_overlap: 4495.4

- name: A penny more profit leaves earnings a penny a week over the limit
period: 2026
absolute_error_margin: 0.001
input:
age: 45
self_employment_income: 12576.77
personal_pension_contributions: 3932.96
care_hours: 40
country: SCOTLAND
output:
# 12,576.77 - 1.36 - 0.41 - 1,966.48 = 10,608.52, or 204.01 a week.
carers_allowance_earnings: 10608.52
carer_support_payment_pre_overlap: 0
Loading
Loading