Skip to content

Value share-like capital by asset type for the sale-expense deduction - #2131

Open
MaxGhenis wants to merge 18 commits into
uc-capital-sale-expensesfrom
sale-expense-share-split
Open

MaxGhenis wants to merge 18 commits into
uc-capital-sale-expensesfrom
sale-expense-share-split

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #1969 (sale-expense deduction, head 1efee62). It also merges #1974 (share_like_capital, head 365f642). Once both are on main, this diff is the split below plus its tests.

What

#1969 deducts 10% for the expenses of sale from corporate_wealth as a whole. The guidance treats its parts differently:

Asset Guidance 10%?
Quoted shares ADM H1665; DMG 29671, 52671, 84763; HBGM W1.513 yes
Unit trusts bid price, no costs of sale even through a broker: ADM H1673-H1674; DMG 29680-29681, 52680-52681, 84771-84772; HBGM W1.530-W1.531 no
ISAs withdrawal value; no paragraph applies the 10%: ADM H1656-H1658; DMG 29662-29664, 52662, 84748-84750 no (see the methodology note)

#1974's share_like_capital is corporate_wealth as supplied, or the itemised components' sum where that is larger. This PR splits it in two:

  • share_like_capital_with_sale_expenses: share_like_capital less the itemised holdings listed in gov.dwp.share_like_capital.without_sale_expenses (unit and investment trusts, stocks and shares ISAs), floored at nil. When nothing is itemised, it is all of share_like_capital.
  • share_like_capital_without_sale_expenses: the rest. It is exactly nil when nothing is itemised.

All six capital lists (UC, HB, IS, JSA, ESA, PC) name both parts, and all six sale-expense lists name the first.

Methodology note (d1396, parked). The UK hub's review asked whether the trust bucket and stocks and shares ISAs should escape the 10%:

  • Investment trusts: WAS asks about unit and investment trusts in one question. Investment trusts are quoted shares, and were 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).
  • ISAs: H1656 values an ISA at what the holder would get on withdrawal, but does not say whether the 10% applies.

The exempt holdings are therefore one parameter list of whole variables. A ruling that moves a whole component, for example applying the 10% to stocks and shares ISAs, or to the whole trust bucket, is a one-line parameter change and needs no code change. A ruling that applies the 10% to only part of a component (say, the investment-trust share of the trust bucket) cannot be expressed in this list; it would need a weighting parameter and a formula change.

Impact

None on any dataset that does not itemise corporate_wealth, which covers every released uk-data build. The differential test below checks this exactly.

