Skip to content

Fix Class 2 and Class 4 NICs against SSCBA 1992 for 2015-16 to 2026-27 - #2058

Merged
MaxGhenis merged 14 commits into
mainfrom
fix-class-2-class-4-ni-parameters
Oct 10, 2026
Merged

MaxGhenis merged 14 commits into
mainfrom
fix-class-2-class-4-ni-parameters

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1968
Fixes #1887

Supersedes #1888. Its commit (the Class 2 fix) is the first commit here, unchanged apart from one notebook cell that main had also edited. The second commit is the Class 4 fix that #1888 left for a follow-up.

What was wrong

I read s.11 and s.15 of the Social Security Contributions and Benefits Act 1992 as in force on 6 April of each year from 2015 to 2026, the instrument behind each figure, and regulation 100 of SI 2001/1004. The model samples each tax year at 30 April, so "model year 2023" is 2023-24.

Class 4 (s.15)

Model year Parameter Model Law Source
2023 Lower profits limit £11,908 £12,570 NICs (Increase of Thresholds) Act 2022 s.2(3)-(4)
2023 Additional rate 3.5% 2% s.15(3ZA)(b)
2022 Main rate 10.25% 9.73% Health and Social Care Levy (Repeal) Act 2022 s.2(2)(a)
2022 Additional rate 3.5% 2.73% s.2(2)(b) of that Act
2015 Upper profits limit £42,386 £42,385 SI 2015/588 art 3(b)
  • The 3.5% additional rate matched no statute. The Health and Social Care Levy Act 2021 s.5(2) set 3.25% for 2022-23, and the Repeal Act replaced that with 2.73% for the whole year.
  • Class 4 is charged on the year's profits, so 2022-23 has one rate for the year. The old 2022-11-06: 0.09 entry never took effect, because the year is sampled in April.
  • Two dates were wrong without changing results: the £43,000 upper limit was dated 5 June 2015 (law: 6 April 2016) and the 6% main rate 4 April 2024 (law: 6 April 2024). A third, £12,570 dated 1 January 2024 instead of 6 April 2023, is the 2023-24 lower-limit error in the table.

Class 2 (s.11), from #1888:

  1. The 2023-24 rate is £3.45 a week (SI 2023/236 reg 3(a)). The model charged £3.15.
  2. In 2022-23 and 2023-24 Class 2 is payable only on profits that exceed the lower profits threshold: £11,908, then £12,570 (SI 2022/1329 reg 2, with effect from 6 April 2022; SI 2023/236 reg 3(b)). Profits from the small profits threshold up to it are treated as paid (s.11(5A)-(5B)). The model charged 52 weeks from the small profits threshold.
  3. The small profits threshold stayed at £6,725 in 2023-24 and 2024-25. The model CPI-uprated it to £7,215.94 and £7,396.34, and projected 2027-28 from 2022 (£7,980) instead of from 2026-27's £7,105 (giving £7,247).
  4. The small profits threshold was £5,965 in 2015-16 and 2016-17 (NICA 2015 Sch 1 para 3). The model had 3,965.
  5. Compulsory Class 2 ended on 6 April 2024 (NICs (Reduction in Rates) Act 2023 s.3), not 1 January 2024. Results don't change.

Class 2, found in review of this PR (commits 0278f13 and c1364a4):

  1. Class 2 tested its thresholds on self_employment_income. s.11(3) applies them to "relevant profits": the profits on which Class 4 is payable under s.15, which s.15(3) computes under Schedule 2. HMRC NIM70650: "From the 2015 to 2016 tax year, the profits used to determine whether a Class 2 NICs liability exists are those profits which are already used for Class 4 NICs purposes under section 15". Since Charge Class 4 NICs on Chapter 2 profits, after capital allowances, the trading allowance and Schedule 2 losses #1919 the model calls those ni_class_4_profits (after capital allowances, the trading allowance and loss relief). With the fixes above but the old profit measure, £13,000 of profit with £1,000 of capital allowances in 2023-24 paid £179.40 of Class 2 on relevant profits of £12,000, which do not exceed the £12,570 threshold.
  2. Class 2 is due for each contribution week in the year (s.11(2)). A contribution week starts at midnight between Saturday and Sunday (SI 2001/1004 reg 1(2)), and the year's first week starts on the first Sunday after 5 April (HMRC NIM70200: "a person who is self-employed for the full year will be liable for all 53 weeks"). 2019-20 runs from Sunday 7 April 2019 to the week starting Sunday 5 April 2020: 53 weeks, £159 at £3.00. The model charged 52 (£156) in every year. 2025-26 also has 53 weeks, but the compulsory rate is nil then.
  3. The Universal Credit minimum income floor deducts the Class 2 and Class 4 a person would pay on profits equal to their threshold (UC Regs 2013 reg 62(4)(b)). It computed that Class 2 with the pre-2022 rule, so in 2022-23 and 2023-24 it deducted £163.80 or £179.40 from thresholds that s.11(5A)-(5B) treats as paid. ni_class_2 and the floor now share one s.11(2) test and one week count (policyengine_uk/utils/class_2.py).

Regulation 100 (the Class 4 annual maximum). The formula is right. Regulation 100 writes its percentages out, and in every year they equal the Class 4 rates: 9% and 2%; 9.73%, 100/9.73 and 2.73% for 2022-23 (Health and Social Care Levy (Repeal) Act 2022 Sch para 6(2)); 6% and 100/6 from 2024-25 (NICs (Reduction in Rates) Act 2024 s.2(3)). ni_class_4_maximum reads the rate parameters, so it follows each year's text. A comment now records this. The wrong 2023 figures came from the stale parameters, not the formula.

