Repository navigation
Conversation
…core 3.32.21 Certify enhanced_frs_2024_25 from policyengine-uk-data 1.58.0 as the UK default, on the publisher's compatibility claim added to the 1.58.0 release manifest at HF commit c30504aa. Pin the latest policyengine-uk (2.123.4) and policyengine-core (3.32.21), regenerate the extras, lock and TRO sidecars, and move the tests that pin the certified UK release. Fixes #554 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Employer NI falls by GBP 1.20 per employee: policyengine-uk 2.123.2 stores the Class 1 secondary threshold as the statutory GBP 5,000 a year rather than 52 x GBP 96. - The couple's three-year-old now gets the extended 30-hour childcare entitlement (GBP 7,104.38) instead of the universal 15 hours (GBP 3,552.19). Bisected to policyengine-uk 2.114.2, which rewrote the extended entitlement's qualifying-child and income tests (SI 2022/1134). - The model surface grows to about 3,200 parameters and 1,000 variables. - personal_rent became a formula variable with no defined_for, so the metadata test checks child_benefit's defined_for instead. Fixes #554 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the bundle manifest and both TRO sidecars by regenerating them on main's: re-run certify-data against the 1.58.0 manifest at HF c30504aa, re-apply the policyengine-core 3.32.21 package pin, then bundle.py generate (with TROs). The UK entry keeps main's 6.2.2 stamps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Pin policyengine-uk ≥ 2.123.6, not 2.123.4. The certified bundle needs PolicyEngine/policyengine-uk#1927 ("Key the Housing Benefit Guarantee Credit passport on receipt"). It merged on 2026-10-08 at 12:07Z as On earlier releases the HB passport keys on Guarantee Credit entitlement, so pensioners who don't claim Pension Credit still get passported to maximum Housing Benefit. In the uk-triple-lock model-v2 pilot, that overstates the Burnham plan's HB offset by about £3.3bn on an affected path. The review on PolicyEngine/uk-triple-lock#24 makes #1927 a hard precondition for the certified bundle the rebuild uses (d778), and the rebuild will refuse a bundle whose HB passport doesn't read So please certify 2.123.7, or 2.123.6, with whatever core it needs, and extend the 1.58.0 manifest's publisher claim to cover it. If that claim can't be extended without a new data build, say so here. |
|
Heads-up for the UK tables in this PR body: the policyengine.py-API columns ("6.2.1" and "This PR") carry a wrapper bug, #556, fixed in #557. A UK year-file run took the projected year as policyengine-uk's data year, so the State Pension followed CPI instead of the triple lock. The direct- The same
The 6.2.1 column moves too: State Pension £127.5bn → £133.7bn, absolute BHC everyone 14.7% → 14.4%, and 65+ absolute BHC 15.2% → 13.5%. #557 has the full table and the record-level checks. Reforms are affected too, which matters for the triple-lock rebuild. Take a State Pension rate reform (new £260/wk, basic £200/wk from 2026) through
|
|
#557 is merged into main ( |
Fixes #554
Certified versions
enhanced_frs_2024_25(sha2565ba399ea…b960b6)c30504aalegacy_compatible_model_package: the publisher's claim in that manifestcompatible_core_packages)populace-us-2024-spm-20260915Before this PR, the bundle certified 1.56.16 with policyengine-uk 2.102.3 and core 3.32.10.
Merging releases this as policyengine 6.2.3: main is at 6.2.2 after #552, and a
changedfragment bumps the patch version.This is the release Max ruled on in d778 (2026-10-05): pin the latest policyengine-uk and core with the uk-data batch release, and certify that bundle. I checked 2.123.4 and 3.32.21 against live PyPI on 2026-10-07; they were uploaded at 16:20Z and 13:49Z. 1.58.0 was built with policyengine-uk 2.122.2 and core 3.32.13, so the newer pair is covered by a publisher compatibility claim, as #536 did for 1.56.16.
Certification
c30504aachanges onlyreleases/1.58.0/release_manifest.json. It appendspolicyengine-uk==2.123.4tocompatible_model_packagesandpolicyengine-core==3.32.21tocompatible_core_packages. The build-time claims stay, and tag1.58.0still points at47bbb58d.validate_release_manifest(at4cbedbec) passes on the new manifest.data_upload.pyreads the manifest at the tag, not atmain, so later uploads are unaffected.scripts/bundle.py certify-data --country uk --data-producer populace --manifest-uri hf://model/policyengine/policyengine-uk-data-private@c30504aa…/releases/1.58.0/release_manifest.json --model-version 2.123.4.packages.policyengine-corein the bundle manifest moves to 3.32.21.bundle.py generateregenerates the four extras from it, as in Update PolicyEngine Core to 3.32.10 #540.uv.lock(uv 0.12.14,--upgrade-packagefor the two packages only: 13 lines), both TRO sidecars,docs/households.md's bundle line, and the test constants that pin the certified UK release.Evidence on the 1.58.0 artifact
All figures below are
policyengine_uk.Microsimulationruns on the exact artifact, in clean environments, for 2025, 2026 and 2030. Three environments:Every model-only move traces to a policyengine-uk 2.122.3–2.123.4 changelog entry:
opt_out_charge_shareat 1 an opted-out claimant stays opted out.child_benefit's formula is identical in both versions.US. Core also moves for the US bundle, so I ran policyengine-us 2.2.1 on the certified
populace_us_2024(sha256 matches) with core 3.32.10 and with 3.32.21, for 2026. All 18 totals (income, state income and payroll taxes, EITC, CTC, SNAP, SSI, TANF, Social Security, WIC, school meals, the ACA PTC, household and SPM unit net income) and the SPM poverty rate are bit-identical. I did not run the ACS-local dataset that #552 now uses for US state and district regions. It is 9.8 GB, and this machine had 41 GB free. It runs the same policyengine-us 2.2.1 code on different rows.What changes for users
UK results change, mainly because of the new data release. These come from policyengine.py's own API (
ensure_datasets,Simulation,calculate_uk_poverty_ratesand_by_age) for 2026. The left column is policyengine 6.2.1 from PyPI, the right is this branch, and both use the bundle's certified default dataset. 6.2.1 reproduces the figures in #536.child)senior)For comparison, #536 cites DWP's FYE 2027 projection for children (DWP counts dependent children) as 17% BHC and 24% AHC. On the new data, both absolute child rates are above those.
Why absolute child poverty rises: it corrects an understatement. Every release from 1.56.16 to 1.57.4, run on policyengine-uk 2.123.4, gives 16.3–16.7% child absolute BHC poverty for 2026-27. The rise happens entirely at 1.57.4 → 1.58.0, where it reaches 20.0%.
HBAI counts dependent children; this table uses ages 0–17. Child AHC now overshoots by 2.8pp. One candidate cause, being followed up separately: the data does not fill
uc_reported_capital. Without it, Universal Credit uses a household wealth proxy, and 34% of poor FRS families with children have UC-assessable capital above £16,000. Relative poverty falls because the lower median lowers the relative line.Model versus data. Separating the two needs one more run: policyengine-uk 2.123.4 with core 3.32.21 on the 1.56.16 artifact. These are direct-
Microsimulationtotals, 2026:income_taxnational_insuranceuniversal_creditchild_benefitpension_creditstate_pensionhousing_benefitcouncil_tax_reductionhousehold_net_incomehbai_household_net_incomeThe model step moves every poverty rate by 0.5pp or less. Almost all of the poverty change comes from the data: absolute child poverty is +3.7pp BHC and +5.7pp AHC, and relative poverty is −2.3pp overall. The Housing Benefit caseload falls from 1.71m to 1.30m and Pension Credit's from 1.78m to 1.48m on the data step.
guarantee_creditis left out of these tables. In 2.102.3 it had nodefined_for = "is_pension_credit_eligible", so its total there (£113bn) is not the same quantity.pension_creditis comparable.Household snapshots (refreshed with
PE_UPDATE_SNAPSHOTS=1; nothing else changed):uk_couple_two_kids, the three-year-old now gets the extended 30-hour childcare entitlement, £7,104.38 in place of the universal 15 hours (£3,552.19). Household benefits and net income rise by £3,552.19. I bisected this to policyengine-uk 2.114.2, which rewrote the extended entitlement's qualifying-child and income tests (SI 2022/1134 regs 13, 14(3)(c) and 18). Both parents work and each earns under £100,000, so 30 hours applies.personal_rentis now a formula variable with nodefined_for, sotest_uk_model_exposes_selected_variable_metadatacheckschild_benefit'sdefined_for(would_claim_child_benefit) instead.Invariants
This PR changes pins and certification metadata, not logic. The checks above that hold for every input are:
Checks run locally
make formatandmake lintpass.scripts/bundle.py check --published-spm --include-tros --strict-trosandscripts/release_lock.pypass.uv lock --checkwith uv 0.12.14 passes.scripts/check_release_credentials.pyfails locally by design: it accepts only a read-role token, and mine is fine-grained. CI's secret is read-role.cdad33aemerges it. The bundle manifest and both TROs are resolved by regenerating them on main's:certify-data, the core pin, thenbundle.py generatewith TROs. Against main, the manifest differs only in the UK entry and the core package. At the merged head, the bundle, certification, release-manifest, region, model, metadata, snapshot and release-lock tests give 226 passed. The strict TRO check,release_lock.pyanduv lock --checkpass.tests/test_release_lock.py. That fixture runs a liveuv lockagainst PyPI, and it failed while the machine was heavily loaded. Re-run alone, the file gives 25 passed.axiom: n/a: a wrapper pin and data certification; no policy is encoded here.
🤖 Generated with Claude Code