On a split dataset (PolicyEngine/policyengine-uk-data#501), WAS round 8 puts directly held shares at 32.9% of the share-like wealth (£217bn of £659bn). The average deduction on corporate_wealth therefore falls from 10% to about 3.3%. Measured caseload effects will come from #501's release-equivalent builds, which are queued behind the shared heavy-run lock.

Invariants (tests)

test_capital_share_components.py, Hypothesis with pounds-and-pence inputs (as a dataset stores them; the engine rounds each to float32), checked exactly against the engine's float32 arithmetic:

  1. share_like_capital keeps the supplied aggregate unless the components exceed it beyond the tolerance.
  2. With nothing itemised, the part with sale expenses equals share_like_capital and the other part is exactly 0. Otherwise the part with sale expenses equals share_like_capital less trusts and ISAs, floored at nil, and the two parts sum to share_like_capital.
  3. Differential against the lists before itemising. On identical unitemised inputs, every programme's assessable capital and UC eligibility equal Value means-tested capital less 10% sale expenses and secured debt (UC reg 49 and legacy equivalents) #1969's exactly, annually and monthly. The inputs include negative aggregates, and a value whose 90% is a fraction of a penny over £16,000.
  4. Split effect. A consistent split raises a working-age adult's UC capital by 10% × (trusts + ISA).
  5. Components alone are valued by type: £1,000 + 90% × £4,000 + £3,000 + £5,000 = £12,600.

Fixed cases:

  • float32 grouping: trusts and ISA are summed before they are subtracted, so £399,999.98 of share-like capital less £200,000 + £199,999.98 is exactly nil.
  • Empty exempt list: a reform listing no exempt holdings values everything less 10% (£11,800 either way, itemised or not).
  • Before Universal Credit: IS and JSA capital in 2012 (the exempt list starts on 1996-10-07, the earliest legacy source date).
  • Rounding boundaries carried over from Itemise corporate_wealth's share-like components for the means tests #1974: a penny of shares at the £16,000 limit counts, 10p of genuine excess counts, and one float32 unit above £16,384.01 keeps the aggregate.

#1969's property tests keep their own legal asset set, now naming share_like_capital_with_sale_expenses, and assert each programme's list against it. Their oracle values an unitemised household's share-like capital from its corporate_wealth.

Mutation check. Dropping the nothing-itemised branch from the formula fails the differential.

Round-2 review fixes (head 10c54a5):

  • The exempt list started in 2013, so 2012 legacy capital raised ParameterNotFoundError. It now starts on 1996-10-07, with a 2012 regression for IS and JSA.
  • add() returns None for an empty list. The exempt holdings are now summed from a numeric zero, and an empty-list reform is tested.
  • The property oracle subtracted trusts and ISA one at a time. It now reproduces the engine's grouping exactly, and the counterexample is pinned.
  • This body no longer claims a partial-component ruling is a parameter edit.

Local runs (head 6a5a13a): pending; results to follow.

Reproducer: policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation_share_split.yaml::UC split of the same total exempts trusts and ISAs and crosses the limit

axiom: TheAxiomFoundation/rulespec-uk#395 queued (extended with the asset-type distinction: TheAxiomFoundation/rulespec-uk#395 (comment))

🤖 Generated with Claude Code

MaxGhenis and others added 5 commits September 30, 2026 22:19
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>
# 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>
…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 vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.sources lists;
  • 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_wealth of £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 at tests/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:

  1. 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.

  2. 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.

  3. 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.

  4. Nit. tests/test_capital_share_components.py. You removed the itemising-invariance test on purpose. A one-line comment pointing to the replacement differential in test_capital_valuation_properties.py would stop someone restoring it.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Independent review (GPT-6.1 Sol, UK hub sweep, 2026-10-12): REQUEST_CHANGES at b1a660045. The full review is below. Blockers 1 and 2 are methodology calls the ADM leaves open; they are queued for Max as d1396. Findings 3–6 are for whoever picks this up after uk-data#501 lands (the triage deferred this PR until after 28 Oct).

VERDICT: REQUEST_CHANGES
Head reviewed: b1a6600

  1. [blocker] Investment-trust treatment requires Max’s methodology decision. UC sale_expenses/sources.yaml:14 exempts the combined unit-and-investment-trust bucket across all six programmes. ADM H1665/H1674 distinguishes quoted shares, which receive 10%, from unit trusts, which have no sale costs. Fix: obtain Max’s explicit decision; separate investment trusts or implement an approved proxy.

  2. [blocker] The ISA exclusion is an unresolved interpretation. UC sale_expenses/sources.yaml:20 infers exemption from the ISA paragraphs’ silence about 10%. ADM H1656 specifies withdrawal value without expressly overriding the general sale-cost rule. The input describes only “amount held”:7. Fix: have Max settle whether the input represents net withdrawal proceeds and how sale costs apply, then align all six lists and tests.

  3. [should-fix] Reconcile main’s reported-capital changes. Against local origin/main 3f174d0, merge-tree reports conflicts in growth-factor documentation, uprating indices, and uc_assessable_capital.py:10. Main Record benefit-unit capital once; derive UC and Pension Credit reported capital from it #2201 introduced shared reported-capital handling. Fix: update the stack while preserving its reported-capital formulas, documentation, and uprating entries.

  4. [should-fix] Clean merges still change newer regression expectations. pension_credit_assessable_capital.py:33 values unitemised £20,000 corporate wealth at £18,000. Main’s new CTR regression:660 expects £20,000. Fix: recalculate its capital, deemed-income and savings-credit expectations, and test the newer HB/CTR routes after reconciliation.

  5. [should-fix] Impact evidence is missing. The PR’s Impact section defers measurement to the data PR. test_capital_valuation_properties.py:336 establishes compatibility when every component is zero; it does not establish enhanced-FRS impact against main. Fix: provide an actual Microsimulation comparison with dataset/version, simulation year, both SHAs, commands and traceable outputs, including any measured zero result.

  6. [should-fix] The stacked diff includes protected and unrelated changes. Its actual base-to-head diff spans 164 files, including simulation.py:235, tests/conftest.py:19, and unrelated tax, earnings and housing changes inherited from main. Fix: refresh the prerequisites/base so the final review diff isolates the exemption changes.

The stated mechanisms and invariants match the code under the chosen methodology. Property tests cover the load-bearing logic; replacing the old itemising-invariance test is justified. The exemption commit adds no skips or xfails. Ruff formatting and lint passed for its three changed Python files.

Shell testing was attempted below the 30 GB compressor threshold. pytest -n 0 lacked xdist; three property files failed collection because Hypothesis was missing. The serial subset collected six tests but was interrupted before any ran. No independent test passes are claimed.

GB regulations and programme manuals were reviewed; several NI references and the HMRC percentages remain unverified. Requested gh commands failed network access, so web and local Git evidence were used. No files were changed.

MaxGhenis and others added 2 commits October 12, 2026 09:59
# Conflicts:
#	docs/book/assumptions/growthfactors.md
#	policyengine_uk/data/uprating_indices.yaml
The independent review of 21412b6 found that reconstructing
corporate_wealth as components plus a floored residual could tip a household
across the capital limit on float32 rounding (components summing to
16,000.0009 against a supplied 16,000), and changed unsplit inputs with a
negative corporate_wealth. The six capital lists now name one formula
variable, share_like_capital: corporate_wealth as supplied, unless the
itemised components add up to more than it beyond a rounding tolerance
(1e-5 relative plus a penny), in which case their sum. Every dataset that
carries only corporate_wealth, or builds it as the components' sum, counts
exactly corporate_wealth; a household given only components has them
counted.

Tests: a differential against the original corporate_wealth lists on
identical inputs (unsplit with negative and fractional aggregates, and
consistent splits), annual and monthly, asserting capital and UC
eligibility equal exactly; the float32 limit case and the negative
aggregate; and the block's definition as a property. Replacing the formula
with the old floored residual fails the float32 test.

Also: the pension-age HB home disregard is Schedule 6 paragraph 26 of SI
2006/214, not paragraph 1 (review finding, predates this PR).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis MaxGhenis added the ci-recheck Re-triggers Fix evidence without changing the PR (UK hub, 2026-10-12) label Oct 12, 2026
MaxGhenis and others added 3 commits October 12, 2026 10:59
…ale-expense-share-split

# Conflicts:
#	docs/book/assumptions/growthfactors.md
#	policyengine_uk/data/uprating_indices.yaml
#	policyengine_uk/tests/test_capital_valuation_properties.py
…le-expense-share-split

# Conflicts:
#	docs/book/assumptions/growthfactors.md
#	policyengine_uk/data/uprating_indices.yaml
#	policyengine_uk/tests/test_capital_share_components.py
#1974 replaced the components-plus-residual design with one share_like_capital
block that keeps the supplied corporate_wealth exactly. This follow-up now
splits that block in two:

- share_like_capital_with_sale_expenses: share_like_capital less the itemised
  holdings in gov.dwp.share_like_capital.without_sale_expenses (unit and
  investment trusts, stocks and shares ISAs), floored at nil; all of it when
  nothing is itemised.
- share_like_capital_without_sale_expenses: the rest, exactly nil when nothing
  is itemised.

The six capital lists name both parts and the six sale-expense lists the
first, so datasets that carry only corporate_wealth keep #1969's flat 10%
exactly (differential test, annual and monthly, against the lists before
itemising, including negative aggregates and a value whose 90% is a fraction
of a penny over the limit). The exempt holdings are a parameter list, so the
methodology call on investment trusts and ISAs (d1396) is a one-line change.

Merged the refreshed #1969 (54ed063) and #1974 (7784193). #1969's
property oracle reads the share-like sources from an unitemised household's
corporate_wealth; the split invariants (definition of both parts, the
unitemised differential, split effect = 10% of trusts plus ISAs on UC
capital, components-only valuation) are in test_capital_share_components.
Dropping the nothing-itemised branch from the formula fails the differential.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis MaxGhenis changed the title Exempt unit trusts and stocks and shares ISAs from the sale-expense deduction Value share-like capital by asset type for the sale-expense deduction Oct 12, 2026
MaxGhenis and others added 3 commits October 13, 2026 08:25
Round-3 review of 7784193: with no corporate_wealth, a penny of shares fell
inside the absolute tolerance and vanished, so UC eligibility at the £16,000
limit differed from the same penny entered as corporate_wealth; and 1e-5
relative plus a penny (£0.17 at £16,000, about 174 units in the last place)
hid genuine excesses. The tolerance is now 1e-6 of the larger of
corporate_wealth and the components' sum, against a float32 bound of about
3e-7 for a float64 sum of three components rounded and re-added in float32,
and it is relative only, so a household with no corporate_wealth has any
positive components counted in full.

Tests: the component-winning case compares exactly against the engine's
float32 sum; new independently specified cases for a component penny at the
limit (same capital and UC eligibility as the penny entered as
corporate_wealth, annually and monthly) and a genuine £0.10 excess; both fail
under the old tolerance. The six list descriptions and the changelog state
the qualified rule; the module claims are narrowed to UC eligibility and
uprating metadata.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uping

Review of b7e6bc5:
- gov.dwp.share_like_capital.without_sale_expenses started in 2013, after
  the legacy capital lists (JSA from 1996-10-07), so a 2012 simulation with
  unitemised corporate_wealth raised ParameterNotFoundError; it now starts at
  1996-10-07, and Income Support and JSA capital in 2012 are tested (both
  fail with the 2013 start).
- An empty exempt list made add() return None; the exempt holdings are now
  summed from a numeric zero, and an empty-list reform (every share-like
  holding less 10%) is tested.
- The property oracle now follows the engine's float32 grouping (components
  left to right, exempt holdings summed before subtraction) and compares
  exactly; the reviewer's example (trusts £200,000, ISA £199,999.984375) is
  pinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 5 commits October 13, 2026 08:50
