Repository navigation
Conversation
…r one person business Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Until 27 November 2018 any Chapter 8 or 9 ITEPA employed earnings from the company excluded the owner; from 28 November 2018 Chapters 8-10 exclude only when derived from main-employment activities. Replace the single boolean with the ITEPA chapter and a main-employment flag, and parameterise the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Company losses count as nil self-employed earnings (reg 57(2)). - Company earnings count towards the benefit cap earnings exemption (reg 82). - In multi-benunit households, disregarded holdings leave the household capital pool before it is shared; a reporting benunit's holdings come off its own reported capital. Both floored at zero. - Main employment in the company's trade counts as engagement in it for the 77(3)(a) trade-asset disregard. - Replace bitwise NOT on a Python bool in the 77(5) exclusion. - Document dating, trade assets net of secured liabilities, NI references, and the dividend double count until dividends leave UC unearned income. - Strengthen the Hypothesis strategies, add a conservation property, and make the Axiom test an explicit golden-case mirror asserting modelled earnings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve uc_assessable_capital onto main's claimant-based allocation: reg 77 holdings leave the household pool before it is shared among unreported claimants; company capital and reported-path holdings count only for the claimant and partner. 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 19323628.
What I checked:
- The law. Your reg 77 quote matches legislation.gov.uk word for word, including 77(3)(a) "wholly and exclusively". That wording is stricter than the Sch 10 para 7 business-assets disregard ("wholly or mainly"), so following the regulation over ADM H1880 is right. The dating of 77(5) (Chapters 8/9 until 27.11.2018, then 8/9/10 with the main-employment condition) is right too.
- Tests at the head. Properties plus Axiom parity: 9 passed. UC YAML directory: 245 passed. CI is green.
- A probe at the head. A trading-company owner whose main employment is the company, with £6,000 of pay and a £20,000 income share, gets
uc_company_self_employed_earnings£20,000,uc_mif_appliestrue anduc_earned_income£26,000. That is 77(3)(b) and (4) working as intended. - Mergeability. It does not merge into current main (
b5b09231; the branch is 249 commits behind). There are conflicts inis_benefit_cap_exempt_earnings.py,uc_mif_applies.pyanduc_mif_capped_earned_income.py. It merges cleanly with #1969, #1974 and #2131.
Findings:
-
Blocking.
variables/gov/dwp/universal_credit/income/income_floor/uc_mif_capped_earned_income.py:20. Main has deleted this file. #1949 replaced it withuc_individual_earned_income_before_mifanduc_individual_earned_income, which use a net floor, the reg 62(3) couple threshold and a per-person tax/NI slice. If you resolve the conflict by keeping main's side, the company earnings are orphaned: nothing reads them, and reg 77(3)(b) silently does nothing. The body's line that "#1949'suc_individual_earned_incomereads this variable" is no longer true. Fix:- add
uc_company_self_employed_earningsnext toself_employedinuc_individual_earned_income_before_mif; - check it doesn't pick up personal income tax in
uc_income_tax_on_earnings, since reg 57 step 3 deducts only tax the person pays; - re-derive invariants 4 and 5 against the net floor and the couple rule.
- add
-
Blocking.
uc_mif_applies.py:25-30andis_benefit_cap_exempt_earnings.py:32. Main now gates both onis_uc_assessed_claimant(reg 62(1), and reg 82(1)(a)'s "claimant's earned income"). When you rebase, ANDuc_company_gainful_self_employmentwithclaimant, and multiply the company term in the benefit-cap sum byclaimant. Otherwise a dependant owner-manager gets the floor or lifts the cap. -
Blocking (interaction with #1969, which merges cleanly so nothing forces the fix).
uc_assessable_capital.py:60-77andhousehold_uc_unreported_company_holdings.py:22-23. #1969 counts the holding at 90% insidecorporate_wealth(ordirectly_held_sharesafter #2131), but this PR subtracts it at 100%.- On #1969 merged with this branch: savings £5,000,
corporate_wealth£10,000, all of it the owner's holding, givesuc_assessable_capital£4,000. It should be £5,000. - #1969 will almost certainly land first, so this PR owns the fix, together with finding 4 (one change; see there).
- Add a YAML case pinning the £5,000.
- On #1969 merged with this branch: savings £5,000,
-
Should fix. Same lines. A holding that isn't in any capital source eats other capital. At the head: savings £10,000, no
corporate_wealth, holding £10,000 gives £0. The body says "a holding cannot reduce other capital", but the only floor is at zero on the total. Fix for 3 and 4 together: in both places, subtractmin(holding, share-like capital) × (1 − sale_expenses.rate). Share-like capital iscorporate_wealthbefore #2131 anddirectly_held_shares + unitemised_corporate_wealthafter it. Add the £10,000-savings case as a test. -
Should fix (body). Several statements are stale against current main and should be refreshed after the rebase:
- "Bit-identical to main" was measured at
00fb451d. - "Not modelled: … the couple threshold rule (62(3)) and net thresholds (62(4))" no longer holds: main has both. Only 62(1)(b) remains.
- The impact table needs re-running on the rebased head.
- "Bit-identical to main" was measured at
-
Nit (body, disclosure). There are no record ids or weights in the body, but the "What this means for #1948" section gives dividend totals for a cohort it describes as coming from fewer than ten FRS households. An aggregate that small is close to record-level. I'd keep the conclusion (they aren't owner-managers; it's an imputation artefact) and drop the small-cell totals and row counts.
-
Nit.
uc_company_capital.py:36-38. Treating "main employment is the trade" as "engaged in the trade" for 77(3)(a) is sensible, but it's an inference, not the text. A one-line comment saying so would help the next reader.
Fixes #1964. Part of #1948.
Summary
This PR models Universal Credit regulation 77, "Company analogous to a partnership or one person business" (UC Regs 2013; UC Regs (NI) 2016, same number). It applies to a person who stands in a position analogous to a sole owner or partner of a company carrying on a trade or a property business. For that person:
Every new input defaults to "no such company", so no dataset changes. On the Enhanced FRS the branch is bit-identical to main (below).
#1948 asked whether its six-figure-dividend UC units are owner-managers under reg 77. The survey says they are not, and the dividends are an imputation artefact. That fix is PolicyEngine/policyengine-uk-data#498; see "What this means for #1948".
The law
UC Regs 2013 reg 77, verbatim from legislation.gov.uk (revised text valid 2026-07-16, no outstanding effects):
Until 27 November 2018, 77(5) read "...Chapter 8 ... or Chapter 9 ... of Part 2 of ITEPA", with no Chapter 10 and no main-employment condition (point-in-time texts 2013-04-29 and 2014-11-26; SI 2018/1129 reg 3(5)). The model dates this with two parameters.
The regulation is mandatory. DWP guidance treats "analogous" as a question of fact:
A shareholder in a widely held company is an investor (ADM H4362-H4364, H1877-H1879, citing R(IS) 8/92 and 13/93 as reported in CA v Hastings BC [2022] UKUT 57 (AAC)). The only Upper Tribunal decision found applying UC reg 77, SSWP v Faghy (UA-2026-000266-USTA, 27 August 2026), accepted the Secretary of State's ground that a property business gets no 77(3)(a) disregard. It was an unopposed paper decision, so this is not the tribunal's own reasoned construction. This model does the same.
Where DWP guidance and the regulation differ, the model follows the regulation.
uc_mif_capped_earned_incomealready does.owned_company_capitalis documented.Company income is before corporation tax. Reg 57(2) step 3 deducts only income tax and NICs paid by the person. Neither the regulations nor ADM H1/H3/H4/H5 provide for deducting corporation tax, so
owned_company_income_shareis documented as the reg-57 amount before it.What changes
Inputs, all under
variables/input/owned_company/, per person, each defaulting to no company:stands_as_sole_owner_or_partner_of_companyowned_company_carries_on_tradeowned_company_carries_on_property_businessowned_company_intermediary_earnings_chapter(enum: none, or ITEPA Part 2 Chapter 8/9/10)owned_company_intermediary_earnings_from_main_employmentowned_company_income_shareowned_company_is_main_employmentis_engaged_in_owned_company_tradeowned_company_capitalowned_company_trade_assetsowned_company_holding_valueUC variables (
gov/dwp/universal_credit/company/):uc_company_intermediary_exclusion_applies(77(5), dated)uc_company_owner_treatment_applies(77(1), (5))uc_company_self_employed_earnings(77(3)(b))uc_company_gainful_self_employment(77(3)(c))uc_company_capital(77(2), (3)(a), clamped at zero)uc_company_holding_disregard(77(2))Parameters:
gov.dwp.universal_credit.company_owner.intermediary_exclusion.{chapters, requires_main_employment}.Wiring:
uc_mif_capped_earned_incomeadds the company earnings to the person's earned income. Deduct only each person's own tax and NI on earnings from UC earned income #1949'suc_individual_earned_incomereads this variable, so either version of the earned-income formula picks them up.uc_mif_appliesadds the 77(3)(c) route, still switched off in a start-up period (reg 62(5)).is_benefit_cap_exempt_earningsadds the company earnings to the earnings test. Reg 82(4) excludes only income deemed by the floor, so the floor itself is not added.uc_assessable_capitaladds the company capital of the claimant and partner (is_uc_claimant, following main's rule that a dependant's capital is not the claimant's) and removes disregarded holdings.household_uc_unreported_company_holdings), so no unit counts any part of a disregarded holding.uc_reported_capital.uc_assessable_capitalfor households with a UC award. This is intended: those schemes take UC's capital figure.Dividends are left alone. A shareholder's dividends are not UC unearned income under reg 66(1) at any capital level; #1950 takes them out of
uc_unearned_income. Before it merged, main still counted dividends as unearned income when tariff income did not apply. So a household calculation that sets these inputs and also enters that person's dividends would count the company's income twice;owned_company_income_share's documentation says so. #1950 has now merged (main is merged into this branch), so on current main the double count cannot arise.Invariants (stated and tested)
test_uc_company_owner_properties.pychecks these with Hypothesis on generated benefit units: singles and couples, 0-2 children, pay around the floor, self-employment profit, small savings andcorporate_wealth, start-up status, and company facts including losses.universal_credit,uc_assessable_capital,uc_earned_income,uc_mif_capped_earned_incomeoruc_mif_applies.uc_assessable_capital= max(0, capital without the rule − Σ owners' holdings) + Σ owners' max(0, company capital − trade assets if trade and engaged or main employment).How hard the properties are exercised. There are 10 examples per property, each with 1-4 benefit units. The strategies make most adults owners and keep capital mostly under the limit. In 1,759 sampled adults:
98% of units stay under £16,000.
Mutation check. I reinstated each defect the review found, one at a time:
test_uc_company_owner_axiom_parity.pyis a golden-case mirror of the independent Axiom encoding, TheAxiomFoundation/rulespec-ukuk/regulations/uksi/2013/376/77.yaml. It copies the four cases of its77.test.yaml(commit 0644db8) and maps Axiom's inputs one to one (table below). It checks:It does not run Axiom, so it will not catch drift in that encoding; rulespec-uk#394 covers that side.
Tests
tests/policy/.../universal_credit/company/uc_company_analogous_business.yaml:uc_income_reduction.19323628(main merged in): the UC YAML directory, the Lifetime ISA and CTR suites (305 passed), and the capital tests (allocation, Lifetime ISA, stock periods, mixed-age couples) plus these properties (12 passed). Before the merge: full policy YAML suite 1,308 passed; full pytest 328 passed, 45 skipped. CI runs the full suite.Enhanced FRS impact
Data and runs. The dataset is a private copy of
enhanced_frs_2024_25.h5(sha256e433e532…). Every number below is from a real microsimulation run with stored weights, 2025-2030. Both runs are on clean heads: main00fb451d, branch19323628(main merged in).Main vs this branch: bit-identical. All 21 arrays compared (19 benefit-unit, 2 household) are identical in every year 2025-2030. They include
universal_credit,uc_assessable_capital,uc_earned_income,uc_unearned_income,uc_tariff_income,is_uc_eligible, the income components andhousehold_net_income. The dataset has no owner-manager inputs, so the rule is inert.Preview with the FRS's own director fields (indicative only; not a proposed release). This illustrates what a data build that fills the inputs would do. The FRS 2024-25 job table asks directors of limited companies what share they own (
DIRPERC) and what dividends they took (DIVIDEND). For this run only:stands_as_sole_owner_or_partner_of_companyandowned_company_carries_on_tradeare true for directors owning 50% or more. The 50% line is an assumption drawn from the ADM examples, not the law. Both dataset copies of each FRS household get the inputs: the original and its capital-gains clone.DIVIDENDis a weekly net amount. It equals the adult table'sDIVIDNETwhere both exist, despite the question asking about the last 12 months.Capital inputs stay zero, since the FRS has no company balance sheet. Result, against the branch without inputs:
In 2026, 6.4k benefit units lose UC and none gains. Company earnings total £9.5bn.
Filling the inputs is follow-up data work in policyengine-uk-data. Director shares and dividends are in the FRS job table. Its
DIVIDENDis stored as a weekly net amount, and whether director dividends also appear in other FRS income fields has to be checked first.What this means for #1948
The 19 benefit-unit rows behind #1948 (UC units with more than £50,000 of dividends in 2026) are 15 FRS-half rows and 4 SPI-donor rows. The 15 come from fewer than ten FRS households, each appearing twice because the capital-gains imputation stacks a copy of every FRS household. I linked them to the raw FRS 2024-25 (aggregates only):
dividend_incomeThe cohort's FRS households report no dividends from a company they direct. So they are not owner-managers. Their dividends come from policyengine-uk-data, which has two defects:
impute_incomereplaces every FRS respondent's dividends with a draw from an SPI model predicting from age, gender and region alone;frs.pykeys the survey's own dividends on row position, so almost none survive.PolicyEngine/policyengine-uk-data#498 fixes both.
#1948 also asked how #1837 changes the picture. Real runs of the same dataset on main as it was then (
44240bd8, before #1950 merged) follow main's cohort (UC and over £50,000 of dividends: 30.9k units, 19 records):#1837 removes the cohort's UC only because, without
corporate_wealth, tariff income stops applying, and their £4.7bn of dividends then count as unearned income. Reg 66 does not allow that. With dividends treated as the law requires (#1950), nothing in the rules stops these units, whether or not #1837 lands. The fix is in the data.Not modelled here (tracked separately)
Axiom
axiom: uk:regulations/uksi/2013/376/77 encoded-correct for the law in force from 28.11.2018 (rulespec-uk
77.test.yaml, 4 cases, mirrored bytest_uc_company_owner_axiom_parity.py) | TheAxiomFoundation/rulespec-uk#394 queuedThe queued issue covers the module's two gaps:
Axiom to policyengine-uk mapping (for rulespec-uk#394 and axiom-oracles)
uk:regulations/uksi/2013/376/77person_stands_in_position_analogous_to_sole_owner_or_partner_in_relation_to_companystands_as_sole_owner_or_partner_of_companycompany_carries_on_tradeowned_company_carries_on_tradecompany_carries_on_property_business_within_meaning_of_corporation_tax_act_2009_section_204owned_company_carries_on_property_businessperson_derives_company_income_that_is_employed_earnings_by_itepa_part_2_chapter_8/_9/_10owned_company_intermediary_earnings_chapter(enum)intermediary_employed_earnings_derived_from_person_main_employment_activitiesowned_company_intermediary_earnings_from_main_employmentcompany_capital_value_or_person_share_valueowned_company_capitalcompany_trade_asset_value_or_person_share_used_wholly_and_exclusively_for_tradeowned_company_trade_assetsperson_engaged_in_activities_in_course_of_company_tradeis_engaged_in_owned_company_tradeperson_holding_value_in_companyowned_company_holding_valuecompany_income_or_person_share_calculated_as_self_employed_earnings_under_regulation_57(monthly)owned_company_income_share(annual)person_employed_earnings_as_director_or_employee_of_company(monthly)employment_income(annual)person_activities_in_course_of_company_trade_are_main_employmentowned_company_is_main_employmentcompany_intermediary_employed_earnings_main_employment_exclusion_appliesuc_company_intermediary_exclusion_applies(dated as in rulespec-uk#394)company_analogous_owner_or_partner_treatment_appliesuc_company_owner_treatment_appliesperson_capital_treated_as_possessed_from_companyuc_company_capitalperson_company_holding_disregarded_from_capitaluc_company_holding_disregardcompany_income_treated_as_person_self_employed_earningsuc_company_self_employed_earningsperson_treated_as_gainfully_self_employed_for_company_tradeuc_company_gainful_self_employmentminimum_income_floor_applies_due_to_company_tradeuc_mif_applies(which also applies reg 62(5))Provenance
Law texts, ADM extracts, case-law notes, the Axiom audit and all impact scripts and outputs are in
~/reviews/uc-dividends-1948-2026-09-30/:law/,axiom/,impact/anddiag/. They are local and contain aggregates only.🤖 Generated with Claude Code