Repository navigation
Conversation
Add two household-level wealth input variables, cash_isa and stocks_and_shares_isa, so the model can carry ISA balances separately. Previously the only ISA variable was the interest-income flow (individual_savings_account_interest_income); ISA *balances* had nowhere to land — investment ISAs were folded into corporate_wealth in the (now archived) policyengine-uk-data wealth imputation, and cash ISAs were not represented at all. These variables provide the model-side home for ISA balances imputed by the data pipeline (populace). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The repo dropped root changelog_entry.yaml for changelog.d/ fragments; bump_version.py and the versioning workflow only read changelog.d/**, and the .added suffix is what infers the minor bump. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the axiom: PR-description line (encoded-correct | encoded | queued | n/a) and the dispatch-ready standard for queued rulespec issues. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Class 4 was charged on raw self_employment_income. It now uses ni_class_4_profits: profit after capital allowances and the trading allowance (ITTOIA 2005 Part 2 Chapter 2), less trading losses as SSCBA 1992 Sch. 2 para. 3 allows, carried forward without limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…test Addresses the independent review: documents trading_loss carry-over, that negative profit creates no loss (as for income tax), unmodelled carry-backs and para. 3(5) deductions, pooling across trades, and the s. 83(4) order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
basic_state_pension and new_state_pension split the data year's reported State Pension by state_pension_type in the period, but additional_state_pension used the data year's type. Survey ages are held fixed across projected years, so a record's cohort, and its type, can change: for records on the basic State Pension in the data year and the new State Pension later, the band between the two flat rates was paid twice (£0.84bn in 2025-26 rising to £6.77bn in 2030-31 on the enhanced FRS 2024-25). All three components now use the period's type and add up to the reported amount uprated by that type's flat rate. Adds property tests (Hypothesis) for that identity on simulations built from data, including datasets that carry other ages in later years, and examples at hand-worked cohorts. Updates the State Pension docs with the split across years and a sourced comparison with the OBR's March 2026 forecast. Fixes #1921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dit uses The Pension Credit minimum guarantee included the severe disability addition for an Attendance Allowance recipient, but the Housing Benefit and Council Tax Reduction applicable amounts took the legacy severe disability premium, which tests a narrower tax-credit disability flag (DLA care highest rate, PIP daily living enhanced rate). Guarantee Credit passports HB to its maximum, so the gap only showed when GC ended: a single pensioner on AA lost £2,040.52 of net income when private pension rose from £11,900 to £12,000. HB(SPC) Regs 2006 Sch 3 paras 6 and 12(1) and the pensioner CTR schedules give the severe disability premium the same qualifying benefits, conditions and amounts as SPC Regs Sch I para 1 and reg 6(5), and have no adult disability or enhanced disability premium. At pension age benefits_premiums is now the Pension Credit severe disability addition plus the carer premium. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review of the State Pension docs: - Compare the model with DWP's Spring Forecast 2026 less payments abroad, which agrees with the OBR's March 2026 forecast from 2026-27; the OBR's 2024-25 and 2025-26 figures are £1.4bn and £0.1bn higher. The data-year gap is then £12.2bn in both the table and the text. - Replace the unsourced explanation that an "SRP" figure caps SERPS in the FRS: state_pension_reported comes from the FRS benefits table (and is imputed on Survey of Personal Incomes donor rows), and the FRS's mean State Pension matches DWP's. - Point the open items at their tracking issues: the enhanced FRS shortfall (policyengine-uk-data#493) and the projected pension-age population and new-cohort awards (#1929). - Drop an unsourced reference note and a reference the page no longer uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rating Address review on #1922: - Keep the is_SP_age factor in additional_state_pension as a guard. A computed state_pension_type is already NONE below State Pension age, so results are unchanged (checked with a full microsimulation rerun), and it also holds when the type is an input. - The tests now check that the components partition the reported amount: the flat-rate part is the amount up to the full rate uprated by the full rate, and the part above it is uprated by add_on_uprating, which is the model's flat-rate ratio for now. In law additional pensions and protected payments rise with CPI (SI 2026/148 arts 4(3), 6(3)); #1941 tracks that, and fixing it only needs that helper changed. - Docs: say that the model uprates add-ons by the full rate while the law uses CPI (#1941), and that records moving to a new State Pension cohort keep their reported amounts, one reason award growth lags DWP's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion Review of this PR found that sharing the Pension Credit severe disability addition made pension-age HB and CTR inherit two deviations from SPC Regs Sch I: a child in the benefit unit withheld it, although the residence test counts only people aged 18 or over (para 2(2)(f)), and a claimant's own Carer's Allowance withheld it, although only one paid "in respect of caring for him" does (para 1(1)(a)(iii)). Each qualifying adult is now withheld only when another member of the benefit unit receives a carer benefit. A couple who both qualify, one paid Carer's Allowance for the other, now gets one rate, as reg 6(5)(a) gives. Also: the pension-age premium is zero below State Pension age; YAML cases that assert an applicable amount use claimants who reached State Pension age before April 2021, so they hold with the allowance cohort split; the schedule property checks whole multiples of the weekly rate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ncome uc_earned_income subtracted benunit_tax, the whole benefit unit's income tax and NI on all income, from the unit's gross earnings. UC Regs 2013 reg. 55(5)(b) and reg. 57(2) step 3 deduct only tax and NI paid by the person in respect of their employment or trade. - uc_income_tax_on_earnings: income tax on the person's earnings, taken as the lowest slice of their non-savings income after their allowances (savings and dividends sit above it under ITA 2007 s. 16, property income above it in the engine and under s. 16A from 2027-28). - uc_national_insurance_on_earnings: Class 1 employee, Class 2, Class 4. - uc_individual_earned_income: gross earnings less the person's own pension contributions, tax and NI, floored at nil. - uc_earned_income: sum over the unit, less the work allowance. Fixes #1942. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- test_uc_earnings_deductions_properties.py: unearned income never changes earned income; UC is non-increasing in every kind of unearned income; the tax deducted equals the tax on earnings alone; earned income is never lower, and UC never higher, than under the pre-fix formula. - test_uc_state_pension_properties.py: the #1942 strict xfail now passes and loses its marker; pound-for-pound and the property-income equivalence cover families with earnings; a new strict xfail pins the Marriage Allowance transfer, which the model books on the recipient as the transferor's unused allowance (ITA 2007 s. 55B gives a fixed reduction). - Document the earnings deductions in the UC docs page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
corporate_wealth bundles three assets the means tests value differently: quoted shares less 10% for the expenses of sale (ADM H1665), unit trusts at the manager's withdrawal price with no deduction (H1673-H1674), and stocks and shares ISAs at their withdrawal value (H1656). Add household inputs for the two parts not yet modelled, directly_held_shares (UK shares and employee shares and options) and unit_and_investment_trusts, and uprate them, cash_isa and stocks_and_shares_isa with per-capita GDP like corporate_wealth, so a dataset's identity corporate_wealth == sum of components survives projection. The inputs have no consumers yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o sdp-carer-attribution
…ium and the Pension Credit addition Both rules ask whether anyone is entitled to and in receipt of Carer's Allowance or Carer Support Payment in respect of caring for the claimant or partner (HB Regs 2006 Sch 3 para 14(2)(a)(iii) and (2)(b); SPC Regs 2002 Sch I para 1(1)). The legacy premium counted only carers in the claimant's own benefit unit; the addition also attributed carers in other benefit units of the household. Both now read is_cared_for_by_carer_benefit_recipient, a person-level attribution over the people a carer benefit can be paid for (SSCBA 1992 s.70(2)). The residence tests stay separate (HB reg 3 non-dependants with para 14(4); SPC Sch I para 2). Fixes #1972 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ags, pin the qualifying lists - The attribution docstring says an unplaced award is for someone outside the household, and notes the s.70(1A) run-on. - The person-level property now checks other members (such as disabled children) against the reference's within-unit matching. - YAML cases for three claimant-or-partner flags. - A test that the Carer's Allowance, legacy premium and Pension Credit qualifying lists are the same model variables from 8 April 2013. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… at #1947 The docs edit left 'plus all of its unearned income' hanging off the earnings taper, which read as if unearned income were tapered. State the two deductions separately. The strict xfail's reason and the module docstring now cite #1947. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scottish carers receive Carer Support Payment in place of Carer's Allowance, but council_tax_reduction_applicable_income listed only carers_allowance, so a Scottish carer's reduction ignored the carer's benefit. Scottish CTR counts the Carer Support Payment component in full: SSI 2021/249 reg 57(1)(b)(iva) at working age and SSI 2012/319 reg 27(1)(j) at pension age. Neither counts the Scottish Carer Supplement (reg 57(1) is a closed list that omits it; reg 27(1)(j)(xxib) excepts it), so scottish_carer_supplement, split out in #1952, stays off the list. Adds YAML cases from statutory rates and Hypothesis properties: CTR income rises by exactly the CSP component when the carer claims, is invariant to the supplement except through income tax, and matches Housing Benefit income for carers in all three nations. Fixes #1955 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…duction Both Scottish CTR instruments deduct income tax only from earnings (SSI 2021/249 Part 6 Chapter 3; SSI 2012/319 regs 33 and 36), so in law the Scottish Carer Supplement does not touch CTR. The model deducts all income tax, so the property and YAML comments now say the dependence on the supplement through income tax is that existing approximation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stand-ins for rent_paid_as_boarder, rent_paid_as_lodger and pays_rent_to_householder, which the householder-side branch (boarder-lodger-rent) adds. This commit is dropped when that branch is merged in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…egory - personal_rent / benunit_rent: each family's own liability. The household's rent is shared equally among the people liable for it (the household head's family plus any family liable_for_share_of_household_rent: UC Regs 2013 Sch 4 para 24(4); HB Regs 2006 reg 12B(4)), plus what boarders and lodgers pay the householder (UC Sch 1 para 2(b); HB reg 12(1)). - benunit_tenure_type: a boarder or lodger rents privately whatever the household's tenure (UC Sch 4 para 20; HB reg 13C(5)(a)); in_social_housing and uc_housing_costs_element follow the family's tenure. - Non-dependants: only the household head's family has them, and families liable for rent are never non-dependants (UC Sch 4 para 9(2)(d)-(f); HB reg 3(2)(d)-(e), 3(4)). Applied to UC and HB deductions, UC bedrooms and the specified-renter test. - LHA category: Universal Credit by entitlement only (Sch 4 para 25(2)(b)); a new Housing Benefit category (reg 13D(2)-(3)) with its own size criteria and rate, including the shared rate for a claimant entitled to one bedroom who lacks exclusive use, used by LHA_cap. - Housing Benefit meals: fixed weekly amounts (Sch 1 para 2, 2008-2026) and a meals_included_in_rent input; deducted from HB eligible rent (reg 12B(2)(b), 13(13)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…able pension contributions Review of #1949 found two defects in the new deductions. - uc_income_tax_on_earnings capped the tax on the earnings slice at the person's income_tax. When a tax reduction (the married couple's allowance) made that cap bind, the pension annual allowance charge and the High Income Child Benefit Charge raised the deduction, and so did more pension income. Reductions now come off the earnings slice first, as allowances do, so the deduction never includes a charge and does not move with other income. - uc_individual_earned_income deducted every pension contribution. Contributions paid after 75 are not relievable (Finance Act 2004 s. 188(3)(a)), so reg. 55(5)(a) does not deduct them. Adds YAML cases for both, draws a married couple's allowance in the property tests, and says in the test docstring that payroll giving (reg. 55(5)(c)) is not modelled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…roperty tests The random generator rarely produced an earner old enough for the married couple's allowance, so the properties did not exercise tax reductions. A dedicated family shape now does. With it, restoring the old min(tax, income_tax) cap fails both the invariance and the differential property. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deduct only each person's own tax and NI on earnings from UC earned income
Address the merge-gate review of 215ef0b: - Use the repo's usual Hypothesis settings (derandomize=True, too_slow health check suppressed) with 10 examples per property test, so the file runs in about 5 minutes. Both property tests still fail on main's formula. - Docs: the additional State Pension bullet now says the excess is uprated; "no component before State Pension age" is stated for a computed type; FRS tables M.6a/M.6b are for Great Britain, the model's 11.36m for the UK. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…income Count Carer Support Payment as Council Tax Reduction income
…eriod-type Split additional State Pension by the period's State Pension type
Require mirroring policy changes in Axiom RuleSpec
…bility-premium Give pension-age HB and CTR the severe disability premium Pension Credit uses
Tighten the Pension Credit reported-capital docs and properties (review of #2018)
Add cash ISA and stocks and shares ISA holdings variables
# Conflicts: # docs/book/assumptions/growthfactors.md
The six capital sources lists (UC, HB, IS, JSA, ESA, PC) name directly_held_shares, unit_and_investment_trusts and stocks_and_shares_isa in place of corporate_wealth, plus a new formula variable, unitemised_corporate_wealth = max(0, corporate_wealth - components), for whatever a dataset does not itemise. Datasets without the components keep counting corporate_wealth in full; datasets that build corporate_wealth as the components' exact sum count the same total, now itemised, so each component can carry its own valuation rule (the sale-expense deduction stacked on #1969 exempts unit trusts and ISAs). No dataset's capital changes: a differential property test checks that every programme's assessable capital equals the same holdings entered as one corporate_wealth. Review nits: the growth-factor sentence now matches uprating_indices.yaml exactly; the variable docs cite the DMG for the legacy benefits, the expert valuation of unquoted shares and the quoted-share rule for investment trusts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…le-expense-share-split
…eduction corporate_wealth is now itemised in the capital sources lists (#1974), so the sale-expense lists name directly_held_shares, which DWP values less 10% for costs of sale (ADM H1665; DMG 29671/52671/84763; HBGM W1.513), and unitemised_corporate_wealth, which keeps the previous flat treatment on datasets that do not itemise. Unit trusts have no costs of sale even when sold through a broker (ADM H1673-H1674; DMG 29680-29681, 52680-52681, 84771-84772; HBGM W1.530-W1.531), and an ISA is valued at what the holder would get by withdrawing it, with no paragraph applying the 10% (ADM H1656-H1658; DMG 29662-29664, 52662, 84748-84750). The survey bucket of unit and investment trusts is treated as having no costs of sale; investment trusts were 8.2% and 6.9% of the pooled funds in stocks and shares ISAs at 5 April 2022 and 2025 (HMRC ISA Table 9.6). The property tests keep their own legal asset set and assert each programme's list against it, and gain the split invariants: the residual, backward compatibility with every component nil, conservation at a zero rate, split effect = rate x (trusts + ISA), and no double counting. #1974's itemising-invariance test no longer holds by design and is replaced by them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Thanks Max. Reviewed at head b1a66004.
The "+10.5k lines" is the main merge carried in through #1974. The real diff over #1969 + #1974 (merged at their heads) is 11 files, +710/−125:
- the six
sale_expenses.sourceslists; - the new
capital_valuation_share_split.yaml; - the property tests;
test_stock_capital_periods.py;- a changelog fragment.
That's what I reviewed.
Guidance:
- ADM H1674 is explicit: unit trusts have "no costs of sale. This applies even if persons use an agent, such as a stockbroker."
- H1665 applies the 10% to quoted shares.
- H1656 values an ISA at "what people would get if they withdrew their investment".
The lists now apply the 10% to directly_held_shares and the unitemised residual only, which is right for shares and unit trusts. SPC Sch V and UC Sch 10 have no disregard that changes this.
Probes:
- savings £5,000, shares £4,000, trusts £3,000, ISA £5,000 (
corporate_wealth£12,000) gives £16,600 for UC, HB and IS. The same holdings with only the components entered also give £16,600. - An unsplit
corporate_wealthof £12,000 still gives #1969's £15,800. - Your monthly case (£12,300) matches.
Tests:
- At the head: the capital-valuation, share-component, wealth-component, stock-period and PC reported-capital property tests, 26 passed. DWP, family and household YAML, 1,064 passed.
- Merged into current main (the merge is clean): YAML, 1,389 passed. Properties: 19 passed and 2 failed. The two failures are the same stale
applies()oracle as on #1969 (here attests/test_capital_valuation_properties.py:240), not the new share-split properties. They'll clear when #1969's fix is carried through. - There's no CI on this PR, because its base isn't main, so these local runs are the only test evidence so far.
Findings:
-
Should fix (merge order). Retarget to main as soon as #1969 merges, and get CI green on the retargeted head before merging. Until then, nothing hosted has run on these lists. This PR must land in the same window as #1969 and #1974 (see my notes there): with those two in and this one out, the 10% on shares disappears.
-
Should fix.
parameters/gov/dwp/universal_credit/means_test/capital/sale_expenses/sources.yaml:20-22, and the same sentence in the other five lists. The ISA exemption is weaker than the unit-trust one:- H1674 says outright that unit trusts have no costs of sale. For ISAs, the guidance is silent and you're inferring from H1656 ("withdrawal value").
- A stocks-and-shares ISA holding quoted shares has to sell them through the ISA manager. That is a broker sale under H1605, and reg 49(1)(a) applies wherever "there would be expenses attributable to sale".
I'd keep ISAs exempt, since most ISA money is in funds, but describe it as a judgement, like the investment-trust one, rather than "no ISA paragraph applies the 10%". Give the directly-held-shares share of stocks-and-shares ISAs from HMRC Table 9.6 alongside it.
-
Nit.
variables/input/directly_held_shares.py:9. Employee share options now take the 10% as "shares". An unexercised option isn't sold through a broker and is often not realisable at all. It's fine as an approximation, but say so in the list descriptions next to the investment-trust caveat. -
Nit.
tests/test_capital_share_components.py. You removed the itemising-invariance test on purpose. A one-line comment pointing to the replacement differential intest_capital_valuation_properties.pywould stop someone restoring it.
Stacked on #1969 (sale-expense deduction) and includes #1974 (the itemised capital lists). Once both merge, this diff is just the sale-expense lists and tests.
What
#1969 deducts 10% for the expenses of sale from
corporate_wealthas a whole. The guidance treats its parts differently:All six
sale_expenses.sourceslists (UC, HB, IS, JSA, ESA, PC) therefore namedirectly_held_sharesandunitemised_corporate_wealthin place ofcorporate_wealth.unitemised_corporate_wealthis #1974's residual: all ofcorporate_wealthon datasets that don't itemise it, so those datasets keep #1969's flat treatment exactly.Approximation, stated in every list. The Wealth and Assets Survey asks about unit trusts and investment trusts in one question, so the whole
unit_and_investment_trustsbucket counts at full value. Investment trusts are quoted shares and arguably take the 10%. They made up 8.2% of the pooled funds in stocks and shares ISAs at 5 April 2022 and 6.9% at 5 April 2025 (HMRC ISA Table 9.6).On WAS round 8, directly held shares are 32.9% of the share-like wealth (£217bn of £659bn; PolicyEngine/policyengine-uk-data#501). The deduction therefore averages 3.3% of
corporate_wealthon split data, against 10% under #1969.Invariants (tests)
The #1969 property tests keep their own hard-coded legal asset set: land, property, directly held shares and unitemised corporate wealth; not cash, trusts or ISAs. They assert each programme's list against it, so a list that drops HB's property sources or adds trusts or ISAs fails. New properties:
corporate_wealth− Σ components);corporate_wealth];corporate_wealth, Σ components);total_wealth,net_wealthandcorporate_sector_wealthignore the components.The new YAML file
capital_valuation_share_split.yamlhas hand-computed cases for UC (unsplit, consistent split, components only, partial split, components abovecorporate_wealth) and one split case each for HB, IS, JSA, ESA and PC. For example, with savings £5,000 plus shares £4,000, trusts £3,000 and an ISA £5,000, UC capital is £5,000 + £3,600 + £3,000 + £5,000 = £16,600, over the limit. The same £12,000 unitemised gives £15,800.#1974's itemising-invariance test no longer holds by design, so it is replaced by these properties.
Local results:
gov/dwp,household/wealth): 833 passed;tests/code_health: 1,864 passed;ruff format --check: clean.Impact
None on datasets that don't itemise
corporate_wealth, which is every released uk-data build so far. On policyengine-uk-data#501's split build the deduction falls from 10% ofcorporate_wealthto 10% of the directly held shares. The data PR measures the effect once both land.axiom: TheAxiomFoundation/rulespec-uk#395 queued (extended with the asset-type distinction: TheAxiomFoundation/rulespec-uk#395 (comment))
🤖 Generated with Claude Code