Repository navigation
Conversation
UC Regs 2013 reg. 49(1) and its legacy equivalents (HB Regs 2006 reg. 47, HB (SPC) Regs 2006 reg. 45, IS Regs 1987 reg. 49, JSA Regs 1996 reg. 111, ESA Regs 2008 reg. 113, SPC Regs 2002 reg. 19) calculate capital at market or surrender value less 10% where a sale would incur expenses and less any encumbrance secured on it. The model summed every capital source at full value. Each programme gets a capital.sale_expenses node (rate 0.1 and the sources whose sale incurs expenses: land, property and corporate_wealth, not cash savings). A shared helper applies the 10% before the encumbrance and never values an encumbered asset below nil. New household inputs carry debt secured on other residential property, non-residential property and land; the Enhanced FRS has none, so they default to zero. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Each programme's sale-expense parameters now cite its GB and NI regulations, the guidance paragraph that orders the 10% before the encumbrance, and per-asset guidance with exact PDF page anchors (DMG ch 52 for ESA, HBGM Annex F for HB savings, H1656/H1665/H1673-H1675 for UC). - The source-list descriptions and changelog say plainly that corporate_wealth also holds unit trusts, ISAs, employee share options and, in datasets built before the pension split, non-DB pension wealth. - The helper and secured-debt docs say debts net within a source category. - The property-test oracle fixes the sale-expense assets and the 10% itself instead of reading the parameters, checks pension-age HB, and runs on larger populations. New hand-computed cases cover HB second homes and premises, per-source flooring between two encumbered sources, pension-age HB, and a monthly secured debt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HBGM W1.430 states only the general 10% rule; the rule that real property always has costs of sale comes from R(IS) 21/93, as DMG 29622 applies it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Coordination note from #1950 (UC capital income). If this PR lands after #1950, please update the "reg 49 is #1960" notes #1950 adds:
Those cases enter £10,000 of property as capital. At 90% that is 12 tariff steps, not 16, so either update the expected values or restate the input as a property value of £11,111.11. If #1950 lands second, I'll do it on rebase. #1950's merge is waiting on a decision from Max (over the £1bn/yr line). 🤖 Generated with Claude Code |
|
#1950 merged (770bc06), so this PR is second. Please update the "reg 49 is #1960" notes:
At 90% valuation, £10,000 of property is 12 tariff steps, not 16, so either update the expected values or enter £11,111.11. 🤖 Generated with Claude Code |
Resolve the capital variables onto main's claimant/partner allocation and person-level sources, valuing household sources through valued_capital. Update the let-property tests #1950 added: £10,000 of property is now £9,000 of capital under reg. 49(1), so 12 tariff steps, not 16. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two tests main added after this branch's earlier base assumed full-value capital: - The CTR savings-credit-only case holds savings 10,000 and a 7,000 second property: capital is 10,000 + 90% of 7,000 = 16,300 (SPC Regs 2002 reg. 19(a)), still over the 16,000 limit, so CTR stays nil. Deemed income is 13 steps x 52 = 676, Pension Credit income 13,314 + 676 = 13,990, and savings credit 60% of (12,376 - 208.07 x 52) less 40% of (13,990 - 12,376) = 288.22. - The reported-capital property test's proxy oracle now values land, property and shares at 90% and savings at face value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
|
Stacked follow-up: #2131 lists only 🤖 Generated with Claude Code |
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Thanks Max. Reviewed at head 22274cad.
The law is right in every programme. I re-fetched each provision from legislation.gov.uk:
-
UC Regs 2013 reg 49(1): "Capital is to be calculated at its current market value or surrender value less— (a) where there would be expenses attributable to sale, 10%; and (b) the amount of any encumbrances secured on it."
-
The same rule appears, in older wording ("10 per cent", "encumbrance/incumbrance"), in:
- SPC Regs 2002 reg 19;
- HB Regs 2006 reg 47 and HB (SPC) Regs 2006 reg 45;
- IS Regs 1987 reg 49;
- JSA Regs 1996 reg 111;
- ESA Regs 2008 reg 113.
The regulation numbers are right (JSA 111 and ESA 113).
-
CTR Prescribed Requirements SI 2012/2885 Sch 1 para 32 has the same 10% rule for pension-age CTR.
-
SPC Sch V has no disregard that touches share, unit trust or ISA valuation. Para 9 is business assets only.
The helper follows the guidance. valued_capital takes the 10% off gross value before the debt (ADM H1608) and floors each encumbered source on its own (H1615-H1616).
Probes all match hand arithmetic:
- savings £5,000 +
corporate_wealth£12,000 gives £15,800 for UC, HB and IS, and £15,800 for PC at 70 (main: £17,000); - a £100,000 second home with £95,000 debt plus £3,000 savings gives £3,000;
- a second home of £20,000 with £25,000 debt plus premises of £10,000 gives £9,000.
Tests:
- At the head: properties, PC reported capital and stock periods, 9 passed. DWP, family and CTR YAML, 967 passed.
- Merged into current main
b5b09231(the merge is clean; the branch is 280 commits behind): the same YAML set, 1,274 passed. But two of the new property tests fail; see finding 1. The green CI is from the stale merge ref.
Findings:
-
Blocking (rebase). On main + this branch,
test_valuation_matches_the_regulation_and_never_adds_capitalandtest_cash_only_households_have_no_deductionfail (2 failed, 8 passed). The valuation isn't the problem; the test's oracle is out of date.- Main now sets HB capital to nil for anyone on UC, IS, income-based JSA or income-related ESA (HB Regs Sch 6 para 5,
housing_benefit_on_passporting_benefit). It also switches the pension-age rules onhousing_benefit_pension_age_regulations_applyrather than age 67. - So a working-age single person with £2,441.62 of cash now has HB capital of nil (on main too), while
applies()attests/test_capital_valuation_properties.py:127still expects their savings. - I reproduced the cash-only failure directly. The other failing test uses the same
applies()predicate, so it is most likely the same cause. - Fix: rebase and key the pension-age branch on
housing_benefit_pension_age_regulations_apply. Then either skip units wherehousing_benefit_on_passporting_benefitis true, or give the generated units enough earnings to stay off UC. Skipping alone would hollow out the working-age HB branch, because the strategy's no-income singles are nearly all on UC.
- Main now sets HB capital to nil for anyone on UC, IS, income-based JSA or income-related ESA (HB Regs Sch 6 para 5,
-
Blocking (merge order with #1974). Git merges this branch and #1974 cleanly, but together they undo this PR:
- #1974 takes
corporate_wealthout of everycapital.sourceslist, while this PR'ssale_expenses.sourcesstill names it. So the 10% on shares silently stops. - On a 1969 + 1974 tree, the probe above goes back to £17,000. Seven YAML cases fail: 3 in
capital_valuation.yaml, and 2 each in the IS and ESA capital files. - #2131 fixes this. So either merge #1974 first and then this PR and #2131 together, or merge this PR and then #2131 retargeted to main (it carries #1974).
- A cheap guard in
tests/test_capital_valuation_properties.py: assertset(sale_expenses.sources) <= set(capital.sources)for each programme. The existing check at line 160 intersects both sides withcounted, so it can't see a stale name.
- #1974 takes
-
Should fix (body, disclosure). In "A few records carry each figure", the UC, PC and HB bullets, and the poverty bullet, attribute most of each year's change to one or a handful of records, with percentages and counts. Read against the impact table, that is effectively a record-level weighted amount. Keep the caveat ("driven by a handful of records; not an estimate") and drop the percentages, record counts and the median gain.
-
Nit.
parameters/gov/dwp/income_support/means_test/capital/sale_expenses/rate.yaml:9. This starts on 2010-01-01, to matchsources. IS reg 49 has applied the 10% since 11.4.1988. Add a sentence saying the date follows the sources list, as the HB and PC files already explain their own dates. -
Nit.
utils/capital_valuation.py:18-19. Netting debt across assets within a category is documented. H1616 actually allows it where one debt is secured on several assets. You could cite that, so the approximation reads as partly lawful rather than purely a data limitation. -
Coordination with #1965. Merged with #1965 there is no textual conflict, but the holding comes off at 100% while it is counted at 90%: savings £5,000 + a £10,000 holding gives £4,000 instead of £5,000. I've put the fix on #1965, since it rebases second.
Keep main's recorded benefit-unit capital (benunit_reported_capital), which replaces the valued household sources as recorded, and register the secured-debt inputs beside main's uprating entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
£20,000 of shares is £18,000 of Pension Credit capital (SPC Regs 2002 reg. 19(a)), still over the CTR limit: deemed income 16 x 52 = 832, Pension Credit income 14,146, savings credit 933.816 - 0.4 x 1,770 = 225.82. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's Housing Benefit passport (#1927 and the Universal Credit limb) gives a family on a passporting benefit nil HB capital, so the property's independent reg 47 valuation applies only to non-passported families. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
UK hub: #1995 (head 3727eb8) now depends on this PR. Its r3 finding 3, the Pension Credit savings-credit exit cliff, is Pension Credit's gross property valuation, which this PR fixes. So #1969 should land first; #1995 will then merge main and add two property boundary cases. This PR's latest review (Subfleet 20261019-181511-pr1969-review-v3b, 2026-10-20 01:43Z) requested changes, and there has been no new head since. 🤖 Generated with Claude Code |
… penny From the GPT-6.1 Sol review of a7d8988: - A recorded benunit_reported_capital total holds its owner's reg. 77 holding at full value, while the pool counts that holding at 90%. The report now consumes its known holding part at the counted 90% (household_uc_reported_financial_capital), so it can no longer eat another unit's savings; the owner's own assessment still takes the full holding off the report. The company-override conservation oracle consumes the same way, and a YAML regression pins the reviewer's case: £16,500 of savings and a £10,000 report that is all holding give [0, 16,500]. - valued_capital rounds the 90% value down to the penny in the claimant's favour (ADM H1665), in float64 with a guard against binary noise. A YAML regression puts £1,000 of savings and £16,666.67 of shares at exactly £16,000.00, which passes the limit (WRA 2012 s. 5(1)(a), UC reg. 18(1)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Inputs are float32, so 90% of £16,001 came to £14,400.8994 and the penny floor gave £14,400.89 (the HB £16,001 case failed). less_sale_expenses takes the value to the penny in float64 before the 10% deduction and rounds down to the penny (ADM H1665). The UC property path now uses it too, so every reg. 49(1)(a) valuation rounds the same way. Adds a Hypothesis property checking 90% of every whole-penny float32 input up to £131,071.99 against integer pence, and a UC YAML case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sol review v4b found that rounding the input to the penny first could round up (the ADM H1665 example gave 930.94, not 930.93), that nothing was rounded at the last stage, and that UC rounds to the nearest penny. - capital.round_down per programme: false for UC (UC Regs 2013 reg 6(1); NI reg 7(1)) and HB (HB Regs 2006 reg 80; HB (SPC) reg 61(6); NI 78(8), 59(7)); true for IS (reg 27), JSA (reg 92), ESA (reg 3(a)) and Pension Credit (reg 24A), which count a fraction only to the claimant's advantage. - exact_amount removes float32 storage error only where a value is the stored form of a whole penny; other values are kept exactly. - Each valuation, each UC holding and property share, and each programme's assessed capital (the last stage) is rounded by that rule. - A recorded financial total below its owner's holding now consumes the holding at its counted value, as an override does, so no part of the holding is left for another unit. Tests: the H1665 example (930.93 / 930.94), whole-penny properties for both rules, a never-wrong-way bound for any float32 input, UC half-penny, 16,000.00 after a holding, a three-way split, IS shared-capital rounding, and reports below the holding in the reg 77 conservation grid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merge-order note from #1974's owner. #1974 (head 6600477, main a8b2848 merged) is being finished for the Budget cut. If it lands first, this PR's next merge of main needs the following, or the 10% sale-expense deduction silently stops applying to shares. #1974 renames the share-like source in all six capital Rename in this PR.
Tests.
If this PR lands first instead, #1974 does the same reconciliation when it merges main. #2131 is then rebuilt on whichever head results. 🤖 Generated with Claude Code |
Reg 77 holdings are shares with sale expenses, so HOLDINGS_SOURCE is share_like_capital_with_sale_expenses: the holdings budget and the 90% counted share both read it, where #1969 read corporate_wealth. The test file keeps the round-3 fixes (projected years, the 16,000 overshoot, the power-of-two precondition, the grouping example, the exempt list's start). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sol review v5 at b3f6f60: - exact_amount raised an underflow warning on zero inputs, failing test_warning_filters. Errors are now ignored inside np.errstate, and twice the gap is compared with the spacing. - IS, JSA and ESA read household values through benunit.max, which is float64, so exact_amount used float64 spacing and never removed float32 storage error: 16,000.01 of savings floored to 16,000.00, at the limit. A value equal to its float32 is now judged at float32 spacing. - From 131,072 float32 cannot hold every penny, so no penny is identified and the stored value is kept; rounding down then never goes against the claimant. - The Lifetime ISA's 75% and UC company capital are worked in float64 from the stored amounts; company capital is rounded under reg. 6(1). - test_uc_capital_allocation expected exact conservation; each share is now its own nearest-penny amount (1.00 three ways is 0.33 each). - Docstrings: the guard's intended tolerance; no report leaves a holding in the pool. Tests: a model-level property that every programme counts whole-penny savings, shares and Lifetime ISA balances to the penny; widened-input and above-131,072 helper checks; YAML for 16,000.01 of savings under IS, JSA and ESA and a 1,000.04 Lifetime ISA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1974 renamed the share-like capital source from corporate_wealth to share_like_capital. The six sale-expense lists, the three holding valuations (counted_share) and the two holding budgets now name it through HOLDINGS_SOURCE, so shares keep the reg. 49(1)(a) deduction. The sale-list guard now also requires share_like_capital in each list, the differential's original lists rename the sale-expense lists too, and a components-only household counts 1,000 + 90% of 12,000 = 11,800 under UC. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s rule The engine stores lifetime_isa_countable_capital as float32, so 75% of a whole-penny balance that ends in half a penny (75% of 0.26 is 0.195) was read back just below it and rounded the wrong way under UC and HB: 0.26 of LISA and 15,999.81 of savings gave UC capital of 16,000.00, eligible, instead of 16,000.01. valued_person_capital now works a LISA's surrender value out in float64 from the balance and rounds each person's to the penny under the programme's rule, like any other valuation, in all six means tests. The whole-penny property draws any whole-penny balance, with the half-penny cases as examples, and two YAML cases pin the limit case and per-partner rounding. exact_amount's docstring no longer claims that rounding down never goes against the claimant above 131,072: a figure built from a stored value there can be a penny either way. The float32 cast moves inside errstate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
UK hub: adopting this PR to finish it. Its owner session (CLI 8279ead2) stopped on 25 Oct at 00:02Z, after a weekly-limit stop, and can't be reached. Its last plan was to push, refresh the impact from CI and hand the PR to the hub. What the owner left. None of it was pushed. On 27 Oct at 19:50Z the hub took a snapshot of the work; the owner's worktree is untouched.
Next. A Subfleet build commits those edits and merges current main. It also ports #2688's oracle correction (1193614), which this PR needs once main's couple-role change lands. It then reruns the capital, company and property suites and pushes fast-forward to this branch. After that, an independent review of the delta from 9b9ef66 runs, and the PR lands on the usual gates. #2131, #2688 and #1995 follow it. 🤖 Generated with Claude Code |
Reconstruct the baseline surrender value in float64 only when the active formula is the baseline function and no input was supplied for this period and visible branch. Numeric equality with a float32 formula result cannot establish provenance: it can discard a supplied whole penny. Read the active variable from the tax-benefit system, since an existing holder can retain a definition from before a reform. Reuse supplied-input tracking and cover explicit inputs, float32 collisions, replacement and parameter reforms, late inputs, periods and branches. Reuse the existing independent-clone test fixture for the capital property suite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Retain main's claimant and partner role corrections alongside the programme-specific capital valuations and penny rounding. Resolve the supplied-input registry hunk by retaining both the Lifetime ISA entry and main's monthly domestic energy consumption entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port of #2688's 1193614. Model stored-input precision, the raw holdings budget scale, separately rounded share and holding valuations, each owner's company capital and each benefit unit's final capital. Sum the rounded benefit units for the household expectation under UC regulation 6(1). Pin the original CI witness and the holdings-budget precision boundary, while preserving main's explicit claimant and partner roles. Production calculations and comparison tolerances are unchanged by this port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
UK hub: pushed d5c2a57, a fast-forward from 9b9ef66. These are the owner's two unpushed commits plus three from the hub's adoption build:
Validation so far:
🤖 Generated with Claude Code |
Main's ISA fix (feb50e4, merged here in 6467438) added cash_isa to every means test's capital sources. The property file's households had no cash_isa input, so the differential and the fixed Housing Benefit units raised KeyError: 'cash_isa' when they read each source. Households now draw a cash ISA balance. The cash-only property holds savings and a cash ISA, both deposit balances (ADM H1675), and checks each programme counts the two in full, so a source list that drops cash_isa fails it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The float64 recompute called the baseline LISA formula directly, so a reform that only adds a defined_for mask (keeping the baseline formula) still counted the ISA where Core stores the default. A masked 0.26 ISA then added 0.20 to Universal Credit capital, and with 15,999.81 of savings made the claimant ineligible (v7 review, P2-1). Apply the mask the way Core does: where the defined_for variable, mapped to the person, is above zero, keep the float64 value; elsewhere keep the stored value, which is Core's default. New tests cover a mixed masked/counted pair across the six means tests and the UC eligibility case at the limit; both fail on the previous helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core computes a variable's defined_for mask first and, when it applies to nobody, stores the default without running the formula. The exact float64 valuation ran the formula before masking, so under a reform that masks everyone it calculated dependencies Core never needs, and could fail where Core returns zero. It now works out the mask first and skips the formula when nobody is applicable. A regression gives the balance a formula that raises and checks every programme's capital. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Pushed
Local runs, each under a 4 GB RSS cap at
Next: a v9 delta review (GPT-6.1 Sol) reruns v8's nine mask probes and its provenance probe at this head, runs three mutations, and drafts the final body. Merging waits: on 28 October Vahid asked for no automatic agent merging, and the hub holds every merge until that is resolved. 🤖 Generated with Claude Code |
…pital Main's test_isa_balances expected Universal Credit capital to count a stored stocks-and-shares ISA at its full projected value. This branch values share_like_capital, which carries that ISA, less UC's 10% sale-expense rate until the data separate ISAs from shares (see the sale_expenses.sources description), so the merged test failed with £6,218.99 against £6,433.44: £5,800 rather than £6,000 times growth. The test now reads the rate from the parameters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
UK hub: merged main and fixed one test it brought in. Head CI at Why: the test counts £1,000 savings, a £3,000 cash ISA and a £2,000 stocks-and-shares ISA, all projected by the same growth (1.07224 in 2027). This PR values Commits:
Local runs on the merged tree:
A delta review is running. The merge into 🤖 Generated with Claude Code |
Fixes #1960.
Apply the statutory 10% sale-expense deduction and secured debt when valuing capital for Universal Credit, Housing Benefit, Income Support, income-based JSA, income-related ESA and Pension Credit. Savings and cash ISAs remain at face value. The helper floors each encumbered source at nil so negative equity in one source cannot reduce another.
Reproducer:
policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml::UC values a mortgaged holiday home as in ADM H1602,policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml::UC shares valued less sale expenses bring capital within the limit,policyengine_uk/tests/test_capital_valuation_properties.py::test_valuation_matches_the_regulation_and_never_adds_capital,policyengine_uk/tests/policy/baseline/gov/dwp/capital_valuation.yaml::A Lifetime ISA value given as an input is counted as given,policyengine_uk/tests/test_capital_valuation_properties.py::test_lifetime_isa_reformed_value_is_kept_as_storedThe law
The 10% applies to gross value before debt, only where sale incurs expenses; real property always has sale costs (ADM H1604–H1608). Deduct only debt secured on that source (H1615–H1616). Parameters start with each programme's existing capital-source list. Each programme uses the provision in its own instrument, including the later UC and ESA instruments.
What changes
capital.sale_expenses.rate: 0.1, an explicit list of sources, and its owncapital.round_downrule.valued_capitalapplies the deduction before secured debt, with float64 arithmetic.exact_amountrecovers an unambiguous whole penny from float32 storage below £131,072. It preserves other stored amounts. Above that boundary, original pennies can be ambiguous; the result can differ by a penny in either direction. This PR cannot recover arbitrary precision lost before valuation.defined_formask through Core's entity mapping. It keeps the stored result outside the mask. Regressions cover mixed masked/counted people across all six means tests and UC eligibility at the £16,000 capital limit. Commitdbc0c587fcalculates the Lifetime ISA mask before its high-precision recomputation. It runs the formula only when at least one person applies and keeps Core's stored value outside the mask. The regression makeslifetime_isa_balanceraise when a reform masks everyone and checks capital for all six programmes against a run without a Lifetime ISA.cash_isaas well assavings. Its cash-only property checks their sum at face value. Direct source lookup still exposes a source omitted by the oracle as aKeyError; cash ISAs stay outside both the sale-expense and secured-debt mappings.share_like_capitalis the sale-expense source in all six lists;corporate_wealthremains its backing household input. UC company-holding deductions useHOLDINGS_SOURCEconsistently, including pool and reported-capital budgets read throughexact_amount. Property oracles map the renamed source to the backing input.owned_land_secured_debtand deducts all three in every programme's valuation. Each defaults to zero, anduprating_indices.yamllists each once.Which sources take the 10%
share_like_capitalReview responses and integration
errstatedefined_for696ae34ad). Add mixed-person and UC-limit regressions. The v8 follow-up below also preserves Core's all-masked short circuit.cash_isasourceb168dc509). Keep direct lookup and existing tolerances.dbc0c587fevaluates the mask first and runs the formula only when someone applies. The new raising-dependency regression checks all six programmes.dbc0c587f)dbc0c587f: main's newtest_isa_balances.pyexpected a stocks-and-shares ISA at full value in UC capitalfc066bd31expects UC's sale-expense deduction on it: the ISA reaches capital throughshare_like_capital, which UC values less 10% until the data separate ISAs from shares. #2131 then values itemised ISAs without the 10%.646743859merges main at41fa5ddb5. The supplied-input registry retains both this PR's LISA entry and main'smonthly_domestic_energy_consumptionentry.d5c2a57e8ports Add overseas and other real estate as property components, and count UK land once in household land #2688's company-capital conservation oracle correction from1193614a6. The file is byte-identical to that source revision and keeps main's claimant/partner roles. The oracle reflects stored-input precision, holdings-budget scaling, separately rounded valuations and company capital, and the sum of rounded benefit units. The pinned example yields £25.28 + £25.28 = £50.56. The port changes no production code or tolerance. All seven company-owner properties completed successfully in v7's CI; that result supersedes the earlier interrupted local run.5efb62cefmerges main at2d437ebba. Of 3,660 paths, onlypolicyengine_uk/data/uprating_indices.yamlchanged on both sides since41fa5ddb, and the merge commit's combined diff shows no hand-resolved hunk in it. The merged file keeps main's newcash_isa_balanceandstocks_and_shares_isa_balance, drops main's duplicatecash_isaandstocks_and_shares_isaentries, and keeps all three secured-debt inputs. It lists each of its 124 variables once, under 14 distinct indices. The merge keeps every one-sided change: 59 files from this branch and 123 from main.fc066bd31changes onlytest_isa_balances.py. Main's Model the ISA subscription limits, with per-person ISA subscriptions and balances #2712 (issue Model ISA subscription limits and per-person cash and stocks-and-shares ISA subscriptions #2710) added the test; the edit makes it expect UC capital of (1,000 + 3,000 + 2,000 × (1 − rate)) × growth, which is £5,800 × 1.07224 = £6,218.99 in 2027. It reads the rate from the parameters. The test still checks first that the stored household totals grow with savings.41fa5ddbleave the valuation alone. Model the ISA subscription limits, with per-person ISA subscriptions and balances #2712 changes howcash_isaandstocks_and_shares_isaread their values but not which sources the means tests count, and its subscription limits move no balance. Update the economic assumptions to the October 2026 EFO #2717 changes growth rates, not sources or deductions. Compare property allowance routes on only the households with a choice #2732's household subsets slice every stored array and_model_valuesto the kept households, and its tests, which cover the ancestor walk thatsupplied_inputuses, pass here. Make Pension Credit and pension-age HB projections safe under reforms #2092, Limit Housing Benefit childcare to qualifying charges and earnings residuals #2229 and Build the module-release test's systems with automatic GC off #2716 touch no capital code.fc066bd318f2e059623ab30df56985e3605e24d0.Validation
An independent review (v10, Opus 5.5, after the GPT-6.1 Sol lanes reached capacity) ran these checks against
fc066bd318f2e059623ab30df56985e3605e24d0, one file at a time. Every unmutated test passed.test_isa_balances.pytest_wealth_components.pytest_capital_valuation_properties.pytest_lifetime_isa_capital.pytest_household_subset.py(main's #2732)git grep -lfinds namingcash_isa,stocks_and_shares_isa,share_like_capitalorcorporate_wealthlifetime_isa_capital.yamlshare_like_capitalto within 2.8p of penny roundingThe probes cover UC, HB, PC, IS, income-based JSA and income-related ESA in 2025, 2027, 2032 and 2033. They use four kinds of data: stored household ISA totals, person balances, person balances with a Lifetime ISA, and
corporate_wealththat already holds the ISA. Each programme counts savings and cash ISAs in full, takes 10% offshare_like_capital, and counts a Lifetime ISA once, throughvalued_person_capital. No source counts twice.The review ran four scratch mutations on the edited test, made each in place, and restored it byte for byte, checking SHA-256 before and after:
share_like_capitalfailed it at £4,288.96 (£4,000 × growth).share_like_capitalfrom UC's sale-expense sources failed it at £6,433.44 (£6,000 × growth).capital_valuation.yamlfailed 8 cases.One defect already on main, which this PR neither causes nor changes:
cash_isaandstocks_and_shares_isasum person balances throughadds, so after the 2032 projection horizon a dataset that stores only the household totals loses both. In the 2033 probe, UC capital is £1,310.81, the savings alone, where the stored totals give £7,602.69; main gives the same £1,310.81. policyengine-uk-data's Enhanced FRS writes neither total, but Microcosm's UK exports store both, so their runs for 2033 and later lose them. #2740 tracks it: #2712 replaced the totals'upratingattribute withadds.The review ran model commands one at a time under the 4 GB / 1,500-second cap, and mutations under the 2 GB cap. It reused the adoption environment read-only, with this checkout on PYTHONPATH. It ran no microsimulation over a survey dataset and loaded none.
At 2026-10-29T08:16:41Z,
gh pr checks 1969 -R PolicyEngine/policyengine-ukreported 17 passed and 2 failed forfc066bd318f2e059623ab30df56985e3605e24d0(exit 1). All six Python shards and Aggregate impact passed. Test / YAML passed all 5,266 cases, but itspolicyengine-coreprocess had not exited when the job reached its 45-minute limit, so GitHub cancelled the job. Test / Result then failed on the cancelled YAML result. Every YAML job the review checked takes 11.8 to 15.0 minutes to exit after its summary, main's merge queue included. This run's tests took 37 minutes, which left 8. Re-running the failed jobs should clear both checks.Impact on the certified data
The aggregate-impact comment, updated at 2026-10-29T07:46:28Z, compares main
2d437ebbawith0ab53939232733dffcefc96e3477f6d3a08ebd4f. That commit mergesfc066bd31into2d437ebba; the review checked its parents, and the workflow run reportsfc066bd31as its head. Both runs useenhanced_frs_2024_25.h5(policyengine-uk-data 1.58.1). The job passed: no check broke, one fails on both sides, and none got fixed.† The report rebuilds these totals without the suppressed Disabled Students' Allowance figure.
Lower assessed capital raises each of the six benefits whose capital the PR values, or leaves it unchanged, in every year. The report shows 0.0% of people losing over £1 in every year, and every base-run decile gains or holds. The moves the other way follow from higher awards:
council_tax_reduction/_legacy.py:50-53), so a larger award lowers it.universal_credit_pre_benefit_capabove nil (tax_free_childcare_program_eligible.py;disqualifying_benefits.yaml).tv_licence_free_licence_share.py).attends_private_school.py).The bundled share-like-capital data still limits the legal reading of any aggregate result.
Coordination
share_like_capitalin programme lists and retaincorporate_wealthonly as the backing input or an explanation of it.1193614a6).axiom: TheAxiomFoundation/rulespec-uk#395 queued
🤖 Generated with Claude Code