…le-expense-share-split

# Conflicts:
#	policyengine_uk/tests/test_capital_share_components.py
Round-4 review of f64da77 (APPROVE WITH NITS):
- N2: the tests pinned the tolerance from above only. A new case uses
  pence-valued components (£16,015.98 + £286.98 + £81.05) whose float32 sum
  lands one unit in the last place (£0.00195) above £16,384.01: more than 1e-7
  of the value, less than 1e-6. It exposed that comparing
  itemised > corporate_wealth + tolerance in float32 rounds the tolerance up
  to a whole unit; the formula now compares the difference, which float32
  computes exactly for close values, and a 1e-7 tolerance now fails the case.
  Property-test components are drawn as pounds and pence.
- N4: the differential now also runs a projected year (2027, annual and
  monthly), with the original lists restored for 2026-2030.
- N1: the error-bound comment states it assumes float64 dataset tables.
- N5: stocks_and_shares_isa says it is part of corporate_wealth.

N3 (a microcosm export where corporate_wealth falls below the ISA) does not
apply to microcosm main: corporate_wealth there is corporate_wealth_excl_isa
plus the ISA, both drawn non-negative.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…le-expense-share-split

# Conflicts:
#	policyengine_uk/tests/test_capital_share_components.py

@vahid-ahmadi vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs changes before merge. The split itself is right and well tested. But this branch carries both CI failures from #1969 and #1974, it inherits the #1965 holding problem in both forms, and nothing hosted has run on it.

@MaxGhenis, this is a delta review. My last review was at b1a66004; this one is at 6a5a13a4. Since then the split has been rebuilt on #1974's block: share_like_capital_with_sale_expenses and _without_sale_expenses, with an exempt-holdings parameter. I reviewed the diff against #1969 + #1974 merged at their current heads: 21 files, +678/−186.

Status of my earlier findings:

  • F1 (retarget to main, CI): still open. See finding 2.
  • F2 (ISA exemption described as a judgement): partly addressed. The body now has a methodology note, but the parameter text still states it as settled. See finding 3.
  • F3 (employee share options caveat): not taken. See finding 5.
  • F4 (invariance test comment): addressed. The module docstring now points to the differential.

Findings:

  1. must (carried in from #1969 and #1974). This head contains both CI failures and the #1965 interaction:

    • test_projection_horizon.py:181 fails, as on #1974. The ISA variables are now mapped in uprating_indices.yaml.
    • test_savings_credit_only_receipt_properties.py:508 fails, as on #1969. It expects 601.02 where reg 19 gives 621.82.
    • Company holdings, probed on this head merged into current main. Take a single UC claimant who is sole owner of a trading company, with a £10,000 holding and £5,000 savings:
      • with corporate_wealth £10,000, UC capital is £4,000 (expected £5,000);
      • with only directly_held_shares £10,000, UC capital is £14,000 (expected £5,000), because the pool cap still reads corporate_wealth.
    • On this head merged into main, the same 8 uc_company_analogous_business.yaml cases and 3 test_uc_company_owner_properties.py properties fail as on #1969. Five of those YAML cases are the holding problem; three are the plain 90% revaluation and only need new expectations (see my #1969 review).
    • Here the holding should come off share_like_capital_with_sale_expenses at 90%, since an owner's shares are directly held shares.

    Once the fixes land on #1969 and #1974, merge them through and re-run.

  2. must. No CI has run on this PR, because its base is uc-capital-sale-expenses. The body's "Local runs" line is still "pending". Retarget to main and get the full suite green before anything in the stack merges. If this PR lands alone, it carries #1969 and #1974 with no window where the 10% on shares disappears. On a #1969 + #1974 tree without this PR, £5,000 savings + corporate_wealth £12,000 gives £17,000 for UC; this head gives £15,800.

  3. should. parameters/gov/dwp/share_like_capital/without_sale_expenses.yaml:10-12 still says "no ISA paragraph applies the deduction", as if that settled it. The changelog fragment states the ISA exemption flatly too.

    • ADM H1656 and DMG 29662 value an ISA at "what people would get if they withdrew their investment" and say nothing about costs of sale.
    • The body parks this, and the investment-trust question, for a decision (d1396).
    • Until it's decided, the parameter text should call the exemption a judgement, as it already does for investment trusts. I'm not suggesting which way to decide.
  4. nit. The six capital/sources.yaml descriptions each have an unwrapped line of about 175 characters. An example is universal_credit/means_test/capital/sources.yaml:8 ("share_like_capital_with_sale_expenses and share_like_capital_without_sale_expenses split ..."). Rewrap to match the rest.

  5. nit. share_like_capital_with_sale_expenses.py:3 hardcodes COMPONENTS for the "is anything itemised" gate, while the exempt list is a parameter. A reform adding a new exempt variable outside COMPONENTS would be ignored for a household that itemises only that variable. Consider a comment saying the exempt list must be a subset of the components, or a test asserting it. Separately, employee share options still take the 10% as "directly held shares" with no caveat (my F3). One clause in without_sale_expenses.yaml would cover it.

What I checked:

  • Guidance, re-read from the current PDFs:

    • ADM H1656-H1658 (ISA at withdrawal value; nothing on costs of sale);
    • ADM H1673-H1674 and DMG 29680-29681 (unit trusts: "no costs of sale ... even if persons use an agent");
    • DMG 29662 and 29664 (ISA), and DMG 29671 (10% on shares).

    The paragraph numbers in the parameters match. I didn't check the NI or HBGM numbers, or the HMRC Table 9.6 percentages.

  • Probes on this head:

    • unsplit £5,000 + corporate_wealth £12,000 gives £15,800 (UC, IS; PC at 70), as on #1969;
    • split shares £4,000, trusts £3,000, ISA £5,000 gives £16,600;
    • components only with £1,000 savings gives £1,000 + 90% × £4,000 + £3,000 + £5,000 = £12,600, matching the body.
  • Revert check. capital_valuation_share_split.yaml run on #1969 + #1974 without this PR's source changes: 10 failed. At this head: 10 passed.

  • Tests. I ran the same property files and YAML directories as on #1969 and #1974, plus #1965's company-owner tests.

    • At this head: 2 failed (the two carried CI failures) and 2,360 passed; YAML 1,889 passed.
    • Merged into current main (clean): 5 failed (those two plus the three #1965 properties) and 2,405 passed; YAML 8 failed (company cases) and 1,980 passed. Current main 714b1438c on the same set: all 2,363 pass, and YAML 1,964 pass.
  • Lint. ruff check and ruff format --check on the 11 changed Python files: clean.

  • Repo process. The .fixed fragment and the Reproducer and axiom lines are present, and the named reproducer case exists. The branch also carries #1974's .added fragment, which is fine if it lands as one unit.

  • Overlap with my open PRs. #2382 merges cleanly with it.

  • Not checked. Any dataset run, or uk-data #501.

🤖 Generated with Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-recheck Re-triggers Fix evidence without changing the PR (UK hub, 2026-10-12)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants