Repository navigation
Relieve trading losses by each programme's rule - #2085
Conversation
trading_loss (a loss as a positive amount, separate from the profit in self_employment_income) now reaches each programme by its own rule: - Income Tax: trade loss relief against general income (ITA 2007 s.64) reduces net income, and so adjusted net income, for the loss-making year. It is limited to net income (s.25(4)) and to the s.24A cap, the greater of £50,000 and 25% of adjusted total income (s.24A(5), (8)). It comes off non-savings income first, then savings, then dividends. - Class 4 and Class 2 NICs: the relief reduces trading profits only (SSCBA 1992 Sch 2 para 3(4); s.11(3) relevant profits), with losses brought forward (loss_relief, s.83). - Tax credits: the claimants' losses come off their income (SI 2002/2006 reg 3(1) Step 4). - Market income and HBAI household income count the loss as negative income. - Means tests read neither the loss nor anything net of it, so it never offsets other earnings (UC reg 57, HB reg 38(10), IS reg 38(11) etc.). loss_relief now holds only losses brought forward (s.83). It no longer adds the previous year's trading_loss, which relief against general income may already have used. trading_loss is uprated like self-employment income. Tests: YAML cases for the relief, cap, ordering, Class 4, tax credits and household income; Hypothesis properties for the relief definition, a differential against income cut in s.25 order, monotonicity and bounds, means tests seeing the loss only through tax, tax credit income, and the channels HBAI income can move through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…it loss - adjusted_total_income follows s.24A(8): Step 1 total income (taxable components, losses brought forward added back) less own pension contributions given relief, up to the greater of £3,600 and relevant UK earnings (FA 2004 s.190) and none from age 75 (s.188(3)(a)). - net_income_before_trade_loss_relief is the one base for adjusted net income, the relief limit and the savings/dividends part; it counts basic income where a reform makes it taxable. - UC sets a trading loss against the person's other trades' profits before the minimum income floor, never against employed earnings (UC Regs 2013 reg 57(2) Steps 1-3). - Tax credits subtract only the claimants' losses, not a child's. - New input ni_class_4_losses_brought_forward for losses carried forward for Class 4 only (SSCBA 1992 Sch 2 para 3(4)(b)). - The savings-then-dividends order is the model's allowance order, which s.25(2) can beat for the Personal Allowance too: documented, #2106. - YAML cases for each finding; property tests cover UC netting and children's losses, with fewer examples for CI time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nings - uc_trading_losses_set_against_profits (UC Regs 2013 reg 57(2)) is the one netting UC earnings and the reg 82 earnings tests in is_benefit_cap_exempt_earnings and is_benefit_cap_exempt_health_disability deduct, so a loss-maker's cap matches the same household with netted profits. - adjusted_total_income takes relevant UK earnings (FA 2004 s.189(2)) as taxable employment income (incl. taxable benefits and statutory pay) plus chargeable trading profits. - YAML for both review cases; the property test's netted twin compares the earnings test and the capped award; property tests run 3 examples per property with larger batches to cut CI time (#2099). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With 3 generated examples per property (to keep CI time down, #2099), a run could miss the cases that matter, and a mutant that stopped limiting relief to net income survived. Each property now also checks pinned inputs: relief limited by net income, both caps, contributions above relevant earnings, no relief from age 75, profits beside a loss, income spilling into savings and dividends, the benefit-cap household, a child's loss and a loss beside pay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
UK hub (2026-10-12 12:05Z): the hub adopted this PR under d1280's fallback, because it has no live owner session. A Subfleet build job ( |
|
Adoption hand-off for #2085 at head Locked validation:
The 2026 enhanced-FRS comparison used the certified artifact, re-hashed before use: SHA-256 Disclosed limitations: round 2 accepted the allocation deferral to #2106, including the saved £107.50 overcharge. #2108 covers existing benefit tax-deduction approximations. UC annual netting assumes even accrual and omits reg.57A's monthly forward-only loss stock and award continuity. Income Tax carry-forward requires explicit unrelieved losses; tax-credit carry-forward needs its own balance. The hub owns the independent review at the final pushed head; no final approval is claimed here. policyengine-uk-data #528 relocks after this PR releases. This job does not merge either PR. The committed work is pushed once. The PR remains draft for resumption under the user’s disk-stop instruction; readiness and independent review are pending. Logs, |
|
Independent review (GPT-6.1 Sol, UK hub): REQUEST_CHANGES at VERDICT: REQUEST_CHANGES
The review covers only
The programme-law assessment is qualified:
The uprating entry is correct and consistent: uprating_indices.yaml:125 places profits and losses together under OBR per-capita mixed-income growth. Both variables’ metadata use the corresponding cumulative index. The £0 impact is expected, supported by impact.json:29: both runs have zero effective losses, identical weights and dependencies, and calculated outcomes rather than supplied outcome columns. The artifact lacks #528’s relock should measure loss prevalence and weighted amounts after imputation/calibration/uprating, then compare the released model with losses present versus zeroed on the same rebuilt artifact. Re-estimate relief, taxes, benefits and household/HBAI income; the historical £13m–£18m figures are not current-head estimates. Tax-credit impact needs an active-policy year. The zero-profit property directly compares actual tax, but its benefit comparisons hold paid tax/NI deductions fixed. It proves the disclosed programme-rule invariant, not unconditional end-to-end award monotonicity. No new skips, xfails or allowlist changes weaken this PR’s tests; rewritten carry-forward expectations reflect the corrected contract. The logs support 29/29 reproduction assertions, 90 programme YAML tests and 3,187 full YAML tests passing. Python stopped at 75%, without a final result. Unlabelled worksteal output cannot establish which tests remain; the HBAI property in finding 2 is the concrete outstanding failure risk. I ran no tests or microsimulation and made no changes. |
|
Round-3 fixes are ready for the hub's independent review at 5c0d13b. Original author/history preserved; no force-push or merge. The taxpayer/year trading-allowance election now coordinates Income Tax and Class 4 current losses, retaining separate prior nominal NIC balances. Required England regression gives net income £38,800 and tax £5,246. The Pension Credit TV-licence passport and both Scottish pinned populations are covered. Full-run DOB timing failures were reproduced and addressed only by suppressing Validation: the full Python suite completed all 5,680 nodes (5,560 passed, 16 failed, 102 skipped, 2 xfailed); all 16 failures subsequently passed on rerun. 94 focused Python checks, 3,214 policy YAML cases, 29 saved-review assertions, and the NI before/after proof pass. This combines the completed full run with scoped reruns; it is not a single green full run at the final head. The coverage-dependent local skip passed with sys.monitoring; the glibc-only check remains unsupported on macOS. Existing strict xfails are #1986 and #1947. Formatting/lint, required 2026 certified enhanced-FRS comparison: main ea00c02 versus final head above; dataset SHA-256 5ba399ea5ab9a6c7d4e9aaf6c623080beb34d9ad5f330f6244dbad72b8d960b6, rehashed before use. Exact differences are £0 for Income Tax, UC, tax credits, HB, household net income and HBAI income. The artifact has no trading_loss input or negative self-employment income, so this cannot refresh the historical £13m–£18m estimate. Foreground simulations and resource gates passed. Main advanced during validation; a read-only merge against f64155a is clean. The recorded merged baseline is the one used for local validation and impact. Open scope remains explicit: accepted #2106 optimal-allocation deferral, #2108 annual benefit-tax approximation, annual UC rather than reg.57A monthly loss stock, and no separate historical tax-credit loss balance. Axiom parity remains queued at rulespec-uk #429. PolicyEngine/policyengine-uk-data #528 relocks after this model PR releases. No data build or merge was performed. Local hand-off and aggregate-only evidence are in |
|
UK hub independent review, round 4 (Subfleet, review standard tier, served by Opus 5.5 because the Codex lanes were on hold), head VERDICT: REQUEST_CHANGES All three earlier findings are fixed. The Class 4 £699/£700/£701 cases are correct. I'm still requesting changes for one new problem introduced by e1debd4: the allowance election can be triggered by a loss that Class 4 itself says does not exist (finding 1). The fix is small.
The three earlier findings
R3.1 detail. The election is one Person/YEAR variable, so it covers the taxpayer's year. It compares the current loss with the allowance's saving after capital allowances and prior losses (trading_allowance_deduction.py:78-83).
Other checks
Limits of this review: I had no shell, so I ran no tests and couldn't use |
|
Round-4 fixes are ready for the hub's independent review at 60ae5a5, merged with main The allowance election now reads only the year's supplied loss: the unset-2026-loss regression preserves the £900 allowance and £10,000 nominal Class 4 balance. Raw-loss/tie docs are corrected; the retained DOB health-check suppression is explicitly unrelated to trading losses. The current-main UC conflict is resolved with company-trade netting, separate employment/trade deductions and actual pre-MIF cap earnings. Validation: 204 unique focused YAML cases and 101 Python checks pass, no focused skips/xfails/failures. The adjusted 8-case UC file passed again at final head (CLI and core API). Locked clone venv, at most 4 workers/BLAS threads, foreground throughout; nice +10 was attempted but sandbox-denied. Format/lint, required uvx Ruff format check, diff/fix-evidence checks and final recovery bundle pass. No new full local suite per round-4 instruction; prior 5c CI had all four Python shards/YAML/Test Result green, new CI pending. 2026 certified enhanced-FRS impact: Income Tax £0; UC +£8,924,131.55; tax credits £0; HB £0; household net income +£8,924,137.99; HBAI +£8,924,131.55; Class 4 £0. Dataset SHA-256 5ba399ea5ab9a6c7d4e9aaf6c623080beb34d9ad5f330f6244dbad72b8d960b6, rehashed before each load. Restoring only main's cap-earnings consumer makes all seven outcomes match main exactly: the uplift comes from that merge integration, while this artifact has no effective trading losses and cannot refresh the historical £13m–£18m tax estimate. Final test-only commit leaves model code unchanged; final branch simulation reproduces the prior results exactly. Accepted #2106 allocation deferral, #2108 annual benefit-tax approximation, annual UC instead of the reg.57A monthly loss stock, absent historical tax-credit loss stock and queued Axiom #429 remain explicit. PolicyEngine/policyengine-uk-data #528 relocks after this model PR releases; its rebuilt artifact must compare losses present versus zeroed and confirm supplied-year Class 4 eligibility. No data build or merge was performed. Local hand-off/evidence: |
#2399 landed the same benefit-cap earnings exception change this branch made (is_benefit_cap_exempt_earnings reads uc_individual_earned_income_before_mif). The only conflict was in that file's comments; take main's version, so this PR no longer touches it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Fine once the changelog and impact section are brought up to date with the #2399 merge (finding 1). The loss rules themselves check out.
@MaxGhenis, I reviewed the current head 379f504b. The earlier rounds' findings are fixed, and I re-checked the Income Tax core against the statute: s. 64 relief against net income, limited by s. 65(1) to the s. 24A cap and the available income. I also checked the s. 24A(8) adjusted total income steps and the s. 783AF/783AL election. My hand calculations agree with the model:
- Cap. 2025, London, employment income £300,000 and a £200,000 loss. Cap = max(£50,000, 25% × £300,000) = £75,000. Net income is £225,000 and tax is 7,540 + 34,976 + 44,937 = £87,453. The model gives £75,000 and £87,453.
- Cap with relief at source. Adding £40,000 of personal contributions gives adjusted total income of £260,000 (s. 24A(8) Step 3) and a £65,000 cap. The model matches.
- The relief wastes the personal allowance. Employment income £20,000 and a £15,000 loss gives net income £5,000 and tax £0. That follows s. 65: a claim can't be restricted to keep the allowance in use.
- Trades netted for Income Tax and Class 4. A £30,000 profit and a £10,000 loss on another trade gives Income Tax of £1,486 and Class 4 of (20,000 − 12,570) × 6% = £445.80.
- HICBC follows the lower adjusted net income. Employment income £70,000 and a £15,000 loss gives adjusted net income £55,000, so no charge. With no loss the charge is £677.
-
must: one changelog fragment and the impact section describe a change this PR no longer makes.
changelog.d/trading-loss-company-merge.fixed.mdsays the PR applies "the same actual earnings before the minimum income floor in the benefit cap earnings test".- At this head,
is_benefit_cap_exempt_earnings.pyis not in the diff. Main already readsuc_individual_earned_income_before_mifthere (#2399,e6564306b), and the merge at379f504btook main's version. - So the release note would claim a change main already made. The impact table's UC row (+£8.924m) and the sentence explaining it were measured at
60ae5a5, before that merge. - With no losses in the data, the only UC change left in the diff is the
uc_trading_losses_set_against_profitsterm. I'd expect £0 now, but I haven't re-run it. - Please drop that clause from the fragment and re-run or relabel the table.
-
should:
adjusted_total_incomere-implements the pension relief limit, and differs from #2240.adjusted_total_income.py:56-67relieves contributions up to max(£3,600, relevant earnings) for any contribution type. It usestaxable_employment_incomeplus profits.- #2240 rewrites
pension_contributions_reliefto the same s. 190 limit. It gives the £3,600 increase only through relief at source (s. 191(7)), and it usesemployment_income. - s. 24A(8) Steps 3-4 deduct the contributions actually given relief at source (s. 192) and excess net pay or claimed relief (ss. 193(4), 194).
- Once #2240 lands, reading
pension_contributions_reliefhere would keep the two in step, instead of having two versions of s. 190. - The amounts are small; it only moves the cap above £200,000 of adjusted total income. But whichever PR merges second should reconcile them.
- #2240 rewrites
-
nit: the date-of-birth test change is unrelated. It brings
changelog.d/date-of-birth-properties.fixed.md, a user-facing "fixed" entry for a test-only change, and threetest_date_of_birth.pyentries on theReproducer:line. The earlier round already suggested splitting it out. If it stays, I'd drop the fragment and those Reproducer entries. -
nit: carry-forward still depends on explicit zeros for Income Tax.
trading_loss.py:24-26documents that an unset later year inherits and uprates the loss, and Income Tax relieves it again as a new current-year loss. That's fine for per-year microdata. In a multi-year household run it repeats the relief. The documentation is clear, so no change is needed. It's worth keeping in mind when #528 decides how the data supplies losses.
Overlap. None of my open PRs touches the same lines.
- #2382 edits
hbai_household_net_income.pyanduprating_indices.yamlin different hunks. - #1820 rewrites
is_benefit_cap_exempt_earnings.pybut reads the sameuc_individual_earned_income_before_mif, so the UC loss netting reaches the cap test either way.
What I checked
- I read the PR body, the full diff and all the hub review rounds and responses in the comments. There are no formal reviews.
- I read ITA 2007 ss. 24A, 64 and 65 on legislation.gov.uk.
- I ran the hand-computed cases above against this head.
- At head
379f504b, in a freshuv syncenvironment in a worktree:- the 7 changed YAML files: 54 passed;
test_trading_loss_properties.pyandtest_ni_class_4_profits_properties.py: 37 passed;ruff checkandruff format --checkon the 22 added or changed Python files are clean.
- Mutation: I forced allowance treatment in
trading_allowance_deduction.py. The trade-loss and Class 4 YAML then failed 4 of 34, so the election cases bite. I restored the file afterwards. - I did not run
test_date_of_birth.pyor the national impact. CI is green at this head. - I did not re-check the UC reg. 57A, tax-credit Step Four or HB reg. 38(10) treatment beyond the earlier rounds and the YAML.
🤖 Generated with Claude Code
|
Round-5 hand-off: 4c85dfa, pushed once as a normal fast-forward. PR body updated; PR is ready. The hub dispatches the independent delta review of Fresh 2026 certified enhanced-FRS comparison: main 714b143 versus merged checkpoint 379f504. Exact £0 for Income Tax, UC, tax credits, HB, household net income, HBAI income and Class 4. Dataset SHA-256 5ba399ea5ab9a6c7d4e9aaf6c623080beb34d9ad5f330f6244dbad72b8d960b6, rehashed before each load; matching weights/dependencies, seed 0. The artifact has no trading losses, so it cannot refresh the historical £13m–£18m tax estimate. #2399 now carries the former cap change on main; this PR no longer touches the cap-earnings file. Validation: 122 focused Python checks and 166 policy YAML cases pass, no skips/xfails/failures; locked clone venv, foreground, at most four workers/threads. Trading-loss/allowance properties, all Class 4 files and UC claimant/deduction/MIF/company/statutory-pay properties are covered, plus touched programme and UC earned-income YAML. The only new commit aligns release notes: removes the stale benefit-cap clause and unrelated DOB test-only fragment. The DOB suppression remains disclosed in the body. Model and test code match the measured checkpoint. Earlier rounds through r4 and their fix commits are mapped in the body and Open items remain explicit: accepted #2106 allocation deferral, #2108 annual benefit-tax approximation, annual UC rather than monthly reg.57A loss stock, absent historical tax-credit loss stock, Axiom #429 queued, and pension-relief integration with open #2240 when the second PR merges. PolicyEngine/policyengine-uk-data #528 relocks after this model PR releases; its rebuilt artifact must compare losses present versus zeroed and confirm supplied-year Class 4 eligibility. Hand-off/evidence: |
|
Merged by the UK hub (audit). Merged with a merge commit at the tested head Gates:
|
…2085 - #2085's channel identity (test_trading_loss_properties) now measures HBAI income before the reset, the sum the identity holds for. - household_income_decile documents the tie rule: households at zero share the rank at the top of their group, so they are in decile 1 while they hold at most a tenth of people. Unit tests pin both sides of that line; the property test checks they share the lowest decile, and decile 1 below a tenth (new pinned population). - When the median before the reset is at or below zero, the reset makes it zero and no one is in relative poverty before housing costs: checked. - YAML: the reset under gov.contrib.abolish_council_tax. - Changelog: headcounts, gaps, bottom-decile moves and unchanged labour supply responses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…shared-cap-lha-rules #2399 changed the shared earnings exception this PR deletes. Its measure, uc_individual_earned_income_before_mif summed over the assessed claimants (reg. 82(1)(a), excluding MIF income under reg. 82(4)), is carried over unchanged into the UC-only is_uc_benefit_cap_exempt_earnings; the shared file stays deleted. Main's new tests that read the deleted shared names now read the UC ones, with their expected values unchanged: - test_uc_statutory_pay_properties.py (#2399; conflict): main's text and regression case, reading is_uc_benefit_cap_exempt(_earnings). - benefit_cap_earnings_exception_earned_income.yaml (#2399) and uc_trading_loss.yaml (#2085). - test_trading_loss_properties.py (#2085). Targeted YAML (benefit_cap folder, benefit_cap_by_scheme, uc_trading_loss): 121 passed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #1916
Trading losses now follow each programme's rule: Income Tax can relieve a loss against general income; UC nets concurrent trades; tax credits deduct the claimants' losses; HB does not offset another employment's earnings. Profits remain non-negative
self_employment_income, and losses are supplied separately as positivetrading_loss. Market and HBAI income count losses as negative income.The branch preserves the original author's commits and merges main
714b1438c1f6f2a46e279728caa5c7d77835f981at379f504b934ec2ed255ef9dd0dbc5b375676522b. Main's independent Class 4 loss pool, net UC minimum income floor, Pension Credit tax-credit passport and winter-heating income components are retained. Claimant-only tax-credit losses enter the sharedtax_credits_current_year_incomecalculation before passporting.The UC conflict combines this PR's concurrent trading-loss netting with main's reg.77 company earnings and separate employment/trade tax and NI deductions. The loss helper caps relief at the positive combined result of the person's own trades and signed company earnings. #2399 now carries the benefit-cap earnings change on main; this PR no longer touches
is_benefit_cap_exempt_earnings.py. The UC loss helper continues to feed actual earned income, including company trade results. Four new YAML cases cover a loss against company-only profit, the cap transition from £12,000 to £7,000 with identical paid deductions and a £20,000 MIF, a signed company loss leaving employment unchanged, and fixed trade/employment tax and NI deductions when losses cancel all trade profit.Trading allowance election
ITTOIA 2005 s.783AF makes every relevant trade's profits and losses nil under full relief; s.783AL makes the opt-out election for the individual's year. HMRC BIM86076 explains electing out to claim a loss. The model compares the raw loss supplied for the individual's tax year, before the s.24A and available-net-income caps, with the allowance's effective saving after capital allowances and explicit prior losses. Ordinary expense treatment and a loss claim win when that raw supplied loss is larger; a tie uses allowance treatment. Comparing the raw loss preserves possible unrelieved carry-forward even when both treatments yield nil current net income. Otherwise allowance treatment suppresses current Income Tax and Class 4 expense-based loss relief across the person's trades. This is a modelled choice, rather than an automatic HMRC opt-out, and does not optimise future loss use, carry-back, optimal allocation across income components or benefit effects. Missing receipts retain the documented existing allowance fallback.
The election uses
supplied_inputfor the election's annualtrading_loss, as Class 4 already does: a prior year's carried/uprated input cannot cancel this year's allowance. Income Tax's documentedtrading_lossinput behaviour remains: an unset year can inherit and uprate an earlier input; callers must supply explicit zeros when that is not intended.Partial relief also replaces all trades' current expenses (s.783AI, BIM86018); prior carry-forward losses remain separate and may follow partial relief (BIM86015).
trading_lossunset. The 2026 allowance is £900, Class 4 profits before losses and current Class 4 loss are £0, and the entire prior £10,000 nominal Class 4 balance remains unconsumed. The multi-year property reference now uses each year's supplied loss for this election.free_tv_licence_valueto move with its Pension Credit passport. The exact age 76/pension £19,500/loss £10,000/child-age 1 case is pinned and directly tested.zip.Programme law and limits
loss_reliefis explicit, with trade matching/unrelieved balance supplied by the caller. Carry-back, non-commercial/non-active restrictions and historical cash-basis restrictions remain outside scope. S.25(2) allocation optimisation remains the accepted Allowances and reliefs are set against savings before dividends, not in the order giving the greatest reduction (ITA 2007 s.25(2)) #2106 deferral, including its saved £107.50 overcharge.trading_lossis included alongside profits inpolicyengine_uk/data/uprating_indices.yaml:128; its metadata uses the same cumulative OBR per-capita mixed-income index.Earlier findings mapped to the merged head
Both earlier reviews/responses and their cited law memo were read. Their confirmed findings and accepted deferrals are mapped below to source at
379f504b934ec2ed255ef9dd0dbc5b375676522b.379f504b9(policyengine_uk/paths)variables/gov/hmrc/income_tax/reliefs/adjusted_total_income.py:49and:62variables/gov/hmrc/income_tax/allowances/received_allowances/received_allowances_savings_income.py:18variables/gov/dwp/universal_credit/income/uc_individual_earned_income_before_mif.py:79variables/gov/dwp/tax_credits_current_year_income.py:53variables/gov/hmrc/national_insurance/class_4/ni_class_4_losses_brought_forward.py:36variables/gov/hmrc/income_tax/reliefs/net_income_before_trade_loss_relief.py:26variables/gov/dwp/is_benefit_cap_exempt_earnings.py:29(now carried by main #2399)variables/gov/hmrc/income_tax/reliefs/adjusted_total_income.py:56variables/gov/hmrc/income_tax/allowances/trading_allowance_deduction.py:90;variables/gov/hmrc/income_tax/reliefs/trade_loss_relief_against_general_income.py:44variables/gov/hmrc/national_insurance/class_4/ni_class_4_trading_loss.py:62;tests/test_ni_class_4_profits_properties.py:121;tests/policy/baseline/gov/hmrc/national_insurance/class_4/ni_class_4_trading_loss.yaml:62tests/test_trading_loss_properties.py:116,:478and:762tests/test_trading_loss_properties.py:216and:349variables/gov/hmrc/income_tax/allowances/trading_allowance_deduction.py:90; unset-year YAMLtests/policy/baseline/gov/hmrc/national_insurance/class_4/ni_class_4_trading_loss.yaml:200; property referencetests/test_ni_class_4_profits_properties.py:682variables/gov/hmrc/income_tax/allowances/trading_allowance_deduction.py:21;variables/gov/hmrc/income_tax/reliefs/trade_loss_relief_against_general_income.py:19tests/test_date_of_birth.py:87,:128,:268; disclosure below; its test-only release note is removeddata/uprating_indices.yaml:128;variables/input/trading_loss.py:31Review rounds through r4 are addressed: original-review fixes are incorporated in
eac9df01376c00f1fb74e987ebccf41b519eab95; r3 election/TV-licence/Scotland changes are in31a877b7a15b9128d606ea3d5caab99960432316and Class 4 coordination ine1debd40ecc20194bd1eec7446c3f95c08ae32f4; r4 supplied-year-loss/tie fixes are in2d408a2af17e6380d1fcea0ee303cb7e8168e107. Main/company integration and fixture updates are3de25876d999f88c910d4a9373a93e59de5f9d47and60ae5a5ae6821adfcd80deec3cc6b8d35f0afb21. The hub's #2399 merge is379f504b934ec2ed255ef9dd0dbc5b375676522b.The latest review's stale cap release-note clause has been removed. The test-only DOB release note and its unrelated Reproducer entries are also removed; the timing-health suppression itself remains, documented below. The pension-relief overlap with #2240 remains an integration follow-up: whichever PR merges second must reconcile
adjusted_total_incomewith the contribution relief actually allowed under ss.190–194. No model code was changed in round 5.Validation
At final head
4c85dfa0d6023f3f6cffdf10d947313013cfab6d, 122 focused Python checks and 166 policy YAML cases passed, with no skips, xfails or failures. This covers trading-loss and allowance properties; all four Class 4 Python files and the Class 4 YAML directory; UC claimant earnings, deductions, MIF, company and statutory-pay properties; and loss/relief, UC earned-income, tax-credit and HB YAML. The model/test tree is identical to the measured checkpoint379f504b934ec2ed255ef9dd0dbc5b375676522b.Commands ran in the foreground:
uv run --frozen --no-sync pytest ... -n 4 --dist worksteal -o xfail_strict=trueanduv run --frozen --no-sync policyengine-core test ... -c policyengine_uk. Exact paths, commands and results are retained in.job/validation-r5.json. The requested nice +10 was attempted but the sandbox deniedsetpriority. All BLAS/OpenMP limits were four threads.make format,uvx ruff format --check .,git diff --checkand the fix-evidence checker pass. A verified recovery bundle is saved in.job/self-employment-loss-r5.bundle.Locked environment: Python 3.13.9, policyengine-core 3.33.2 and policyengine-uk 2.130.1; installed with
UV_LINK_MODE=clone uv sync --frozen --extra dev.uv.lockSHA-256:72f8b9da78db07a5af32eec54a80cb1375fff56749b7fa21227f91e231a85139. Repositorymake formatpasses; requireduvx ruff format --check .is recorded with the final validation below.No new full local suite under the round-5 instruction; CI runs it. The previous full local run completed with failures that passed subsequent focused reruns; it was not a single green full local run. Checkpoint CI at
379f504b9and final-head CI status are recorded in the hand-off.The retained DOB change is unrelated to trading-loss policy: it suppresses only
HealthCheck.too_slowon three properties. Their 30/25/25 example counts, pinned examples, bounds, assertions and other health checks remain unchanged. No new skips or xfails were added.The zero-profit property compares Income Tax with the same zero-loss person. Benefit comparisons hold paid tax/NI and other benefits consistently to isolate each programme's loss rule; annual tax-payment timing and passport changes can otherwise lower an award (#2108). Axiom parity remains queued at #429 with the recorded signed-encoder/corpus blockers.
Reproducer: policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/reliefs/trade_loss_relief_against_general_income.yaml
2026 enhanced-FRS impact
Fresh round-5 comparison: 2026 in the same locked interpreter, seed 0, unchanged entity weights and committed source archives.
714b1438c1f6f2a46e279728caa5c7d77835f981.379f504b934ec2ed255ef9dd0dbc5b375676522b(round-5 release-note edits leave model code unchanged).5ba399ea5ab9a6c7d4e9aaf6c623080beb34d9ad5f330f6244dbad72b8d960b6.~/reviews/pepy-uk-data-1.58.0-cert/data/1.58.0/enhanced_frs_2024_25.h5.All seven differences are exactly £0, before rounding. The former +£8.924m UC uplift was #2399's cap change, now on main; the refreshed comparison supersedes it. This PR no longer changes the cap-earnings file.
The certified artifact has no
trading_lossinput or negative self-employment income; both runs have zero effective losses. This cannot update the historical £13m–£18m Income Tax loss-relief estimate. Tax credits are inactive in 2026. A losses-enabled dataset is needed to measure the policy's actual fiscal effect.Both runs stayed foreground and sequential, with at most four BLAS/OpenMP threads; pre-run free disk exceeded 110 GB and compressor use stayed below 20 GB. Source file hashes, full entity-weight hashes, matching dependency versions and aggregate-only totals are retained in
.job/impact-r5.json. Outcomes were calculated, inputs/weights preserved, and no survey records were exported. Temporary source copies are deleted after verification.PolicyEngine/policyengine-uk-data#528 relocks after this model PR releases. Its rebuilt artifact must measure effective loss prevalence/amounts and compare losses present versus zeroed before reporting updated fiscal impact. No dataset build or merge is performed by this job. The hub dispatches the independent review at the final pushed head.
axiom: TheAxiomFoundation/rulespec-uk#429 queued