Changes

  • class_4/thresholds/lower_profits_limit.yaml: adds 2023-04-06: 12_570, drops the duplicate 2024-01-01 entry, cites every value.
  • class_4/thresholds/upper_profits_limit.yaml: 2015-16 is 42,385; £43,000 is dated 6 April 2016; cites every value to 2021-22.
  • class_4/rates/main.yaml: 9.73% for 2022-23, 9% from 6 April 2023, 6% dated 6 April 2024.
  • class_4/rates/additional.yaml: 2.73% for 2022-23, 2% from 6 April 2023; drops the 2024-01-01 entry.
  • ni_class_4_maximum: the comment above; no formula change.
  • Class 2 files, as in Fix Class 2 NICs: 2023-24 rate, the 2022-23 lower profits threshold, and the small profits threshold #1888:
    • flat_rate.yaml: £3.45 for 2023-24, zero dated 6 April 2024, citations.
    • small_profits_threshold.yaml: corrected values, and CPI uprating now projects from the latest statutory value.
    • New lower_profits_threshold.yaml and lower_profits_threshold_applies.yaml.
    • ni_class_2: liable on relevant profits above the lower profits threshold when that test applies, else on relevant profits at or above the small profits threshold. Relevant profits are ni_class_4_profits (s.11(3)). A full year is the year's contribution weeks.
  • New policyengine_uk/utils/class_2.py: class_2_liable (the s.11(2) test) and class_2_contribution_weeks (Sundays from 6 April to the next 5 April). ni_class_2 and uc_minimum_income_floor_national_insurance both use them.
  • Docs: the NI notebook text and saved chart values; model-baseline.md line links.

#1959 (merged) holds the two Class 4 limits through 2030-31. This branch is rebased on it and keeps its 2026-27 to 2030-31 entries unchanged. The NI notebook's saved chart, which #1959 left on the old CPI-uprated thresholds, now shows its values too.

Invariants

For every tax year from 2015-16 to 2026-27, profits ≥ 0 and primary Class 1 ≥ 0:

  1. Parameters. Each Class 2 and Class 4 rate, limit and threshold equals the statutory figure for that year. The test tables are typed from the instruments, not read from the parameter files.
  2. Differential, Class 4. ni_class_4 equals an exact-rational reference: the s.15(3) amount on the full profits, capped by the regulation 100 maximum where primary Class 1 or, before 2024-25, Class 2 is payable.
  3. Differential, Class 2. ni_class_2 is the weekly rate × the year's contribution weeks when s.11(2) makes the earner liable on relevant profits, else 0. The test's inputs are profit, whole-pound capital allowances and a whole-pound trading loss in the same year, with no gross receipts, so relevant profits are profit less both, computed exactly. (From 2017-18 a profit of £1,000 or less is covered by the trading allowance and gives nil relevant profits; such profits are below every threshold, so Class 2 is nil either way.) The trading allowance with gross receipts and losses brought forward are covered by YAML cases only.
  4. Shared base, Class 2. ni_class_2 is the s.11(2) rule applied to the model's own ni_class_4_profits, on the same inputs.
  5. Bounds. 0 ≤ ni_class_4 ≤ the s.15(3) amount; ni_class_2 ∈ {0, a full year at the weekly rate}.
  6. Monotonicity. ni_class_2 is non-decreasing in relevant profits: non-decreasing in profit and non-increasing in capital allowances and losses.
  7. Calendar. The contribution-week count equals a typed table (53 in 2019-20 and 2025-26, else 52) for every model year from 2015 to 2030, and HMRC's NIM70200 example for 2021-22.
  8. UC floor, differential. The floor's notional NI equals the Class 2 and Class 4 the same person would pay on profits equal to their threshold (the existing property in test_uc_minimum_income_floor_properties.py, now drawn over 2019, 2020, 2022, 2023, 2026 and 2027).

Tests

  • The four stale 2023 YAML expectations now hold statutory values, each derived in a comment:
    • ni_class_2 over the lower profits threshold: 3.45 × 52 = 179.40.
    • ni_class_4 under the UPL: (30,000 − 12,570) × 9% = 1,568.70.
    • ni_class_4_main over the UPL: 37,700 × 9% = 3,393.
    • ni_class_4_maximum with £100,000 of pay and £100,000 of profits: 1,748.60. Step Four is negative (Case 3, nil); Step Eight is 37,700 × 2% = 754; Step Nine is 49,730 × 2% = 994.60. The old 3,083.22, and the 3,060.05 seen after fixing only the limit, both used the 3.5% rate.
  • New Class 4 YAML cases for 2022-23 (9.73%, 2.73% and the maximum, 2,404.91), 2015-16 and 2016-17. Run against main's parameters, 8 of the 10 Class 4 cases fail; the 2016-17 and 2026-27 cases are regression guards.
  • New test_ni_class_4_statute.py:
    • a statute table for 2015–2026;
    • 20 hand-derived liabilities, with regulation 100 Cases 1, 2 and 3 in each regime (to 2021-22, 2022-23, 2023-24 and from 2024-25);
    • the differential at every limit and threshold ±1p/£1 with four Class 1 amounts, in all 12 years;
    • the same differential as a Hypothesis property (6 derandomised examples of up to 16 people × 12 years).
  • ni_class_2.yaml (17 cases) and test_ni_class_2.py from Fix Class 2 NICs: 2023-24 rate, the 2022-23 lower profits threshold, and the small profits threshold #1888. Its regulation 100 pin no longer overrides the Class 4 parameters, since the defaults are now the statutory ones.
  • For s.11(3), 8 more ni_class_2.yaml cases put capital allowances, the trading allowance (with gross receipts) and losses (brought forward and the year's own) against the thresholds: below and at or above the 2021-22 and 2023-24 thresholds, and below the 2015-16 and 2022-23 ones. 6 of them fail on the previous formula; the other 2 sit at or just above a threshold. test_ni_class_2.py draws relevant profits first (so sampled threshold points stay on their thresholds) and adds capital allowances and an in-year trading loss to the statute differential and the Hypothesis property, and checks invariant 4. Both tests fail on the previous formula, and on two narrower mutants (reading ni_class_4_profits_before_losses, or profit less capital allowances only).
  • Contribution weeks: ni_class_2.yaml cases for 2019-20 (53 × £3.00 = £159) and 2020-21 (52 weeks); test_ni_class_2.py checks the week count against a typed table and NIM70200's example; the two 2019-20 rows of test_ni_class_4_statute.py use 53 weeks (with £2,000 of Class 1 the regulation 100 maximum is £2,167.56: Step Four 3,723.12 + 159 − 159 − 2,000 = 1,723.12, plus 2% × (41,368 − 1,723.12 / 9%)).
  • UC minimum income floor: YAML cases for a lone parent's 16-hour floor in 2022-23 (£7,904) and 2023-24 (£8,669.44), both with no NI deducted, and 35-hour floors in 2023-24 (£754.90 of NI) and 2019-20 (£726.92, with 53 weeks of Class 2). The floor property test now samples 2019, 2022 and 2023 and has the lone parent as explicit examples.

Effect

Single-person households at default parameters, main (a094911) against this branch (c1364a4), each state run from its own worktree and venv on 2026-10-07.

Case Class 2 Class 4 Total NI
2023-24, £10,000 profits £163.80 → £0 £0 −£163.80
2023-24, £12,570 profits £163.80 → £0 £59.58 → £0 −£223.38
2023-24, £30,000 profits £163.80 → £179.40 £1,628.28 → £1,568.70 −£43.98
2023-24, £60,000 profits £163.80 → £179.40 £3,793.13 → £3,587.60 −£189.93
2023-24, £60,000 profits + £30,000 pay £163.80 → £179.40 £2,516.85 → £1,963.48 −£537.78
2023-24, £60,000 profits + £60,000 pay £163.80 → £179.40 £1,683.22 → £948.60 −£719.02
2022-23, £10,000 profits £163.80 → £0 £0 −£163.80
2022-23, £30,000 profits £163.80 £1,854.43 → £1,760.35 −£94.08
2022-23, £60,000 profits £163.80 £4,272.65 → £3,998.25 −£274.40
2022-23, £60,000 profits + £60,000 pay £163.80 £1,683.22 → £1,312.91 −£370.31
2015-16, £5,000 profits £145.60 → £0 £0 −£145.60
2015-16, £50,000 profits £145.60 £3,241.62 → £3,241.55 −£0.07
2024-25 and 2025-26, £60,000 profits £0 £2,456.60, unchanged 0
2026-27, £60,000 profits + £60,000 pay £0 £948.60, unchanged 0
2023-24, £13,000 profits, £1,000 capital allowances £163.80 → £0 £8.28 → £0 −£172.08
2023-24, £13,000 profits, £1,000 capital allowances + £50,000 pay £163.80 → £0 £3.22 → £0 −£167.02
2022-23, £12,500 profits, £1,000 capital allowances £163.80 → £0 £0 −£163.80
2021-22, £7,000 profits, £1,000 capital allowances £158.60 → £0 £0 −£158.60
2015-16, £6,500 profits, £1,000 capital allowances £145.60 → £0 £0 −£145.60
2019-20, £30,000 profits £156 → £159 £1,923.12, unchanged +£3.00
2019-20, £50,000 profits + £25,000 pay £156 → £159 £2,197.77 → £2,195.44 +£0.67

Household net income moves by the negative of the NI change in every row, to within 1p, in these runs.

These runs and the Universal Credit and Enhanced FRS runs below are at a094911 against c1364a4. Since then the branch has one comment-only commit (0e9736d) and two merges of main:

  • 92acbb4. Review r5 re-ran both household scripts at this head and reproduced every NI and Universal Credit figure. Household net income there also carries main's Energy Bills Support Scheme correction (Correct Energy Bills Support Scheme amounts and timing #2103): −£200 in the 2015-16, 2019-20 and 2021-22 rows, −£1 in 2022-23 and +£201 in 2023-24, against the figures behind this table.
  • 28b11c1 (the head). This brings Charge employer Class 1 NI at 15.05% in 2022-23 #2227, which changes employer Class 1 for 2022-23 and moves the start date of the employee main rate's 13.25% from 1 to 6 April 2022 without changing its value. The regulation 100 maximum subtracts primary Class 1 (ni_class_1_employee_primary) and Class 2 only, so employer Class 1 does not enter it. I did not re-run the tables at this head, because the host was reserved for other work; CI ran the full test suite there.

The first 14 rows are unchanged from this table's first run (8b2e6e1 against 25bd7a9). The next five isolate s.11(3) against the branch's previous formula; against main four of them also include the threshold fixes (only the 2021-22 row is s.11(3) alone), and the Class 4 drops in the two 2023-24 rows come from the lower profits limit. The last two are the 53-week year: in the dual earner's row regulation 100 binds, so £3 more Class 2 lowers the Class 4 maximum by £2.33.

Universal Credit. A lone parent aged 30 with a child aged 3 (a 16-hour floor), £3,000 of profit, £7,200 of private rent, in the North East:

Year Floor NI Net floor UC
2023-24 £163.80 → £0 £8,505.64 → £8,669.44 £12,683.14 → £12,593.05 (−£90.09)
2022-23 £163.80 → £0 £7,740.20 → £7,904.00 £12,167.17 → £12,077.08 (−£90.09)
2019-20 £156.00 → £159.00 £6,674.72 → £6,671.72 £12,303.45 → £12,305.34 (+£1.89)
2021-22 £158.60, unchanged £7,254.52, unchanged £12,627.81, unchanged

Enhanced FRS. The dataset's base year is 2024-25 (its only time_period is 2024), so it covers model years 2024 onward. From 2024-25 the Class 2 rate is zero, so the changed Class 2 thresholds, profit measure and week count, in ni_class_2 and in the UC floor's notional Class 2 alike, multiply a zero rate. Each Class 4 limit and rate equals main's from 2024-25 on. The dataset has no capital allowance, trading loss or gross receipts inputs.

On 2026-10-07 I ran main (a094911) and this branch (c1364a4), each from its own worktree and venv on its own copy of the 2024-25 enhanced FRS (sha256 e433e532…), for every year from 2024 to 2031: 16 simulation-years.

  • No record changes in any year on any of the 12 outputs compared: ni_class_2, ni_class_4, ni_class_4_main, ni_class_4_maximum, ni_self_employed, ni_class_1_employee, national_insurance, income_tax, self_employment_income, household_net_income, household_tax and household_benefits (which includes Universal Credit).
  • In both states Class 2 is £0 in every year, and Class 4 is £2.61bn in 2024, £2.65bn in 2025 and £2.79bn in 2026.

The dataset has no year before 2024-25, so there is no aggregate figure for the 2015-16 to 2023-24 changes. The household table above shows their size.

Not in this PR

  • Class 1 in 2022-23 and 2023-24. The main primary rate and the primary threshold changed mid-year (6 July and 6 November 2022, 6 January 2024). The model samples them at 30 April. That is Mid-year parameter changes are dropped by fiscal year conversion #1807. It affects the Class 1 amount that regulation 100 subtracts for dual earners in those two years.
  • Part-year Class 2. The model charges a full year to anyone liable by age for the year (ni_liable); s.11(7) stops Class 2 after the week of reaching pensionable age, and the model does not count weeks of self-employment within a year.
  • Voluntary Class 2 (s.11(6): £3.45, £3.50 and £3.65 from 2024-25) is not modelled. The flat-rate parameter describes compulsory liability only.

Axiom parity

axiom: TheAxiomFoundation/rulespec-uk#353 queued (s.11) | TheAxiomFoundation/rulespec-uk#379 queued (Sch 2 Class 4 profits, which s.11(3) relevant profits import) | TheAxiomFoundation/rulespec-uk#423 queued (s.15 and reg 100)

rulespec-uk's uk/statutes/ukpga/1992/4/15.yaml and uk/regulations/uksi/2001/1004/100.yaml encode only the current text: limits from 2026-04-06, 6% from 2024-04-06 and a 2% additional rate from 2011 with no 2022-23 exception. None of the amending instruments are in the corpus. All three issues are dispatch-ready: module path, corpus citation, verbatim law, a figures table, a pasteable review_finding, and companion tests built on the same statutory figures as the tests here.

On 2026-10-07 #353 gained two sections. The first says that no small profits threshold after 2026-27 has been announced: the £7,105 for 2026-27 (Budget 2025 para 4.118; SI 2026/231 reg 3(a)) stands until amended, and this model's CPI projection from 2027-28 is not law. The second covers s.11(3) relevant profits: review_finding item 8 binds them to #379's profits_chargeable_to_class_4_contributions, with two companion cases that use capital allowances. #353's oracle note now uses the year's contribution weeks (53 in 2019-20), and #379 lists s.11 among the consumers of its output. #423's companion row E (2019-20) now uses 53 weeks of Class 2 (£159; Class 4 £2,167.56), matching test_ni_class_4_statute.py.

Verification of the figures

  • Point-in-time XML of s.11 and s.15 for 6 April of each year 2015–2026, and of regulation 100 at eight dates, fetched from legislation.gov.uk on 2 October 2026.
  • The made or enacted text of each amending instrument: SI 2015/588 art 3; SI 2016/343 reg 2; reg 5 of SIs 2017/415, 2018/337, 2019/262, 2020/299, 2021/157 and 2022/232; NICA 2011 s.2; NICs (Increase of Thresholds) Act 2022 ss.2-3; SI 2022/1329; Health and Social Care Levy Act 2021 s.5; the Repeal Act 2022 s.2 and Schedule; NICs (Reduction in Rates) Acts 2023 and 2024; SI 2024/377 regs 1 and 6.
  • legislation.gov.uk's point-in-time text does not show the 2022-23 rates, because the Repeal Act modifies s.15 for the year without amending its text. Those come from the Act itself.
  • The Class 2 figures were verified separately for Fix Class 2 NICs: 2023-24 rate, the 2022-23 lower profits threshold, and the small profits threshold #1888.

Independent review

Opus 5.5 via Subfleet (--task review --tier standard, job 20261002-081207-ni-class-2-4-review-r1): APPROVE WITH NITS, with nothing blocking.

The reviewer found:

  • every Class 2 and Class 4 figure for 2015-16 to 2026-27 matches s.11, s.15 and the amending instruments;
  • ni_class_2 and the regulation 100 formula follow the statutory text step by step;
  • every YAML expectation, hand-derived row and rulespec-uk#423 companion row it recomputed by hand is right.

Its findings and what I did:

  1. Hand-derived table missing cases. It lacked a Case 3 before 2022-23, a Case 2 in 2022-23 and a Case 3 in 2023-24. I added all three: £827.36, £3,998.25 and £1,748.60.
  2. The Enhanced FRS reasoning overstated "nothing changes". Reworded above. The zero-diff result stands.
  3. Possible conflict with Hold NICs thresholds at 2026-27 levels through 2030-31 #1959. Hold NICs thresholds at 2026-27 levels through 2030-31 #1959 merged first, and this branch is rebased on it.
  4. Nits, all fixed:
    • the £7,247 label;
    • "to within 1p" for the household rows;
    • changelog scope ("from 2015-16 to 2025-26");
    • the ni_class_4_maximum comment, which now says "from 2015-16" and that the 2024 Act changed only Steps Two and Five;
    • an Act name in ni_class_2.yaml;
    • the lower_profits_threshold_applies description;
    • the notebook table's reg 100 wording;
    • the Class 1 assumption behind the 2023-24 Case 3 YAML comment;
    • rulespec-uk#423 now lists NICA 2011 s.2 and says Change PolicyEngine label for "Claims UC" to "Claims Universal Credit" #353 must land first.

A delta review of 6cb67d6 (job 20261002-094504-ni-class-2-4-review-r2) checked the #1959 conflict resolution, the r1 fixes and the three new rows: APPROVE WITH NITS. Its nits are fixed in d978a9f:

  • the date-error sentence above;
  • the test docstring's reg 100 wording;
  • a note that the impact runs predate the rebase;
  • saved test logs;
  • the changelog now says "legal source".

A delta review of 8e62932 on GPT-6.1 Sol (--task review --tier hard, job 20261003-220428-ni-class-2-4-review-r3c) gave REQUEST CHANGES:

  1. Blocking: Class 2 tested the wrong profit measure after Charge Class 4 NICs on Chapter 2 profits, after capital allowances, the trading allowance and Schedule 2 losses #1919. With £13,000 of profit and £1,000 of capital allowances in 2023-24, Class 4 was £0 but Class 2 was £179.40. Fixed in 0278f13: ni_class_2 reads ni_class_4_profits (s.11(3)), with the YAML cases and property tests above.
  2. Nit: the impact runs predated the merges. The household table and the Enhanced FRS runs above were re-run at the current heads on 2026-10-07.

A delta review of b3f3de5 on Opus 5.5 (--task review --tier standard, job 20261007-121526-ni-class-2-4-review-r4) confirmed the s.11(3) fix in law, the tests, the merges and every Effect and Enhanced FRS number, and gave REQUEST CHANGES:

  1. Blocking: the UC minimum income floor's notional Class 2 used the pre-2022 rule, so in 2022-23 and 2023-24 it disagreed with ni_class_2 (an existing property test failed once it sampled those years). Fixed in c1364a4 with a shared helper, YAML cases and wider property years; the UC table above shows the effect.
  2. Change PolicyEngine label for "Claims UC" to "Claims Universal Credit" #353's s.11(3) section pointed at WTC worker element sets > instead of >= for hours requirement #423, but the Class 4 profit measure is Change date format in PR template #379's. Fixed in Change PolicyEngine label for "Claims UC" to "Claims Universal Credit" #353 and Change date format in PR template #379, and in the axiom: line above.
  3. Change PolicyEngine label for "Claims UC" to "Claims Universal Credit" #353's companion cases P and Q mislabelled profit before capital allowances as Chapter 2 profit. Relabelled.
  4. 2019-20 has 53 contribution weeks (HMRC NIM70200), and the model charged 52. Fixed in c1364a4 (class_2_contribution_weeks) instead of being listed as a gap.
  5. The Hypothesis property no longer reached any threshold, because profit and allowances were drawn independently. It now draws relevant profits first.
  6. Nits, all fixed: invariant 4's domain (in-year losses added to the tests, and the narrower domain stated in invariant 3); the test docstring's trading-allowance and whole-pound wording; this body's item 6 baseline, row attribution and test-coverage wording; saved logs; Change PolicyEngine label for "Claims UC" to "Claims Universal Credit" #353's 2027 figure, "from 6 April 2024", the Budget PDF link and item 8 inside the paste-as-is block; ni_class_2's documentation now cites NIM70650 and says "as modelled in ni_class_4_profits".

A delta review of 92acbb4 (c1364a4 merged with main) on GPT-6.1 Sol (--task review --tier hard, job 20261008-093036-ni-class-2-4-review-r5b; a first dispatch was cancelled by a restart) gave APPROVE WITH NITS. It found all 13 r4 findings resolved; checked the week count against an independent calendar enumeration for 2015-2030 and regulation 155; recomputed the two 2019-20 statute rows and the four new floor cases exactly; swept 1,920 person-years at every threshold corner and eight ages (floor NI less Class 4 equalled Class 2 to £0.0002, and every age-gated row had nil Class 2); confirmed that b3f3de5's formulas fail 8 of the new Python tests and 4 of the new YAML cases; reproduced every NI and UC figure, explained the household net-income differences through #2103, and verified the saved Enhanced FRS comparison. Its nits, all fixed:

  1. WTC worker element sets > instead of >= for hours requirement #423's 2019-20 companion row still used 52 weeks. Updated (row E, and the week note).
  2. Household net income at a merged head also moves with main's Energy Bills Support Scheme correction (Correct Energy Bills Support Scheme amounts and timing #2103). The Effect section now says which heads its runs used and what has merged since.
  3. The test's 53-week comment was too broad (2024-25 starts on Sunday 7 April but has 52 weeks). Fixed in 0e9736d.
  4. The test's carry-forward comment, invariant 3's trading-allowance caveat, and "Both issues" with three issues named. Fixed.
  5. class_2_liable's docstring described a full liability test; it is the threshold condition, and callers apply the rate (nil from 2024-25). Fixed in 0e9736d.

A read-only delta review of 28b11c1, the head (GPT-6.1 Sol, --task review --tier hard, job 20261009-200213-ni-class-2-4-review-r6), gave APPROVE WITH NITS: 0e9736d changes two test comments and one docstring and no behaviour; apart from the model-baseline.md resolution the merge is byte-for-byte main's own changes; the three model-baseline.md links point at the right lines; the PR's other 24 files are unchanged by the merge; all five r5 nits are resolved; #423's row E recomputes to £2,167.56; and #2227 conflicts with nothing here. Its two wording nits are fixed: #423's week note now names 2025-26, and the r5 summary above says what r5 reproduced and what it verified from saved results.

Commands run

At 28b11c1 (the head): CI passed every check, including the full test job. I ran nothing locally at this head, because the host was reserved for other work. It differs from 92acbb4 by a comment-only commit and a merge of main.

At 92acbb4, c1364a4 merged with main (logs in ~/reviews/ni-class-2-4-2058-2026-10-07/logs/, *-92acbb446.log; run under the machine-wide heavy-test lock):

  • ruff format --check . and ruff check .: clean.
  • policyengine-core test policyengine_uk/tests/policy -c policyengine_uk (the full YAML suite): 2,747 passed.
  • pytest test_ni_class_2.py test_ni_class_4_statute.py test_ni_class_4_maximum.py test_ni_class_4_properties.py test_ni_class_4_profits_properties.py test_ni_class_1_age_properties.py test_ni_threshold_freeze.py test_uc_minimum_income_floor_properties.py test_parameter_descriptions.py test_parameter_metadata.py test_fiscal_year_parameters.py test_build_metadata.py: 184 passed, 1 skipped. (190 at c1364a4; main's Correct the 2015-16 and 2016-17 secondary threshold; pin the annual threshold to reg 11(3A)(b) in every year #2182 removed six parametrised cases from test_ni_threshold_freeze.py.)

At c1364a4:

  • Mutants of ni_class_2 reading ni_class_4_profits_before_losses, or profit less capital allowances: both fail test_ni_class_2_tests_thresholds_on_profits_after_deductions and test_ni_class_2_properties (mutants-ni_class_2-c1364a42f.log).
  • Enhanced FRS and household runs as described under Effect (impact/).

At 0278f13 (the s.11(3) fix): ni_class_2.yaml and test_ni_class_2.py with the previous ni_class_2 formula fail 6 of the 8 new YAML cases and both new pytest tests. Review r4 re-ran this independently; its logs are in review_r4_artifacts/r4_logs/ (mut_*.log).

Earlier rounds:

  • The Class 4 YAML run against main's Class 4 parameters: 8 failed, 2 passed (2026-10-02; no log was saved).
  • PR Apply the income-related ESA and income-based JSA remunerative work conditions #2031's head (e38ea0c) with this PR's NI parameter, variable and test files overlaid: its ESA remunerative-work YAML and the NI YAML, 108 passed. That includes the 2023-24 case this fix was needed for (£12,500 profit, £7,300 personal pension: esa_exempt_work_earnings 170.19, esa_income_eligible false).
  • Not run locally: the microsimulation tests and make documentation. CI runs both.

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits October 2, 2026 09:33
- 2023-24 weekly rate £3.45 (SI 2023/236 reg 3(a)); model year 2023
  charged £3.15.
- From 2022-23 Class 2 is payable only on profits that exceed the lower
  profits threshold (£11,908, SI 2022/1329; £12,570, SI 2023/236 reg
  3(b)). Profits from the small profits threshold up to it are treated
  as paid (s.11(5A)-(5B)); the model charged 52 weeks on them.
- Small profits threshold: £6,725 in 2023-24 and 2024-25 (not CPI
  uprated), £5,965 in 2015-16 and 2016-17 (not 3,965). CPI projections
  now run from the latest statutory value.
- Compulsory Class 2 ends 6 April 2024 (NICRRA 2023 s.3), not 1 January.
- Every value cites its amending instrument.
- Tests: YAML cases per year and threshold; a statute-table differential,
  range and monotonicity property test over model years 2015-2030; a
  2023-24 regulation 100 pin using the default £3.45 rate.
- NI notebook: describe the rule and regenerate saved charts; the rates
  chart now selects percentage parameters by unit.

Fixes #1887

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 2023-24 lower profits limit £12,570 from 6 April 2023 (NICs (Increase
  of Thresholds) Act 2022 s.2(3)-(4)); model year 2023 used £11,908.
- 2022-23 main and additional rates 9.73% and 2.73% for the whole year
  (Health and Social Care Levy (Repeal) Act 2022 s.2(2)); the model used
  10.25% and 3.5%.
- 2023-24 additional rate 2% (s.15(3ZA)(b)); the model used 3.5%.
- 2015-16 upper profits limit £42,385 (SI 2015/588 art 3(b)), not
  £42,386; the £43,000 limit dated 6 April 2016 (SI 2016/343 reg 2).
- Main rate cut to 6% dated 6 April 2024 (NICRRA 2024 s.1(3)(a)).
- Every Class 4 limit and rate cites its amending instrument.
- Regulation 100 already reads the rate parameters; a comment records
  that its written percentages track the Class 4 rates in every year,
  including the 2022-23 modification (HSCL (Repeal) Act 2022 Sch para 6).
- Tests: the four stale 2023 YAML expectations replaced with hand-derived
  statutory values (ni_class_4 1,568.70; ni_class_4_main 3,393;
  ni_class_4_maximum 1,748.60 by reg 100 Case 3), plus 2022-23, 2015-16
  and 2016-17 cases; test_ni_class_4_statute.py adds a statute table for
  every year, 17 hand-derived liabilities and an exact-rational
  differential (s.15(3) capped by reg 100) at every limit and as a
  Hypothesis property.
- Docs: NI notebook chart values and the model-baseline link.

Fixes #1968

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Hand-derived table: add regulation 100 Case 3 before 2022-23 (2019-20,
  £827.36), Case 2 in 2022-23 (£3,998.25) and Case 3 in 2023-24
  (£1,748.60), so each regime has all three cases.
- ni_class_4_maximum comment: the percentages match from 2015-16; the 2024
  Act changed only Steps Two and Five.
- Class 4 maximum YAML: state the pay-spread assumption behind Case 3.
- lower_profits_threshold_applies description: the treated-as-paid band
  applied in 2022-23 and 2023-24.
- ni_class_2.yaml: Act name; changelog: citations run to 2025-26;
  notebook table: reg 100 also applied where Class 2 was paid before
  2024-25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1959 holds the PT, UEL, LPL and UPL through 2030-31 and corrects the
2025-26 LEL to £125, but left the notebook's saved chart on the old
CPI-uprated values. Only the chart's y values change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 6 commits October 3, 2026 18:29
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…i-parameters

# Conflicts:
#	docs/book/programs/gov/hmrc/national-insurance.ipynb
s.11(3) defines Class 2 "relevant profits" as the profits on which Class 4
is payable under s.15, which s.15(3) computes under Schedule 2. Since #1919
those are ni_class_4_profits: profit after capital allowances, the trading
allowance and loss relief. ni_class_2 still read self_employment_income, so
in 2023-24 £13,000 of profits with £1,000 of capital allowances paid £179.40
of Class 2 on relevant profits of £12,000, below the £12,570 threshold.

- ni_class_2 reads ni_class_4_profits; documentation and references.
- ni_class_2.yaml: 8 cases with capital allowances, the trading allowance
  and losses on each side of the 2015-16, 2021-22, 2022-23 and 2023-24
  thresholds (6 fail on the previous formula).
- test_ni_class_2.py: the statute differential and Hypothesis property now
  vary capital allowances, and check the shared-base invariant against the
  model's own ni_class_4_profits.
- Notebook and changelog wording.

Found by delta review r3 (job 20261003-220428-ni-class-2-4-review-r3c).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 7, 2026 16:12
Review r4 (job 20261007-121526-ni-class-2-4-review-r4):

- The UC minimum income floor computed its notional Class 2 with the
  pre-2022 rule (threshold >= small profits threshold). In 2022-23 and
  2023-24 it deducted £163.80 or £179.40 from thresholds that s.11(5A)-(5B)
  treats as paid, so it disagreed with ni_class_2 and moved UC away from
  the law (lone parent, 16-hour floor of £8,669.44 in 2023-24: UC £90.09
  too high on main's figures, £98.67 on this branch's previous head).
  New policyengine_uk/utils/class_2.py holds the s.11(2) test and the
  contribution-week count; ni_class_2 and the floor both use it.
- A contribution week starts at midnight between Saturday and Sunday
  (SI 2001/1004 reg 1(2)) and the year's first week on the first Sunday
  after 5 April (HMRC NIM70200), so a full year is 53 weeks in 2019-20
  (and 2025-26, when the rate is nil). The model charged 52: £156
  instead of £159.
- Tests: floor YAML for 2019-20, 2022-23 and 2023-24; floor property
  years 2019, 2022 and 2023 with a lone-parent example; Class 2 YAML for
  2019-20 and 2020-21 weeks; test_ni_class_2 draws relevant profits
  first, adds in-year trading losses, checks the week count against the
  calendar and NIM70200's example; the 2019-20 reg 100 rows in
  test_ni_class_4_statute use 53 weeks (£2,167.56).
- Docstring, documentation, notebook and changelog wording.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 9, 2026 07:52
- test_ni_class_2: a year has 53 contribution weeks when 6 April is a
  Sunday, or a Saturday in a 366-day year (2024-25 starts on Sunday 7
  April but has 52); the carry-forward comment notes the trading
  allowance case.
- class_2_liable: the s.11(2) threshold condition only; callers apply
  the rate, which handles the 2024 abolition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 10, 2026 00:19
@MaxGhenis
MaxGhenis merged commit cfee0e6 into main Oct 10, 2026
7 checks passed
@MaxGhenis
MaxGhenis deleted the fix-class-2-class-4-ni-parameters branch October 10, 2026 00:20
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Merged on gates at 28b11c1 (merge commit, --match-head-commit). Audit:

  • CI: gh pr checks exit 0 at 28b11c1; both workflow runs (37926455188, 37926455163) are for that head and succeeded, including the full test job.
  • Mergeable: MERGEABLE / CLEAN, no change request.
  • Independent review at the merged head: r6, GPT-6.1 Sol via Subfleet (--task review --tier hard, job 20261009-200213-ni-class-2-4-review-r6): APPROVE WITH NITS. Both nits were wording (rulespec-uk#423's week note and this PR body's r5 summary) and are fixed; neither touched code.
  • Earlier rounds: r1 and r2 approve with nits (Opus 5.5); r3 request changes (GPT-6.1 Sol: s.11(3) relevant profits), fixed in 0278f13; r4 request changes (Opus 5.5: the UC minimum income floor's notional Class 2, 53-week years, and test and Axiom-issue findings), fixed in c1364a4; r5 approve with nits at 92acbb4 (GPT-6.1 Sol), fixed in 0e9736d.
  • Impact: stated in the body from real runs. Enhanced FRS (2024-25 base): no record changes in 2024-2031 on 12 outputs, at a094911 against c1364a4. Liabilities change only in model years 2015-2023, shown by the household and Universal Credit tables. The tables were not re-run at 28b11c1 (the host was reserved for other work); r5 reproduced every NI and UC figure at 92acbb4, and the later merge of main changes no input they read.
  • Why no separate approval: this corrects the model to SSCBA 1992 ss.11 and 15, SI 2001/1004 regs 1(2) and 100, and HMRC NIM70200/NIM70650. It supersedes Fix Class 2 NICs: 2023-24 rate, the 2022-23 lower profits threshold, and the small profits threshold #1888.

Axiom parity stays queued in TheAxiomFoundation/rulespec-uk#353 (s.11), #379 (Sch 2 Class 4 profits) and #423 (s.15 and reg 100).

Reports, logs and run outputs: ~/reviews/ni-class-2-4-2058-2026-10-07/ and ~/reviews/ni-class-2-4-audit-2026-10-02/.

MaxGhenis added a commit that referenced this pull request Oct 10, 2026
Brings in #2058 (cfee0e6), which fixes Class 2 and Class 4 National
Insurance against SSCBA 1992 for 2015-16 to 2026-27. It conflicted with this
branch's NI corrections in nine files, all resolved to main's version:

- Parameters: class_2/flat_rate, class_2/small_profits_threshold,
  class_4/rates/main, class_4/rates/additional and
  class_4/thresholds/lower_profits_limit. Every value this branch set is the
  same on main (2015-16 and 2016-17 SPT £5,965; 2023-24 Class 2 £3.45;
  2023-24 LPL £12,570; 2022-23 Class 4 9.73% and 2.73%; 2023-24 2%). Main
  also adds the 2023-24 and 2024-25 SPT of £6,725 (s.11(4)(b)) and dates
  each entry from 6 April with its statute. Class 2 ends on 6 April 2024
  (NICs (Reduction in Rates) Act 2023 s.3) where this branch kept the
  model's 1 January 2024 entry. The Class 4 main rate falls to 6% on
  6 April 2024, where this branch kept 4 April.
- Tests: ni_class_2, ni_class_4, ni_class_4_main and ni_class_4_maximum.
  Main has this branch's statutory values (52 x £3.45 = £179.40;
  £1,568.70; £3,393; reg 100 maximum £1,748.60) plus 2015-16, 2016-17
  and 2022-23 cases.

So the PR no longer changes any shared NI parameter or test. The changelog
drops its NI bullet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 10, 2026
Reg 99(3)(a) as at 6 April 2023 spares chargeable income "equal to or less
than the amount specified in section 11(4)(a) ... (lower profits
threshold)". #2058 added that amount as
gov.hmrc.national_insurance.class_2.lower_profits_threshold (£11,908 in
2022-23, £12,570 in 2023-24). The rule and the test reference now read it
instead of the Class 4 lower profits limit. The values are the same in both
years the deduction applies, so no result changes.

Two 2022-23 YAML cases pin the threshold and its date. At £11,908 of profit
there is no Class 2: (£11,908 - £3,900) / 52 = £154.00, over the £152
higher limit. At £11,909, Class 2 of 52 x £3.15 and Class 4 of 9.73% x £1
come off: (£11,909 - £0.0973 - £163.80 - £3,900) / 52 = £150.87, within
it. ESA YAML: 43 cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 10, 2026
Brings in #2027 (claimant and partner legacy awards) and #2058 (NI
classes 2 and 4). Resolutions:

- docs/book/programs/gov/dwp/housing-benefit.ipynb: main's passport
  paragraph (#2027's claimant-or-partner wording); this branch's benefit
  cap paragraph (each scheme's own cap).
- legacy_award_readers/passports.yaml (#2027): its benefit-cap case read
  the removed shared is_benefit_cap_exempt_health_disability. It now
  asserts both per-scheme specified-benefit exceptions (HB reg 75F(1)(a),
  UC reg 83(1)(a)); both read the benefit unit's income-related ESA, so the
  claimant's own award lifts each cap as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant