Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/1301-uk-dense-signoff-2026-11-03.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sign dense build 1's gate-only failures for the local line (microcosm#1301, attempt uk-local-candidate-f100-s42-20261102T182958Z-78667c3a): 4 national target-fit rows, 11 local target-fit cells and 0 areas below the support floor, approved 2026-11-03; 13 entries that build 2 would fail are retired. Every signed row stays bound in the solve, each entry suppresses only the local line's release fence, and a build in which a signed row passes fails its entry as stale.
1 change: 1 addition & 0 deletions changelog.d/1301-uk-dense-signoff-2026-11-04.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sign dense build 1's gate-only failures for the local line (microcosm#1301, attempt uk-local-candidate-f100-s42-20261104T000247Z-3a5b4051): 3 national target-fit rows, 9 local target-fit cells and 0 areas below the support floor, approved 2026-11-04; 13 entries that build 2 would fail are retired. Every signed row stays bound in the solve, each entry suppresses only the local line's release fence, and a build in which a signed row passes fails its entry as stale.
1 change: 1 addition & 0 deletions changelog.d/1418-company-car-targets.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The national calibration binds HMRC's 2024-25 company cars (Benefits in kind statistics, July 2026), five rows in a new family, `hmrc_benefits_in_kind` (María's ruling of 3 November 2026): Table 1's car recipients (920,000) and car taxable value (£3,070m), and Table 2C's recipients by fuel, fully electric (465,000), petrol including hybrids (390,000, the engine's `PETROL` and `ALTERNATIVE_FUEL`) and diesel including hybrids (60,000). The counts count people with a company car list price, held at 2024-25 since no index projects them. The taxable value is the engine's company car benefit in 2024-25, through a new dated measure, `company_car_benefit_2024` (`measurement_period` 2024), since the calibration year's appropriate percentages are a point higher; the measure resolver refuses a binding that measures a dated car benefit at any other period, as it does a dated CGT measure. Two signed holds cover the rows in `uprating_holds.json`. The company car fact fence keeps the vendored facts out of the solve, as imputation seeds, and names the bound rows in a new `calibrated_facts` field.
1 change: 1 addition & 0 deletions changelog.d/1418-company-cars-without-epb.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`company_cars` keeps the car on every tape row, whatever EPB it drew (María's rulings of 3 November 2026). EPB is drawn on uniforms the car never conditions. The national `f6e33b93` lost about 272,000 weighted holders and £10.6bn of list price, at the stage's weights, to a rule that dropped the car where EPB was zero. A cap of EPB alone also dropped or shrank the cars of the rows that drew a little EPB (Vahid's review of microcosm#1491). A tape row's car and fuel benefits are now capped at its EPB + PAY within the pay its employee pension contribution leaves; the carve declares `cap: epb_then_pay` and `pay_column`. They come out of `employment_income` as before and sit in EPB first, and the part above EPB moves from `hmrc_spi_pay` into `hmrc_spi_employment_benefits`, so PAY + EPB + TAXTERM stays the tape's. A row whose EPB and PAY can't hold the car still loses it. The stage now rewrites `hmrc_spi_pay` and `hmrc_spi_employment_benefits`. In the receipt, `holders.spi_dropped_without_epb` becomes `holders.spi_channel_tape_without_epb`, and `cap_below_epb_for_the_employee_contribution` becomes `cap_below_epb_and_pay_for_the_employee_contribution`. `spi_carve_out` adds `holders_without_epb`, `kept_without_epb`, `kept_with_epb_topped_up_from_pay`, `kept_leaving_no_pay` and `weighted_pay_moved_into_epb_gbp`. Two invariants join the stage-health gate: a tape row's PAY below zero, and a tape row's PAY + EPB moved.
114 changes: 76 additions & 38 deletions docs/uk-company-cars-316.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ car from their car job with the lowest JOBTYPE, the main job first, so a person
most one, as in the engine. The survey asks CARVAL and CARCON of a company van too;
they are taken as the car's.

SPI-channel rows carry their FRS twin's carriers, as they carry every root column.
A row drawn from the SPI tape (`person_is_spi_income_recipient`) has the tape's PAY +
EPB + TAXTERM as pay, where EPB is every taxable expense payment and benefit in kind,
so it keeps its twin's car only where its drawn EPB is positive. The channel's other
rows, the undrawn copies and the dependants aged 16 to 19, keep their twin's pay, and
keep its car as an FRS row does.
SPI-channel rows carry their FRS twin's carriers, as they carry every root column,
and keep their twin's car. A row drawn from the SPI tape (`person_is_spi_income_recipient`)
has the tape's PAY + EPB + TAXTERM as pay, where EPB is every taxable expense payment
and benefit in kind. EPB is drawn on uniforms the car never conditions, so every tape
row keeps its twin's car, whatever EPB it drew, and the part of the car's benefits above
its EPB moves from its PAY into its EPB (below; María's rulings of 3 November 2026). The
channel's other rows,
the undrawn copies and the dependants aged 16 to 19, keep their twin's pay, and keep
its car as an FRS row does.

## The draws

Expand All @@ -54,8 +57,7 @@ Every draw is keyed on the person's identity, so reordering rows moves none.
fuels draw at HMRC Table 2C's shares together. A holder who reports private fuel,
which an electric car cannot carry, draws among petrol and diesel alone, and the
others draw electricity at the share that keeps Table 2C's among all of them at the
stage's weights (all of them, where the private fuel holders leave too few). The tape
rows that lose their car for want of EPB draw at the holders' electric share. Matching
stage's weights (all of them, where the private fuel holders leave too few). Matching
Table 2C at the stage's weights makes each drawn fuel depend on the other drawn cars'
private fuel and weights, as the CO2 split does: reordering rows moves none, but a
car's fuel can move when other rows or weights do. It never draws a hybrid:
Expand Down Expand Up @@ -83,14 +85,20 @@ Every draw is keyed on the person's identity, so reordering rows moves none.
## The tape rows' pay

On a tape row the engine's car and fuel benefits come out of `employment_income`,
capped at EPB (María's ruling of 30 October 2026) within the pay the row's employee
pension contribution leaves. The SPI income stage capped that contribution at the pay
capped at EPB + PAY within the pay the row's employee pension contribution leaves
(`cap: epb_then_pay`). EPB holds the benefits first, and the part above EPB moves from
the row's PAY (`hmrc_spi_pay`) into its EPB (`hmrc_spi_employment_benefits`): its PAY +
EPB + TAXTERM stays the tape's, and its split agrees with what the engine taxes (María's
rulings of 3 November 2026). Until then the cap was EPB alone (María's ruling of 30
October 2026), with PAY only where EPB was zero. That dropped or shrank the cars of the
rows that drew a little EPB, which says no more about the car than a zero does (Vahid's
review of microcosm#1491). A row whose EPB and PAY can't hold the car loses it as below.
The SPI income stage capped that contribution at the pay
it drew, and `salary_sacrifice`, which runs later on the carved pay, refuses a
contribution above the pay that remains; it keeps the salary and bonus sacrifice within
that pay itself. A row whose contribution takes all of its pay has no room, so it loses
its car and keeps its pay. The room bites only where the SPI stage's drawn contribution
exceeds the row's cash pay, PAY + TAXTERM, since that stage capped it at a pay that
includes EPB. The receipt measures what it costs beside a cap of EPB within pay alone:
its car and keeps its pay. The receipt measures what the room costs beside a cap of
EPB + PAY within pay alone:
the cars it scales further or drops, and the list price they give up
(`spi_carve_out.cars_the_employee_contribution_scales_or_drops` and
`weighted_list_price_given_up_for_the_employee_contribution_gbp`). Re-capping the
Expand All @@ -106,7 +114,7 @@ them alone.
fits, with its contributions dropped. The benefit is the price above the capped
contributions times the appropriate percentage, so the scaling is exact.
3. A car that would need a list price below £5,000 to fit is dropped, and its EPB
stays in pay.
and PAY stay in pay.

A scaled car's price is the room over its appropriate percentage, so what sets the
percentage sets the price, and with it the base the 2030-31 rise acts on: the CO2
Expand Down Expand Up @@ -146,34 +154,64 @@ list prices and contributions grow by CPI, and the weights are not projected.
Expect the static 2030-31 cost to come in well under Table 6.1's £310m, from the
size of that base. The OBR's NICs line (£92.4m, at Class 1A's 15%) implies about
£616m of extra taxable value, a list price base of about £60bn. HMRC's 2024-25
taxable value implies roughly half of that, so even a file that matches Table 1's
920,000 holders and £3,070m should fall about 30 to 45% short. Matching Table 1's
taxable value does not pin the base, since a different electric mix and different
prices reach the same total. So the stage's receipt records the weighted total list
price of electric cars and of the others, for the results to read the gap as base
size.

Two parts of a shortfall are measured here rather than corrected (María's ruling of 31
October 2026: measure first).

- **The tape rows' EPB draw.** A tape row keeps its twin's car only where its drawn
EPB is positive, and EPB is drawn on uniforms the car never conditions. The SPI
channel holds half the working-age prior mass, so before calibration holders and
the base come to about half the FRS level plus half of it times the share of tape
rows that draw EPB. The receipt records the weighted holders and list price lost
this way (`holders.spi_dropped_without_epb`).
- **The carve-out.** Cars that do not fit their EPB are scaled or dropped, above.
taxable value implies roughly half of that, so a file that matches Table 1's
920,000 holders and £3,070m, as the national now binds (below), should still fall
about 30 to 45% short. With Table 2C's fuel counts bound as well the electric mix is
pinned, but the prices are not: a different price mix reaches the same total. So the
stage's receipt records the weighted total list price of electric cars and of the
others, for the results to read the gap as base size.

Two parts of a shortfall were measured first (María's ruling of 31 October 2026:
measure first), and the first is corrected now.

- **The tape rows' EPB draw.** Until 3 November 2026 a tape row kept its twin's car
only where its drawn EPB was positive, and the national `f6e33b93` lost about
272,000 weighted holders and £10.6bn of list price that way, at the stage's
weights. They are
kept now, their benefits moved from PAY into EPB. The receipt records the weighted
holders kept without EPB and the pay moved (`holders.spi_channel_tape_without_epb`
and `spi_carve_out.weighted_pay_moved_into_epb_gbp`), and how many of those rows the
car leaves with no PAY, their cash pay being their termination pay alone
(`spi_carve_out.kept_leaving_no_pay`). It also counts the rows with EPB whose car
takes more than it (`spi_carve_out.kept_with_epb_topped_up_from_pay`).
- **The carve-out.** Cars that do not fit their EPB and PAY are
scaled or dropped, above.

These figures, like the list price totals, are at the stage's weights, before
calibration moves the holders. The results measure the base on the calibrated file.

## Measured, not bound

No HMRC company car fact is a calibration target: the stage draws fuel and CO2 to
Tables 2A and 2C, so binding them would be circular. No build step reads the other
tables after calibration yet: comparing the calibrated file with HMRC's Table 1
(recipients, taxable value, income tax and NICs), Table 3A (by income range) and Table
4 (by region) is a manual step. `uk_stage_company_cars_invariants` blocks a release on
## Bound and measured

The national calibration binds five of HMRC's 2024-25 facts from the Chronicle feed
(María's ruling of 3 November 2026), in their own family, `hmrc_benefits_in_kind`:

| Target | HMRC | Frame |
|---|---|---|
| `hmrc.benefits_in_kind.company_car_recipients` | Table 1, car recipients, 920,000 | People with a list price |
| `hmrc.benefits_in_kind.company_car_taxable_value` | Table 1, car taxable value, £3,070m | The engine's company car benefit in 2024-25 |
| `hmrc.benefits_in_kind.company_car_fuel.fully_electric` | Table 2C, 465,000 | `ELECTRIC` |
| `hmrc.benefits_in_kind.company_car_fuel.petrol_including_hybrids` | Table 2C, 390,000 | `PETROL` and `ALTERNATIVE_FUEL` |
| `hmrc.benefits_in_kind.company_car_fuel.diesel_including_hybrids` | Table 2C, 60,000 | `DIESEL_RDE2` and `DIESEL_NON_RDE2` |

- **The taxable value** is measured in 2024-25 (`company_car_benefit_2024`,
`measurement_period` 2024), as the CGT rows are: the calibration year's appropriate
percentages are a point higher, so measuring 2025 would set 2024-25's total against
2025-26's rates and pull the base down.
- **The counts** count stored inputs, so the year they are measured in moves nothing
but the fact. They are held at 2024-25 (`uprating_holds.json`): no index projects
company car holders, and HMRC's 2025-26 figures are due in July 2027.
- **The fuel counts** bring the fuel mix to HMRC's rather than the FRS respondents':
about a third of the FRS's company cars are electric, and half of HMRC's. Table 2C
counts hybrids with their fuel, and the stage maps every FRS hybrid to
`ALTERNATIVE_FUEL`, which counts with petrol here, since diesel hybrids are few. If
the reweighting distorts other targets, redrawing the fuel types in the stage is
the next step.
- The three fuel rows sum to 915,000 against Table 1's 920,000, from HMRC's rounding.

The stage still draws fuel and CO2 from its vendored copy of Tables 2A and 2C, which
the weight solve never reads. Comparing the calibrated file with Table 2A (by CO2),
Table 3A (by income range) and Table 4 (by region) is a manual step.
`uk_stage_company_cars_invariants` blocks a release on
any record that breaks an invariant, a tape row whose employee pension contribution
exceeds its carved pay included, and on a tape row whose pay plus benefits misses the
tape's total by more than 5p.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14264,7 +14264,9 @@
"kind",
"outputs",
"epb_column",
"pay_column",
"benefits",
"cap",
"minimum_scaled_list_price_gbp"
],
"properties": {
Expand All @@ -14281,6 +14283,14 @@
"epb_column": {
"type": "string"
},
"pay_column": {
"type": "string"
},
"cap": {
"enum": [
"epb_then_pay"
]
},
"benefits": {
"type": "array",
"minItems": 1,
Expand All @@ -14303,7 +14313,8 @@
"classification_rationale",
"fact_fence_id",
"fenced_fact_composition",
"fenced_fact_count"
"fenced_fact_count",
"calibrated_facts"
],
"properties": {
"kind": {
Expand All @@ -14326,6 +14337,9 @@
},
"fenced_fact_count": {
"type": "number"
},
"calibrated_facts": {
"type": "string"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"compiled_count": 1420,
"compiled_count": 1425,
"counts_by_kind": {
"calibration_drift": 566,
"fixture_only": 42,
"ledger_only": 825
"ledger_only": 830
},
"difference_count": 1433,
"difference_count": 1438,
"differences": [
{
"fixture_value": 1608000.0,
Expand Down Expand Up @@ -1295,6 +1295,41 @@
"period": 2025,
"reason": "Ledger-compiled row has no fixture counterpart at this comparison period."
},
{
"kind": "ledger_only",
"ledger_value": 60000.0,
"name": "hmrc.benefits_in_kind.company_car_fuel.diesel_including_hybrids",
"period": 2025,
"reason": "Ledger-compiled row has no fixture counterpart at this comparison period."
},
{
"kind": "ledger_only",
"ledger_value": 465000.0,
"name": "hmrc.benefits_in_kind.company_car_fuel.fully_electric",
"period": 2025,
"reason": "Ledger-compiled row has no fixture counterpart at this comparison period."
},
{
"kind": "ledger_only",
"ledger_value": 390000.0,
"name": "hmrc.benefits_in_kind.company_car_fuel.petrol_including_hybrids",
"period": 2025,
"reason": "Ledger-compiled row has no fixture counterpart at this comparison period."
},
{
"kind": "ledger_only",
"ledger_value": 920000.0,
"name": "hmrc.benefits_in_kind.company_car_recipients",
"period": 2025,
"reason": "Ledger-compiled row has no fixture counterpart at this comparison period."
},
{
"kind": "ledger_only",
"ledger_value": 3070000000.0,
"name": "hmrc.benefits_in_kind.company_car_taxable_value",
"period": 2025,
"reason": "Ledger-compiled row has no fixture counterpart at this comparison period."
},
{
"kind": "ledger_only",
"ledger_value": 32000000.0,
Expand Down
Loading
Loading