Repository navigation
Sign off the local cuts' target-fit rows (dbacb023, 83802786), and the company car base - #1491
juaristi22 wants to merge 11 commits into
Conversation
Gate-only sign-off from dense build 1 of the local cut built at 329a99e (attempt uk-local-candidate-f100-s42-20261102T182958Z-78667c3a), drafted by tools/draft_uk_dense_signoff.py and approved by María on 2026-11-03 (microcosm#1301 route). The national target-fit register adds four rows and retires one; the local target-fit register adds eleven cells and retires twelve; the area-support entries are kept. Every signed row stays bound in the solve: the entries are scoped to the local line and suppress only their release fence, so the reuse build at this commit keeps build 1's solve. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The local area moves from 6528c865 to microcosm-uk-2024-25-dense-20261103T092045Z-dbacb023, built from PolicyEngine/microcosm#1428 at 329a99e71 (the national's commit and spine) with its gate-only sign-off (PolicyEngine/microcosm#1491), on policyengine-uk 2.165.1. Both cuts now certify on their own build, so the regional accepted-mismatch record and its input-surface audit drop out: area runs read every input the engine takes, company cars and ISA payments included. certify-data, the release lock, the TROs and the bundle checks are rerun; the lock and the household snapshots are unchanged. The certified local-area constants in the tests follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review of 1affbc1 I checked where #1428 merged against the commit these cuts were built from, the four files in the diff, and the reuse build's published gate report and staged manifest for Should1. Both cuts predate the banding fix that #1428 merged with, and the body doesn't say so.
2. The merge-commit requirement isn't enforced anywhere. The repo allows squash, rebase and merge commits, Nit3. The body reads as if the high-value homes check blocked build 1 and is signed here. It wasn't, and nothing signs it.
4. The body's window gives area entries an expiry of 2027-02-03, but this PR adds no area entries. None of the six kept entries carries that date. Drop it or say it would apply to new ones. Checked and fine
What I ran: a fresh clone with Not verified: any build, build 1's gate report, and how far the banding fix moves these signed rows. CI at this head: no run had started for Verdict: the sign-off does what it says for the cut as built, and nothing here is must-fix. Item 1 needs a decision before #731 leaves draft. 🤖 Generated with Claude Code |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
María's ruling of 3 November 2026 (microcosm#1418, the company car base). A tape row's EPB is drawn on uniforms the car never conditions, so dropping the car where EPB is zero lost about 272,000 weighted holders and GBP 10.6bn of list price on f6e33b93, at the stage's weights. - A tape row whose drawn EPB is zero keeps its twin's car. Its car and fuel benefits are capped at its PAY within the pay its employee pension contribution leaves, come out of employment_income as on any tape row, and move from hmrc_spi_pay into hmrc_spi_employment_benefits, so its PAY + EPB + TAXTERM stays the tape's. A row whose PAY can't hold the car still loses it. Rows with positive EPB keep the cap at EPB. - The stage rewrites hmrc_spi_pay and hmrc_spi_employment_benefits, and the carve declares pay_column (schema, both manifests, graph cells). - The lost cars' fuel and price draws go, with assign_fuel_types's unfueled_electric parameter, which only they used. - Receipt: holders.spi_dropped_without_epb becomes holders.spi_channel_tape_without_epb, and spi_carve_out adds holders_without_epb, kept_without_epb 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. - The engine test gains a tape row without EPB; the coverage manifest and the H2 fixture follow the manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
María's ruling of 3 November 2026 (microcosm#1418, the company car base): bind HMRC's 2024-25 holders and taxable value, and the three fuel counts, to bring the fuel mix to HMRC's shares rather than the FRS respondents'. If the fuel counts distort calibration, the fuel types are redrawn instead. - Five national rows in a new family, hmrc_benefits_in_kind, from HMRC Benefits in kind statistics (July 2026) in Chronicle 08962f1: Table 1's car recipients and car taxable value, and Table 2C's recipients by fuel (fully electric; petrol including hybrids, the engine's PETROL and ALTERNATIVE_FUEL; diesel including hybrids). The counts count people with a company car list price. No uk-data metric holds them. - The taxable value is the engine's company car benefit in 2024-25, through a dated measure, company_car_benefit_2024 (measurement_period 2024, require_matching_fact_period), as the CGT rows read their gains: the calibration year's appropriate percentages are a point higher. The measure resolver, the frame adapter's value_period and the measure input route know it. - Two holds in uprating_holds.json, signed for the ruling: the taxable value as matched_period, the four counts as reviewed_no_index (no index projects company car holders; HMRC's 2025-26 figures are due July 2027). - The company car fact fence keeps the vendored tables out of the solve, as imputation seeds, and names the bound rows in a new calibrated_facts field (schema, both manifests, code). The stage notes, the statistics module, the stage-health docstring and the doc say what is bound. - The plain-column period register reviews the two stored inputs the counts filter on: the list price as a sign filter, and the fuel type, which nothing uprates. - The national references and membership and the national compile-parity receipt are regenerated on the pinned feed (08962f1): five new rows, every other reference unchanged. The coverage manifest and the H2 fixture follow the manifest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Round 2 at dd99a1d You asked for a review of the company car work while the dataset builds, so this round covers Round 1 items
Should5. A tape row with a small positive EPB now loses a car that the same row with EPB of zero keeps.
Nit6. A scaled car can empty the row's PAY. With PAY £6,000, TAXTERM £24,000 and EPB zero, the £40,000 car scales to £24,000. All £6,000 of PAY moves into EPB, so the row's cash pay is TAXTERM alone. That is within the rule. But under PolicyEngine/policyengine-uk#2823 (open), a Class 1A rise passes into employment income, and on these rows it would hit #2823's cash-pay floor first. #2823's wage solver acts only on a reform's change, so I don't expect it to move the stage's baseline pay identity gate (checked by reading, not run). If the next build pins an engine with #2823, a receipt count of zero-EPB keepers left with no PAY would show how many rows this affects. 7. The dated car measure's name year isn't checked against its 8. Holding the counts flat will likely understate 2025-26. The hold declares this, but for the record: over the last three years HMRC's Table 1 holders went 760,000, 840,000, 920,000, and Table 2C's electric cars went 220,000, 340,000, 465,000. Bound at 2025, the counts and the electric share are probably low. The Checked and fine
CI at this head: lint, wheels, integration-uk and engine-uk (3.13, 3.14) pass. engine-free is still pending. engine-us fails on both Pythons in Verdict: the car work does what the body says, and the HMRC rows and fuel mapping check out against the source. Item 5 is the one I'd settle before the next national, because it leaves a cliff in the same place this fix removes one. 🤖 Generated with Claude Code |
Vahid's round 2 on microcosm#1491 (at dd99a1d). - Item 7: the measure resolver refuses a binding that measures a dated company car benefit at any period but the year in its name, as it does a dated CGT measure. A rename to company_car_benefit_2025 that kept measurement_period 2024 would otherwise price 2025-26 percentages against the 2024-25 fact and still compile. Tested at 2023, 2025 and no declared period. - Item 6: spi_carve_out counts the rows without EPB whose car takes all of their PAY (kept_without_epb_leaving_no_pay), whose cash pay is then their termination pay alone, ahead of an engine with the cash-pay floor of PolicyEngine/policyengine-uk#2823. - Item 8: the counts' reviewed_no_index hold says that held flat they probably understate 2025-26, with HMRC's last three years of holders and electric cars. Item 5, the cap on tape rows with positive EPB, waits for María's ruling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Vahid. In your order: Round 1 items
Round 2
CI. engine-us fails on main too, after the ACS merges, as you found, so it isn't from this PR. The national from
🤖 Generated with Claude Code |
Vahid's review of microcosm#1491, item 5, which María took on 3 November 2026 for later builds. The pair built from dd99a1d keeps the cap at EPB on the rows that drew EPB. - Every tape row's car and fuel benefits are capped at EPB + PAY within the pay its employee pension contribution leaves. EPB holds them first, and the part above EPB moves from hmrc_spi_pay into hmrc_spi_employment_benefits, so PAY + EPB + TAXTERM stays the tape's. - Under the old cap, rows with positive EPB were capped at EPB alone. A row that drew GBP 100 of EPB lost the car that the same row with none kept, and GBP 2,000 of EPB shrank a GBP 40,000 car to GBP 8,000. EPB is drawn on uniforms the car never conditions, so a small EPB says no more about the car than a zero one does. The zero-EPB rule is now the special case. - The carve declares the rule (cap: epb_then_pay) in the schema, both manifests and the fixture, so a declaration for the old cap is refused. - Receipt: kept_with_epb_topped_up_from_pay counts the rows with EPB whose car takes more than it. kept_without_epb_leaving_no_pay becomes kept_leaving_no_pay, any row whose car takes all of its PAY. cap_below_epb_for_the_employee_contribution becomes cap_below_epb_and_pay_for_the_employee_contribution. - Tests: - the carve-out tests take the new cap, with the review's three-row probe; - the identity test's flat engine prices above any row's pay; - the engine test's row with EPB of GBP 1,500 now keeps its car and moves the rest of its benefits from PAY. - The doc, the changelog fragment, the coverage manifest and the H2 fixture follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@vahid-ahmadi, item 5 is in
It's for later builds. The local cut being built now from 🤖 Generated with Claude Code |
Gate-only sign-off from dense build 1 of the local cut built at dd99a1d (attempt uk-local-candidate-f100-s42-20261104T000247Z-3a5b4051), drafted by tools/draft_uk_dense_signoff.py and approved by María on 2026-11-04 (microcosm#1301 route). The national target-fit register adds three rows and retires three; the local target-fit register adds nine cells and retires ten; the area-support entries are kept. Every signed row stays bound in the solve: the entries are scoped to the local line and suppress only their release fence, so the reuse build at this commit keeps build 1's solve. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The local cut microcosm-uk-2024-25-dense-20261104T093024Z-83802786 was built at dd99a1d and assembled by the reuse build at 5293966, the gate-only sign-off of its build 1. Merged with a merge commit, so the cut's build commit stays in main's history once this PR merges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The national moves from f6e33b93 to microcosm-uk-2024-25-national-20261103T154302Z-0639b9c7, built from PolicyEngine/microcosm#1491 at dd99a1dcd on policyengine-uk 2.165.1, and the local area from dbacb023 to microcosm-uk-2024-25-dense-20261104T093024Z-83802786, built from the same commit and spine with its gate-only sign-off (5293966d4). Both certify on their own build. certify-data, the release lock, the TROs and the bundle checks are rerun; the household snapshots are unchanged. The bundle versions follow main's 6.13.0 (bump_version.sync_bundle_versions), the certified constants in the tests follow uk_qualification.rewrite_certified_constants plus the local-area id, and one changelog fragment describes the new pair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main brings #1426 (SPI age bands and #1095's B3 to B10 items, with HMRC's two High Income Child Benefit Charge rows), #1391 (QRF gate calibration) and the rest merged since 3 November. Resolved by hand: - uk_population_targets.json keeps both sides' rows: the five company car rows, then the two HICBC rows, in the targets and the registry scope, and both sides' unmapped declarations; - uprating_holds.json keeps both sides' holds; - the counts in test_uk_population_targets.py (467 targets, 405 in the registry scope, 220 unmapped declarations) and test_uk_target_references.py (1,425 active references) add both sides' rows. Regenerated on the merged tree, after syncing the venv to the merged lock: - the target references and their membership, on Chronicle 08962f1. Against main only the five car rows are new; no existing row changes; - the national compile-parity receipt; - the release input coverage manifest: the source-manifest hash, and company_cars' two pay columns; - the H2 UK spine fixture: company_cars' declaration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The company car rows (dd99a1d) added hmrc.benefits_in_kind to the contract's hierarchy, which the local references restate, but the local surface wasn't regenerated with them. Regenerated from the pinned feed (Chronicle 08962f1), it differs from the committed file by that category alone: the 27,168 local references and the local membership are unchanged. test_committed_surfaces_regenerate_from_pinned_feed[local] caught it; it needs the feed, so it skips without one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Round 3 at c2f91e2 This round covers Earlier items
Should9. The title and body describe only the 3 Nov sign-off, but the registers at head are the 4 Nov sign-off's, which added 12 entries and retired 7 of the 3 Nov ones.
Checked and fine
CI at this head: lint, wheels, integration-uk, installed-emitter and select-countries pass. engine-free, engine-uk and engine-us (3.13, 3.14) were still pending when I posted. Verdict: every earlier item is fixed apart from item 2, which waits for the merge. The car code is right as far as reading it shows. What's left is item 9: the title and body are behind the registers they would merge. 🤖 Generated with Claude Code |
…dules ledger_targets reads company_car_dated_benefit_year from hmrc_company_car_statistics to measure a dated company car measure at its year (dd99a1d), as it reads uk_cgt_dated_measure_year from cgt_calibration, which is listed. The import check that came with the main merge found the edge unlisted. Listing the module re-keys both UK target kernels; its one first-party import, ledger_fact_vendoring, is listed already. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This PR carries three pieces of work:
microcosm-uk-2024-25-dense-20261103T092045Z-dbacb023(1affbc127, 3 Nov), which pairs with the nationalf6e33b93. Both are built from SPI donor savings rebased to SPI's 2023-24 bands (savings follow-up to #1418) #1428 at329a99e71.microcosm-uk-2024-25-dense-20261104T093024Z-83802786(5293966d4, 4 Nov), which pairs with the nationalmicrocosm-uk-2024-25-national-20261103T154302Z-0639b9c7. Both are built from this PR atdd99a1dcd. Certify the Microcosm UK pair from microcosm#1491 on policyengine-uk 2.165.1 (national 0639b9c7, local area 83802786) policyengine.py#731 now bundles this pair.d0e87370eanddd99a1dcd) and the fixes from Vahid's second review (5304b3c50and6ef5983e9), below.737f52088(3 Nov) and22bda9511(4 Nov, with UK #1095 A/B fixes: the SPI age band (uk-data#628), households' HRAD from Table 8a receipts, and the SPI pay floor (uk-data#629) #1426 and Calibrate the QRF sign gates out of fold, for every gated UK imputation #1391).c2f91e201then adds thehmrc.benefits_in_kindcategory, whichdd99a1dcdput in the contract's hierarchy, to the local references (4 lines; no reference or membership changes).Merging
Use a merge commit. Three of this branch's commits are the build commits that published cuts record, so all three must stay in main's history:
1affbc127: the reuse build and assembly ofdbacb023;dd99a1dcd: the build of the national0639b9c7, and build 1 of83802786;5293966d4: the reuse build and assembly of83802786. It is reachable only as the second parent offab42beff.A squash merge would drop all three. After the merge I'll run
git merge-base --is-ancestoron each againstorigin/mainand post the result here.2dbf7cf56and the two pairs.2dbf7cf56(merge commite226192ad), so329a99e71is in main as its parent.dbacb023andf6e33b93were built from329a99e71, before2dbf7cf56, which bands SPI records on total income net of expenses and without gifts (Vahid's review of329a99e71, items 1, 2 and 5). Neither carries it.dd99a1dcd(0639b9c7and83802786) carries it.6ef5983e9, so it keeps the cap at EPB on tape rows that drew EPB. Later builds pick up the EPB + PAY cap.What happened
dbacb023(3 Nov):329a99e71, 2 Nov) passed every structural gate and was blocked only by target fit, national and local. The diagnostic high-value homes support check also fails, and the cut ships failing it: a diagnostic gate blocks nothing, and nothing here signs it. Its counts are in Vahid's review of1affbc127, item 3.1affbc127signs those rows in the gate-only registers.1affbc127(gate clock 2026-11-03) reused build 1's solve, passed every release-blocking gate and assembled.latestuntouched).83802786(4 Nov):dd99a1dcd, 4 Nov) passed every structural gate and was blocked only by target fit, national and local. The diagnostic high-value homes support check fails, as ondbacb023, and nothing here signs it.5293966d4signs those rows, on a branch fromdd99a1dcd, merged here byfab42beff.5293966d4(gate clock 2026-11-04) reused build 1's solve, passed every release-blocking gate and assembled.0639b9c7.Company car base (María's ruling of 3 November 2026)
The two commits took effect in the pair built from
dd99a1dcd.dbacb023andf6e33b93don't carry them.Why. The national
f6e33b93has 473,000 company car holders, against HMRC's 920,000 in 2024-25. About a third of its cars are electric, against half in HMRC's Table 2C. Most of the shortfall is SPI tape rows losing their FRS twin's car whenever their drawn EPB is zero, though EPB is drawn independently of the car: about 272,000 weighted holders and £10.6bn of list price at the stage's weights.d0e87370eKeep company cars on SPI rows whose drawn EPB is zeroemployment_income, capped at its PAY within the pay its employee pension contribution leaves. They move fromhmrc_spi_payintohmrc_spi_employment_benefits, so the row's PAY + EPB + TAXTERM stays the tape's.dd99a1dcdBind HMRC's 2024-25 company car holders, taxable value and fuel countsFive national rows in a new family,
hmrc_benefits_in_kind:hmrc.benefits_in_kind.company_car_recipientshmrc.benefits_in_kind.company_car_taxable_valuehmrc.benefits_in_kind.company_car_fuel.fully_electricELECTRIChmrc.benefits_in_kind.company_car_fuel.petrol_including_hybridsPETROL,ALTERNATIVE_FUELhmrc.benefits_in_kind.company_car_fuel.diesel_including_hybridsDIESEL_RDE2,DIESEL_NON_RDE2The taxable value is measured as the engine's benefit in 2024-25, through a new dated measure (
company_car_benefit_2024,measurement_period2024), as the CGT rows are. The calibration year's appropriate percentages are a point higher, so measuring 2025 would pull the base down.The counts are held at 2024-25, since no index projects company car holders.
The fact fence keeps the vendored copy of the tables out of the solve: it only seeds the fuel and CO2 draws. A new
calibrated_factsfield names the bound rows.Measured on the pair.
0639b9c7and within 2% on83802786.f6e33b93). The 2024-25 base matches HMRC; what's left is car volumes, which the dashboard's forecast holds flat. Every costing on the pair is in PolicyEngine/policyengine.py#731.5304b3c50and6ef5983e9: Vahid's second review.cap: epb_then_pay).Both come after
dd99a1dcd, the commit the national and the local cut were built from, so later builds pick them up.For you: the two holds in
uprating_holds.jsonare signed in your name for the ruling of 3 Nov (approved 2026-11-03, expiring 2027-01-03). Say if you'd rather sign them differently.Tests run locally for the car commits
All pass. The national target references, membership and compile-parity receipt were regenerated on the pinned feed (08962f1): five new rows, every other reference unchanged.
After the main merge (
22bda9511):test_committed_surfaces_regenerate_from_pinned_feed[national], run on the feed. Its[local]case caught the missing category, andc2f91e201commits that case's regenerated file unchanged.Registers at head, against main
uk_target_fit)uk_local_target_fit)uk_local_area_support)uk-local-candidate-f100-s42-20261102T182958Z-78667c3aand report7f7d66cc44ab2370a126d344cba66a923be871291f0397ef4e8496bf060f57f8. They expire on 2026-12-01.uk-local-candidate-f100-s42-20261104T000247Z-3a5b4051and report365f2878c6e3c8ca333486e9255632c5362c5b01a93d3fb699eca1ee22aa0795. They expire on 2026-12-02.5293966d4retires 2 of the 4 national rows and 5 of the 11 local cells that1affbc127added.Gate-only sign-off from dense build 1 of
83802786(microcosm#1301,5293966d4)Build-1 attempt
uk-local-candidate-f100-s42-20261104T000247Z-3a5b4051, full gate report sha256365f2878c6e3c8ca333486e9255632c5362c5b01a93d3fb699eca1ee22aa0795, gates evaluated on 2026-11-04.Register data and test pins only. Every signed row stays bound in the solve: each entry is scoped to the local line and suppresses only its release fence. A build in which a signed row passes fails its entry as stale.
uk_target_fit)uk_local_target_fit)uk_local_area_support)National target-fit rows: 2 stale-risk, 0 near-bound. Stale-risk counts signed rows within 0.01 above the bound, which build 2 fails as stale if it does not reproduce build 1 exactly; near-bound counts unsigned rows within the same margin below it. The local registers' counts are not printed here.
Window: approved 2026-11-04 by juaristi22, adjudication microcosm#1301 route for the local cut built with microcosm#1491 (sign-off 2026-11-04); fit entries expire 2026-12-02. Build 2 needed a gate clock (
--gate-review-date) on or after 2026-11-04 and on or before 2026-11-16; it ran at 2026-11-04.Predicted build-2 verdicts on build 1's rows:
uk_target_fitpasses,uk_local_target_fitpasses,uk_local_area_supportpasses. The reuse build bore them out.Gate-only sign-off from dense build 1 of
dbacb023(microcosm#1301,1affbc127)Build-1 attempt
uk-local-candidate-f100-s42-20261102T182958Z-78667c3a, full gate report sha2567f7d66cc44ab2370a126d344cba66a923be871291f0397ef4e8496bf060f57f8, gates evaluated on 2026-11-02.uk_target_fit)uk_local_target_fit)uk_local_area_support)National target-fit rows: 1 stale-risk, 2 near-bound.
Window: approved 2026-11-03 by juaristi22, adjudication microcosm#1301 route for the local cut built with microcosm#1428 (sign-off 2026-11-03); fit entries expire 2026-12-01. Build 2 needed a gate clock on or after 2026-11-03 and on or before 2026-11-16; it ran at 2026-11-03.
Predicted build-2 verdicts on build 1's rows:
uk_target_fitpasses,uk_local_target_fitpasses,uk_local_area_supportpasses.Tests to run
Disclosure: the company car sections carry HMRC's published 2024-25 figures, Table 6.1's costing, and weighted aggregates of the nationals
f6e33b93and0639b9c7, of83802786and of the stage receipt. Those are holders, taxable value, the electric share, the fit of the bound rows, the 2030-31 score, and the holders and list price the zero-EPB rule removed at the stage's weights. Each is over many households, and none is a record's value. The sign-off sections carry:Per-row errors, the local registers' stale-risk and near-bound counts and per-area support figures stay in the private review files outside every git work tree.
🤖 Generated with Claude Code