Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4ac9d16
Lock policyengine-uk 2.165.0 for the company car inputs
juaristi22 Oct 30, 2026
7b60be2
Add the company cars stage runtime and the typed HMRC company car facts
juaristi22 Oct 30, 2026
03f18ed
Carry each person's company car from the FRS job tab
juaristi22 Oct 30, 2026
404204e
Count the company cars stage's invariant breaks in its receipt
juaristi22 Oct 30, 2026
25dc483
Register the company cars gate, operation kinds and exports
juaristi22 Oct 30, 2026
5a42a3f
Declare the company cars stage and wire it into the graph
juaristi22 Oct 30, 2026
dee8d19
Read HMRC's employment income as pay plus the company car benefits
juaristi22 Oct 30, 2026
81fc2c5
Merge #1421's head (c0ed9a751) into the company cars branch
juaristi22 Oct 30, 2026
73fb479
Teach the local metric stubs benefits_in_kind and the stage order com…
juaristi22 Oct 30, 2026
63acef4
Merge main after #1421 into the company cars branch
juaristi22 Oct 30, 2026
957130b
Draw company car list prices from cells of 3 WAS households or more
juaristi22 Oct 30, 2026
21e3623
Type HMRC's company car facts from the Chronicle package's rows
juaristi22 Oct 30, 2026
424b898
Compute HMRC's employment income in the annual measures test
juaristi22 Oct 31, 2026
d9bf936
Price SPI company cars again on the engine, and keep pension deductio…
juaristi22 Oct 31, 2026
3b70999
Re-pin the UK feed onto the merge of chronicle#399 and vendor HMRC's …
juaristi22 Oct 31, 2026
57dc7ec
Count the company cars stage in the roster tests, and load the vendor…
juaristi22 Oct 31, 2026
574badc
Let a calendar-year window take each year from its own table
juaristi22 Oct 31, 2026
e67e76c
Bind the 19 OBR windows across the March and October EFOs
juaristi22 Oct 31, 2026
7491ecf
Merge #1422's head into the company cars branch
juaristi22 Oct 31, 2026
eb43bbb
Address the independent review of the company cars stage
juaristi22 Oct 31, 2026
3c26a96
Merge #1422's review round into the company cars branch
juaristi22 Oct 31, 2026
1fb4a9e
Merge #1422's DfE test fix into the company cars branch
juaristi22 Oct 31, 2026
9a65657
Regenerate the UK surfaces on 08962f1 after the merges of #1422
juaristi22 Oct 31, 2026
223402e
Merge #1422's re-review round into the company cars branch
juaristi22 Oct 31, 2026
4d7356e
Regenerate the surfaces #1422's re-review round moves, on 08962f1
juaristi22 Oct 31, 2026
9a3ef50
Merge #1422's payload comparator test fix into the company cars branch
juaristi22 Oct 31, 2026
f1cf6ba
Merge #1422's local parity receipt into the company cars branch
juaristi22 Oct 31, 2026
acbf4c0
Merge #1422's H2 fixture regeneration into the company cars branch
juaristi22 Oct 31, 2026
9ea662f
Merge #1422's third-review fixes into the company cars branch
juaristi22 Nov 1, 2026
40968ff
State the electric range rule by the car's CO2
juaristi22 Nov 1, 2026
4d4c1a6
Merge #1422's fourth-review fixes into the company cars branch
juaristi22 Nov 1, 2026
23aadd8
Merge #1422's fifth-review fixes into the company cars branch
juaristi22 Nov 1, 2026
14dc815
Merge main (11c1f4e69, with #1422) into the company cars branch
juaristi22 Nov 1, 2026
083ee9f
Address the second review of the company cars stage
juaristi22 Nov 1, 2026
51259e7
Regenerate the surfaces the second review's fixes move
juaristi22 Nov 1, 2026
144d738
Spell the test frames' employment status as the engine's enum does
juaristi22 Nov 1, 2026
a22e33d
Address the third review of the company cars stage
juaristi22 Nov 1, 2026
de41aba
Regenerate the coverage manifest and H2 fixture for the renamed fuel …
juaristi22 Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/uk-company-cars-316.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK spine writes company cars (PolicyEngine/uk-autumn-budget-dashboard-2026#316). A new stage, `company_cars`, sets six of policyengine-uk 2.165.0's company car inputs for each employee the FRS job record gives a company car (`EXPBEN01`), through four carriers the root stage now writes from the job tab: the list price, drawn within the respondent's CARVAL band from WAS round-8 company cars' prices grown by the engine's CPI index; the fuel (FUELTYP, and HMRC Table 2C's shares among the unknown fuels, without electricity where the holder reports private fuel); the CO2 figure at HMRC Table 2A's shares among cars that emit CO2, hybrids first into 1 to 50 g/km, which takes a 50-mile electric range; private fuel (EXPBEN03); and capital contributions (CARAMT). The stage runs right after the SPI income stage, so every later stage reads the tape rows' pay without the car benefits (María's ruling of 31 October 2026). A row drawn from the SPI tape keeps its twin's car only where its drawn EPB is positive, and its `employment_income`, the tape's PAY + EPB + TAXTERM, gives up the engine's car and fuel benefits, capped at EPB (María's ruling of 30 October 2026) within the pay its employee pension contribution leaves, so `salary_sacrifice` never meets a contribution above pay; where the two do not fit together the fuel goes first, and a carved row's UC gainful self-employment follows its carved pay. The channel's other rows keep their twin's pay and car. `obr.ni_employer` binds Class 1 employer NICs (`ni_class_1_employer`), since OBR's line leaves Class 1A out, and the employment income count rows count pay plus the car benefits, as the amount rows do. Three company car inputs stay signed at the engine's default: availability, payments for private use and the 2020 registration flag. No HMRC company car fact is a calibration target, and comparing the calibrated file with HMRC's tables is a manual step for now; `uk_stage_company_cars_invariants` blocks a release on any invariant break. The stage fits no model and declares no fit-weight records, so the release-cut weights audit does not read it as a fitting stage that recorded none.
5 changes: 5 additions & 0 deletions changelog.d/uk-feed-repin-08962f1.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The UK Chronicle feed is re-pinned to 08962f1, the merge of PolicyEngine/chronicle#399 on top of PolicyEngine/chronicle#396's merge (1,512,256 rows; the consumer-fact schema is unchanged). It brings HMRC's benefits in kind statistics of July 2026 (544 facts) and the UK facts of PolicyEngine/chronicle#395 (1,076). It also keeps one OBR EFO number per line and year (PolicyEngine/chronicle#397): the March 2026 edition drops the 427 record sets the October 2026 edition also publishes. A new vendored resource, `hmrc_benefits_in_kind_facts.json`, carries the 96 2024-25 rows the company cars stage reads. The other vendored resources, and the DESNZ constituency resource, carry the same rows under the new feed identity. `obr.winter_fuel_allowance` now reads the October edition's FY2025-26 outturn, 0.02% above the March projection it read before.

No EFO edition now carries both years of a calendar-2025 window, so the 19 OBR targets that window FY2024-25 and FY2025-26 declare a new selector key, `source_table_by_opening_year`, as do the three council tax nation rows of PolicyEngine/microcosm#1422 and the signed-out fuel duties row (23 in all). It takes three twelfths of the March edition's FY2024-25 outturn and nine twelfths of the October edition's FY2025-26 outturn (María's ruling of 31 October 2026). Fifteen of the 19 move by under 1%. The four larger moves are domestic rates (+3.2%), Pension Credit (+2.3%), Jobseeker's Allowance (−2.5%) and SDLT (−1.2%); income tax moves −0.5% and Universal Credit +0.7%. Three report-only diagnostics pinned the March edition's FY2025-26 forecasts, which the feed no longer carries: the OBR's capital gains tax receipts, State Pension spending and total NICs. They now pin the October edition's FY2025-26 outturns, and none of them is in the fit.

The national membership also catches up with policyengine-uk 2.164.1's economic assumptions (the October 2026 EFO), which PolicyEngine/microcosm#1421 locked after PolicyEngine/microcosm#1420 had generated the membership. The eight SPI Table 3.10 self-employment bands move −0.55% (OBR mixed income per head), and the thirteen SPI dividend bands move by under 0.001% (GDP per head). The national compile-parity receipt, which builds check against, already carried their new values.
2 changes: 1 addition & 1 deletion docs/concept-coverage/policyengine-uk.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Engine version `2.165.1`; concept schema `5a55669d0447`. Generated by `tools/ref
| `fact:person.legal_marital_status` | policyengine-uk derives marital status from benefit-unit composition; marital_status and is_married are formula-owned. |
| `fact:person.partner_person_id` | Partnerships reach policyengine-uk only through benefit-unit membership, a structure the bundle must already carry (the adapter builds no units); is_benunit_head and is_married are formula-owned. |
| `fact:household.reference_person_id` | is_household_head is formula-owned (the oldest member). The UK build overrides it with the FRS household reference person (frs_spine.py), an override the loader accepts, but it is not an input, so the mapping does not target it. Every housing input is household-level, so nothing is allocated to the reference person. |
| `fact:person.liquid_financial_assets` | policyengine-uk holds financial wealth on the household: savings ('Household liquid savings'), corporate_wealth ('Wealth held in corporations directly or through investment funds'), gross_financial_wealth and net_financial_wealth are household inputs, and no transform puts a person amount on a household input. Its person-level GBP stock inputs are student_loan_balance, a debt; car_list_price, the price vehicle excise duty's expensive-car supplement tests; and lifetime_isa_balance ('Current value of the person's Lifetime ISAs, cash and stocks and shares together'), one savings wrapper, which the engine documents as already inside gross_financial_wealth and net_financial_wealth. Since policyengine-uk 2.130.0 three more describe a company the person owns, for Universal Credit's regulation 77 (owned_company_capital, owned_company_holding_value and owned_company_trade_assets); every one defaults to no such company, and the build sets none. Since policyengine-uk 2.164.0 cash_isa_balance and stocks_and_shares_isa_balance hold the person's ISAs, and the household cash_isa and stocks_and_shares_isa sum them; the isa_subscriptions stage splits the WAS household totals into them (microcosm#1415), a split of one wrapper's balance, not of liquid financial assets. savings and share_like_capital are two of Universal Credit's capital sources (gov.dwp.universal_credit.means_test.capital.sources); since policyengine-uk 2.147.0 share_like_capital is corporate_wealth unless its components, the household inputs directly_held_shares and unit_and_investment_trusts, add up to more; the WAS stage writes both on its corporate_wealth less the stocks-and-shares ISA, so they and the ISA sum to it (microcosm#1095). Universal Credit's one person-level source is lifetime_isa_countable_capital, the Lifetime ISA at its surrender value (capital.person_sources). uc_reported_capital (benefit unit, default -1) is Universal Credit capital; since policyengine-uk 2.136.1 a value of zero or more set directly is the unit's complete countable capital, in place of every source, property included. benunit_reported_capital, a benefit-unit input ('Savings and investments of the benefit unit's adults (the claimant and any partner) as recorded'), replaces the financial sources only: the household pool it otherwise sums from the household sources, net of what other benefit units report or override, and apportions by claimant and partner count, and the person-level sources of the unit's claimant and partner. Property is valued separately (uc_property_capital) and shared across every claimant and partner in the household. Feeding either would be a modelling choice for a UK build, not a mapping of this concept. |
| `fact:person.liquid_financial_assets` | policyengine-uk holds financial wealth on the household: savings ('Household liquid savings'), corporate_wealth ('Wealth held in corporations directly or through investment funds'), gross_financial_wealth and net_financial_wealth are household inputs, and no transform puts a person amount on a household input. Its person-level GBP stock inputs are student_loan_balance, a debt; car_list_price, the price vehicle excise duty's expensive-car supplement tests; and lifetime_isa_balance ('Current value of the person's Lifetime ISAs, cash and stocks and shares together'), one savings wrapper, which the engine documents as already inside gross_financial_wealth and net_financial_wealth. Since policyengine-uk 2.130.0 three more describe a company the person owns, for Universal Credit's regulation 77 (owned_company_capital, owned_company_holding_value and owned_company_trade_assets); every one defaults to no such company, and the build sets none. Since policyengine-uk 2.164.0 cash_isa_balance and stocks_and_shares_isa_balance hold the person's ISAs, and the household cash_isa and stocks_and_shares_isa sum them; the isa_subscriptions stage splits the WAS household totals into them (microcosm#1415), a split of one wrapper's balance, not of liquid financial assets. Since policyengine-uk 2.165.0 company_car_list_price and company_car_capital_contributions describe a car the person's employer makes available, whose benefit is taxed as employment income (ITEPA 2003 ss. 121 and 132); the company_cars stage writes them from the FRS job table, and neither is the person's asset. savings and share_like_capital are two of Universal Credit's capital sources (gov.dwp.universal_credit.means_test.capital.sources); since policyengine-uk 2.147.0 share_like_capital is corporate_wealth unless its components, the household inputs directly_held_shares and unit_and_investment_trusts, add up to more; the WAS stage writes both on its corporate_wealth less the stocks-and-shares ISA, so they and the ISA sum to it (microcosm#1095). Universal Credit's one person-level source is lifetime_isa_countable_capital, the Lifetime ISA at its surrender value (capital.person_sources). uc_reported_capital (benefit unit, default -1) is Universal Credit capital; since policyengine-uk 2.136.1 a value of zero or more set directly is the unit's complete countable capital, in place of every source, property included. benunit_reported_capital, a benefit-unit input ('Savings and investments of the benefit unit's adults (the claimant and any partner) as recorded'), replaces the financial sources only: the household pool it otherwise sums from the household sources, net of what other benefit units report or override, and apportions by claimant and partner count, and the person-level sources of the unit's claimant and partner. Property is valued separately (uc_property_capital) and shared across every claimant and partner in the household. Feeding either would be a modelling choice for a UK build, not a mapping of this concept. |
| `fact:person.public_pension_income` | The State Pension is computed from state_pension_reported, which is formula-owned: the loader accepts it as an override, but it is not an input. |
| `fact:household.source_household_id` | Original donor household lineage is build provenance and weight diagnostic support, not a policyengine-uk rules input. |

Expand Down
49 changes: 49 additions & 0 deletions docs/uk-chronicle-feed-repin.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,52 @@ from the same `53815b2` artifact: `hmrc_isa_statistics_facts.json`, the 1,074 ro
statistics the ISA subscriptions stage and the Lifetime ISA anchor read. None is a calibration
target, so no reference moves for it. That pull request first pinned #392's head (`e56af9a`) and
then its merge (`0b721a4`), and took `53815b2` when PR C merged first.

The `08962f1` re-pin (PolicyEngine/microcosm#1430, the merge of PolicyEngine/chronicle#399 on top
of the `7d5d627` merge of PolicyEngine/chronicle#396) brought HMRC's benefits in kind statistics of
July 2026 (544 facts) and the UK facts of PolicyEngine/chronicle#395 (1,076). It also carries
PolicyEngine/chronicle#397, María's rule of 30 October that of two EFO editions' numbers for one
line and year Chronicle keeps the later, so the March 2026 edition drops the 427 record sets the
October 2026 edition also publishes (1,512,256 rows; the schema digest is unchanged). The merge
commit's tree is the pull request head's (`ac9d7bb`), so the artifact was built from that head's
bundle and carries the merge commit's identity.

A new vendored resource, `hmrc_benefits_in_kind_facts.json`, carries the 96 2024-25 rows the
company cars stage reads. The other vendored resources, and the constituency energy resource
rebuilt beside them, carry the same rows under the new feed identity.

After #397 no EFO edition carries both years of a calendar-2025 window: March keeps each line's
FY2024-25 outturn and October carries FY2025-26 on. The 19 OBR rows that window the two years
declare `source_table_by_opening_year`, which takes each year from the table that carries it
(María's ruling of 2026-10-31; `docs/uk-income-anchors-280.md`), as do the three council tax nation
rows of PolicyEngine/microcosm#1422 and the fuel duties row, which is signed out of the references:
23 in all. The 19's values move with October's outturns: fifteen by under 1%, with domestic rates +3.2%, Pension Credit +2.3%, Jobseeker's
Allowance −2.5% and SDLT −1.2%. `obr.winter_fuel_allowance` drops its pin to March's expenditure
table and reads October's FY2025-26 outturn (+0.02%). Three report-only diagnostics pinned March's
FY2025-26 forecasts by fact key: `obr.capital_gains_tax`, `obr.state_pension` and the `obr.ni`
total. They now pin October's outturns (`required_assertion: observation`). The test feed
fixture's three captured March FY2025-26 rows (income tax, incapacity benefits and capital gains
tax) give way to October's.

The national membership also catches up with policyengine-uk 2.164.1's October-EFO economic
assumptions. PolicyEngine/microcosm#1421 locked them after PolicyEngine/microcosm#1420 had
generated the membership, so the 21 SPI rows grown by an OBR per-head index still carried the
old factors there: the eight Table 3.10 self-employment bands move −0.55% (mixed income per
head), and the thirteen dividend bands by under 0.001% (GDP per head). The national compile-parity
receipt already carried their new values. No other national value moves. The receipt moves the 19
windowed values and gains two drift rows, domestic rates and Winter Fuel, which had equalled the
frozen incumbent. The OBR rationales of the parity tool name the two editions, and Winter Fuel has
a rationale of its own.

On the local surface the reference file and the compile-parity receipt are byte-identical. The
membership moves only its feed label and the 1,263 DESNZ keys, and the census restates the pin.
Both surfaces were regenerated from cuts of the pinned artifact, as for `200bf6d` (national
940,989 rows, local 885,543).

The national register version moves with the OBR values (the SPI rows already compiled at their
new values), so the uk-candidate-eval scoring register is re-frozen before the next national
solve. The 23 maps name
EFO editions, so a later EFO moves them: once Chronicle keeps a newer edition's FY2025-26,
October's number leaves the feed and the windows refuse until their maps name the new table. The
high-value home stock still names `735820c`: its inputs are the same on `08962f1` (the feed-gated
fingerprint check passes), so it was not rebuilt.
Loading
Loading